33#if defined _WIN32 && !defined __CYGWIN__
39#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
40 #include <sys/types.h>
44 #define __STDC_FORMAT_MACROS
48#if defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ || defined __EMX__
55#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
56 #if defined __BORLANDC__
59 #include <sys/utime.h>
62 #include <sys/types.h>
91namespace FlacNamespace
93#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
95 #undef PACKAGE_VERSION
96 #define PACKAGE_VERSION "1.4.3"
98 #define FLAC__NO_DLL 1
100 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312 4505 4365 4005 4334 181 111 6340 6308 6297 6001 6320)
102 #define HAVE_LROUND 1
106 #define FLAC__SYS_DARWIN 1
110 #define SIZE_MAX 0xffffffff
113 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wconversion",
114 "-Wdeprecated-register",
116 "-Wimplicit-fallthrough",
117 "-Wlanguage-extension-token",
123 "-Wzero-as-null-pointer-constant")
127 #define FLAC__CPU_IA32 1
130 #define FLAC__CPU_X86_64 1
132 #define FLAC__HAS_X86INTRIN 1
135 #if JUCE_ARM && JUCE_64BIT
136 #define FLAC__CPU_ARM64 1
138 #if JUCE_USE_ARM_NEON
139 #define FLAC__HAS_NEONINTRIN 1
140 #define FLAC__HAS_A64NEONINTRIN 1
144 #define flac_max jmax
145 #define flac_min jmin
147 #pragma push_macro ("DEBUG")
148 #pragma push_macro ("NDEBUG")
157 #include "flac/all.h"
158 #include "flac/libFLAC/bitmath.c"
159 #include "flac/libFLAC/bitreader.c"
160 #include "flac/libFLAC/bitwriter.c"
161 #include "flac/libFLAC/cpu.c"
162 #include "flac/libFLAC/crc.c"
163 #include "flac/libFLAC/fixed.c"
164 #include "flac/libFLAC/float.c"
165 #include "flac/libFLAC/format.c"
166 #include "flac/libFLAC/lpc_flac.c"
167 #include "flac/libFLAC/lpc_intrin_neon.c"
168 #include "flac/libFLAC/md5.c"
169 #include "flac/libFLAC/memory.c"
170 #include "flac/libFLAC/stream_decoder.c"
171 #include "flac/libFLAC/stream_encoder.c"
172 #include "flac/libFLAC/stream_encoder_framing.c"
173 #include "flac/libFLAC/window_flac.c"
176 #pragma pop_macro ("DEBUG")
177 #pragma pop_macro ("NDEBUG")
179 #undef PACKAGE_VERSION
181 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
182 JUCE_END_IGNORE_WARNINGS_MSVC
185 #include <FLAC/all.h>
193static const char*
const flacFormatName =
"FLAC file";
195template <
typename Item>
199class FlacReader final :
public AudioFormatReader
202 FlacReader (InputStream* in) : AudioFormatReader (in, flacFormatName)
205 decoder = FlacNamespace::FLAC__stream_decoder_new();
207 ok = FLAC__stream_decoder_init_stream (decoder,
208 readCallback_, seekCallback_, tellCallback_, lengthCallback_,
209 eofCallback_, writeCallback_, metadataCallback_, errorCallback_,
210 this) == FlacNamespace::FLAC__STREAM_DECODER_INIT_STATUS_OK;
214 FLAC__stream_decoder_process_until_end_of_metadata (decoder);
216 if (lengthInSamples == 0 && sampleRate > 0)
220 scanningForLength =
true;
221 FLAC__stream_decoder_process_until_end_of_stream (decoder);
222 scanningForLength =
false;
223 auto tempLength = lengthInSamples;
225 FLAC__stream_decoder_reset (decoder);
226 FLAC__stream_decoder_process_until_end_of_metadata (decoder);
227 lengthInSamples = tempLength;
232 ~FlacReader()
override
234 FlacNamespace::FLAC__stream_decoder_delete (decoder);
237 void useMetadata (
const FlacNamespace::FLAC__StreamMetadata_StreamInfo& info)
239 sampleRate = info.sample_rate;
240 bitsPerSample = info.bits_per_sample;
241 lengthInSamples = (
unsigned int) info.total_samples;
242 numChannels = info.channels;
244 reservoir.setSize ((
int) numChannels, 2 * (
int) info.max_blocksize,
false,
false,
true);
247 bool readSamples (
int*
const* destSamples,
int numDestChannels,
int startOffsetInDestBuffer,
248 int64 startSampleInFile,
int numSamples)
override
253 const auto getBufferedRange = [
this] {
return bufferedRange; };
255 const auto readFromReservoir = [
this, &destSamples, &numDestChannels, &startOffsetInDestBuffer, &startSampleInFile] (
const Range<int64> rangeToRead)
257 const auto bufferIndices = rangeToRead - bufferedRange.getStart();
258 const auto writePos = (int64) startOffsetInDestBuffer + (rangeToRead.getStart() - startSampleInFile);
260 for (
int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
262 if (destSamples[i] !=
nullptr)
264 memcpy (destSamples[i] + writePos,
265 reservoir.getReadPointer (i) + bufferIndices.getStart(),
266 (
size_t) bufferIndices.getLength() * sizeof (
int));
271 const auto fillReservoir = [
this] (
const int64 requestedStart)
273 if (requestedStart >= lengthInSamples)
275 bufferedRange = emptyRange (requestedStart);
279 if (requestedStart < bufferedRange.getStart()
280 ||
jmax (bufferedRange.getEnd(), bufferedRange.getStart() + (int64) 511) < requestedStart)
284 bufferedRange = emptyRange (requestedStart & ~511);
285 FLAC__stream_decoder_seek_absolute (decoder, (FlacNamespace::FLAC__uint64) bufferedRange.getStart());
289 bufferedRange = emptyRange (bufferedRange.getEnd());
290 FLAC__stream_decoder_process_single (decoder);
293 const auto remainingSamples = Reservoir::doBufferedRead (Range<int64> { startSampleInFile, startSampleInFile + numSamples },
298 if (! remainingSamples.isEmpty())
299 for (
int i = numDestChannels; --i >= 0;)
300 if (destSamples[i] !=
nullptr)
301 zeromem (destSamples[i] + startOffsetInDestBuffer + (remainingSamples.getStart() - startSampleInFile),
302 (
size_t) remainingSamples.getLength() * sizeof (
int));
307 void useSamples (
const FlacNamespace::FLAC__int32*
const buffer[],
int numSamples)
309 if (scanningForLength)
311 lengthInSamples += numSamples;
315 if (numSamples > reservoir.getNumSamples())
316 reservoir.setSize ((
int) numChannels, numSamples,
false,
false,
true);
318 auto bitsToShift = 32 - bitsPerSample;
320 for (
int i = 0; i < (
int) numChannels; ++i)
322 auto* src = buffer[i];
325 while (src ==
nullptr && n > 0)
330 auto* dest =
reinterpret_cast<int*
> (reservoir.getWritePointer (i));
332 for (
int j = 0; j < numSamples; ++j)
333 dest[j] = src[j] << bitsToShift;
337 bufferedRange.setLength (numSamples);
342 static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (
const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[],
size_t* bytes,
void* client_data)
344 *bytes = (
size_t)
static_cast<const FlacReader*
> (client_data)->input->read (buffer, (
int) *bytes);
345 return FlacNamespace::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
348 static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (
const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset,
void* client_data)
350 static_cast<const FlacReader*
> (client_data)->input->setPosition ((
int) absolute_byte_offset);
351 return FlacNamespace::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
354 static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (
const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset,
void* client_data)
356 *absolute_byte_offset = (uint64)
static_cast<const FlacReader*
> (client_data)->input->getPosition();
357 return FlacNamespace::FLAC__STREAM_DECODER_TELL_STATUS_OK;
360 static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (
const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length,
void* client_data)
362 *stream_length = (uint64)
static_cast<const FlacReader*
> (client_data)->input->getTotalLength();
363 return FlacNamespace::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
366 static FlacNamespace::FLAC__bool eofCallback_ (
const FlacNamespace::FLAC__StreamDecoder*,
void* client_data)
368 return static_cast<const FlacReader*
> (client_data)->input->isExhausted();
371 static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (
const FlacNamespace::FLAC__StreamDecoder*,
372 const FlacNamespace::FLAC__Frame* frame,
373 const FlacNamespace::FLAC__int32*
const buffer[],
376 static_cast<FlacReader*
> (client_data)->useSamples (buffer, (
int) frame->header.blocksize);
377 return FlacNamespace::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
380 static void metadataCallback_ (
const FlacNamespace::FLAC__StreamDecoder*,
381 const FlacNamespace::FLAC__StreamMetadata* metadata,
384 static_cast<FlacReader*
> (client_data)->useMetadata (metadata->data.stream_info);
387 static void errorCallback_ (
const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus,
void*)
392 FlacNamespace::FLAC__StreamDecoder* decoder;
393 AudioBuffer<float> reservoir;
394 Range<int64> bufferedRange;
395 bool ok =
false, scanningForLength =
false;
402class FlacWriter final :
public AudioFormatWriter
405 FlacWriter (OutputStream* out,
double rate, uint32 numChans, uint32 bits,
int qualityOptionIndex)
406 : AudioFormatWriter (out, flacFormatName, rate, numChans, bits),
407 streamStartPos (output != nullptr ?
jmax (output->getPosition(), 0ll) : 0ll)
409 encoder = FlacNamespace::FLAC__stream_encoder_new();
411 if (qualityOptionIndex > 0)
412 FLAC__stream_encoder_set_compression_level (encoder, (uint32) jmin (8, qualityOptionIndex));
414 FLAC__stream_encoder_set_do_mid_side_stereo (encoder, numChannels == 2);
415 FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, numChannels == 2);
416 FLAC__stream_encoder_set_channels (encoder, numChannels);
417 FLAC__stream_encoder_set_bits_per_sample (encoder, jmin ((
unsigned int) 24, bitsPerSample));
418 FLAC__stream_encoder_set_sample_rate (encoder, (
unsigned int) sampleRate);
419 FLAC__stream_encoder_set_blocksize (encoder, 0);
420 FLAC__stream_encoder_set_do_escape_coding (encoder,
true);
422 ok = FLAC__stream_encoder_init_stream (encoder,
423 encodeWriteCallback, encodeSeekCallback,
424 encodeTellCallback, encodeMetadataCallback,
425 this) == FlacNamespace::FLAC__STREAM_ENCODER_INIT_STATUS_OK;
428 ~FlacWriter()
override
432 FlacNamespace::FLAC__stream_encoder_finish (encoder);
441 FlacNamespace::FLAC__stream_encoder_delete (encoder);
445 bool write (
const int** samplesToWrite,
int numSamples)
override
450 HeapBlock<int*> channels;
452 auto bitsToShift = 32 - (
int) bitsPerSample;
456 temp.malloc (numChannels * (
size_t) numSamples);
457 channels.calloc (numChannels + 1);
459 for (
unsigned int i = 0; i < numChannels; ++i)
461 if (samplesToWrite[i] ==
nullptr)
464 auto* destData = temp.get() + i * (
size_t) numSamples;
465 channels[i] = destData;
467 for (
int j = 0; j < numSamples; ++j)
468 destData[j] = (samplesToWrite[i][j] >> bitsToShift);
471 samplesToWrite =
const_cast<const int**
> (channels.get());
474 return FLAC__stream_encoder_process (encoder, (
const FlacNamespace::FLAC__int32**) samplesToWrite, (
unsigned) numSamples) != 0;
477 bool writeData (
const void*
const data,
const int size)
const
479 return output->write (data, (
size_t) size);
482 static void packUint32 (FlacNamespace::FLAC__uint32 val, FlacNamespace::FLAC__byte* b,
const int bytes)
486 for (
int i = 0; i < bytes; ++i)
488 *(--b) = (FlacNamespace::FLAC__byte) (val & 0xff);
493 void writeMetaData (
const FlacNamespace::FLAC__StreamMetadata* metadata)
495 using namespace FlacNamespace;
496 auto& info = metadata->data.stream_info;
498 unsigned char buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
499 const unsigned int channelsMinus1 = info.channels - 1;
500 const unsigned int bitsMinus1 = info.bits_per_sample - 1;
502 packUint32 (info.min_blocksize, buffer, 2);
503 packUint32 (info.max_blocksize, buffer + 2, 2);
504 packUint32 (info.min_framesize, buffer + 4, 3);
505 packUint32 (info.max_framesize, buffer + 7, 3);
506 buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff);
507 buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff);
508 buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4));
509 buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (
unsigned int) ((info.total_samples >> 32) & 0x0f));
510 packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);
511 memcpy (buffer + 18, info.md5sum, 16);
513 [[maybe_unused]]
const bool seekOk = output->setPosition (streamStartPos + 4);
519 output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
520 output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
524 static FlacNamespace::FLAC__StreamEncoderWriteStatus encodeWriteCallback (
const FlacNamespace::FLAC__StreamEncoder*,
525 const FlacNamespace::FLAC__byte buffer[],
531 return static_cast<FlacWriter*
> (client_data)->writeData (buffer, (
int) bytes)
532 ? FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_OK
533 : FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
536 static FlacNamespace::FLAC__StreamEncoderSeekStatus encodeSeekCallback (
const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64,
void*)
538 return FlacNamespace::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
541 static FlacNamespace::FLAC__StreamEncoderTellStatus encodeTellCallback (
const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset,
void* client_data)
543 if (client_data ==
nullptr)
544 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
546 *absolute_byte_offset = (FlacNamespace::FLAC__uint64)
static_cast<FlacWriter*
> (client_data)->output->getPosition();
547 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
550 static void encodeMetadataCallback (
const FlacNamespace::FLAC__StreamEncoder*,
const FlacNamespace::FLAC__StreamMetadata* metadata,
void* client_data)
552 static_cast<FlacWriter*
> (client_data)->writeMetaData (metadata);
558 FlacNamespace::FLAC__StreamEncoder* encoder;
559 int64 streamStartPos;
566FlacAudioFormat::FlacAudioFormat() : AudioFormat (flacFormatName,
".flac") {}
567FlacAudioFormat::~FlacAudioFormat() {}
569Array<int> FlacAudioFormat::getPossibleSampleRates()
571 return { 8000, 11025, 12000, 16000, 22050, 32000, 44100, 48000,
572 88200, 96000, 176400, 192000, 352800, 384000 };
575Array<int> FlacAudioFormat::getPossibleBitDepths()
580bool FlacAudioFormat::canDoStereo() {
return true; }
581bool FlacAudioFormat::canDoMono() {
return true; }
582bool FlacAudioFormat::isCompressed() {
return true; }
584AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in,
const bool deleteStreamIfOpeningFails)
588 if (r->sampleRate > 0)
591 if (! deleteStreamIfOpeningFails)
597AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
599 unsigned int numberOfChannels,
601 const StringPairArray& ,
602 int qualityOptionIndex)
604 if (out !=
nullptr && getPossibleBitDepths().contains (bitsPerSample))
607 (uint32) bitsPerSample, qualityOptionIndex));
615StringArray FlacAudioFormat::getQualityOptions()
617 return {
"0 (Fastest)",
"1",
"2",
"3",
"4",
"5 (Default)",
"6",
"7",
"8 (Highest quality)" };
static constexpr Range emptyRange(const ValueType start) noexcept
Returns a range with the specified start position and a length of zero.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
void zeromem(void *memory, size_t numBytes) noexcept
Fills a block of memory with zeros.