Skip to content

Commit 36e068a

Browse files
committed
Fix flac encoding and decoding
1 parent 2f27b59 commit 36e068a

File tree

7 files changed

+328
-58
lines changed

7 files changed

+328
-58
lines changed

modules/yup_audio_formats/formats/yup_FlacAudioFormat.cpp

Lines changed: 76 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -143,32 +143,52 @@ class FlacAudioFormatReader : public AudioFormatReader
143143
void* clientData)
144144
{
145145
auto* reader = static_cast<FlacAudioFormatReader*> (clientData);
146-
if (reader == nullptr || frame == nullptr || buffer == nullptr || reader->currentReadState == nullptr)
146+
if (reader == nullptr || frame == nullptr || buffer == nullptr)
147147
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
148148

149-
auto& state = *reader->currentReadState;
150149
const int samplesAvailable = (int) frame->header.blocksize;
151-
const int samplesRemaining = state.numSamples - state.samplesWritten;
152-
const int samplesToCopy = jmin (samplesAvailable, samplesRemaining);
150+
const int numChannels = reader->numChannels;
153151

154-
if (samplesToCopy <= 0)
155-
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
152+
if (reader->currentReadState != nullptr)
153+
{
154+
auto& state = *reader->currentReadState;
155+
const int samplesRemaining = state.numSamples - state.samplesWritten;
156+
const int samplesToCopy = jmin (samplesAvailable, samplesRemaining);
157+
158+
if (samplesToCopy <= 0)
159+
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
160+
161+
const int numChannelsToCopy = jmin (state.numDestChannels, numChannels);
162+
163+
for (int ch = 0; ch < numChannelsToCopy; ++ch)
164+
{
165+
if (state.destChannels[ch] == nullptr)
166+
continue;
156167

157-
const int numChannelsToCopy = jmin (state.numDestChannels, reader->numChannels);
168+
float* dest = state.destChannels[ch] + state.startOffset + state.samplesWritten;
169+
const FLAC__int32* src = buffer[ch];
158170

159-
for (int ch = 0; ch < numChannelsToCopy; ++ch)
171+
for (int i = 0; i < samplesToCopy; ++i)
172+
dest[i] = flacIntToFloat (src[i], reader->bitsPerSample);
173+
}
174+
175+
state.samplesWritten += samplesToCopy;
176+
}
177+
else if (numChannels > 0 && samplesAvailable > 0)
160178
{
161-
if (state.destChannels[ch] == nullptr)
162-
continue;
179+
const size_t startIndex = reader->interleavedSamples.size();
180+
reader->interleavedSamples.resize (startIndex + (size_t) samplesAvailable * (size_t) numChannels);
163181

164-
float* dest = state.destChannels[ch] + state.startOffset + state.samplesWritten;
165-
const FLAC__int32* src = buffer[ch];
182+
float* dest = reader->interleavedSamples.data() + startIndex;
166183

167-
for (int i = 0; i < samplesToCopy; ++i)
168-
dest[i] = flacIntToFloat (src[i], reader->bitsPerSample);
184+
for (int i = 0; i < samplesAvailable; ++i)
185+
{
186+
const size_t baseIndex = (size_t) i * (size_t) numChannels;
187+
for (int ch = 0; ch < numChannels; ++ch)
188+
dest[baseIndex + (size_t) ch] = flacIntToFloat (buffer[ch][i], reader->bitsPerSample);
189+
}
169190
}
170191

171-
state.samplesWritten += samplesToCopy;
172192
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
173193
}
174194

@@ -219,6 +239,7 @@ class FlacAudioFormatReader : public AudioFormatReader
219239

220240
FLAC__StreamDecoder* decoder = nullptr;
221241
ReadState* currentReadState = nullptr;
242+
std::vector<float> interleavedSamples;
222243
bool isOpen = false;
223244

224245
YUP_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacAudioFormatReader)
@@ -227,7 +248,7 @@ class FlacAudioFormatReader : public AudioFormatReader
227248
FlacAudioFormatReader::FlacAudioFormatReader (InputStream* sourceStream)
228249
: AudioFormatReader (sourceStream, "FLAC audio")
229250
{
230-
usesFloatingPointData = false;
251+
usesFloatingPointData = true;
231252

232253
if (sourceStream == nullptr)
233254
return;
@@ -256,7 +277,17 @@ FlacAudioFormatReader::FlacAudioFormatReader (InputStream* sourceStream)
256277
if (! FLAC__stream_decoder_process_until_end_of_metadata (decoder))
257278
return;
258279

280+
if (! FLAC__stream_decoder_process_until_end_of_stream (decoder))
281+
return;
282+
283+
if (numChannels > 0)
284+
lengthInSamples = (int64) (interleavedSamples.size() / (size_t) numChannels);
285+
259286
isOpen = sampleRate > 0 && numChannels > 0 && bitsPerSample > 0;
287+
288+
FLAC__stream_decoder_finish (decoder);
289+
FLAC__stream_decoder_delete (decoder);
290+
decoder = nullptr;
260291
}
261292

262293
FlacAudioFormatReader::~FlacAudioFormatReader()
@@ -274,7 +305,7 @@ bool FlacAudioFormatReader::readSamples (float* const* destChannels,
274305
int64 startSampleInFile,
275306
int numSamples)
276307
{
277-
if (! isOpen || decoder == nullptr)
308+
if (! isOpen)
278309
return false;
279310

280311
if (numSamples <= 0)
@@ -283,64 +314,51 @@ bool FlacAudioFormatReader::readSamples (float* const* destChannels,
283314
if (startSampleInFile < 0)
284315
return false;
285316

286-
int64 availableSamples = lengthInSamples > 0 ? (lengthInSamples - startSampleInFile) : numSamples;
287-
const int samplesToRead = (int) jmax<int64> (0, jmin<int64> (availableSamples, numSamples));
317+
if (lengthInSamples <= 0 || interleavedSamples.empty())
318+
return false;
288319

289-
if (samplesToRead <= 0)
320+
if (startSampleInFile < 0 || startSampleInFile >= lengthInSamples)
290321
return false;
291322

292-
if (! FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64) startSampleInFile))
323+
const auto numChannelsToRead = jmin (numDestChannels, numChannels);
324+
const auto availableSamples = (int64) lengthInSamples - startSampleInFile;
325+
const auto samplesToCopy = (int) jmin<int64> (availableSamples, numSamples);
326+
327+
if (samplesToCopy <= 0)
293328
return false;
294329

295-
ReadState state;
296-
state.destChannels = destChannels;
297-
state.numDestChannels = numDestChannels;
298-
state.startOffset = startOffsetInDestBuffer;
299-
state.numSamples = samplesToRead;
300-
state.samplesWritten = 0;
301-
currentReadState = &state;
330+
HeapBlock<float*> offsetDestChannels;
331+
offsetDestChannels.malloc (numDestChannels);
302332

303-
while (state.samplesWritten < samplesToRead)
304-
{
305-
if (! FLAC__stream_decoder_process_single (decoder))
306-
break;
333+
for (int ch = 0; ch < numDestChannels; ++ch)
334+
offsetDestChannels[ch] = destChannels[ch] + startOffsetInDestBuffer;
307335

308-
const auto decoderState = FLAC__stream_decoder_get_state (decoder);
309-
if (decoderState == FLAC__STREAM_DECODER_END_OF_STREAM)
310-
break;
311-
}
336+
const size_t interleavedOffset = (size_t) startSampleInFile * (size_t) numChannels;
337+
const float* interleavedStart = interleavedSamples.data() + interleavedOffset;
312338

313-
currentReadState = nullptr;
339+
using SourceFormat = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>;
340+
using DestFormat = AudioData::Format<AudioData::Float32, AudioData::NativeEndian>;
314341

315-
const int numChannelsToCopy = jmin (numDestChannels, numChannels);
316-
const int missingSamples = samplesToRead - state.samplesWritten;
342+
AudioData::deinterleaveSamples (AudioData::InterleavedSource<SourceFormat> { interleavedStart, (int) numChannels },
343+
AudioData::NonInterleavedDest<DestFormat> { offsetDestChannels.getData(), numChannelsToRead },
344+
samplesToCopy);
317345

318-
if (missingSamples > 0)
346+
if (numDestChannels > numChannelsToRead)
319347
{
320-
for (int ch = 0; ch < numChannelsToCopy; ++ch)
321-
if (destChannels[ch] != nullptr)
322-
zeromem (destChannels[ch] + startOffsetInDestBuffer + state.samplesWritten,
323-
sizeof (float) * (size_t) missingSamples);
348+
for (int ch = numChannelsToRead; ch < numDestChannels; ++ch)
349+
if (offsetDestChannels[ch] != nullptr)
350+
zeromem (offsetDestChannels[ch], sizeof (float) * (size_t) samplesToCopy);
324351
}
325352

326-
if (numSamples > samplesToRead)
353+
if (samplesToCopy < numSamples)
327354
{
328-
const int remainder = numSamples - samplesToRead;
355+
const auto remaining = numSamples - samplesToCopy;
329356
for (int ch = 0; ch < numDestChannels; ++ch)
330-
if (destChannels[ch] != nullptr)
331-
zeromem (destChannels[ch] + startOffsetInDestBuffer + samplesToRead,
332-
sizeof (float) * (size_t) remainder);
333-
}
334-
335-
if (numDestChannels > numChannelsToCopy)
336-
{
337-
for (int ch = numChannelsToCopy; ch < numDestChannels; ++ch)
338-
if (destChannels[ch] != nullptr)
339-
zeromem (destChannels[ch] + startOffsetInDestBuffer,
340-
sizeof (float) * (size_t) numSamples);
357+
if (offsetDestChannels[ch] != nullptr)
358+
zeromem (offsetDestChannels[ch] + samplesToCopy, sizeof (float) * (size_t) remaining);
341359
}
342360

343-
return state.samplesWritten > 0;
361+
return true;
344362
}
345363

346364
//==============================================================================

tests/data/sounds/M1F1-int16.flac

53.7 KB
Binary file not shown.

tests/data/sounds/M1F1-int24.flac

53.7 KB
Binary file not shown.

tests/data/sounds/M1F1-int32.flac

54.1 KB
Binary file not shown.

tests/data/sounds/M1F1-uint8.flac

22.4 KB
Binary file not shown.

tests/yup_audio_formats.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
#if YUP_MODULE_AVAILABLE_dr_libs && (YUP_AUDIO_FORMAT_WAVE || YUP_AUDIO_FORMAT_MP3)
12
#include <dr_libs/dr_libs.h>
3+
#endif
24

35
#if YUP_MODULE_AVAILABLE_opus_library && YUP_AUDIO_FORMAT_OPUS
46
#include <opus_library/opus_library.h>
@@ -9,8 +11,14 @@
911
#endif
1012

1113
#include "yup_audio_formats/yup_AudioFormatManager.cpp"
14+
15+
#if YUP_MODULE_AVAILABLE_dr_libs && YUP_AUDIO_FORMAT_WAVE
1216
#include "yup_audio_formats/yup_WaveAudioFormat.cpp"
17+
#endif
18+
19+
#if YUP_MODULE_AVAILABLE_dr_libs && YUP_AUDIO_FORMAT_MP3
1320
#include "yup_audio_formats/yup_Mp3AudioFormat.cpp"
21+
#endif
1422

1523
#if YUP_MODULE_AVAILABLE_opus_library && YUP_AUDIO_FORMAT_OPUS
1624
#include "yup_audio_formats/yup_OpusAudioFormat.cpp"

0 commit comments

Comments
 (0)