OpenShot Library | libopenshot-audio 0.2.0
juce_FlacAudioFormat.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30#if JUCE_USE_FLAC
31
32}
33
34#if defined _WIN32 && !defined __CYGWIN__
35 #include <io.h>
36#else
37 #include <unistd.h>
38#endif
39
40#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
41 #include <sys/types.h> /* for off_t */
42#endif
43
44#if HAVE_INTTYPES_H
45 #define __STDC_FORMAT_MACROS
46 #include <inttypes.h>
47#endif
48
49#if defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ || defined __EMX__
50 #include <io.h> /* for _setmode(), chmod() */
51 #include <fcntl.h> /* for _O_BINARY */
52#else
53 #include <unistd.h> /* for chown(), unlink() */
54#endif
55
56#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
57 #if defined __BORLANDC__
58 #include <utime.h> /* for utime() */
59 #else
60 #include <sys/utime.h> /* for utime() */
61 #endif
62#else
63 #include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
64 #include <utime.h> /* for utime() */
65#endif
66
67#if defined _MSC_VER
68 #if _MSC_VER >= 1600
69 #include <stdint.h>
70 #else
71 #include <limits.h>
72 #endif
73#endif
74
75#ifdef _WIN32
76 #include <stdio.h>
77 #include <sys/stat.h>
78 #include <stdarg.h>
79 #include <windows.h>
80#endif
81
82#ifdef DEBUG
83 #include <assert.h>
84#endif
85
86#include <stdlib.h>
87#include <stdio.h>
88
89namespace juce
90{
91
92namespace FlacNamespace
93{
94#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
95
96 #undef VERSION
97 #define VERSION "1.3.1"
98
99 #define FLAC__NO_DLL 1
100
101 #if JUCE_MSVC
102 #pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312 4505 4365 4005 4334 181 111)
103 #else
104 #define HAVE_LROUND 1
105 #endif
106
107 #if JUCE_MAC
108 #define FLAC__SYS_DARWIN 1
109 #endif
110
111 #ifndef SIZE_MAX
112 #define SIZE_MAX 0xffffffff
113 #endif
114
115 #if JUCE_CLANG
116 #pragma clang diagnostic push
117 #pragma clang diagnostic ignored "-Wconversion"
118 #pragma clang diagnostic ignored "-Wshadow"
119 #pragma clang diagnostic ignored "-Wdeprecated-register"
120 #if __has_warning("-Wzero-as-null-pointer-constant")
121 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
122 #endif
123 #endif
124
125 #if JUCE_INTEL
126 #if JUCE_32BIT
127 #define FLAC__CPU_IA32 1
128 #endif
129 #if JUCE_64BIT
130 #define FLAC__CPU_X86_64 1
131 #endif
132 #define FLAC__HAS_X86INTRIN 1
133 #endif
134
135 #undef __STDC_LIMIT_MACROS
136 #define __STDC_LIMIT_MACROS 1
137 #define flac_max jmax
138 #define flac_min jmin
139 #undef DEBUG // (some flac code dumps debug trace if the app defines this macro)
140 #include "flac/all.h"
141 #include "flac/libFLAC/bitmath.c"
142 #include "flac/libFLAC/bitreader.c"
143 #include "flac/libFLAC/bitwriter.c"
144 #include "flac/libFLAC/cpu.c"
145 #include "flac/libFLAC/crc.c"
146 #include "flac/libFLAC/fixed.c"
147 #include "flac/libFLAC/float.c"
148 #include "flac/libFLAC/format.c"
149 #include "flac/libFLAC/lpc_flac.c"
150 #include "flac/libFLAC/md5.c"
151 #include "flac/libFLAC/memory.c"
152 #include "flac/libFLAC/stream_decoder.c"
153 #include "flac/libFLAC/stream_encoder.c"
154 #include "flac/libFLAC/stream_encoder_framing.c"
155 #include "flac/libFLAC/window_flac.c"
156 #undef VERSION
157#else
158 #include <FLAC/all.h>
159#endif
160
161 #if JUCE_CLANG
162 #pragma clang diagnostic pop
163 #endif
164}
165
166#undef max
167#undef min
168
169//==============================================================================
170static const char* const flacFormatName = "FLAC file";
171
172
173//==============================================================================
174class FlacReader : public AudioFormatReader
175{
176public:
177 FlacReader (InputStream* in) : AudioFormatReader (in, flacFormatName)
178 {
179 lengthInSamples = 0;
180 decoder = FlacNamespace::FLAC__stream_decoder_new();
181
185 this) == FlacNamespace::FLAC__STREAM_DECODER_INIT_STATUS_OK;
186
187 if (ok)
188 {
190
191 if (lengthInSamples == 0 && sampleRate > 0)
192 {
193 // the length hasn't been stored in the metadata, so we'll need to
194 // work it out the length the hard way, by scanning the whole file..
195 scanningForLength = true;
197 scanningForLength = false;
198 auto tempLength = lengthInSamples;
199
202 lengthInSamples = tempLength;
203 }
204 }
205 }
206
207 ~FlacReader() override
208 {
209 FlacNamespace::FLAC__stream_decoder_delete (decoder);
210 }
211
212 void useMetadata (const FlacNamespace::FLAC__StreamMetadata_StreamInfo& info)
213 {
214 sampleRate = info.sample_rate;
215 bitsPerSample = info.bits_per_sample;
216 lengthInSamples = (unsigned int) info.total_samples;
217 numChannels = info.channels;
218
219 reservoir.setSize ((int) numChannels, 2 * (int) info.max_blocksize, false, false, true);
220 }
221
222 // returns the number of samples read
223 bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
224 int64 startSampleInFile, int numSamples) override
225 {
226 if (! ok)
227 return false;
228
229 while (numSamples > 0)
230 {
233 {
234 auto num = (int) jmin ((int64) numSamples,
236
237 jassert (num > 0);
238
239 for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
240 if (destSamples[i] != nullptr)
242 reservoir.getReadPointer (i, (int) (startSampleInFile - reservoirStart)),
243 sizeof (int) * (size_t) num);
244
247 numSamples -= num;
248 }
249 else
250 {
251 if (startSampleInFile >= lengthInSamples)
252 {
254 }
257 {
258 // had some problems with flac crashing if the read pos is aligned more
259 // accurately than this. Probably fixed in newer versions of the library, though.
262 FLAC__stream_decoder_seek_absolute (decoder, (FlacNamespace::FLAC__uint64) reservoirStart);
263 }
264 else
265 {
269 }
270
271 if (samplesInReservoir == 0)
272 break;
273 }
274 }
275
276 if (numSamples > 0)
277 {
278 for (int i = numDestChannels; --i >= 0;)
279 if (destSamples[i] != nullptr)
280 zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples);
281 }
282
283 return true;
284 }
285
286 void useSamples (const FlacNamespace::FLAC__int32* const buffer[], int numSamples)
287 {
289 {
290 lengthInSamples += numSamples;
291 }
292 else
293 {
294 if (numSamples > reservoir.getNumSamples())
295 reservoir.setSize ((int) numChannels, numSamples, false, false, true);
296
297 auto bitsToShift = 32 - bitsPerSample;
298
299 for (int i = 0; i < (int) numChannels; ++i)
300 {
301 auto* src = buffer[i];
302 int n = i;
303
304 while (src == nullptr && n > 0)
305 src = buffer [--n];
306
307 if (src != nullptr)
308 {
309 auto* dest = reinterpret_cast<int*> (reservoir.getWritePointer(i));
310
311 for (int j = 0; j < numSamples; ++j)
312 dest[j] = src[j] << bitsToShift;
313 }
314 }
315
316 samplesInReservoir = numSamples;
317 }
318 }
319
320 //==============================================================================
321 static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data)
322 {
323 *bytes = (size_t) static_cast<const FlacReader*> (client_data)->input->read (buffer, (int) *bytes);
324 return FlacNamespace::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
325 }
326
327 static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data)
328 {
329 static_cast<const FlacReader*> (client_data)->input->setPosition ((int) absolute_byte_offset);
330 return FlacNamespace::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
331 }
332
333 static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
334 {
335 *absolute_byte_offset = (uint64) static_cast<const FlacReader*> (client_data)->input->getPosition();
336 return FlacNamespace::FLAC__STREAM_DECODER_TELL_STATUS_OK;
337 }
338
339 static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data)
340 {
341 *stream_length = (uint64) static_cast<const FlacReader*> (client_data)->input->getTotalLength();
342 return FlacNamespace::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
343 }
344
345 static FlacNamespace::FLAC__bool eofCallback_ (const FlacNamespace::FLAC__StreamDecoder*, void* client_data)
346 {
347 return static_cast<const FlacReader*> (client_data)->input->isExhausted();
348 }
349
350 static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
351 const FlacNamespace::FLAC__Frame* frame,
352 const FlacNamespace::FLAC__int32* const buffer[],
353 void* client_data)
354 {
355 static_cast<FlacReader*> (client_data)->useSamples (buffer, (int) frame->header.blocksize);
356 return FlacNamespace::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
357 }
358
359 static void metadataCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
360 const FlacNamespace::FLAC__StreamMetadata* metadata,
361 void* client_data)
362 {
363 static_cast<FlacReader*> (client_data)->useMetadata (metadata->data.stream_info);
364 }
365
366 static void errorCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus, void*)
367 {
368 }
369
370private:
371 FlacNamespace::FLAC__StreamDecoder* decoder;
372 AudioBuffer<float> reservoir;
374 bool ok = false, scanningForLength = false;
375
376 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacReader)
377};
378
379
380//==============================================================================
381class FlacWriter : public AudioFormatWriter
382{
383public:
384 FlacWriter (OutputStream* out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
385 : AudioFormatWriter (out, flacFormatName, rate, numChans, bits),
386 streamStartPos (output != nullptr ? jmax (output->getPosition(), 0ll) : 0ll)
387 {
388 encoder = FlacNamespace::FLAC__stream_encoder_new();
389
390 if (qualityOptionIndex > 0)
392
396 FLAC__stream_encoder_set_bits_per_sample (encoder, jmin ((unsigned int) 24, bitsPerSample));
397 FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate);
400
404 this) == FlacNamespace::FLAC__STREAM_ENCODER_INIT_STATUS_OK;
405 }
406
407 ~FlacWriter() override
408 {
409 if (ok)
410 {
411 FlacNamespace::FLAC__stream_encoder_finish (encoder);
412 output->flush();
413 }
414 else
415 {
416 output = nullptr; // to stop the base class deleting this, as it needs to be returned
417 // to the caller of createWriter()
418 }
419
420 FlacNamespace::FLAC__stream_encoder_delete (encoder);
421 }
422
423 //==============================================================================
424 bool write (const int** samplesToWrite, int numSamples) override
425 {
426 if (! ok)
427 return false;
428
429 HeapBlock<int*> channels;
430 HeapBlock<int> temp;
431 auto bitsToShift = 32 - (int) bitsPerSample;
432
433 if (bitsToShift > 0)
434 {
435 temp.malloc (numChannels * (size_t) numSamples);
436 channels.calloc (numChannels + 1);
437
438 for (unsigned int i = 0; i < numChannels; ++i)
439 {
440 if (samplesToWrite[i] == nullptr)
441 break;
442
443 auto* destData = temp.get() + i * (size_t) numSamples;
444 channels[i] = destData;
445
446 for (int j = 0; j < numSamples; ++j)
448 }
449
450 samplesToWrite = const_cast<const int**> (channels.get());
451 }
452
453 return FLAC__stream_encoder_process (encoder, (const FlacNamespace::FLAC__int32**) samplesToWrite, (unsigned) numSamples) != 0;
454 }
455
456 bool writeData (const void* const data, const int size) const
457 {
458 return output->write (data, (size_t) size);
459 }
460
461 static void packUint32 (FlacNamespace::FLAC__uint32 val, FlacNamespace::FLAC__byte* b, const int bytes)
462 {
463 b += bytes;
464
465 for (int i = 0; i < bytes; ++i)
466 {
467 *(--b) = (FlacNamespace::FLAC__byte) (val & 0xff);
468 val >>= 8;
469 }
470 }
471
472 void writeMetaData (const FlacNamespace::FLAC__StreamMetadata* metadata)
473 {
474 using namespace FlacNamespace;
475 auto& info = metadata->data.stream_info;
476
477 unsigned char buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
478 const unsigned int channelsMinus1 = info.channels - 1;
479 const unsigned int bitsMinus1 = info.bits_per_sample - 1;
480
481 packUint32 (info.min_blocksize, buffer, 2);
482 packUint32 (info.max_blocksize, buffer + 2, 2);
483 packUint32 (info.min_framesize, buffer + 4, 3);
484 packUint32 (info.max_framesize, buffer + 7, 3);
485 buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff);
486 buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff);
487 buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4));
488 buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (unsigned int) ((info.total_samples >> 32) & 0x0f));
489 packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);
490 memcpy (buffer + 18, info.md5sum, 16);
491
492 const bool seekOk = output->setPosition (streamStartPos + 4);
493 ignoreUnused (seekOk);
494
495 // if this fails, you've given it an output stream that can't seek! It needs
496 // to be able to seek back to write the header
497 jassert (seekOk);
498
499 output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
500 output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
501 }
502
503 //==============================================================================
504 static FlacNamespace::FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FlacNamespace::FLAC__StreamEncoder*,
505 const FlacNamespace::FLAC__byte buffer[],
506 size_t bytes,
507 unsigned int /*samples*/,
508 unsigned int /*current_frame*/,
509 void* client_data)
510 {
511 return static_cast<FlacWriter*> (client_data)->writeData (buffer, (int) bytes)
512 ? FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_OK
514 }
515
516 static FlacNamespace::FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64, void*)
517 {
518 return FlacNamespace::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
519 }
520
521 static FlacNamespace::FLAC__StreamEncoderTellStatus encodeTellCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
522 {
523 if (client_data == nullptr)
524 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
525
526 *absolute_byte_offset = (FlacNamespace::FLAC__uint64) static_cast<FlacWriter*> (client_data)->output->getPosition();
527 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
528 }
529
530 static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data)
531 {
532 static_cast<FlacWriter*> (client_data)->writeMetaData (metadata);
533 }
534
535 bool ok = false;
536
537private:
538 FlacNamespace::FLAC__StreamEncoder* encoder;
539 int64 streamStartPos;
540
541 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacWriter)
542};
543
544
545//==============================================================================
546FlacAudioFormat::FlacAudioFormat() : AudioFormat (flacFormatName, ".flac") {}
547FlacAudioFormat::~FlacAudioFormat() {}
548
549Array<int> FlacAudioFormat::getPossibleSampleRates()
550{
551 return { 8000, 11025, 12000, 16000, 22050, 32000, 44100, 48000,
552 88200, 96000, 176400, 192000, 352800, 384000 };
553}
554
555Array<int> FlacAudioFormat::getPossibleBitDepths()
556{
557 return { 16, 24 };
558}
559
560bool FlacAudioFormat::canDoStereo() { return true; }
561bool FlacAudioFormat::canDoMono() { return true; }
562bool FlacAudioFormat::isCompressed() { return true; }
563
564AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails)
565{
566 std::unique_ptr<FlacReader> r (new FlacReader (in));
567
568 if (r->sampleRate > 0)
569 return r.release();
570
571 if (! deleteStreamIfOpeningFails)
572 r->input = nullptr;
573
574 return nullptr;
575}
576
577AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
578 double sampleRate,
579 unsigned int numberOfChannels,
580 int bitsPerSample,
581 const StringPairArray& /*metadataValues*/,
582 int qualityOptionIndex)
583{
584 if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample))
585 {
586 std::unique_ptr<FlacWriter> w (new FlacWriter (out, sampleRate, numberOfChannels,
587 (uint32) bitsPerSample, qualityOptionIndex));
588 if (w->ok)
589 return w.release();
590 }
591
592 return nullptr;
593}
594
595StringArray FlacAudioFormat::getQualityOptions()
596{
597 return { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)" };
598}
599
600#endif
601
602} // namespace juce
int size() const noexcept
Returns the current number of elements in the array.
Definition juce_Array.h:219
Array()=default
Creates an empty array.
ElementType * data() const noexcept
Returns a pointer to the first element in the array.
Definition juce_Array.h:325