Memcpy error writing .WAV


#1

I’ve had a go at making a basic class that will save data to a .WAV on a background thread.

Alas it is giving an error during a memcpy.

Can anyone see what I’m doing wrong?

(I’m on OSX fwiw).

// WavDump.hh

#include "../JuceLibraryCode/JuceHeader.h"

class WavDump
{
public:
    TimeSliceThread backgroundThread; // the thread that will write our audio data to disk
    ScopedPointer<AudioFormatWriter::ThreadedWriter> threadedWriter; // the FIFO used to buffer the incoming data
    double sampleRate;
    //int64 nextSampleNum;
    //int numInputChannels;
    CriticalSection writerLock;
    AudioFormatWriter::ThreadedWriter* volatile activeWriter;

    WavDump(File& file, int numInputChannels) : backgroundThread("RecThread"), sampleRate (44100),
                                    /*numInputChannels(_numInputChannels), nextSampleNum (0),*/ activeWriter (nullptr)
    {
        backgroundThread.startThread();
        

        // Create an OutputStream to write to our destination file...
        file.deleteFile();
        ScopedPointer<FileOutputStream> fileStream (file.createOutputStream());

        assert(fileStream != nullptr);
        
        // Now create a WAV writer object that writes to our output stream...
        WavAudioFormat wavFormat;
        AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, numInputChannels, 16, StringPairArray(), 0);

        assert(writer != nullptr);
        
        fileStream.release(); // (passes responsibility for deleting the stream to the writer object that is now using it)
        
        // Now we'll create one of these helper objects which will act as a FIFO buffer, and will
        // write the data to disk on our background thread.
        threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768);
        
        assert(threadedWriter != nullptr);
        
        // Reset our recording thumbnail
        //thumbnail.reset (writer->getNumChannels(), writer->getSampleRate());
        //nextSampleNum = 0;
        
        // And now, swap over our active writer pointer so that the audio callback will start using it..
        {
            const ScopedLock sl (writerLock);
            activeWriter = threadedWriter;
        }
        
    }

    void stop()
    {
        // First, clear this pointer to stop the audio callback from using our writer object..
        {
            const ScopedLock sl (writerLock);
            activeWriter = nullptr;
        }
        
        // Now we can delete the writer object. It's done in this order because the deletion could
        // take a little time while remaining data gets flushed to disk, so it's best to avoid blocking
        // the audio callback while this happens.
        threadedWriter = nullptr;
    }
    
    void feed (const float** inputChannelData, int numSamples)
    {
        const ScopedLock sl (writerLock);
        
        if (activeWriter != nullptr)
            activeWriter->write (inputChannelData, numSamples);
    }
};

class TestWavDump
{
public:
    TestWavDump() {
        File file("/Users/pi/Desktop/dump.wav");

        int numChans = 1;
        float data[6] = {.1f,.2f,.4f,.3f,.5f,.6f};

        WavDump dumper(file, numChans);
        dumper.feed( (const float**)&data, 5 );
        dumper.stop();
    }
};

I call it with:

        TestWavDump td = TestWavDump();

#2

Ok this works:

class TestWavDump
{
public:
    TestWavDump() {
        File file("/Users/pi/Desktop/dump.wav");

        int numChans = 1;
        float data[6] = {.1f,.2f,.4f,.3f,.5f,.6f};
        float* d0 = &data[0];
        
        WavDump dumper(file, numChans);
        dumper.feed( (const float**)&d0, 5 );
        dumper.stop();
    }
};

#3

Why does it now work?

what’s different between
dumper.feed( (const float**)&data, 5 );

and

float* d0 = &data[0];
dumper.feed( (const float**)&d0, 5 );