Having trouble accessing recorded audio from memory output stream. Please help!


#1

I have recorded a very short audio sample (approx 200,000 bytes) via a threaded writer, and into a MemoryOutputSource. Then when recording is finished, I try to create an AudioFormatReaderSource so that I can access the recording and do some analysis on a sample by sample basis. But the AudioFormatReaderSource has a total length of zero. I can’t figure out what I’m doing wrong. Some advice would be tremendously appreciated.

void StartRecording() {
    StopRecording(false);
    if (SampleRate == 0) return;
    memOutStream = new MemoryOutputStream();
    
    WavAudioFormat wavFormat;
    AudioFormatWriter* writer = wavFormat.createWriterFor (memOutStream, SampleRate, 1, 16, StringPairArray(), 0);
    if (writer == nullptr) throw std::logic_error("Failed create audio format writer");
    threadedWriter = new AudioFormatWriter::ThreadedWriter (writer, backgroundThread, 32768);
    const ScopedLock sl (writerLock);
    activeWriter = threadedWriter;
}

void StopRecording(bool shouldProcessRecording) {
const ScopedLock sl (writerLock);
activeWriter = nullptr;

if (shouldProcessRecording && memOutStream != nullptr) {
    memInStream = new MemoryInputStream(memOutStream->getData(), memOutStream->getDataSize(), true);
    
    WavAudioFormat wavFormat;
    AudioFormatReader* reader = wavFormat.createReaderFor(memInStream, true);
    if (reader == nullptr) throw std::logic_error("Failed to create reader from memstream");
    AudioSource = new AudioFormatReaderSource (reader, true);
    AudioSource->setLooping(false);
    AudioSource->prepareToPlay(1024, static_cast<double>(SampleRate));
    auto totalSamples = AudioSource->getTotalLength();  // <------ THIS RETURNS ZERO!!!!
    AudioBuffer<float> Buffer; 
    Buffer.setSize(1, static_cast<int>(TotalSamples));     // <-------- THIS CAUSES THE THREAD TO CRASH BECAUSE IT DOES NOT WANT A ZERO VALUE
    AudioSourceChannelInfo data(Buffer);
   while (AudioSource->getNextReadPosition() < TotalSamples) {
         /* DO SOMETHING WITH AUDIO HERE */
   }
}
memOutStream = nullptr;
memInStream = nullptr;
threadedWriter = nullptr;
}

#2

Never mind. I figured out the problem.


#3

What was the problem? I’m having the same exact issue


#4

I’m guessing: before the AudioFormatWriter is destroyed or flushed, the wav file has the length of zero samples…


#5

This was quite some time ago and I’ve forgotten what the problem was. However, I will have a look at my code to find what the solution was and I will post it here for you within the next day or so.


#6

I just had a look at my code, and it looks like my solution was to abandon the threaded writer. Instead, I just captured samples from the “getNextAudioBlock” function and sent them to a class (“AudioCapture”) that was waiting to record.
Its pretty simple, but its all that I needed. The JUCE classes were massively overcomplicating a basic task.

MainComponent.cpp

void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override {
     auto numChannels = bufferToFill->getNumChannels();
     for (auto i = 0; i < bufferToFill.numSamples; ++i) {
          auto readPointer = bufferToFill.buffer->getReadPointer(0, i);
          ACapture->AddNextSample(*readPointer);
          /* DO OTHER STUFF WITH AUDIO HERE */
     }
     /* DO OTHER STUFF WITH AUDIO HERE */
}

AudioCapture.cpp

void AudioCapture::StartRecording(int expectedTotalSamples) {
     ExpectedTotalSamples = expectedTotalSamples;
     AudioVec.reserve(expectedTotalSamples);
     IsRecording = true;
     TotalSamples = 0;
     AudioVec.clear();
}

void AudioCapture::AddNextSample(float sample) {
     if (!IsRecording || TotalSamples >= ExpectedTotalSamples) { return; }
     AudioVec.push_back(sample);
     ++TotalSamples;
}