Using a circular buffer to visualize audio

I just want to share (and discuss if you want) this solution that seems very simple and useful. Previously I was creating various procedures to visualize spectrogram or waveform data according to tutorials, but this seems to be more effective since it unifies everything and does not depend on available states that have to be checked. It is a circular buffer, in which I simply add the input blocks. Currently the class is very basic, but it is functional and serves as an example.

class CircularBuffer 
{
    std::unique_ptr<float[]> data;
    int size = 0;
    std::atomic <int> cursor;

public:
    void prepareToPlay(double sampleRate, double duration)
    {
        size =  sampleRate * duration;
        data.reset(new float[size]());
        cursor = 0;
    }

    void pushNextBlock(const float*samples, int numSamples)
    {
        int i = cursor;
        for (int n = 0; n < numSamples; n++) {
            data[i] = samples[n];
            if (++i == size) i = 0;
        }

        cursor = i;
    }

    float *getData() { return data.get(); }
    int getBufferSize() { return size; }
    int getCursorPos() { return cursor; }
};  

Now my spectrogram with opengl is displayed to very high framerate. Another advantage is that I no longer have to worry about creating new implementations for other visualizations. the data can be used at any time and place in the UI, for a meter, a sound detector, always with unlimited duration or size (depending on the length of the circular buffer, of course), just avoid reading after the write cursor of the next block. I think even with a programming more conscientious it might be possible to read the samples as they are available, but for me that’s enough.

I don’t know if it is necessary for the cursor variable to be atomic, but I did it since it is the only shared data that will be read outside the thread. Regarding the buffer, I think there should be no problem as long as the content of the buffer is read before the cursor.

I think I’ll try to add Midi data as well, with a parallel buffer where events are associated with each sample.

1 Like