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

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;
}

Never mind. I figured out the problem.

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

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

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.

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;
}

I’ve been having this issue but don’t understand how this could be happening as there’s no threads in the works 0.o

Is there a special flush or something which forces it to dump to disk before a function exits?

Yes, that’s what I was pointing to. While the AudioFormatWriter is alive, the size will be zero, because it is still writing. Only upon destruction of the writer the actual length in samples and other information is written to the header of the produced audio file.

It seems the OP had a different issue though or fixed it accidently during his refactor.
That’s why I would always encourage anybody to start a new thread with a description of YOUR problem and maybe referencing the old topic you think it might be the same or related.
Too many assumptions when starting a post “I have the same problem” :wink:

2 Likes

Hehe well that solved it for me : ) I was trying to load the file in the same function as writing. Deleting the writer before trying to load solved it. Thanks @daniel !

1 Like