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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « media/base/BUILD.gn ('k') | media/base/audio_bus.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MEDIA_BASE_AUDIO_BUS_H_ 5 #ifndef MEDIA_BASE_AUDIO_BUS_H_
6 #define MEDIA_BASE_AUDIO_BUS_H_ 6 #define MEDIA_BASE_AUDIO_BUS_H_
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <memory> 10 #include <memory>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/memory/aligned_memory.h" 14 #include "base/memory/aligned_memory.h"
15 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
16 #include "media/base/media_export.h" 16 #include "media/base/media_export.h"
17 17
18 namespace media { 18 namespace media {
19 class AudioParameters; 19 class AudioParameters;
20 20
21 // Scoped container for "busing" audio channel data around. Each channel is 21 // Represents a sequence of audio frames containing frames() audio samples for
22 // stored in planar format and guaranteed to be aligned by kChannelAlignment. 22 // each of channels() channels. The data is stored as a set of contiguous
23 // AudioBus objects can be created normally or via wrapping. Normally, AudioBus 23 // float arrays with one array per channel. The memory for the arrays is either
24 // will dice up a contiguous memory block for channel data. When wrapped, 24 // allocated and owned by the AudioBus or it is provided to one of the factory
25 // AudioBus instead routes requests for channel data to the wrapped object. 25 // methods. AudioBus guarantees that it allocates memory such that float array
26 // for each channel is aligned by AudioBus::kChannelAlignment bytes and it
27 // requires the same for memory passed to its Wrap...() factory methods.
28 // TODO(chfremer): There are currently no unit tests involving CreateWrapper and
29 // SetChannelData, so we need to add them.
26 class MEDIA_EXPORT AudioBus { 30 class MEDIA_EXPORT AudioBus {
27 public: 31 public:
28 // Guaranteed alignment of each channel's data; use 16-byte alignment for easy 32 // Guaranteed alignment of each channel's data; use 16-byte alignment for easy
29 // SSE optimizations. 33 // SSE optimizations.
30 enum { kChannelAlignment = 16 }; 34 enum { kChannelAlignment = 16 };
31 35
32 // Creates a new AudioBus and allocates |channels| of length |frames|. Uses 36 // Creates a new AudioBus and allocates |channels| of length |frames|. Uses
33 // channels() and frames_per_buffer() from AudioParameters if given. 37 // channels() and frames_per_buffer() from AudioParameters if given.
34 static std::unique_ptr<AudioBus> Create(int channels, int frames); 38 static std::unique_ptr<AudioBus> Create(int channels, int frames);
35 static std::unique_ptr<AudioBus> Create(const AudioParameters& params); 39 static std::unique_ptr<AudioBus> Create(const AudioParameters& params);
36 40
37 // Creates a new AudioBus with the given number of channels, but zero length. 41 // Creates a new AudioBus with the given number of channels, but zero length.
38 // It's expected to be used with SetChannelData() and set_frames() to 42 // Clients are expected to subsequently call SetChannelData() and set_frames()
39 // wrap externally allocated memory. 43 // to wrap externally allocated memory.
40 static std::unique_ptr<AudioBus> CreateWrapper(int channels); 44 static std::unique_ptr<AudioBus> CreateWrapper(int channels);
41 45
42 // Creates a new AudioBus from an existing channel vector. Does not transfer 46 // Creates a new AudioBus from an existing channel vector. Does not transfer
43 // ownership of |channel_data| to AudioBus; i.e., |channel_data| must outlive 47 // ownership of |channel_data| to AudioBus; i.e., |channel_data| must outlive
44 // the returned AudioBus. Each channel must be aligned by kChannelAlignment. 48 // the returned AudioBus. Each channel must be aligned by kChannelAlignment.
45 static std::unique_ptr<AudioBus> WrapVector( 49 static std::unique_ptr<AudioBus> WrapVector(
46 int frames, 50 int frames,
47 const std::vector<float*>& channel_data); 51 const std::vector<float*>& channel_data);
48 52
49 // Creates a new AudioBus by wrapping an existing block of memory. Block must 53 // Creates a new AudioBus by wrapping an existing block of memory. Block must
50 // be at least CalculateMemorySize() bytes in size. |data| must outlive the 54 // be at least CalculateMemorySize() bytes in size. |data| must outlive the
51 // returned AudioBus. |data| must be aligned by kChannelAlignment. 55 // returned AudioBus. |data| must be aligned by kChannelAlignment.
52 static std::unique_ptr<AudioBus> WrapMemory(int channels, 56 static std::unique_ptr<AudioBus> WrapMemory(int channels,
53 int frames, 57 int frames,
54 void* data); 58 void* data);
55 static std::unique_ptr<AudioBus> WrapMemory(const AudioParameters& params, 59 static std::unique_ptr<AudioBus> WrapMemory(const AudioParameters& params,
56 void* data); 60 void* data);
61
62 // Based on the given number of channels and frames, calculates the minimum
63 // required size in bytes of a contiguous block of memory to be passed to
64 // AudioBus for storage of the audio data.
65 // Uses channels() and frames_per_buffer() from AudioParameters if given.
66 static int CalculateMemorySize(int channels, int frames);
57 static int CalculateMemorySize(const AudioParameters& params); 67 static int CalculateMemorySize(const AudioParameters& params);
58 68
59 // Calculates the required size for an AudioBus given the number of channels 69 // Methods that are expected to be called after AudioBus::CreateWrapper() in
60 // and frames. 70 // order to wrap externally allocated memory. Note: It is illegal to call
61 static int CalculateMemorySize(int channels, int frames); 71 // these methods when using a factory method other than CreateWrapper().
72 void SetChannelData(int channel, float* data);
73 void set_frames(int frames);
62 74
63 // Helper methods for converting an AudioBus from and to interleaved integer 75 // Overwrites the sample values stored in this AudioBus instance with values
64 // data. Expects interleaving to be [ch0, ch1, ..., chN, ch0, ch1, ...] with 76 // from a given interleaved |source_buffer| with expected layout
65 // |bytes_per_sample| per value. Values are scaled and bias corrected during 77 // [ch0, ch1, ..., chN, ch0, ch1, ...] and sample values in the format
66 // conversion. ToInterleaved() will also clip values to format range. 78 // corresponding to the given SourceSampleTypeTraits.
67 // Handles uint8_t, int16_t, and int32_t currently. FromInterleaved() will 79 // The sample values are converted to float values by means of the method
68 // zero out 80 // convert_to_float32() provided by the SourceSampleTypeTraits. For a list of
69 // any unfilled frames when |frames| is less than frames(). 81 // ready-to-use SampleTypeTraits, see file audio_sample_types.h.
82 // If |num_frames_to_write| is less than frames(), the remaining frames are
83 // zeroed out. If |num_frames_to_write| is more than frames(), this results in
84 // undefined behavior.
85 template <class SourceSampleTypeTraits>
86 void FromInterleaved(
87 const typename SourceSampleTypeTraits::ValueType* source_buffer,
88 int num_frames_to_write);
89
90 // DEPRECATED (https://crbug.com/580391)
91 // Please use the version templated with SourceSampleTypeTraits instead.
92 // TODO(chfremer): Remove (https://crbug.com/619623)
70 void FromInterleaved(const void* source, int frames, int bytes_per_sample); 93 void FromInterleaved(const void* source, int frames, int bytes_per_sample);
71 void ToInterleaved(int frames, int bytes_per_sample, void* dest) const;
72 void ToInterleavedPartial(int start_frame, int frames, int bytes_per_sample,
73 void* dest) const;
74 94
75 // Similar to FromInterleaved() above, but meant for streaming sources. Does 95 // Similar to FromInterleaved...(), but overwrites the frames starting at a
76 // not zero out remaining frames, the caller is responsible for doing so using 96 // given offset |write_offset_in_frames| and does not zero out frames that are
77 // ZeroFramesPartial(). Frames are deinterleaved from the start of |source| 97 // not overwritten.
78 // to channel(x)[start_frame]. 98 template <class SourceSampleTypeTraits>
99 void FromInterleavedPartial(
100 const typename SourceSampleTypeTraits::ValueType* source_buffer,
101 int write_offset_in_frames,
102 int num_frames_to_write);
103
104 // DEPRECATED (https://crbug.com/580391)
105 // Please use the version templated with SourceSampleTypeTraits instead.
106 // TODO(chfremer): Remove (https://crbug.com/619623)
79 void FromInterleavedPartial(const void* source, int start_frame, int frames, 107 void FromInterleavedPartial(const void* source, int start_frame, int frames,
80 int bytes_per_sample); 108 int bytes_per_sample);
81 109
110 // Reads the sample values stored in this AudioBus instance and places them
111 // into the given |dest_buffer| in interleaved format using the sample format
112 // specified by TargetSampleTypeTraits. For a list of ready-to-use
113 // SampleTypeTraits, see file audio_sample_types.h. If |num_frames_to_read| is
114 // larger than frames(), this results in undefined behavior.
115 template <class TargetSampleTypeTraits>
116 void ToInterleaved(
117 int num_frames_to_read,
118 typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
119
120 // DEPRECATED (https://crbug.com/580391)
121 // Please use the version templated with TargetSampleTypeTraits instead.
122 // TODO(chfremer): Remove (https://crbug.com/619623)
123 void ToInterleaved(int frames, int bytes_per_sample, void* dest) const;
124
125 // Similar to ToInterleaved(), but reads the frames starting at a given
126 // offset |read_offset_in_frames|.
127 template <class TargetSampleTypeTraits>
128 void ToInterleavedPartial(
129 int read_offset_in_frames,
130 int num_frames_to_read,
131 typename TargetSampleTypeTraits::ValueType* dest_buffer) const;
132
133 // DEPRECATED (https://crbug.com/580391)
134 // Please use the version templated with TargetSampleTypeTraits instead.
135 // TODO(chfremer): Remove (https://crbug.com/619623)
136 void ToInterleavedPartial(int start_frame,
137 int frames,
138 int bytes_per_sample,
139 void* dest) const;
140
82 // Helper method for copying channel data from one AudioBus to another. Both 141 // Helper method for copying channel data from one AudioBus to another. Both
83 // AudioBus object must have the same frames() and channels(). 142 // AudioBus object must have the same frames() and channels().
84 void CopyTo(AudioBus* dest) const; 143 void CopyTo(AudioBus* dest) const;
85 144
86 // Helper method to copy frames from one AudioBus to another. Both AudioBus 145 // Helper method to copy frames from one AudioBus to another. Both AudioBus
87 // objects must have the same number of channels(). |source_start_frame| is 146 // objects must have the same number of channels(). |source_start_frame| is
88 // the starting offset. |dest_start_frame| is the starting offset in |dest|. 147 // the starting offset. |dest_start_frame| is the starting offset in |dest|.
89 // |frame_count| is the number of frames to copy. 148 // |frame_count| is the number of frames to copy.
90 void CopyPartialFramesTo(int source_start_frame, 149 void CopyPartialFramesTo(int source_start_frame,
91 int frame_count, 150 int frame_count,
92 int dest_start_frame, 151 int dest_start_frame,
93 AudioBus* dest) const; 152 AudioBus* dest) const;
94 153
95 // Returns a raw pointer to the requested channel. Pointer is guaranteed to 154 // Returns a raw pointer to the requested channel. Pointer is guaranteed to
96 // have a 16-byte alignment. Warning: Do not rely on having sane (i.e. not 155 // have a 16-byte alignment. Warning: Do not rely on having sane (i.e. not
97 // inf, nan, or between [-1.0, 1.0]) values in the channel data. 156 // inf, nan, or between [-1.0, 1.0]) values in the channel data.
98 float* channel(int channel) { return channel_data_[channel]; } 157 float* channel(int channel) { return channel_data_[channel]; }
99 const float* channel(int channel) const { return channel_data_[channel]; } 158 const float* channel(int channel) const { return channel_data_[channel]; }
100 void SetChannelData(int channel, float* data);
101 159
160 // Returns the number of channels.
102 int channels() const { return static_cast<int>(channel_data_.size()); } 161 int channels() const { return static_cast<int>(channel_data_.size()); }
162 // Returns the number of frames.
103 int frames() const { return frames_; } 163 int frames() const { return frames_; }
104 void set_frames(int frames);
105 164
106 // Helper method for zeroing out all channels of audio data. 165 // Helper method for zeroing out all channels of audio data.
107 void Zero(); 166 void Zero();
108 void ZeroFrames(int frames); 167 void ZeroFrames(int frames);
109 void ZeroFramesPartial(int start_frame, int frames); 168 void ZeroFramesPartial(int start_frame, int frames);
110 169
111 // Checks if all frames are zero. 170 // Checks if all frames are zero.
112 bool AreFramesZero() const; 171 bool AreFramesZero() const;
113 172
114 // Scale internal channel values by |volume| >= 0. If an invalid value 173 // Scale internal channel values by |volume| >= 0. If an invalid value
115 // is provided, no adjustment is done. 174 // is provided, no adjustment is done.
116 void Scale(float volume); 175 void Scale(float volume);
117 176
118 // Swaps channels identified by |a| and |b|. The caller needs to make sure 177 // Swaps channels identified by |a| and |b|. The caller needs to make sure
119 // the channels are valid. 178 // the channels are valid.
120 void SwapChannels(int a, int b); 179 void SwapChannels(int a, int b);
121 180
122 virtual ~AudioBus(); 181 virtual ~AudioBus();
123 182
124 protected: 183 protected:
125 AudioBus(int channels, int frames); 184 AudioBus(int channels, int frames);
126 AudioBus(int channels, int frames, float* data); 185 AudioBus(int channels, int frames, float* data);
127 AudioBus(int frames, const std::vector<float*>& channel_data); 186 AudioBus(int frames, const std::vector<float*>& channel_data);
128 explicit AudioBus(int channels); 187 explicit AudioBus(int channels);
129 188
130 private: 189 private:
131 // Helper method for building |channel_data_| from a block of memory. |data| 190 // Helper method for building |channel_data_| from a block of memory. |data|
132 // must be at least BlockSize() bytes in size. 191 // must be at least CalculateMemorySize(...) bytes in size.
133 void BuildChannelData(int channels, int aligned_frame, float* data); 192 void BuildChannelData(int channels, int aligned_frame, float* data);
134 193
194 static void CheckOverflow(int start_frame, int frames, int total_frames);
195
196 template <class SourceSampleTypeTraits>
197 static void CopyConvertFromInterleavedSourceToAudioBus(
198 const typename SourceSampleTypeTraits::ValueType* source_buffer,
199 int write_offset_in_frames,
200 int num_frames_to_write,
201 AudioBus* dest);
202
203 template <class TargetSampleTypeTraits>
204 static void CopyConvertFromAudioBusToInterleavedTarget(
205 const AudioBus* source,
206 int read_offset_in_frames,
207 int num_frames_to_read,
208 typename TargetSampleTypeTraits::ValueType* dest_buffer);
209
135 // Contiguous block of channel memory. 210 // Contiguous block of channel memory.
136 std::unique_ptr<float, base::AlignedFreeDeleter> data_; 211 std::unique_ptr<float, base::AlignedFreeDeleter> data_;
137 212
213 // One float pointer per channel pointing to a contiguous block of memory for
214 // that channel. If the memory is owned by this instance, this will
215 // point to the memory in |data_|. Otherwise, it may point to memory provided
216 // by the client.
138 std::vector<float*> channel_data_; 217 std::vector<float*> channel_data_;
139 int frames_; 218 int frames_;
140 219
141 // Protect SetChannelData() and set_frames() for use by CreateWrapper(). 220 // Protect SetChannelData() and set_frames() for use by CreateWrapper().
142 bool can_set_channel_data_; 221 bool can_set_channel_data_;
143 222
144 DISALLOW_COPY_AND_ASSIGN(AudioBus); 223 DISALLOW_COPY_AND_ASSIGN(AudioBus);
145 }; 224 };
146 225
226 // Delegates to FromInterleavedPartial()
227 template <class SourceSampleTypeTraits>
228 void AudioBus::FromInterleaved(
229 const typename SourceSampleTypeTraits::ValueType* source_buffer,
230 int num_frames_to_write) {
231 FromInterleavedPartial<SourceSampleTypeTraits>(source_buffer, 0,
232 num_frames_to_write);
233 // Zero any remaining frames.
234 ZeroFramesPartial(num_frames_to_write, frames_ - num_frames_to_write);
235 }
236
237 template <class SourceSampleTypeTraits>
238 void AudioBus::FromInterleavedPartial(
239 const typename SourceSampleTypeTraits::ValueType* source_buffer,
240 int write_offset_in_frames,
241 int num_frames_to_write) {
242 CheckOverflow(write_offset_in_frames, num_frames_to_write, frames_);
243 CopyConvertFromInterleavedSourceToAudioBus<SourceSampleTypeTraits>(
244 source_buffer, write_offset_in_frames, num_frames_to_write, this);
245 }
246
247 // Delegates to ToInterleavedPartial()
248 template <class TargetSampleTypeTraits>
249 void AudioBus::ToInterleaved(
250 int num_frames_to_read,
251 typename TargetSampleTypeTraits::ValueType* dest_buffer) const {
252 ToInterleavedPartial<TargetSampleTypeTraits>(0, num_frames_to_read,
253 dest_buffer);
254 }
255
256 template <class TargetSampleTypeTraits>
257 void AudioBus::ToInterleavedPartial(
258 int read_offset_in_frames,
259 int num_frames_to_read,
260 typename TargetSampleTypeTraits::ValueType* dest) const {
261 CheckOverflow(read_offset_in_frames, num_frames_to_read, frames_);
262 CopyConvertFromAudioBusToInterleavedTarget<TargetSampleTypeTraits>(
263 this, read_offset_in_frames, num_frames_to_read, dest);
264 }
265
266 // TODO(chfremer): Consider using vector instructions to speed this up,
267 // https://crbug.com/619628
268 template <class SourceSampleTypeTraits>
269 void AudioBus::CopyConvertFromInterleavedSourceToAudioBus(
270 const typename SourceSampleTypeTraits::ValueType* source_buffer,
271 int write_offset_in_frames,
272 int num_frames_to_write,
273 AudioBus* dest) {
274 const int channels = dest->channels();
275 for (int ch = 0; ch < channels; ++ch) {
276 float* channel_data = dest->channel(ch);
277 for (int target_frame_index = write_offset_in_frames,
278 read_pos_in_source = ch;
279 target_frame_index < write_offset_in_frames + num_frames_to_write;
280 ++target_frame_index, read_pos_in_source += channels) {
281 auto source_value = source_buffer[read_pos_in_source];
282 channel_data[target_frame_index] =
283 SourceSampleTypeTraits::ToFloat(source_value);
284 }
285 }
286 }
287
288 // TODO(chfremer): Consider using vector instructions to speed this up,
289 // https://crbug.com/619628
290 template <class TargetSampleTypeTraits>
291 void AudioBus::CopyConvertFromAudioBusToInterleavedTarget(
292 const AudioBus* source,
293 int read_offset_in_frames,
294 int num_frames_to_read,
295 typename TargetSampleTypeTraits::ValueType* dest_buffer) {
296 const int channels = source->channels();
297 for (int ch = 0; ch < channels; ++ch) {
298 const float* channel_data = source->channel(ch);
299 for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch;
300 source_frame_index < read_offset_in_frames + num_frames_to_read;
301 ++source_frame_index, write_pos_in_dest += channels) {
302 float sourceSampleValue = channel_data[source_frame_index];
303 dest_buffer[write_pos_in_dest] =
304 TargetSampleTypeTraits::FromFloat(sourceSampleValue);
305 }
306 }
307 }
308
147 // RefCounted version of AudioBus. This is not meant for general use. Only use 309 // RefCounted version of AudioBus. This is not meant for general use. Only use
148 // this when your lifetime requirements make it impossible to use an 310 // this when your lifetime requirements make it impossible to use an
149 // AudioBus scoped_ptr. 311 // AudioBus scoped_ptr.
150 class MEDIA_EXPORT AudioBusRefCounted 312 class MEDIA_EXPORT AudioBusRefCounted
151 : public media::AudioBus, 313 : public media::AudioBus,
152 public base::RefCountedThreadSafe<AudioBusRefCounted> { 314 public base::RefCountedThreadSafe<AudioBusRefCounted> {
153 public: 315 public:
154 static scoped_refptr<AudioBusRefCounted> Create(int channels, int frames); 316 static scoped_refptr<AudioBusRefCounted> Create(int channels, int frames);
155 317
156 private: 318 private:
157 friend class base::RefCountedThreadSafe<AudioBusRefCounted>; 319 friend class base::RefCountedThreadSafe<AudioBusRefCounted>;
158 320
159 AudioBusRefCounted(int channels, int frames); 321 AudioBusRefCounted(int channels, int frames);
160 ~AudioBusRefCounted() override; 322 ~AudioBusRefCounted() override;
161 323
162 DISALLOW_COPY_AND_ASSIGN(AudioBusRefCounted); 324 DISALLOW_COPY_AND_ASSIGN(AudioBusRefCounted);
163 }; 325 };
164 326
165 } // namespace media 327 } // namespace media
166 328
167 #endif // MEDIA_BASE_AUDIO_BUS_H_ 329 #endif // MEDIA_BASE_AUDIO_BUS_H_
OLDNEW
« 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