2014-01-21 24 views
1

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))); 
    } 
} 

답변

0

난 당신이 m_listBA으로 뭘 하려는지 궁금하네요. 분명히 그것은 FIFO이지만, 당신은 [0]을 사용하지 않습니다.

왜 몇 줄 뒤에서 제거하기 위해 원시 입력을 목록에 추가하는 이유는 무엇입니까?

마지막으로 m_AECBufferOut은 포인터 일 수 있습니다. 이 경우 sizeof(m_AECBufferOut)은 아마도 4 또는 8입니다. 출력의 바이트 수가 아닙니다.

기본적으로 설정을 으로 설정하고 반향 제거를 사용하지 않고 지연이 추가되는지 확인하십시오. 그래야만 에코 취소 작동을 시도해야합니다. 첫 번째 부분이 작동하면 여기에 게시 할 필요가 없습니다.

+0

이 테스트는 에코 제거없이 정상적으로 작동하며 음성은 녹음되고 400ms 후에 재생되어 LIFO로 인한 네트워크 지연을 시뮬레이션합니다.
메모리 또는 포인터 크기에는 문제가 없습니다. 문제는 부분적으로 에코가 제거 되어도 계속들을 수 있다는 것입니다. – Pierre