Flac buffer contains only header but no audio data

Hello

I’m pretty new with JUCE. I’m trying to convert a small buffer into flac. However, i’m only recieving the flac header and no audio data after the convertion.

fLaC "€€ ¸ð „ ( reference libFLAC 1.3.1 20141125 (no audio data)

Here is the code I’m using

MemoryOutputStream* outputStream = new MemoryOutputStream(m_oAudioBuffer.getNumSamples() * sizeof(float)); // Size in bytes
FlacAudioFormat flacFormat;
std::unique_ptr<AudioFormatWriter> afw(flacFormat.createWriterFor(outputStream, 48000, m_oAudioBuffer.getNumChannels(), 16, {}, 0));
if (!afw->writeFromAudioSampleBuffer(m_oAudioBuffer, 0, m_oAudioBuffer.getNumSamples()))
{
    flacData = MemoryBlock();
    return false;
}
else
{
    flacData = outputStream->getMemoryBlock();
    return true;
}

I have found that if I do a m_oAudioBuffer.setSize(2, BufSize * sizeof(float)), then I do get the audio data in the flac but this makes no sense to me. JUCE should create a flac buffer and copy the audio data from m_oAudioBuffer. Why would I need to increase the size of my original buffer?

Thanks in advance for your help.

Because you are feeding audio samples from an AudioBuffer<float> a.k.a AudioSampleBuffer into an AudioFormatWriter. If the buffer is size zero no audio is added to the flac file.

If you say convert, where is the audio coming from?

And N.B. buffer.setSize() takes the number of samples, not bytes…

Hi Daniel. Thanks for you help.

The audio buffer in question: m_oAudioBuffer which is of type AudioBuffer has a small size, but is not zero. With the code shown, I would expect flacData to have the flac header plus the small amount of audio that I am passing. However, flacData only contains the header. Nothing else.

where is the audio coming from? : The audio is valid and coming from a short recording.

The evidence speaks against that theory unfortunately:

this shows, that the writing part works. Can you somehow verify that the m_oAudioBuffer has samples?

e.g. by adding before the writing part:

DBG ("m_oAudioBuffer has " << m_oAudioBuffer.getNumChannels() << " channels and " << m_oAudioBuffer.getNumSamples() << " samples.");

Hi
Here is the requested output: m_oAudioBuffer has 2 channels and 480 samples.
Sorry but I’m not sure what other clues I can give you.
Thanks again.

Interesting. I don’t know what to suggest without knowing the rest of the code. I can only speculate, there might be a race condition between the recording audio thread and the writing code.

If you could post a bit more of the code where the audio buffer is filled etc.

Hi. No worries if you’re not sure. It’s nice to get a reply.
Not sure what other code I can include. Here is essentially what happening. It’s very simple.
I receive a small buffer from the recording (bufferFromCallback) from a call back function and copying it to another buffer. Then I use the code already posted to convert to flac.

void SomeClass::Callback(AudioBuffer<float>& bufferFromCallback)
{
	...

	// This works. Audio is fine in flac.
	m_oAudioBuffer.setSize(2, bufferFromCallback.getNumSamples() * sizeof(float)); 

	// This does not works. Audio is silent. Flac only contains header.
	// m_oAudioBuffer.setSize(2, bufferFromCallback.getNumSamples()); 

	m_oAudioBuffer.copyFrom(0, 0, bufferFromCallback.getReadPointer(0), bufferFromCallback.getNumSamples());
	m_oAudioBuffer.copyFrom(1, 0, bufferFromCallback.getReadPointer(1), bufferFromCallback.getNumSamples());

	...

	MemoryOutputStream* outputStream = new MemoryOutputStream(m_oAudioBuffer.getNumSamples()); // Size in bytes (bufferFromCallback.getNumSamples() * sizeof(float))
	FlacAudioFormat flacFormat;
	std::unique_ptr<AudioFormatWriter> afw(flacFormat.createWriterFor(outputStream, 48000, m_oAudioBuffer.getNumChannels(), 16, {}, 0));
	if (!afw->writeFromAudioSampleBuffer(m_oAudioBuffer, 0, m_oAudioBuffer.getNumSamples()))
	{
		flacData = MemoryBlock();
		return false;
	}
	else
	{
		flacData = outputStream->getMemoryBlock();
		return true;
	}
}

That is dangerous code and explains the misbehaviour.

  • If the Callback is actually called from the audio callback, then you are allocating when you set the size of m_oAudioBuffer (if you are lucky only once, but bad enough)
  • Then opening the MemoryOutputStream: nice idea to skip the file IO, but it is still allocating when you append data to the MemoryBlock.
  • last but not least this is called in a loop, so each time will overwrite the flacData. Instead you want to keep the writer outside and keep feeding to the same writer each time.

And instead have a look at the ThreadedWriter, that has a fifo you can add data and the file IO is done on a separate thread.

Hope that helps to get further