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 #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
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
00076 #define MAX_SAMPLES_PER_FRAME (MS_PER_FRAME * MAX_SAMPLE_RATE / 1000)
00077
00078
00079 #define ECHO_TAIL 4096
00080
00081
00082 #ifndef OUTRBSZ
00083 # define OUTRBSZ 32768
00084 #endif
00085
00086
00087
00088
00089 #ifndef INRBSZ
00090 # define INRBSZ 2048
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 #ifndef RBOUTTARGET
00119 # define RBOUTTARGET (80)
00120 #endif
00121
00122
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
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
00149
00150
00151
00152
00153
00154
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 )
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
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
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
00222 for ( i=0; i < nSamples; i++ )
00223 {
00224 *(out) = *(in++);
00225 out++; in++;
00226
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
00268 sp = &sounds;
00269 while ( sp && *sp )
00270 {
00271 s = *sp;
00272 outpos = 0;
00273
00274 if ( s->channel == channel )
00275 {
00276
00277
00278 for(;;)
00279 {
00280 int n;
00281
00282 if ( outpos == frames )
00283 break;
00284 if ( s->pos == s->len )
00285 {
00286 if ( s->repeat == 0 )
00287 {
00288
00289
00290
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
00302 n = (frames - outpos) < (unsigned long)(s->len - s->pos) ?
00303 (frames - outpos) :
00304 (unsigned long)(s->len - s->pos);
00305
00306
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 )
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);
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;
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
00360 (*sp) = s->next;
00361 free(s);
00362
00363 retval= 0;
00364 break;
00365 }
00366 }
00367 MUTEXUNLOCK(&sound_lock);
00368
00369 return retval;
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
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
00388
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
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
00420 rb_WriteRingBuffer(&ecOutRing, outputBuffer, n * 2);
00421
00422
00423
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
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
00471 if (virtualMonoOut)
00472 {
00473 bWritten = rb_ReadRingBuffer(&outRing, virtualOutBuffer,
00474 totBytes);
00475
00476
00477 if ( bWritten < totBytes )
00478 {
00479 memset(((char *)virtualOutBuffer) + bWritten,
00480 0, totBytes - bWritten);
00481
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
00494 }
00495 }
00496
00497
00498
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
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
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;
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,
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,
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,
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
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
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) &&
00655 pa_open(1, 1, 1) &&
00656 pa_open(0, 0, 0);
00657 #else
00658 #ifdef MACOSX
00659 err = pa_open(1, 0, 0) &&
00660 pa_open(1, 1, 0) &&
00661 pa_open(1, 1, 1) &&
00662 pa_open(0, 0, 0);
00663 #else
00664 err = pa_open(1, 1, 1) &&
00665 pa_open(1, 0, 0) &&
00666 pa_open(1, 1, 0) &&
00667 pa_open(0, 0, 0);
00668 #endif
00669 #endif
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
00684
00685
00686
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;
00709 no_device.hostApiSpecificStreamInfo = NULL;
00710
00711 err = Pa_OpenStream ( &aStream,
00712 &in_stream_params,
00713 &ring_stream_params,
00714 sample_rate,
00715 paFramesPerBufferUnspecified,
00716 paNoFlag,
00717 (PaStreamCallback *)pa_aux_callback,
00718 NULL);
00719
00720 if ( err != paNoError )
00721 {
00722
00723
00724 err = Pa_OpenStream ( &aStream,
00725 &no_device,
00726 &ring_stream_params,
00727 sample_rate,
00728 paFramesPerBufferUnspecified,
00729 paNoFlag,
00730 (PaStreamCallback *)pa_aux_callback,
00731 NULL);
00732 }
00733
00734
00735 if ( err != paNoError )
00736 {
00737
00738
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
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
00772
00773 iaxc_millisleep(1000);
00774
00775 }
00776
00777
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;
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
00824 if ( iMixer != NULL && !mixers_initialized )
00825 {
00826
00827
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
00842
00843
00844
00845 Px_SetMicrophoneBoost( iMixer, 0 );
00846
00847
00848
00849
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
00889
00890
00891
00892
00893
00894
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
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
00931 if (outRingLen > (int)RBOUTTARGET_BYTES &&
00932 outRingLenAvg > (int)RBOUTTARGET_BYTES)
00933 {
00934
00935 return outRingLen/2;
00936 }
00937
00938
00939
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
00978 if ( !iMixer )
00979 return -1;
00980
00981
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
00993
00994
00995
00996 if ( oMixer )
00997 mix = oMixer;
00998 else if ( iMixer )
00999 mix = iMixer;
01000 else
01001 return -1;
01002
01003
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
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
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
01058 static int _pa_initialize (struct iaxc_audio_driver *d, int sr)
01059 {
01060 PaError err;
01061
01062 sample_rate = sr;
01063
01064
01065 if ( paNoError != (err = Pa_Initialize()) )
01066 {
01067 iaxci_usermsg(IAXC_TEXT_TYPE_ERROR, "Failed Pa_Initialize");
01068 return err;
01069 }
01070
01071
01072 scan_devices(d);
01073
01074
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
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
01108
01109 int pa_initialize(struct iaxc_audio_driver *d, int sr)
01110 {
01111 _pa_initialize(d, sr);
01112
01113
01114
01115
01116
01117
01118
01119 if ( iaxci_audio_output_mode )
01120 return 0;
01121
01122
01123 pa_start(d);
01124 pa_stop(d);
01125
01126 return 0;
01127 }
01128
01129
01130
01131
01132
01133 int pa_initialize_deferred(struct iaxc_audio_driver *d, int sr)
01134 {
01135 _pa_initialize(d, sr);
01136 return 0;
01137 }
01138