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