audio_portaudio.c

00001 /*
00002  * iaxclient: a cross-platform IAX softphone library
00003  *
00004  * Copyrights:
00005  * Copyright (C) 2003-2006, Horizon Wimba, Inc.
00006  * Copyright (C) 2007, Wimba, Inc.
00007  *
00008  * Contributors:
00009  * Steve Kann <stevek@stevek.com>
00010  * Michael Van Donselaar <mvand@vandonselaar.org>
00011  * Shawn Lawrence <shawn.lawrence@terracecomm.com>
00012  *
00013  * This program is free software, distributed under the terms of
00014  * the GNU Lesser (Library) General Public License.
00015  *
00016  * Module: audio_portaudio
00017  * Purpose: Audio code to provide portaudio driver support for IAX library
00018  * Developed by: Shawn Lawrence, Terrace Communications Inc.
00019  * Creation Date: April 18, 2003
00020  *
00021  * This library uses the PortAudio Portable Audio Library
00022  * For more information see: http://www.portaudio.com/
00023  * PortAudio Copyright (c) 1999-2000 Ross Bencina and Phil Burk
00024  *
00025  */
00026 
00027 #if defined(WIN32)  ||  defined(_WIN32_WCE)
00028 #include <stdlib.h>
00029 #define strcasecmp _stricmp
00030 #else
00031 #include <strings.h>
00032 #endif
00033 
00034 #include "audio_portaudio.h"
00035 #include "iaxclient_lib.h"
00036 #include "ringbuffer.h"
00037 #include "portmixer.h"
00038 
00039 #ifdef USE_MEC2
00040 #include "mec3.h"
00041 static echo_can_state_t *ec;
00042 #endif
00043 
00044 #ifdef SPAN_EC
00045 #include "ec/echo.h"
00046 static echo_can_state_t *ec;
00047 #endif
00048 
00049 #ifdef SPEEX_EC
00050 #define restrict __restrict
00051 #include "speex/speex_echo.h"
00052 static SpeexEchoState *ec;
00053 #endif
00054 
00055 #define EC_RING_SZ  8192 /* must be pow(2) */
00056 
00057 
00058 typedef short SAMPLE;
00059 
00060 static PaStream *iStream, *oStream, *aStream;
00061 static PxMixer *iMixer = NULL, *oMixer = NULL;
00062 
00063 static int selectedInput, selectedOutput, selectedRing;
00064 
00065 static int sample_rate = 8000;
00066 static int mixers_initialized;
00067 
00068 
00069 #define MAX_SAMPLE_RATE       48000
00070 #ifndef MS_PER_FRAME
00071 # define MS_PER_FRAME         40
00072 #endif
00073 #define SAMPLES_PER_FRAME     (MS_PER_FRAME * sample_rate / 1000)
00074 
00075 /* static frame buffer allocation */
00076 #define MAX_SAMPLES_PER_FRAME (MS_PER_FRAME * MAX_SAMPLE_RATE  / 1000)
00077 
00078 /* echo_tail length, in frames must be pow(2) for mec/span ? */
00079 #define ECHO_TAIL 4096
00080 
00081 /* RingBuffer Size; Needs to be Pow(2), 1024 = 512 samples = 64ms */
00082 #ifndef OUTRBSZ
00083 # define OUTRBSZ 32768
00084 #endif
00085 
00086 /* Input ringbuffer size;  this doesn't seem to be as critical, and making it big
00087  * causes issues when we're answering calls, etc., and the audio system is running
00088  * but not being drained */
00089 #ifndef INRBSZ
00090 # define INRBSZ  2048
00091 #endif
00092 
00093 /* TUNING:  The following constants may help in tuning for situations
00094  * where you are getting audio-level under/overruns.
00095  *
00096  * If you are running iaxclient on a system where you cannot get
00097  * low-latency scheduling, you may need to increase these.  This tends
00098  * to be an issue on non-MacOSX unix systems, when you are not running
00099  * as root, and cannot ask the OS for higher priority.
00100  *
00101  * RBOUTTARGET:  This a target size of the output ringbuffer, in milliseconds,
00102  * where audio for your speakers goes after being decoded and mixed, and
00103  * before the audio callback asks for it.  It can get larger than this
00104  * (up to OUTRBSZ, above), but when it does, for a bit, we will start
00105  * dropping some frames.  For no drops at all, this needs to be set to
00106  * contain the number of samples in your largest scheduling gap
00107  *
00108  * PA_NUMBUFFERS:  This is the number of buffers that the low-level
00109  * operating system driver will use, for buffering our output (and also
00110  * our input) between the soundcard and portaudio.  This should also be
00111  * set to the maximum scheduling delay.  Some drivers, though, will
00112  * callback _into_ portaudio with a higher priority, so this doesn't
00113  * necessarily need to be as big as RBOUTMAXSZ, although on linux, it
00114  * does.  The default is to leave this up to portaudio..
00115  */
00116 
00117 /* 80ms if average outRing length is more than this many bytes, start dropping */
00118 #ifndef RBOUTTARGET
00119 # define RBOUTTARGET (80)
00120 #endif
00121 
00122 /* size in bytes of ringbuffer target */
00123 #define RBOUTTARGET_BYTES (RBOUTTARGET * (sample_rate / 1000) * sizeof(SAMPLE))
00124 
00125 static char inRingBuf[INRBSZ], outRingBuf[OUTRBSZ];
00126 static rb_RingBuffer inRing, outRing;
00127 
00128 static int outRingLenAvg;
00129 
00130 static int oneStream;
00131 static int auxStream;
00132 static int virtualMonoIn;
00133 static int virtualMonoOut;
00134 
00135 static int running;
00136 
00137 static struct iaxc_sound *sounds;
00138 static int  nextSoundId = 1;
00139 
00140 static MUTEX sound_lock;
00141 
00142 /* forward declarations */
00143 static int pa_start (struct iaxc_audio_driver *d );
00144 static void handle_paerror(PaError err, char * where);
00145 static int pa_input_level_set(struct iaxc_audio_driver *d, float level);
00146 static float pa_input_level_get(struct iaxc_audio_driver *d);
00147 
00148 /* scan devices and stash pointers to dev structures.
00149  *  But, these structures only remain valid while Pa is initialized,
00150  *  which, with pablio, is only while it's running!
00151  *  Also, storing these things in two separate arrays loses the actual
00152  *  PaDeviceID's associated with devices (since their index in these
00153  *  input/output arrays isn't the same as their index in the combined
00154  *  array */
00155 static int scan_devices(struct iaxc_audio_driver *d)
00156 {
00157         int nDevices;
00158         int i;
00159 
00160         d->nDevices = nDevices = Pa_GetDeviceCount();
00161         d->devices = (struct iaxc_audio_device *)
00162                 malloc(nDevices * sizeof(struct iaxc_audio_device));
00163 
00164         for ( i=0; i < nDevices; i++ )
00165         {
00166                 const PaDeviceInfo *pa;
00167                 struct iaxc_audio_device *dev;
00168 
00169                 pa=Pa_GetDeviceInfo(i);
00170                 dev = &(d->devices[i]);
00171 
00172                 if ( pa ) //frik: under Terminal Services this is NULL
00173                 {
00174                         dev->name = (char *)pa->name;
00175                         dev->devID = i;
00176                         dev->capabilities = 0;
00177 
00178                         if ( pa->maxInputChannels > 0 )
00179                                 dev->capabilities |= IAXC_AD_INPUT;
00180 
00181                         if ( pa->maxOutputChannels > 0 )
00182                         {
00183                                 dev->capabilities |= IAXC_AD_OUTPUT;
00184                                 dev->capabilities |= IAXC_AD_RING;
00185                         }
00186 
00187                         if ( i == Pa_GetDefaultInputDevice() )
00188                                 dev->capabilities |= IAXC_AD_INPUT_DEFAULT;
00189 
00190                         if ( i == Pa_GetDefaultOutputDevice() )
00191                         {
00192                                 dev->capabilities |= IAXC_AD_OUTPUT_DEFAULT;
00193                                 dev->capabilities |= IAXC_AD_RING_DEFAULT;
00194                         }
00195                 }
00196                 else //frik: under Terminal Services
00197                 {
00198                         dev->name = "Not usable device";
00199                         dev->devID = i;
00200                         dev->capabilities = 0;
00201                 }
00202         }
00203 
00204         return 0;
00205 }
00206 
00207 static void mono2stereo(SAMPLE *out, SAMPLE *in, int nSamples)
00208 {
00209         int i;
00210         //fprintf(stderr, "mono2stereo: %d samples\n", nSamples);
00211         for ( i=0; i < nSamples; i++ )
00212         {
00213                 *(out++) = *in;
00214                 *(out++) = *(in++);
00215         }
00216 }
00217 
00218 static void stereo2mono(SAMPLE *out, SAMPLE *in, int nSamples)
00219 {
00220         int i;
00221         //fprintf(stderr, "stereo2mono: %d samples\n", nSamples);
00222         for ( i=0; i < nSamples; i++ )
00223         {
00224                 *(out) = *(in++);
00225                 out++; in++;
00226                 //*(out++) += *(in++);
00227         }
00228 }
00229 
00230 static void mix_slin(short *dst, short *src, int samples)
00231 {
00232         int i=0,val=0;
00233         for ( i=0; i < samples; i++ )
00234         {
00235                 if ( virtualMonoOut )
00236                         val = ((short *)dst)[2*i] + ((short *)src)[i];
00237                 else
00238                         val = ((short *)dst)[i] + ((short *)src)[i];
00239 
00240                 if ( val > 0x7fff )
00241                 {
00242                         val = 0x7fff-1;
00243                 } else if (val < -0x7fff)
00244                 {
00245                         val = -0x7fff+1;
00246                 }
00247 
00248                 if ( virtualMonoOut )
00249                 {
00250                         dst[2*i] = val;
00251                         dst[2*i+1] = val;
00252                 } else
00253                 {
00254                         dst[i] = val;
00255                 }
00256 
00257         }
00258 }
00259 
00260 static int pa_mix_sounds (void *outputBuffer, unsigned long frames, int channel)
00261 {
00262         struct iaxc_sound *s;
00263         struct iaxc_sound **sp;
00264         unsigned long outpos;
00265 
00266         MUTEXLOCK(&sound_lock);
00267         /* mix each sound into the outputBuffer */
00268         sp = &sounds;
00269         while ( sp && *sp )
00270         {
00271                 s = *sp;
00272                 outpos = 0;
00273 
00274                 if ( s->channel == channel )
00275                 {
00276                         /* loop over the sound until we've played it enough
00277                          * times, or we've filled the outputBuffer */
00278                         for(;;)
00279                         {
00280                                 int n;
00281 
00282                                 if ( outpos == frames )
00283                                         break;  /* we've filled the buffer */
00284                                 if ( s->pos == s->len )
00285                                 {
00286                                         if ( s->repeat == 0 )
00287                                         {
00288                                                 // XXX free the sound
00289                                                 // structure, and maybe the
00290                                                 // buffer!
00291                                                 (*sp) = s->next;
00292                                                 if(s->malloced)
00293                                                         free(s->data);
00294                                                 free(s);
00295                                                 break;
00296                                         }
00297                                         s->pos = 0;
00298                                         s->repeat--;
00299                                 }
00300 
00301                                 /* how many frames do we add in this loop? */
00302                                 n = (frames - outpos) < (unsigned long)(s->len - s->pos) ?
00303                                         (frames - outpos) :
00304                                         (unsigned long)(s->len - s->pos);
00305 
00306                                 /* mix in the frames */
00307                                 mix_slin((short *)outputBuffer + outpos,
00308                                                 s->data+s->pos, n);
00309 
00310                                 s->pos += n;
00311                                 outpos += n;
00312                         }
00313                 }
00314                 if ( *sp ) /* don't advance if we removed this member */
00315                         sp = &((*sp)->next);
00316         }
00317         MUTEXUNLOCK(&sound_lock);
00318         return 0;
00319 }
00320 
00321 static int pa_play_sound(struct iaxc_sound *inSound, int ring)
00322 {
00323         struct iaxc_sound *sound;
00324 
00325         sound = (struct iaxc_sound *)malloc(sizeof(struct iaxc_sound));
00326         if ( !sound )
00327                 return 1;
00328 
00329         *sound = *inSound;
00330 
00331         MUTEXLOCK(&sound_lock);
00332         sound->channel = ring;
00333         sound->id = nextSoundId++;
00334         sound->pos = 0;
00335 
00336         sound->next = sounds;
00337         sounds = sound;
00338         MUTEXUNLOCK(&sound_lock);
00339 
00340         if ( !running )
00341                 pa_start(NULL); /* XXX fixme: start/stop semantics */
00342 
00343         return sound->id;
00344 }
00345 
00346 static int pa_stop_sound(int soundID)
00347 {
00348         struct iaxc_sound **sp;
00349         int retval = 1; /* not found */
00350 
00351         MUTEXLOCK(&sound_lock);
00352         for ( sp = &sounds; *sp; (*sp) = (*sp)->next )
00353         {
00354                 struct iaxc_sound *s = *sp;
00355                 if ( s->id == soundID )
00356                 {
00357                         if ( s->malloced )
00358                                 free(s->data);
00359                         /* remove from list */
00360                         (*sp) = s->next;
00361                         free(s);
00362 
00363                         retval= 0; /* found */
00364                         break;
00365                 }
00366         }
00367         MUTEXUNLOCK(&sound_lock);
00368 
00369         return retval; /* found? */
00370 }
00371 
00372 static void iaxc_echo_can(short *inputBuffer, short *outputBuffer, int n)
00373 {
00374         static rb_RingBuffer ecOutRing;
00375         static char outRingBuf[EC_RING_SZ];
00376         static long bias = 0;
00377         short  delayedBuf[1024];
00378         int i;
00379 
00380         /* remove bias -- whether ec is on or not. */
00381         for ( i = 0; i < n; i++ )
00382         {
00383                 bias += ((((long int) inputBuffer[i]) << 15) - bias) >> 14;
00384                 inputBuffer[i] -= (short int) (bias >> 15);
00385         }
00386 
00387         /* if ec is off, clear ec state -- this way, we start fresh if/when
00388          * it's turned back on. */
00389         if ( !(iaxc_get_filters() & IAXC_FILTER_ECHO) )
00390         {
00391                 if ( ec )
00392                 {
00393 #if defined(USE_MEC2) || defined(SPAN_EC)
00394                         echo_can_free(ec);
00395                         ec = NULL;
00396 #endif
00397 #if defined(SPEEX_EC)
00398                         speex_echo_state_destroy(ec);
00399                         ec = NULL;
00400 #endif
00401                 }
00402 
00403                 return;
00404         }
00405 
00406         /* we want echo cancellation */
00407 
00408         if ( !ec )
00409         {
00410                 rb_InitializeRingBuffer(&ecOutRing, EC_RING_SZ, &outRingBuf);
00411 #if defined(USE_MEC2) || defined(SPAN_EC)
00412                 ec = echo_can_create(ECHO_TAIL, 0);
00413 #endif
00414 #if defined(SPEEX_EC)
00415                 ec = speex_echo_state_init(SAMPLES_PER_FRAME, ECHO_TAIL);
00416 #endif
00417         }
00418 
00419         /* fill ecOutRing */
00420         rb_WriteRingBuffer(&ecOutRing, outputBuffer, n * 2);
00421 
00422         // Make sure we have enough buffer.
00423         // Currently, just one SAMPLES_PER_FRAME's worth.
00424         if ( rb_GetRingBufferReadAvailable(&ecOutRing) < ((n + SAMPLES_PER_FRAME) * 2) )
00425                 return;
00426 
00427         rb_ReadRingBuffer(&ecOutRing, delayedBuf, n * 2);
00428 
00429 #if defined(SPEEX_EC)
00430         {
00431                 short cancelledBuffer[1024];
00432 
00433                 speex_echo_cancel(ec, inputBuffer, delayedBuf,
00434                                 cancelledBuffer, NULL);
00435 
00436                 for ( i = 0; i < n; i++ )
00437                         inputBuffer[i] = cancelledBuffer[i];
00438         }
00439 #endif
00440 
00441 #if defined(USE_MEC2) || defined(SPAN_EC)
00442         for ( i = 0; i < n; i++ )
00443                 inputBuffer[i] = echo_can_update(ec, delayedBuf[i],
00444                                 inputBuffer[i]);
00445 #endif
00446 }
00447 
00448 static int pa_callback(void *inputBuffer, void *outputBuffer,
00449             unsigned long samplesPerFrame,
00450             const PaStreamCallbackTimeInfo* outTime,
00451             PaStreamCallbackFlags statusFlags,
00452             void *userData)
00453 {
00454         int totBytes = samplesPerFrame * sizeof(SAMPLE);
00455 
00456         short virtualInBuffer[MAX_SAMPLES_PER_FRAME * 2];
00457         short virtualOutBuffer[MAX_SAMPLES_PER_FRAME * 2];
00458 
00459 #if 0
00460         /* I think this can't happen */
00461         if(virtualMono && samplesPerFrame > SAMPLES_PER_FRAME) {
00462                 fprintf(stderr, "ERROR: buffer in callback is too big!\n");
00463                 exit(1);
00464         }
00465 #endif
00466 
00467         if ( outputBuffer )
00468         {
00469                 int bWritten;
00470                 /* output underflow might happen here */
00471                 if (virtualMonoOut)
00472                 {
00473                         bWritten = rb_ReadRingBuffer(&outRing, virtualOutBuffer,
00474                                         totBytes);
00475                         /* we zero "virtualOutBuffer", then convert the whole thing,
00476                          * yes, because we use virtualOutBuffer for ec below */
00477                         if ( bWritten < totBytes )
00478                         {
00479                                 memset(((char *)virtualOutBuffer) + bWritten,
00480                                                 0, totBytes - bWritten);
00481                                 //fprintf(stderr, "*U*");
00482                         }
00483                         mono2stereo((SAMPLE *)outputBuffer, virtualOutBuffer,
00484                                         samplesPerFrame);
00485                 }
00486                 else
00487                 {
00488                         bWritten = rb_ReadRingBuffer(&outRing, outputBuffer, totBytes);
00489                         if ( bWritten < totBytes)
00490                         {
00491                                 memset((char *)outputBuffer + bWritten,
00492                                                 0, totBytes - bWritten);
00493                                 //fprintf(stderr, "*U*");
00494                         }
00495                 }
00496 
00497                 /* zero underflowed space [ silence might be more golden
00498                  * than garbage? ] */
00499 
00500                 pa_mix_sounds(outputBuffer, samplesPerFrame, 0);
00501 
00502                 if(!auxStream)
00503                         pa_mix_sounds(outputBuffer, samplesPerFrame, 1);
00504         }
00505 
00506 
00507         if ( inputBuffer )
00508         {
00509                 /* input overflow might happen here */
00510                 if ( virtualMonoIn )
00511                 {
00512                         stereo2mono(virtualInBuffer, (SAMPLE *)inputBuffer,
00513                                         samplesPerFrame);
00514                         iaxc_echo_can(virtualInBuffer, virtualOutBuffer,
00515                                         samplesPerFrame);
00516 
00517                         rb_WriteRingBuffer(&inRing, virtualInBuffer, totBytes);
00518                 }
00519                 else
00520                 {
00521                         iaxc_echo_can((short *)inputBuffer,
00522                                         (short *)outputBuffer,
00523                                         samplesPerFrame);
00524 
00525                         rb_WriteRingBuffer(&inRing, inputBuffer, totBytes);
00526                 }
00527         }
00528 
00529         return 0;
00530 }
00531 
00532 static int pa_aux_callback(void *inputBuffer, void *outputBuffer,
00533             unsigned long samplesPerFrame,
00534             const PaStreamCallbackTimeInfo* outTime,
00535             PaStreamCallbackFlags statusFlags,
00536             void *userData)
00537 {
00538         int totBytes = samplesPerFrame * sizeof(SAMPLE);
00539 
00540         /* XXX: need to handle virtualMonoOut case!!! */
00541         if ( outputBuffer )
00542         {
00543                 memset((char *)outputBuffer, 0, totBytes);
00544                 pa_mix_sounds(outputBuffer, samplesPerFrame, 1);
00545         }
00546         return 0;
00547 }
00548 
00549 static int pa_open(int single, int inMono, int outMono)
00550 {
00551         PaError err;
00552         PaDeviceInfo *result;
00553 
00554         struct PaStreamParameters in_stream_params, out_stream_params, no_device;
00555         in_stream_params.device = selectedInput;
00556         in_stream_params.channelCount = (inMono ? 1 : 2);
00557         in_stream_params.sampleFormat = paInt16;
00558         result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedInput);
00559         if ( result == NULL ) return -1;
00560         in_stream_params.suggestedLatency = result->defaultLowInputLatency;
00561         in_stream_params.hostApiSpecificStreamInfo = NULL;
00562 
00563         out_stream_params.device = selectedOutput;
00564         out_stream_params.channelCount = (outMono ? 1 : 2);
00565         out_stream_params.sampleFormat = paInt16;
00566         result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedOutput);
00567         if ( result == NULL ) return -1;
00568         out_stream_params.suggestedLatency = result->defaultLowOutputLatency;
00569         out_stream_params.hostApiSpecificStreamInfo = NULL;
00570 
00571         no_device.device = paNoDevice;
00572         no_device.channelCount = 0;
00573         no_device.sampleFormat = paInt16;
00574         result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedInput);
00575         if ( result == NULL ) return -1;
00576         no_device.suggestedLatency = result->defaultLowInputLatency; // FEEDBACK - unsure if appropriate
00577         no_device.hostApiSpecificStreamInfo = NULL;
00578 
00579         if ( single )
00580         {
00581                 err = Pa_OpenStream(&iStream,
00582                         &in_stream_params,
00583                         &out_stream_params,
00584                         sample_rate,
00585                         paFramesPerBufferUnspecified, //FEEBACK - unsure if appropriate
00586                         paNoFlag,
00587                         (PaStreamCallback *)pa_callback,
00588                         NULL);
00589                 if (err != paNoError) return -1;
00590                 oStream = iStream;
00591                 oneStream = 1;
00592         } else
00593         {
00594                 err = Pa_OpenStream(&iStream,
00595                         &in_stream_params,
00596                         &no_device,
00597                         sample_rate,
00598                         paFramesPerBufferUnspecified, //FEEBACK - unsure if appropriate
00599                         paNoFlag,
00600                         (PaStreamCallback *)pa_callback,
00601                         NULL);
00602                 if ( err != paNoError ) return -1;
00603 
00604                 err = Pa_OpenStream(&oStream,
00605                         &no_device,
00606                         &out_stream_params,
00607                         sample_rate,
00608                         paFramesPerBufferUnspecified, //FEEBACK - unsure if appropriate
00609                         paNoFlag,
00610                         (PaStreamCallback *)pa_callback,
00611                         NULL);
00612 
00613                 if ( err != paNoError )
00614                 {
00615                         Pa_CloseStream(iStream);
00616                         iStream = NULL;
00617                         return -1;
00618                 }
00619                 oneStream = 0;
00620         }
00621 
00622         virtualMonoIn = (inMono ? 0 : 1);
00623         virtualMonoOut = (outMono ? 0 : 1);
00624         return 0;
00625 }
00626 
00627 /* some commentary here:
00628  * 1: MacOSX: MacOSX often needs "virtual mono" and a single stream.
00629  * That doesn't work for some USB devices (a Platronics headset), so
00630  * mono in, virtual mono out, and mono in/out are also tried.
00631  *
00632  * 2: Unix/OSS: most cards are OK with real mono, and a single stream.
00633  * Except some.  For those, a single open with real mono will succeed,
00634  * but execution will fail.  Maybe others will open OK with a single
00635  * stream, and real mono, but fail later? Two stream mono is tried first,
00636  * since it reportedly provides better sound quality with ALSA
00637  * and Sound Blaster Live.
00638  *
00639  * The failure mode I saw with a volunteer was that reads/writes would
00640  * return -enodev (down in the portaudio code).  Bummer.
00641  *
00642  * Win32 works fine, in all cases, with a single stream and real mono,
00643  * so far.
00644  *
00645  * We could probably do this more cleanly, because there are still cases
00646  * where we will fail (i.e. if the user has only mono in and out on a Mac).
00647  *
00648  * */
00649 static int pa_openstreams (struct iaxc_audio_driver *d )
00650 {
00651         int err;
00652 
00653 #ifdef LINUX
00654         err = pa_open(0, 1, 1) && /* two stream mono */
00655                 pa_open(1, 1, 1) &&   /* one stream mono */
00656                 pa_open(0, 0, 0);     /* two stream stereo */
00657 #else
00658 #ifdef MACOSX
00659         err = pa_open(1, 0, 0) &&  /* one stream stereo */
00660                 pa_open(1, 1, 0) &&    /* one stream mono in stereo out */
00661                 pa_open(1, 1, 1) &&    /* one stream mono */
00662                 pa_open(0, 0, 0);      /* two stream stereo */
00663 #else
00664         err = pa_open(1, 1, 1) &&  /* one stream mono */
00665                 pa_open(1, 0, 0) &&    /* one stream stereo */
00666                 pa_open(1, 1, 0) &&    /* one stream mono in stereo out */
00667                 pa_open(0, 0, 0);      /* two stream stereo */
00668 #endif /*MACOSX */
00669 #endif /* LINUX */
00670 
00671         if (err)
00672         {
00673                 handle_paerror(err, "Unable to open streams");
00674                 return -1;
00675         }
00676         return 0;
00677 }
00678 
00679 static int pa_openauxstream (struct iaxc_audio_driver *d )
00680 {
00681         PaError err;
00682 
00683         /* FEEDBACK - iaxclient seems to assume that the ring device is a
00684          * mono device. I can't find any mono devices on the Mac and so
00685          * ring device opening will fail. My code assumes the ring device
00686          * is a stereo device - this might break stuff */
00687         struct PaStreamParameters ring_stream_params, no_device;
00688 
00689         struct PaStreamParameters in_stream_params;
00690         in_stream_params.device = selectedInput;
00691         in_stream_params.channelCount = virtualMonoOut + 1;
00692         in_stream_params.sampleFormat = paInt16;
00693         in_stream_params.suggestedLatency =
00694                 Pa_GetDeviceInfo(selectedInput)->defaultLowInputLatency;
00695         in_stream_params.hostApiSpecificStreamInfo = NULL;
00696 
00697         ring_stream_params.device = selectedRing;
00698         ring_stream_params.channelCount = virtualMonoOut+1;
00699         ring_stream_params.sampleFormat = paInt16;
00700         ring_stream_params.suggestedLatency =
00701                 Pa_GetDeviceInfo(selectedRing)->defaultLowOutputLatency;
00702         ring_stream_params.hostApiSpecificStreamInfo = NULL;
00703 
00704         no_device.device = paNoDevice;
00705         no_device.channelCount = 0;
00706         no_device.sampleFormat = paInt16;
00707         no_device.suggestedLatency =
00708                 Pa_GetDeviceInfo(selectedInput)->defaultLowInputLatency; //TODOC
00709         no_device.hostApiSpecificStreamInfo = NULL;
00710 
00711         err = Pa_OpenStream ( &aStream,
00712                         &in_stream_params,
00713                         &ring_stream_params,
00714                         sample_rate,
00715                         paFramesPerBufferUnspecified, //FEEBACK - unsure if appropriate
00716                         paNoFlag,
00717                         (PaStreamCallback *)pa_aux_callback,
00718                         NULL);
00719 
00720         if ( err != paNoError )
00721         {
00722                 /* FEEDBACK, we try one more time, maybe ring device is a mono
00723                  * output device */
00724                 err = Pa_OpenStream ( &aStream,
00725                                 &no_device,
00726                                 &ring_stream_params,
00727                                 sample_rate,
00728                                 paFramesPerBufferUnspecified, //FEEBACK - unsure if appropriate
00729                                 paNoFlag,   /* flags */
00730                                 (PaStreamCallback *)pa_aux_callback,
00731                                 NULL);
00732         }
00733 
00734         // mmok, failure...
00735         if ( err != paNoError )
00736         {
00737                 //fprintf(stderr, "Failure opening ring device with params: id: %d, output %d, default output %d\n",
00738                 //selectedRing, selectedOutput, Pa_GetDefaultOutputDevice());
00739 
00740                 handle_paerror(err, "opening separate ring stream");
00741                 return -1;
00742         }
00743 
00744         return 0;
00745 }
00746 
00747 static int pa_start(struct iaxc_audio_driver *d)
00748 {
00749         static int errcnt = 0;
00750 
00751         if ( running )
00752                 return 0;
00753 
00754         /* re-open mixers if necessary */
00755         if ( iMixer )
00756         {
00757                 Px_CloseMixer(iMixer);
00758                 iMixer = NULL;
00759         }
00760 
00761         if ( oMixer )
00762         {
00763                 Px_CloseMixer(oMixer);
00764                 oMixer = NULL;
00765         }
00766 
00767         if ( errcnt > 5 )
00768         {
00769                 iaxci_usermsg(IAXC_TEXT_TYPE_FATALERROR,
00770                                 "iaxclient audio: Can't open Audio Device. Perhaps you do not have an input or output device?");
00771                 /* OK, we'll give the application the option to abort or
00772                  * not here, but we will throw a fatal error anyway */
00773                 iaxc_millisleep(1000);
00774                 //return -1; // Give Up.  Too many errors.
00775         }
00776 
00777         /* flush the ringbuffers */
00778         rb_InitializeRingBuffer(&inRing, INRBSZ, inRingBuf);
00779         rb_InitializeRingBuffer(&outRing, OUTRBSZ, outRingBuf);
00780 
00781         if ( pa_openstreams(d) )
00782         {
00783                 errcnt++;
00784                 return -1;
00785         }
00786 
00787         errcnt = 0; // only count consecutive errors.
00788 
00789         if ( Pa_StartStream(iStream) != paNoError )
00790                 return -1;
00791 
00792         iMixer = Px_OpenMixer(iStream, 0);
00793 
00794         if ( !oneStream )
00795         {
00796                 PaError err = Pa_StartStream(oStream);
00797                 oMixer = Px_OpenMixer(oStream, 0);
00798                 if ( err != paNoError )
00799                 {
00800                         Pa_StopStream(iStream);
00801                         return -1;
00802                 }
00803         }
00804 
00805         if ( selectedRing != selectedOutput )
00806         {
00807                 auxStream = 1;
00808         }
00809         else
00810         {
00811                 auxStream = 0;
00812         }
00813 
00814         if ( auxStream )
00815         {
00816                 pa_openauxstream(d);
00817                 if ( Pa_StartStream(aStream) != paNoError )
00818                 {
00819                         auxStream = 0;
00820                 }
00821         }
00822 
00823         /* select the microphone as the input source */
00824         if ( iMixer != NULL && !mixers_initialized )
00825         {
00826                 /* First, select the "microphone" device, if it's available */
00827                 /* try the new method, reverting to the old if it fails */
00828                 if ( Px_SetCurrentInputSourceByName( iMixer, "microphone" ) != 0 )
00829                 {
00830                         int n = Px_GetNumInputSources( iMixer ) - 1;
00831                         for ( ; n > 0; --n )
00832                         {
00833                                 if ( !strcasecmp("microphone",
00834                                                 Px_GetInputSourceName(iMixer, n)) )
00835                                 {
00836                                         Px_SetCurrentInputSource( iMixer, n );
00837                                 }
00838                         }
00839                 }
00840 
00841                 /* try to set the microphone boost -- we just turn off this
00842                  * "boost" feature, because it often leads to clipping, which
00843                  * we can't fix later -- but we can deal with low input levels
00844                  * much more gracefully */
00845                 Px_SetMicrophoneBoost( iMixer, 0 );
00846 
00847                 /* If the input level is very low, raise it up a bit.
00848                  * Otherwise, AGC cannot detect speech, and cannot adjust
00849                  * levels */
00850                 if ( pa_input_level_get(d) < 0.5f )
00851                         pa_input_level_set(d, 0.6f);
00852                 mixers_initialized = 1;
00853         }
00854 
00855         running = 1;
00856         return 0;
00857 }
00858 
00859 static int pa_stop (struct iaxc_audio_driver *d )
00860 {
00861         PaError err;
00862 
00863         if ( !running )
00864                 return 0;
00865 
00866         if ( sounds )
00867                 return 0;
00868 
00869         err = Pa_AbortStream(iStream);
00870         err = Pa_CloseStream(iStream);
00871 
00872         if ( !oneStream )
00873         {
00874                 err = Pa_AbortStream(oStream);
00875                 err = Pa_CloseStream(oStream);
00876         }
00877 
00878         if ( auxStream )
00879         {
00880                 err = Pa_AbortStream(aStream);
00881                 err = Pa_CloseStream(aStream);
00882         }
00883 
00884         running = 0;
00885         return 0;
00886 }
00887 
00888 /* Mihai: apparently nobody loves this function. Some actually hate it.
00889  * I bet if it's gone, no one will miss it.  Such a cold, cold world!
00890 static void pa_shutdown()
00891 {
00892         CloseAudioStream( iStream );
00893         if(!oneStream) CloseAudioStream( oStream );
00894         if(auxStream) CloseAudioStream( aStream );
00895 }
00896 */
00897 
00898 static void handle_paerror(PaError err, char * where)
00899 {
00900         fprintf(stderr, "PortAudio error at %s: %s\n", where,
00901                         Pa_GetErrorText(err));
00902 }
00903 
00904 static int pa_input(struct iaxc_audio_driver *d, void *samples, int *nSamples)
00905 {
00906         int bytestoread;
00907 
00908         bytestoread = *nSamples * sizeof(SAMPLE);
00909 
00910         /* we don't return partial buffers */
00911         if ( rb_GetRingBufferReadAvailable(&inRing) < bytestoread )
00912         {
00913                 *nSamples = 0;
00914                 return 0;
00915         }
00916 
00917         rb_ReadRingBuffer(&inRing, samples, bytestoread);
00918 
00919         return 0;
00920 }
00921 
00922 static int pa_output(struct iaxc_audio_driver *d, void *samples, int nSamples)
00923 {
00924         int bytestowrite = nSamples * sizeof(SAMPLE);
00925         int outRingLen;
00926 
00927         outRingLen = rb_GetRingBufferReadAvailable(&outRing);
00928         outRingLenAvg = (outRingLenAvg * 9 + outRingLen ) / 10;
00929 
00930         /* if we've got a big output buffer, drop this */
00931         if (outRingLen > (int)RBOUTTARGET_BYTES &&
00932                         outRingLenAvg > (int)RBOUTTARGET_BYTES)
00933         {
00934           //fprintf(stderr, "*O*");
00935           return outRingLen/2;
00936         }
00937 
00938         //if(rb_GetRingBufferWriteAvailable(&outRing) < bytestowrite)
00939         //      fprintf(stderr, "O");
00940 
00941         rb_WriteRingBuffer(&outRing, samples, bytestowrite);
00942 
00943         return (outRingLen + bytestowrite)/2;
00944 
00945 }
00946 
00947 static int pa_select_devices(struct iaxc_audio_driver *d, int input,
00948                 int output, int ring)
00949 {
00950         selectedInput = input;
00951         selectedOutput = output;
00952         selectedRing = ring;
00953         if ( running )
00954         {
00955                 pa_stop(d);
00956                 pa_start(d);
00957         }
00958         return 0;
00959 }
00960 
00961 static int pa_selected_devices(struct iaxc_audio_driver *d, int *input,
00962                 int *output, int *ring)
00963 {
00964         *input = selectedInput;
00965         *output = selectedOutput;
00966         *ring = selectedRing;
00967         return 0;
00968 }
00969 
00970 static int pa_destroy(struct iaxc_audio_driver *d)
00971 {
00972         return Pa_Terminate();
00973 }
00974 
00975 static float pa_input_level_get(struct iaxc_audio_driver *d)
00976 {
00977         /* iMixer should be non-null if we using either one or two streams */
00978         if ( !iMixer )
00979                 return -1;
00980 
00981         /* make sure this device supports input volume controls */
00982         if ( Px_GetNumInputSources( iMixer ) == 0 )
00983                 return -1;
00984 
00985         return Px_GetInputVolume(iMixer);
00986 }
00987 
00988 static float pa_output_level_get(struct iaxc_audio_driver *d)
00989 {
00990         PxMixer *mix;
00991 
00992         /* oMixer may be null if we're using one stream,
00993            in which case, iMixer should not be null,
00994            if it is, return an error */
00995 
00996         if ( oMixer )
00997                 mix = oMixer;
00998         else if ( iMixer )
00999                 mix = iMixer;
01000         else
01001                 return -1;
01002 
01003         /* prefer the pcm output, but default to the master output */
01004         if ( Px_SupportsPCMOutputVolume(mix) )
01005                 return Px_GetPCMOutputVolume(mix);
01006         else
01007                 return Px_GetMasterVolume(mix);
01008 }
01009 
01010 static int pa_input_level_set(struct iaxc_audio_driver *d, float level)
01011 {
01012         /* make sure this device supports input volume controls */
01013         if ( !iMixer || Px_GetNumInputSources(iMixer) == 0 )
01014                 return -1;
01015 
01016         Px_SetInputVolume(iMixer, level);
01017 
01018         return 0;
01019 }
01020 
01021 static int pa_output_level_set(struct iaxc_audio_driver *d, float level)
01022 {
01023         PxMixer *mix;
01024 
01025         if ( oMixer )
01026                 mix = oMixer;
01027         else if ( iMixer )
01028                 mix = iMixer;
01029         else
01030                 return -1;
01031 
01032         /* prefer the pcm output, but default to the master output */
01033         if ( Px_SupportsPCMOutputVolume(mix) )
01034                 Px_SetPCMOutputVolume(mix, level);
01035         else
01036                 Px_SetMasterVolume(mix, level);
01037 
01038         return 0;
01039 }
01040 
01041 static int pa_mic_boost_get(struct iaxc_audio_driver* d)
01042 {
01043         if ( !iMixer )
01044                 return -1;
01045 
01046         return Px_GetMicrophoneBoost(iMixer);
01047 }
01048 
01049 int pa_mic_boost_set(struct iaxc_audio_driver* d, int enable)
01050 {
01051         if ( !iMixer )
01052                 return -1;
01053 
01054         return Px_SetMicrophoneBoost(iMixer, enable);
01055 }
01056 
01057 /* initialize audio driver */
01058 static int _pa_initialize (struct iaxc_audio_driver *d, int sr)
01059 {
01060         PaError  err;
01061 
01062         sample_rate = sr;
01063 
01064         /* initialize portaudio */
01065         if ( paNoError != (err = Pa_Initialize()) )
01066         {
01067                 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR, "Failed Pa_Initialize");
01068                 return err;
01069         }
01070 
01071         /* scan devices */
01072         scan_devices(d);
01073 
01074         /* setup methods */
01075         d->initialize = pa_initialize;
01076         d->destroy = pa_destroy;
01077         d->select_devices = pa_select_devices;
01078         d->selected_devices = pa_selected_devices;
01079         d->start = pa_start;
01080         d->stop = pa_stop;
01081         d->output = pa_output;
01082         d->input = pa_input;
01083         d->input_level_get = pa_input_level_get;
01084         d->input_level_set = pa_input_level_set;
01085         d->output_level_get = pa_output_level_get;
01086         d->output_level_set = pa_output_level_set;
01087         d->play_sound = pa_play_sound;
01088         d->stop_sound = pa_stop_sound;
01089         d->mic_boost_get = pa_mic_boost_get;
01090         d->mic_boost_set = pa_mic_boost_set;
01091 
01092         /* setup private data stuff */
01093         selectedInput  = Pa_GetDefaultInputDevice();
01094         selectedOutput = Pa_GetDefaultOutputDevice();
01095         selectedRing   = Pa_GetDefaultOutputDevice();
01096         sounds = NULL;
01097         MUTEXINIT(&sound_lock);
01098 
01099         rb_InitializeRingBuffer(&inRing, INRBSZ, inRingBuf);
01100         rb_InitializeRingBuffer(&outRing, OUTRBSZ, outRingBuf);
01101 
01102         running = 0;
01103 
01104         return 0;
01105 }
01106 
01107 /* standard initialization:  Do the normal initialization, and then
01108    also initialize mixers and levels */
01109 int pa_initialize(struct iaxc_audio_driver *d, int sr)
01110 {
01111         _pa_initialize(d, sr);
01112 
01113         /* TODO: Kludge alert. We only do the funny audio start-stop
01114          * business if iaxci_audio_output_mode is not set. This is a
01115          * hack to allow certain specific users of iaxclient to avoid
01116          * certain problems associated with portaudio initialization
01117          * hitting a deadlock condition.
01118          */
01119         if ( iaxci_audio_output_mode )
01120                 return 0;
01121 
01122         /* start/stop audio, in order to initialize mixers and levels */
01123         pa_start(d);
01124         pa_stop(d);
01125 
01126         return 0;
01127 }
01128 
01129 /* alternate initialization:  delay mixer/level initialization until
01130    we actually start the device.  This is somewhat useful when you're about to start
01131    the device as soon as you've initialized it, and want to avoid the time it
01132    takes to start/stop the device before starting it again */
01133 int pa_initialize_deferred(struct iaxc_audio_driver *d, int sr)
01134 {
01135         _pa_initialize(d, sr);
01136         return 0;
01137 }
01138 

Generated on Mon Sep 24 15:43:29 2007 for IAXClient by  doxygen 1.5.3