cocos-engine-external/sources/LabSound/include/LabSound/core/AudioBus.h

149 lines
5.6 KiB
C++

// License: BSD 3 Clause
// Copyright (C) 2010, Google Inc. All rights reserved.
// Copyright (C) 2015+, The LabSound Authors. All rights reserved.
#ifndef AudioBus_h
#define AudioBus_h
#include "LabSound/core/AudioChannel.h"
#include "LabSound/core/Mixing.h"
#include <iostream>
#include <vector>
namespace lab
{
using lab::Channel;
using lab::ChannelInterpretation;
// An AudioBus represents a collection of one or more AudioChannels.
// The data layout is "planar" as opposed to "interleaved".
// An AudioBus with one channel is mono, an AudioBus with two channels is stereo, etc.
class AudioBus
{
AudioBus(const AudioBus &); // noncopyable
public:
// Can define non-standard layouts here:
enum
{
LayoutCanonical = 0
};
// allocate indicates whether or not to initially have the AudioChannels created with managed storage.
// Normal usage is to pass true here, in which case the AudioChannels will memory-manage their own storage.
// If allocate is false then setChannelMemory() has to be called later on for each channel before the AudioBus is useable...
AudioBus(int numberOfChannels, int length, bool allocate = true);
// Tells the given channel to use an externally allocated buffer.
void setChannelMemory(int channelIndex, float * storage, int length);
// Channels
int numberOfChannels() const { return static_cast<int>(m_channels.size()); }
// Use this when looping over channels
AudioChannel * channel(int channel) { return m_channels[channel].get(); }
const AudioChannel * channel(int channel) const
{
return const_cast<AudioBus *>(this)->m_channels[channel].get();
}
// use this when accessing channels semantically
AudioChannel * channelByType(Channel type);
const AudioChannel * channelByType(Channel type) const;
// Number of sample-frames
int length() const { return m_length; }
// resizeSmaller() can only be called with a new length <= the current length.
// The data stored in the bus will remain undisturbed.
void resizeSmaller(int newLength);
// Sample-rate : 0.0 if unknown or "don't care"
float sampleRate() const { return m_sampleRate; }
void setSampleRate(float sampleRate) { m_sampleRate = sampleRate; }
// Zeroes all channels.
void zero();
// Clears the silent flag on all channels.
void clearSilentFlag();
// Returns true if the silent bit is set on all channels.
bool isSilent() const;
// Returns true if the channel count and frame-size match.
bool topologyMatches(const AudioBus & sourceBus) const;
// Scales all samples by the same amount.
void scale(float scale);
void reset() { m_isFirstTime = true; } // for de-zippering
// Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.
void copyFrom(const AudioBus & sourceBus, ChannelInterpretation = ChannelInterpretation::Speakers);
// Sums the sourceBus into our bus with unity gain.
// Our own internal gain m_busGain is ignored.
void sumFrom(const AudioBus & sourceBus, ChannelInterpretation = ChannelInterpretation::Speakers);
// Copy each channel from sourceBus into our corresponding channel.
// We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
// The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be applied to this bus.
// This represents the dezippering memory.
void copyWithGainFrom(const AudioBus & sourceBus, float * lastMixGain, float targetGain);
// Copies the sourceBus by scaling with sample-accurate gain values.
void copyWithSampleAccurateGainValuesFrom(const AudioBus & sourceBus, float * gainValues, int numberOfGainValues);
// Returns maximum absolute value across all channels (useful for normalization).
float maxAbsValue() const;
// Makes maximum absolute value == 1.0 (if possible).
void normalize();
bool isFirstTime() { return m_isFirstTime; }
// Static Functions
// Creates a new buffer from a range in the source buffer.
// 0 may be returned if the range does not fit in the sourceBuffer
static std::unique_ptr<AudioBus> createBufferFromRange(const AudioBus * sourceBus, int startFrame, int endFrame);
// Creates a new AudioBus by sample-rate converting sourceBus to the newSampleRate.
// setSampleRate() must have been previously called on sourceBus.
static std::unique_ptr<AudioBus> createBySampleRateConverting(const AudioBus * sourceBus, bool mixToMono, float newSampleRate);
// Creates a new AudioBus by mixing all the channels down to mono.
// If sourceBus is already mono, then the returned AudioBus will simply be a copy.
static std::unique_ptr<AudioBus> createByMixingToMono(const AudioBus * sourceBus);
// Creates a new AudioBus by cloning an existing one
static std::unique_ptr<AudioBus> createByCloning(const AudioBus * sourceBus);
protected:
AudioBus() = default;
void speakersCopyFrom(const AudioBus &);
void discreteCopyFrom(const AudioBus &);
void speakersSumFrom(const AudioBus &);
void discreteSumFrom(const AudioBus &);
void speakersSumFrom5_1_ToMono(const AudioBus &);
void speakersSumFrom7_1_ToMono(const AudioBus &);
std::unique_ptr<AudioFloatArray> m_dezipperGainValues;
std::vector<std::unique_ptr<AudioChannel>> m_channels;
bool m_isFirstTime = true;
float m_sampleRate = 0.0f;
float m_busGain = 1.0f;
int m_layout = LayoutCanonical;
int m_length = 0;
};
} // lab
#endif // AudioBus_h