Qt 5.2.0에서 Speex Accoustic Echo Cancellation을 사용하려고했으나 반향 부분 만 제거되었지만 여전히 남아 있습니다.
여기 내 테스트가 있습니다 (메모리 관리에 최적화되지 않았습니다). 음성을 녹음하고, 에코를 제거하고, 실제로 작은 에코 제거로 400ms 후에 재생합니다.
내 코드가 어디에서 잘못 되었습니까?
Speex AEC는 반향 부분 만 제거합니다.
//************
// declared in MainWindows.h
QAudioInput* m_audioInput;
QAudioOutput* m_audioOutput;
QIODevice* m_ioIn;
QIODevice* m_ioOut;
QList<QByteArray> m_listBA;
//************
void MainWindow::InitSpeex()
{
int loc_samplingRate=16000;
int loc_frameSize=320;
m_echo_state = speex_echo_state_init(loc_frameSize, 10*loc_frameSize);
speex_echo_ctl(m_echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &loc_samplingRate);
m_preprocess = speex_preprocess_state_init(loc_frameSize, loc_samplingRate);
}
void MainWindow::DestroySpeex()
{
speex_echo_state_destroy(m_echo_state);
speex_preprocess_state_destroy(m_preprocess);
m_echo_state = NULL;
m_preprocess = NULL;
}
void MainWindow::Start()
{
QAudioFormat format;
// Set up the desired format, for example:
format.setSampleRate(SAMPLING_RATE);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo loc_infoInput = QAudioDeviceInfo::defaultInputDevice();
if (!loc_infoInput.isFormatSupported(format)) {
qWarning() << "Default format not supported, trying to use the nearest.";
format = loc_infoInput.nearestFormat(format);
}
m_audioInput = new QAudioInput(format, this);
QAudioDeviceInfo loc_infoOutput(QAudioDeviceInfo::defaultOutputDevice());
if (!loc_infoOutput.isFormatSupported(format)) {
qWarning() << "Raw audio format not supported by backend, cannot play audio.";
return;
}
m_audioOutput = new QAudioOutput(format, this);
m_ioIn = m_audioInput->start();
m_ioOut = m_audioOutput->start();
connect(m_ioIn, SIGNAL(readyRead()), this, SLOT(on_data_input()));
}
void MainWindow::on_data_input()
{
// push data on the list
m_listBA.push_back(m_ioIn->readAll());
// il list is about 400ms of sample
if(m_listBA.size() > 20)
{
// send oldest sample to speex and play it
speex_echo_playback(m_echo_state, (spx_int16_t*)m_listBA[1].constData());
m_ioOut->write(m_listBA.takeFirst());
// get most recent sample, remove echo and repush it on the list to be played later
speex_echo_capture(m_echo_state, (spx_int16_t*)m_listBA[m_listBA.size()-1].data(), m_AECBufferOut);
loc_vad = speex_preprocess_run(m_preprocess, m_AECBufferOut);
m_listBA.takeLast();
m_listBA.push_back(QByteArray((const char*)m_AECBufferOut, sizeof(m_AECBufferOut)));
}
}
이 테스트는 에코 제거없이 정상적으로 작동하며 음성은 녹음되고 400ms 후에 재생되어 LIFO로 인한 네트워크 지연을 시뮬레이션합니다.
메모리 또는 포인터 크기에는 문제가 없습니다. 문제는 부분적으로 에코가 제거 되어도 계속들을 수 있다는 것입니다. – Pierre