direct sound captured audio sample rate is not correct

41 views Asked by At

guys. I am using direct sound to capture audio from microphone. Everything was fine except captured sample rate is not correct. Sample rate I got was 2/3 of what I required. I don't know what is wrong with it.

Here's a piece of codes of initialization.

long audio_rec::init_capture_buffer(
    const long dwNotifyArraySize,
    const long dwNotifyTickInterval,
    const GUID& guidDevice,
    const WAVEFORMATEX& wfxInput)
{
    HRESULT hr = S_OK;
    SAFE_RELEASE(m_pDSCapture);       // LPDIRECTSOUNDCAPTURE
    SAFE_RELEASE(m_pDSNotify);        // LPDIRECTSOUNDNOTIFY
    SAFE_RELEASE(m_pDSCaptureBuffer); // LPDIRECTSOUNDCAPTUREBUFFER
    SAFE_DELETE_ARRAY(m_pNotifyArray);// LPDSBPOSITIONNOTIFY

    //  Save Notify Array Size
    m_dwNotifyArraySize = dwNotifyArraySize;

    //  Init Notification Event
    if (nullptr == m_hNotificationEvent) {
        m_hNotificationEvent = ::CreateEventW(NULL, FALSE, FALSE, NULL);
    }
    if (m_hNotificationEvent) { ::ResetEvent(m_hNotificationEvent); }

    //  Init Direct Sound
    // Create IDirectSoundCapture using the preferred capture device
    if (FAILED(hr = ::DirectSoundCaptureCreate(&guidDevice, &m_pDSCapture, NULL))) {
        return hr;
    }

    //  Allocate Buffer for Recording
    //  Create Capture Buffer
    //  Initialize Notification
    long dwNotifyByteInterval
        = (long)(((dwNotifyTickInterval) / 1000.0) * mic_wfx.nAvgBytesPerSec);
    dwNotifyByteInterval -= dwNotifyByteInterval % mic_wfx.nBlockAlign;
    m_dwNotifyByteInterval = dwNotifyByteInterval;

    // Set the buffer sizes    
    m_dwBufferSize = dwNotifyByteInterval * dwNotifyArraySize;

    // Set the format during creatation 
    DSCBUFFERDESC dscbd = { 0 };
    dscbd.dwSize = sizeof(dscbd);
    dscbd.dwBufferBytes = m_dwBufferSize;
    dscbd.lpwfxFormat = (LPWAVEFORMATEX)&wfxInput;

    // Create the capture buffer   
    if (FAILED(hr = m_pDSCapture->CreateCaptureBuffer(&dscbd, &m_pDSCaptureBuffer, nullptr))) {
        SAFE_RELEASE(m_pDSCapture);
        return hr;
    }
    
    //  Set Notification
    if (FAILED(hr = m_pDSCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, (VOID**)&m_pDSNotify))) {
        SAFE_RELEASE(m_pDSCapture);
        SAFE_RELEASE(m_pDSCaptureBuffer);
        return hr;
    }

    //  Allocate Notification Array
    if (m_pNotifyArray) { SAFE_DELETE_ARRAY(m_pNotifyArray); }
    m_pNotifyArray = new DSBPOSITIONNOTIFY[dwNotifyArraySize + 1];
    ::memset(m_pNotifyArray, 0, sizeof(DSBPOSITIONNOTIFY) * (dwNotifyArraySize + 1));

    // Setup the notification positions   
    for (int i = 0; i < (int)m_dwNotifyArraySize; i++)
    {
        m_pNotifyArray[i].dwOffset = m_dwNotifyByteInterval * (i + 1) - 1;
        m_pNotifyArray[i].hEventNotify = m_hNotificationEvent;
    }

    // Tell DirectSound when to notify us. the notification will come in the from    
    // of signaled events that are handled in WinMain()
    if (FAILED(hr = m_pDSNotify->SetNotificationPositions(dwNotifyArraySize, m_pNotifyArray))) {
        SAFE_RELEASE(m_pDSCapture);
        SAFE_RELEASE(m_pDSNotify);
        SAFE_RELEASE(m_pDSCaptureBuffer);
        SAFE_DELETE_ARRAY(m_pNotifyArray);
        return hr;
    }


    return hr;
}

and another piece of codes of main thread.

void audio_rec::record_loop()
{
    HANDLE& hNotiEvent = m_hNotificationEvent;
    long hr = S_OK;
    
    //  Prepare buffer to record
    std::vector<unsigned char> buffer1;
    std::vector<unsigned char> buffer2;
    long dwNextOffset = 0;
    WAVEFORMATEX wfx = this->mic_wfx;

    //  Reset Notify Event
    ::ResetEvent(hNotiEvent);

    //  Start Recording
    if (FAILED(hr = this->m_pDSCaptureBuffer->Start(DSCBSTART_LOOPING))) {
        return;
    }


    //  Loop Until Stop sign is signaled
    while (this->flag_stop_capture == false)
    {
        ::WaitForSingleObject(hNotiEvent, INFINITE);


        //  read buffer
        //  ReadCapturedData()함수에서 Buffer를 할당 
        hr = this->read_captured_data(
            this->m_pDSCaptureBuffer,
            buffer1,
            buffer2,
            dwNextOffset);

        if (FAILED(hr)) {
            break;
        }


        ...


        ::ResetEvent(hNotiEvent);
    }
}

and this is codes reading captured audio.

long audio_rec::read_captured_data(
    __in LPDIRECTSOUNDCAPTUREBUFFER pCaptureBuffer,
    __out std::vector<unsigned char>& buffer1,
    __out std::vector<unsigned char>& buffer2,
    __inout long& dwNextOffset)
{
    HRESULT hr = S_OK;
    PVOID   pbCaptureData1 = nullptr;
    unsigned long   dwCapturedLength1 = 0;
    PVOID   pbCaptureData2 = nullptr;
    unsigned long   dwCapturedLength2 = 0;
    unsigned long   dwReadPos = 0;
    unsigned long   dwCapturePos = 0;
    long    lLockSize = 0;

    buffer1.clear();
    buffer2.clear();

    if (nullptr == pCaptureBuffer) {
        return S_FALSE;
    }

    if (FAILED(hr = pCaptureBuffer->GetCurrentPosition(&dwCapturePos, &dwReadPos))) {
        return (long)hr;
    }


    //assert(dwCapturePos - dwReadPos == dwNotiByteInterval);
    //dwLockSize = dwNotiByteInterval;
    lLockSize = dwReadPos - dwNextOffset;
    if (lLockSize < 0) {
        lLockSize += m_dwBufferSize;
    }

    // Block align lock size
    lLockSize -= (lLockSize % m_dwNotifyByteInterval);

    if (lLockSize == 0) {
        return S_FALSE;
    }

    // Lock the capture buffer down   
    if (FAILED(hr = m_pDSCaptureBuffer->Lock(
        dwNextOffset, lLockSize,
        &pbCaptureData1, &dwCapturedLength1,
        &pbCaptureData2, &dwCapturedLength2, 0L))) {
        return hr;
    }

    //  copy captured buffer
    if (pbCaptureData1 != nullptr)
    {
        if (dwCapturedLength1 > 0) {
            //buffer1.resize(dwCapturedLength1);
            //::memcpy(buffer1.data(), (unsigned char*)pbCaptureData1, dwCapturedLength1);
            buffer1.assign((unsigned char*)pbCaptureData1, ((unsigned char*)pbCaptureData1) + dwCapturedLength1);
        }

        // Move the capture offset along   
        dwNextOffset += dwCapturedLength1;
        dwNextOffset %= m_dwBufferSize; // Circular buffer   
    }

    if (pbCaptureData2 != nullptr)
    {
        if (dwCapturedLength2 > 0) {
            buffer2.assign(
                (unsigned char*)pbCaptureData2,
                ((unsigned char*)pbCaptureData2) + dwCapturedLength2);
        }
        dwNextOffset += dwCapturedLength2;
        dwNextOffset %= m_dwBufferSize; // Circular buffer
    }

    // Unlock the capture buffer
    hr = pCaptureBuffer->Unlock(
        pbCaptureData1, dwCapturedLength1,
        pbCaptureData2, dwCapturedLength2);

    return S_OK;
}

I tried to capture audio with sample rate 44100 but actual sample rate captured was like 30320. I had changed required sample rate to 22050 and I got sample rate like 14690.

0

There are 0 answers