Шумоподавление с помощью speex
У меня есть Java-приложение, создающее живой поток на RTMP-сервер, я хочу отменить шум, используя speex через JNI, я делаю реализацию jni очень хорошо, но в java-приложении он хорошо обрабатывает короткий массив, но результаты во флеш-плеере для потока не очень хорошие звук очень непонятный.
я покажу вам простой код, чтобы получить представление о том, что сделано в коде, и что не так в моем коде
здесь код c для jni
#include <jni.h>
#include "speex/speex_preprocess.h"
#include "speex_pushStream.h"
SpeexPreprocessState *st;
int i;
float f;
JNIEXPORT void JNICALL Java_speex_pushStream_echoCanceller_1open
(JNIEnv *env, jobject jObj, jint jSampleRate, jint jBufSize)
{
int sampleRate = jSampleRate;
st = speex_preprocess_state_init(jBufSize , sampleRate);
i = 1;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i);
i = 0;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);
i = sampleRate;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
i = 0;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i);
f = .0;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
f = .0;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
}
JNIEXPORT jshortArray JNICALL Java_speex_pushStream_cancel_1noise
(JNIEnv *env , jobject jObj , jshortArray input_frame)
{
//create native shorts from java shorts
jshort *native_input_frame = (*env)->GetShortArrayElements(env, input_frame, NULL);
//allocate memory for output data
jint length = (*env)->GetArrayLength(env, input_frame);
jshortArray temp = (*env)->NewShortArray(env, length);
jshort *native_output_frame = (*env)->GetShortArrayElements(env, temp, 0);
//preprocess output frame
speex_preprocess_run(st , native_input_frame);
//convert native output to java layer output
jshortArray output_shorts = (*env)->NewShortArray(env, length);
(*env)->SetShortArrayRegion(env, output_shorts, 0, length, native_input_frame);
//cleanup and return
(*env)->ReleaseShortArrayElements(env, input_frame, native_input_frame, 0);
(*env)->ReleaseShortArrayElements(env, temp, native_output_frame, 0);
return output_shorts;
}
JNIEXPORT void JNICALL Java_speex_pushStream_close_1noise
(JNIEnv *env , jobject jObj)
{
speex_preprocess_state_destroy(st);
}
и это часть потоковой передачи в приложении Java
new Thread(new Runnable() {
private int rate;
private int numChannels;
private byte[] audioBytes;
@Override
public void run() {
final float sampleRate = sampleAudioRateInHz;
int sampleSizeBit = 16;
int channel = audioChannel;
boolean signed = true;
boolean endian = false;
AudioFormat audioFormat = new AudioFormat(sampleRate , sampleSizeBit , channel , signed , endian );
Mixer.Info[] minfoSet = AudioSystem.getMixerInfo();
Mixer mixer = AudioSystem.getMixer(minfoSet[AUDIO_DEVICE_INDEX]);
final DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
try {
line = (TargetDataLine)AudioSystem.getLine(dataLineInfo);
line.open(audioFormat);
line.start();
rate = (int) audioFormat.getSampleRate();
numChannels = audioFormat.getChannels();
// Let's initialize our audio buffer...
int audioBufferSize = rate * numChannels;
audioBytes = new byte[audioBufferSize];
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
int nBytesRead = 0;
while (nBytesRead == 0) {// filterNoise(audioBytes , 2) filterNoise(audioBytes , 10)
nBytesRead = line.read( audioBytes , 0 , line.available());
}
int nSamplesRead = nBytesRead / 2;
short[] samples = new short[nSamplesRead];
//System.out.println("sample length: " + nSamplesRead + " length : " + samples.length );
echoCanceller_open((int)sampleRate , nSamplesRead); // nSamplesRead);
//echoCanceller_open((int)sampleRate , nSamplesRead , 0);
ByteBuffer.wrap(audioBytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(samples);
ShortBuffer sBuff = null;
short tmp[] = samples; // cancel_noise(samples);
for(short frame : tmp)
{
System.out.println( "two: " + frame);
}
sBuff = ShortBuffer.wrap( tmp , 0, samples.length); //cancel_noise(samples)
close_noise();
recorder.recordSamples( rate , numChannels, sBuff );
} catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 0, (long) ((long) 1000 / frameRate) , TimeUnit.MILLISECONDS);
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
}).start();
я хочу знать, есть ли проблема на Java-приложение или код C спасибо