OpenShot Audio Library | OpenShotAudio: juce_FlacAudioFormat.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.2

Loading...
Searching...
No Matches
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_GCC
126 #pragma GCC diagnostic push
127 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
128 #pragma GCC diagnostic ignored "-Wconversion"
129 #pragma GCC diagnostic ignored "-Wsign-conversion"
130 #endif
131
132 #if JUCE_INTEL
133 #if JUCE_32BIT
134 #define FLAC__CPU_IA32 1
135 #endif
136 #if JUCE_64BIT
137 #define FLAC__CPU_X86_64 1
138 #endif
139 #define FLAC__HAS_X86INTRIN 1
140 #endif
141
142 #undef __STDC_LIMIT_MACROS
143 #define __STDC_LIMIT_MACROS 1
144 #define flac_max jmax
145 #define flac_min jmin
146 #undef DEBUG // (some flac code dumps debug trace if the app defines this macro)
147 #include "flac/all.h"
148 #include "flac/libFLAC/bitmath.c"
149 #include "flac/libFLAC/bitreader.c"
150 #include "flac/libFLAC/bitwriter.c"
151 #include "flac/libFLAC/cpu.c"
152 #include "flac/libFLAC/crc.c"
153 #include "flac/libFLAC/fixed.c"
154 #include "flac/libFLAC/float.c"
155 #include "flac/libFLAC/format.c"
156 #include "flac/libFLAC/lpc_flac.c"
157 #include "flac/libFLAC/md5.c"
158 #include "flac/libFLAC/memory.c"
159 #include "flac/libFLAC/stream_decoder.c"
160 #include "flac/libFLAC/stream_encoder.c"
161 #include "flac/libFLAC/stream_encoder_framing.c"
162 #include "flac/libFLAC/window_flac.c"
163 #undef VERSION
164#else
165 #include <FLAC/all.h>
166#endif
167
168 #if JUCE_CLANG
169 #pragma clang diagnostic pop
170 #endif
171
172 #if JUCE_GCC
173 #pragma GCC diagnostic pop
174 #endif
175}
176
177#undef max
178#undef min
179
180//==============================================================================
181static const char* const flacFormatName = "FLAC file";
182
183
184//==============================================================================
185class FlacReader : public AudioFormatReader
186{
187public:
188 FlacReader (InputStream* in) : AudioFormatReader (in, flacFormatName)
189 {
190 lengthInSamples = 0;
191 decoder = FlacNamespace::FLAC__stream_decoder_new();
192
193 ok = FLAC__stream_decoder_init_stream (decoder,
194 readCallback_, seekCallback_, tellCallback_, lengthCallback_,
195 eofCallback_, writeCallback_, metadataCallback_, errorCallback_,
196 this) == FlacNamespace::FLAC__STREAM_DECODER_INIT_STATUS_OK;
197
198 if (ok)
199 {
200 FLAC__stream_decoder_process_until_end_of_metadata (decoder);
201
202 if (lengthInSamples == 0 && sampleRate > 0)
203 {
204 // the length hasn't been stored in the metadata, so we'll need to
205 // work it out the length the hard way, by scanning the whole file..
206 scanningForLength = true;
207 FLAC__stream_decoder_process_until_end_of_stream (decoder);
208 scanningForLength = false;
209 auto tempLength = lengthInSamples;
210
211 FLAC__stream_decoder_reset (decoder);
212 FLAC__stream_decoder_process_until_end_of_metadata (decoder);
213 lengthInSamples = tempLength;
214 }
215 }
216 }
217
218 ~FlacReader() override
219 {
220 FlacNamespace::FLAC__stream_decoder_delete (decoder);
221 }
222
223 void useMetadata (const FlacNamespace::FLAC__StreamMetadata_StreamInfo& info)
224 {
225 sampleRate = info.sample_rate;
226 bitsPerSample = info.bits_per_sample;
227 lengthInSamples = (unsigned int) info.total_samples;
228 numChannels = info.channels;
229
230 reservoir.setSize ((int) numChannels, 2 * (int) info.max_blocksize, false, false, true);
231 }
232
233 // returns the number of samples read
234 bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
235 int64 startSampleInFile, int numSamples) override
236 {
237 if (! ok)
238 return false;
239
240 while (numSamples > 0)
241 {
242 if (startSampleInFile >= reservoirStart
243 && startSampleInFile < reservoirStart + samplesInReservoir)
244 {
245 auto num = (int) jmin ((int64) numSamples,
246 reservoirStart + samplesInReservoir - startSampleInFile);
247
248 jassert (num > 0);
249
250 for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
251 if (destSamples[i] != nullptr)
252 memcpy (destSamples[i] + startOffsetInDestBuffer,
253 reservoir.getReadPointer (i, (int) (startSampleInFile - reservoirStart)),
254 (size_t) num * sizeof (int));
255
256 startOffsetInDestBuffer += num;
257 startSampleInFile += num;
258 numSamples -= num;
259 }
260 else
261 {
262 if (startSampleInFile >= lengthInSamples)
263 {
264 samplesInReservoir = 0;
265 }
266 else if (startSampleInFile < reservoirStart
267 || startSampleInFile > reservoirStart + jmax (samplesInReservoir, 511))
268 {
269 // had some problems with flac crashing if the read pos is aligned more
270 // accurately than this. Probably fixed in newer versions of the library, though.
271 reservoirStart = (int) (startSampleInFile & ~511);
272 samplesInReservoir = 0;
273 FLAC__stream_decoder_seek_absolute (decoder, (FlacNamespace::FLAC__uint64) reservoirStart);
274 }
275 else
276 {
277 reservoirStart += samplesInReservoir;
278 samplesInReservoir = 0;
279 FLAC__stream_decoder_process_single (decoder);
280 }
281
282 if (samplesInReservoir == 0)
283 break;
284 }
285 }
286
287 if (numSamples > 0)
288 {
289 for (int i = numDestChannels; --i >= 0;)
290 if (destSamples[i] != nullptr)
291 zeromem (destSamples[i] + startOffsetInDestBuffer, (size_t) numSamples * sizeof (int));
292 }
293
294 return true;
295 }
296
297 void useSamples (const FlacNamespace::FLAC__int32* const buffer[], int numSamples)
298 {
299 if (scanningForLength)
300 {
301 lengthInSamples += numSamples;
302 }
303 else
304 {
305 if (numSamples > reservoir.getNumSamples())
306 reservoir.setSize ((int) numChannels, numSamples, false, false, true);
307
308 auto bitsToShift = 32 - bitsPerSample;
309
310 for (int i = 0; i < (int) numChannels; ++i)
311 {
312 auto* src = buffer[i];
313 int n = i;
314
315 while (src == nullptr && n > 0)
316 src = buffer [--n];
317
318 if (src != nullptr)
319 {
320 auto* dest = reinterpret_cast<int*> (reservoir.getWritePointer(i));
321
322 for (int j = 0; j < numSamples; ++j)
323 dest[j] = src[j] << bitsToShift;
324 }
325 }
326
327 samplesInReservoir = numSamples;
328 }
329 }
330
331 //==============================================================================
332 static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data)
333 {
334 *bytes = (size_t) static_cast<const FlacReader*> (client_data)->input->read (buffer, (int) *bytes);
335 return FlacNamespace::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
336 }
337
338 static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data)
339 {
340 static_cast<const FlacReader*> (client_data)->input->setPosition ((int) absolute_byte_offset);
341 return FlacNamespace::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
342 }
343
344 static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
345 {
346 *absolute_byte_offset = (uint64) static_cast<const FlacReader*> (client_data)->input->getPosition();
347 return FlacNamespace::FLAC__STREAM_DECODER_TELL_STATUS_OK;
348 }
349
350 static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data)
351 {
352 *stream_length = (uint64) static_cast<const FlacReader*> (client_data)->input->getTotalLength();
353 return FlacNamespace::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
354 }
355
356 static FlacNamespace::FLAC__bool eofCallback_ (const FlacNamespace::FLAC__StreamDecoder*, void* client_data)
357 {
358 return static_cast<const FlacReader*> (client_data)->input->isExhausted();
359 }
360
361 static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
362 const FlacNamespace::FLAC__Frame* frame,
363 const FlacNamespace::FLAC__int32* const buffer[],
364 void* client_data)
365 {
366 static_cast<FlacReader*> (client_data)->useSamples (buffer, (int) frame->header.blocksize);
367 return FlacNamespace::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
368 }
369
370 static void metadataCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
371 const FlacNamespace::FLAC__StreamMetadata* metadata,
372 void* client_data)
373 {
374 static_cast<FlacReader*> (client_data)->useMetadata (metadata->data.stream_info);
375 }
376
377 static void errorCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus, void*)
378 {
379 }
380
381private:
382 FlacNamespace::FLAC__StreamDecoder* decoder;
383 AudioBuffer<float> reservoir;
384 int reservoirStart = 0, samplesInReservoir = 0;
385 bool ok = false, scanningForLength = false;
386
387 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacReader)
388};
389
390
391//==============================================================================
392class FlacWriter : public AudioFormatWriter
393{
394public:
395 FlacWriter (OutputStream* out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
396 : AudioFormatWriter (out, flacFormatName, rate, numChans, bits),
397 streamStartPos (output != nullptr ? jmax (output->getPosition(), 0ll) : 0ll)
398 {
399 encoder = FlacNamespace::FLAC__stream_encoder_new();
400
401 if (qualityOptionIndex > 0)
402 FLAC__stream_encoder_set_compression_level (encoder, (uint32) jmin (8, qualityOptionIndex));
403
404 FLAC__stream_encoder_set_do_mid_side_stereo (encoder, numChannels == 2);
405 FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, numChannels == 2);
406 FLAC__stream_encoder_set_channels (encoder, numChannels);
407 FLAC__stream_encoder_set_bits_per_sample (encoder, jmin ((unsigned int) 24, bitsPerSample));
408 FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate);
409 FLAC__stream_encoder_set_blocksize (encoder, 0);
410 FLAC__stream_encoder_set_do_escape_coding (encoder, true);
411
412 ok = FLAC__stream_encoder_init_stream (encoder,
413 encodeWriteCallback, encodeSeekCallback,
414 encodeTellCallback, encodeMetadataCallback,
415 this) == FlacNamespace::FLAC__STREAM_ENCODER_INIT_STATUS_OK;
416 }
417
418 ~FlacWriter() override
419 {
420 if (ok)
421 {
422 FlacNamespace::FLAC__stream_encoder_finish (encoder);
423 output->flush();
424 }
425 else
426 {
427 output = nullptr; // to stop the base class deleting this, as it needs to be returned
428 // to the caller of createWriter()
429 }
430
431 FlacNamespace::FLAC__stream_encoder_delete (encoder);
432 }
433
434 //==============================================================================
435 bool write (const int** samplesToWrite, int numSamples) override
436 {
437 if (! ok)
438 return false;
439
440 HeapBlock<int*> channels;
441 HeapBlock<int> temp;
442 auto bitsToShift = 32 - (int) bitsPerSample;
443
444 if (bitsToShift > 0)
445 {
446 temp.malloc (numChannels * (size_t) numSamples);
447 channels.calloc (numChannels + 1);
448
449 for (unsigned int i = 0; i < numChannels; ++i)
450 {
451 if (samplesToWrite[i] == nullptr)
452 break;
453
454 auto* destData = temp.get() + i * (size_t) numSamples;
455 channels[i] = destData;
456
457 for (int j = 0; j < numSamples; ++j)
458 destData[j] = (samplesToWrite[i][j] >> bitsToShift);
459 }
460
461 samplesToWrite = const_cast<const int**> (channels.get());
462 }
463
464 return FLAC__stream_encoder_process (encoder, (const FlacNamespace::FLAC__int32**) samplesToWrite, (unsigned) numSamples) != 0;
465 }
466
467 bool writeData (const void* const data, const int size) const
468 {
469 return output->write (data, (size_t) size);
470 }
471
472 static void packUint32 (FlacNamespace::FLAC__uint32 val, FlacNamespace::FLAC__byte* b, const int bytes)
473 {
474 b += bytes;
475
476 for (int i = 0; i < bytes; ++i)
477 {
478 *(--b) = (FlacNamespace::FLAC__byte) (val & 0xff);
479 val >>= 8;
480 }
481 }
482
483 void writeMetaData (const FlacNamespace::FLAC__StreamMetadata* metadata)
484 {
485 using namespace FlacNamespace;
486 auto& info = metadata->data.stream_info;
487
488 unsigned char buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
489 const unsigned int channelsMinus1 = info.channels - 1;
490 const unsigned int bitsMinus1 = info.bits_per_sample - 1;
491
492 packUint32 (info.min_blocksize, buffer, 2);
493 packUint32 (info.max_blocksize, buffer + 2, 2);
494 packUint32 (info.min_framesize, buffer + 4, 3);
495 packUint32 (info.max_framesize, buffer + 7, 3);
496 buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff);
497 buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff);
498 buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4));
499 buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (unsigned int) ((info.total_samples >> 32) & 0x0f));
500 packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);
501 memcpy (buffer + 18, info.md5sum, 16);
502
503 const bool seekOk = output->setPosition (streamStartPos + 4);
504 ignoreUnused (seekOk);
505
506 // if this fails, you've given it an output stream that can't seek! It needs
507 // to be able to seek back to write the header
508 jassert (seekOk);
509
510 output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
511 output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
512 }
513
514 //==============================================================================
515 static FlacNamespace::FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FlacNamespace::FLAC__StreamEncoder*,
516 const FlacNamespace::FLAC__byte buffer[],
517 size_t bytes,
518 unsigned int /*samples*/,
519 unsigned int /*current_frame*/,
520 void* client_data)
521 {
522 return static_cast<FlacWriter*> (client_data)->writeData (buffer, (int) bytes)
523 ? FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_OK
524 : FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
525 }
526
527 static FlacNamespace::FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64, void*)
528 {
529 return FlacNamespace::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
530 }
531
532 static FlacNamespace::FLAC__StreamEncoderTellStatus encodeTellCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
533 {
534 if (client_data == nullptr)
535 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
536
537 *absolute_byte_offset = (FlacNamespace::FLAC__uint64) static_cast<FlacWriter*> (client_data)->output->getPosition();
538 return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
539 }
540
541 static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data)
542 {
543 static_cast<FlacWriter*> (client_data)->writeMetaData (metadata);
544 }
545
546 bool ok = false;
547
548private:
549 FlacNamespace::FLAC__StreamEncoder* encoder;
550 int64 streamStartPos;
551
552 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacWriter)
553};
554
555
556//==============================================================================
557FlacAudioFormat::FlacAudioFormat() : AudioFormat (flacFormatName, ".flac") {}
558FlacAudioFormat::~FlacAudioFormat() {}
559
560Array<int> FlacAudioFormat::getPossibleSampleRates()
561{
562 return { 8000, 11025, 12000, 16000, 22050, 32000, 44100, 48000,
563 88200, 96000, 176400, 192000, 352800, 384000 };
564}
565
566Array<int> FlacAudioFormat::getPossibleBitDepths()
567{
568 return { 16, 24 };
569}
570
571bool FlacAudioFormat::canDoStereo() { return true; }
572bool FlacAudioFormat::canDoMono() { return true; }
573bool FlacAudioFormat::isCompressed() { return true; }
574
575AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails)
576{
577 std::unique_ptr<FlacReader> r (new FlacReader (in));
578
579 if (r->sampleRate > 0)
580 return r.release();
581
582 if (! deleteStreamIfOpeningFails)
583 r->input = nullptr;
584
585 return nullptr;
586}
587
588AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
589 double sampleRate,
590 unsigned int numberOfChannels,
591 int bitsPerSample,
592 const StringPairArray& /*metadataValues*/,
593 int qualityOptionIndex)
594{
595 if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample))
596 {
597 std::unique_ptr<FlacWriter> w (new FlacWriter (out, sampleRate, numberOfChannels,
598 (uint32) bitsPerSample, qualityOptionIndex));
599 if (w->ok)
600 return w.release();
601 }
602
603 return nullptr;
604}
605
606StringArray FlacAudioFormat::getQualityOptions()
607{
608 return { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)" };
609}
610
611#endif
612
613} // namespace juce