Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / src / audio / audio_file_formats / juce_OggVorbisAudioFormat.cpp
blobf8ec68cb8da43d37199cb57b798c9465f8b168bf
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_TargetPlatform.h"
27 #include "../../../juce_Config.h"
29 #if JUCE_USE_OGGVORBIS
31 #include "../../core/juce_StandardHeader.h"
33 #if JUCE_MAC && ! defined (__MACOSX__)
34 #define __MACOSX__ 1
35 #endif
37 BEGIN_JUCE_NAMESPACE
39 namespace OggVorbisNamespace
41 #if JUCE_INCLUDE_OGGVORBIS_CODE
42 #include "oggvorbis/vorbisenc.h"
43 #include "oggvorbis/codec.h"
44 #include "oggvorbis/vorbisfile.h"
46 #include "oggvorbis/bitwise.c"
47 #include "oggvorbis/framing.c"
48 #include "oggvorbis/libvorbis-1.3.2/lib/analysis.c"
49 #include "oggvorbis/libvorbis-1.3.2/lib/bitrate.c"
50 #include "oggvorbis/libvorbis-1.3.2/lib/block.c"
51 #include "oggvorbis/libvorbis-1.3.2/lib/codebook.c"
52 #include "oggvorbis/libvorbis-1.3.2/lib/envelope.c"
53 #include "oggvorbis/libvorbis-1.3.2/lib/floor0.c"
54 #include "oggvorbis/libvorbis-1.3.2/lib/floor1.c"
55 #include "oggvorbis/libvorbis-1.3.2/lib/info.c"
56 #include "oggvorbis/libvorbis-1.3.2/lib/lpc.c"
57 #include "oggvorbis/libvorbis-1.3.2/lib/lsp.c"
58 #include "oggvorbis/libvorbis-1.3.2/lib/mapping0.c"
59 #include "oggvorbis/libvorbis-1.3.2/lib/mdct.c"
60 #include "oggvorbis/libvorbis-1.3.2/lib/psy.c"
61 #include "oggvorbis/libvorbis-1.3.2/lib/registry.c"
62 #include "oggvorbis/libvorbis-1.3.2/lib/res0.c"
63 #include "oggvorbis/libvorbis-1.3.2/lib/sharedbook.c"
64 #include "oggvorbis/libvorbis-1.3.2/lib/smallft.c"
65 #include "oggvorbis/libvorbis-1.3.2/lib/synthesis.c"
66 #include "oggvorbis/libvorbis-1.3.2/lib/vorbisenc.c"
67 #include "oggvorbis/libvorbis-1.3.2/lib/vorbisfile.c"
68 #include "oggvorbis/libvorbis-1.3.2/lib/window.c"
69 #else
70 #include <vorbis/vorbisenc.h>
71 #include <vorbis/codec.h>
72 #include <vorbis/vorbisfile.h>
73 #endif
76 #undef max
77 #undef min
79 #include "juce_OggVorbisAudioFormat.h"
80 #include "../../application/juce_Application.h"
81 #include "../../maths/juce_Random.h"
82 #include "../../io/files/juce_FileInputStream.h"
83 #include "../../text/juce_LocalisedStrings.h"
85 //==============================================================================
86 static const char* const oggFormatName = "Ogg-Vorbis file";
87 static const char* const oggExtensions[] = { ".ogg", 0 };
89 //==============================================================================
90 class OggReader : public AudioFormatReader
92 public:
93 //==============================================================================
94 OggReader (InputStream* const inp)
95 : AudioFormatReader (inp, TRANS (oggFormatName)),
96 reservoir (2, 4096),
97 reservoirStart (0),
98 samplesInReservoir (0)
100 using namespace OggVorbisNamespace;
101 sampleRate = 0;
102 usesFloatingPointData = true;
104 callbacks.read_func = &oggReadCallback;
105 callbacks.seek_func = &oggSeekCallback;
106 callbacks.close_func = &oggCloseCallback;
107 callbacks.tell_func = &oggTellCallback;
109 const int err = ov_open_callbacks (input, &ovFile, 0, 0, callbacks);
111 if (err == 0)
113 vorbis_info* info = ov_info (&ovFile, -1);
114 lengthInSamples = (uint32) ov_pcm_total (&ovFile, -1);
115 numChannels = info->channels;
116 bitsPerSample = 16;
117 sampleRate = info->rate;
119 reservoir.setSize (numChannels,
120 (int) jmin (lengthInSamples, (int64) reservoir.getNumSamples()));
124 ~OggReader()
126 OggVorbisNamespace::ov_clear (&ovFile);
129 //==============================================================================
130 bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
131 int64 startSampleInFile, int numSamples)
133 while (numSamples > 0)
135 const int numAvailable = reservoirStart + samplesInReservoir - startSampleInFile;
137 if (startSampleInFile >= reservoirStart && numAvailable > 0)
139 // got a few samples overlapping, so use them before seeking..
141 const int numToUse = jmin (numSamples, numAvailable);
143 for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
144 if (destSamples[i] != nullptr)
145 memcpy (destSamples[i] + startOffsetInDestBuffer,
146 reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)),
147 sizeof (float) * numToUse);
149 startSampleInFile += numToUse;
150 numSamples -= numToUse;
151 startOffsetInDestBuffer += numToUse;
153 if (numSamples == 0)
154 break;
157 if (startSampleInFile < reservoirStart
158 || startSampleInFile + numSamples > reservoirStart + samplesInReservoir)
160 // buffer miss, so refill the reservoir
161 int bitStream = 0;
163 reservoirStart = jmax (0, (int) startSampleInFile);
164 samplesInReservoir = reservoir.getNumSamples();
166 if (reservoirStart != (int) OggVorbisNamespace::ov_pcm_tell (&ovFile))
167 OggVorbisNamespace::ov_pcm_seek (&ovFile, reservoirStart);
169 int offset = 0;
170 int numToRead = samplesInReservoir;
172 while (numToRead > 0)
174 float** dataIn = nullptr;
176 const int samps = OggVorbisNamespace::ov_read_float (&ovFile, &dataIn, numToRead, &bitStream);
177 if (samps <= 0)
178 break;
180 jassert (samps <= numToRead);
182 for (int i = jmin ((int) numChannels, reservoir.getNumChannels()); --i >= 0;)
184 memcpy (reservoir.getSampleData (i, offset),
185 dataIn[i],
186 sizeof (float) * samps);
189 numToRead -= samps;
190 offset += samps;
193 if (numToRead > 0)
194 reservoir.clear (offset, numToRead);
198 if (numSamples > 0)
200 for (int i = numDestChannels; --i >= 0;)
201 if (destSamples[i] != nullptr)
202 zeromem (destSamples[i] + startOffsetInDestBuffer,
203 sizeof (int) * numSamples);
206 return true;
209 //==============================================================================
210 static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource)
212 return (size_t) (static_cast <InputStream*> (datasource)->read (ptr, (int) (size * nmemb)) / size);
215 static int oggSeekCallback (void* datasource, OggVorbisNamespace::ogg_int64_t offset, int whence)
217 InputStream* const in = static_cast <InputStream*> (datasource);
219 if (whence == SEEK_CUR)
220 offset += in->getPosition();
221 else if (whence == SEEK_END)
222 offset += in->getTotalLength();
224 in->setPosition (offset);
225 return 0;
228 static int oggCloseCallback (void*)
230 return 0;
233 static long oggTellCallback (void* datasource)
235 return (long) static_cast <InputStream*> (datasource)->getPosition();
238 private:
239 OggVorbisNamespace::OggVorbis_File ovFile;
240 OggVorbisNamespace::ov_callbacks callbacks;
241 AudioSampleBuffer reservoir;
242 int reservoirStart, samplesInReservoir;
244 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggReader);
247 //==============================================================================
248 class OggWriter : public AudioFormatWriter
250 public:
251 //==============================================================================
252 OggWriter (OutputStream* const out,
253 const double sampleRate_,
254 const int numChannels_,
255 const int bitsPerSample_,
256 const int qualityIndex)
257 : AudioFormatWriter (out, TRANS (oggFormatName), sampleRate_, numChannels_, bitsPerSample_),
258 ok (false)
260 using namespace OggVorbisNamespace;
262 vorbis_info_init (&vi);
264 if (vorbis_encode_init_vbr (&vi, numChannels_, (int) sampleRate_,
265 jlimit (0.0f, 1.0f, qualityIndex * 0.1f)) == 0)
267 vorbis_comment_init (&vc);
269 if (JUCEApplication::getInstance() != nullptr)
270 vorbis_comment_add_tag (&vc, "ENCODER", const_cast <char*> (JUCEApplication::getInstance()->getApplicationName().toUTF8().getAddress()));
272 vorbis_analysis_init (&vd, &vi);
273 vorbis_block_init (&vd, &vb);
275 ogg_stream_init (&os, Random::getSystemRandom().nextInt());
277 ogg_packet header;
278 ogg_packet header_comm;
279 ogg_packet header_code;
281 vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
283 ogg_stream_packetin (&os, &header);
284 ogg_stream_packetin (&os, &header_comm);
285 ogg_stream_packetin (&os, &header_code);
287 for (;;)
289 if (ogg_stream_flush (&os, &og) == 0)
290 break;
292 output->write (og.header, og.header_len);
293 output->write (og.body, og.body_len);
296 ok = true;
300 ~OggWriter()
302 using namespace OggVorbisNamespace;
303 if (ok)
305 // write a zero-length packet to show ogg that we're finished..
306 writeSamples (0);
308 ogg_stream_clear (&os);
309 vorbis_block_clear (&vb);
310 vorbis_dsp_clear (&vd);
311 vorbis_comment_clear (&vc);
313 vorbis_info_clear (&vi);
314 output->flush();
316 else
318 vorbis_info_clear (&vi);
319 output = nullptr; // to stop the base class deleting this, as it needs to be returned
320 // to the caller of createWriter()
324 //==============================================================================
325 bool write (const int** samplesToWrite, int numSamples)
327 if (ok)
329 using namespace OggVorbisNamespace;
331 if (numSamples > 0)
333 const double gain = 1.0 / 0x80000000u;
334 float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples);
336 for (int i = numChannels; --i >= 0;)
338 float* const dst = vorbisBuffer[i];
339 const int* const src = samplesToWrite [i];
341 if (src != nullptr && dst != nullptr)
343 for (int j = 0; j < numSamples; ++j)
344 dst[j] = (float) (src[j] * gain);
349 writeSamples (numSamples);
352 return ok;
355 void writeSamples (int numSamples)
357 using namespace OggVorbisNamespace;
359 vorbis_analysis_wrote (&vd, numSamples);
361 while (vorbis_analysis_blockout (&vd, &vb) == 1)
363 vorbis_analysis (&vb, 0);
364 vorbis_bitrate_addblock (&vb);
366 while (vorbis_bitrate_flushpacket (&vd, &op))
368 ogg_stream_packetin (&os, &op);
370 for (;;)
372 if (ogg_stream_pageout (&os, &og) == 0)
373 break;
375 output->write (og.header, og.header_len);
376 output->write (og.body, og.body_len);
378 if (ogg_page_eos (&og))
379 break;
385 bool ok;
387 private:
388 OggVorbisNamespace::ogg_stream_state os;
389 OggVorbisNamespace::ogg_page og;
390 OggVorbisNamespace::ogg_packet op;
391 OggVorbisNamespace::vorbis_info vi;
392 OggVorbisNamespace::vorbis_comment vc;
393 OggVorbisNamespace::vorbis_dsp_state vd;
394 OggVorbisNamespace::vorbis_block vb;
396 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggWriter);
400 //==============================================================================
401 OggVorbisAudioFormat::OggVorbisAudioFormat()
402 : AudioFormat (TRANS (oggFormatName), StringArray (oggExtensions))
406 OggVorbisAudioFormat::~OggVorbisAudioFormat()
410 const Array <int> OggVorbisAudioFormat::getPossibleSampleRates()
412 const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
413 return Array <int> (rates);
416 const Array <int> OggVorbisAudioFormat::getPossibleBitDepths()
418 const int depths[] = { 32, 0 };
419 return Array <int> (depths);
422 bool OggVorbisAudioFormat::canDoStereo() { return true; }
423 bool OggVorbisAudioFormat::canDoMono() { return true; }
424 bool OggVorbisAudioFormat::isCompressed() { return true; }
426 AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in,
427 const bool deleteStreamIfOpeningFails)
429 ScopedPointer <OggReader> r (new OggReader (in));
431 if (r->sampleRate > 0)
432 return r.release();
434 if (! deleteStreamIfOpeningFails)
435 r->input = nullptr;
437 return nullptr;
440 AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out,
441 double sampleRate,
442 unsigned int numChannels,
443 int bitsPerSample,
444 const StringPairArray& /*metadataValues*/,
445 int qualityOptionIndex)
447 ScopedPointer <OggWriter> w (new OggWriter (out,
448 sampleRate,
449 numChannels,
450 bitsPerSample,
451 qualityOptionIndex));
453 return w->ok ? w.release() : nullptr;
456 StringArray OggVorbisAudioFormat::getQualityOptions()
458 const char* options[] = { "64 kbps", "80 kbps", "96 kbps", "112 kbps", "128 kbps", "160 kbps",
459 "192 kbps", "224 kbps", "256 kbps", "320 kbps", "500 kbps", 0 };
460 return StringArray (options);
463 int OggVorbisAudioFormat::estimateOggFileQuality (const File& source)
465 FileInputStream* const in = source.createInputStream();
467 if (in != nullptr)
469 ScopedPointer <AudioFormatReader> r (createReaderFor (in, true));
471 if (r != nullptr)
473 const int64 numSamps = r->lengthInSamples;
474 r = nullptr;
476 const int64 fileNumSamps = source.getSize() / 4;
477 const double ratio = numSamps / (double) fileNumSamps;
479 if (ratio > 12.0)
480 return 0;
481 else if (ratio > 6.0)
482 return 1;
483 else
484 return 2;
488 return 1;
491 END_JUCE_NAMESPACE
493 #endif