27 : isCurrentlyLooping (shouldLoop)
53 auto& dst = *bufferToFill.
buffer;
60 for (; (i < n || isCurrentlyLooping) && (pos < m); i += max)
62 max =
jmin (m - pos, n - (i % n));
65 for (; ch < channels; ++ch)
66 dst.copyFrom (ch, bufferToFill.
startSample + pos, buffer, ch, i % n, max);
68 for (; ch < dst.getNumChannels(); ++ch)
69 dst.clear (ch, bufferToFill.
startSample + pos, max);
75 dst.clear (bufferToFill.
startSample + pos, m - pos);
83 position = (
int) newPosition;
99 return isCurrentlyLooping;
104 isCurrentlyLooping = shouldLoop;
111struct MemoryAudioSourceTests final :
public UnitTest
113 MemoryAudioSourceTests() :
UnitTest (
"MemoryAudioSource", UnitTestCategories::audio) {}
115 void runTest()
override
117 constexpr int blockSize = 512;
118 AudioBuffer<float> bufferToFill { 2, blockSize };
119 AudioSourceChannelInfo channelInfo { bufferToFill };
121 beginTest (
"A zero-length buffer produces silence, whether or not looping is enabled");
123 for (
const bool enableLooping : {
false,
true })
125 AudioBuffer<float> buffer;
126 MemoryAudioSource source { buffer,
true,
false };
127 source.setLooping (enableLooping);
128 source.prepareToPlay (blockSize, 44100.0);
130 for (
int i = 0; i < 2; ++i)
132 play (source, channelInfo);
133 expect (isSilent (bufferToFill));
138 beginTest (
"A short buffer without looping is played once and followed by silence");
140 auto buffer = getShortBuffer();
141 MemoryAudioSource source { buffer,
true,
false };
142 source.setLooping (
false);
143 source.prepareToPlay (blockSize, 44100.0);
145 play (source, channelInfo);
148 copy.setSize (buffer.getNumChannels(), blockSize,
true,
true,
false);
150 expect (bufferToFill == copy);
152 play (source, channelInfo);
154 expect (isSilent (bufferToFill));
157 beginTest (
"A short buffer with looping is played multiple times");
159 auto buffer = getShortBuffer();
160 MemoryAudioSource source { buffer,
true,
false };
161 source.setLooping (
true);
162 source.prepareToPlay (blockSize, 44100.0);
164 play (source, channelInfo);
166 for (
int sample = 0;
sample < buffer.getNumSamples(); ++
sample)
167 expectEquals (bufferToFill.getSample (0, sample + buffer.getNumSamples()), buffer.getSample (0, sample));
169 expect (! isSilent (bufferToFill));
172 beginTest (
"A long buffer without looping is played once");
174 auto buffer = getLongBuffer();
175 MemoryAudioSource source { buffer,
true,
false };
176 source.setLooping (
false);
177 source.prepareToPlay (blockSize, 44100.0);
179 play (source, channelInfo);
182 copy.setSize (buffer.getNumChannels(), blockSize,
true,
true,
false);
184 expect (bufferToFill == copy);
186 for (
int i = 0; i < 10; ++i)
187 play (source, channelInfo);
189 expect (isSilent (bufferToFill));
192 beginTest (
"A long buffer with looping is played multiple times");
194 auto buffer = getLongBuffer();
195 MemoryAudioSource source { buffer,
true,
false };
196 source.setLooping (
true);
197 source.prepareToPlay (blockSize, 44100.0);
199 for (
int i = 0; i < 100; ++i)
201 play (source, channelInfo);
202 expectEquals (bufferToFill.getSample (0, 0), buffer.getSample (0, (i * blockSize) % buffer.getNumSamples()));
207 static AudioBuffer<float> getTestBuffer (
int length)
209 AudioBuffer<float> buffer { 2, length };
211 for (
int channel = 0; channel < buffer.getNumChannels(); ++channel)
212 for (
int sample = 0;
sample < buffer.getNumSamples(); ++
sample)
213 buffer.setSample (channel, sample,
jmap ((
float) sample, 0.0f, (
float) length, -1.0f, 1.0f));
218 static AudioBuffer<float> getShortBuffer() {
return getTestBuffer (5); }
219 static AudioBuffer<float> getLongBuffer() {
return getTestBuffer (1000); }
221 static void play (MemoryAudioSource& source, AudioSourceChannelInfo& info)
223 info.clearActiveBufferRegion();
224 source.getNextAudioBlock (info);
227 static bool isSilent (
const AudioBuffer<float>& b)
229 for (
int channel = 0; channel < b.getNumChannels(); ++channel)
230 if (b.findMinMax (channel, 0, b.getNumSamples()) != Range<float>{})
237static MemoryAudioSourceTests memoryAudioSourceTests;
A multi-channel buffer containing floating point audio samples.
void makeCopyOf(const AudioBuffer< OtherType > &other, bool avoidReallocating=false)
Resizes this buffer to match the given one, and copies all of its content across.
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 setDataToReferTo(Type *const *dataToReferTo, int newNumChannels, int newStartSample, int newNumSamples)
Makes this buffer point to a pre-allocated set of channel data arrays.
Type *const * getArrayOfWritePointers() noexcept
Returns an array of pointers to the channels in the buffer.
bool isLooping() const override
Implementation of the PositionableAudioSource method.
int64 getNextReadPosition() const override
Implementation of the PositionableAudioSource method.
MemoryAudioSource(AudioBuffer< float > &audioBuffer, bool copyMemory, bool shouldLoop=false)
Creates a MemoryAudioSource by providing an audio buffer.
void setNextReadPosition(int64 newPosition) override
Implementation of the PositionableAudioSource method.
int64 getTotalLength() const override
Implementation of the PositionableAudioSource method.
void prepareToPlay(int samplesPerBlockExpected, double sampleRate) override
Implementation of the AudioSource method.
void setLooping(bool shouldLoop) override
Implementation of the PositionableAudioSource method.
void getNextAudioBlock(const AudioSourceChannelInfo &bufferToFill) override
Implementation of the AudioSource method.
void releaseResources() override
Implementation of the AudioSource method.
This is a base class for classes that perform a unit test.
@ copy
The command ID that should be used to send a "Copy to clipboard" command.
constexpr Type jmap(Type value0To1, Type targetRangeMin, Type targetRangeMax)
Remaps a normalised value (between 0 and 1) to a target range.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
long long int64
A platform-independent 64-bit integer type.
Used by AudioSource::getNextAudioBlock().
int numSamples
The number of samples in the buffer which the callback is expected to fill with data.
void clearActiveBufferRegion() const
Convenient method to clear the buffer if the source is not producing any data.
AudioBuffer< float > * buffer
The destination buffer to fill with audio data.
int startSample
The first sample in the buffer from which the callback is expected to write data.