Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members  

pipe.cpp

00001 /*
00002   Copyright (c) 2001 Charles Samuels <charles@kde.org>
00003   Copyright (c) 2002 - 2003 Denis Rojo <jaromil@dyne.org>
00004   
00005 this pipe class was first written by Charles Samuels
00006 and then heavily mutilated and optimized by Denis Rojo
00007 
00008 This library is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU Library General Public
00010 License as published by the Free Software Foundation; either
00011 version 2 of the License, or (at your option) any later version.
00012   
00013 This library is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 Library General Public License for more details.
00017    
00018 You should have received a copy of the GNU Library General Public License
00019 along with this library; see the file COPYING.LIB.  If not, write to
00020 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021 Boston, MA 02111-1307, USA.
00022 
00023 "$Id: pipe.cpp,v 1.1.1.1 2003/12/08 12:20:33 jaromil Exp $"
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   start is a pointer to the first character that goes out
00050   end is a pointer to the last character to go out
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   //  _thread_destroy();
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     //    func("Pipe::read_float(%i,%p) : only %i bytes in the pipe",
00085     //          samples,buf,buffered);
00086     unlock();
00087     return -1;
00088   }
00089 
00090   int origLength=length;
00091   
00092   while (buffered && length)    {
00093                                 
00094     /* |buffer*****|end-----------|start********|bufferEnd
00095        |buffer-----|start*********|end----------|bufferEnd */
00096     
00097     int len = MIN(length,buffered);
00098     
00099     int currentBlockSize = (char*)bufferEnd-(char*)start;
00100     currentBlockSize=MIN(currentBlockSize,len);
00101 
00102     /* fill */
00103     cc = currentBlockSize; //>>2 QUAAA
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; // /2 /32768.0f
00109       break;
00110     case 2:
00111       for(c=0; c<cc; c++) {
00112         //      pp[c*2] = ((IN_DATATYPE*)start)[c*2] /32768.0f;
00113         //      pp[c*2+1] = ((IN_DATATYPE*)start)[c*2+1] /32768.0f;
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) { /* short circuit */
00129       
00130       /* fill */
00131       cc = len; // >>2 QUAAA
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; // /2 /32768.0f
00137       break;
00138     case 2:
00139       for(c=0; c<cc; c++) {
00140         //      pp[c*2] = ((IN_DATATYPE*)start)[c*2] /32768.0f;
00141         //      pp[c*2+1] = ((IN_DATATYPE*)start)[c*2+1] /32768.0f;
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 /* this takes SAMPLES, they can be stereo or mono
00164    mono will be averaged between the two channels
00165    it is supposed that the pipes always contains 16bit STEREO (length = samples<<2)
00166    
00167    RETURNS: samples read
00168  */
00169 int Pipe::read_float_bidi(int samples, float **buf, int channels) {
00170   lock();
00171 
00172   _SIZE(buffered);
00173 
00174   /* if nothing is in, returns -1 */
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     /* |buffer*****|end-----------|start********|bufferEnd
00200        |buffer-----|start*********|end----------|bufferEnd */
00201     
00202     int len = MIN(length,buffered);
00203     
00204     int currentBlockSize = (char*)bufferEnd-(char*)start;
00205     currentBlockSize=MIN(currentBlockSize,len);
00206 
00207     /* fill */
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; // /2 /32768.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) { /* short circuit */
00235       
00236       /* fill */
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; // /2 /32768.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   /* int buffered = size(); */
00279   _SIZE(buffered);
00280   int c, cc;
00281 
00282   int length = samples<<2;
00283   int32_t *pp = mix;
00284 
00285   //  if (!buffered) return -1;  
00286 
00287   if (buffered<length) {
00288     //    func("Pipe::mix16stereo(%i,%p) : only %i bytes in the pipe",
00289     //    samples,mix,buffered);
00290     unlock();
00291     return -1;
00292   }
00293   
00294   int origLength=length;
00295   
00296   while (buffered && length)    {
00297                                 
00298     /* |buffer*****|end-----------|start********|bufferEnd
00299        |buffer-----|start*********|end----------|bufferEnd */
00300     
00301     int len = MIN(length,buffered);
00302     
00303     int currentBlockSize = (char*)bufferEnd-(char*)start;
00304     currentBlockSize=MIN(currentBlockSize,len);
00305 
00306     /* mix */
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) { /* short circuit */
00320       
00321       /* mix */
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   /* if nothing is in, returns -1 */
00345   if(!buffered) {
00346     unlock();
00347     return -1;
00348   }
00349 
00350   /* if less than desired is in, then 
00351      (blocking) returns -1
00352      (non blocking) returns what's available */
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     /* |buffer*****|end-----------|start********|bufferEnd
00366        |buffer-----|start*********|end----------|bufferEnd */
00367     
00368     int len = MIN(length,buffered);
00369     
00370     int currentBlockSize = (char*)bufferEnd-(char*)start;
00371     currentBlockSize=MIN(currentBlockSize,len);
00372     /* fill */
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) { /* short circuit */
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     //    warning("Pipe::write(%i,%p) : not enough space in the pipe (spc=%i)",length,data,spc);
00403 //    fprintf(stderr,".");
00404     unlock();
00405     return -1;
00406   }
00407 
00408   int origLength=length;
00409 
00410   while (length) {
00411     
00412     /* |buffer-----|end***********|start--------|bufferEnd
00413        |buffer*****|start---------|end**********|bufferEnd */
00414     //    _SPACE(spc);
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) { // short circuit         
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 // |buffer******|end--------------|start**************|bufferEnd
00445 // |buffer-----|start**************|end---------------|bufferEnd
00446 int Pipe::size() {
00447   /* size macro allocates the result variable by itself */
00448   lock();
00449   _SIZE(res);
00450   unlock();
00451   return res;
00452 }
00453 
00454 // |buffer------|end**************|start--------------|bufferEnd
00455 // |buffer*****|start--------------|end***************|bufferEnd
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 }

Generated on Sat Apr 17 17:38:49 2004 for MuSE by doxygen1.3