AudioVisualiserComponent/AudioThumbnail Tearing


#1

I’m experimenting with feeding a buffer into both the AudioVisualiserComponent class and the AudioThumbnail class. Both approaches are working fine, except that I’m getting some visual tearing right at the 50% mark of the component width:
Here’s using AudioVisualiserComponent


Here’s using AudioThumbnail showing 2 different waveforms:

and a clip:

any ideas?

Here’s the majority of the work for the AudioThumbnail version:

void OscillatorFIFOThumbnailView::pushSamples(const AudioBuffer<float> &buf)
{
    int readIndex = 0;
    //DBG( "numSamples to push: " << buf.getNumSamples() );
    auto writer = fifo.write(buf.getNumSamples());
    /*
    DBG( "startIndex1: " << writer.startIndex1 << " " <<
        "blockSize1: " << writer.blockSize1 << " " <<
        "startIndex2: " << writer.startIndex2 << " " <<
        "blockSize2: " << writer.blockSize2 );
     */
    writer.forEach([this, &buf, &readIndex](int writeIndex)
    {
        for( int i = 0; i < buf.getNumChannels(); ++i )
        {
            buffer.setSample(i, writeIndex, buf.getSample(i, readIndex));
        }
        ++readIndex;
    });
    //DBG( "read index: " << readIndex );
}
void OscillatorFIFOThumbnailView::timerCallback()
{
    if( thumbnail.get() )
    {
        auto numReady = fifo.getNumReady();

        AudioBuffer<float> readyChunk;
        readyChunk.setSize(buffer.getNumChannels(), numReady);

        auto reader = fifo.read(numReady);
        int writePos = 0;
        reader.forEach([this, &readyChunk, &writePos](int readPos)
        {
            for( int i = 0; i < readyChunk.getNumChannels(); ++i )
            {
                readyChunk.setSample(i,
                                     writePos,
                                     buffer.getSample(i,
                                                      readPos));
            }
            ++writePos;
        });

        thumbnail->addBlock(0, readyChunk, 0, readyChunk.getNumSamples());
    }
    repaint();
}
void OscillatorFIFOThumbnailView::paint(Graphics &g)
{
    g.fillAll(Colours::black);
    g.setColour(Colours::red);
    g.fillRoundedRectangle(getLocalBounds().toFloat(), 4);
    g.setColour(Colours::white);
    g.fillRoundedRectangle(getLocalBounds().toFloat().reduced(1), 4);

    g.setColour(Colours::red);
    if( thumbnail.get() && thumbnail->getTotalLength() > 0.0)
    {
        auto endTime = thumbnail->getTotalLength();
        //DBG( "thumbnail ok.  endtime: " << endTime );

        auto thumbArea = getLocalBounds();
        thumbnail->drawChannels (g, thumbArea.reduced (2), 0.0, endTime, 1.0f);
    }
    else
    {
        DBG( "thumbnail not ready" );
    }
}

the class is defined thusly:

struct OscillatorFIFOThumbnailView : public Component, public ChangeListener, public Timer
{
    OscillatorFIFOThumbnailView();
    ~OscillatorFIFOThumbnailView();
    void pushSamples(const AudioBuffer<float>& buf);
    void paint(Graphics& g) override;
    void changeListenerCallback(ChangeBroadcaster *source) override;
    void timerCallback() override;
    static constexpr int SampleRate = 44100;
    static constexpr int BufferChannels = 2;
    static constexpr int bufferSize = SampleRate * BufferChannels;
    void resized() override;
private:
    AbstractFifo fifo{bufferSize};
    AudioBuffer<float> buffer{BufferChannels,
                              bufferSize};
    AudioFormatManager manager;
    AudioThumbnailCache cache{10};
    std::unique_ptr<AudioThumbnail> thumbnail;
    Colour pathColor;
};

#2

Solved!

I was using a timer to push samples into it from my plugin Editor, and using a 2nd timer in the OscillatorFIFOThumbnailView to trigger reading from the FIFO. Once I switched the OscillatorFIFOThumbnailView to using AsyncUpdate to trigger reading, the tearing went away.