00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <iostream>
00028 #include <stdlib.h>
00029 #include <audioproc.h>
00030 #include <pipe.h>
00031 #include <jutils.h>
00032 #include <config.h>
00033
00034
00035 #define MIN(a,b) (a<=b) ? a : b;
00036
00037 #define _SIZE(val) \
00038 int val; \
00039 if ((char*)end >= (char*)start) \
00040 val = (char*)end-(char*)start; \
00041 else \
00042 val = ((char*)bufferEnd-(char*)start)+((char*)end-(char*)buffer);
00043
00044 #define _SPACE(val) \
00045 _SIZE(__size); \
00046 val = ((char*)bufferEnd-(char*)buffer)-__size;
00047
00048
00049
00050
00051
00052
00053 Pipe::Pipe(int size) {
00054 func("Pipe::Pipe(%i)",size);
00055 pipesize = size;
00056 buffer = malloc(pipesize);
00057 if(!buffer)
00058 error("FATAL: can't allocate %i bytes buffer for audio Pipe: %s",
00059 pipesize, strerror(errno));
00060 bufferEnd=(char*)buffer+size;
00061 end=start=buffer;
00062 blocking = true;
00063 _thread_init();
00064 unlock();
00065 }
00066
00067 Pipe::~Pipe() {
00068 func("Pipe::~Pipe : freeing %p",buffer);
00069 lock();
00070 free(buffer);
00071 unlock();
00072
00073 }
00074
00075
00076 int Pipe::read_float_intl(int samples, float *buf, int channels) {
00077 lock();
00078 _SIZE(buffered);
00079 int c, cc;
00080 int length = samples<<2;
00081 float *pp = buf;
00082
00083 if (buffered<length) {
00084
00085
00086 unlock();
00087 return -1;
00088 }
00089
00090 int origLength=length;
00091
00092 while (buffered && length) {
00093
00094
00095
00096
00097 int len = MIN(length,buffered);
00098
00099 int currentBlockSize = (char*)bufferEnd-(char*)start;
00100 currentBlockSize=MIN(currentBlockSize,len);
00101
00102
00103 cc = currentBlockSize;
00104 switch(channels) {
00105 case 1:
00106 for(c=0; c<cc; c++)
00107 pp[c] = (((IN_DATATYPE*)start)[c*2] +
00108 ((IN_DATATYPE*)start)[c*2+1]) / 65536.0f;
00109 break;
00110 case 2:
00111 for(c=0; c<cc; c++) {
00112
00113
00114 pp[c] = ((IN_DATATYPE*)start)[c] / 32768.0f;
00115 }
00116 break;
00117 default: break;
00118 }
00119
00120
00121 (char*)start += currentBlockSize;
00122 len -= currentBlockSize;
00123 (char*)pp += currentBlockSize;
00124 length -= currentBlockSize;
00125 if ((end!=buffer) && (start==bufferEnd))
00126 start = buffer;
00127
00128 if (len) {
00129
00130
00131 cc = len;
00132 switch(channels) {
00133 case 1:
00134 for(c=0; c<cc; c++)
00135 pp[c] = (((IN_DATATYPE*)start)[c*2] +
00136 ((IN_DATATYPE*)start)[c*2+1]) / 65536.0f;
00137 break;
00138 case 2:
00139 for(c=0; c<cc; c++) {
00140
00141
00142 pp[c] = ((IN_DATATYPE*)start)[c] / 32768.0f;
00143 }
00144 break;
00145 default: break;
00146 }
00147
00148
00149 (char*)pp += len;
00150 (char*)start += len;
00151 length -= len;
00152 if ((end!=buffer) && (start==bufferEnd))
00153 start = buffer;
00154 }
00155 }
00156
00157 unlock();
00158 return (origLength-length)>>2;
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 int Pipe::read_float_bidi(int samples, float **buf, int channels) {
00170 lock();
00171
00172 _SIZE(buffered);
00173
00174
00175 if(!buffered) {
00176 unlock();
00177 func("Pipe:read_float_bidi(%i,%p,%i) : nothing in the pipe",
00178 samples, buf, channels);
00179 return -1;
00180 }
00181
00182 int c, cc;
00183 int length = samples<<2;
00184 float **pp = buf;
00185
00186 if (buffered<length)
00187 if(blocking) {
00188 unlock();
00189 func("Pipe::read_float_bidi(%i,%p,%i) : only %i bytes in the pipe",
00190 samples,buf,channels,buffered);
00191 return -1;
00192 } else
00193 length = buffered;
00194
00195 int origLength=length;
00196
00197 while (buffered && length) {
00198
00199
00200
00201
00202 int len = MIN(length,buffered);
00203
00204 int currentBlockSize = (char*)bufferEnd-(char*)start;
00205 currentBlockSize=MIN(currentBlockSize,len);
00206
00207
00208 cc = currentBlockSize>>2;
00209 switch(channels) {
00210 case 1:
00211 for(c=0; c<cc; c++)
00212 pp[0][c] = (((IN_DATATYPE*)start)[c*2] +
00213 ((IN_DATATYPE*)start)[c*2+1]) / 65536.0f;
00214 break;
00215 case 2:
00216 for(c=0; c<cc; c++) {
00217 pp[0][c] = ((IN_DATATYPE*)start)[c*2] /32768.0f;
00218 pp[1][c] = ((IN_DATATYPE*)start)[c*2+1] /32768.0f;
00219 }
00220 break;
00221 default:
00222 error("Pipe:read_float_bidi doesn't supports %i channels",channels);
00223 break;
00224 }
00225
00226
00227 (char*)start += currentBlockSize;
00228 len -= currentBlockSize;
00229 (char*)pp += currentBlockSize;
00230 length -= currentBlockSize;
00231 if ((end!=buffer) && (start==bufferEnd))
00232 start = buffer;
00233
00234 if (len) {
00235
00236
00237 cc = len>>2;
00238 switch(channels) {
00239 case 1:
00240 for(c=0; c<cc; c++)
00241 pp[0][c] = (((IN_DATATYPE*)start)[c*2] +
00242 ((IN_DATATYPE*)start)[c*2+1]) / 65536.0f;
00243 break;
00244 case 2:
00245 for(c=0; c<cc; c++) {
00246 pp[0][c] = ((IN_DATATYPE*)start)[c*2] /32768.0f;
00247 pp[1][c] = ((IN_DATATYPE*)start)[c*2+1] /32768.0f;
00248 }
00249 break;
00250 default:
00251 error("Pipe:read_float_bidi doesn't supports %i channels",channels);
00252 break;
00253 }
00254
00255
00256 (char*)pp += len;
00257 (char*)start += len;
00258 length -= len;
00259 if ((end!=buffer) && (start==bufferEnd))
00260 start = buffer;
00261 }
00262 }
00263
00264 unlock();
00265 return (origLength-length)>>2;
00266 }
00267
00268
00269 void Pipe::block(bool val) {
00270 lock();
00271 blocking = val;
00272 unlock();
00273 }
00274
00275
00276 int Pipe::mix16stereo(int samples, int32_t *mix) {
00277 lock();
00278
00279 _SIZE(buffered);
00280 int c, cc;
00281
00282 int length = samples<<2;
00283 int32_t *pp = mix;
00284
00285
00286
00287 if (buffered<length) {
00288
00289
00290 unlock();
00291 return -1;
00292 }
00293
00294 int origLength=length;
00295
00296 while (buffered && length) {
00297
00298
00299
00300
00301 int len = MIN(length,buffered);
00302
00303 int currentBlockSize = (char*)bufferEnd-(char*)start;
00304 currentBlockSize=MIN(currentBlockSize,len);
00305
00306
00307 cc = currentBlockSize>>1;
00308 for(c=0; c<cc ;c++)
00309 pp[c] += (int32_t) ((IN_DATATYPE*)start)[c];
00310
00311
00312 (char*)start += currentBlockSize;
00313 len -= currentBlockSize;
00314 (char*)pp += currentBlockSize;
00315 length -= currentBlockSize;
00316 if ((end!=buffer) && (start==bufferEnd))
00317 start = buffer;
00318
00319 if (len) {
00320
00321
00322 cc = len>>1;
00323 for(c=0; c<cc ;c++)
00324 pp[c] += (int) ((IN_DATATYPE*)start)[c];
00325
00326
00327 (char*)pp += len;
00328 (char*)start += len;
00329 length -= len;
00330 if ((end!=buffer) && (start==bufferEnd))
00331 start = buffer;
00332 }
00333 }
00334
00335 unlock();
00336 return origLength-length;
00337 }
00338
00339 int Pipe::read(int length, void *data) {
00340 lock();
00341
00342 _SIZE(buffered);
00343
00344
00345 if(!buffered) {
00346 unlock();
00347 return -1;
00348 }
00349
00350
00351
00352
00353 if (buffered<length)
00354 if(blocking) {
00355 unlock();
00356 return -1;
00357 } else
00358 length = buffered;
00359
00360
00361 int origLength=length;
00362
00363 while (buffered && length) {
00364
00365
00366
00367
00368 int len = MIN(length,buffered);
00369
00370 int currentBlockSize = (char*)bufferEnd-(char*)start;
00371 currentBlockSize=MIN(currentBlockSize,len);
00372
00373 memcpy(data, start, currentBlockSize);
00374
00375 (char*)start += currentBlockSize;
00376 len -= currentBlockSize;
00377 (char*)data += currentBlockSize;
00378 length -= currentBlockSize;
00379 if ((end!=buffer) && (start==bufferEnd))
00380 start = buffer;
00381
00382 if (len) {
00383 memcpy(data, start, len);
00384 (char*)data += len;
00385 (char*)start += len;
00386 length -= len;
00387 if ((end!=buffer) && (start==bufferEnd))
00388 start = buffer;
00389 }
00390 }
00391
00392 unlock();
00393 return origLength-length;
00394 }
00395
00396 int Pipe::write(int length, void *data) {
00397 int spc;
00398 lock();
00399
00400 _SPACE(spc);
00401 if (length>(spc-1)) {
00402
00403
00404 unlock();
00405 return -1;
00406 }
00407
00408 int origLength=length;
00409
00410 while (length) {
00411
00412
00413
00414
00415 int len=MIN(length, spc-1);
00416
00417 int currentBlockSize = (char*)bufferEnd-(char*)end;
00418 currentBlockSize=MIN(currentBlockSize, len);
00419 ::memcpy(end, data, currentBlockSize);
00420
00421 (char*)end += currentBlockSize;
00422
00423 len -= currentBlockSize;
00424
00425 (char*)data += currentBlockSize;
00426 length -= currentBlockSize;
00427 if ((start!=buffer) && (end==bufferEnd))
00428 end = buffer;
00429
00430 if (len) {
00431 ::memcpy(end, data, len);
00432 (char*)data += len;
00433 (char*)end += len;
00434 length -= len;
00435
00436 if ((start!=buffer) && (end==bufferEnd))
00437 end = buffer;
00438 }
00439 }
00440 unlock();
00441 return origLength-length;
00442 }
00443
00444
00445
00446 int Pipe::size() {
00447
00448 lock();
00449 _SIZE(res);
00450 unlock();
00451 return res;
00452 }
00453
00454
00455
00456 int Pipe::space() {
00457 int res;
00458 lock();
00459 _SPACE(res);
00460 unlock();
00461 return res;
00462 }
00463
00464 void Pipe::flush() {
00465 lock();
00466 bufferEnd=(char*)buffer+pipesize;
00467 end=start=buffer;
00468 unlock();
00469 }
00470
00471 void Pipe::flush(int bytes) {
00472 lock();
00473 void *temp = malloc(bytes);
00474 read(bytes, temp);
00475 free(temp);
00476 unlock();
00477 }