~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/audio/audio-oss.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * audio-oss.cc --
  3  *
  4  *      Audio driver for OSS (Open Sound) API, which is primarily
  5  *      used on FreeBSD and Linux.
  6  */
  7 
  8 /*
  9  * Full Duplex audio module for the new sound driver and full duplex
 10  * cards. Luigi Rizzo, from original sources supplied by Amancio Hasty.
 11  *
 12  * This includes some enhancements:
 13  * - limit the maximum size of the playout queue to approx 4 frames;
 14  *   this is necessary if the write channel is slower than expected;
 15  *   the fix is based on two new ioctls, AIOGCAP and AIONWRITE,
 16  *   but the code should compile with the old driver as well.
 17  * - use whatever format is available from the card (included split
 18  *   format e.g. for the sb16);
 19  */
 20 
 21 #ifdef __FreeBSD__
 22     /* included for __FreeBSD_version */
 23 #   include <sys/param.h>
 24 #   if (__FreeBSD_version >= 400000)
 25 #       include <sys/soundcard.h>
 26 #   else
 27 #       include <machine/soundcard.h>
 28 #   endif
 29 #else
 30 #   include <sys/soundcard.h>
 31 #endif
 32 
 33 //#include <osfcn.h>
 34 #include <fcntl.h>
 35 #include "mulaw.h"
 36 #include "tclcl.h"
 37 #include "audio-oss.h"
 38 
 39 #define ULAW_ZERO 0x7f
 40 #define ABUFLOG2 7
 41 #define ABUFLEN ( 1<< ABUFLOG2)
 42 #define NFRAG 5
 43 #define NDRVRBUF 5
 44 
 45 // this is the OTcl wrapper to make the C++ object a Tcl class
 46 static class OSSAudioClass : public TclClass {
 47 public:
 48     OSSAudioClass() : TclClass("Audio/OSS") {}
 49     TclObject* create(int, const char*const*) {
 50         return (new OSSAudio);
 51 
 52     }
 53 } oss_audio_class;
 54 
 55 OSSAudio::OSSAudio() : mixerfd(-1)
 56 {
 57   // the "*2" is because we want to accomodate 16 bit samples as well as 8.
 58     readbuf = new u_char[ABUFLEN*NDRVRBUF*2];
 59     s16_buf = new u_short[blksize_];
 60     readCopyInPtr = readbuf;
 61     readCopyOutPtr = readbuf;
 62 
 63     //typically we will be using 8 bit samples in u-law mode...
 64     memset(readbuf, ULAW_ZERO, blksize_);
 65 
 66     /*
 67      * The only way to determine if the device is full duplex
 68      * or not is by actually opening it.  Unfortunately, we might
 69      * not be able to open it because some other process is
 70      * using it.  Assume half-duplex.  Obtain() will override
 71      * if appropriate.
 72      */
 73     duplex_ = 0;
 74 
 75     input_names_ = "mike linein cd";
 76     output_names_ = "speaker lineout";
 77     played=0;
 78     playedDuringLast=0;
 79     sample_rate = 8000; // default value is 8K
 80     use16RawPCM = 0;    // default value is to use 8 bit mulaw...
 81     stereo = 0; // default value is mono
 82 }
 83 
 84 void
 85 OSSAudio::Obtain()
 86 {
 87     char *thedev;
 88     char buf[64];
 89     int d = -1;
 90     int capabilities = 0;
 91     played=0;
 92 
 93     if (haveaudio())
 94         return;
 95 
 96     // get ready to open the audio device
 97     if(device_ < 0)
 98     {
 99         thedev=getenv("AUDIODEV");
100         if (thedev==NULL)
101             thedev="/dev/audio";
102         else if (thedev[0]>='') {
103             d = atoi(thedev);
104             sprintf(buf,"/dev/audio%d", d);
105             thedev = buf ;
106         }
107     }
108     else
109     {
110         d = device_;
111         sprintf(buf, "/dev/audio%d", d);
112         thedev = buf;
113     }
114     // open the audio device
115 #if 0
116     fd_ = open(thedev, O_WRONLY);
117     ioctl(fd_, SNDCTL_DSP_GETCAPS, &capabilities);
118     if (capabilities & DSP_CAP_DUPLEX) {
119         close(fd_);
120 #endif
121         fd_ = open(thedev, O_RDWR);
122 #if 0
123     }
124 #endif
125 
126     // get ready to open the mixer
127     if(device_ < 0)
128     {
129         thedev=getenv("MIXERDEV");
130         if (thedev == NULL)
131         {
132             if (d < 0)
133                 thedev = "/dev/mixer";
134             else {
135                 sprintf(buf,"/dev/mixer%d", d);
136                 thedev = buf ;
137             }
138         }
139     }
140     else
141     {
142       sprintf(buf,"/dev/mixer%d", d);
143       thedev = buf ;
144     }
145     // open the mixer
146     mixerfd = open(thedev, O_RDWR); // O_NDELAY
147 
148     // check for errors in opening the device
149     if(fd_ <0 ) {
150         printf("couldn't open audio device\n"); 
151         // retry using read only(?)
152         // -- if so, then will need to track the last mode that was used
153     }
154     if(mixerfd <0 ) 
155         printf("couldn't open mixer device\n");
156 
157     if (fd_ >= 0) {
158         // do the IOCTL to control the audio device and mixer
159         int channels = stereo+1;
160         int rec_rate=sample_rate;
161         int formats=0;
162         int playformat=0, recordformat=0;
163         int ret1=0;
164 #ifdef SNDCTL_DSP_CHANNELS
165         ret1=ioctl(fd_, SNDCTL_DSP_CHANNELS, &channels);
166 #else   
167         if (channels == 2)
168             ret1=ioctl(fd_, SNDCTL_DSP_STEREO, &channels);
169 #endif
170         if(ret1<0) {
171           perror("failed to set number of channels correctly");
172         }
173         ret1=ioctl(fd_, SNDCTL_DSP_SPEED, &rec_rate);
174         if(ret1<0) {
175           perror("failed to set sampling rate");
176         } 
177         capabilities=0;
178         if (ioctl(fd_, SNDCTL_DSP_GETCAPS, &capabilities) <0) {
179             perror("failed to get capabilities");
180         }
181         if( ioctl(fd_, SNDCTL_DSP_GETFMTS, &formats) <0) {
182             perror("failed to get formats");
183         }
184 
185         int sources=0;
186         if ( ioctl(mixerfd, SOUND_MIXER_READ_DEVMASK, &sources) == -1 ) {
187             perror("failed to poll inputs");
188         }
189 
190         if(!(sources & (1 << SOUND_MIXER_RECLEV))) {
191             vol_device=SOUND_MIXER_IGAIN;
192         }
193         else vol_device=SOUND_MIXER_RECLEV;
194 
195         switch (capabilities & (DSP_CAP_DUPLEX) ) {
196         case DSP_CAP_DUPLEX :
197 #ifdef AFMT_WEIRD
198             if(formats & AFMT_WEIRD) { /* this is the sb16... */
199                 if (formats & AFMT_S16_LE) {
200                     playformat = AFMT_U8 ;
201                     recordformat = AFMT_S16_LE;
202                 } else {
203                     printf("sorry, no supported formats\n");
204                     close(fd_);
205                     close(mixerfd);
206                     fd_ = -1 ;
207                     return;
208                 }
209             }
210             else { // well-behaved soundcard
211 #endif
212             /*
213              * this entry for cards with decent full duplex. Use s16
214              * preferably (some are broken in ulaw) or ulaw or u8 otherwise.
215              */
216             if (formats & AFMT_S16_LE)
217                 playformat = recordformat = AFMT_S16_LE ;
218             else if (formats & AFMT_MU_LAW)
219                 playformat = recordformat = AFMT_MU_LAW ;
220             else if (formats & AFMT_U8)
221                 playformat = recordformat = AFMT_U8 ;
222             else {
223                 printf("sorry, no supported formats\n");
224                 close(fd_);
225                 close(mixerfd);
226                 fd_ = -1 ;
227                 return;
228             }
229 #ifdef AFMT_WEIRD
230          }
231 #endif      
232             if ((playformat != AFMT_S16_LE) && (use16RawPCM == 1))
233               printf("sorry, can't do 16 bit samples with this sound card...\n");
234             break ;
235 
236         default :
237             // start of new section
238             //printf("sorry don't know how to deal with this card\n");
239             /*
240              * this entry for cards with half duplex. Use s16
241              * preferably (some are broken in ulaw) or ulaw or u8 otherwise.
242              */
243             if (formats & AFMT_S16_LE)
244                 playformat = recordformat = AFMT_S16_LE ;
245             else if (formats & AFMT_MU_LAW)
246                 playformat = recordformat = AFMT_MU_LAW ;
247             else if (formats & AFMT_U8)
248                 playformat = recordformat = AFMT_U8 ;
249             else {
250                 printf("sorry, no supported formats\n");
251                 // end of new section
252                 close (fd_);
253                 close(mixerfd);
254                 fd_ = -1;
255                 // start of new section
256             }
257             // end of new section
258             if ((playformat != AFMT_S16_LE) && (use16RawPCM == 1))
259               printf("sorry, can't do 16 bit samples with this sound card...\n");
260             break;
261         }
262 
263 #ifdef AIOSFMT
264         if(playformat!=recordformat) {
265                 // printf("specifing two formats to your poor soundcard\n");
266                 snd_chan_param params;
267                 params.play_rate=sample_rate;
268                 params.rec_rate=sample_rate;
269                 params.play_format=playformat;
270                 params.rec_format=recordformat;
271                 int stat=ioctl(fd_, AIOSFMT, &params);
272                 if(stat<0) {
273                         printf("dual-format specification failed\n");
274                 }
275         }
276         else {
277                 ioctl(fd_, SNDCTL_DSP_SETFMT, &playformat);
278         }
279         play_fmt=playformat;
280         rec_fmt=recordformat;
281 #else
282         if(playformat!=recordformat) {
283                 printf("Different formats for playback and capture: binary not compiled for this\n");
284                 close(fd_);
285                 close(mixerfd);
286                 fd_=-1;
287                 return;
288         }
289         ioctl(fd_, SNDCTL_DSP_SETFMT, &playformat);
290         play_fmt=playformat;
291         rec_fmt=recordformat;
292 #endif
293 
294         int frag= (NFRAG << 16) | ABUFLOG2;
295         int ret=ioctl(fd_, SNDCTL_DSP_SETFRAGMENT, &frag);
296 
297         duplex_ = (capabilities & DSP_CAP_DUPLEX) ? 1:0;
298 
299         /*
300          * Set the line input level to 0 to shut
301          * off the analog side-tone gain between
302          * the line-in and line-out.  This would otherwise
303          * wreak havoc on an echo canceler, for example,
304          * plugged into the audio adaptor.
305          */
306         int v = 0;
307         ret=ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_LINE), &v);
308         ret=ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_MIC), &v);
309         if( sources & (1 << SOUND_MIXER_DIGITAL1) ) {
310              ret=ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_DIGITAL1),&v);
311         }
312         if( sources & (1 << SOUND_MIXER_DIGITAL2) ) {
313              ret=ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_DIGITAL2),&v);
314         }
315         int device = 1 << SOUND_MIXER_MIC;
316         if ( ioctl(mixerfd, SOUND_MIXER_WRITE_RECSRC, &device) == -1 ) {
317           perror("failed to select input");
318         }
319 
320         /*
321          * Restore the hardware settings in case
322          * some other vat changed them.
323          */
324 
325         InputPort(iport_);
326         SetRGain(rgain_);
327         SetPGain(pgain_);
328 
329         if (duplex_)
330             Audio::Obtain();
331         else
332             notify();
333     }
334 }
335 
336 
337 void OSSAudio::Release()
338 {
339     if (haveaudio()) {
340         if (mixerfd > 0) {
341             close(mixerfd);
342         }
343         mixerfd = -1;
344         Audio::Release();
345     }
346 }
347 
348 // Called when you want to write audio out to the sound
349 // card. Called from within controller.cc
350 void OSSAudio::Write(u_char *cp)
351 {
352     // blksize_ is inherited from Audio parent class (audio.h/.cc)
353     // it is the number of samples NOT the size of the samples
354     unsigned int i = blksize_;
355     int l;
356 
357     if (play_fmt == AFMT_S16_LE) {      
358       if (use16RawPCM == 0) {
359         // translate it from 8 bit mulaw to 16 bit linear
360         for (i=0; i< blksize_; i++)
361           s16_buf[i] = mulawtolin[cp[i]] ;
362         cp = (u_char *)s16_buf;
363       }
364       // size goes from 8 bit to 16 bit, so you need to double i.
365       i = 2 *blksize_ ;
366     }
367     else if (play_fmt == AFMT_S8) {
368         for (i=0; i< blksize_; i++) {
369             int x = mulawtolin[cp[i]] ;
370             x =  (x >> 8 ) & 0xff;
371             cp[i] = (u_char)x ;
372         }
373         i = blksize_ ;
374     } else if (play_fmt == AFMT_U8) {
375         for (i=0; i< blksize_; i++) {
376             int x = mulawtolin[cp[i]] ;
377             x =  (x >> 8 ) & 0xff;
378             x = (x ^ 0x80) & 0xff ;
379             cp[i] = (u_char)x ;
380         }
381         i = blksize_ ;
382     }
383     played=1;
384     audio_buf_info info;
385     ioctl(fd_, SNDCTL_DSP_GETOSPACE,&info);
386     if(info.bytes>=(info.fragstotal*info.fragsize)-(info.fragsize>>1) ) {
387       if(playedDuringLast) { // adjusting for fast sound card
388           int locali=i/2;
389             unsigned char * localcp=cp;
390             for ( ; locali > 0 ; locali -= l) {
391                 l = write(fd_, localcp, locali);
392                 localcp += l;
393             } 
394         } else { // would adjust, but haven't played during last
395             unsigned char buf[blksize_/2];
396             memset(buf,cp[0],blksize_/2);
397             write(fd_, buf, blksize_/2);
398         }
399     }
400     // write the audio data to the sound card.
401     for ( ; i > 0 ; i -= l) {
402         l = write(fd_, cp, i);
403         cp += l;
404     }
405 }
406 
407 // The Read call is to read data in from the sound
408 // card (called in controller.cc). Basically it just
409 // reads from a ring buffer. The data is put into the
410 // buffer by FrameReady()
411 u_char* OSSAudio::Read()
412 {
413   playedDuringLast=played;
414   played=0;
415     
416   u_char* ptr=readCopyOutPtr;
417   if (use16RawPCM == 0) {
418     // these are 8 bit samples
419     readCopyOutPtr+=blksize_;
420     // since it is 8 bit, we only use half the buffer
421     if(readCopyOutPtr>=readbuf+ABUFLEN*NDRVRBUF) {
422       if(readCopyOutPtr>readbuf+ABUFLEN*NDRVRBUF) {
423         printf("::read() pointer error: %d\n",
424                readCopyOutPtr-readbuf+ABUFLEN*NDRVRBUF );
425       }
426       readCopyOutPtr=readbuf;
427     }
428   } else {
429     // these are 16 bit samples, so we have blksize_ * 2 bytes
430     readCopyOutPtr+=(blksize_*2);
431     // since it is 16 bit samples, we use the whole buffer
432     if(readCopyOutPtr>=readbuf+(ABUFLEN*NDRVRBUF*2)) {
433       if(readCopyOutPtr>readbuf+(ABUFLEN*NDRVRBUF*2)) {
434         printf("::read() pointer error: %d\n",
435                readCopyOutPtr-readbuf+(ABUFLEN*NDRVRBUF*2));
436       }
437       readCopyOutPtr=readbuf;
438     }
439   }
440   return ptr;
441 }
442 
443 /*
444  * In most mixer devices, there is only a master volume control on
445  * the capture channel, so the following code does not really work
446  * as expected. The only (partial) exception is the MIC line, where
447  * there is generally a 20dB boost which can be enabled or not
448  * depending on the type of device.
449  */
450 void OSSAudio::SetRGain(int level)
451 {    
452     // start of new section
453   /*    if (!haveaudio())
454         Obtain(); */
455     // end of new section
456 
457     rgain_ = level;
458     float x = level;
459     level = (int) (x/2.56);
460     int foo = (level<<8) | level;
461     switch (iport_) {
462     case 2:
463         if (ioctl(mixerfd, MIXER_WRITE(vol_device), &foo) == -1)
464            perror("failed set input line volume for 2");
465         break;
466     case 1:
467         if (ioctl(mixerfd, MIXER_WRITE(vol_device), &foo) == -1)
468            perror("failed set input line volume for 1");
469         break;
470     case 0:
471         if (ioctl(mixerfd, MIXER_WRITE(vol_device), &foo) == -1)
472            perror("failed set input line volume for 0");
473         break;
474     }
475 }
476 
477 // set the playback gain (volume)
478 void OSSAudio::SetPGain(int level)
479 {
480     // start of new section
481   /*    if (!haveaudio())
482                 Obtain(); */
483     // end of new section
484     pgain_ = level;
485     float x = level;
486     level = (int) (x/2.56);
487     int foo = (level<<8) | level;
488     if (mixerfd >= 0) {
489             if (ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &foo) == -1) {
490                     perror("failed to output level");
491             }
492     }
493 }
494 
495 void OSSAudio::OutputPort(int p)
496 {
497     oport_ = p;
498 }
499 
500 void OSSAudio::InputPort(int p)
501 {
502     int   zero = 0;
503 
504     switch(p) {
505     case 2:
506         zero = 1 << SOUND_MIXER_CD;
507         break;
508     case 1:
509         zero = 1 << SOUND_MIXER_LINE;
510         break;
511     case 0 :
512         zero = 1 << SOUND_MIXER_MIC;
513         break;
514     }
515     int i=0;
516     if ( ioctl(mixerfd, SOUND_MIXER_READ_DEVMASK, &i) == -1 ) {
517         perror("failed to select input");
518         p = 0;
519     }
520     if ( ioctl(mixerfd, SOUND_MIXER_READ_RECMASK, &i) == -1 ) {
521         perror("failed to select input");
522         p = 0;
523     }
524     if ( ioctl(mixerfd, SOUND_MIXER_READ_RECSRC, &i) == -1 ) {
525         perror("failed to select input");
526         p = 0;
527     }
528     if ( ioctl(mixerfd, SOUND_MIXER_WRITE_RECSRC, &zero) == -1 ) {
529         perror("failed to select input");
530         p = 0;
531     }
532     iport_ = p;
533     if ( ioctl(mixerfd, SOUND_MIXER_READ_RECSRC, &i) == -1 ) {
534         perror("failed to select input");
535         p = 0;
536     }
537 }
538 
539 /*
540  * FrameReady must return 0 every so often, or the system will keep
541  * processing mike data and not other events. This function is called
542  * by Audio::dispatch() and if it returns 1 then dispatch will go on
543  * to call Controller::handle_audio(). Basically, this function gets
544  * audio data from the sound card and stores it in a ring buffer (which
545  * is read when the Read() function is called). It returns when there is
546  * a full frame of audio data ready.
547  */
548 int OSSAudio::FrameReady()
549 {
550   if (rec_fmt == AFMT_S16_LE) {
551     if (use16RawPCM == 0) {
552       // we want to store 8 bit mulaw audio in the ring buffer.
553       u_short s16Buffer[ABUFLEN];
554       if( read(fd_, (u_char*)s16Buffer, ABUFLEN) != (int)(ABUFLEN)) {
555         // there isn't a full buffer of audio yet, keep waiting...
556         perror("sound device read");
557       } else {
558         // translate it from 16 bit linear to 8 bit mulaw
559         for (int i=0; i< (int)ABUFLEN>>1; i++) {
560           readCopyInPtr[i] = lintomulaw[ s16Buffer[i] & 0xffff ] ;
561         }
562         readCopyInPtr+=(ABUFLEN>>1);
563         // write it to the ring buffer
564         if(readCopyInPtr>=readbuf+ABUFLEN*NDRVRBUF) {
565           if(readCopyInPtr>readbuf+ABUFLEN*NDRVRBUF) {
566             printf("ossaudio::frameready pointer error by %d\n",
567                    readCopyInPtr-readbuf+ABUFLEN*NDRVRBUF);
568           }
569           readCopyInPtr=readbuf;
570         }
571       }
572     } else {
573       // we want to store 16 bit linear audio in the ring buffer.
574       if( read(fd_, (u_char*)readCopyInPtr, ABUFLEN) != (int)(ABUFLEN)) {
575         // there isn't a full buffer of audio yet, keep waiting...
576         perror("sound device read");
577       } else
578         readCopyInPtr+=ABUFLEN;
579       // store it in the ring buffer
580       if(readCopyInPtr>=readbuf+(ABUFLEN*NDRVRBUF*2)) {
581         if(readCopyInPtr>readbuf+(ABUFLEN*NDRVRBUF*2)) {
582           printf("ossaudio::frameready pointer error by %d\n",
583                  readCopyInPtr-readbuf+(ABUFLEN*NDRVRBUF*2));
584         }
585         readCopyInPtr=readbuf;
586       }
587     }
588   } else {
589     // here we are dealing with legacy 8 bit cards...
590     if( read(fd_, readCopyInPtr, ABUFLEN) != (int)(ABUFLEN) ) {
591       perror("sound device read");
592     }
593     else {
594       if (rec_fmt == AFMT_S8) {
595         int i;
596         for (i=0; i< (int)ABUFLEN; i++) {
597           readCopyInPtr[i] = lintomulaw[ readCopyInPtr[i]<<8 ] ;
598         }
599       }
600       else if (rec_fmt == AFMT_U8) {
601         for (int i=0; i< (int)ABUFLEN; i++) {
602           readCopyInPtr[i] = lintomulaw[ (readCopyInPtr[i]<<8) ^ 0x8000 ] ;
603         }
604       }
605       readCopyInPtr+=ABUFLEN;
606       if(readCopyInPtr>=readbuf+ABUFLEN*NDRVRBUF)
607         readCopyInPtr=readbuf;   
608     }
609   }
610 
611   int ret;
612     
613   // return value is dependant on how much data we have saved up...
614   if( (unsigned int)(readCopyInPtr)>=(unsigned int)(readCopyOutPtr) ) {
615     // if the data doesn't wrap around the end of the buffer
616     if (use16RawPCM == 1)
617       // wait for a 16 bit frame
618       ret= ( (unsigned int)(readCopyInPtr)-(unsigned int)(readCopyOutPtr)>=(blksize_*2));
619     else
620       // wait for an 8 bit frame
621       ret= ( (unsigned int)(readCopyInPtr)-(unsigned int)(readCopyOutPtr)>=blksize_);
622     return ret;
623   }
624   else {
625     // the data wraps around the end of the buffer...
626     if (use16RawPCM == 1)
627       // wait for a 16 bit frame
628       ret=((readbuf+(ABUFLEN*NDRVRBUF*2)-readCopyOutPtr+readCopyInPtr-readbuf)
629                >=(int)(blksize_*2));
630     else
631       // wait for an 8 bit frame
632       ret=((readbuf+ABUFLEN*NDRVRBUF-readCopyOutPtr+readCopyInPtr-readbuf)
633                >=(int)blksize_);
634     return ret;
635   }
636 }
637 
638 // commands that allow control from Tcl code
639 int OSSAudio::command(int argc, const char*const* argv)
640 {
641         Tcl& tcl = Tcl::instance();
642         if (argc == 2) {
643           if (strcmp(argv[1], "useRaw16PCM") == 0) {
644             use16RawPCM = 1;
645             return (TCL_OK);
646           }
647           if (strcmp(argv[1], "useStereo") == 0) {
648             stereo = 1;
649             return (TCL_OK);
650           }
651           if (strcmp(argv[1], "in16bitMode") == 0) {
652             sprintf(tcl.result(), "%d", use16RawPCM);
653             return (TCL_OK);
654           }
655           if (strcmp(argv[1], "inStereoMode") == 0) {
656             sprintf(tcl.result(), "%d", stereo);
657             return (TCL_OK);
658           }
659           if (strcmp(argv[1], "getSampleRate") == 0) {
660             sprintf(tcl.result(), "%d", sample_rate);
661             return (TCL_OK);
662           }
663         }
664         if (argc == 3) {
665           if (strcmp(argv[1], "set_sample_rate") == 0) {
666             sample_rate = atoi(argv[2]);
667             return (TCL_OK);
668           }
669         }
670         return (Audio::command(argc,argv));
671 }
672 
673 
674 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.