Note: Forums will be making significant UX changes to address key usability improvements surrounding search, discoverability and navigation. To learn more about these changes please visit the announcement which can be found HERE.

Answered Audio Sample Manipulation

  • Monday, June 11, 2012 2:37 AM
     
     

    Hello, I'm developing an audio application and don't know how to manipulate the data that comes from IAudioCaptureClient ::GetBuffer().

    I need to manipulate the sample to change the wave form and produce some bass guitar effects like overdrive, chorus and delay.

    I inspect the data from WAVEFORMATEX structure to try to discovery something but I can't.

    The code to print the data from WAVEFORMATEX is:

    printf("Samples per second: %d\n", pwfx->nSamplesPerSec);
    printf("Channels: %d\n", pwfx->nChannels);
    printf("Size of extra information: %d\n", pwfx->cbSize);
    printf("Block alignment in bytes: %d\n", pwfx->nBlockAlign);
    printf("Format type code: %d\n", pwfx->wFormatTag);
    printf("Bits per sample: %d\n", pwfx->wBitsPerSample);
    printf("Required average data tranfer rate: %d\n", pwfx->nAvgBytesPerSec);

    And the output is:

    Samples per second: 44100
    Channels: 2
    Size of extra information: 22
    Block alignment in bytes: 8
    Format type code: 65534  //this code stands for WAVE_FORMAT_EXTENSIBLE
    Bits per sample: 32
    Required average data tranfer rate: 352800

    Someone can help me with this?

    Thank you

All Replies

  • Monday, June 11, 2012 3:22 PM
    Moderator
     
     Answered

    When the format type code is WAVE_FORMAT_EXTENSIBLE, cast pwfx to a WAVEFORMATEXTENSIBLE.  Then inspect the SubFormat member.  See http://blogs.msdn.com/b/matthew_van_eerde/archive/2011/09/09/how-to-validate-and-log-a-waveformatex.aspx

    I suspect in this case it will be equal to KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.  This means that each sample is a four-byte floating-point integer of type "float".

    To back up a step, where are you getting the data from?  Is it coming from a recording device like the line in or microphone, or are you doing WASAPI loopback capture from a playback device like the speakers or the headphones?

    If you're pulling it from a recording device, you can do what you like with the data and then hand it off to somewhere.

    If you're pulling it from a playback device using WASAPI loopback capture, then be aware that WASAPI loopback capture is a read-only tap; modifications you make to the data will not be applied to what goes out of the speakers.


    Matthew van Eerde

  • Monday, June 11, 2012 5:31 PM
     
     

    Matthew, i will make the cast after because here I don't have my source code.

    I'm getting the data from microphone and want to modify the resulting sound.

    Guilherme

  • Monday, June 11, 2012 8:16 PM
    Moderator
     
     Answered

    OK.

    Assuming that the audio is indeed in float format (and the SubFormat will tell you this) you can modify the data in a given packet something like this:

    BYTE *pData = NULL;
    UINT32 nFrames = 0;
    pAudioCaptureClient::GetBuffer(&pData, &nFrames, ...);
    float *pFloatData = reinterpret_cast<float*>(pData);
    for (UINT32 f = 0; f < nFrames; f++) {
        for (WORD c = 0; c < pWfx->nChannels; c++) {
            // this is the sample corresponding to the c'th channel in frame f
            float sample = pFloatData[f * pWfx->nChannels + c];
            // do your processing here
        }
    }


    Matthew van Eerde

  • Wednesday, June 13, 2012 2:43 AM
     
     

    The format is correct Matthew.

    Now I must create a temporary buffer to store data before processing.

    I'm just starting this project and guess that some problems will arise.

    Thanks for your help.