Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: media/base/audio_bus.h

Issue 2024993004: AudioBus: Add a ToInterleavedFloat() method to AudioBus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed a todo Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/BUILD.gn ('k') | media/base/audio_bus.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/audio_bus.h
diff --git a/media/base/audio_bus.h b/media/base/audio_bus.h
index f827f9db87d396667e39d3105f10a33f85e39d11..6d381ccac3daa3c9325fb9d4af99259e4cef3825 100644
--- a/media/base/audio_bus.h
+++ b/media/base/audio_bus.h
@@ -18,11 +18,15 @@
namespace media {
class AudioParameters;
-// Scoped container for "busing" audio channel data around. Each channel is
-// stored in planar format and guaranteed to be aligned by kChannelAlignment.
-// AudioBus objects can be created normally or via wrapping. Normally, AudioBus
-// will dice up a contiguous memory block for channel data. When wrapped,
-// AudioBus instead routes requests for channel data to the wrapped object.
+// Represents a sequence of audio frames containing frames() audio samples for
+// each of channels() channels. The data is stored as a set of contiguous
+// float arrays with one array per channel. The memory for the arrays is either
+// allocated and owned by the AudioBus or it is provided to one of the factory
+// methods. AudioBus guarantees that it allocates memory such that float array
+// for each channel is aligned by AudioBus::kChannelAlignment bytes and it
+// requires the same for memory passed to its Wrap...() factory methods.
+// TODO(chfremer): There are currently no unit tests involving CreateWrapper and
+// SetChannelData, so we need to add them.
class MEDIA_EXPORT AudioBus {
public:
// Guaranteed alignment of each channel's data; use 16-byte alignment for easy
@@ -35,8 +39,8 @@ class MEDIA_EXPORT AudioBus {
static std::unique_ptr<AudioBus> Create(const AudioParameters& params);
// Creates a new AudioBus with the given number of channels, but zero length.
- // It's expected to be used with SetChannelData() and set_frames() to
- // wrap externally allocated memory.
+ // Clients are expected to subsequently call SetChannelData() and set_frames()
+ // to wrap externally allocated memory.
static std::unique_ptr<AudioBus> CreateWrapper(int channels);
// Creates a new AudioBus from an existing channel vector. Does not transfer
@@ -54,31 +58,86 @@ class MEDIA_EXPORT AudioBus {
void* data);
static std::unique_ptr<AudioBus> WrapMemory(const AudioParameters& params,
void* data);
- static int CalculateMemorySize(const AudioParameters& params);
- // Calculates the required size for an AudioBus given the number of channels
- // and frames.
+ // Based on the given number of channels and frames, calculates the minimum
+ // required size in bytes of a contiguous block of memory to be passed to
+ // AudioBus for storage of the audio data.
+ // Uses channels() and frames_per_buffer() from AudioParameters if given.
static int CalculateMemorySize(int channels, int frames);
+ static int CalculateMemorySize(const AudioParameters& params);
+
+ // Methods that are expected to be called after AudioBus::CreateWrapper() in
+ // order to wrap externally allocated memory. Note: It is illegal to call
+ // these methods when using a factory method other than CreateWrapper().
+ void SetChannelData(int channel, float* data);
+ void set_frames(int frames);
- // Helper methods for converting an AudioBus from and to interleaved integer
- // data. Expects interleaving to be [ch0, ch1, ..., chN, ch0, ch1, ...] with
- // |bytes_per_sample| per value. Values are scaled and bias corrected during
- // conversion. ToInterleaved() will also clip values to format range.
- // Handles uint8_t, int16_t, and int32_t currently. FromInterleaved() will
- // zero out
- // any unfilled frames when |frames| is less than frames().
+ // Overwrites the sample values stored in this AudioBus instance with values
+ // from a given interleaved |source_buffer| with expected layout
+ // [ch0, ch1, ..., chN, ch0, ch1, ...] and sample values in the format
+ // corresponding to the given SourceSampleTypeTraits.
+ // The sample values are converted to float values by means of the method
+ // convert_to_float32() provided by the SourceSampleTypeTraits. For a list of
+ // ready-to-use SampleTypeTraits, see file audio_sample_types.h.
+ // If |num_frames_to_write| is less than frames(), the remaining frames are
+ // zeroed out. If |num_frames_to_write| is more than frames(), this results in
+ // undefined behavior.
+ template <class SourceSampleTypeTraits>
+ void FromInterleaved(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int num_frames_to_write);
+
+ // DEPRECATED (https://crbug.com/580391)
+ // Please use the version templated with SourceSampleTypeTraits instead.
+ // TODO(chfremer): Remove (https://crbug.com/619623)
void FromInterleaved(const void* source, int frames, int bytes_per_sample);
- void ToInterleaved(int frames, int bytes_per_sample, void* dest) const;
- void ToInterleavedPartial(int start_frame, int frames, int bytes_per_sample,
- void* dest) const;
- // Similar to FromInterleaved() above, but meant for streaming sources. Does
- // not zero out remaining frames, the caller is responsible for doing so using
- // ZeroFramesPartial(). Frames are deinterleaved from the start of |source|
- // to channel(x)[start_frame].
+ // Similar to FromInterleaved...(), but overwrites the frames starting at a
+ // given offset |write_offset_in_frames| and does not zero out frames that are
+ // not overwritten.
+ template <class SourceSampleTypeTraits>
+ void FromInterleavedPartial(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int write_offset_in_frames,
+ int num_frames_to_write);
+
+ // DEPRECATED (https://crbug.com/580391)
+ // Please use the version templated with SourceSampleTypeTraits instead.
+ // TODO(chfremer): Remove (https://crbug.com/619623)
void FromInterleavedPartial(const void* source, int start_frame, int frames,
int bytes_per_sample);
+ // Reads the sample values stored in this AudioBus instance and places them
+ // into the given |dest_buffer| in interleaved format using the sample format
+ // specified by TargetSampleTypeTraits. For a list of ready-to-use
+ // SampleTypeTraits, see file audio_sample_types.h. If |num_frames_to_read| is
+ // larger than frames(), this results in undefined behavior.
+ template <class TargetSampleTypeTraits>
+ void ToInterleaved(
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
+
+ // DEPRECATED (https://crbug.com/580391)
+ // Please use the version templated with TargetSampleTypeTraits instead.
+ // TODO(chfremer): Remove (https://crbug.com/619623)
+ void ToInterleaved(int frames, int bytes_per_sample, void* dest) const;
+
+ // Similar to ToInterleaved(), but reads the frames starting at a given
+ // offset |read_offset_in_frames|.
+ template <class TargetSampleTypeTraits>
+ void ToInterleavedPartial(
+ int read_offset_in_frames,
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
+
+ // DEPRECATED (https://crbug.com/580391)
+ // Please use the version templated with TargetSampleTypeTraits instead.
+ // TODO(chfremer): Remove (https://crbug.com/619623)
+ void ToInterleavedPartial(int start_frame,
+ int frames,
+ int bytes_per_sample,
+ void* dest) const;
+
// Helper method for copying channel data from one AudioBus to another. Both
// AudioBus object must have the same frames() and channels().
void CopyTo(AudioBus* dest) const;
@@ -97,11 +156,11 @@ class MEDIA_EXPORT AudioBus {
// inf, nan, or between [-1.0, 1.0]) values in the channel data.
float* channel(int channel) { return channel_data_[channel]; }
const float* channel(int channel) const { return channel_data_[channel]; }
- void SetChannelData(int channel, float* data);
+ // Returns the number of channels.
int channels() const { return static_cast<int>(channel_data_.size()); }
+ // Returns the number of frames.
int frames() const { return frames_; }
- void set_frames(int frames);
// Helper method for zeroing out all channels of audio data.
void Zero();
@@ -129,12 +188,32 @@ class MEDIA_EXPORT AudioBus {
private:
// Helper method for building |channel_data_| from a block of memory. |data|
- // must be at least BlockSize() bytes in size.
+ // must be at least CalculateMemorySize(...) bytes in size.
void BuildChannelData(int channels, int aligned_frame, float* data);
+ static void CheckOverflow(int start_frame, int frames, int total_frames);
+
+ template <class SourceSampleTypeTraits>
+ static void CopyConvertFromInterleavedSourceToAudioBus(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int write_offset_in_frames,
+ int num_frames_to_write,
+ AudioBus* dest);
+
+ template <class TargetSampleTypeTraits>
+ static void CopyConvertFromAudioBusToInterleavedTarget(
+ const AudioBus* source,
+ int read_offset_in_frames,
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest_buffer);
+
// Contiguous block of channel memory.
std::unique_ptr<float, base::AlignedFreeDeleter> data_;
+ // One float pointer per channel pointing to a contiguous block of memory for
+ // that channel. If the memory is owned by this instance, this will
+ // point to the memory in |data_|. Otherwise, it may point to memory provided
+ // by the client.
std::vector<float*> channel_data_;
int frames_;
@@ -144,6 +223,89 @@ class MEDIA_EXPORT AudioBus {
DISALLOW_COPY_AND_ASSIGN(AudioBus);
};
+// Delegates to FromInterleavedPartial()
+template <class SourceSampleTypeTraits>
+void AudioBus::FromInterleaved(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int num_frames_to_write) {
+ FromInterleavedPartial<SourceSampleTypeTraits>(source_buffer, 0,
+ num_frames_to_write);
+ // Zero any remaining frames.
+ ZeroFramesPartial(num_frames_to_write, frames_ - num_frames_to_write);
+}
+
+template <class SourceSampleTypeTraits>
+void AudioBus::FromInterleavedPartial(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int write_offset_in_frames,
+ int num_frames_to_write) {
+ CheckOverflow(write_offset_in_frames, num_frames_to_write, frames_);
+ CopyConvertFromInterleavedSourceToAudioBus<SourceSampleTypeTraits>(
+ source_buffer, write_offset_in_frames, num_frames_to_write, this);
+}
+
+// Delegates to ToInterleavedPartial()
+template <class TargetSampleTypeTraits>
+void AudioBus::ToInterleaved(
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest_buffer) const {
+ ToInterleavedPartial<TargetSampleTypeTraits>(0, num_frames_to_read,
+ dest_buffer);
+}
+
+template <class TargetSampleTypeTraits>
+void AudioBus::ToInterleavedPartial(
+ int read_offset_in_frames,
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest) const {
+ CheckOverflow(read_offset_in_frames, num_frames_to_read, frames_);
+ CopyConvertFromAudioBusToInterleavedTarget<TargetSampleTypeTraits>(
+ this, read_offset_in_frames, num_frames_to_read, dest);
+}
+
+// TODO(chfremer): Consider using vector instructions to speed this up,
+// https://crbug.com/619628
+template <class SourceSampleTypeTraits>
+void AudioBus::CopyConvertFromInterleavedSourceToAudioBus(
+ const typename SourceSampleTypeTraits::ValueType* source_buffer,
+ int write_offset_in_frames,
+ int num_frames_to_write,
+ AudioBus* dest) {
+ const int channels = dest->channels();
+ for (int ch = 0; ch < channels; ++ch) {
+ float* channel_data = dest->channel(ch);
+ for (int target_frame_index = write_offset_in_frames,
+ read_pos_in_source = ch;
+ target_frame_index < write_offset_in_frames + num_frames_to_write;
+ ++target_frame_index, read_pos_in_source += channels) {
+ auto source_value = source_buffer[read_pos_in_source];
+ channel_data[target_frame_index] =
+ SourceSampleTypeTraits::ToFloat(source_value);
+ }
+ }
+}
+
+// TODO(chfremer): Consider using vector instructions to speed this up,
+// https://crbug.com/619628
+template <class TargetSampleTypeTraits>
+void AudioBus::CopyConvertFromAudioBusToInterleavedTarget(
+ const AudioBus* source,
+ int read_offset_in_frames,
+ int num_frames_to_read,
+ typename TargetSampleTypeTraits::ValueType* dest_buffer) {
+ const int channels = source->channels();
+ for (int ch = 0; ch < channels; ++ch) {
+ const float* channel_data = source->channel(ch);
+ for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch;
+ source_frame_index < read_offset_in_frames + num_frames_to_read;
+ ++source_frame_index, write_pos_in_dest += channels) {
+ float sourceSampleValue = channel_data[source_frame_index];
+ dest_buffer[write_pos_in_dest] =
+ TargetSampleTypeTraits::FromFloat(sourceSampleValue);
+ }
+ }
+}
+
// RefCounted version of AudioBus. This is not meant for general use. Only use
// this when your lifetime requirements make it impossible to use an
// AudioBus scoped_ptr.
« no previous file with comments | « media/base/BUILD.gn ('k') | media/base/audio_bus.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698