Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / src / audio / audio_file_formats / juce_AudioFormatWriter.cpp
blob5e55e86daf3b03848b9efb5e7c98b89eed13c751
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_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_AudioFormat.h"
31 #include "../dsp/juce_AudioSampleBuffer.h"
32 #include "../../containers/juce_AbstractFifo.h"
33 #include "juce_AudioThumbnail.h"
36 //==============================================================================
37 AudioFormatWriter::AudioFormatWriter (OutputStream* const out,
38 const String& formatName_,
39 const double rate,
40 const unsigned int numChannels_,
41 const unsigned int bitsPerSample_)
42 : sampleRate (rate),
43 numChannels (numChannels_),
44 bitsPerSample (bitsPerSample_),
45 usesFloatingPointData (false),
46 output (out),
47 formatName (formatName_)
51 AudioFormatWriter::~AudioFormatWriter()
53 delete output;
56 bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader,
57 int64 startSample,
58 int64 numSamplesToRead)
60 const int bufferSize = 16384;
61 AudioSampleBuffer tempBuffer (numChannels, bufferSize);
63 int* buffers [128] = { 0 };
65 for (int i = tempBuffer.getNumChannels(); --i >= 0;)
66 buffers[i] = reinterpret_cast<int*> (tempBuffer.getSampleData (i, 0));
68 if (numSamplesToRead < 0)
69 numSamplesToRead = reader.lengthInSamples;
71 while (numSamplesToRead > 0)
73 const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
75 if (! reader.read (buffers, numChannels, startSample, numToDo, false))
76 return false;
78 if (reader.usesFloatingPointData != isFloatingPoint())
80 int** bufferChan = buffers;
82 while (*bufferChan != nullptr)
84 int* b = *bufferChan++;
86 if (isFloatingPoint())
88 // int -> float
89 const double factor = 1.0 / std::numeric_limits<int>::max();
91 for (int i = 0; i < numToDo; ++i)
92 reinterpret_cast<float*> (b)[i] = (float) (factor * b[i]);
94 else
96 // float -> int
97 for (int i = 0; i < numToDo; ++i)
99 const double samp = *(const float*) b;
101 if (samp <= -1.0)
102 *b++ = std::numeric_limits<int>::min();
103 else if (samp >= 1.0)
104 *b++ = std::numeric_limits<int>::max();
105 else
106 *b++ = roundToInt (std::numeric_limits<int>::max() * samp);
112 if (! write (const_cast<const int**> (buffers), numToDo))
113 return false;
115 numSamplesToRead -= numToDo;
116 startSample += numToDo;
119 return true;
122 bool AudioFormatWriter::writeFromAudioSource (AudioSource& source, int numSamplesToRead, const int samplesPerBlock)
124 AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock);
126 while (numSamplesToRead > 0)
128 const int numToDo = jmin (numSamplesToRead, samplesPerBlock);
130 AudioSourceChannelInfo info;
131 info.buffer = &tempBuffer;
132 info.startSample = 0;
133 info.numSamples = numToDo;
134 info.clearActiveBufferRegion();
136 source.getNextAudioBlock (info);
138 if (! writeFromAudioSampleBuffer (tempBuffer, 0, numToDo))
139 return false;
141 numSamplesToRead -= numToDo;
144 return true;
147 bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& source, int startSample, int numSamples)
149 jassert (startSample >= 0 && startSample + numSamples <= source.getNumSamples() && source.getNumChannels() > 0);
151 if (numSamples <= 0)
152 return true;
154 HeapBlock<int> tempBuffer;
155 HeapBlock<int*> chans (numChannels + 1);
156 chans [numChannels] = 0;
158 if (isFloatingPoint())
160 for (int i = numChannels; --i >= 0;)
161 chans[i] = reinterpret_cast<int*> (source.getSampleData (i, startSample));
163 else
165 tempBuffer.malloc (numSamples * numChannels);
167 for (unsigned int i = 0; i < numChannels; ++i)
169 typedef AudioData::Pointer <AudioData::Int32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DestSampleType;
170 typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceSampleType;
172 DestSampleType destData (chans[i] = tempBuffer + i * numSamples);
173 SourceSampleType sourceData (source.getSampleData (i, startSample));
174 destData.convertSamples (sourceData, numSamples);
178 return write ((const int**) chans.getData(), numSamples);
181 //==============================================================================
182 class AudioFormatWriter::ThreadedWriter::Buffer : public TimeSliceClient,
183 public AbstractFifo
185 public:
186 Buffer (TimeSliceThread& timeSliceThread_, AudioFormatWriter* writer_, int numChannels, int bufferSize_)
187 : AbstractFifo (bufferSize_),
188 buffer (numChannels, bufferSize_),
189 timeSliceThread (timeSliceThread_),
190 writer (writer_),
191 thumbnailToUpdate (nullptr),
192 samplesWritten (0),
193 isRunning (true)
195 timeSliceThread.addTimeSliceClient (this);
198 ~Buffer()
200 isRunning = false;
201 timeSliceThread.removeTimeSliceClient (this);
203 while (writePendingData() == 0)
207 bool write (const float** data, int numSamples)
209 if (numSamples <= 0 || ! isRunning)
210 return true;
212 jassert (timeSliceThread.isThreadRunning()); // you need to get your thread running before pumping data into this!
214 int start1, size1, start2, size2;
215 prepareToWrite (numSamples, start1, size1, start2, size2);
217 if (size1 + size2 < numSamples)
218 return false;
220 for (int i = buffer.getNumChannels(); --i >= 0;)
222 buffer.copyFrom (i, start1, data[i], size1);
223 buffer.copyFrom (i, start2, data[i] + size1, size2);
226 finishedWrite (size1 + size2);
227 timeSliceThread.notify();
228 return true;
231 int useTimeSlice()
233 return writePendingData();
236 int writePendingData()
238 const int numToDo = getTotalSize() / 4;
240 int start1, size1, start2, size2;
241 prepareToRead (numToDo, start1, size1, start2, size2);
243 if (size1 <= 0)
244 return 10;
246 writer->writeFromAudioSampleBuffer (buffer, start1, size1);
248 const ScopedLock sl (thumbnailLock);
249 if (thumbnailToUpdate != nullptr)
250 thumbnailToUpdate->addBlock (samplesWritten, buffer, start1, size1);
252 samplesWritten += size1;
254 if (size2 > 0)
256 writer->writeFromAudioSampleBuffer (buffer, start2, size2);
258 if (thumbnailToUpdate != nullptr)
259 thumbnailToUpdate->addBlock (samplesWritten, buffer, start2, size2);
261 samplesWritten += size2;
264 finishedRead (size1 + size2);
265 return 0;
268 void setThumbnail (AudioThumbnail* thumb)
270 if (thumb != nullptr)
271 thumb->reset (buffer.getNumChannels(), writer->getSampleRate(), 0);
273 const ScopedLock sl (thumbnailLock);
274 thumbnailToUpdate = thumb;
275 samplesWritten = 0;
278 private:
279 AudioSampleBuffer buffer;
280 TimeSliceThread& timeSliceThread;
281 ScopedPointer<AudioFormatWriter> writer;
282 CriticalSection thumbnailLock;
283 AudioThumbnail* thumbnailToUpdate;
284 int64 samplesWritten;
285 volatile bool isRunning;
287 JUCE_DECLARE_NON_COPYABLE (Buffer);
290 AudioFormatWriter::ThreadedWriter::ThreadedWriter (AudioFormatWriter* writer, TimeSliceThread& backgroundThread, int numSamplesToBuffer)
291 : buffer (new AudioFormatWriter::ThreadedWriter::Buffer (backgroundThread, writer, writer->numChannels, numSamplesToBuffer))
295 AudioFormatWriter::ThreadedWriter::~ThreadedWriter()
299 bool AudioFormatWriter::ThreadedWriter::write (const float** data, int numSamples)
301 return buffer->write (data, numSamples);
304 void AudioFormatWriter::ThreadedWriter::setThumbnailToUpdate (AudioThumbnail* thumb)
306 buffer->setThumbnail (thumb);
309 END_JUCE_NAMESPACE