diff --git a/lib/native/linux-64/libjportaudio.so b/lib/native/linux-64/libjportaudio.so index 6479f83c3..fd2e408a7 100755 Binary files a/lib/native/linux-64/libjportaudio.so and b/lib/native/linux-64/libjportaudio.so differ diff --git a/lib/native/linux/libjportaudio.so b/lib/native/linux/libjportaudio.so index 30ec4cb3e..f9cdaa54b 100755 Binary files a/lib/native/linux/libjportaudio.so and b/lib/native/linux/libjportaudio.so differ diff --git a/lib/native/mac/libjportaudio.jnilib b/lib/native/mac/libjportaudio.jnilib index 684da1bfa..cc2f5ce8e 100755 Binary files a/lib/native/mac/libjportaudio.jnilib and b/lib/native/mac/libjportaudio.jnilib differ diff --git a/lib/native/windows-64/jportaudio.dll b/lib/native/windows-64/jportaudio.dll index cab3f2db4..dc6d3281e 100644 Binary files a/lib/native/windows-64/jportaudio.dll and b/lib/native/windows-64/jportaudio.dll differ diff --git a/lib/native/windows/jportaudio.dll b/lib/native/windows/jportaudio.dll index 6b32241b0..55761a00a 100644 Binary files a/lib/native/windows/jportaudio.dll and b/lib/native/windows/jportaudio.dll differ diff --git a/src/native/portaudio/AudioQualityImprovement.c b/src/native/portaudio/AudioQualityImprovement.c index 3fe58f5ef..dfaf55057 100644 --- a/src/native/portaudio/AudioQualityImprovement.c +++ b/src/native/portaudio/AudioQualityImprovement.c @@ -12,118 +12,90 @@ #include #include -/** - * The minimum number of frames by which the playback is to be delayed before it - * is accessible to the echo cancellation/capture. - */ -#define MIN_PLAY_DELAY_IN_FRAMES 2 - static void AudioQualityImprovement_cancelEchoFromPlay - (AudioQualityImprovement *aqi, - void *buffer, unsigned long length); -static void AudioQualityImprovement_free(AudioQualityImprovement *aqi); + (AudioQualityImprovement *audioQualityImprovement, + void *buffer, + unsigned long length); +static void AudioQualityImprovement_free + (AudioQualityImprovement *audioQualityImprovement); static AudioQualityImprovement *AudioQualityImprovement_new (const char *stringID, jlong longID, AudioQualityImprovement *next); -static void AudioQualityImprovement_popFromPlay - (AudioQualityImprovement *aqi, spx_uint32_t sampleCount); static void AudioQualityImprovement_resampleInPlay - (AudioQualityImprovement *aqi, - double sampleRate, unsigned long sampleSizeInBits, int channels, - void *buffer, unsigned long length); -static void AudioQualityImprovement_retain(AudioQualityImprovement *aqi); + (AudioQualityImprovement *audioQualityImprovement, + double sampleRate, + unsigned long sampleSizeInBits, + int channels, + void *buffer, + unsigned long length); +static void AudioQualityImprovement_retain + (AudioQualityImprovement *audioQualityImprovement); static void AudioQualityImprovement_setFrameSize - (AudioQualityImprovement *aqi, jint frameSize); -static void AudioQualityImprovement_setInputLatency - (AudioQualityImprovement *aqi, jlong inputLatency); -static void AudioQualityImprovement_setOutputLatency - (AudioQualityImprovement *aqi, jlong outputLatency); - -/** - * Updates the indicator of the specified AudioQualityImprovement which - * determines whether AudioQualityImprovement#play delays the access to - * it from AudioQualityImprovement#echo. - * - * @param aqi the AudioQualityImprovement of which to update the - * indicator which determines whether AudioQualityImprovement#play - * delays the access to it from AudioQualityImprovement#echo - */ -static void AudioQualityImprovement_updatePlayDelay - (AudioQualityImprovement *aqi); -static void AudioQualityImprovement_updatePlayIsDelaying - (AudioQualityImprovement *aqi); + (AudioQualityImprovement *audioQualityImprovement, jint frameSize); static void AudioQualityImprovement_updatePreprocess - (AudioQualityImprovement *aqi); + (AudioQualityImprovement *audioQualityImprovement); -static Mutex *AudioQualityImprovement_sharedInstancesMutex = NULL; -static AudioQualityImprovement *AudioQualityImprovement_sharedInstances = NULL; +#ifndef _WIN32 +static pthread_mutex_t AudioQualityImprovement_sharedInstancesMutex + = PTHREAD_MUTEX_INITIALIZER; +#else /* Windows */ +static CRITICAL_SECTION AudioQualityImprovement_sharedInstancesMutex = {(void*)-1, -1, 0, 0, 0, 0}; +#endif + +static AudioQualityImprovement *AudioQualityImprovement_sharedInstances + = NULL; -/** - * - * @param aqi - * @param buffer - * @param length the length of buffer in bytes - */ static void AudioQualityImprovement_cancelEchoFromPlay - (AudioQualityImprovement *aqi, + (AudioQualityImprovement *audioQualityImprovement, void *buffer, unsigned long length) { - spx_uint32_t sampleCount; - - if (aqi->playIsDelaying == JNI_TRUE) - return; - - sampleCount = length / sizeof(spx_int16_t); - if (aqi->playLength < sampleCount) - return; - - /* - * Ensure that out exists and is large enough to receive the result of the - * echo cancellation. - */ - if (!(aqi->out) || (aqi->outCapacity < length)) + if (!(audioQualityImprovement->out) + || (audioQualityImprovement->outCapacity < length)) { - spx_int16_t *newOut = realloc(aqi->out, length); + spx_int16_t *newOut = realloc(audioQualityImprovement->out, length); if (newOut) { - aqi->out = newOut; - aqi->outCapacity = length; + audioQualityImprovement->out = newOut; + audioQualityImprovement->outCapacity = length; } else return; } - - /* Perform the echo cancellation and return the result in buffer. */ - speex_echo_cancellation(aqi->echo, buffer, aqi->play, aqi->out); - AudioQualityImprovement_popFromPlay(aqi, sampleCount); - memcpy(buffer, aqi->out, length); + speex_echo_cancellation( + audioQualityImprovement->echo, + buffer, + audioQualityImprovement->play, + audioQualityImprovement->out); + audioQualityImprovement->playSize = 0; + memcpy(buffer, audioQualityImprovement->out, length); } static void -AudioQualityImprovement_free(AudioQualityImprovement *aqi) +AudioQualityImprovement_free(AudioQualityImprovement *audioQualityImprovement) { /* mutex */ - Mutex_free(aqi->mutex); + mutex_destroy(audioQualityImprovement->mutex); + free(audioQualityImprovement->mutex); /* preprocess */ - if (aqi->preprocess) - speex_preprocess_state_destroy(aqi->preprocess); + if (audioQualityImprovement->preprocess) + speex_preprocess_state_destroy(audioQualityImprovement->preprocess); /* echo */ - if (aqi->echo) - speex_echo_state_destroy(aqi->echo); + if (audioQualityImprovement->echo) + speex_echo_state_destroy(audioQualityImprovement->echo); /* out */ - if (aqi->out) - free(aqi->out); + if (audioQualityImprovement->out) + free(audioQualityImprovement->out); /* play */ - if (aqi->play) - free(aqi->play); + if (audioQualityImprovement->play) + free(audioQualityImprovement->play); /* resampler */ - if (aqi->resampler) - speex_resampler_destroy(aqi->resampler); + if (audioQualityImprovement->resampler) + speex_resampler_destroy(audioQualityImprovement->resampler); /* stringID */ - free(aqi->stringID); + free(audioQualityImprovement->stringID); - free(aqi); + free(audioQualityImprovement); } AudioQualityImprovement * @@ -131,7 +103,7 @@ AudioQualityImprovement_getSharedInstance(const char *stringID, jlong longID) { AudioQualityImprovement *theSharedInstance = NULL; - if (!Mutex_lock(AudioQualityImprovement_sharedInstancesMutex)) + if (!mutex_lock(&AudioQualityImprovement_sharedInstancesMutex)) { AudioQualityImprovement *aSharedInstance = AudioQualityImprovement_sharedInstances; @@ -159,131 +131,125 @@ AudioQualityImprovement_getSharedInstance(const char *stringID, jlong longID) if (theSharedInstance) AudioQualityImprovement_sharedInstances = theSharedInstance; } - Mutex_unlock(AudioQualityImprovement_sharedInstancesMutex); + mutex_unlock(&AudioQualityImprovement_sharedInstancesMutex); } return theSharedInstance; } -/** Loads the AudioQualityImprovement class. */ -void -AudioQualityImprovement_load() -{ - AudioQualityImprovement_sharedInstancesMutex = Mutex_new(NULL); -} - static AudioQualityImprovement * AudioQualityImprovement_new (const char *stringID, jlong longID, AudioQualityImprovement *next) { - AudioQualityImprovement *aqi = calloc(1, sizeof(AudioQualityImprovement)); + AudioQualityImprovement *audioQualityImprovement + = malloc(sizeof(AudioQualityImprovement)); - if (aqi) + if (audioQualityImprovement) { + audioQualityImprovement->echo = NULL; + audioQualityImprovement->mutex = NULL; + audioQualityImprovement->out = NULL; + audioQualityImprovement->play = NULL; + audioQualityImprovement->preprocess = NULL; + audioQualityImprovement->resampler = NULL; + /* audioQualityImprovement->stringID = NULL; */ + /* stringID */ - aqi->stringID = strdup(stringID); - if (!(aqi->stringID)) + audioQualityImprovement->stringID = strdup(stringID); + if (!(audioQualityImprovement->stringID)) { - AudioQualityImprovement_free(aqi); + AudioQualityImprovement_free(audioQualityImprovement); return NULL; } /* mutex */ - aqi->mutex = Mutex_new(NULL); - if (!(aqi->mutex)) + audioQualityImprovement->mutex = malloc(sizeof(Mutex)); + if (!(audioQualityImprovement->mutex) + || mutex_init(audioQualityImprovement->mutex, NULL)) { - AudioQualityImprovement_free(aqi); + AudioQualityImprovement_free(audioQualityImprovement); return NULL; } - aqi->inputLatency = -1; - aqi->longID = longID; - aqi->next = next; - aqi->outputLatency = -1; - aqi->retainCount = 1; + audioQualityImprovement->denoise = JNI_FALSE; + audioQualityImprovement->echoFilterLengthInMillis = 0; + audioQualityImprovement->frameSize = 0; + audioQualityImprovement->longID = longID; + audioQualityImprovement->next = next; + audioQualityImprovement->retainCount = 1; + audioQualityImprovement->sampleRate = 0; } - return aqi; -} - -static void -AudioQualityImprovement_popFromPlay - (AudioQualityImprovement *aqi, spx_uint32_t sampleCount) -{ - spx_uint32_t i; - spx_uint32_t sampleCountToMove = aqi->playLength - sampleCount; - spx_int16_t *playNew = aqi->play; - spx_int16_t *playOld = aqi->play + sampleCount; - - for (i = 0; i < sampleCountToMove; i++) - *playNew++ = *playOld++; - aqi->playLength -= sampleCount; + return audioQualityImprovement; } -/** - * - * @param aqi - * @param sampleOrigin - * @param sampleRate - * @param sampleSizeInBits - * @param channels - * @param latency the latency of the stream associated with buffer in - * milliseconds - * @param buffer - * @param length the length of buffer in bytes - */ -void -AudioQualityImprovement_process - (AudioQualityImprovement *aqi, +void AudioQualityImprovement_process + (AudioQualityImprovement *audioQualityImprovement, AudioQualityImprovementSampleOrigin sampleOrigin, - double sampleRate, unsigned long sampleSizeInBits, int channels, - jlong latency, - void *buffer, unsigned long length) + double sampleRate, + unsigned long sampleSizeInBits, + int channels, + void *buffer, + unsigned long length) { - if ((sampleSizeInBits == 16) && (channels == 1) && !Mutex_lock(aqi->mutex)) + if ((sampleSizeInBits == 16) + && (channels == 1) + && !mutex_lock(audioQualityImprovement->mutex)) { switch (sampleOrigin) { case AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_INPUT: - if (sampleRate == aqi->sampleRate) + if (sampleRate == audioQualityImprovement->sampleRate) { - AudioQualityImprovement_setFrameSize(aqi, length); - if (aqi->preprocess) + AudioQualityImprovement_setFrameSize( + audioQualityImprovement, + length); + if (audioQualityImprovement->preprocess) { - AudioQualityImprovement_setInputLatency(aqi, latency); - if (aqi->echo && aqi->play && aqi->playLength) + if (audioQualityImprovement->echo + && audioQualityImprovement->play + && (audioQualityImprovement->playSize + == audioQualityImprovement->frameSize)) { AudioQualityImprovement_cancelEchoFromPlay( - aqi, - buffer, length); + audioQualityImprovement, + buffer, + length); } - speex_preprocess_run(aqi->preprocess, buffer); + speex_preprocess_run( + audioQualityImprovement->preprocess, + buffer); } } break; case AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT: - if (aqi->preprocess && aqi->echo) + if (audioQualityImprovement->preprocess + && audioQualityImprovement->echo) { - AudioQualityImprovement_setOutputLatency(aqi, latency); AudioQualityImprovement_resampleInPlay( - aqi, - sampleRate, sampleSizeInBits, channels, - buffer, length); + audioQualityImprovement, + sampleRate, + sampleSizeInBits, + channels, + buffer, + length); } break; } - Mutex_unlock(aqi->mutex); + mutex_unlock(audioQualityImprovement->mutex); } } void -AudioQualityImprovement_release(AudioQualityImprovement *aqi) +AudioQualityImprovement_release + (AudioQualityImprovement *audioQualityImprovement) { - if (!Mutex_lock(AudioQualityImprovement_sharedInstancesMutex)) + if (!mutex_lock(&AudioQualityImprovement_sharedInstancesMutex)) { - if (!Mutex_lock(aqi->mutex)) + if (!mutex_lock(audioQualityImprovement->mutex)) { - --(aqi->retainCount); - if (aqi->retainCount < 1) + --(audioQualityImprovement->retainCount); + if (audioQualityImprovement->retainCount < 1) { - if (aqi == AudioQualityImprovement_sharedInstances) + if (audioQualityImprovement + == AudioQualityImprovement_sharedInstances) { AudioQualityImprovement_sharedInstances = AudioQualityImprovement_sharedInstances->next; @@ -298,435 +264,299 @@ AudioQualityImprovement_release(AudioQualityImprovement *aqi) AudioQualityImprovement *nextSharedInstance = prevSharedInstance->next; - if (aqi == nextSharedInstance) + if (audioQualityImprovement == nextSharedInstance) { - prevSharedInstance->next = aqi->next; + prevSharedInstance->next + = audioQualityImprovement->next; break; } prevSharedInstance = nextSharedInstance; } } - Mutex_unlock(aqi->mutex); - AudioQualityImprovement_free(aqi); + mutex_unlock(audioQualityImprovement->mutex); + AudioQualityImprovement_free(audioQualityImprovement); } else - Mutex_unlock(aqi->mutex); + mutex_unlock(audioQualityImprovement->mutex); } - Mutex_unlock(AudioQualityImprovement_sharedInstancesMutex); + mutex_unlock(&AudioQualityImprovement_sharedInstancesMutex); } } - -/** - * - * @param aqi - * @param sampleRate - * @param sampleSizeInBits - * @param channels - * @param buffer - * @param length the length of buffer in bytes - */ static void AudioQualityImprovement_resampleInPlay - (AudioQualityImprovement *aqi, - double sampleRate, unsigned long sampleSizeInBits, int channels, - void *buffer, unsigned long length) + (AudioQualityImprovement *audioQualityImprovement, + double sampleRate, + unsigned long sampleSizeInBits, + int channels, + void *buffer, + unsigned long length) { spx_uint32_t playSize; - spx_uint32_t playCapacity; - spx_uint32_t playLength;; - spx_int16_t *play; - if (sampleRate == aqi->sampleRate) + if (sampleRate == audioQualityImprovement->sampleRate) playSize = length; - else if (length * aqi->sampleRate == aqi->frameSize * sampleRate) + else if (length * audioQualityImprovement->sampleRate + == audioQualityImprovement->frameSize * sampleRate) { - if (aqi->resampler) + if (audioQualityImprovement->resampler) { speex_resampler_set_rate( - aqi->resampler, - (spx_uint32_t) sampleRate, (spx_uint32_t) (aqi->sampleRate)); - playSize = aqi->frameSize; + audioQualityImprovement->resampler, + (spx_uint32_t) sampleRate, + (spx_uint32_t) (audioQualityImprovement->sampleRate)); + playSize = audioQualityImprovement->frameSize; } else { - aqi->resampler + audioQualityImprovement->resampler = speex_resampler_init( channels, - (spx_uint32_t) sampleRate, (spx_uint32_t) (aqi->sampleRate), + (spx_uint32_t) sampleRate, + (spx_uint32_t) (audioQualityImprovement->sampleRate), SPEEX_RESAMPLER_QUALITY_VOIP, NULL); - if (aqi->resampler) - playSize = aqi->frameSize; - else + if (!(audioQualityImprovement->resampler)) { - aqi->playIsDelaying = JNI_TRUE; - aqi->playLength = 0; + audioQualityImprovement->playSize = 0; return; } } } else { - /* - * The specified buffer neither is in the format of the audio capture - * nor can be resampled to it. - */ - aqi->playIsDelaying = JNI_TRUE; - aqi->playLength = 0; + audioQualityImprovement->playSize = 0; return; } - - /* Ensure that play exists and is large enough. */ - playCapacity - = ((1 + aqi->playDelay) + 1) * (aqi->frameSize / sizeof(spx_int16_t)); - playLength = playSize / sizeof(spx_int16_t); - if (playCapacity < playLength) - playCapacity = playLength; - if (!(aqi->play) || (aqi->playCapacity < playCapacity)) + if (!(audioQualityImprovement->play) + || (audioQualityImprovement->playCapacity < playSize)) { - spx_int16_t *newPlay; + spx_int16_t *newPlay = realloc(audioQualityImprovement->play, playSize); - newPlay = realloc(aqi->play, playCapacity * sizeof(spx_int16_t)); if (newPlay) { - if (!(aqi->play)) - { - aqi->playIsDelaying = JNI_TRUE; - aqi->playLength = 0; - } - - aqi->play = newPlay; - aqi->playCapacity = playCapacity; + audioQualityImprovement->play = newPlay; + audioQualityImprovement->playCapacity = playSize; } else { - aqi->playIsDelaying = JNI_TRUE; - aqi->playLength = 0; + audioQualityImprovement->playSize = 0; return; } } - - /* Ensure that there is room for buffer in play. */ - if (aqi->playLength + playLength > aqi->playCapacity) + if (length == audioQualityImprovement->frameSize) { - aqi->playIsDelaying = JNI_TRUE; - aqi->playLength = 0; - /* - * We don't have enough room in play for buffer which means that we'll - * have to throw some samples away. But it'll effectively mean that - * we'll enlarge the drift which will disrupt the echo cancellation. So - * it seems the least of two evils to just reset the echo cancellation. - */ - speex_echo_state_reset(aqi->echo); + memcpy(audioQualityImprovement->play, buffer, playSize); + audioQualityImprovement->playSize = playSize; } - - /* Place buffer in play. */ - play = aqi->play + aqi->playLength; - if (length == aqi->frameSize) - memcpy(play, buffer, playSize); else { unsigned long sampleSizeInBytes = sampleSizeInBits / 8; spx_uint32_t bufferSampleCount = length / sampleSizeInBytes; + spx_uint32_t playSampleCount = playSize / sampleSizeInBytes; speex_resampler_process_interleaved_int( - aqi->resampler, - buffer, &bufferSampleCount, play, &playLength); + audioQualityImprovement->resampler, + buffer, + &bufferSampleCount, + audioQualityImprovement->play, + &playSampleCount); + audioQualityImprovement->playSize = playSampleCount * sampleSizeInBytes; } - aqi->playLength += playLength; - - /* Take into account the latency. */ - if (aqi->playIsDelaying == JNI_TRUE) - AudioQualityImprovement_updatePlayIsDelaying(aqi); } static void -AudioQualityImprovement_retain(AudioQualityImprovement *aqi) +AudioQualityImprovement_retain + (AudioQualityImprovement *audioQualityImprovement) { - if (!Mutex_lock(aqi->mutex)) + if (!mutex_lock(audioQualityImprovement->mutex)) { - ++(aqi->retainCount); - Mutex_unlock(aqi->mutex); + ++(audioQualityImprovement->retainCount); + mutex_unlock(audioQualityImprovement->mutex); } } -/** - * Sets the indicator which determines whether noise suppression is to be - * performed by the specified AudioQualityImprovement (for captured - * audio). - * - * @param aqi the AudioQualityImprovement on which to set the indicator - * which determines whether it is to perform noise suppression (for captured audio) - * @param denoise JNI_TRUE if the specified aqi is to perform - * noise suppression (for captured audio); otherwise, JNI_FALSE - */ void AudioQualityImprovement_setDenoise - (AudioQualityImprovement *aqi, jboolean denoise) + (AudioQualityImprovement *audioQualityImprovement, jboolean denoise) { - if (!Mutex_lock(aqi->mutex)) + if (!mutex_lock(audioQualityImprovement->mutex)) { - if (aqi->denoise != denoise) + if (audioQualityImprovement->denoise != denoise) { - aqi->denoise = denoise; - AudioQualityImprovement_updatePreprocess(aqi); + audioQualityImprovement->denoise = denoise; + AudioQualityImprovement_updatePreprocess(audioQualityImprovement); } - Mutex_unlock(aqi->mutex); + mutex_unlock(audioQualityImprovement->mutex); } } -/** - * Sets the filter length in milliseconds of the echo cancellation - * implementation of the specified AudioQualityImprovement. The - * recommended filter length is approximately the third of the room - * reverberation time. For example, in a small room, reverberation time is in - * the order of 300 ms, so a filter length of 100 ms is a good choice (800 - * samples at 8000 Hz sampling rate). - * - * @param aqi the AudioQualityImprovement to set the filter length of - * @param echoFilterLengthInMillis the filter length in milliseconds of the echo - * cancellation of aqi - */ void AudioQualityImprovement_setEchoFilterLengthInMillis - (AudioQualityImprovement *aqi, jlong echoFilterLengthInMillis) + (AudioQualityImprovement *audioQualityImprovement, + jlong echoFilterLengthInMillis) { if (echoFilterLengthInMillis < 0) echoFilterLengthInMillis = 0; - if (!Mutex_lock(aqi->mutex)) + if (!mutex_lock(audioQualityImprovement->mutex)) { - if (aqi->echoFilterLengthInMillis != echoFilterLengthInMillis) + if (audioQualityImprovement->echoFilterLengthInMillis + != echoFilterLengthInMillis) { - aqi->echoFilterLengthInMillis = echoFilterLengthInMillis; - AudioQualityImprovement_updatePreprocess(aqi); + audioQualityImprovement->echoFilterLengthInMillis + = echoFilterLengthInMillis; + AudioQualityImprovement_updatePreprocess(audioQualityImprovement); } - Mutex_unlock(aqi->mutex); + mutex_unlock(audioQualityImprovement->mutex); } } static void AudioQualityImprovement_setFrameSize - (AudioQualityImprovement *aqi, jint frameSize) + (AudioQualityImprovement *audioQualityImprovement, jint frameSize) { - if (aqi->frameSize != frameSize) + if (audioQualityImprovement->frameSize != frameSize) { - aqi->frameSize = frameSize; - AudioQualityImprovement_updatePreprocess(aqi); - } -} - -static void -AudioQualityImprovement_setInputLatency - (AudioQualityImprovement *aqi, jlong inputLatency) -{ - if (aqi->inputLatency != inputLatency) - { - aqi->inputLatency = inputLatency; - AudioQualityImprovement_updatePlayDelay(aqi); - } -} - -static void -AudioQualityImprovement_setOutputLatency - (AudioQualityImprovement *aqi, jlong outputLatency) -{ - if (aqi->outputLatency != outputLatency) - { - aqi->outputLatency = outputLatency; - AudioQualityImprovement_updatePlayDelay(aqi); + audioQualityImprovement->frameSize = frameSize; + AudioQualityImprovement_updatePreprocess(audioQualityImprovement); } } void AudioQualityImprovement_setSampleRate - (AudioQualityImprovement *aqi, int sampleRate) + (AudioQualityImprovement *audioQualityImprovement, int sampleRate) { - if (!Mutex_lock(aqi->mutex)) + if (!mutex_lock(audioQualityImprovement->mutex)) { - if (aqi->sampleRate != sampleRate) + if (audioQualityImprovement->sampleRate != sampleRate) { - aqi->sampleRate = sampleRate; - AudioQualityImprovement_updatePlayDelay(aqi); - AudioQualityImprovement_updatePreprocess(aqi); + audioQualityImprovement->sampleRate = sampleRate; + AudioQualityImprovement_updatePreprocess(audioQualityImprovement); } - Mutex_unlock(aqi->mutex); - } -} - -/** Unloads the AudioQualityImprovement class. */ -void -AudioQualityImprovement_unload() -{ - if (AudioQualityImprovement_sharedInstancesMutex) - { - Mutex_free(AudioQualityImprovement_sharedInstancesMutex); - AudioQualityImprovement_sharedInstancesMutex = NULL; - } -} - -static void -AudioQualityImprovement_updatePlayDelay(AudioQualityImprovement *aqi) -{ - spx_uint32_t playDelay; - - if ((aqi->inputLatency < 0) - || (aqi->outputLatency < 0) - || !(aqi->frameSize) - || !(aqi->sampleRate)) - { - playDelay = MIN_PLAY_DELAY_IN_FRAMES; + mutex_unlock(audioQualityImprovement->mutex); } - else - { - playDelay - = (aqi->outputLatency * aqi->sampleRate) - / ((aqi->frameSize / sizeof(spx_int16_t)) * 1000); - if (playDelay < MIN_PLAY_DELAY_IN_FRAMES) - playDelay = MIN_PLAY_DELAY_IN_FRAMES; - } - - if (aqi->playDelay != playDelay) - { - aqi->playDelay = playDelay; - - if (aqi->play && (aqi->playIsDelaying == JNI_TRUE)) - AudioQualityImprovement_updatePlayIsDelaying(aqi); - } -} - -/** - * Updates the indicator of the specified AudioQualityImprovement which - * determines whether AudioQualityImprovement#play delays the access to - * it from AudioQualityImprovement#echo. - * - * @param aqi the AudioQualityImprovement of which to update the - * indicator which determines whether AudioQualityImprovement#play - * delays the access to it from AudioQualityImprovement#echo - */ -static void -AudioQualityImprovement_updatePlayIsDelaying(AudioQualityImprovement *aqi) -{ - spx_uint32_t playDelay - = aqi->playDelay * (aqi->frameSize / sizeof(spx_int16_t)); - - aqi->playIsDelaying - = ((aqi->playLength < playDelay) && (playDelay <= aqi->playCapacity)) - ? JNI_TRUE - : JNI_FALSE; } static void -AudioQualityImprovement_updatePreprocess(AudioQualityImprovement *aqi) +AudioQualityImprovement_updatePreprocess + (AudioQualityImprovement *audioQualityImprovement) { - if (aqi->echo) + if (audioQualityImprovement->echo) { int frameSize = 0; - if ((aqi->echoFilterLengthInMillis > 0) - && (aqi->sampleRate > 0) + if ((audioQualityImprovement->echoFilterLengthInMillis > 0) + && (audioQualityImprovement->sampleRate > 0) && speex_echo_ctl( - aqi->echo, - SPEEX_ECHO_GET_FRAME_SIZE, &frameSize)) + audioQualityImprovement->echo, + SPEEX_ECHO_GET_FRAME_SIZE, + &frameSize)) frameSize = 0; if (frameSize - && (aqi->frameSize + && (audioQualityImprovement->frameSize == (frameSize * (16 /* sampleSizeInBits */ / 8)))) { int echoFilterLength = (int) - ((aqi->sampleRate * aqi->echoFilterLengthInMillis) + ((audioQualityImprovement->sampleRate + * audioQualityImprovement->echoFilterLengthInMillis) / 1000); - if (aqi->filterLengthOfEcho != echoFilterLength) + if (audioQualityImprovement->filterLengthOfEcho != echoFilterLength) frameSize = 0; } else frameSize = 0; if (frameSize < 1) { - if (aqi->preprocess) + if (audioQualityImprovement->preprocess) { speex_preprocess_ctl( - aqi->preprocess, - SPEEX_PREPROCESS_SET_ECHO_STATE, NULL); + audioQualityImprovement->preprocess, + SPEEX_PREPROCESS_SET_ECHO_STATE, + NULL); } - speex_echo_state_destroy(aqi->echo); - aqi->echo = NULL; + speex_echo_state_destroy(audioQualityImprovement->echo); + audioQualityImprovement->echo = NULL; } } - if (aqi->preprocess - && ((aqi->frameSize != aqi->frameSizeOfPreprocess) - || (aqi->sampleRate != aqi->sampleRateOfPreprocess))) + if (audioQualityImprovement->preprocess + && ((audioQualityImprovement->frameSize + != audioQualityImprovement->frameSizeOfPreprocess) + || (audioQualityImprovement->sampleRate + != audioQualityImprovement->sampleRateOfPreprocess))) { - speex_preprocess_state_destroy(aqi->preprocess); - aqi->preprocess = NULL; + speex_preprocess_state_destroy(audioQualityImprovement->preprocess); + audioQualityImprovement->preprocess = NULL; } - if ((aqi->frameSize > 0) && (aqi->sampleRate > 0)) + if ((audioQualityImprovement->frameSize > 0) + && (audioQualityImprovement->sampleRate > 0)) { - if (aqi->echoFilterLengthInMillis > 0) + if (audioQualityImprovement->echoFilterLengthInMillis > 0) { - if (!(aqi->echo)) + if (!(audioQualityImprovement->echo)) { - int echoFrameSize - = aqi->frameSize / (16 /* sampleSizeInBits */ / 8); int echoFilterLength = (int) - ((aqi->sampleRate * aqi->echoFilterLengthInMillis) + ((audioQualityImprovement->sampleRate + * audioQualityImprovement + ->echoFilterLengthInMillis) / 1000); - aqi->echo - = speex_echo_state_init(echoFrameSize, echoFilterLength); - aqi->filterLengthOfEcho = echoFilterLength; - /* - * Since echo has just been (re)created, make sure that the - * delay in play will happen again taking into consideration the - * latest frameSize. - */ - if (aqi->play) - AudioQualityImprovement_updatePlayIsDelaying(aqi); + audioQualityImprovement->echo + = speex_echo_state_init( + audioQualityImprovement->frameSize + / (16 /* sampleSizeInBits */ / 8), + echoFilterLength); + audioQualityImprovement->filterLengthOfEcho + = echoFilterLength; } - if (aqi->echo) + if (audioQualityImprovement->echo) { speex_echo_ctl( - aqi->echo, - SPEEX_ECHO_SET_SAMPLING_RATE, &(aqi->sampleRate)); + audioQualityImprovement->echo, + SPEEX_ECHO_SET_SAMPLING_RATE, + &(audioQualityImprovement->sampleRate)); } } - if (aqi->denoise || aqi->echo) + if (audioQualityImprovement->denoise || audioQualityImprovement->echo) { - if (!(aqi->preprocess)) + if (!(audioQualityImprovement->preprocess)) { - aqi->preprocess + audioQualityImprovement->preprocess = speex_preprocess_state_init( - aqi->frameSize / (16 /* sampleSizeInBits */ / 8), - aqi->sampleRate); - aqi->frameSizeOfPreprocess = aqi->frameSize; - aqi->sampleRateOfPreprocess = aqi->sampleRate; - if (aqi->preprocess) + audioQualityImprovement->frameSize + / (16 /* sampleSizeInBits */ / 8), + audioQualityImprovement->sampleRate); + audioQualityImprovement->frameSizeOfPreprocess + = audioQualityImprovement->frameSize; + audioQualityImprovement->sampleRateOfPreprocess + = audioQualityImprovement->sampleRate; + if (audioQualityImprovement->preprocess) { - int on = 1; + int vad = 1; speex_preprocess_ctl( - aqi->preprocess, - SPEEX_PREPROCESS_SET_DEREVERB, &on); - speex_preprocess_ctl( - aqi->preprocess, - SPEEX_PREPROCESS_SET_VAD, &on); + audioQualityImprovement->preprocess, + SPEEX_PREPROCESS_SET_VAD, + &vad); } } - if (aqi->preprocess) + if (audioQualityImprovement->preprocess) { - int denoise = (aqi->denoise == JNI_TRUE) ? 1 : 0; + int denoise + = (audioQualityImprovement->denoise == JNI_TRUE) ? 1 : 0; speex_preprocess_ctl( - aqi->preprocess, - SPEEX_PREPROCESS_SET_DENOISE, &denoise); - if (aqi->echo) + audioQualityImprovement->preprocess, + SPEEX_PREPROCESS_SET_DENOISE, + &denoise); + if (audioQualityImprovement->echo) { speex_preprocess_ctl( - aqi->preprocess, - SPEEX_PREPROCESS_SET_ECHO_STATE, aqi->echo); + audioQualityImprovement->preprocess, + SPEEX_PREPROCESS_SET_ECHO_STATE, + audioQualityImprovement->echo); } } } diff --git a/src/native/portaudio/AudioQualityImprovement.h b/src/native/portaudio/AudioQualityImprovement.h index 49277679f..176d850b3 100644 --- a/src/native/portaudio/AudioQualityImprovement.h +++ b/src/native/portaudio/AudioQualityImprovement.h @@ -14,7 +14,64 @@ typedef void *AudioQualityImprovement; #else /* #ifndef AUDIO_QUALITY_IMPROVEMENT_IMPLEMENTATION */ -#include "Mutex.h" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +typedef CRITICAL_SECTION Mutex; + +static inline int mutex_init(Mutex* mutex, void* arg) +{ + InitializeCriticalSection(mutex); + arg = NULL; /* unused */ + return 0; +} + +static inline int mutex_destroy(Mutex* mutex) +{ + DeleteCriticalSection(mutex); + return 0; +} + +static inline int mutex_lock(Mutex* mutex) +{ + EnterCriticalSection(mutex); + return 0; +} + +static inline int mutex_unlock(Mutex* mutex) +{ + LeaveCriticalSection(mutex); + return 0; +} + +#else /* Unix */ +#include + +typedef pthread_mutex_t Mutex; + +static inline int mutex_init(Mutex* mutex, void* arg) +{ + return pthread_mutex_init(mutex, arg); +} + +static inline int mutex_destroy(Mutex* mutex) +{ + return pthread_mutex_destroy(mutex); +} + +static inline int mutex_lock(Mutex* mutex) +{ + return pthread_mutex_lock(mutex); +} + +static inline int mutex_unlock(Mutex* mutex) +{ + return pthread_mutex_unlock(mutex); + return 0; +} +#endif + #include #include #include @@ -24,48 +81,17 @@ typedef struct _AudioQualityImprovement jboolean denoise; SpeexEchoState *echo; jlong echoFilterLengthInMillis; - - /** The length of the echo cancelling filter of #echo in samples. */ int filterLengthOfEcho; jint frameSize; int frameSizeOfPreprocess; - - /** The capture latency in milliseconds. */ - jlong inputLatency; jlong longID; Mutex *mutex; struct _AudioQualityImprovement *next; - - /** - * The intermediate buffer into which the result of echo cancellation is - * written for a specific buffer of captured audio. - */ spx_int16_t *out; - - /** The capacity of #out in bytes. */ spx_uint32_t outCapacity; - - /** The playback latency in milliseconds. */ - jlong outputLatency; spx_int16_t *play; - - /** - * The number of samples allocated to #play regardless of whether they are - * valid or not. - */ spx_uint32_t playCapacity; - - /** The number of frames to delay playback with. */ - spx_uint32_t playDelay; - - /** - * The indicator which determines whether #play is currently delaying the - * access to it from #echo. - */ - jboolean playIsDelaying; - - /** The number of valid samples written into #play. */ - spx_uint32_t playLength; + spx_uint32_t playSize; SpeexPreprocessState *preprocess; SpeexResamplerState *resampler; int retainCount; @@ -73,68 +99,32 @@ typedef struct _AudioQualityImprovement int sampleRateOfPreprocess; char *stringID; } AudioQualityImprovement; - #endif /* #ifndef AUDIO_QUALITY_IMPROVEMENT_IMPLEMENTATION */ typedef enum { - /** - * The constant which indicates that the associated samples have originated - * from an input stream i.e. capture. - */ AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_INPUT, - - /** - * The constant which indicates that the associated samples have originated - * from an output stream i.e. playback. - */ AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT } AudioQualityImprovementSampleOrigin; AudioQualityImprovement *AudioQualityImprovement_getSharedInstance (const char *stringID, jlong longID); - -/** Loads the AudioQualityImprovement class. */ -void AudioQualityImprovement_load(); void AudioQualityImprovement_process - (AudioQualityImprovement *aqi, + (AudioQualityImprovement *audioQualityImprovement, AudioQualityImprovementSampleOrigin sampleOrigin, - double sampleRate, unsigned long sampleSizeInBits, int channels, - jlong latency, - void *buffer, unsigned long length); -void AudioQualityImprovement_release(AudioQualityImprovement *aqi); - -/** - * Sets the indicator which determines whether noise suppression is to be - * performed by the specified AudioQualityImprovement (for captured - * audio). - * - * @param aqi the AudioQualityImprovement on which to set the indicator - * which determines whether it is to perform noise suppression (for captured audio) - * @param denoise JNI_TRUE if the specified aqi is to perform - * noise suppression (for captured audio); otherwise, JNI_FALSE - */ + double sampleRate, + unsigned long sampleSizeInBits, + int channels, + void *buffer, + unsigned long length); +void AudioQualityImprovement_release + (AudioQualityImprovement *audioQualityImprovement); void AudioQualityImprovement_setDenoise - (AudioQualityImprovement *aqi, jboolean denoise); - -/** - * Sets the filter length in milliseconds of the echo cancellation - * implementation of the specified AudioQualityImprovement. The - * recommended filter length is approximately the third of the room - * reverberation time. For example, in a small room, reverberation time is in - * the order of 300 ms, so a filter length of 100 ms is a good choice (800 - * samples at 8000 Hz sampling rate). - * - * @param aqi the AudioQualityImprovement to set the filter length of - * @param echoFilterLengthInMillis the filter length in milliseconds of the echo - * cancellation of aqi - */ + (AudioQualityImprovement *audioQualityImprovement, jboolean denoise); void AudioQualityImprovement_setEchoFilterLengthInMillis - (AudioQualityImprovement *aqi, jlong echoFilterLengthInMillis); + (AudioQualityImprovement *audioQualityImprovement, + jlong echoFilterLengthInMillis); void AudioQualityImprovement_setSampleRate - (AudioQualityImprovement *aqi, int sampleRate); - -/** Unloads the AudioQualityImprovement class. */ -void AudioQualityImprovement_unload(); + (AudioQualityImprovement *audioQualityImprovement, int sampleRate); #endif /* #ifndef _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_AUDIOQUALITYIMPROVEMENT_H_ */ diff --git a/src/native/portaudio/ConditionVariable.h b/src/native/portaudio/ConditionVariable.h deleted file mode 100644 index 7ab5927e3..000000000 --- a/src/native/portaudio/ConditionVariable.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ - -#ifndef _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_CONDITIONVARIABLE_H_ -#define _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_CONDITIONVARIABLE_H_ - -#include "Mutex.h" - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -typedef HANDLE ConditionVariable; - -static inline void ConditionVariable_free(ConditionVariable *condVar) -{ - if (CloseHandle(*condVar)) - free(condVar); -} - -static inline ConditionVariable *ConditionVariable_new(void *attr) -{ - ConditionVariable *condVar = malloc(sizeof(ConditionVariable)); - - if (condVar) - { - HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); - - if (event) - *condVar = event; - else - { - free(condVar); - condVar = NULL; - } - } - return condVar; -} - -static inline int ConditionVariable_notify(ConditionVariable *condVar) -{ - return SetEvent(*condVar) ? 0 : GetLastError(); -} - -static inline int ConditionVariable_wait - (ConditionVariable *condVar, Mutex *mutex) -{ - DWORD waitForSingleObject; - - LeaveCriticalSection(mutex); - waitForSingleObject = WaitForSingleObject(*condVar, INFINITE); - EnterCriticalSection(mutex); - return waitForSingleObject; -} - -#else /* #ifdef _WIN32 */ -#include - -typedef pthread_cond_t ConditionVariable; - -static inline void ConditionVariable_free(ConditionVariable *condVar) -{ - if (!pthread_cond_destroy(condVar)) - free(condVar); -} - -static inline ConditionVariable *ConditionVariable_new(void *attr) -{ - ConditionVariable *condVar = malloc(sizeof(ConditionVariable)); - - if (condVar && pthread_cond_init(condVar, attr)) - { - free(condVar); - condVar = NULL; - } - return condVar; -} - -static inline int ConditionVariable_notify(ConditionVariable *condVar) -{ - return pthread_cond_signal(condVar); -} - -static inline int ConditionVariable_wait - (ConditionVariable *condVar, Mutex *mutex) -{ - return pthread_cond_wait(condVar, mutex); -} -#endif /* #ifdef _WIN32 */ - -#endif /* _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_CONDITIONVARIABLE_H_ */ diff --git a/src/native/portaudio/Mutex.h b/src/native/portaudio/Mutex.h deleted file mode 100644 index 7d2ac2d17..000000000 --- a/src/native/portaudio/Mutex.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ - -#ifndef _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_MUTEX_H_ -#define _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_MUTEX_H_ - -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -typedef CRITICAL_SECTION Mutex; - -static inline void Mutex_free(Mutex* mutex) -{ - DeleteCriticalSection(mutex); - free(mutex); -} - -static inline int Mutex_lock(Mutex* mutex) -{ - EnterCriticalSection(mutex); - return 0; -} - -static inline Mutex *Mutex_new(void* attr) -{ - Mutex *mutex = malloc(sizeof(Mutex)); - - (void) attr; - - if (mutex) - InitializeCriticalSection(mutex); - return mutex; -} - -static inline int Mutex_unlock(Mutex* mutex) -{ - LeaveCriticalSection(mutex); - return 0; -} - -#else /* #ifdef _WIN32 */ -#include - -typedef pthread_mutex_t Mutex; - -static inline void Mutex_free(Mutex* mutex) -{ - if (!pthread_mutex_destroy(mutex)) - free(mutex); -} - -static inline int Mutex_lock(Mutex* mutex) -{ - return pthread_mutex_lock(mutex); -} - -static inline Mutex *Mutex_new(void* attr) -{ - Mutex *mutex = malloc(sizeof(Mutex)); - - if (mutex && pthread_mutex_init(mutex, attr)) - { - free(mutex); - mutex = NULL; - } - return mutex; -} - -static inline int Mutex_unlock(Mutex* mutex) -{ - return pthread_mutex_unlock(mutex); -} -#endif /* #ifdef _WIN32 */ - -#endif /* #ifndef _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_MUTEX_H_ */ diff --git a/src/native/portaudio/README b/src/native/portaudio/README index f7024f2e1..101913bc3 100644 --- a/src/native/portaudio/README +++ b/src/native/portaudio/README @@ -10,7 +10,7 @@ - Windows $./configure --enable-static --disable-shared && make - + Note for Windows x64, edit Makefile (after ./configure) and modify %.lo: %.c $(MAKEFILE) $(PAINC) $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $< -o $@ diff --git a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c index 6c41dab38..ea97907c7 100644 --- a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c +++ b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c @@ -8,10 +8,7 @@ #include "net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h" #include "AudioQualityImprovement.h" -#include "ConditionVariable.h" -#include "Mutex.h" #include -#include #include #include #include @@ -21,40 +18,8 @@ typedef struct AudioQualityImprovement *audioQualityImprovement; int channels; JNIEnv *env; - jboolean finished; - - /** - * The value specified as the framesPerBuffer argument to the - * Pa_OpenStream function call which has opened #stream. - */ - unsigned long framesPerBuffer; - void *input; - size_t inputCapacity; - ConditionVariable *inputCondVar; long inputFrameSize; - - /** The input latency of #stream. */ - jlong inputLatency; - size_t inputLength; - Mutex *inputMutex; - Mutex *mutex; - void *output; - size_t outputCapacity; - ConditionVariable *outputCondVar; long outputFrameSize; - - /** The output latency of #stream. */ - jlong outputLatency; - size_t outputLength; - Mutex *outputMutex; - - /** - * The indicator which determines whether this PortAudioStream - * implements the blocking stream interface on top of the non-blocking - * stream interface. - */ - jboolean pseudoBlocking; - jlong retainCount; double sampleRate; int sampleSizeInBits; PaStream *stream; @@ -72,60 +37,22 @@ static long PortAudio_getFrameSize(PaStreamParameters *streamParameters); static unsigned long PortAudio_getSampleSizeInBits (PaStreamParameters *streamParameters); static void PortAudio_throwException(JNIEnv *env, PaError errorCode); -static jlong System_currentTimeMillis(); -/** - * Allocates (and initializes) the memory and its associated variables for a - * specific buffer to be used by the pseudo-blocking stream interface - * implementation of a PortAudioStream. - * - * @param capacity the number of bytes to be allocated to the buffer - * @param bufferPtr a pointer which specifies where the location of the - * allocated buffer is to be stored - * @param bufferLengthPtr a pointer which specifies where the initial length - * (i.e. zero) is to be stored - * @param bufferCapacityPtr a pointer which specifies where the capacity of the - * allocated buffer is to be stored - * @param bufferMutexPtr a pointer which specifies where the Mute to - * synchronize the access to the allocated buffer is to be stored - * @param bufferCondVarPtr a pointer which specifies where the - * ConditionVariable to synchronize the access to the allocated buffer - * is to be stored - * @return the location of the allocated buffer upon success; otherwise, - * NULL - */ -static void *PortAudioStream_allocPseudoBlockingBuffer - (size_t capacity, - void **bufferPtr, size_t *bufferLengthPtr, size_t *bufferCapacityPtr, - Mutex **bufferMutexPtr, ConditionVariable **bufferCondVarPtr); -static void PortAudioStream_free(JNIEnv *env, PortAudioStream *stream); -static int PortAudioStream_javaCallback - (const void *input, - void *output, - unsigned long frameCount, - const PaStreamCallbackTimeInfo *timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData); -static void PortAudioStream_javaFinishedCallback(void *userData); -static PortAudioStream * PortAudioStream_new - (JNIEnv *env, jobject streamCallback); -static void PortAudioStream_popFromPseudoBlockingBuffer - (void *buffer, size_t length, size_t *bufferLengthPtr); -static int PortAudioStream_pseudoBlockingCallback - (const void *input, +static int PortAudioStream_callback( + const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData); -static void PortAudioStream_pseudoBlockingFinishedCallback(void *userData); -static void PortAudioStream_release(PortAudioStream *stream); -static void PortAudioStream_retain(PortAudioStream *stream); +static void PortAudioStream_finishedCallback(void *userData); +static void PortAudioStream_free(JNIEnv *env, PortAudioStream *stream); +static PortAudioStream * PortAudioStream_new( + JNIEnv *env, jobject streamCallback); static const char *AUDIO_QUALITY_IMPROVEMENT_STRING_ID = "portaudio"; #define LATENCY_HIGH net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH #define LATENCY_LOW net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW -#define LATENCY_UNSPECIFIED net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSPECIFIED JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_free @@ -153,8 +80,6 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream if (paNoError != errorCode) PortAudio_throwException(env, errorCode); - else if (portAudioStream->pseudoBlocking) - PortAudioStream_release(portAudioStream); else PortAudioStream_free(env, portAudioStream); } @@ -254,8 +179,6 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1OpenStream jobject streamCallback) { PortAudioStream *stream = PortAudioStream_new(env, streamCallback); - PaStreamCallback *effectiveStreamCallback; - PaStreamFinishedCallback *effectiveStreamFinishedCallback; PaError errorCode; PaStreamParameters *inputStreamParameters = (PaStreamParameters *) inputParameters; @@ -265,197 +188,55 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1OpenStream if (!stream) return 0; - if (streamCallback) - { - effectiveStreamCallback = PortAudioStream_javaCallback; - effectiveStreamFinishedCallback = PortAudioStream_javaFinishedCallback; - stream->pseudoBlocking = JNI_FALSE; - } - else - { - /* - * Some host APIs such as DirectSound don't really implement the - * blocking stream interface. If we're to ever be able to try them out, - * we'll have to implement the blocking stream interface on top of the - * non-blocking stream interface. - */ - - effectiveStreamCallback = NULL; - effectiveStreamFinishedCallback = NULL; - stream->pseudoBlocking = JNI_FALSE; - - /* - * TODO It should be possible to implement the blocking stream interface - * without a specific framesPerBuffer. - */ - if ((paFramesPerBufferUnspecified != framesPerBuffer) - && (framesPerBuffer > 0)) - { - PaDeviceIndex device; - - if (inputStreamParameters) - device = inputStreamParameters->device; - else if (outputStreamParameters) - device = outputStreamParameters->device; - else - device = paNoDevice; - if (device != paNoDevice) - { - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(device); - - if (deviceInfo) - { - const PaHostApiInfo *hostApiInfo - = Pa_GetHostApiInfo(deviceInfo->hostApi); - - if (hostApiInfo && (paDirectSound == hostApiInfo->type)) - { - effectiveStreamCallback - = PortAudioStream_pseudoBlockingCallback; - effectiveStreamFinishedCallback - = PortAudioStream_pseudoBlockingFinishedCallback; - stream->pseudoBlocking = JNI_TRUE; - } - } - } - } - } - - if (JNI_TRUE == stream->pseudoBlocking) - { - stream->mutex = Mutex_new(NULL); - errorCode = (stream->mutex) ? paNoError : paInsufficientMemory; - } - else - errorCode = paNoError; - - if (paNoError == errorCode) - { - errorCode - = Pa_OpenStream( - &(stream->stream), - PortAudio_fixInputParametersSuggestedLatency( - inputStreamParameters), - PortAudio_fixOutputParametersSuggestedLatency( - outputStreamParameters), - sampleRate, - framesPerBuffer, - streamFlags, - effectiveStreamCallback, - stream); - } + errorCode + = Pa_OpenStream( + &(stream->stream), + PortAudio_fixInputParametersSuggestedLatency(inputStreamParameters), + PortAudio_fixOutputParametersSuggestedLatency( + outputStreamParameters), + sampleRate, + framesPerBuffer, + streamFlags, + streamCallback ? PortAudioStream_callback : NULL, + stream); if (paNoError == errorCode) { - stream->framesPerBuffer = framesPerBuffer; stream->inputFrameSize = PortAudio_getFrameSize(inputStreamParameters); stream->outputFrameSize = PortAudio_getFrameSize(outputStreamParameters); - stream->sampleRate = sampleRate; - if (effectiveStreamFinishedCallback) - { + if (streamCallback) errorCode = Pa_SetStreamFinishedCallback( stream->stream, - effectiveStreamFinishedCallback); - } - + PortAudioStream_finishedCallback); + stream->audioQualityImprovement = AudioQualityImprovement_getSharedInstance( AUDIO_QUALITY_IMPROVEMENT_STRING_ID, 0); + stream->sampleRate = sampleRate; if (inputStreamParameters) { stream->sampleSizeInBits = PortAudio_getSampleSizeInBits(inputStreamParameters); stream->channels = inputStreamParameters->channelCount; - - /* - * Prepare whatever is necessary for the pseudo-blocking stream - * interface implementation. For example, allocate its memory early - * because doing it in the stream callback may introduce latency. - */ - if (stream->pseudoBlocking - && !PortAudioStream_allocPseudoBlockingBuffer( - 2 * framesPerBuffer * (stream->inputFrameSize), - &(stream->input), - &(stream->inputLength), - &(stream->inputCapacity), - &(stream->inputMutex), - &(stream->inputCondVar))) - { - Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream( - env, clazz, - (jlong) stream); - if (JNI_FALSE == (*env)->ExceptionCheck(env)) - { - PortAudio_throwException(env, paInsufficientMemory); - return 0; - } - } - if (stream->audioQualityImprovement) { AudioQualityImprovement_setSampleRate( stream->audioQualityImprovement, (int) sampleRate); - - if (stream->pseudoBlocking) - { - const PaStreamInfo *streamInfo; - - streamInfo = Pa_GetStreamInfo(stream->stream); - if (streamInfo) - { - stream->inputLatency - = (jlong) (streamInfo->inputLatency * 1000); - } - } } } - if (outputStreamParameters) + else if (outputStreamParameters) { stream->sampleSizeInBits = PortAudio_getSampleSizeInBits(outputStreamParameters); stream->channels = outputStreamParameters->channelCount; - - if (stream->pseudoBlocking - && !PortAudioStream_allocPseudoBlockingBuffer( - 2 * framesPerBuffer * (stream->outputFrameSize), - &(stream->output), - &(stream->outputLength), - &(stream->outputCapacity), - &(stream->outputMutex), - &(stream->outputCondVar))) - { - Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream( - env, clazz, - (jlong) stream); - if (JNI_FALSE == (*env)->ExceptionCheck(env)) - { - PortAudio_throwException(env, paInsufficientMemory); - return 0; - } - } - - if (stream->audioQualityImprovement) - { - const PaStreamInfo *streamInfo; - - streamInfo = Pa_GetStreamInfo(stream->stream); - if (streamInfo) - { - stream->outputLatency - = (jlong) (streamInfo->outputLatency * 1000); - } - } } - if (stream->pseudoBlocking) - PortAudioStream_retain(stream); - return (jlong) stream; } else @@ -475,54 +256,12 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1ReadStream if (data) { PortAudioStream *portAudioStream = (PortAudioStream *) stream; - PaError errorCode; - jlong framesInBytes = frames * portAudioStream->inputFrameSize; + PaError errorCode + = Pa_ReadStream(portAudioStream->stream, data, frames); - if (portAudioStream->pseudoBlocking) + if ((paNoError == errorCode) || (paInputOverflowed == errorCode)) { - if (Mutex_lock(portAudioStream->inputMutex)) - errorCode = paInternalError; - else - { - jlong bytesRead = 0; - - errorCode = paNoError; - while (bytesRead < framesInBytes) - { - jlong bytesToRead; - - if (JNI_TRUE == portAudioStream->finished) - { - errorCode = paStreamIsStopped; - break; - } - if (!(portAudioStream->inputLength)) - { - ConditionVariable_wait( - portAudioStream->inputCondVar, - portAudioStream->inputMutex); - continue; - } - - bytesToRead = framesInBytes - bytesRead; - if (bytesToRead > portAudioStream->inputLength) - bytesToRead = portAudioStream->inputLength; - memcpy( - data + bytesRead, - portAudioStream->input, - bytesToRead); - PortAudioStream_popFromPseudoBlockingBuffer( - portAudioStream->input, - bytesToRead, - &(portAudioStream->inputLength)); - bytesRead += bytesToRead; - } - Mutex_unlock(portAudioStream->inputMutex); - } - - /* Improve the audio quality of the input if possible. */ - if ((paNoError == errorCode) - && portAudioStream->audioQualityImprovement) + if (portAudioStream->audioQualityImprovement) { AudioQualityImprovement_process( portAudioStream->audioQualityImprovement, @@ -530,36 +269,14 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1ReadStream portAudioStream->sampleRate, portAudioStream->sampleSizeInBits, portAudioStream->channels, - portAudioStream->inputLatency, - data, framesInBytes); + data, + frames * portAudioStream->inputFrameSize); } + (*env)->ReleaseByteArrayElements(env, buffer, data, 0); } else { - errorCode = Pa_ReadStream(portAudioStream->stream, data, frames); - if ((paNoError == errorCode) || (paInputOverflowed == errorCode)) - { - errorCode = paNoError; - - if (portAudioStream->audioQualityImprovement) - { - AudioQualityImprovement_process( - portAudioStream->audioQualityImprovement, - AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_INPUT, - portAudioStream->sampleRate, - portAudioStream->sampleSizeInBits, - portAudioStream->channels, - portAudioStream->inputLatency, - data, framesInBytes); - } - } - } - - if (paNoError == errorCode) (*env)->ReleaseByteArrayElements(env, buffer, data, 0); - else - { - (*env)->ReleaseByteArrayElements(env, buffer, data, JNI_ABORT); PortAudio_throwException(env, errorCode); } } @@ -569,27 +286,8 @@ JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StartStream (JNIEnv *env, jclass clazz, jlong stream) { - PortAudioStream *portAudioStream = (PortAudioStream *) stream; - PaError errorCode; + PaError errorCode = Pa_StartStream(((PortAudioStream *) stream)->stream); - if (portAudioStream->pseudoBlocking) - { - PortAudioStream_retain(portAudioStream); - if (Mutex_lock(portAudioStream->mutex)) - errorCode = paInternalError; - else - { - portAudioStream->finished = JNI_FALSE; - errorCode = Pa_StartStream(portAudioStream->stream); - if (paNoError != errorCode) - portAudioStream->finished = JNI_TRUE; - Mutex_unlock(portAudioStream->mutex); - } - if (paNoError != errorCode) - PortAudioStream_release(portAudioStream); - } - else - errorCode = Pa_StartStream(portAudioStream->stream); if (paNoError != errorCode) PortAudio_throwException(env, errorCode); } @@ -614,14 +312,14 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream jbyte *bufferBytes; jbyte* data; PortAudioStream *portAudioStream; - jint i; - PaError errorCode = paNoError; - jlong framesInBytes; + PaStream *paStream; AudioQualityImprovement *audioQualityImprovement; double sampleRate; unsigned long sampleSizeInBits; int channels; - jlong outputLatency; + long framesInBytes; + PaError errorCode; + jint i; bufferBytes = (*env)->GetByteArrayElements(env, buffer, NULL); if (!bufferBytes) @@ -629,103 +327,38 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream data = bufferBytes + offset; portAudioStream = (PortAudioStream *) stream; - framesInBytes = frames * portAudioStream->outputFrameSize; + paStream = portAudioStream->stream; audioQualityImprovement = portAudioStream->audioQualityImprovement; sampleRate = portAudioStream->sampleRate; sampleSizeInBits = portAudioStream->sampleSizeInBits; channels = portAudioStream->channels; - outputLatency = portAudioStream->outputLatency; - - if (portAudioStream->pseudoBlocking) - { - for (i = 0; i < numberOfWrites; i++) - { - if (Mutex_lock(portAudioStream->outputMutex)) - errorCode = paInternalError; - else - { - jlong bytesWritten = 0; - - errorCode = paNoError; - while (bytesWritten < framesInBytes) - { - size_t outputCapacity - = portAudioStream->outputCapacity - - portAudioStream->outputLength; - jlong bytesToWrite; - - if (JNI_TRUE == portAudioStream->finished) - { - errorCode = paStreamIsStopped; - break; - } - if (outputCapacity < 1) - { - ConditionVariable_wait( - portAudioStream->outputCondVar, - portAudioStream->outputMutex); - continue; - } - - bytesToWrite = framesInBytes - bytesWritten; - if (bytesToWrite > outputCapacity) - bytesToWrite = outputCapacity; - memcpy( - ((jbyte *) portAudioStream->output) - + portAudioStream->outputLength, - data + bytesWritten, - bytesToWrite); - - portAudioStream->outputLength += bytesToWrite; - bytesWritten += bytesToWrite; - } - Mutex_unlock(portAudioStream->outputMutex); - } + framesInBytes = frames * portAudioStream->outputFrameSize; - if (paNoError == errorCode) - { - if (audioQualityImprovement) - { - AudioQualityImprovement_process( - audioQualityImprovement, - AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT, - sampleRate, sampleSizeInBits, channels, - outputLatency, - data, framesInBytes); - } - - data += framesInBytes; - } - } - } - else + for (i = 0; i < numberOfWrites; i++) { - PaStream *paStream = portAudioStream->stream; - - for (i = 0; i < numberOfWrites; i++) + errorCode = Pa_WriteStream(paStream, data, frames); + if ((paNoError != errorCode) && (errorCode != paOutputUnderflowed)) + break; + else { - errorCode = Pa_WriteStream(paStream, data, frames); - if ((paNoError != errorCode) && (paOutputUnderflowed != errorCode)) - break; - else + if (audioQualityImprovement) { - if (audioQualityImprovement) - { - AudioQualityImprovement_process( - audioQualityImprovement, - AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT, - sampleRate, sampleSizeInBits, channels, - outputLatency, - data, framesInBytes); - } - data += framesInBytes; + AudioQualityImprovement_process( + audioQualityImprovement, + AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT, + sampleRate, + sampleSizeInBits, + channels, + data, + framesInBytes); } + data += framesInBytes; } } (*env)->ReleaseByteArrayElements(env, buffer, bufferBytes, JNI_ABORT); - if ((paNoError != errorCode) && (paOutputUnderflowed != errorCode)) + if ((paNoError != errorCode) && (errorCode != paOutputUnderflowed)) PortAudio_throwException(env, errorCode); } @@ -785,6 +418,20 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1g return ((PaDeviceInfo *) deviceInfo)->maxOutputChannels; } +JNIEXPORT jstring JNICALL +Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName + (JNIEnv *env, jclass clazz, jlong deviceInfo) +{ + const char *name = ((PaDeviceInfo *) deviceInfo)->name; + + /* + * PaDeviceInfo_getName has been deprected in the Java source code and the + * implementation here is left to allow the application to execute even + * without the recompiled JNI counterpart. + */ + return name ? (*env)->NewStringUTF(env, name) : NULL; +} + JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getNameBytes (JNIEnv *jniEnv, jclass clazz, jlong deviceInfo) @@ -896,20 +543,6 @@ Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setEchoFilterLe } } -JNIEXPORT jint JNICALL -JNI_OnLoad(JavaVM *vm, void *reserved) -{ - AudioQualityImprovement_load(); - - return JNI_VERSION_1_4; -} - -JNIEXPORT void JNICALL -JNI_OnUnload(JavaVM *vm, void *reserved) -{ - AudioQualityImprovement_unload(); -} - static PaStreamParameters * PortAudio_fixInputParametersSuggestedLatency (PaStreamParameters *inputParameters) @@ -921,15 +554,13 @@ PortAudio_fixInputParametersSuggestedLatency if (deviceInfo) { - PaTime suggestedLatency = inputParameters->suggestedLatency; - - if ((suggestedLatency == LATENCY_LOW) - || (suggestedLatency == LATENCY_UNSPECIFIED)) + if (inputParameters->suggestedLatency == LATENCY_LOW) { inputParameters->suggestedLatency = deviceInfo->defaultLowInputLatency; } - else if (suggestedLatency == LATENCY_HIGH) + else if ((inputParameters->suggestedLatency == LATENCY_HIGH) + || (inputParameters->suggestedLatency == 0)) { inputParameters->suggestedLatency = deviceInfo->defaultHighInputLatency; @@ -950,15 +581,13 @@ PortAudio_fixOutputParametersSuggestedLatency( if (deviceInfo) { - PaTime suggestedLatency = outputParameters->suggestedLatency; - - if ((suggestedLatency == LATENCY_LOW) - || (suggestedLatency == LATENCY_UNSPECIFIED)) + if (outputParameters->suggestedLatency == LATENCY_LOW) { outputParameters->suggestedLatency = deviceInfo->defaultLowOutputLatency; } - else if (suggestedLatency == LATENCY_HIGH) + else if ((outputParameters->suggestedLatency == LATENCY_HIGH) + || (outputParameters->suggestedLatency == 0)) { outputParameters->suggestedLatency = deviceInfo->defaultHighOutputLatency; @@ -998,7 +627,8 @@ static void PortAudio_throwException(JNIEnv *env, PaError errorCode) { jclass clazz - = (*env)->FindClass( + = (*env) + ->FindClass( env, "net/java/sip/communicator/impl/neomedia/portaudio/PortAudioException"); @@ -1006,105 +636,9 @@ PortAudio_throwException(JNIEnv *env, PaError errorCode) (*env)->ThrowNew(env, clazz, Pa_GetErrorText(errorCode)); } -/** - * Allocates (and initializes) the memory and its associated variables for a - * specific buffer to be used by the pseudo-blocking stream interface - * implementation of a PortAudioStream. - * - * @param capacity the number of bytes to be allocated to the buffer - * @param bufferPtr a pointer which specifies where the location of the - * allocated buffer is to be stored - * @param bufferLengthPtr a pointer which specifies where the initial length - * (i.e. zero) is to be stored - * @param bufferCapacityPtr a pointer which specifies where the capacity of the - * allocated buffer is to be stored - * @param bufferMutexPtr a pointer which specifies where the Mute to - * synchronize the access to the allocated buffer is to be stored - * @param bufferCondVarPtr a pointer which specifies where the - * ConditionVariable to synchronize the access to the allocated buffer - * is to be stored - * @return the location of the allocated buffer upon success; otherwise, - * NULL - */ -static void * -PortAudioStream_allocPseudoBlockingBuffer - (size_t capacity, - void **bufferPtr, size_t *bufferLengthPtr, size_t *bufferCapacityPtr, - Mutex **bufferMutexPtr, ConditionVariable **bufferCondVarPtr) -{ - void *buffer = malloc(capacity); - - if (buffer) - { - Mutex *mutex = Mutex_new(NULL); - - if (mutex) - { - ConditionVariable *condVar = ConditionVariable_new(NULL); - - if (condVar) - { - if (bufferPtr) - *bufferPtr = buffer; - if (bufferLengthPtr) - *bufferLengthPtr = 0; - if (bufferCapacityPtr) - *bufferCapacityPtr = capacity; - *bufferMutexPtr = mutex; - *bufferCondVarPtr = condVar; - } - else - { - Mutex_free(mutex); - free(buffer); - buffer = NULL; - } - } - else - { - free(buffer); - buffer = NULL; - } - } - return buffer; -} - -static void -PortAudioStream_free(JNIEnv *env, PortAudioStream *stream) -{ - if (stream->streamCallback) - (*env)->DeleteGlobalRef(env, stream->streamCallback); - - if (stream->inputMutex && !Mutex_lock(stream->inputMutex)) - { - if (stream->input) - free(stream->input); - ConditionVariable_free(stream->inputCondVar); - Mutex_unlock(stream->inputMutex); - Mutex_free(stream->inputMutex); - } - - if (stream->outputMutex && !Mutex_lock(stream->outputMutex)) - { - if (stream->output) - free(stream->output); - ConditionVariable_free(stream->outputCondVar); - Mutex_unlock(stream->outputMutex); - Mutex_free(stream->outputMutex); - } - - if (stream->audioQualityImprovement) - AudioQualityImprovement_release(stream->audioQualityImprovement); - - if (stream->mutex) - Mutex_free(stream->mutex); - - free(stream); -} - static int -PortAudioStream_javaCallback - (const void *input, +PortAudioStream_callback( + const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, @@ -1136,7 +670,8 @@ PortAudioStream_javaCallback = (*env)->GetObjectClass(env, streamCallback); streamCallbackMethodID - = (*env)->GetMethodID( + = (*env) + ->GetMethodID( env, streamCallbackClass, "callback", @@ -1148,18 +683,21 @@ PortAudioStream_javaCallback } return - (*env)->CallIntMethod( + (*env) + ->CallIntMethod( env, streamCallback, streamCallbackMethodID, input - ? (*env)->NewDirectByteBuffer( + ? (*env) + ->NewDirectByteBuffer( env, (void *) input, frameCount * stream->inputFrameSize) : NULL, output - ? (*env)->NewDirectByteBuffer( + ? (*env) + ->NewDirectByteBuffer( env, output, frameCount * stream->outputFrameSize) @@ -1167,7 +705,7 @@ PortAudioStream_javaCallback } static void -PortAudioStream_javaFinishedCallback(void *userData) +PortAudioStream_finishedCallback(void *userData) { PortAudioStream *stream = (PortAudioStream *) userData; jobject streamCallback = stream->streamCallback; @@ -1194,7 +732,8 @@ PortAudioStream_javaFinishedCallback(void *userData) = (*env)->GetObjectClass(env, streamCallback); streamFinishedCallbackMethodID - = (*env)->GetMethodID( + = (*env) + ->GetMethodID( env, streamCallbackClass, "finishedCallback", @@ -1209,10 +748,22 @@ PortAudioStream_javaFinishedCallback(void *userData) (*env)->CallVoidMethod(env, streamCallback, streamFinishedCallbackMethodID); } +static void +PortAudioStream_free(JNIEnv *env, PortAudioStream *stream) +{ + if (stream->streamCallback) + (*env)->DeleteGlobalRef(env, stream->streamCallback); + + if (stream->audioQualityImprovement) + AudioQualityImprovement_release(stream->audioQualityImprovement); + + free(stream); +} + static PortAudioStream * PortAudioStream_new(JNIEnv *env, jobject streamCallback) { - PortAudioStream *stream = calloc(1, sizeof(PortAudioStream)); + PortAudioStream *stream = malloc(sizeof(PortAudioStream)); if (!stream) { @@ -1237,148 +788,17 @@ PortAudioStream_new(JNIEnv *env, jobject streamCallback) return NULL; } } - - return stream; -} - -static void -PortAudioStream_popFromPseudoBlockingBuffer - (void *buffer, size_t length, size_t *bufferLengthPtr) -{ - size_t i; - size_t newLength = *bufferLengthPtr - length; - jbyte *oldBuffer = (jbyte *) buffer; - jbyte *newBuffer = ((jbyte *) buffer) + length; - - for (i = 0; i < newLength; i++) - *oldBuffer++ = *newBuffer++; - *bufferLengthPtr = newLength; -} - -static int -PortAudioStream_pseudoBlockingCallback - (const void *input, - void *output, - unsigned long frameCount, - const PaStreamCallbackTimeInfo *timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData) -{ - PortAudioStream *stream = (PortAudioStream *) userData; - - if (input && stream->inputMutex && !Mutex_lock(stream->inputMutex)) - { - size_t inputLength = frameCount * stream->inputFrameSize; - size_t newInputLength; - void *inputInStream; - - /* - * Remember the specified input so that it can be retrieved later on in - * our pseudo-blocking Pa_ReadStream(). - */ - newInputLength = stream->inputLength + inputLength; - if (newInputLength > stream->inputCapacity) - { - PortAudioStream_popFromPseudoBlockingBuffer( - stream->input, - newInputLength - stream->inputCapacity, - &(stream->inputLength)); - } - inputInStream = ((jbyte *) (stream->input)) + stream->inputLength; - memcpy(inputInStream, input, inputLength); - stream->inputLength += inputLength; - - ConditionVariable_notify(stream->inputCondVar); - Mutex_unlock(stream->inputMutex); - } - if (output && stream->outputMutex && !Mutex_lock(stream->outputMutex)) - { - size_t outputLength = frameCount * stream->outputFrameSize; - size_t availableOutputLength = outputLength; - - if (availableOutputLength > stream->outputLength) - availableOutputLength = stream->outputLength; - memcpy(output, stream->output, availableOutputLength); - PortAudioStream_popFromPseudoBlockingBuffer( - stream->output, - availableOutputLength, - &(stream->outputLength)); - if (availableOutputLength < outputLength) - { - memset( - ((jbyte *) output) + availableOutputLength, - 0, - outputLength - availableOutputLength); - } - - ConditionVariable_notify(stream->outputCondVar); - Mutex_unlock(stream->outputMutex); - } - return paContinue; -} - -static void -PortAudioStream_pseudoBlockingFinishedCallback(void *userData) -{ - PortAudioStream *stream = (PortAudioStream *) userData; - - if (!Mutex_lock(stream->mutex)) - { - stream->finished = JNI_TRUE; - if (stream->inputMutex && !Mutex_lock(stream->inputMutex)) - { - ConditionVariable_notify(stream->inputCondVar); - Mutex_unlock(stream->inputMutex); - } - if (stream->outputMutex && !Mutex_lock(stream->outputMutex)) - { - ConditionVariable_notify(stream->outputCondVar); - Mutex_unlock(stream->outputMutex); - } - Mutex_unlock(stream->mutex); - } - PortAudioStream_release(stream); -} - -static void -PortAudioStream_release(PortAudioStream *stream) -{ - if (!Mutex_lock(stream->mutex)) - { - --(stream->retainCount); - if (stream->retainCount < 1) - { - Mutex_unlock(stream->mutex); - PortAudioStream_free(NULL, stream); - } - else - Mutex_unlock(stream->mutex); - } -} - -static void -PortAudioStream_retain(PortAudioStream *stream) -{ - if (!Mutex_lock(stream->mutex)) + else { - ++(stream->retainCount); - Mutex_unlock(stream->mutex); + stream->vm = NULL; + stream->streamCallback = NULL; } -} -/** - * Returns the current time in milliseconds (akin to - * java.lang.System#currentTimeMillis()). - * - * @return the current time in milliseconds - */ -static jlong -System_currentTimeMillis() -{ - struct timeval tv; + stream->audioQualityImprovement = NULL; + stream->env = NULL; + stream->stream = NULL; + stream->streamCallbackMethodID = NULL; + stream->streamFinishedCallbackMethodID = NULL; - return - (gettimeofday(&tv, NULL) == 0) - ? ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)) - : -1; + return stream; } diff --git a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h index c0da0274e..cf2b4d9bd 100644 --- a/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h +++ b/src/native/portaudio/net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.h @@ -221,6 +221,14 @@ JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_Po JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels (JNIEnv *, jclass, jlong); +/* + * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio + * Method: PaDeviceInfo_getName + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getName + (JNIEnv *, jclass, jlong); + /* * Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio * Method: PaDeviceInfo_getNameBytes