Ich habe eine grundlegende Audioorecord-Audiotrack, UDP-Pakete Voice-Chat zwischen zwei Android-Geräten. Es funktioniert, aber ich habe ein schlechtes Echo. Ich versuche, das Echo mit Speex zu entfernen, das von JNI nach Android portiert wurde. Die von mir importierte Speex funktioniert, aber die Echokompensation nicht. Nativen C-Code ist:Android Speex Echokompensation Probleme
#include <jni.h>
#include <speex/speex_echo.h>
#define FRAME_SIZE 256
#define FILTER_LENGTH 800
SpeexEchoState *echoState;
// Initialization of echo cancelation
void Java_telefonie_voip_VoIPActivity_InitEcho(JNIEnv * env, jobject jobj)
{
echoState = speex_echo_state_init(FRAME_SIZE, FILTER_LENGTH);
}
// Queue the frame to soundcard for playing (receiving)
void Java_telefonie_voip_VoIPActivity_Playback(JNIEnv * env, jobject jobj, jshortArray inputFrame)
{
speex_echo_playback(echoState, inputFrame);
}
jshortArray Java_telefonie_voip_VoIPActivity_Capture(JNIEnv * env, jobject jobj, jshortArray inputFrame)
{
jshortArray outputFrame;
speex_echo_capture(echoState, inputFrame, *&outputFrame);
return outputFrame;
}
// Destroing echo cancelation
void Java_telefonie_voip_VoIPActivity_DestroyEcho(JNIEnv * env, jobject jobj)
{
speex_echo_state_destroy(echoState);
}
Und einige wichtige Java-Code:
native void InitEcho();
native void DestroyEcho();
native void Playback(short[] inputData); // listener/receiving
native short[] Capture(short[] inputData); // recorder/sender
static {
System.loadLibrary("speex");
}
public void Initialize()
{
minBufferSize = 4096;
try
{
InitEcho();
}
catch (Exception e){Log.e(TAG, "jni " + e.getMessage());}
}
public void startRecording()
{
isStreaming = true;
streamingThread = new Thread(new Runnable(){
@Override
public void run()
{
try
{
audioRecorder = new AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
channelConfig,
audioFormat,
minBufferSize*10
);
buffer = new short[minBufferSize];
audioRecorder.startRecording();
while(isStreaming)
{
sendPackets++;
minBufferSize = audioRecorder.read(buffer, 0, buffer.length);
// Echo cancelling
buffer = Capture(buffer);
// Send
dataPacket = new DatagramPacket(ShortToByteArray(buffer), buffer.length*2, receiverAddressIA, serverPort1);
dataSocket.send(dataPacket);
}
}
catch(Exception e)
{
Log.e(TAG, "2" + e.getMessage());
}
}
});
streamingThread.start();
}
public void startListen()
{
isListening = true;
receivingThread = new Thread(new Runnable(){
@Override
public void run()
{
try
{
audioTrack = new AudioTrack(
AudioManager.STREAM_VOICE_CALL,
sampleRate,
channelConfig,
audioFormat,
minBufferSize*10,
AudioTrack.MODE_STREAM
);
audioTrack.play();
buffer2 = new short[minBufferSize];
while (isListening)
{
receivedPackets++;
dataPacket2 = new DatagramPacket(ShortToByteArray(buffer2), buffer2.length*2);
dataSocket2.receive(dataPacket2);
// Cancel echo
Playback(buffer2);
// Queue to soundcard
audioTrack.write(buffer2, 0, minBufferSize);
}
}
catch(Exception e)
{
Log.e(TAG, "3" + e.getMessage());
}
}
});
receivingThread.start();
}
public short[] ByteToShortArray(byte[] byteArray)
{
short[] shortArray = new short[byteArray.length/2];
ByteBuffer.wrap(byteArray).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(shortArray);
return shortArray;
}
Das Problem ist, dass, wenn ich den Recorder/Streaming-Thread starten, es zeigt mir, dass es ein Paket sendet und dann die App stürzt ohne Nachricht ab. Haben Sie Anregungen oder Ratschläge? Bitte helfen Sie mir, weil ich dieses Projekt so schnell wie möglich machen muss und ich habe hart gearbeitet und mich selbst dokumentiert, aber trotzdem will es nicht gut funktionieren. Vielen Dank!
Edit: Ich habe das
// Echo cancelling
buffer = Capture(buffer);
auslöst den Absturz gerade entdeckt.
Ein Update zu meiner Antwort entsprechend Ihrem Update zum Absturz hinzugefügt. – SirKnigget
Hallo Emil Pana hast du erfolgreich das Echo entfernt? –
Haben Sie das Problem schon einmal gelöst? – aProgrammer