32 const unsigned int numChannels_,
33 const unsigned int bitsPerSample_)
35 numChannels (numChannels_),
36 bitsPerSample (bitsPerSample_),
37 usesFloatingPointData (false),
38 channelLayout (
AudioChannelSet::canonicalChannelSet (static_cast<int> (numChannels_))),
40 formatName (formatName_)
48 const unsigned int bitsPerSample_)
50 numChannels (static_cast<unsigned int> (channelLayout_.size())),
51 bitsPerSample (bitsPerSample_),
52 usesFloatingPointData (false),
53 channelLayout (channelLayout_),
55 formatName (formatName_)
64static void convertFloatsToInts (
int* dest,
const float* src,
int numSamples)
noexcept
66 while (--numSamples >= 0)
68 const double samp = *src++;
71 *dest = std::numeric_limits<int>::min();
73 *dest = std::numeric_limits<int>::max();
75 *dest = roundToInt (std::numeric_limits<int>::max() * samp);
83 int64 numSamplesToRead)
85 const int bufferSize = 16384;
88 int* buffers[128] = {
nullptr };
91 buffers[i] =
reinterpret_cast<int*
> (tempBuffer.
getWritePointer (i, 0));
93 if (numSamplesToRead < 0)
96 while (numSamplesToRead > 0)
98 const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
100 if (! reader.
read (buffers, (
int)
numChannels, startSample, numToDo,
false))
105 int** bufferChan = buffers;
107 while (*bufferChan !=
nullptr)
109 void*
const b = *bufferChan++;
111 constexpr auto scaleFactor = 1.0f /
static_cast<float> (0x7fffffff);
114 FloatVectorOperations::convertFixedToFloat ((
float*) b, (
int*) b, scaleFactor, numToDo);
116 convertFloatsToInts ((
int*) b, (
float*) b, numToDo);
120 if (!
write (
const_cast<const int**
> (buffers), numToDo))
123 numSamplesToRead -= numToDo;
124 startSample += numToDo;
134 while (numSamplesToRead > 0)
136 auto numToDo = jmin (numSamplesToRead, samplesPerBlock);
146 numSamplesToRead -= numToDo;
158 return write ((
const int**) channels, numSamples);
160 std::vector<int*> chans (256);
161 std::vector<int> scratch (4096);
163 jassert (numSourceChannels < (
int) chans.size());
164 const int maxSamples = (int) scratch.size() / numSourceChannels;
166 for (
int i = 0; i < numSourceChannels; ++i)
167 chans[(
size_t) i] = scratch.data() + (i * maxSamples);
169 chans[(size_t) numSourceChannels] =
nullptr;
172 while (numSamples > 0)
174 auto numToDo = jmin (numSamples, maxSamples);
176 for (
int i = 0; i < numSourceChannels; ++i)
177 convertFloatsToInts (chans[(
size_t) i], channels[(
size_t) i] + startSample, numToDo);
179 if (!
write ((
const int**) chans.data(), numToDo))
182 startSample += numToDo;
183 numSamples -= numToDo;
192 jassert (startSample >= 0 && startSample + numSamples <= source.
getNumSamples() && numSourceChannels > 0);
194 if (startSample == 0)
197 const float* chans[256];
198 jassert ((
int)
numChannels < numElementsInArray (chans));
200 for (
int i = 0; i < numSourceChannels; ++i)
203 chans[numSourceChannels] =
nullptr;
214class AudioFormatWriter::ThreadedWriter::Buffer final :
private TimeSliceClient
219 buffer (channels, numSamples),
220 timeSliceThread (tst),
231 while (writePendingData() == 0)
235 bool write (
const float*
const* data,
int numSamples)
237 if (numSamples <= 0 || ! isRunning)
242 int start1, size1, start2, size2;
245 if (size1 + size2 < numSamples)
250 buffer.
copyFrom (i, start1, data[i], size1);
251 buffer.
copyFrom (i, start2, data[i] + size1, size2);
259 int useTimeSlice()
override
261 return writePendingData();
264 int writePendingData()
268 int start1, size1, start2, size2;
274 writer->writeFromAudioSampleBuffer (buffer, start1, size1);
276 const ScopedLock sl (thumbnailLock);
278 if (receiver !=
nullptr)
279 receiver->addBlock (samplesWritten, buffer, start1, size1);
281 samplesWritten += size1;
285 writer->writeFromAudioSampleBuffer (buffer, start2, size2);
287 if (receiver !=
nullptr)
288 receiver->addBlock (samplesWritten, buffer, start2, size2);
290 samplesWritten += size2;
295 if (samplesPerFlush > 0)
297 flushSampleCounter -= size1 + size2;
299 if (flushSampleCounter <= 0)
301 flushSampleCounter = samplesPerFlush;
309 void setDataReceiver (IncomingDataReceiver* newReceiver)
311 if (newReceiver !=
nullptr)
312 newReceiver->reset (buffer.
getNumChannels(), writer->getSampleRate(), 0);
314 const ScopedLock sl (thumbnailLock);
315 receiver = newReceiver;
319 void setFlushInterval (
int numSamples)
noexcept
321 samplesPerFlush = numSamples;
326 AudioBuffer<float> buffer;
327 TimeSliceThread& timeSliceThread;
328 std::unique_ptr<AudioFormatWriter> writer;
329 CriticalSection thumbnailLock;
330 IncomingDataReceiver* receiver = {};
331 int64 samplesWritten = 0;
332 int samplesPerFlush = 0, flushSampleCounter = 0;
333 std::atomic<bool> isRunning {
true };
335 JUCE_DECLARE_NON_COPYABLE (Buffer)
349 return buffer->write (data, numSamples);
354 buffer->setDataReceiver (receiver);
359 buffer->setFlushInterval (numSamplesPerFlush);
void prepareToWrite(int numToWrite, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
int getTotalSize() const noexcept
void prepareToRead(int numWanted, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
void finishedRead(int numRead) noexcept
void finishedWrite(int numWritten) noexcept
Type * getWritePointer(int channelNumber) noexcept
int getNumChannels() const noexcept
int getNumSamples() const noexcept
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
const Type * getReadPointer(int channelNumber) const noexcept
const Type *const * getArrayOfReadPointers() const noexcept
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
bool isThreadRunning() const
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
void clearActiveBufferRegion() const