mirror of https://github.com/sipwise/jitsi.git
- Prevents a NullPointerException in ice4j's Connector#stop() which appears quite often with unknown side effects.
- Prevents a NullPointerException in ToolsMenu related to the Jitsi VideoBridge menu item which causes of long chain of other exceptions and, eventually, prevents the application from completing its startup. - Moves the C source code of JNI PortAudio library from Jitsi/net.java.sip.communicator to libjitsi/org.jitsi. Removes a couple of Java method and C function implementations each of which repeats three times. Fixes possible cases of leaving native callback threads which have been attached to the JVM in undetermined states.cusax-fix
parent
f00ac9fb21
commit
afb27d05c3
Binary file not shown.
@ -1,911 +0,0 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
|
||||
#define AUDIO_QUALITY_IMPROVEMENT_IMPLEMENTATION
|
||||
#include "AudioQualityImprovement.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define MIN_SOUND_PRESSURE_LEVEL 40
|
||||
#define MAX_SOUND_PRESSURE_LEVEL 85
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param samples
|
||||
* @param count the number of samples specified in <tt>samples</tt>
|
||||
* @return the sound pressure level in dB of the specified <tt>samples</tt>
|
||||
*/
|
||||
static float AudioQualityImprovement_calculateSoundPressureLevel
|
||||
(AudioQualityImprovement *aqi, spx_int16_t *samples, spx_uint32_t count);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param buffer
|
||||
* @param length the length of <tt>buffer</tt> in bytes
|
||||
* @return the sound pressure level in dB of the playback which has been matched
|
||||
* to the specified capture <tt>buffer</tt> for the purposes of echo
|
||||
* cancellation if echo suppression is enabled; otherwise, <tt>0</tt>
|
||||
*/
|
||||
static float AudioQualityImprovement_cancelEchoFromPlay
|
||||
(AudioQualityImprovement *aqi,
|
||||
void *buffer, unsigned long length);
|
||||
static void AudioQualityImprovement_free(AudioQualityImprovement *aqi);
|
||||
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);
|
||||
static void AudioQualityImprovement_setFrameSize
|
||||
(AudioQualityImprovement *aqi, jint frameSize);
|
||||
static void AudioQualityImprovement_setInputLatency
|
||||
(AudioQualityImprovement *aqi, jlong inputLatency);
|
||||
static void AudioQualityImprovement_setOutputLatency
|
||||
(AudioQualityImprovement *aqi, jlong outputLatency);
|
||||
static void AudioQualityImprovement_suppressEcho
|
||||
(AudioQualityImprovement *aqi,
|
||||
spx_int16_t *buffer, spx_uint32_t length,
|
||||
float spl);
|
||||
|
||||
/**
|
||||
* Updates the indicator of the specified <tt>AudioQualityImprovement</tt> which
|
||||
* determines whether <tt>AudioQualityImprovement#play</tt> delays the access to
|
||||
* it from <tt>AudioQualityImprovement#echo</tt>.
|
||||
*
|
||||
* @param aqi the <tt>AudioQualityImprovement</tt> of which to update the
|
||||
* indicator which determines whether <tt>AudioQualityImprovement#play</tt>
|
||||
* delays the access to it from <tt>AudioQualityImprovement#echo</tt>
|
||||
*/
|
||||
static void AudioQualityImprovement_updatePlayDelay
|
||||
(AudioQualityImprovement *aqi);
|
||||
static void AudioQualityImprovement_updatePlayIsDelaying
|
||||
(AudioQualityImprovement *aqi);
|
||||
static void AudioQualityImprovement_updatePreprocess
|
||||
(AudioQualityImprovement *aqi);
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds (akin to
|
||||
* <tt>java.lang.System#currentTimeMillis()</tt>).
|
||||
*
|
||||
* @return the current time in milliseconds
|
||||
*/
|
||||
static jlong System_currentTimeMillis();
|
||||
|
||||
static Mutex *AudioQualityImprovement_sharedInstancesMutex = NULL;
|
||||
static AudioQualityImprovement *AudioQualityImprovement_sharedInstances = NULL;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param samples
|
||||
* @param count the number of samples specified in <tt>samples</tt>
|
||||
* @return the sound pressure level in dB of the specified <tt>samples</tt>
|
||||
*/
|
||||
static float
|
||||
AudioQualityImprovement_calculateSoundPressureLevel
|
||||
(AudioQualityImprovement *aqi, spx_int16_t *samples, spx_uint32_t count)
|
||||
{
|
||||
spx_uint32_t i;
|
||||
float rms;
|
||||
float spl;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
rms = 0;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
float sample = samples[i] / (float) SHRT_MAX;
|
||||
|
||||
rms += sample * sample;
|
||||
}
|
||||
rms = sqrtf(rms / count);
|
||||
|
||||
spl = (rms > 0) ? 20 * log10f(rms / 0.00002) : -MAX_SOUND_PRESSURE_LEVEL;
|
||||
return spl;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param buffer
|
||||
* @param length the length of <tt>buffer</tt> in bytes
|
||||
* @return the sound pressure level in dB of the playback which has been matched
|
||||
* to the specified capture <tt>buffer</tt> for the purposes of echo
|
||||
* cancellation if echo suppression is enabled; otherwise, <tt>0</tt>
|
||||
*/
|
||||
static float
|
||||
AudioQualityImprovement_cancelEchoFromPlay
|
||||
(AudioQualityImprovement *aqi,
|
||||
void *buffer, unsigned long length)
|
||||
{
|
||||
spx_uint32_t sampleCount;
|
||||
float spl;
|
||||
|
||||
if (aqi->playIsDelaying == JNI_TRUE)
|
||||
return 0;
|
||||
|
||||
sampleCount = length / sizeof(spx_int16_t);
|
||||
if (aqi->playLength < sampleCount)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Ensure that out exists and is large enough to receive the result of the
|
||||
* echo cancellation.
|
||||
*/
|
||||
if (!(aqi->out) || (aqi->outCapacity < length))
|
||||
{
|
||||
spx_int16_t *newOut = realloc(aqi->out, length);
|
||||
|
||||
if (newOut)
|
||||
{
|
||||
aqi->out = newOut;
|
||||
aqi->outCapacity = length;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform the echo cancellation and return the result in buffer. */
|
||||
speex_echo_cancellation(aqi->echo, buffer, aqi->play, aqi->out);
|
||||
memcpy(buffer, aqi->out, length);
|
||||
|
||||
/*
|
||||
* Calculate the sound pressure level in dB to be returned (if echo
|
||||
* suppression is enabled and, thus, needs it).
|
||||
*/
|
||||
spl
|
||||
= (JNI_TRUE == aqi->suppressEcho)
|
||||
? AudioQualityImprovement_calculateSoundPressureLevel(
|
||||
aqi,
|
||||
aqi->play, sampleCount)
|
||||
: 0;
|
||||
|
||||
AudioQualityImprovement_popFromPlay(aqi, sampleCount);
|
||||
|
||||
return spl;
|
||||
}
|
||||
|
||||
static void
|
||||
AudioQualityImprovement_free(AudioQualityImprovement *aqi)
|
||||
{
|
||||
/* mutex */
|
||||
Mutex_free(aqi->mutex);
|
||||
/* preprocess */
|
||||
if (aqi->preprocess)
|
||||
speex_preprocess_state_destroy(aqi->preprocess);
|
||||
/* echo */
|
||||
if (aqi->echo)
|
||||
speex_echo_state_destroy(aqi->echo);
|
||||
/* out */
|
||||
if (aqi->out)
|
||||
free(aqi->out);
|
||||
/* play */
|
||||
if (aqi->play)
|
||||
free(aqi->play);
|
||||
/* resampler */
|
||||
if (aqi->resampler)
|
||||
speex_resampler_destroy(aqi->resampler);
|
||||
/* stringID */
|
||||
free(aqi->stringID);
|
||||
|
||||
free(aqi);
|
||||
}
|
||||
|
||||
AudioQualityImprovement *
|
||||
AudioQualityImprovement_getSharedInstance(const char *stringID, jlong longID)
|
||||
{
|
||||
AudioQualityImprovement *theSharedInstance = NULL;
|
||||
|
||||
if (!Mutex_lock(AudioQualityImprovement_sharedInstancesMutex))
|
||||
{
|
||||
AudioQualityImprovement *aSharedInstance
|
||||
= AudioQualityImprovement_sharedInstances;
|
||||
|
||||
while (aSharedInstance)
|
||||
{
|
||||
if ((aSharedInstance->longID == longID)
|
||||
&& ((aSharedInstance->stringID == stringID)
|
||||
|| (0 == strcmp(aSharedInstance->stringID, stringID))))
|
||||
{
|
||||
theSharedInstance = aSharedInstance;
|
||||
break;
|
||||
}
|
||||
aSharedInstance = aSharedInstance->next;
|
||||
}
|
||||
if (theSharedInstance)
|
||||
AudioQualityImprovement_retain(theSharedInstance);
|
||||
else
|
||||
{
|
||||
theSharedInstance
|
||||
= AudioQualityImprovement_new(
|
||||
stringID,
|
||||
longID,
|
||||
AudioQualityImprovement_sharedInstances);
|
||||
if (theSharedInstance)
|
||||
AudioQualityImprovement_sharedInstances = theSharedInstance;
|
||||
}
|
||||
Mutex_unlock(AudioQualityImprovement_sharedInstancesMutex);
|
||||
}
|
||||
return theSharedInstance;
|
||||
}
|
||||
|
||||
/** Loads the <tt>AudioQualityImprovement</tt> 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));
|
||||
|
||||
if (aqi)
|
||||
{
|
||||
/* stringID */
|
||||
size_t slen = strlen(stringID);
|
||||
aqi->stringID = malloc(slen + 1);
|
||||
|
||||
if (!(aqi->stringID))
|
||||
{
|
||||
AudioQualityImprovement_free(aqi);
|
||||
return NULL;
|
||||
}
|
||||
strncpy(aqi->stringID, stringID, slen);
|
||||
aqi->stringID[slen] = 0x00;
|
||||
|
||||
/* mutex */
|
||||
aqi->mutex = Mutex_new(NULL);
|
||||
if (!(aqi->mutex))
|
||||
{
|
||||
AudioQualityImprovement_free(aqi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aqi->inputLatency = -1;
|
||||
aqi->longID = longID;
|
||||
aqi->next = next;
|
||||
aqi->outputLatency = -1;
|
||||
aqi->retainCount = 1;
|
||||
aqi->suppressEcho = JNI_TRUE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param sampleOrigin
|
||||
* @param sampleRate
|
||||
* @param sampleSizeInBits
|
||||
* @param channels
|
||||
* @param latency the latency of the stream associated with <tt>buffer</tt> in
|
||||
* milliseconds
|
||||
* @param buffer
|
||||
* @param length the length of <tt>buffer</tt> in bytes
|
||||
*/
|
||||
void
|
||||
AudioQualityImprovement_process
|
||||
(AudioQualityImprovement *aqi,
|
||||
AudioQualityImprovementSampleOrigin sampleOrigin,
|
||||
double sampleRate, unsigned long sampleSizeInBits, int channels,
|
||||
jlong latency,
|
||||
void *buffer, unsigned long length)
|
||||
{
|
||||
if ((sampleSizeInBits == 16) && (channels == 1) && !Mutex_lock(aqi->mutex))
|
||||
{
|
||||
switch (sampleOrigin)
|
||||
{
|
||||
case AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_INPUT:
|
||||
if (sampleRate == aqi->sampleRate)
|
||||
{
|
||||
AudioQualityImprovement_setFrameSize(aqi, length);
|
||||
if (aqi->preprocess)
|
||||
{
|
||||
float spl;
|
||||
jboolean suppressEcho;
|
||||
|
||||
AudioQualityImprovement_setInputLatency(aqi, latency);
|
||||
|
||||
if (aqi->echo && aqi->play && aqi->playLength)
|
||||
{
|
||||
spl
|
||||
= AudioQualityImprovement_cancelEchoFromPlay(
|
||||
aqi,
|
||||
buffer, length);
|
||||
suppressEcho = aqi->suppressEcho;
|
||||
}
|
||||
else
|
||||
{
|
||||
spl = 0;
|
||||
/*
|
||||
* Let the echo suppression fade out if it's enabled and
|
||||
* there hasn't been recent playback.
|
||||
*/
|
||||
suppressEcho
|
||||
= (aqi->suppressEcho && !(aqi->playLength))
|
||||
? JNI_TRUE
|
||||
: JNI_FALSE;
|
||||
}
|
||||
|
||||
speex_preprocess_run(aqi->preprocess, buffer);
|
||||
|
||||
if (JNI_TRUE == suppressEcho)
|
||||
AudioQualityImprovement_suppressEcho(
|
||||
aqi,
|
||||
buffer, length / sizeof(spx_int16_t),
|
||||
spl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_QUALITY_IMPROVEMENT_SAMPLE_ORIGIN_OUTPUT:
|
||||
if (aqi->preprocess && aqi->echo)
|
||||
{
|
||||
AudioQualityImprovement_setOutputLatency(aqi, latency);
|
||||
AudioQualityImprovement_resampleInPlay(
|
||||
aqi,
|
||||
sampleRate, sampleSizeInBits, channels,
|
||||
buffer, length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioQualityImprovement_release(AudioQualityImprovement *aqi)
|
||||
{
|
||||
if (!Mutex_lock(AudioQualityImprovement_sharedInstancesMutex))
|
||||
{
|
||||
if (!Mutex_lock(aqi->mutex))
|
||||
{
|
||||
--(aqi->retainCount);
|
||||
if (aqi->retainCount < 1)
|
||||
{
|
||||
if (aqi == AudioQualityImprovement_sharedInstances)
|
||||
{
|
||||
AudioQualityImprovement_sharedInstances
|
||||
= AudioQualityImprovement_sharedInstances->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioQualityImprovement *prevSharedInstance
|
||||
= AudioQualityImprovement_sharedInstances;
|
||||
|
||||
while (prevSharedInstance)
|
||||
{
|
||||
AudioQualityImprovement *nextSharedInstance
|
||||
= prevSharedInstance->next;
|
||||
|
||||
if (aqi == nextSharedInstance)
|
||||
{
|
||||
prevSharedInstance->next = aqi->next;
|
||||
break;
|
||||
}
|
||||
prevSharedInstance = nextSharedInstance;
|
||||
}
|
||||
}
|
||||
|
||||
Mutex_unlock(aqi->mutex);
|
||||
AudioQualityImprovement_free(aqi);
|
||||
}
|
||||
else
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
Mutex_unlock(AudioQualityImprovement_sharedInstancesMutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param aqi
|
||||
* @param sampleRate
|
||||
* @param sampleSizeInBits
|
||||
* @param channels
|
||||
* @param buffer
|
||||
* @param length the length of <tt>buffer</tt> in bytes
|
||||
*/
|
||||
static void
|
||||
AudioQualityImprovement_resampleInPlay
|
||||
(AudioQualityImprovement *aqi,
|
||||
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)
|
||||
playSize = length;
|
||||
else if (length * aqi->sampleRate == aqi->frameSize * sampleRate)
|
||||
{
|
||||
if (aqi->resampler)
|
||||
{
|
||||
speex_resampler_set_rate(
|
||||
aqi->resampler,
|
||||
(spx_uint32_t) sampleRate, (spx_uint32_t) (aqi->sampleRate));
|
||||
playSize = aqi->frameSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
aqi->resampler
|
||||
= speex_resampler_init(
|
||||
channels,
|
||||
(spx_uint32_t) sampleRate, (spx_uint32_t) (aqi->sampleRate),
|
||||
SPEEX_RESAMPLER_QUALITY_VOIP,
|
||||
NULL);
|
||||
if (aqi->resampler)
|
||||
playSize = aqi->frameSize;
|
||||
else
|
||||
{
|
||||
aqi->playIsDelaying = JNI_TRUE;
|
||||
aqi->playLength = 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;
|
||||
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))
|
||||
{
|
||||
spx_int16_t *newPlay;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
aqi->playIsDelaying = JNI_TRUE;
|
||||
aqi->playLength = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that there is room for buffer in play. */
|
||||
if (aqi->playLength + playLength > aqi->playCapacity)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
speex_resampler_process_interleaved_int(
|
||||
aqi->resampler,
|
||||
buffer, &bufferSampleCount, play, &playLength);
|
||||
}
|
||||
aqi->playLength += playLength;
|
||||
|
||||
/* Take into account the latency. */
|
||||
if (aqi->playIsDelaying == JNI_TRUE)
|
||||
AudioQualityImprovement_updatePlayIsDelaying(aqi);
|
||||
}
|
||||
|
||||
static void
|
||||
AudioQualityImprovement_retain(AudioQualityImprovement *aqi)
|
||||
{
|
||||
if (!Mutex_lock(aqi->mutex))
|
||||
{
|
||||
++(aqi->retainCount);
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indicator which determines whether noise suppression is to be
|
||||
* performed by the specified <tt>AudioQualityImprovement</tt> (for captured
|
||||
* audio).
|
||||
*
|
||||
* @param aqi the <tt>AudioQualityImprovement</tt> on which to set the indicator
|
||||
* which determines whether it is to perform noise suppression (for captured audio)
|
||||
* @param denoise <tt>JNI_TRUE</tt> if the specified <tt>aqi</tt> is to perform
|
||||
* noise suppression (for captured audio); otherwise, <tt>JNI_FALSE</tt>
|
||||
*/
|
||||
void
|
||||
AudioQualityImprovement_setDenoise
|
||||
(AudioQualityImprovement *aqi, jboolean denoise)
|
||||
{
|
||||
if (!Mutex_lock(aqi->mutex))
|
||||
{
|
||||
if (aqi->denoise != denoise)
|
||||
{
|
||||
aqi->denoise = denoise;
|
||||
AudioQualityImprovement_updatePreprocess(aqi);
|
||||
}
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filter length in milliseconds of the echo cancellation
|
||||
* implementation of the specified <tt>AudioQualityImprovement</tt>. 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 <tt>AudioQualityImprovement</tt> to set the filter length of
|
||||
* @param echoFilterLengthInMillis the filter length in milliseconds of the echo
|
||||
* cancellation of <tt>aqi</tt>
|
||||
*/
|
||||
void
|
||||
AudioQualityImprovement_setEchoFilterLengthInMillis
|
||||
(AudioQualityImprovement *aqi, jlong echoFilterLengthInMillis)
|
||||
{
|
||||
if (echoFilterLengthInMillis < 0)
|
||||
echoFilterLengthInMillis = 0;
|
||||
if (!Mutex_lock(aqi->mutex))
|
||||
{
|
||||
if (aqi->echoFilterLengthInMillis != echoFilterLengthInMillis)
|
||||
{
|
||||
aqi->echoFilterLengthInMillis = echoFilterLengthInMillis;
|
||||
AudioQualityImprovement_updatePreprocess(aqi);
|
||||
}
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AudioQualityImprovement_setFrameSize
|
||||
(AudioQualityImprovement *aqi, jint frameSize)
|
||||
{
|
||||
if (aqi->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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioQualityImprovement_setSampleRate
|
||||
(AudioQualityImprovement *aqi, int sampleRate)
|
||||
{
|
||||
if (!Mutex_lock(aqi->mutex))
|
||||
{
|
||||
if (aqi->sampleRate != sampleRate)
|
||||
{
|
||||
aqi->sampleRate = sampleRate;
|
||||
AudioQualityImprovement_updatePlayDelay(aqi);
|
||||
AudioQualityImprovement_updatePreprocess(aqi);
|
||||
}
|
||||
Mutex_unlock(aqi->mutex);
|
||||
}
|
||||
}
|
||||
static void
|
||||
AudioQualityImprovement_suppressEcho
|
||||
(AudioQualityImprovement *aqi,
|
||||
spx_int16_t *buffer, spx_uint32_t length,
|
||||
float spl)
|
||||
{
|
||||
float amplifier;
|
||||
spx_int16_t i;
|
||||
|
||||
if (spl < MIN_SOUND_PRESSURE_LEVEL)
|
||||
spl = MIN_SOUND_PRESSURE_LEVEL;
|
||||
else if (spl > MAX_SOUND_PRESSURE_LEVEL)
|
||||
spl = MAX_SOUND_PRESSURE_LEVEL;
|
||||
|
||||
/* Decay #suppressEchoSPL. */
|
||||
if (aqi->suppressEchoSPLTime
|
||||
&& (aqi->suppressEchoSPL > MIN_SOUND_PRESSURE_LEVEL))
|
||||
{
|
||||
aqi->suppressEchoSPL
|
||||
-= (System_currentTimeMillis() - aqi->suppressEchoSPLTime)
|
||||
* aqi->suppressEchoSPLDecay;
|
||||
if (aqi->suppressEchoSPL <= MIN_SOUND_PRESSURE_LEVEL)
|
||||
{
|
||||
aqi->suppressEchoSPLDecay = 0;
|
||||
aqi->suppressEchoSPLTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (spl < aqi->suppressEchoSPL)
|
||||
spl = aqi->suppressEchoSPL;
|
||||
else
|
||||
{
|
||||
aqi->suppressEchoSPL = spl;
|
||||
aqi->suppressEchoSPLDecay
|
||||
= ((MIN_SOUND_PRESSURE_LEVEL == spl)
|
||||
? 1
|
||||
: (spl - MIN_SOUND_PRESSURE_LEVEL))
|
||||
/ 1000.0;
|
||||
aqi->suppressEchoSPLTime = System_currentTimeMillis();
|
||||
}
|
||||
|
||||
amplifier
|
||||
= 1
|
||||
- (spl - MIN_SOUND_PRESSURE_LEVEL)
|
||||
/ (float) (MAX_SOUND_PRESSURE_LEVEL - MIN_SOUND_PRESSURE_LEVEL);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
buffer[i] = (spx_int16_t) (amplifier * buffer[i]);
|
||||
}
|
||||
|
||||
/** Unloads the <tt>AudioQualityImprovement</tt> 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;
|
||||
}
|
||||
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 <tt>AudioQualityImprovement</tt> which
|
||||
* determines whether <tt>AudioQualityImprovement#play</tt> delays the access to
|
||||
* it from <tt>AudioQualityImprovement#echo</tt>.
|
||||
*
|
||||
* @param aqi the <tt>AudioQualityImprovement</tt> of which to update the
|
||||
* indicator which determines whether <tt>AudioQualityImprovement#play</tt>
|
||||
* delays the access to it from <tt>AudioQualityImprovement#echo</tt>
|
||||
*/
|
||||
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)
|
||||
{
|
||||
if (aqi->echo)
|
||||
{
|
||||
int frameSize = 0;
|
||||
|
||||
if ((aqi->echoFilterLengthInMillis > 0)
|
||||
&& (aqi->sampleRate > 0)
|
||||
&& speex_echo_ctl(
|
||||
aqi->echo,
|
||||
SPEEX_ECHO_GET_FRAME_SIZE, &frameSize))
|
||||
frameSize = 0;
|
||||
if (frameSize
|
||||
&& (aqi->frameSize
|
||||
== (frameSize * (16 /* sampleSizeInBits */ / 8))))
|
||||
{
|
||||
int echoFilterLength
|
||||
= (int)
|
||||
((aqi->sampleRate * aqi->echoFilterLengthInMillis)
|
||||
/ 1000);
|
||||
|
||||
if (aqi->filterLengthOfEcho != echoFilterLength)
|
||||
frameSize = 0;
|
||||
}
|
||||
else
|
||||
frameSize = 0;
|
||||
if (frameSize < 1)
|
||||
{
|
||||
if (aqi->preprocess)
|
||||
{
|
||||
speex_preprocess_ctl(
|
||||
aqi->preprocess,
|
||||
SPEEX_PREPROCESS_SET_ECHO_STATE, NULL);
|
||||
}
|
||||
speex_echo_state_destroy(aqi->echo);
|
||||
aqi->echo = NULL;
|
||||
}
|
||||
}
|
||||
if (aqi->preprocess
|
||||
&& ((aqi->frameSize != aqi->frameSizeOfPreprocess)
|
||||
|| (aqi->sampleRate != aqi->sampleRateOfPreprocess)))
|
||||
{
|
||||
speex_preprocess_state_destroy(aqi->preprocess);
|
||||
aqi->preprocess = NULL;
|
||||
}
|
||||
if ((aqi->frameSize > 0) && (aqi->sampleRate > 0))
|
||||
{
|
||||
if (aqi->echoFilterLengthInMillis > 0)
|
||||
{
|
||||
if (!(aqi->echo))
|
||||
{
|
||||
int echoFrameSize
|
||||
= aqi->frameSize / (16 /* sampleSizeInBits */ / 8);
|
||||
int echoFilterLength
|
||||
= (int)
|
||||
((aqi->sampleRate * aqi->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);
|
||||
}
|
||||
if (aqi->echo)
|
||||
{
|
||||
speex_echo_ctl(
|
||||
aqi->echo,
|
||||
SPEEX_ECHO_SET_SAMPLING_RATE, &(aqi->sampleRate));
|
||||
}
|
||||
}
|
||||
if (aqi->denoise || aqi->echo)
|
||||
{
|
||||
if (!(aqi->preprocess))
|
||||
{
|
||||
aqi->preprocess
|
||||
= speex_preprocess_state_init(
|
||||
aqi->frameSize / (16 /* sampleSizeInBits */ / 8),
|
||||
aqi->sampleRate);
|
||||
aqi->frameSizeOfPreprocess = aqi->frameSize;
|
||||
aqi->sampleRateOfPreprocess = aqi->sampleRate;
|
||||
if (aqi->preprocess)
|
||||
{
|
||||
int on = 1;
|
||||
|
||||
speex_preprocess_ctl(
|
||||
aqi->preprocess,
|
||||
SPEEX_PREPROCESS_SET_DEREVERB, &on);
|
||||
speex_preprocess_ctl(
|
||||
aqi->preprocess,
|
||||
SPEEX_PREPROCESS_SET_VAD, &on);
|
||||
}
|
||||
}
|
||||
if (aqi->preprocess)
|
||||
{
|
||||
int denoise = (aqi->denoise == JNI_TRUE) ? 1 : 0;
|
||||
|
||||
speex_preprocess_ctl(
|
||||
aqi->preprocess,
|
||||
SPEEX_PREPROCESS_SET_DENOISE, &denoise);
|
||||
if (aqi->echo)
|
||||
{
|
||||
speex_preprocess_ctl(
|
||||
aqi->preprocess,
|
||||
SPEEX_PREPROCESS_SET_ECHO_STATE, aqi->echo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time in milliseconds (akin to
|
||||
* <tt>java.lang.System#currentTimeMillis()</tt>).
|
||||
*
|
||||
* @return the current time in milliseconds
|
||||
*/
|
||||
static jlong
|
||||
System_currentTimeMillis()
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
return
|
||||
(gettimeofday(&tv, NULL) == 0)
|
||||
? ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))
|
||||
: -1;
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Jitsi, 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_AUDIOQUALITYIMPROVEMENT_H_
|
||||
#define _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_AUDIOQUALITYIMPROVEMENT_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
#ifndef AUDIO_QUALITY_IMPROVEMENT_IMPLEMENTATION
|
||||
typedef void *AudioQualityImprovement;
|
||||
#else /* #ifndef AUDIO_QUALITY_IMPROVEMENT_IMPLEMENTATION */
|
||||
|
||||
#include "Mutex.h"
|
||||
#include <speex/speex_echo.h>
|
||||
#include <speex/speex_preprocess.h>
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
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 <tt>buffer</tt> 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;
|
||||
SpeexPreprocessState *preprocess;
|
||||
SpeexResamplerState *resampler;
|
||||
int retainCount;
|
||||
int sampleRate;
|
||||
int sampleRateOfPreprocess;
|
||||
char *stringID;
|
||||
|
||||
/** The indicator which determines whether echo suppression is enabled. */
|
||||
jboolean suppressEcho;
|
||||
|
||||
/**
|
||||
* The sound pressure level in dB depending on which the echo suppression,
|
||||
* if enabled, decreases the sound volume of the captured oudio.
|
||||
*/
|
||||
float suppressEchoSPL;
|
||||
|
||||
/** The decay in dB per millisecond of #suppressEchoSPL. */
|
||||
float suppressEchoSPLDecay;
|
||||
|
||||
/**
|
||||
* The time in milliseconds at which #suppressEchoSPL has last been assigned
|
||||
* a value and thus determines how much #suppressEchoSPLDecay is to be
|
||||
* applied to #suppressEchoSPL at a certain point in time.
|
||||
*/
|
||||
jlong suppressEchoSPLTime;
|
||||
} 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 <tt>AudioQualityImprovement</tt> class. */
|
||||
void AudioQualityImprovement_load();
|
||||
void AudioQualityImprovement_process
|
||||
(AudioQualityImprovement *aqi,
|
||||
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 <tt>AudioQualityImprovement</tt> (for captured
|
||||
* audio).
|
||||
*
|
||||
* @param aqi the <tt>AudioQualityImprovement</tt> on which to set the indicator
|
||||
* which determines whether it is to perform noise suppression (for captured audio)
|
||||
* @param denoise <tt>JNI_TRUE</tt> if the specified <tt>aqi</tt> is to perform
|
||||
* noise suppression (for captured audio); otherwise, <tt>JNI_FALSE</tt>
|
||||
*/
|
||||
void AudioQualityImprovement_setDenoise
|
||||
(AudioQualityImprovement *aqi, jboolean denoise);
|
||||
|
||||
/**
|
||||
* Sets the filter length in milliseconds of the echo cancellation
|
||||
* implementation of the specified <tt>AudioQualityImprovement</tt>. 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 <tt>AudioQualityImprovement</tt> to set the filter length of
|
||||
* @param echoFilterLengthInMillis the filter length in milliseconds of the echo
|
||||
* cancellation of <tt>aqi</tt>
|
||||
*/
|
||||
void AudioQualityImprovement_setEchoFilterLengthInMillis
|
||||
(AudioQualityImprovement *aqi, jlong echoFilterLengthInMillis);
|
||||
void AudioQualityImprovement_setSampleRate
|
||||
(AudioQualityImprovement *aqi, int sampleRate);
|
||||
|
||||
/** Unloads the <tt>AudioQualityImprovement</tt> class. */
|
||||
void AudioQualityImprovement_unload();
|
||||
|
||||
#endif /* #ifndef _NET_JAVA_SIP_COMMUNICATOR_IMPL_NEOMEDIA_PORTAUDIO_AUDIOQUALITYIMPROVEMENT_H_ */
|
||||
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Jitsi, 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 <windows.h>
|
||||
|
||||
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 <pthread.h>
|
||||
|
||||
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_ */
|
||||
@ -1,50 +0,0 @@
|
||||
PORTAUDIO_HOME?=../../../../portaudio-20101214
|
||||
SPEEX_HOME?=../../../../speex-1.2rc1
|
||||
|
||||
CC=gcc
|
||||
TARGET_BASENAME=jnportaudio
|
||||
|
||||
OS=$(shell $(CC) -dumpmachine | sed -e s/.*-apple-.*/mac/ -e s/.*-linux-.*/linux/ -e s/.*-.*-mingw32/windows/)
|
||||
ifeq "$(OS)" "mac"
|
||||
JAVA_HOME?=/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.5
|
||||
CC:=$(CC) -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.4
|
||||
CPPFLAGS=-I$(JAVA_HOME)/Headers
|
||||
LDFLAGS=-dynamiclib
|
||||
LIBS=-framework AudioToolbox -framework AudioUnit -framework CoreAudio -framework Carbon \
|
||||
-lpthread -pthread -lm -dynamic -lportaudio -lspeexdsp
|
||||
TARGET=../../../lib/native/mac/lib$(TARGET_BASENAME).jnilib
|
||||
else
|
||||
ARCH=$(shell $(CC) -dumpmachine | sed -e s/x86_64-.*/-64/ -e s/i.86-.*//)
|
||||
LDFLAGS=-shared
|
||||
ifeq "$(OS)" "linux"
|
||||
JAVA_HOME?=/usr/lib/jvm/java-6-sun
|
||||
CPPFLAGS=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
|
||||
LIBS=-Wl,-Bstatic -lportaudio -lspeexdsp -Wl,-Bdynamic -lrt -lasound -lm -lpthread
|
||||
TARGET=../../../lib/native/$(OS)$(ARCH)/lib$(TARGET_BASENAME).so
|
||||
else ifeq "$(OS)" "windows"
|
||||
DXSDK_HOME?=/c/Users/lyubomir/Downloads/DXSDK_Jun10
|
||||
ifeq "$(ARCH)" "-64"
|
||||
JAVA_HOME?=C:/PROGRA~1/jdk
|
||||
LIBS=-L$(DXSDK_HOME)/Lib/x64
|
||||
else
|
||||
JAVA_HOME?=C:/PROGRA~2/jdk
|
||||
LIBS=-L$(DXSDK_HOME)/Lib/x86
|
||||
endif
|
||||
CPPFLAGS=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/win32 -I$(DXSDK_HOME)/Include
|
||||
LDFLAGS:=-Wl,--kill-at $(LDFLAGS)
|
||||
LIBS:=$(LIBS) -static -lportaudio -lspeexdsp -lwinmm -ldsound -lm -lstdc++ -lole32 -luuid
|
||||
TARGET=../../../lib/native/$(OS)$(ARCH)/$(TARGET_BASENAME).dll
|
||||
endif
|
||||
endif
|
||||
|
||||
CPPFLAGS:=-D_JNI_IMPLEMENTATION_ \
|
||||
-I$(SPEEX_HOME)/include -I$(PORTAUDIO_HOME)/include \
|
||||
-O2 \
|
||||
-Wall \
|
||||
$(CPPFLAGS)
|
||||
LDFLAGS:=-fPIC $(LDFLAGS)
|
||||
LIBS:=-L$(PORTAUDIO_HOME)/lib/.libs -L$(SPEEX_HOME)/libspeex/.libs $(LIBS)
|
||||
|
||||
$(TARGET): net_java_sip_communicator_impl_neomedia_portaudio_PortAudio.c AudioQualityImprovement.c
|
||||
$(CC) $(CPPFLAGS) $^ $(LDFLAGS) -o $@ $(LIBS)
|
||||
-strip $(TARGET)
|
||||
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Jitsi, 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 <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
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 <pthread.h>
|
||||
|
||||
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_ */
|
||||
@ -1,40 +0,0 @@
|
||||
1. portaudio
|
||||
|
||||
Get portaudio-hotplug branch and apply the portaudio-hotplug-os patch:
|
||||
$ svn -r 1821 co https://subversion.assembla.com/svn/portaudio/portaudio/branches/hotplug
|
||||
$ patch -p0 < portaudio-hotplug-os.patch
|
||||
$ autoreconf -i (OS X and Linux only)
|
||||
|
||||
- Linux/FreeBSD
|
||||
pa_linux_alsa.c-by-Werner.patch (already in portaudio-hotplug-os.patch)
|
||||
pa_linux_alsa.c-fix-blocked-renderer.patch (already in portaudio-hotplug-os.patch)
|
||||
$ ./configure --disable-shared --enable-static --with-pic --with-jack=no && make/gmake
|
||||
|
||||
- Mac OS X
|
||||
$ export MACOSX_DEPLOYMENT_TARGET=10.4
|
||||
$ ./configure --disable-shared --enable-static --with-pic && make
|
||||
|
||||
- Windows
|
||||
Use msys and mingw (A gui installer, use latest
|
||||
http://sf.net/projects/mingw/files/Installer/mingw-get-inst/ this can
|
||||
only compile 32bit).
|
||||
Download directx devpack for MinGW at http://www.dgrigoriadis.net/post/2004/06/26/DirectXDevPak-for-Dev-Cpp.aspx and
|
||||
extract it. (May neeto to remove the define for WAVEFORMATEXTENSIBLE
|
||||
(#ifndef _WAVEFORMATEXTENSIBLE_ .....) include/ksmedia.h)
|
||||
|
||||
$ DXDIR=/path/to/directx_dev_pack_directory
|
||||
$ CFLAGS="-DWINVER=0x501" ./configure --disable-shared --enable-static --with-pic --with-dxdir=$DXDIR --with-winapi=wmme,directx,wdmks && make
|
||||
|
||||
2. speex
|
||||
- Linux/FreeBSD, Windows
|
||||
$ ./configure --disable-shared --enable-static --with-pic && make/gmake
|
||||
|
||||
- Mac OS X
|
||||
$ export MACOSX_DEPLOYMENT_TARGET=10.4
|
||||
$ export CC="gcc -arch i386 -arch ppc -arch x86_64 -mmacosx-version-min=10.4"
|
||||
$ export CPP="gcc -E"
|
||||
$ ./configure --disable-shared --enable-static --with-pic && make
|
||||
|
||||
3. jportaudio
|
||||
- Linux/FreeBSD, Mac OS X, Windows
|
||||
$ make/gmake
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,323 +0,0 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class net_java_sip_communicator_impl_neomedia_portaudio_PortAudio */
|
||||
|
||||
#ifndef _Included_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
#define _Included_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_HIGH -1.0
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_LOW -2.0
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSPECIFIED
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSPECIFIED 0.0
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: free
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_free
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_AbortStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1AbortStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_CloseStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1CloseStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetDefaultInputDevice
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultInputDevice
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetDefaultOutputDevice
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDefaultOutputDevice
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetDeviceCount
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceCount
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetDeviceInfo
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetDeviceInfo
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetHostApiInfo
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetHostApiInfo
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetSampleSize
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetSampleSize
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetStreamReadAvailable
|
||||
* Signature: (J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamReadAvailable
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_GetStreamWriteAvailable
|
||||
* Signature: (J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1GetStreamWriteAvailable
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_Initialize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1Initialize
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_IsFormatSupported
|
||||
* Signature: (JJD)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1IsFormatSupported
|
||||
(JNIEnv *, jclass, jlong, jlong, jdouble);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_OpenStream
|
||||
* Signature: (JJDJJLnet/java/sip/communicator/impl/neomedia/portaudio/PortAudioStreamCallback;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1OpenStream
|
||||
(JNIEnv *, jclass, jlong, jlong, jdouble, jlong, jlong, jobject);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_ReadStream
|
||||
* Signature: (J[BJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1ReadStream
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_StartStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StartStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_StopStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1StopStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: Pa_WriteStream
|
||||
* Signature: (J[BIJI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jint, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultHighInputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultHighOutputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultLowInputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultLowOutputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultSampleRate
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getHostApi
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getHostApi
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getMaxInputChannels
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getMaxOutputChannels
|
||||
* Signature: (J)I
|
||||
*/
|
||||
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_getNameBytes
|
||||
* Signature: (J)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getNameBytes
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getTransportTypeBytes
|
||||
* Signature: (J)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getTransportTypeBytes
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDeviceUIDBytes
|
||||
* Signature: (J)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaDeviceInfo_1getDeviceUIDBytes
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_getDefaultInputDevice
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1getDefaultInputDevice
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_getDefaultOutputDevice
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1getDefaultOutputDevice
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_getDeviceCount
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1getDeviceCount
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_getName
|
||||
* Signature: (J)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1getName
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_getType
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaHostApiInfo_1getType
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: PaStreamParameters_new
|
||||
* Signature: (IIJD)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_PaStreamParameters_1new
|
||||
(JNIEnv *, jclass, jint, jint, jlong, jdouble);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: setDenoise
|
||||
* Signature: (JZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setDenoise
|
||||
(JNIEnv *, jclass, jlong, jboolean);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: setEchoFilterLengthInMillis
|
||||
* Signature: (JJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setEchoFilterLengthInMillis
|
||||
(JNIEnv *, jclass, jlong, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: updateAvailableDeviceList
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_updateAvailableDeviceList
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -1,71 +0,0 @@
|
||||
--- pa_linux_alsa.c 2009-06-03 21:57:56.000000000 +0300
|
||||
+++ pa_linux_alsa.c 2010-04-22 14:26:41.081552093 +0300
|
||||
@@ -2735,8 +2735,19 @@
|
||||
snd_pcm_sframes_t framesAvail = snd_pcm_avail_update( self->pcm );
|
||||
*xrunOccurred = 0;
|
||||
|
||||
- if( -EPIPE == framesAvail )
|
||||
- {
|
||||
+ /* Get pcm_state and check for xrun condition. On playback I often see
|
||||
+ * xrun but avail_update does not return -EPIPE but framesAvail larger
|
||||
+ * than bufferSize. In case of xrun status set xrun flag, leave framesize
|
||||
+ * as reported by avail_update, will be fixed below. In case avail_update
|
||||
+ * returns -EPIPE process as usual. wd-xxx
|
||||
+ */
|
||||
+ snd_pcm_state_t state = snd_pcm_state( self->pcm ); /* wd-xxx */
|
||||
+ if (state == SND_PCM_STATE_XRUN) {
|
||||
+ // printf("xrun, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
|
||||
+ *xrunOccurred = 1;
|
||||
+ }
|
||||
+ if( -EPIPE == framesAvail) {
|
||||
+ // printf("xrun-1, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
|
||||
*xrunOccurred = 1;
|
||||
framesAvail = 0;
|
||||
}
|
||||
@@ -2745,6 +2756,11 @@
|
||||
ENSURE_( framesAvail, paUnanticipatedHostError );
|
||||
}
|
||||
|
||||
+ /* Fix frames avail, should not be bigger than bufferSize wd-xxx */
|
||||
+ if (framesAvail > self->bufferSize) {
|
||||
+ // printf("xrun-2, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
|
||||
+ framesAvail = self->bufferSize;
|
||||
+ }
|
||||
*numFrames = framesAvail;
|
||||
|
||||
error:
|
||||
@@ -3457,9 +3472,24 @@
|
||||
while( frames > 0 )
|
||||
{
|
||||
int xrun = 0;
|
||||
- PA_ENSURE( PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun ) );
|
||||
- framesGot = PA_MIN( framesAvail, frames );
|
||||
+ PA_ENSURE( PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun ) );
|
||||
+ /*
|
||||
+ * In case of overrun WaitForFrames leaves the capture stream in STATE_PREPARED
|
||||
+ * most of the time. handleXrun() restarts the ALSA stream only in case
|
||||
+ * snd_pcm_recover() fails, which usually does not happen.
|
||||
+ * Here we start the pcm stream again and go for another try. Another
|
||||
+ * option is: set result to paOverrun and return to caller. Then
|
||||
+ * the caller needs to call ReadStream again. This takes more time and
|
||||
+ * we lose even more frames.
|
||||
+ */
|
||||
+ if (xrun) { /* wd-xxx */
|
||||
+ if( snd_pcm_state( stream->capture.pcm ) == SND_PCM_STATE_PREPARED ) {
|
||||
+ ENSURE_( snd_pcm_start( stream->capture.pcm ), paUnanticipatedHostError );
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
+ framesGot = PA_MIN( framesAvail, frames );
|
||||
PA_ENSURE( PaAlsaStream_SetUpBuffers( stream, &framesGot, &xrun ) );
|
||||
if( framesGot > 0 )
|
||||
{
|
||||
@@ -3580,6 +3610,7 @@
|
||||
|
||||
PA_ENSURE( PaAlsaStream_HandleXrun( stream ) );
|
||||
savail = snd_pcm_avail_update( stream->playback.pcm );
|
||||
+ // printf("GSWA xrun, sav: %ld (%lx)\n", savail, savail); fflush(stdout); // DEBUG-WD
|
||||
|
||||
/* savail should not contain -EPIPE now, since PaAlsaStream_HandleXrun will only prepare the pcm */
|
||||
ENSURE_( savail, paUnanticipatedHostError );
|
||||
@ -1,39 +0,0 @@
|
||||
Index: pa_linux_alsa.c
|
||||
===================================================================
|
||||
--- pa_linux_alsa.c (revision 1418)
|
||||
+++ pa_linux_alsa.c (working copy)
|
||||
@@ -315,7 +315,10 @@
|
||||
}
|
||||
|
||||
PaUtil_FreeMemory( alsaHostApi );
|
||||
- snd_config_update_free_global();
|
||||
+// damencho, removed fo compability with pulseaudio versions before 0.9.16
|
||||
+// segfault application:
|
||||
+// bugtrack alsa: 0002124: snd_config_update_free_global kills applications using user space alsa plugins
|
||||
+// snd_config_update_free_global();
|
||||
}
|
||||
|
||||
/** Determine max channels and default latencies.
|
||||
@@ -1364,7 +1367,7 @@
|
||||
|
||||
ENSURE_( snd_pcm_sw_params_set_avail_min( self->pcm, swParams, self->framesPerBuffer ), paUnanticipatedHostError );
|
||||
ENSURE_( snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ), paUnanticipatedHostError );
|
||||
- ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
|
||||
+ ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError );
|
||||
|
||||
/* Set the parameters! */
|
||||
ENSURE_( snd_pcm_sw_params( self->pcm, swParams ), paUnanticipatedHostError );
|
||||
@@ -2788,6 +2807,13 @@
|
||||
|
||||
*shouldPoll = 0;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ // not actually used
|
||||
+ unsigned long framesAvail = 0;
|
||||
+ // now check for xrun
|
||||
+ PaAlsaStreamComponent_GetAvailableFrames(self, &framesAvail, xrun );
|
||||
+ }
|
||||
|
||||
error:
|
||||
return result;
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue