19template <
typename SampleType>
27 AudioBuffer (size_t numChannels = 0, size_t numFrames = 0,
double sampleRateHz =
nan<double>()) :
28 m_numChannels (numChannels),
29 m_numFrames (numFrames),
30 m_sampleRateHz (sampleRateHz),
31 m_frames (m_numChannels * m_numFrames),
32 m_channelPointers (m_numChannels)
34 updateChannelPointers();
39 m_numChannels (other.m_numChannels),
40 m_numFrames (other.m_numFrames),
41 m_sampleRateHz (other.m_sampleRateHz),
42 m_frames (other.m_frames),
43 m_channelPointers (m_numChannels)
45 updateChannelPointers();
50 m_numChannels (other.m_numChannels),
51 m_numFrames (other.m_numFrames),
52 m_sampleRateHz (other.m_sampleRateHz),
53 m_frames (std::move (other.m_frames)),
54 m_channelPointers (std::move (other.m_channelPointers))
68 if (m_numChannels != other.m_numChannels)
71 m_numFrames = other.m_numFrames;
72 m_sampleRateHz = other.m_sampleRateHz;
73 m_frames = other.m_frames;
74 m_channelPointers.resize (m_numChannels);
75 updateChannelPointers();
86 m_numChannels = other.m_numChannels;
87 m_numFrames = other.m_numFrames;
88 m_sampleRateHz = other.m_sampleRateHz;
89 m_frames = std::move (other.m_frames);
90 m_channelPointers = std::move (other.m_channelPointers);
100 return static_cast<
const SampleType*
const*> (m_channelPointers.data());
107 return m_channelPointers.data();
115 return other.hasSampleRate()
116 ?
AudioBuffer (other.getNumChannels(), other.getNumFrames(), other.getSampleRateHz())
117 :
AudioBuffer (other.getNumChannels(), other.getNumFrames());
138 if (newNumFrames == m_numFrames)
141 const size_t oldTotalSamples = m_frames.size();
142 const size_t newTotalSamples = m_numChannels * newNumFrames;
144 if (newNumFrames < m_numFrames)
146 m_frames.resize (newTotalSamples);
147 m_numFrames = newNumFrames;
148 updateChannelPointers();
152 if (newTotalSamples > oldTotalSamples)
154 m_frames.resize (newTotalSamples);
156 m_frames.begin() + oldTotalSamples,
162 m_numFrames = newNumFrames;
163 updateChannelPointers();
171 return ! std::isnan (m_sampleRateHz);
179 hassert (! std::isnan (m_sampleRateHz));
180 return m_sampleRateHz;
188 if (m_numFrames == 0)
191 hassert (! std::isnan (m_sampleRateHz));
193 return static_cast <
double> (m_numFrames) / m_sampleRateHz;
201 return m_channelPointers[channel];
207 const SampleType*
operator[] (size_t channel)
const
209 return m_channelPointers[channel];
218 if (otherBuffer.getNumChannels() != m_numChannels)
224 const size_t thisNumFrames = m_numFrames;
225 const size_t otherNumFrames = otherBuffer.getNumFrames();
227 std::vector<SampleType> combinedFrames (m_numChannels * (thisNumFrames + otherNumFrames));
229 for (size_t channel = 0; channel < m_numChannels; ++channel)
231 SampleType* newChannelStart = &combinedFrames[channel * (thisNumFrames + otherNumFrames)];
232 std::copy (m_channelPointers[channel], m_channelPointers[channel] + thisNumFrames, newChannelStart);
233 std::copy (otherBuffer[channel], otherBuffer[channel] + otherNumFrames, newChannelStart + thisNumFrames);
236 m_frames = std::move (combinedFrames);
237 m_numFrames += otherNumFrames;
239 updateChannelPointers();
252 if (m_channelPointers.size() != m_numChannels)
253 m_channelPointers.resize (m_numChannels);
255 updateChannelPointers();
263 SampleType
getMagnitude (size_t channel, size_t startFrame, size_t numFrames)
const
265 if (channel >= m_numChannels)
268 if (startFrame + numFrames > m_numFrames || numFrames == 0)
271 const SampleType* start = m_channelPointers[channel] + startFrame;
272 const SampleType* peakSample = std::max_element (
275 [] (SampleType a, SampleType b) {
return std::abs (a) < std::abs (b); }
278 return std::abs (*peakSample);
287 if (startFrame + numFrames > m_numFrames || numFrames == 0)
290 SampleType peakSampleAcrossAllChannels = (SampleType) 0;
292 for (size_t channel = 0; channel < m_numChannels; ++channel)
294 const SampleType* start = m_channelPointers[channel] + startFrame;
295 const SampleType* peakSample = std::max_element (
298 [] (SampleType a, SampleType b) {
return std::abs (a) < std::abs (b); }
300 peakSampleAcrossAllChannels = std::max (peakSampleAcrossAllChannels, std::abs (*peakSample));
303 return peakSampleAcrossAllChannels;
315 void copyFrom (size_t destChannel, size_t destStartFrame,
const AudioBuffer& source, size_t sourceChannel, size_t sourceStartFrame, size_t numFrames)
317 if (destChannel >= m_numChannels || sourceChannel >= source.m_numChannels)
320 if (destStartFrame + numFrames > m_numFrames || sourceStartFrame + numFrames > source.m_numFrames)
327 source.m_channelPointers[sourceChannel] + sourceStartFrame,
328 source.m_channelPointers[sourceChannel] + sourceStartFrame + numFrames,
329 m_channelPointers[destChannel] + destStartFrame
338 void copyFrom (size_t destChannel, size_t destStartFrame,
const SampleType* source, size_t numFrames)
340 if (destChannel >= m_numChannels)
343 if (destStartFrame + numFrames > m_numFrames)
346 std::copy (source, source + numFrames, m_channelPointers[destChannel] + destStartFrame);
353 std::fill (m_frames.begin(), m_frames.end(), (SampleType) 0);
361 void clear (size_t channel, size_t startFrame, size_t numFrames)
363 if (channel >= m_numChannels)
366 if (startFrame + numFrames > m_numFrames)
369 std::fill (m_channelPointers[channel], m_channelPointers[channel] + numFrames, (SampleType) 0);
376 std::ostringstream oss;
377 stream <<
"AudioBuffer (" << m_numChannels <<
", " << m_numFrames;
380 stream <<
", " <<
hzPrecision << m_sampleRateHz <<
')';
382 stream <<
", nan())";
386 size_t m_numChannels = 0;
387 size_t m_numFrames = 0;
388 double m_sampleRateHz =
nan<double>();
389 std::vector<SampleType> m_frames;
390 std::vector<SampleType*> m_channelPointers;
392 void updateChannelPointers()
394 for (size_t channel = 0; channel < m_numChannels; ++channel)
395 m_channelPointers[channel] = m_numFrames > 0 ? &m_frames[channel * m_numFrames] :
nullptr;
Container for audio data.
void clear(size_t channel, size_t startFrame, size_t numFrames)
Clears a specific section of a given channel.
SampleType * operator[](size_t channel)
Get a raw pointer to a specific channel's mutable audio data.
static AudioBuffer emptyLike(const AudioBuffer &other)
Creates an empty audio buffer with the same number of channels, frames and sample rate as the other b...
AudioBuffer & operator=(AudioBuffer &&other)
Creates an audio buffer by move-assigning.
size_t getNumFrames() const
Get number of frames (samples)
AudioBuffer & operator=(const AudioBuffer &other)
Creates an audio buffer by copy-assigning.
AudioBuffer(size_t numChannels=0, size_t numFrames=0, double sampleRateHz=nan< double >())
Creates an audio buffer.
void appendFrom(const AudioBuffer< SampleType > &otherBuffer)
Appends data from another buffer.
double getLengthSeconds() const
Get a duration of the audio buffer.
bool hasSampleRate() const
Check if a specific sample rate was assigned to the audio buffer.
void setNumFrames(size_t newNumFrames)
Resizes the buffer to hold a new number of frames per channel.
void copyFrom(size_t destChannel, size_t destStartFrame, const SampleType *source, size_t numFrames)
Copies audio from another generic audio buffer.
void copyFrom(size_t destChannel, size_t destStartFrame, const AudioBuffer &source, size_t sourceChannel, size_t sourceStartFrame, size_t numFrames)
Copies audio from another buffer.
double getSampleRateHz() const
Get a sample rate metadata.
const SampleType *const * getArrayOfReadPointers() const
Gets a raw pointer to the read-only audio data.
SampleType getMagnitude(size_t startFrame, size_t numFrames) const
Get the maximum absolute value in the buffer across all channels.
SampleType *const * getArrayOfWritePointers()
Gets a raw pointer to the mutable audio data.
AudioBuffer(const AudioBuffer &other)
Creates an audio buffer by copying.
~AudioBuffer()=default
The destructor.
const SampleType * operator[](size_t channel) const
Get a raw pointer to a specific channel's read-only audio data.
AudioBuffer(AudioBuffer &&other)
Creates an audio buffer by moving.
void represent(std::ostream &stream) const
Prints readable representation of the audio buffer.
SampleType getMagnitude(size_t channel, size_t startFrame, size_t numFrames) const
Get the maximum absolute value in the buffer in a specific channel.
void clear()
Clears the entire buffer.
size_t getNumChannels() const
Get number of channels.
void erase()
Clears the buffer.
Thrown when a numbers of channels is mismatched.
Thrown when a container index is out of range.
#define HART_THROW_OR_RETURN_VOID(ExceptionType, message)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns otherwise.
#define hassert(condition)
Triggers a HartAssertException if the condition is false
#define HART_THROW_OR_RETURN(ExceptionType, message, returnValue)
Throws an exception if HART_DO_NOT_THROW_EXCEPTIONS is set, prints a message and returns a specified ...
std::ostream & hzPrecision(std::ostream &stream)
Sets number of decimal places for values in hertz.
FloatType nan()
Returns a quiet NaN value for the given floating-point type.
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.