33 const unsigned int numChannels_,
34 const unsigned int bitsPerSample_)
36 numChannels (numChannels_),
37 bitsPerSample (bitsPerSample_),
38 usesFloatingPointData (false),
39 channelLayout (
AudioChannelSet::canonicalChannelSet(static_cast<int> (numChannels_))),
41 formatName (formatName_)
49 const unsigned int bitsPerSample_)
51 numChannels (static_cast<unsigned int> (channelLayout_.size())),
52 bitsPerSample (bitsPerSample_),
53 usesFloatingPointData (false),
54 channelLayout (channelLayout_),
56 formatName (formatName_)
65 static void convertFloatsToInts (
int* dest,
const float* src,
int numSamples) noexcept
67 while (--numSamples >= 0)
69 const double samp = *src++;
72 *dest = std::numeric_limits<int>::min();
74 *dest = std::numeric_limits<int>::max();
76 *dest = roundToInt (std::numeric_limits<int>::max() * samp);
84 int64 numSamplesToRead)
86 const int bufferSize = 16384;
89 int* buffers[128] = {
nullptr };
92 buffers[i] =
reinterpret_cast<int*
> (tempBuffer.
getWritePointer (i, 0));
94 if (numSamplesToRead < 0)
97 while (numSamplesToRead > 0)
99 const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
101 if (! reader.
read (buffers, (
int)
numChannels, startSample, numToDo,
false))
106 int** bufferChan = buffers;
108 while (*bufferChan !=
nullptr)
110 void*
const b = *bufferChan++;
115 convertFloatsToInts ((
int*) b, (
float*) b, numToDo);
119 if (!
write (
const_cast<const int**
> (buffers), numToDo))
122 numSamplesToRead -= numToDo;
123 startSample += numToDo;
133 while (numSamplesToRead > 0)
135 auto numToDo = jmin (numSamplesToRead, samplesPerBlock);
145 numSamplesToRead -= numToDo;
157 return write ((
const int**) channels, numSamples);
162 jassert (numSourceChannels < numElementsInArray (chans));
163 const int maxSamples = (int) (numElementsInArray (scratch) / numSourceChannels);
165 for (
int i = 0; i < numSourceChannels; ++i)
166 chans[i] = scratch + (i * maxSamples);
168 chans[numSourceChannels] =
nullptr;
171 while (numSamples > 0)
173 auto numToDo = jmin (numSamples, maxSamples);
175 for (
int i = 0; i < numSourceChannels; ++i)
176 convertFloatsToInts (chans[i], channels[i] + startSample, numToDo);
178 if (!
write ((
const int**) chans, numToDo))
181 startSample += numToDo;
182 numSamples -= numToDo;
191 jassert (startSample >= 0 && startSample + numSamples <= source.
getNumSamples() && numSourceChannels > 0);
193 if (startSample == 0)
196 const float* chans[256];
197 jassert ((
int)
numChannels < numElementsInArray (chans));
199 for (
int i = 0; i < numSourceChannels; ++i)
202 chans[numSourceChannels] =
nullptr;
218 buffer (channels, numSamples),
219 timeSliceThread (tst),
230 while (writePendingData() == 0)
234 bool write (
const float*
const* data,
int numSamples)
236 if (numSamples <= 0 || ! isRunning)
241 int start1, size1, start2, size2;
244 if (size1 + size2 < numSamples)
249 buffer.
copyFrom (i, start1, data[i], size1);
250 buffer.
copyFrom (i, start2, data[i] + size1, size2);
260 return writePendingData();
263 int writePendingData()
267 int start1, size1, start2, size2;
273 writer->writeFromAudioSampleBuffer (buffer, start1, size1);
277 if (receiver !=
nullptr)
278 receiver->addBlock (samplesWritten, buffer, start1, size1);
280 samplesWritten += size1;
284 writer->writeFromAudioSampleBuffer (buffer, start2, size2);
286 if (receiver !=
nullptr)
287 receiver->addBlock (samplesWritten, buffer, start2, size2);
289 samplesWritten += size2;
294 if (samplesPerFlush > 0)
296 flushSampleCounter -= size1 + size2;
298 if (flushSampleCounter <= 0)
300 flushSampleCounter = samplesPerFlush;
308 void setDataReceiver (IncomingDataReceiver* newReceiver)
310 if (newReceiver !=
nullptr)
311 newReceiver->reset (buffer.
getNumChannels(), writer->getSampleRate(), 0);
313 const ScopedLock sl (thumbnailLock);
314 receiver = newReceiver;
318 void setFlushInterval (
int numSamples) noexcept
320 samplesPerFlush = numSamples;
325 AudioBuffer<float> buffer;
326 TimeSliceThread& timeSliceThread;
327 std::unique_ptr<AudioFormatWriter> writer;
328 CriticalSection thumbnailLock;
329 IncomingDataReceiver* receiver = {};
330 int64 samplesWritten = 0;
331 int samplesPerFlush = 0, flushSampleCounter = 0;
332 std::atomic<bool> isRunning {
true };
334 JUCE_DECLARE_NON_COPYABLE (Buffer)
348 return buffer->write (data, numSamples);
353 buffer->setDataReceiver (receiver);
358 buffer->setFlushInterval (numSamplesPerFlush);
void prepareToWrite(int numToWrite, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Returns the location within the buffer at which an incoming block of data should be written.
int getTotalSize() const noexcept
Returns the total size of the buffer being managed.
void prepareToRead(int numWanted, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Returns the location within the buffer from which the next block of data should be read.
void finishedRead(int numRead) noexcept
Called after reading from the FIFO, to indicate that this many items have now been consumed.
void finishedWrite(int numWritten) noexcept
Called after writing from the FIFO, to indicate that this many items have been added.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer's channels.
void copyFrom(int destChannel, int destStartSample, const AudioBuffer &source, int sourceChannel, int sourceStartSample, int numSamples) noexcept
Copies samples from another buffer to this one.
const Type ** getArrayOfReadPointers() const noexcept
Returns an array of pointers to the channels in the buffer.
const Type * getReadPointer(int channelNumber) const noexcept
Returns a pointer to an array of read-only samples in one of the buffer's channels.
Represents a set of audio channel types.
Base class for objects that can produce a continuous stream of audio.
virtual void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill)=0
Called repeatedly to fetch subsequent blocks of audio data.
static void JUCE_CALLTYPE convertFixedToFloat(float *dest, const int *src, float multiplier, int numValues) noexcept
Converts a stream of integers to floats, multiplying each one by the given multiplier.
Automatically locks and unlocks a mutex object.
The base class for streams that write data to some kind of destination.
void notify() const
Wakes up the thread.
bool isThreadRunning() const
Returns true if the thread is currently active.
Used by the TimeSliceThread class.
A thread that keeps a list of clients, and calls each one in turn, giving them all a chance to run so...
void removeTimeSliceClient(TimeSliceClient *clientToRemove)
Removes a client from the list.
void addTimeSliceClient(TimeSliceClient *clientToAdd, int millisecondsBeforeStarting=0)
Adds a client to the list.
Used by AudioSource::getNextAudioBlock().
void clearActiveBufferRegion() const
Convenient method to clear the buffer if the source is not producing any data.