mirror of https://github.com/sipwise/jitsi.git
Second big move of packages. Created jmfext in order to keep jmf requirenment for package name of Datasources ("media.protocol.....") and separate portaudio classes in neomedia.portaudio package.
parent
9a5291e9ff
commit
aa86a86095
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,309 @@
|
||||
/* 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_FRAMES_PER_BUFFER_UNSPECIFIED
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED 0LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT16
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT16 8LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 1LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT32
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT32 2LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT24
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT24 4LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT8
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_INT8 16LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_UINT8
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 32LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG 0LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF 1LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF 2LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT 4LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK 8LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS -65536LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSEPCIFIED
|
||||
#define net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_LATENCY_UNSEPCIFIED 0.0
|
||||
#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
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_portaudio_PortAudio
|
||||
* Method: setEchoCancelParams
|
||||
* Signature: (JJZZII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_setEchoCancelParams
|
||||
(JNIEnv *, jclass, jlong, jlong, jboolean, jboolean, jint, jint);
|
||||
|
||||
/*
|
||||
* 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_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_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_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_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_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_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[BJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_portaudio_PortAudio_Pa_1WriteStream
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jlong);
|
||||
|
||||
/*
|
||||
* 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_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_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_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: 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_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_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_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_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: 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: 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: 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_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_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: 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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -1,309 +0,0 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio */
|
||||
|
||||
#ifndef _Included_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
#define _Included_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_FRAMES_PER_BUFFER_UNSPECIFIED 0LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT16
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT16 8LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_FLOAT32 1LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT32
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT32 2LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT24
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT24 4LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT8
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_INT8 16LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_UINT8
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_SAMPLE_FORMAT_UINT8 32LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NO_FLAG 0LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_CLIP_OFF 1LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_DITHER_OFF 2LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_NEVER_DROP_INPUT 4LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK 8LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS -65536LL
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_UNSEPCIFIED
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_UNSEPCIFIED 0.0
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_HIGH -1.0
|
||||
#undef net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW
|
||||
#define net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_LATENCY_LOW -2.0
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: setEchoCancelParams
|
||||
* Signature: (JJZZII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_setEchoCancelParams
|
||||
(JNIEnv *, jclass, jlong, jlong, jboolean, jboolean, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetDefaultInputDevice
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultInputDevice
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetDefaultOutputDevice
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDefaultOutputDevice
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_CloseStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1CloseStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_AbortStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1AbortStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetDeviceCount
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceCount
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetDeviceInfo
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetDeviceInfo
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_Initialize
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1Initialize
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_OpenStream
|
||||
* Signature: (JJDJJLnet/java/sip/communicator/impl/neomedia/protocol/portaudio/PortAudioStreamCallback;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1OpenStream
|
||||
(JNIEnv *, jclass, jlong, jlong, jdouble, jlong, jlong, jobject);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_StartStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StartStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_StopStream
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1StopStream
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_WriteStream
|
||||
* Signature: (J[BJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1WriteStream
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_ReadStream
|
||||
* Signature: (J[BJ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1ReadStream
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetStreamReadAvailable
|
||||
* Signature: (J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamReadAvailable
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetStreamWriteAvailable
|
||||
* Signature: (J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetStreamWriteAvailable
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetSampleSize
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetSampleSize
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_IsFormatSupported
|
||||
* Signature: (JJD)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1IsFormatSupported
|
||||
(JNIEnv *, jclass, jlong, jlong, jdouble);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getMaxInputChannels
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxInputChannels
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getMaxOutputChannels
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getMaxOutputChannels
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getName
|
||||
* Signature: (J)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getName
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultSampleRate
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultSampleRate
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getHostApi
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getHostApi
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultLowInputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowInputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultLowOutputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultLowOutputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultHighInputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighInputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaDeviceInfo_getDefaultHighOutputLatency
|
||||
* Signature: (J)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaDeviceInfo_1getDefaultHighOutputLatency
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: Pa_GetHostApiInfo
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_Pa_1GetHostApiInfo
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_GetType
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetType
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_GetName
|
||||
* Signature: (J)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetName
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_GetDeviceCount
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDeviceCount
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_GetDefaultInputDevice
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultInputDevice
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaHostApiInfo_GetDefaultOutputDevice
|
||||
* Signature: (J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaHostApiInfo_1GetDefaultOutputDevice
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio
|
||||
* Method: PaStreamParameters_new
|
||||
* Signature: (IIJD)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_neomedia_protocol_portaudio_PortAudio_PaStreamParameters_1new
|
||||
(JNIEnv *, jclass, jint, jint, jlong, jdouble);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.alsa;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
import javax.media.protocol.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* low-latency ALSA access through JNI wrapper
|
||||
*
|
||||
* @author Jean Lorchat
|
||||
*/
|
||||
public class AlsaStream
|
||||
implements PushBufferStream, Runnable
|
||||
{
|
||||
protected ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW);
|
||||
protected int maxDataLength;
|
||||
protected AudioFormat audioFormat;
|
||||
protected boolean started;
|
||||
protected Thread thread;
|
||||
protected BufferTransferHandler transferHandler;
|
||||
protected Control [] controls = new Control[0];
|
||||
|
||||
private native void jni_alsa_init();
|
||||
private native void jni_alsa_read(byte [] arr);
|
||||
private native void jni_alsa_delete();
|
||||
|
||||
int seqNo = 0;
|
||||
|
||||
/**
|
||||
* Dynamically loads JNI object. Will fail if non-Linux
|
||||
* or when libjmf_alsa.so is outside of the LD_LIBRARY_PATH
|
||||
*/
|
||||
static {
|
||||
System.loadLibrary("jmf_alsa");
|
||||
}
|
||||
|
||||
/**
|
||||
* We only provide 8 kbps access to the device for now
|
||||
* In addition, datablock size is fixed to 160 samples (320 bytes)
|
||||
* This turns out to be 20ms worth of samples at 8kbps
|
||||
* Very convenient for ilbc 20ms mode...
|
||||
*/
|
||||
public AlsaStream() {
|
||||
|
||||
audioFormat = new AudioFormat(AudioFormat.LINEAR,
|
||||
8000.0,
|
||||
16,
|
||||
1,
|
||||
AudioFormat.LITTLE_ENDIAN,
|
||||
AudioFormat.SIGNED,
|
||||
16,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray);
|
||||
|
||||
maxDataLength = 160;
|
||||
|
||||
jni_alsa_init();
|
||||
thread = new Thread(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods required for SourceStream interface
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* We are providing access to raw data
|
||||
*
|
||||
*/
|
||||
public ContentDescriptor getContentDescriptor() {
|
||||
return cd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Come on, we are streaming. Can't guess when the user wants to stop...
|
||||
*
|
||||
*/
|
||||
public long getContentLength() {
|
||||
return LENGTH_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream of happiness never ends, somehow.
|
||||
*
|
||||
*/
|
||||
public boolean endOfStream() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell whoever has interest how we are going to send the data
|
||||
*
|
||||
*/
|
||||
public Format getFormat() {
|
||||
return audioFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads sample data using native call
|
||||
*
|
||||
* @param buffer A Buffer with byte array as data, large enough to be
|
||||
* filled with sample data. If this is not the case, we are going
|
||||
* to allocate it ourselves anyway and replace the current data.
|
||||
*
|
||||
* @throws IOException Native method might throw an exception.
|
||||
* Well actually that would surprise me because it is not
|
||||
* implemented, but we love to be future-proof, isn't it ?
|
||||
*/
|
||||
public void read(Buffer buffer) throws IOException {
|
||||
synchronized (this) {
|
||||
Object outdata = buffer.getData();
|
||||
|
||||
if (outdata == null ||
|
||||
!(outdata.getClass() == Format.byteArray) ||
|
||||
((byte[])outdata).length < maxDataLength) {
|
||||
outdata = new byte[maxDataLength];
|
||||
buffer.setData(outdata);
|
||||
}
|
||||
|
||||
buffer.setFormat(audioFormat);
|
||||
buffer.setTimeStamp(1000000000 / 8);
|
||||
jni_alsa_read((byte[])outdata);
|
||||
buffer.setSequenceNumber(seqNo);
|
||||
buffer.setLength(maxDataLength);
|
||||
buffer.setFlags(0);
|
||||
buffer.setHeader(null);
|
||||
seqNo++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dunno about that piece yet...
|
||||
*
|
||||
*/
|
||||
public void setTransferHandler(BufferTransferHandler transferHandler) {
|
||||
synchronized (this) {
|
||||
this.transferHandler = transferHandler;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new thread for the stream operation
|
||||
*
|
||||
*/
|
||||
void start(boolean started) {
|
||||
synchronized (this) {
|
||||
this.started = started;
|
||||
if (started && !thread.isAlive()) {
|
||||
thread = new Thread(this);
|
||||
thread.start();
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer Buffer information through current thread then sleep
|
||||
* until next data slice is ready.
|
||||
*
|
||||
*/
|
||||
public void run() {
|
||||
while (started) {
|
||||
|
||||
synchronized (this) {
|
||||
while (transferHandler == null && started) {
|
||||
try {
|
||||
wait(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (started && transferHandler != null) {
|
||||
transferHandler.transferData(this);
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException ise) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives control information to the caller
|
||||
*
|
||||
*/
|
||||
public Object [] getControls() {
|
||||
return controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return required control from the Control[] array
|
||||
* if exists, that is
|
||||
*/
|
||||
public Object getControl(String controlType) {
|
||||
try {
|
||||
Class<?> cls = Class.forName(controlType);
|
||||
Object cs[] = getControls();
|
||||
for (int i = 0; i < cs.length; i++) {
|
||||
if (cls.isInstance(cs[i]))
|
||||
return cs[i];
|
||||
}
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.alsa;
|
||||
|
||||
import javax.media.Time;
|
||||
import javax.media.protocol.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* low-latency ALSA access through JNI wrapper
|
||||
*
|
||||
* @author Jean Lorchat
|
||||
*/
|
||||
public class DataSource
|
||||
extends PushBufferDataSource
|
||||
{
|
||||
protected Object [] controls = new Object[0];
|
||||
protected boolean started = false;
|
||||
protected String contentType = "raw";
|
||||
protected boolean connected = false;
|
||||
protected Time duration = DURATION_UNKNOWN;
|
||||
protected AlsaStream [] streams = null;
|
||||
protected AlsaStream stream = null;
|
||||
|
||||
public DataSource() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell we are a raw datasource
|
||||
*
|
||||
* @return "raw"
|
||||
*/
|
||||
public String getContentType() {
|
||||
if (!connected){
|
||||
System.err.println("Error: DataSource not connected");
|
||||
return null;
|
||||
}
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the datasource
|
||||
*/
|
||||
public void connect() throws IOException {
|
||||
if (connected)
|
||||
return;
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the datasource
|
||||
*/
|
||||
public void disconnect() {
|
||||
try {
|
||||
if (started)
|
||||
stop();
|
||||
} catch (IOException e) {}
|
||||
connected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the datasource and the underlying stream
|
||||
*/
|
||||
public void start() throws IOException {
|
||||
if (!connected)
|
||||
throw new java.lang.Error("DataSource must be connected");
|
||||
|
||||
if (started)
|
||||
return;
|
||||
|
||||
started = true;
|
||||
stream.start(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the datasource and it's underlying stream
|
||||
*/
|
||||
public void stop() throws IOException {
|
||||
|
||||
if ((!connected) || (!started))
|
||||
return;
|
||||
|
||||
started = false;
|
||||
stream.start(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives control information to the caller
|
||||
*
|
||||
*/
|
||||
public Object [] getControls() {
|
||||
return controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return required control from the Control[] array
|
||||
* if exists, that is
|
||||
*/
|
||||
public Object getControl(String controlType) {
|
||||
try {
|
||||
Class<?> cls = Class.forName(controlType);
|
||||
Object cs[] = getControls();
|
||||
for (int i = 0; i < cs.length; i++) {
|
||||
if (cls.isInstance(cs[i]))
|
||||
return cs[i];
|
||||
}
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives to the caller the duration information of our stream
|
||||
* Which is, obviously unknown. Better turn on that premonition
|
||||
* switch again, Mrs Cake.
|
||||
*
|
||||
* @return DURATION_UNKNOWN
|
||||
*/
|
||||
public Time getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of PushBufferStream containing all the streams
|
||||
* i.e. only one in our case : only sound
|
||||
*
|
||||
* If no stream actually exists, instanciate one on the fly
|
||||
*
|
||||
* @return Array of one stream
|
||||
*/
|
||||
public PushBufferStream [] getStreams() {
|
||||
if (streams == null) {
|
||||
streams = new AlsaStream[1];
|
||||
stream = streams[0] = new AlsaStream();
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.*;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.streams.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
import javax.media.protocol.*;
|
||||
|
||||
/**
|
||||
* The stream used by jmf, wraps our InputPortAudioStream, which wraps
|
||||
* the actual PortAudio stream.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class DSAudioStream
|
||||
implements PullBufferStream
|
||||
{
|
||||
private final static ContentDescriptor cd =
|
||||
new ContentDescriptor(ContentDescriptor.RAW);
|
||||
|
||||
private Control[] controls = new Control[0];
|
||||
|
||||
private final int deviceIndex;
|
||||
|
||||
private InputPortAudioStream stream = null;
|
||||
|
||||
private int seqNo = 0;
|
||||
|
||||
/**
|
||||
* Creates new stream.
|
||||
* @param locator the locator to extract the device index from it.
|
||||
*/
|
||||
public DSAudioStream(MediaLocator locator)
|
||||
{
|
||||
this.deviceIndex = PortAudioUtils.getDeviceIndexFromLocator(locator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the stream operation
|
||||
* @throws PortAudioException if fail to start.
|
||||
*/
|
||||
void start()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(stream == null)
|
||||
{
|
||||
AudioFormat audioFormat =
|
||||
(AudioFormat)DataSource.getCaptureFormat();
|
||||
|
||||
stream = PortAudioManager.getInstance().getInputStream(deviceIndex,
|
||||
audioFormat.getSampleRate(), audioFormat.getChannels());
|
||||
}
|
||||
|
||||
stream.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the stream operation.
|
||||
* @throws PortAudioException if fail to stop.
|
||||
*/
|
||||
void stop()
|
||||
throws PortAudioException
|
||||
{
|
||||
stream.stop();
|
||||
stream = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if the next read will block.
|
||||
* @return true if a read will block.
|
||||
*/
|
||||
public boolean willReadBlock()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block and read a buffer from the stream.
|
||||
*
|
||||
* @param buffer the <tt>Buffer</tt> to read captured media into
|
||||
* @throws IOException if an error occurs while reading.
|
||||
*/
|
||||
public void read(Buffer buffer)
|
||||
throws IOException
|
||||
{
|
||||
if (stream == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] bytebuff = stream.read();
|
||||
|
||||
buffer.setTimeStamp(System.nanoTime());
|
||||
|
||||
buffer.setData(bytebuff);
|
||||
buffer.setLength(bytebuff.length);
|
||||
|
||||
buffer.setFlags(0);
|
||||
buffer.setFormat(getFormat());
|
||||
buffer.setHeader(null);
|
||||
|
||||
buffer.setSequenceNumber(seqNo);
|
||||
seqNo++;
|
||||
}
|
||||
catch (PortAudioException pae)
|
||||
{
|
||||
IOException ioe = new IOException();
|
||||
|
||||
ioe.initCause(pae);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported format by this stream.
|
||||
* @return supported formats
|
||||
*/
|
||||
public Format getFormat()
|
||||
{
|
||||
return DataSource.getCaptureFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* We are providing access to raw data
|
||||
* @return RAW content descriptor.
|
||||
*/
|
||||
public ContentDescriptor getContentDescriptor()
|
||||
{
|
||||
return cd;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are streaming.
|
||||
* @return unknown content length.
|
||||
*/
|
||||
public long getContentLength()
|
||||
{
|
||||
return LENGTH_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream never ends.
|
||||
* @return true if the end of the stream has been reached.
|
||||
*/
|
||||
public boolean endOfStream()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives control information to the caller
|
||||
* @return no controls currently supported.
|
||||
*/
|
||||
public Object[] getControls()
|
||||
{
|
||||
return controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return required control from the Control[] array
|
||||
* if exists
|
||||
*
|
||||
* @param controlType the control class name.
|
||||
* @return the object that implements the control, or null.
|
||||
*/
|
||||
public Object getControl(String controlType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> cls = Class.forName(controlType);
|
||||
Object cs[] = getControls();
|
||||
for(int i = 0; i < cs.length; i++)
|
||||
{
|
||||
if(cls.isInstance(cs[i]))
|
||||
{
|
||||
return cs[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,418 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.control.*;
|
||||
import javax.media.format.*;
|
||||
import javax.media.protocol.*;
|
||||
|
||||
import net.java.sip.communicator.util.*;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.*;
|
||||
|
||||
/**
|
||||
* Implements <tt>DataSource</tt> and <tt>CaptureDevice</tt> for PortAudio.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class DataSource
|
||||
extends PullBufferDataSource
|
||||
implements CaptureDevice
|
||||
{
|
||||
|
||||
/**
|
||||
* The <tt>Logger</tt> used by the <tt>DataSource</tt> class and its
|
||||
* instances for logging output.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(DataSource.class);
|
||||
|
||||
private boolean connected = false;
|
||||
|
||||
/**
|
||||
* The JMF controls (which are likely of type <tt>Control</tt>) available
|
||||
* for this <tt>DataSource</tt>.
|
||||
*/
|
||||
private final Object[] controls
|
||||
= new Object[]
|
||||
{
|
||||
new FormatControlImpl()
|
||||
};
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
private DSAudioStream[] streams = null;
|
||||
|
||||
private static AudioFormat captureAudioFormat =
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
8000,
|
||||
16,
|
||||
1,
|
||||
AudioFormat.LITTLE_ENDIAN,
|
||||
AudioFormat.SIGNED,
|
||||
16,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray);
|
||||
|
||||
/**
|
||||
* Return the formats supported by the datasource.
|
||||
*
|
||||
* @return the supported formats.
|
||||
*/
|
||||
public static Format getCaptureFormat()
|
||||
{
|
||||
return captureAudioFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the datasource
|
||||
* @throws IOException if we cannot initialize portaudio.
|
||||
*/
|
||||
public void connect()
|
||||
throws IOException
|
||||
{
|
||||
if (connected)
|
||||
return;
|
||||
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the datasource
|
||||
*/
|
||||
public void disconnect()
|
||||
{
|
||||
if (!connected)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
stop();
|
||||
}
|
||||
catch (IOException ioex)
|
||||
{
|
||||
logger
|
||||
.warn(
|
||||
"Failed to stop DataSource with locator " + getLocator(),
|
||||
ioex);
|
||||
}
|
||||
|
||||
connected = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>CaptureDeviceInfo</tt> that describes this
|
||||
* <tt>CaptureDevice</tt>.
|
||||
*
|
||||
* @return the <tt>CaptureDeviceInfo</tt> that describes this
|
||||
* <tt>CaptureDevice</tt>
|
||||
*/
|
||||
public CaptureDeviceInfo getCaptureDeviceInfo()
|
||||
{
|
||||
/*
|
||||
* TODO The implemented search for the CaptureDeviceInfo of this
|
||||
* CaptureDevice by looking for its MediaLocator is inefficient.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
Vector<CaptureDeviceInfo> captureDeviceInfos
|
||||
= (Vector<CaptureDeviceInfo>)
|
||||
CaptureDeviceManager.getDeviceList(null);
|
||||
MediaLocator locator = getLocator();
|
||||
|
||||
for (CaptureDeviceInfo captureDeviceInfo : captureDeviceInfos)
|
||||
if (captureDeviceInfo.getLocator().equals(locator))
|
||||
return captureDeviceInfo;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell we are a raw datasource
|
||||
*
|
||||
* @return "raw"
|
||||
*/
|
||||
public String getContentType()
|
||||
{
|
||||
return ContentDescriptor.RAW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return required control from the Control[] array
|
||||
* if exists.
|
||||
* @param controlType the control we are interested in.
|
||||
* @return the object that implements the control, or null.
|
||||
*/
|
||||
public Object getControl(String controlType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> controlClass = Class.forName(controlType);
|
||||
|
||||
for (Object control : getControls())
|
||||
if (controlClass.isInstance(control))
|
||||
return control;
|
||||
}
|
||||
catch (ClassNotFoundException cnfex)
|
||||
{
|
||||
logger
|
||||
.warn(
|
||||
"Failed to load class of requested controlType "
|
||||
+ controlType,
|
||||
cnfex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives control information to the caller
|
||||
* @return the collection of object controls.
|
||||
*/
|
||||
public Object[] getControls()
|
||||
{
|
||||
/*
|
||||
* The field controls represents is private so we cannot directly return
|
||||
* it. Otherwise, the caller will be able to modify it.
|
||||
*/
|
||||
return controls.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives to the caller the duration information of our stream
|
||||
* Which is, obviously unknown.
|
||||
*
|
||||
* @return DURATION_UNKNOWN
|
||||
*/
|
||||
public Time getDuration()
|
||||
{
|
||||
return DURATION_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of <tt>FormatControl</tt> instances each one of which can
|
||||
* be used before {@link #connect()} to get and set the capture
|
||||
* <tt>Format</tt> of each one of the capture streams.
|
||||
*
|
||||
* @return an array of <tt>FormatControl</tt> instances each one of which
|
||||
* can be used before {@link #connect()} to get and set the capture
|
||||
* <tt>Format</tt> of each one of the capture streams
|
||||
*/
|
||||
public FormatControl[] getFormatControls()
|
||||
{
|
||||
List<FormatControl> formatControls = new ArrayList<FormatControl>();
|
||||
|
||||
for (Object control : getControls())
|
||||
if (control instanceof FormatControl)
|
||||
formatControls.add((FormatControl) control);
|
||||
return formatControls.toArray(new FormatControl[formatControls.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of PullBufferStream containing all the streams
|
||||
* i.e. only one in our case : only sound.
|
||||
*
|
||||
* If no stream actually exists, instantiate one on the fly.
|
||||
*
|
||||
* @return Array of one stream
|
||||
*/
|
||||
public PullBufferStream[] getStreams()
|
||||
{
|
||||
MediaLocator locator = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (streams == null)
|
||||
{
|
||||
locator = getLocator();
|
||||
streams = new DSAudioStream[] { new DSAudioStream(locator) };
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// if we cannot parse desired device we will not open a stream
|
||||
// so there is no stream returned
|
||||
streams = new DSAudioStream[0];
|
||||
|
||||
logger
|
||||
.error(
|
||||
"Failed to create DSAudioStream from locator " + locator,
|
||||
e);
|
||||
}
|
||||
|
||||
return streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the datasource and the underlying stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void start()
|
||||
throws IOException
|
||||
{
|
||||
if (started)
|
||||
return;
|
||||
|
||||
if (!connected)
|
||||
throw new IOException("DataSource must be connected");
|
||||
|
||||
try
|
||||
{
|
||||
streams[0].start();
|
||||
}
|
||||
catch (PortAudioException pae)
|
||||
{
|
||||
IOException ioe = new IOException();
|
||||
|
||||
ioe.initCause(pae);
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the datasource and it's underlying stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public void stop()
|
||||
throws IOException
|
||||
{
|
||||
if (!started)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
streams[0].stop();
|
||||
}
|
||||
catch (PortAudioException pae)
|
||||
{
|
||||
IOException ioe = new IOException();
|
||||
|
||||
ioe.initCause(pae);
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements <tt>FormatControl</tt> for this <tt>DataSource</tt> instance.
|
||||
* At least getting the <tt>Format</tt> of the <tt>DataSource</tt> is
|
||||
* important because, for example, <tt>AudioMixer</tt> will ask for it.
|
||||
*/
|
||||
private class FormatControlImpl
|
||||
implements FormatControl
|
||||
{
|
||||
|
||||
/**
|
||||
* The indicator which determines whether this track is enabled. I don't
|
||||
* known what it means for <tt>DataSource</tt> implementations but
|
||||
* at least the choice of the caller is remembered and reported.
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Implements {@link Controls#getControlComponent()}. Since
|
||||
* <tt>DataSource</tt> does not export any UI, returns <tt>null</tt>.
|
||||
*
|
||||
* @return a <tt>Component</tt> which represents UI associated with this
|
||||
* <tt>DataSource</tt> and this <tt>FormatControl</tt> if any;
|
||||
* otherwise, <tt>null</tt>
|
||||
*/
|
||||
public java.awt.Component getControlComponent()
|
||||
{
|
||||
// No Component is exported for this DataSource.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@link FormatControl#getFormat()}.
|
||||
*
|
||||
* @return the <tt>Format</tt> of this <tt>DataSource</tt>
|
||||
*/
|
||||
public Format getFormat()
|
||||
{
|
||||
return getCaptureFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@link FormatControl#getSupportedFormats()}.
|
||||
*
|
||||
* @return an array of <tt>Format</tt> element type which lists the JMF
|
||||
* formats supported by this <tt>DataSource</tt> i.e. the ones in which
|
||||
* it is able to output
|
||||
*/
|
||||
public Format[] getSupportedFormats()
|
||||
{
|
||||
return new Format[] { getCaptureFormat() };
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@link FormatControl#isEnabled()}. Does not mean anything
|
||||
* to this <tt>DataSource</tt> at the time of this writing.
|
||||
*
|
||||
* @return <tt>true</tt> if this track is enabled; otherwise,
|
||||
* <tt>false</tt>
|
||||
*/
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@link FormatControl#setEnabled(boolean)}. Does not mean
|
||||
* anything to this <tt>DataSource</tt> at the time of this writing.
|
||||
*
|
||||
* @param enabled <tt>true</tt> if this track is to be enabled;
|
||||
* otherwise, <tt>false</tt>
|
||||
*/
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements {@link FormatControl#setFormat(Format)}. Not supported at
|
||||
* this time and just returns the currently set format if the specified
|
||||
* <tt>Format</tt> is supported and <tt>null</tt> if it is not
|
||||
* supported.
|
||||
*
|
||||
* @param format the <tt>Format</tt> in which this <tt>DataSource</tt>
|
||||
* is to output
|
||||
* @return the currently set <tt>Format</tt> after the attempt to set it
|
||||
* as the output format of this <tt>DataSource</tt> if <tt>format</tt>
|
||||
* is supported by this <tt>DataSource</tt> and regardless of whether it
|
||||
* was actually set; <tt>null</tt> if <tt>format</tt> is not supported
|
||||
* by this <tt>DataSource</tt>
|
||||
*/
|
||||
public Format setFormat(Format format)
|
||||
{
|
||||
/*
|
||||
* Determine whether the specified format is supported by this
|
||||
* DataSource because we have to return null if it is not supported.
|
||||
* Or at least that is what I gather from the respective javadoc.
|
||||
*/
|
||||
boolean formatIsSupported = false;
|
||||
|
||||
if (format != null)
|
||||
for (Format supportedFormat : getSupportedFormats())
|
||||
if (supportedFormat.matches(format))
|
||||
{
|
||||
formatIsSupported = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not actually support setFormat so we have to return the
|
||||
* currently set format if the specified format is supported.
|
||||
*/
|
||||
return (formatIsSupported) ? getFormat() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.jmfext.media.renderer.audio;
|
||||
|
||||
|
||||
import javax.media.*;
|
||||
import javax.media.format.*;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.*;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.streams.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
/**
|
||||
* Portaudio renderer.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class PortAudioRenderer
|
||||
implements Renderer
|
||||
{
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(PortAudioRenderer.class);
|
||||
|
||||
private static final String name = "PortAudio Renderer";
|
||||
|
||||
/**
|
||||
* The supported input formats. The Inputformats are
|
||||
* changed after the device is set.
|
||||
*/
|
||||
public static Format[] supportedInputFormats = new Format[]{};
|
||||
|
||||
/**
|
||||
* The standart supported sample rates.
|
||||
*/
|
||||
private static double[] supportedSampleRates =
|
||||
new double[]{8000, 16000, 22050, 44100, 48000};
|
||||
|
||||
private Object [] controls = new Object[0];
|
||||
private AudioFormat inputFormat;
|
||||
|
||||
private OutputPortAudioStream stream = null;
|
||||
|
||||
boolean started = false;
|
||||
|
||||
private static int deviceIndex = -1;
|
||||
|
||||
/**
|
||||
* Lists the input formats supported by this Renderer.
|
||||
* @return An array of Format objects that represent
|
||||
* the input formats supported by this Renderer.
|
||||
*/
|
||||
public Format[] getSupportedInputFormats()
|
||||
{
|
||||
return supportedInputFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Format of the input data.
|
||||
* @param format the format to set.
|
||||
* @return The Format that was set.
|
||||
*/
|
||||
public Format setInputFormat(Format format)
|
||||
{
|
||||
if(!(format instanceof AudioFormat))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
this.inputFormat = (AudioFormat) format;
|
||||
|
||||
return inputFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the rendering process.
|
||||
* When start is called, the renderer begins rendering
|
||||
* any data available in its internal buffers.
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
try
|
||||
{
|
||||
stream.start();
|
||||
started = true;
|
||||
}
|
||||
catch (PortAudioException e)
|
||||
{
|
||||
logger.error("Starting portaudio stream failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Halts the rendering process.
|
||||
*/
|
||||
public synchronized void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
started = false;
|
||||
stream.stop();
|
||||
}
|
||||
catch (PortAudioException e)
|
||||
{
|
||||
logger.error("Closing portaudio stream failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the data and renders it
|
||||
* to the output device represented by this Renderer.
|
||||
* @param inputBuffer the input data.
|
||||
* @return BUFFER_PROCESSED_OK if the processing is successful.
|
||||
*/
|
||||
public synchronized int process(Buffer inputBuffer)
|
||||
{
|
||||
byte[] buff = new byte[inputBuffer.getLength()];
|
||||
System.arraycopy(
|
||||
(byte[])inputBuffer.getData(),
|
||||
inputBuffer.getOffset(),
|
||||
buff,
|
||||
0,
|
||||
buff.length);
|
||||
|
||||
try
|
||||
{
|
||||
stream.write(buff);
|
||||
}
|
||||
catch (PortAudioException e)
|
||||
{
|
||||
logger.error("Error writing to device", e);
|
||||
}
|
||||
|
||||
return BUFFER_PROCESSED_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the pluging.
|
||||
* @return A String that contains the descriptive name of the plug-in.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the device and stream that we will use to render data.
|
||||
* @throws ResourceUnavailableException If required resources cannot
|
||||
* be opened/created.
|
||||
*/
|
||||
public void open()
|
||||
throws ResourceUnavailableException
|
||||
{
|
||||
try
|
||||
{
|
||||
stream = PortAudioManager.getInstance().getOutputStream(deviceIndex,
|
||||
inputFormat.getSampleRate(), inputFormat.getChannels());
|
||||
}
|
||||
catch (PortAudioException e)
|
||||
{
|
||||
throw new ResourceUnavailableException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the plug-in.
|
||||
*/
|
||||
public void close()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the state of the plug-in.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives control information to the caller
|
||||
* @return the collection of object controls.
|
||||
*/
|
||||
public Object[] getControls()
|
||||
{
|
||||
return controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return required control from the Control[] array
|
||||
* if exists.
|
||||
* @param controlType the control we are interested in.
|
||||
* @return the object that implements the control, or null.
|
||||
*/
|
||||
public Object getControl(String controlType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> cls = Class.forName(controlType);
|
||||
Object cs[] = getControls();
|
||||
for(int i = 0; i < cs.length; i++)
|
||||
{
|
||||
if(cls.isInstance(cs[i]))
|
||||
{
|
||||
return cs[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set the device index used by the renderer common for all
|
||||
* instances of it. Change the format corresponding the device which
|
||||
* will be used.
|
||||
* @param locator the locator containing the device index.
|
||||
*/
|
||||
public static void setDevice(MediaLocator locator)
|
||||
{
|
||||
deviceIndex = PortAudioUtils.getDeviceIndexFromLocator(locator);
|
||||
|
||||
int outputChannels = 1;
|
||||
|
||||
supportedInputFormats = new Format[supportedSampleRates.length];
|
||||
|
||||
for(int i = 0; i < supportedSampleRates.length; i++)
|
||||
{
|
||||
double sampleRate = supportedSampleRates[i];
|
||||
|
||||
supportedInputFormats[i] =
|
||||
new AudioFormat(
|
||||
AudioFormat.LINEAR,
|
||||
sampleRate,
|
||||
16,
|
||||
outputChannels,
|
||||
AudioFormat.LITTLE_ENDIAN,
|
||||
AudioFormat.SIGNED,
|
||||
16,
|
||||
Format.NOT_SPECIFIED,
|
||||
Format.byteArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio;
|
||||
|
||||
/**
|
||||
* PortAudio functions.
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public final class PortAudio
|
||||
{
|
||||
static
|
||||
{
|
||||
System.loadLibrary("jportaudio");
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be passed as the framesPerBuffer parameter to
|
||||
* Pa_OpenStream() or Pa_OpenDefaultStream() to indicate that the stream
|
||||
* callback will accept buffers of any size.
|
||||
*/
|
||||
public static final long FRAMES_PER_BUFFER_UNSPECIFIED = 0;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The standard format paInt16.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_INT16 = 0x00000008;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The format paFloat32.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_FLOAT32 = 0x00000001;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The format paInt32.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_INT32 = 0x00000002;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The format paInt24.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_INT24 = 0x00000004;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The format paInt8.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_INT8 = 0x00000010;
|
||||
|
||||
/**
|
||||
* A type used to specify one or more sample formats.
|
||||
* The format paUInt8.
|
||||
*/
|
||||
public static final long SAMPLE_FORMAT_UINT8 = 0x00000020;
|
||||
|
||||
/**
|
||||
* Flags used to control the behavior of a stream.
|
||||
* They are passed as parameters to Pa_OpenStream or Pa_OpenDefaultStream.
|
||||
*/
|
||||
public static final long STREAM_FLAGS_NO_FLAG = 0;
|
||||
|
||||
/**
|
||||
* Disable default clipping of out of range samples.
|
||||
*/
|
||||
public static final long STREAM_FLAGS_CLIP_OFF = 0x00000001;
|
||||
|
||||
/**
|
||||
* Disable default dithering.
|
||||
*/
|
||||
public static final long STREAM_FLAGS_DITHER_OFF = 0x00000002;
|
||||
|
||||
/**
|
||||
* Flag requests that where possible a full duplex stream will not discard
|
||||
* overflowed input samples without calling the stream callback.
|
||||
* This flag is only valid for full duplex callback streams and only when
|
||||
* used in combination with the paFramesPerBufferUnspecified (0)
|
||||
* framesPerBuffer parameter. Using this flag incorrectly results in a
|
||||
* paInvalidFlag error being returned from
|
||||
* Pa_OpenStream and Pa_OpenDefaultStream.
|
||||
*/
|
||||
public static final long STREAM_FLAGS_NEVER_DROP_INPUT = 0x00000004;
|
||||
|
||||
/**
|
||||
* Call the stream callback to fill initial output buffers, rather than
|
||||
* the default behavior of priming the buffers with zeros (silence).
|
||||
* This flag has no effect for input-only and blocking read/write streams.
|
||||
*/
|
||||
public static final long
|
||||
STREAM_FLAGS_PRIME_OUTPUT_BUFFERS_USING_STREAM_CALLBACK = 0x00000008;
|
||||
|
||||
/**
|
||||
* A mask specifying the platform specific bits.
|
||||
*/
|
||||
public static final long STREAM_FLAGS_PLATFORM_SPECIFIC_FLAGS = 0xFFFF0000;
|
||||
|
||||
/**
|
||||
* Used when creating new stream parameters for suggested latency.
|
||||
* To use default value.
|
||||
*/
|
||||
public static final double LATENCY_UNSEPCIFIED = 0d;
|
||||
|
||||
/**
|
||||
* Used when creating new stream parameters for suggested latency.
|
||||
* To use high input/output value.
|
||||
*/
|
||||
public static final double LATENCY_HIGH = -1d;
|
||||
|
||||
/**
|
||||
* Used when creating new stream parameters for suggested latency.
|
||||
* To use low input/default value.
|
||||
*/
|
||||
public static final double LATENCY_LOW = -2d;
|
||||
|
||||
private static boolean initialized;
|
||||
|
||||
/**
|
||||
* Used to initialize the portaudio lib.
|
||||
*
|
||||
* @throws PortAudioException if error comes from portaudio.
|
||||
*/
|
||||
public static synchronized void initialize()
|
||||
throws PortAudioException
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
Pa_Initialize();
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set params for echocancel and turns on/off noise suppression.
|
||||
* @param inputStream the input stream.
|
||||
* @param outputStream the output stream.
|
||||
* @param enableDenoise is noise suppression enabled.
|
||||
* @param enableEchoCancel is echo cancel enabled.
|
||||
* @param frameSize Number of samples to process at one time
|
||||
* (should correspond to 10-20 ms)
|
||||
* @param filterLength Number of samples of echo to cancel
|
||||
* (should generally correspond to 100-500 ms)
|
||||
*/
|
||||
public static native void setEchoCancelParams(
|
||||
long inputStream,
|
||||
long outputStream,
|
||||
boolean enableDenoise,
|
||||
boolean enableEchoCancel, int frameSize, int filterLength);
|
||||
|
||||
/**
|
||||
* Retrieve the index of the default input device.
|
||||
* @return The default input device index for the default host API,
|
||||
* or paNoDevice if no default input device is available or
|
||||
* an error was encountered.
|
||||
*/
|
||||
public static native int Pa_GetDefaultInputDevice();
|
||||
|
||||
/**
|
||||
* Retrieve the index of the default output device.
|
||||
* @return The default input device index for the default host API,
|
||||
* or paNoDevice if no default input device is available or
|
||||
* an error was encountered.
|
||||
*/
|
||||
public static native int Pa_GetDefaultOutputDevice();
|
||||
|
||||
/**
|
||||
* Closes an audio stream. If the audio stream is active it discards
|
||||
* any pending buffers as if Pa_AbortStream() had been called.
|
||||
* @param stream the steam pointer.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_CloseStream(long stream)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Terminates audio processing immediately without waiting
|
||||
* for pending buffers to complete.
|
||||
* @param stream the steam pointer.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_AbortStream(long stream)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Retrieve the number of available devices.
|
||||
* The number of available devices may be zero.
|
||||
* @return the number of devices.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native int Pa_GetDeviceCount()
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to a PaDeviceInfo structure containing
|
||||
* information about the specified device.
|
||||
* @param deviceIndex the device index
|
||||
* @return pointer to device info structure.
|
||||
*/
|
||||
public static native long Pa_GetDeviceInfo(int deviceIndex);
|
||||
|
||||
/**
|
||||
* Library initialization function - call this before using PortAudio.s
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
private static native void Pa_Initialize()
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Opens a stream for either input, output or both.
|
||||
* @param inputParameters the input params or 0 if absent.
|
||||
* @param outputParameters the ouput params or 0 if absent.
|
||||
* @param sampleRate The desired sampleRate.
|
||||
* @param framesPerBuffer The number of frames passed to the stream
|
||||
* callback function, or the preferred block granularity for
|
||||
* a blocking read/write stream
|
||||
* @param streamFlags Flags which modify the
|
||||
* behaviour of the streaming process.
|
||||
* @param streamCallback A pointer to a client supplied function that is
|
||||
* responsible for processing and filling input and output buffers.
|
||||
* If this parameter is NULL the stream will be opened in
|
||||
* 'blocking read/write' mode.
|
||||
* @return pointer to the opened stream.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native long Pa_OpenStream(
|
||||
long inputParameters,
|
||||
long outputParameters,
|
||||
double sampleRate,
|
||||
long framesPerBuffer,
|
||||
long streamFlags,
|
||||
PortAudioStreamCallback streamCallback)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Commences audio processing.
|
||||
* @param stream pointer to the stream
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_StartStream(long stream)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Terminates audio processing. It waits until all pending audio buffers
|
||||
* have been played before it returns.
|
||||
* @param stream pointer to the stream
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_StopStream(long stream)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Write samples to an output stream. This function doesn't return until
|
||||
* the entire buffer has been consumed - this may involve waiting for the
|
||||
* operating system to consume the data.
|
||||
* @param stream pointer to the stream
|
||||
* @param buffer A buffer of sample frames.
|
||||
* @param frames The number of frames to be written from buffer.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_WriteStream(
|
||||
long stream,
|
||||
byte[] buffer,
|
||||
long frames)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Read samples from an input stream. The function doesn't return until
|
||||
* the entire buffer has been filled - this may involve waiting for
|
||||
* the operating system to supply the data.
|
||||
* @param stream pointer to the stream.
|
||||
* @param buffer a buffer of sample frames.
|
||||
* @param frames The number of frames to be read into buffer.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public static native void Pa_ReadStream(
|
||||
long stream, byte[] buffer, long frames)
|
||||
throws PortAudioException;
|
||||
|
||||
/**
|
||||
* Retrieve the number of frames that can be read from the stream
|
||||
* without waiting.
|
||||
* @param stream pointer to the stream.
|
||||
* @return returns a non-negative value representing the maximum number
|
||||
* of frames that can be read from the stream without blocking
|
||||
* or busy waiting or, a PaErrorCode (which are always negative)
|
||||
* if PortAudio is not initialized or an error is encountered.
|
||||
*/
|
||||
public static native long Pa_GetStreamReadAvailable(long stream);
|
||||
|
||||
/**
|
||||
* Retrieve the number of frames that can be written to the stream
|
||||
* without waiting.
|
||||
* @param stream pointer to the stream.
|
||||
* @return returns a non-negative value representing the maximum number
|
||||
* of frames that can be written to the stream without blocking
|
||||
* or busy waiting or, a PaErrorCode (which are always negative)
|
||||
* if PortAudio is not initialized or an error is encountered.
|
||||
*/
|
||||
public static native long Pa_GetStreamWriteAvailable(long stream);
|
||||
|
||||
/**
|
||||
* Retrieve the size of a given sample format in bytes.
|
||||
* @param format the format.
|
||||
* @return The size in bytes of a single sample in the specified format,
|
||||
* or paSampleFormatNotSupported if the format is not supported.
|
||||
*/
|
||||
public static native int Pa_GetSampleSize(long format);
|
||||
|
||||
/**
|
||||
* Determine whether it would be possible to open a stream
|
||||
* with the specified parameters.
|
||||
* @param inputParameters A structure that describes the
|
||||
* input parameters used to open a stream.
|
||||
* @param outputParameters A structure that describes the output
|
||||
* parameters used to open a stream.
|
||||
* @param sampleRate The required sampleRate.
|
||||
* @return returns 0 if the format is supported, and an error code
|
||||
* indicating why the format is not supported otherwise.
|
||||
* The constant paFormatIsSupported is provided to compare
|
||||
* with the return value for success.
|
||||
*/
|
||||
public static native boolean Pa_IsFormatSupported(
|
||||
long inputParameters,
|
||||
long outputParameters,
|
||||
double sampleRate);
|
||||
|
||||
/**
|
||||
* Maximum input channels for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return Maximum input channels for the device.
|
||||
*/
|
||||
public static native int PaDeviceInfo_getMaxInputChannels(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Maximum output channels for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return Maximum output channels for the device.
|
||||
*/
|
||||
public static native int PaDeviceInfo_getMaxOutputChannels(long deviceInfo);
|
||||
|
||||
/**
|
||||
* The name of the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return The name of the device.
|
||||
*/
|
||||
public static native String PaDeviceInfo_getName(long deviceInfo);
|
||||
|
||||
/**
|
||||
* The default samplerate for the deviec.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return the default sameple rate for the device.
|
||||
*/
|
||||
public static native double PaDeviceInfo_getDefaultSampleRate(long deviceInfo);
|
||||
|
||||
/**
|
||||
* The host api of the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return The host api of the device.
|
||||
*/
|
||||
public static native int PaDeviceInfo_getHostApi(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Returns defaultLowInputLatency for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return defaultLowInputLatency for the device.
|
||||
*/
|
||||
public static native double PaDeviceInfo_getDefaultLowInputLatency(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Returns defaultLowOutputLatency for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return defaultLowOutputLatency for the device.
|
||||
*/
|
||||
public static native double PaDeviceInfo_getDefaultLowOutputLatency(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Returns defaultHighInputLatency for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return defaultHighInputLatency for the device.
|
||||
*/
|
||||
public static native double PaDeviceInfo_getDefaultHighInputLatency(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Returns defaultHighOutputLatency for the device.
|
||||
* @param deviceInfo device info pointer.
|
||||
* @return defaultHighOutputLatency for the device.
|
||||
*/
|
||||
public static native double PaDeviceInfo_getDefaultHighOutputLatency(long deviceInfo);
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to a structure containing information
|
||||
* about a specific host Api.
|
||||
* @param hostApiIndex host api index.
|
||||
* @return A pointer to an immutable PaHostApiInfo structure
|
||||
* describing a specific host API.
|
||||
*/
|
||||
public static native long Pa_GetHostApiInfo(int hostApiIndex);
|
||||
|
||||
/**
|
||||
* The well known unique identifier of this host API.
|
||||
* @param hostApiInfo pointer to host api info structure.
|
||||
* @return The well known unique identifier of this host API.
|
||||
* Enumerator:
|
||||
paInDevelopment
|
||||
paDirectSound
|
||||
paMME
|
||||
paASIO
|
||||
paSoundManager
|
||||
paCoreAudio
|
||||
paOSS
|
||||
paALSA
|
||||
paAL
|
||||
paBeOS
|
||||
paWDMKS
|
||||
paJACK
|
||||
paWASAPI
|
||||
paAudioScienceHPI
|
||||
*/
|
||||
public static native int PaHostApiInfo_GetType(long hostApiInfo);
|
||||
|
||||
/**
|
||||
* A textual description of the host API for display on user interfaces.
|
||||
* @param hostApiInfo pointer to host api info structure.
|
||||
* @return host api name.
|
||||
*/
|
||||
public static native String PaHostApiInfo_GetName(long hostApiInfo);
|
||||
|
||||
/**
|
||||
* The number of devices belonging to this host API.
|
||||
* @param hostApiInfo pointer to host api info structure.
|
||||
* @return The number of devices belonging to this host API.
|
||||
*/
|
||||
public static native int PaHostApiInfo_GetDeviceCount(long hostApiInfo);
|
||||
|
||||
/**
|
||||
* The default input device for this host API.
|
||||
* @param hostApiInfo pointer to host api info structure.
|
||||
* @return The default input device for this host API.
|
||||
*/
|
||||
public static native int PaHostApiInfo_GetDefaultInputDevice(long hostApiInfo);
|
||||
|
||||
/**
|
||||
* The default output device for this host API.
|
||||
* @param hostApiInfo pointer to host api info structure.
|
||||
* @return The default output device for this host API.
|
||||
*/
|
||||
public static native int PaHostApiInfo_GetDefaultOutputDevice(long hostApiInfo);
|
||||
|
||||
/**
|
||||
* Creates parameters used for opening streams.
|
||||
* @param deviceIndex the device.
|
||||
* @param channelCount the channels to be used.
|
||||
* @param sampleFormat the sample format.
|
||||
* @param suggestedLatency the suggested latency in milliseconds:
|
||||
* LATENCY_UNSEPCIFIED -
|
||||
* use default(default high input/output latency)
|
||||
* LATENCY_HIGH - use default high input/output latency
|
||||
* LATENCY_LOW - use default low input/output latency
|
||||
* ... - any other value in milliseconds (e.g. 0.1 is acceptable)
|
||||
* @return pointer to the params used for Pa_OpenStream.
|
||||
*/
|
||||
public static native long PaStreamParameters_new(
|
||||
int deviceIndex,
|
||||
int channelCount,
|
||||
long sampleFormat,
|
||||
double suggestedLatency);
|
||||
|
||||
/**
|
||||
* Prevents the creation of <code>PortAudio</code> instances.
|
||||
*/
|
||||
private PortAudio()
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio;
|
||||
|
||||
/**
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class PortAudioException
|
||||
extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
public PortAudioException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.streams.*;
|
||||
|
||||
/**
|
||||
* Manages PortAudio stream creation and setting necessary properties when using
|
||||
* them.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class PortAudioManager
|
||||
{
|
||||
/**
|
||||
* 20ms in 8kHz is 160 samples.
|
||||
*/
|
||||
public static final int NUM_SAMPLES = 160;
|
||||
|
||||
/**
|
||||
* The static instance of portaudio manager.
|
||||
*/
|
||||
private static PortAudioManager instance = null;
|
||||
|
||||
private Hashtable<Integer, MasterPortAudioStream> inputStreams =
|
||||
new Hashtable<Integer, MasterPortAudioStream>();
|
||||
|
||||
private ArrayList<OutputPortAudioStream> outputStreams =
|
||||
new ArrayList<OutputPortAudioStream>();
|
||||
|
||||
/**
|
||||
* default values for the params.
|
||||
*/
|
||||
private boolean enabledEchoCancel = false;
|
||||
private boolean enabledDeNoise = true;
|
||||
private int frameSize = NUM_SAMPLES;
|
||||
private int filterLength = 2048;
|
||||
|
||||
private static double suggestedLatency = PortAudio.LATENCY_UNSEPCIFIED;
|
||||
|
||||
/**
|
||||
* Private constructor as we have one static instance of this manager.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
private PortAudioManager()
|
||||
throws PortAudioException
|
||||
{
|
||||
PortAudio.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the only instance of PortAudioManager, if its not already created
|
||||
* will be created.
|
||||
* @return the static instance.
|
||||
* @throws PortAudioException if portaudio cannot be initialized for
|
||||
* some reason.
|
||||
*/
|
||||
public static PortAudioManager getInstance()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(instance == null)
|
||||
instance = new PortAudioManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates input stream from the device with given index.
|
||||
* @param deviceIndex the device index.
|
||||
* @param sampleRate the sample rate to use, its the sample rate of the
|
||||
* input stream.
|
||||
* @param channels the channels that the stream will serve.
|
||||
* @return the stream.
|
||||
* @throws PortAudioException if opening of the stream failes.
|
||||
*/
|
||||
public InputPortAudioStream getInputStream(
|
||||
int deviceIndex, double sampleRate, int channels)
|
||||
throws PortAudioException
|
||||
{
|
||||
MasterPortAudioStream st = inputStreams.get(deviceIndex);
|
||||
if(st == null)
|
||||
{
|
||||
st = new MasterPortAudioStream(deviceIndex, sampleRate, channels);
|
||||
inputStreams.put(deviceIndex, st);
|
||||
|
||||
// if there is a output streams, get the latest one
|
||||
// and connect them
|
||||
// todo: we must link input to all outputs ???
|
||||
if(isEnabledEchoCancel() && outputStreams.size() > 0)
|
||||
{
|
||||
OutputPortAudioStream out = outputStreams.get(
|
||||
outputStreams.size() - 1);
|
||||
st.setParams(out, isEnabledDeNoise(),
|
||||
isEnabledEchoCancel(), getFrameSize(), getFilterLength());
|
||||
}
|
||||
else
|
||||
st.setParams(null, isEnabledDeNoise(),
|
||||
isEnabledEchoCancel(), getFrameSize(), getFilterLength());
|
||||
}
|
||||
|
||||
return new InputPortAudioStream(st);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates output stream from the device with given index.
|
||||
* @param deviceIndex the device index.
|
||||
* @param sampleRate the sample rate to use, its the sample rate of the
|
||||
* output stream.
|
||||
* @param channels the channels that the stream will serve.
|
||||
* @return the stream.
|
||||
* @throws PortAudioException if opening of the stream failes.
|
||||
*/
|
||||
public OutputPortAudioStream getOutputStream(
|
||||
int deviceIndex, double sampleRate, int channels)
|
||||
throws PortAudioException
|
||||
{
|
||||
OutputPortAudioStream out =
|
||||
new OutputPortAudioStream(deviceIndex, sampleRate, channels);
|
||||
outputStreams.add(out);
|
||||
|
||||
// if there are input streams created, get the first one
|
||||
// and link it to this output
|
||||
// todo: what to do with the others
|
||||
if(isEnabledEchoCancel() && inputStreams.size() > 0)
|
||||
{
|
||||
MasterPortAudioStream st = inputStreams.values().iterator().next();
|
||||
|
||||
st.setParams(out, isEnabledEchoCancel(),
|
||||
isEnabledDeNoise(), getFrameSize(), getFilterLength());
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output stream is stopped.
|
||||
* @param st the stream that is stopped.
|
||||
*/
|
||||
public void stoppedOutputPortAudioStream(OutputPortAudioStream st)
|
||||
{
|
||||
outputStreams.remove(st);
|
||||
}
|
||||
|
||||
/**
|
||||
* Input stream is stopped.
|
||||
* @param st the input stream that is stopped.
|
||||
*/
|
||||
public void stoppedInputPortAudioStream(MasterPortAudioStream st)
|
||||
{
|
||||
inputStreams.remove(st.getDeviceIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates output stream from the device with given index.
|
||||
* @param deviceIndex the device index.
|
||||
* @param sampleRate the sample rate to use, its the sample rate of the
|
||||
* output stream.
|
||||
* @param channels the channels that the stream will serve.
|
||||
* @param sampleFormat the format the will be used by the stream.
|
||||
* @return the stream.
|
||||
* @throws PortAudioException if opening of the stream failes.
|
||||
*/
|
||||
public OutputPortAudioStream getOutputStream(
|
||||
int deviceIndex, double sampleRate, int channels, long sampleFormat)
|
||||
throws PortAudioException
|
||||
{
|
||||
return new OutputPortAudioStream(
|
||||
deviceIndex, sampleRate, channels, sampleFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables echo cancel.
|
||||
* @param enabled should we enable or disable echo cancelation
|
||||
* @param frameSize Number of samples to process at one time
|
||||
* (should correspond to 10-20 ms)
|
||||
* @param filterLength Number of samples of echo to cancel
|
||||
* (should generally correspond to 100-500 ms)
|
||||
*/
|
||||
public void setEchoCancel(boolean enabled, int frameSize, int filterLength)
|
||||
{
|
||||
this.enabledEchoCancel = enabled;
|
||||
this.frameSize = frameSize;
|
||||
this.filterLength = filterLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables noise suppression.
|
||||
* @param enabled should we enable or disable noise suppression.
|
||||
*/
|
||||
public void setDeNoise(boolean enabled)
|
||||
{
|
||||
this.enabledDeNoise = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default values of the latency to be used when
|
||||
* openning new streams.
|
||||
* @return the latency.
|
||||
*/
|
||||
public static double getSuggestedLatency()
|
||||
{
|
||||
if(suggestedLatency != PortAudio.LATENCY_UNSEPCIFIED)
|
||||
return suggestedLatency;
|
||||
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.startsWith("Mac"))
|
||||
return PortAudio.LATENCY_HIGH;
|
||||
else if (osName.startsWith("Linux"))
|
||||
return PortAudio.LATENCY_HIGH;
|
||||
else if (osName.startsWith("Windows"))
|
||||
return 0.1d;
|
||||
return PortAudio.LATENCY_UNSEPCIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the suggested latency.
|
||||
* @param aSuggestedLatency the suggestedLatency to set.
|
||||
*/
|
||||
public static void setSuggestedLatency(double aSuggestedLatency)
|
||||
{
|
||||
suggestedLatency = aSuggestedLatency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is echo cancel enabled.
|
||||
* @return true if echo cancel is enabled, false otherwise.
|
||||
*/
|
||||
public boolean isEnabledEchoCancel()
|
||||
{
|
||||
return enabledEchoCancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is noise reduction enabled.
|
||||
* @return true if noise reduction is enabled, false otherwise.
|
||||
*/
|
||||
public boolean isEnabledDeNoise()
|
||||
{
|
||||
return enabledDeNoise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of samples to process at one time (should correspond to 10-20 ms).
|
||||
* @return the frameSize.
|
||||
*/
|
||||
public int getFrameSize()
|
||||
{
|
||||
return frameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of samples of echo to cancel
|
||||
* (should generally correspond to 100-500 ms)
|
||||
* @return the filterLength.
|
||||
*/
|
||||
public int getFilterLength()
|
||||
{
|
||||
return filterLength;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public interface PortAudioStreamCallback
|
||||
{
|
||||
public static final int RESULT_ABORT = 2;
|
||||
|
||||
public static final int RESULT_COMPLETE = 1;
|
||||
|
||||
public static final int RESULT_CONTINUE = 0;
|
||||
|
||||
public int callback(ByteBuffer input, ByteBuffer output);
|
||||
|
||||
public void finishedCallback();
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio;
|
||||
|
||||
import javax.media.*;
|
||||
|
||||
/**
|
||||
* Common used util methods concerning PortAudio.
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class PortAudioUtils
|
||||
{
|
||||
/**
|
||||
* The locator prefix used when creating or parsing <tt>MediaLocator</tt>s.
|
||||
*/
|
||||
public static final String LOCATOR_PREFIX = "portaudio:#";
|
||||
|
||||
/**
|
||||
* Extracts the device index from the locator.
|
||||
* @param locator the locator containing the device index.
|
||||
* @return the extracted device index.
|
||||
*/
|
||||
public static int getDeviceIndexFromLocator(MediaLocator locator)
|
||||
{
|
||||
return Integer.parseInt(locator.toExternalForm().replace(
|
||||
LOCATOR_PREFIX, ""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PortAudio sample format.
|
||||
* @param sampleSizeInBits the size in bits.
|
||||
* @return the portaudio sampleformat.
|
||||
*/
|
||||
public static long getPortAudioSampleFormat(int sampleSizeInBits)
|
||||
{
|
||||
switch(sampleSizeInBits)
|
||||
{
|
||||
case 8 : return PortAudio.SAMPLE_FORMAT_INT8;
|
||||
case 16 : return PortAudio.SAMPLE_FORMAT_INT16;
|
||||
case 24 : return PortAudio.SAMPLE_FORMAT_INT24;
|
||||
case 32 : return PortAudio.SAMPLE_FORMAT_INT32;
|
||||
default : return PortAudio.SAMPLE_FORMAT_INT16;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio.streams;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException;
|
||||
import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*;
|
||||
|
||||
/**
|
||||
* The input audio stream.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class InputPortAudioStream
|
||||
{
|
||||
private final MasterPortAudioStream parentStream;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
/**
|
||||
* The buffer to return.
|
||||
*/
|
||||
protected byte[] buffer = null;
|
||||
|
||||
/**
|
||||
* Creates new input stream (slave) with master input stream.
|
||||
* @param st the parent(master) input stream.
|
||||
*/
|
||||
public InputPortAudioStream(MasterPortAudioStream st)
|
||||
{
|
||||
this.parentStream = st;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block and read a buffer from the stream if there is no buffer.
|
||||
*
|
||||
* @return the bytes that a read from underlying stream.
|
||||
* @throws PortAudioException if an error occurs while reading.
|
||||
*/
|
||||
public byte[] read()
|
||||
throws PortAudioException
|
||||
{
|
||||
synchronized(parentStream)
|
||||
{
|
||||
byte[] res = buffer;
|
||||
|
||||
if(res == null)
|
||||
res = parentStream.read();
|
||||
buffer = null;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the stream. Also starts the parent stream
|
||||
* if its not already started.
|
||||
* @throws PortAudioException if stream cannot be started.
|
||||
*/
|
||||
public synchronized void start()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(started)
|
||||
return;
|
||||
|
||||
parentStream.start(this);
|
||||
started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the stream. Also stops the parent if we are the last slave
|
||||
* stream that use it.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public synchronized void stop()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
|
||||
parentStream.stop(this);
|
||||
started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The parent can set a buffer that was requested and read by other
|
||||
* slave stream.
|
||||
* @param buffer the buffer to set.
|
||||
*/
|
||||
public void setBuffer(byte[] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio.streams;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioManager;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudio;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException;
|
||||
import java.util.*;
|
||||
import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*;
|
||||
|
||||
/**
|
||||
* The master audio stream which opens the PortAudio stream and reads from it.
|
||||
* We can have multiple slave input streams that are connected to this master
|
||||
* stream.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
* @author Lubomir Marinov
|
||||
*/
|
||||
public class MasterPortAudioStream
|
||||
{
|
||||
private int deviceIndex = -1;
|
||||
|
||||
private long stream = 0;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
private int frameSize;
|
||||
|
||||
private int numberOfStarts = 0;
|
||||
|
||||
double sampleRate;
|
||||
int channels;
|
||||
|
||||
private final List<InputPortAudioStream> slaves
|
||||
= new ArrayList<InputPortAudioStream>();
|
||||
|
||||
/**
|
||||
* Creates new stream.
|
||||
* @param deviceIndex the device to use.
|
||||
* @param channels the channels to serve.
|
||||
* @param sampleRate the sample rate.
|
||||
* @throws PortAudioException if stream cannot be opened.
|
||||
*/
|
||||
public MasterPortAudioStream(
|
||||
int deviceIndex, double sampleRate, int channels)
|
||||
throws PortAudioException
|
||||
{
|
||||
this.deviceIndex = deviceIndex;
|
||||
this.sampleRate = sampleRate;
|
||||
this.channels = channels;
|
||||
|
||||
initStream();
|
||||
|
||||
frameSize
|
||||
= PortAudio.Pa_GetSampleSize(PortAudio.SAMPLE_FORMAT_INT16)
|
||||
* channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the stream.
|
||||
* @throws PortAudioException if stream cannot be opened.
|
||||
*/
|
||||
private void initStream()
|
||||
throws PortAudioException
|
||||
{
|
||||
long parameters = PortAudio.PaStreamParameters_new(
|
||||
deviceIndex,
|
||||
channels,
|
||||
PortAudio.SAMPLE_FORMAT_INT16,
|
||||
PortAudioManager.getSuggestedLatency());
|
||||
|
||||
stream = PortAudio.Pa_OpenStream(
|
||||
parameters,
|
||||
0, // no output parameters
|
||||
sampleRate,
|
||||
PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED,
|
||||
PortAudio.STREAM_FLAGS_CLIP_OFF
|
||||
| PortAudio.STREAM_FLAGS_DITHER_OFF,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the stream operation if not already started
|
||||
* and stores the slave inputstream
|
||||
* that starts us.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
synchronized void start(InputPortAudioStream slave)
|
||||
throws PortAudioException
|
||||
{
|
||||
if(numberOfStarts == 0)
|
||||
{
|
||||
if(stream == 0)
|
||||
initStream();
|
||||
|
||||
// start
|
||||
PortAudio.Pa_StartStream(stream);
|
||||
started = true;
|
||||
}
|
||||
|
||||
slaves.add(slave);
|
||||
numberOfStarts++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the PortAudio stream if requested by the last stream that uses us.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
synchronized void stop(InputPortAudioStream slave)
|
||||
throws PortAudioException
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
|
||||
slaves.remove(slave);
|
||||
numberOfStarts--;
|
||||
|
||||
if(numberOfStarts == 0)
|
||||
{
|
||||
// stop
|
||||
PortAudio.Pa_CloseStream(stream);
|
||||
stream = 0;
|
||||
started = false;
|
||||
PortAudioManager.getInstance().stoppedInputPortAudioStream(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the device that we use.
|
||||
* @return the deviceIndex
|
||||
*/
|
||||
public int getDeviceIndex()
|
||||
{
|
||||
return deviceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the stream that we use for reading.
|
||||
* @return the stream pointer.
|
||||
*/
|
||||
public long getStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block and read a buffer from the stream.
|
||||
*
|
||||
* @return the bytes that a read from underlying stream.
|
||||
* @throws PortAudioException if an error occurs while reading.
|
||||
*/
|
||||
public byte[] read()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(!started)
|
||||
return new byte[0];
|
||||
|
||||
byte[] bytebuff = new byte[PortAudioManager.NUM_SAMPLES*frameSize];
|
||||
PortAudio.Pa_ReadStream(
|
||||
stream, bytebuff, PortAudioManager.NUM_SAMPLES);
|
||||
|
||||
for(InputPortAudioStream slave : slaves)
|
||||
slave.setBuffer(bytebuff);
|
||||
|
||||
return bytebuff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets parameters to the underlying stream.
|
||||
* @param out the connected output stream if echo cancel is enabled.
|
||||
* @param deNoiseEnabled true if we want to enable noise reduction.
|
||||
* @param echoCancelEnabled true to enable echo cancel.
|
||||
* @param frameSize Number of samples to process at one time
|
||||
* (should correspond to 10-20 ms).
|
||||
* @param filterLength Number of samples of echo to cancel
|
||||
* (should generally correspond to 100-500 ms)
|
||||
*/
|
||||
public void setParams(OutputPortAudioStream out,
|
||||
boolean deNoiseEnabled,
|
||||
boolean echoCancelEnabled, int frameSize, int filterLength)
|
||||
{
|
||||
long outStream = 0;
|
||||
|
||||
if(out != null)
|
||||
outStream = out.getStream();
|
||||
|
||||
PortAudio.setEchoCancelParams(
|
||||
stream,
|
||||
outStream,
|
||||
deNoiseEnabled,
|
||||
echoCancelEnabled, frameSize, filterLength);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.neomedia.portaudio.streams;
|
||||
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioManager;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudio;
|
||||
import net.java.sip.communicator.impl.neomedia.portaudio.PortAudioException;
|
||||
import net.java.sip.communicator.impl.neomedia.jmfext.media.protocol.portaudio.*;
|
||||
|
||||
/**
|
||||
* The output stream that opens and writes to the PortAudio stream.
|
||||
*
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class OutputPortAudioStream
|
||||
{
|
||||
private int deviceIndex = -1;
|
||||
private long stream = 0;
|
||||
private byte[] bufferLeft = null;
|
||||
private int frameSize;
|
||||
private boolean started = false;
|
||||
|
||||
private double sampleRate;
|
||||
private int channels;
|
||||
private long sampleFormat;
|
||||
|
||||
/**
|
||||
* Creates output stream.
|
||||
* @param deviceIndex the index of the device to use.
|
||||
* @param sampleRate the samepl rate.
|
||||
* @param channels the channels to serve.
|
||||
* @throws PortAudioException if stream fails to open.
|
||||
*/
|
||||
public OutputPortAudioStream(
|
||||
int deviceIndex, double sampleRate, int channels)
|
||||
throws PortAudioException
|
||||
{
|
||||
this(deviceIndex, sampleRate, channels, PortAudio.SAMPLE_FORMAT_INT16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates output stream.
|
||||
* @param deviceIndex the index of the device to use.
|
||||
* @param sampleRate the samepl rate.
|
||||
* @param channels the channels to serve.
|
||||
* @param sampleFormat the sample format to use.
|
||||
* @throws PortAudioException if stream fails to open.
|
||||
*/
|
||||
public OutputPortAudioStream(
|
||||
int deviceIndex, double sampleRate, int channels, long sampleFormat)
|
||||
throws PortAudioException
|
||||
{
|
||||
this.deviceIndex = deviceIndex;
|
||||
this.sampleRate = sampleRate;
|
||||
this.channels = channels;
|
||||
this.sampleFormat = sampleFormat;
|
||||
|
||||
initStream();
|
||||
|
||||
frameSize = PortAudio.Pa_GetSampleSize(sampleFormat)*channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the PortAudio stream.
|
||||
* @throws PortAudioException if stream fails to open.
|
||||
*/
|
||||
private void initStream()
|
||||
throws PortAudioException
|
||||
{
|
||||
long parameters = PortAudio.PaStreamParameters_new(
|
||||
getDeviceIndex(),channels,
|
||||
sampleFormat,
|
||||
PortAudioManager.getSuggestedLatency());
|
||||
|
||||
stream = PortAudio.Pa_OpenStream(
|
||||
0,
|
||||
parameters,
|
||||
sampleRate,
|
||||
PortAudio.FRAMES_PER_BUFFER_UNSPECIFIED,
|
||||
PortAudio.STREAM_FLAGS_CLIP_OFF
|
||||
| PortAudio.STREAM_FLAGS_DITHER_OFF,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* We will split everything into parts of PortAudioManager.NUM_SAMPLES.
|
||||
* If something is left we will save it for next write and use it than.
|
||||
*
|
||||
* @param buffer the current buffer.
|
||||
* @throws PortAudioException error while writing to device.
|
||||
*/
|
||||
public synchronized void write(byte[] buffer)
|
||||
throws PortAudioException
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
|
||||
int numSamples = PortAudioManager.NUM_SAMPLES*frameSize;
|
||||
|
||||
int currentIx = 0;
|
||||
|
||||
// if there are bytes from previous run
|
||||
if(bufferLeft != null && bufferLeft.length > 0)
|
||||
{
|
||||
if(buffer.length + bufferLeft.length >= numSamples)
|
||||
{
|
||||
byte[] tmp = new byte[numSamples];
|
||||
System.arraycopy(bufferLeft, 0, tmp, 0, bufferLeft.length);
|
||||
System.arraycopy(buffer, currentIx, tmp,
|
||||
bufferLeft.length, numSamples - bufferLeft.length);
|
||||
currentIx += numSamples - bufferLeft.length;
|
||||
bufferLeft = null;
|
||||
|
||||
PortAudio.Pa_WriteStream(
|
||||
getStream(),tmp, tmp.length/frameSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// not enough bytes even with previous left
|
||||
// so let store everything
|
||||
byte[] tmp = new byte[numSamples];
|
||||
System.arraycopy(bufferLeft, 0, tmp, 0, bufferLeft.length);
|
||||
System.arraycopy(buffer, currentIx, tmp,
|
||||
bufferLeft.length, numSamples - bufferLeft.length);
|
||||
bufferLeft = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// now use all the current buffer
|
||||
if(buffer.length > numSamples)
|
||||
{
|
||||
while(currentIx <= buffer.length - numSamples)
|
||||
{
|
||||
byte[] tmp = new byte[numSamples];
|
||||
System.arraycopy(buffer, currentIx, tmp, 0, numSamples);
|
||||
|
||||
PortAudio.Pa_WriteStream(
|
||||
getStream(),tmp, tmp.length/frameSize);
|
||||
currentIx += numSamples;
|
||||
}
|
||||
|
||||
if(currentIx < buffer.length)
|
||||
{
|
||||
bufferLeft = new byte[buffer.length - currentIx];
|
||||
System.arraycopy(buffer, currentIx, bufferLeft, 0, bufferLeft.length);
|
||||
}
|
||||
}
|
||||
else if(buffer.length < numSamples)
|
||||
{
|
||||
bufferLeft = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
PortAudio.Pa_WriteStream(
|
||||
getStream(),buffer, buffer.length/frameSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the stream operation
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public synchronized void start()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(started)
|
||||
return;
|
||||
|
||||
if(getStream() == 0)
|
||||
initStream();
|
||||
|
||||
// start
|
||||
PortAudio.Pa_StartStream(getStream());
|
||||
started = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the stream operation.
|
||||
* @throws PortAudioException
|
||||
*/
|
||||
public void stop()
|
||||
throws PortAudioException
|
||||
{
|
||||
if(!started)
|
||||
return;
|
||||
|
||||
// stop
|
||||
PortAudio.Pa_CloseStream(getStream());
|
||||
|
||||
synchronized(this)
|
||||
{
|
||||
stream = 0;
|
||||
bufferLeft = null;
|
||||
started = false;
|
||||
PortAudioManager.getInstance().stoppedOutputPortAudioStream(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The index of the device that we use.
|
||||
* @return the deviceIndex
|
||||
*/
|
||||
public int getDeviceIndex()
|
||||
{
|
||||
return deviceIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* The pointer of the PortAudio stream.
|
||||
* @return the stream pointer.
|
||||
*/
|
||||
public long getStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue