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 <math.h>
00030 #include <errno.h>
00031
00032 #include <audioproc.h>
00033 #include <pipe.h>
00034 #include <jutils.h>
00035 #include <config.h>
00036
00037
00038 #define MIN(a,b) (a<=b) ? a : b;
00039
00040 #define _SIZE(val) \
00041 if ((char*)end > (char*)start) \
00042 val = (char*)end-(char*)start; \
00043 else \
00044 val = ((char*)bufferEnd-(char*)start)+((char*)end-(char*)buffer);
00045
00046 #define _SPACE(val) \
00047 _SIZE(val); \
00048 val = ((char*)bufferEnd-(char*)buffer)-val;
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static inline void copy_byte(void *dst, void *src, int samples) {
00060 memcpy(dst,src,samples);
00061 }
00062
00063 static inline void copy_int16_to_float(void *dst, void *src, int samples) {
00064 register int c;
00065 for( c = samples; c>0 ; c-- ) {
00066 ((float*)dst)[c] = ((int16_t*)src)[c] / 32768.0f;
00067 }
00068 }
00069
00070 static inline void copy_float_to_int16(void *dst, void *src, int samples) {
00071 register int c;
00072 for( c = samples; c>0 ; c-- ) {
00073 ((int16_t*)dst)[c] = (int16_t) lrintf( ((float*)src)[c] );
00074 }
00075 }
00076
00077 static inline void mix_int16_to_int32(void *dst, void *src, int samples) {
00078 register int c;
00079 for( c = samples ; c>0 ; c-- ) {
00080 ((int32_t*)dst)[c]
00081 +=
00082 ((int16_t*)src)[c];
00083 }
00084 }
00085
00087
00088
00089 static struct pipe_copy_list callbacks[] = {
00090 { "copy_byte", copy_byte, 1, 1 },
00091 { "copy_int16_to_float", copy_int16_to_float, sizeof(int16_t), sizeof(float) },
00092 { "copy_float_to_int16", copy_float_to_int16, sizeof(float), sizeof(int16_t) },
00093 { "mix_int16_to_int32", mix_int16_to_int32, sizeof(int16_t), sizeof(int32_t) },
00094 { 0, 0 }
00095 };
00096
00097
00098
00099
00100
00101
00102 bool Pipe::set_input_type(char *name) {
00103 int c;
00104 for(c=0 ; callbacks[c].callback ; c++) {
00105 if(strcasecmp(name,callbacks[c].name)==0) {
00106 write_copy_cb = &callbacks[c];
00107 return true;
00108 }
00109 }
00110 error("can't set input type \"%s\" on pipe",name);
00111 return false;
00112 }
00113
00114 bool Pipe::set_output_type(char *name) {
00115 int c;
00116 for(c=0 ; callbacks[c].callback ; c++) {
00117 if(strcasecmp(name,callbacks[c].name)==0) {
00118 read_copy_cb = &callbacks[c];
00119 return true;
00120 }
00121 }
00122 error("can't set output type \"%s\" on pipe",name);
00123 return false;
00124 }
00125
00126
00127 Pipe::Pipe(int size) {
00128 func("Pipe::Pipe(%i)",size);
00129 pipesize = size;
00130 buffer = calloc(pipesize, 1);
00131 if(!buffer)
00132 error("FATAL: can't allocate %i bytes buffer for audio Pipe: %s",
00133 pipesize, strerror(errno));
00134 bufferEnd=(char*)buffer+size;
00135 end=start=buffer;
00136
00137
00138 set_input_type("copy_byte");
00139 set_output_type("copy_byte");
00140
00141 read_blocking = false;
00142 read_blocking_time = 20000;
00143 write_blocking = false;
00144 write_blocking_time = 20000;
00145
00146 _thread_init();
00147
00148
00149 }
00150
00151 Pipe::~Pipe() {
00152 func("Pipe::~Pipe : freeing %p",buffer);
00153 lock();
00154 free(buffer);
00155 unlock();
00156
00157 }
00158
00159 void Pipe::set_block(bool input, bool output) {
00160 lock();
00161 write_blocking = input;
00162 read_blocking = output;
00163 unlock();
00164 }
00165
00166 void Pipe::set_block_timeout(int input, int output) {
00167 lock();
00168 write_blocking_time = input;
00169 read_blocking_time = output;
00170 unlock();
00171 }
00172
00173 int Pipe::read(int length, void *data) {
00174 int worklen, origlen, truelen;
00175 int blk, len, buffered, buffered_bytes;
00176 int ttl = 0;
00177
00178 if(read_blocking) ttl = read_blocking_time;
00179
00180 lock();
00181
00182 _SIZE(buffered_bytes);
00183 buffered = buffered_bytes
00184 / read_copy_cb->src_samplesize;
00185 truelen = length;
00186
00187
00188 while(buffered<length) {
00189
00190
00191
00192
00193 if(read_blocking) {
00194 unlock();
00195 if(!ttl) return -1;
00196 jsleep(0,100); ttl -= 10;
00197 lock();
00198 _SIZE(buffered_bytes);
00199 buffered = buffered_bytes
00200 / read_copy_cb->src_samplesize;
00201 } else {
00202
00203 if(!buffered) {
00204 unlock();
00205 return 0;
00206 } else
00207 truelen = buffered;
00208 break;
00209 }
00210 }
00211
00212 origlen = worklen = truelen * read_copy_cb->src_samplesize;
00213
00214 while (worklen) {
00215
00216
00217
00218
00219 len = MIN(worklen,buffered_bytes);
00220
00221 blk = ((char*)bufferEnd - (char*)start);
00222
00223 blk=MIN(blk,len);
00224
00225
00226 (*read_copy_cb->callback)
00227 (data, start,
00228 blk / read_copy_cb->src_samplesize);
00229
00230 memset(start,0,blk / read_copy_cb->src_samplesize);
00231
00232 (char*)start += blk;
00233 len -= blk;
00234 (char*)data += blk;
00235 worklen -= blk;
00236 if ((end!=buffer) && (start==bufferEnd))
00237 start = buffer;
00238
00239 if (len) {
00240
00241 (*read_copy_cb->callback)
00242 (data, start,
00243 len / read_copy_cb->src_samplesize);
00244
00245
00246 memset(start,0,len / read_copy_cb->src_samplesize);
00247 (char*)data += len;
00248 (char*)start += len;
00249 worklen -= len;
00250 if ((end!=buffer) && (start==bufferEnd))
00251 start = buffer;
00252 }
00253 }
00254
00255 unlock();
00256 return ( (origlen-worklen)/read_copy_cb->src_samplesize );
00257 }
00258
00259 int Pipe::write(int length, void *data) {
00260 int worklen, origlen, space_samples;
00261 int space_bytes, len, truelen, blk;
00262 int ttl = 0;
00263
00264 if(write_blocking) ttl = write_blocking_time;
00265
00266 lock();
00267
00268 _SPACE(space_bytes);
00269 space_samples = (space_bytes / write_copy_cb->dst_samplesize);
00270 truelen = length;
00271
00272 while(length > space_samples) {
00273
00274
00275 if(write_blocking) {
00276 unlock();
00277 if(!ttl) return -1;
00278 jsleep(0,100); ttl -= 10;
00279 lock();
00280
00281 _SPACE(space_bytes);
00282 space_samples = space_bytes
00283 / write_copy_cb->dst_samplesize;
00284
00285 } else {
00286
00287 if(!space_bytes) {
00288 unlock();
00289 return 0;
00290 } else
00291
00292 truelen = space_samples;
00293 break;
00294 }
00295 }
00296
00297 origlen = worklen = truelen * write_copy_cb->dst_samplesize;
00298
00299 while (worklen) {
00300
00301
00302
00303 len=MIN(worklen, space_bytes);
00304
00305 blk = (char*)bufferEnd-(char*)end;
00306 blk = MIN(blk, len);
00307
00308
00309 (*write_copy_cb->callback)
00310 (end, data,
00311 blk / write_copy_cb->dst_samplesize);
00312
00313 (char*)end += blk;
00314 len -= blk;
00315 (char*)data += blk;
00316 worklen -= blk;
00317 if ((start!=buffer)
00318 && (end==bufferEnd))
00319 end = buffer;
00320
00321 if (len) {
00322
00323 (*write_copy_cb->callback)
00324 (end, data,
00325 len / write_copy_cb->dst_samplesize);
00326
00327 (char*)data += len;
00328 (char*)end += len;
00329 worklen -= len;
00330
00331 if ((start!=buffer)
00332 && (end==bufferEnd))
00333 end = buffer;
00334 }
00335 }
00336 _SPACE(space_bytes);
00337 unlock();
00338 return ((origlen-worklen) / write_copy_cb->dst_samplesize);
00339 }
00340
00341
00342
00343 int Pipe::size() {
00344 int res;
00345
00346 lock();
00347 _SIZE(res);
00348 unlock();
00349
00350 return res;
00351 }
00352
00353
00354
00355 int Pipe::space() {
00356 int res;
00357 lock();
00358 _SPACE(res);
00359 unlock();
00360
00361 return res;
00362 }
00363
00364 void Pipe::flush() {
00365 lock();
00366 bufferEnd=(char*)buffer+pipesize;
00367 end=start=buffer;
00368 unlock();
00369 }
00370
00371 void Pipe::flush(int bytes) {
00372 lock();
00373 void *temp = malloc(bytes);
00374 read(bytes, temp);
00375 free(temp);
00376 unlock();
00377 }