FMOD Voice Recording access to real-time playable bytes/data (C++)

Hello,

I’ve been using FMOD recently and have already looked at the record.cpp example.

However, in order to capture the audio data, it advises to use FMOD::sound::lock and FMOD::sound::unlock in sort of an external way, even though recordStart is non-blocking.

How exactly would I fetch the bytes in a synchronized way, so that there is no popping or artifacts? I’m aware that FMOD is internally using circular buffers as well. Is there no callback I could use? I’ve tried FMOD::System::CreateStream and tried to point recordStart to there and just use PCMReadCallback, which then complains about:

“[ERR] SystemI::recordStart : Invalid sound, must be an FMOD::Sound with positive length created as FMOD_CREATESAMPLE.”, even when I do fulfill everything that FMOD complains about.

Could anyone help? Also, I’m using C++ to do this.

Thank you!

Hi,

Thank you for sharing the information.

It seems that lock and unlock are unable to access the audio buffer, you could consider using a custom DSP to capture the audio buffer directly and add it to your recording channel by using ChannelControl::addDSP.

I will share an example script below as a reference:

FMOD_DSP_DESCRIPTION tap{};
tap.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
tap.numinputbuffers = 1;    
tap.numoutputbuffers = 1;   
tap.numparameters = 0;  

tap.process = [](FMOD_DSP_STATE *dsp_state, unsigned int numsamples, const    FMOD_DSP_BUFFER_ARRAY *inbufferarray,
                 FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op) -> FMOD_RESULT {
    if (op == FMOD_DSP_PROCESS_PERFORM) {
        if (inputsidle) {
            // If input is idle, optionally clear the output buffer to silence
            memset(outbufferarray->buffers[0], 0, numsamples * sizeof(float));
            return FMOD_OK;
        }

        // Process audio samples
        for (unsigned int i = 0; i < numsamples; ++i) {
            outbufferarray->buffers[0][i] = inbufferarray->buffers[0][i] * 0.5f; // Reduce amplitude to prevent clipping
        }
    }

    return FMOD_OK;
};

    FMOD::DSP *myDSP;
    result = system->createDSP(&tap, &myDSP);
    ERRCHECK(result);

    result = myRecordingChannel->addDSP(0, myDSP);  // Add DSP to the channel
    ERRCHECK(result);

Unfortunately, FMOD does not support using PCMReadCallback for recording since recordStart requires a sound object created with FMOD_CREATESAMPLE, which is incompatible with creatStream that is meant for streaming playback.

Hope this helps, let me know if you have any questions.

Hi, what I essentially want is to just capture a real-time buffer in a way that I can just use sendto() on it using a simple UDP socket and just fire-and-forget it so that the audio (my voice) can be replayed in real-time on the other side, allowing for a simple voice cha functionality with FMOD.

Oh, and thank you for your response sir.

Unfortunately, FMOD does not provide built-in networking support, so you’ll need to handle the transmission yourself.

You could consider packaging audio samples inbufferarray->buffers[0][i] into a custom structure like this:

    struct Packet
    {
        char data[32];
        int datalen;
    };

Then, use your own networking API (e.g., UDP sockets) to send the data over the network. On the receiver end, unpack the data and play it back using FMOD.

If you are looking for more information, there was a discussion relate to this topic that is worth reading through: