// This file contains 3 types of view classes: // // * MonoView<>: A single channel contiguous buffer of samples. // // * InterleavedView<>: Channel samples are interleaved (side-by-side) in // the buffer. A single channel InterleavedView<> is the same thing as a // MonoView<> // // * DeinterleavedView<>: Each channel's samples are contiguous within the // buffer. Channels can be enumerated and accessing the individual channel // data is done via MonoView<>. // // The views are comparable to and built on std::span<> but add // audio specific properties for the dimensions of the buffer and the above // specialized [de]interleaved support. // // There are also a few generic utility functions that can simplify // generic code for supporting more than one type of view.
// MonoView<> represents a view over a single contiguous, audio buffer. This // can be either an single channel (mono) interleaved buffer (e.g. AudioFrame), // or a de-interleaved channel (e.g. from AudioBuffer). template <typename T> using MonoView = std::span<T>;
// The maximum number of audio channels supported by WebRTC encoders, decoders // and the AudioFrame class. // AudioFrame's max number of samples is 7680, which can hold 16 10ms 16bit // channels at 48 kHz. static constexpr size_t kMaxNumberOfAudioChannels = 16;
// InterleavedView<> is a view over an interleaved audio buffer (e.g. from // AudioFrame). template <typename T> class InterleavedView { public: using value_type = T; using iterator = typename std::span<T>::iterator; using const_iterator = typename std::span<const T>::iterator;
// Construct an InterleavedView from a C-style array. Samples per channels // is calculated based on the array size / num_channels. template <typename U, size_t N>
InterleavedView(U (&array)[N], // NOLINT
size_t num_channels)
: InterleavedView(array, N / num_channels, num_channels) {
RTC_DCHECK_EQ(N % num_channels, 0u);
}
// A simple wrapper around memcpy that includes checks for properties. // TODO(tommi): Consider if this can be utility function for both interleaved // and deinterleaved views. template <typename U> void CopyFrom(const InterleavedView<U>& source) {
static_assert(sizeof(T) == sizeof(U), "");
RTC_DCHECK_EQ(num_channels(), source.num_channels());
RTC_DCHECK_EQ(samples_per_channel(), source.samples_per_channel());
RTC_DCHECK_GE(data_.size(), source.data().size()); constauto data = source.data();
memcpy(&data_[0], &data[0], data.size() * sizeof(U));
}
private: // TODO(tommi): Consider having these both be stored as uint16_t to // save a few bytes per view. Use `dchecked_cast` to support size_t during // construction.
size_t num_channels_ = 0u;
size_t samples_per_channel_ = 0u;
std::span<T> data_;
};
template <typename T> class DeinterleavedView { public: using value_type = T;
DeinterleavedView() = default;
// Construct a view where all the channels are coallocated in a single buffer. template <typename U>
DeinterleavedView(U* data, size_t samples_per_channel, size_t num_channels)
: num_channels_(num_channels),
samples_per_channel_(samples_per_channel),
data_(data) {}
// Construct a view from an array of channel pointers where the channels // may all be allocated seperately. template <typename U>
DeinterleavedView(U* const* channels,
size_t samples_per_channel,
size_t num_channels)
: num_channels_(num_channels),
samples_per_channel_(samples_per_channel),
data_(channels) {}
// Construct a view from an array of channel pointers where the pointers are // helt in a `std::vector<>`. template <typename U>
DeinterleavedView(const std::vector<U*>& channels, size_t samples_per_channel)
: num_channels_(channels.size()),
samples_per_channel_(samples_per_channel),
data_(channels.data()) {}
// Construct a view from another view. Note that the type of // the other view may be different from the current type and // therefore the internal data types may not be exactly the // same, but still compatible. // E.g.: // DeinterleavedView<float> mutable_view; // DeinterleavedView<const float> const_view(mutable_view); template <typename U>
DeinterleavedView(const DeinterleavedView<U>& other)
: num_channels_(other.num_channels_),
samples_per_channel_(other.samples_per_channel()) {
if (other.is_ptr_array()) {
data_ = std::get<U* const*>(other.data_);
} else {
data_ = std::get<U*>(other.data_);
}
}
// Returns a deinterleaved channel where `idx` is the zero based index, // in the range [0 .. num_channels()-1].
MonoView<T> operator[](size_t idx) const {
RTC_DCHECK_LT(idx, num_channels());
if (is_ptr_array()) return MonoView<T>(std::get<T* const*>(data_)[idx], samples_per_channel_); return MonoView<T>(&std::get<T*>(data_)[idx * samples_per_channel_],
samples_per_channel_);
}
// Returns the first (and possibly only) channel.
MonoView<T> AsMono() const {
RTC_DCHECK_GE(num_channels(), 1u); return (*this)[0];
}
// Zeros out all samples in channels represented by the view. void Clear() {
for (size_t i = 0u; i < num_channels_; ++i) {
MonoView<T> view = (*this)[i];
absl::c_fill(view, 0);
}
}
template <typename T>
size_t SamplesPerChannel(const DeinterleavedView<T>& view) { return view.samples_per_channel();
} // A simple wrapper around memcpy that includes checks for properties. // The parameter order is the same as for memcpy(), first destination then // source. template <typename D, typename S> void CopySamples(D& destination, const S& source) {
static_assert( sizeof(typename D::value_type) == sizeof(typename S::value_type), ""); // Here we'd really like to do // static_assert(IsInterleavedView(destination) == IsInterleavedView(source), // ""); // but the compiler doesn't like it inside this template function for // some reason. The following check is an approximation but unfortunately // means that copying between a MonoView and single channel interleaved or // deinterleaved views wouldn't work. // static_assert(sizeof(destination) == sizeof(source), // "Incompatible view types");
RTC_DCHECK_EQ(NumChannels(destination), NumChannels(source));
RTC_DCHECK_EQ(SamplesPerChannel(destination), SamplesPerChannel(source));
RTC_DCHECK_GE(destination.size(), source.size());
memcpy(&destination[0], &source[0],
source.size() * sizeof(typename S::value_type));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.