1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/base/audio_buffer.h"
9 #include "base/logging.h"
10 #include "media/base/audio_bus.h"
11 #include "media/base/limits.h"
12 #include "media/base/timestamp_constants.h"
16 static base::TimeDelta
CalculateDuration(int frames
, double sample_rate
) {
17 DCHECK_GT(sample_rate
, 0);
18 return base::TimeDelta::FromMicroseconds(
19 frames
* base::Time::kMicrosecondsPerSecond
/ sample_rate
);
22 AudioBuffer::AudioBuffer(SampleFormat sample_format
,
23 ChannelLayout channel_layout
,
28 const uint8
* const* data
,
29 const base::TimeDelta timestamp
)
30 : sample_format_(sample_format
),
31 channel_layout_(channel_layout
),
32 channel_count_(channel_count
),
33 sample_rate_(sample_rate
),
34 adjusted_frame_count_(frame_count
),
36 end_of_stream_(!create_buffer
&& data
== NULL
&& frame_count
== 0),
37 timestamp_(timestamp
),
38 duration_(end_of_stream_
40 : CalculateDuration(adjusted_frame_count_
, sample_rate_
)) {
41 CHECK_GE(channel_count_
, 0);
42 CHECK_LE(channel_count_
, limits::kMaxChannels
);
43 CHECK_GE(frame_count
, 0);
44 DCHECK(channel_layout
== CHANNEL_LAYOUT_DISCRETE
||
45 ChannelLayoutToChannelCount(channel_layout
) == channel_count
);
47 int bytes_per_channel
= SampleFormatToBytesPerChannel(sample_format
);
48 DCHECK_LE(bytes_per_channel
, kChannelAlignment
);
49 int data_size
= frame_count
* bytes_per_channel
;
55 if (sample_format
== kSampleFormatPlanarF32
||
56 sample_format
== kSampleFormatPlanarS16
||
57 sample_format
== kSampleFormatPlanarS32
) {
58 // Planar data, so need to allocate buffer for each channel.
59 // Determine per channel data size, taking into account alignment.
60 int block_size_per_channel
=
61 (data_size
+ kChannelAlignment
- 1) & ~(kChannelAlignment
- 1);
62 DCHECK_GE(block_size_per_channel
, data_size
);
64 // Allocate a contiguous buffer for all the channel data.
65 data_
.reset(static_cast<uint8
*>(base::AlignedAlloc(
66 channel_count_
* block_size_per_channel
, kChannelAlignment
)));
67 channel_data_
.reserve(channel_count_
);
69 // Copy each channel's data into the appropriate spot.
70 for (int i
= 0; i
< channel_count_
; ++i
) {
71 channel_data_
.push_back(data_
.get() + i
* block_size_per_channel
);
73 memcpy(channel_data_
[i
], data
[i
], data_size
);
78 // Remaining formats are interleaved data.
79 DCHECK(sample_format_
== kSampleFormatU8
||
80 sample_format_
== kSampleFormatS16
||
81 sample_format_
== kSampleFormatS32
||
82 sample_format_
== kSampleFormatF32
) << sample_format_
;
83 // Allocate our own buffer and copy the supplied data into it. Buffer must
84 // contain the data for all channels.
85 data_size
*= channel_count_
;
87 static_cast<uint8
*>(base::AlignedAlloc(data_size
, kChannelAlignment
)));
88 channel_data_
.reserve(1);
89 channel_data_
.push_back(data_
.get());
91 memcpy(data_
.get(), data
[0], data_size
);
94 AudioBuffer::~AudioBuffer() {}
97 scoped_refptr
<AudioBuffer
> AudioBuffer::CopyFrom(
98 SampleFormat sample_format
,
99 ChannelLayout channel_layout
,
103 const uint8
* const* data
,
104 const base::TimeDelta timestamp
) {
105 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
106 CHECK_GT(frame_count
, 0); // Otherwise looks like an EOF buffer.
108 return make_scoped_refptr(new AudioBuffer(sample_format
,
119 scoped_refptr
<AudioBuffer
> AudioBuffer::CreateBuffer(
120 SampleFormat sample_format
,
121 ChannelLayout channel_layout
,
125 CHECK_GT(frame_count
, 0); // Otherwise looks like an EOF buffer.
126 return make_scoped_refptr(new AudioBuffer(sample_format
,
137 scoped_refptr
<AudioBuffer
> AudioBuffer::CreateEmptyBuffer(
138 ChannelLayout channel_layout
,
142 const base::TimeDelta timestamp
) {
143 CHECK_GT(frame_count
, 0); // Otherwise looks like an EOF buffer.
144 // Since data == NULL, format doesn't matter.
145 return make_scoped_refptr(new AudioBuffer(kSampleFormatF32
,
156 scoped_refptr
<AudioBuffer
> AudioBuffer::CreateEOSBuffer() {
157 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat
,
167 template <typename Target
, typename Dest
>
168 static inline Dest
ConvertSample(Target value
);
170 // Convert int16 values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0].
172 inline float ConvertSample
<int16
, float>(int16 value
) {
173 return value
* (value
< 0 ? -1.0f
/ std::numeric_limits
<int16
>::min()
174 : 1.0f
/ std::numeric_limits
<int16
>::max());
177 // Specializations for int32
179 inline int32 ConvertSample
<int16
, int32
>(int16 value
) {
180 return static_cast<int32
>(value
) << 16;
184 inline int32 ConvertSample
<int32
, int32
>(int32 value
) {
189 inline int32 ConvertSample
<float, int32
>(float value
) {
190 return static_cast<int32
>(value
< 0
191 ? (-value
) * std::numeric_limits
<int32
>::min()
192 : value
* std::numeric_limits
<int32
>::max());
195 // Specializations for int16
197 inline int16 ConvertSample
<int16
, int16
>(int16 sample
) {
202 inline int16 ConvertSample
<int32
, int16
>(int32 sample
) {
207 inline int16 ConvertSample
<float, int16
>(float sample
) {
208 return static_cast<int16
>(
209 nearbyint(sample
< 0 ? (-sample
) * std::numeric_limits
<int16
>::min()
210 : sample
* std::numeric_limits
<int16
>::max()));
213 void AudioBuffer::ReadFrames(int frames_to_copy
,
214 int source_frame_offset
,
215 int dest_frame_offset
,
217 // Deinterleave each channel (if necessary) and convert to 32bit
218 // floating-point with nominal range -1.0 -> +1.0 (if necessary).
220 // |dest| must have the same number of channels, and the number of frames
221 // specified must be in range.
222 DCHECK(!end_of_stream());
223 DCHECK_EQ(dest
->channels(), channel_count_
);
224 DCHECK_LE(source_frame_offset
+ frames_to_copy
, adjusted_frame_count_
);
225 DCHECK_LE(dest_frame_offset
+ frames_to_copy
, dest
->frames());
227 // Move the start past any frames that have been trimmed.
228 source_frame_offset
+= trim_start_
;
231 // Special case for an empty buffer.
232 dest
->ZeroFramesPartial(dest_frame_offset
, frames_to_copy
);
236 if (sample_format_
== kSampleFormatPlanarF32
) {
237 // Format is planar float32. Copy the data from each channel as a block.
238 for (int ch
= 0; ch
< channel_count_
; ++ch
) {
239 const float* source_data
=
240 reinterpret_cast<const float*>(channel_data_
[ch
]) +
242 memcpy(dest
->channel(ch
) + dest_frame_offset
,
244 sizeof(float) * frames_to_copy
);
249 if (sample_format_
== kSampleFormatPlanarS16
) {
250 // Format is planar signed16. Convert each value into float and insert into
251 // output channel data.
252 for (int ch
= 0; ch
< channel_count_
; ++ch
) {
253 const int16
* source_data
=
254 reinterpret_cast<const int16
*>(channel_data_
[ch
]) +
256 float* dest_data
= dest
->channel(ch
) + dest_frame_offset
;
257 for (int i
= 0; i
< frames_to_copy
; ++i
) {
258 dest_data
[i
] = ConvertSample
<int16
, float>(source_data
[i
]);
264 if (sample_format_
== kSampleFormatF32
) {
265 // Format is interleaved float32. Copy the data into each channel.
266 const float* source_data
= reinterpret_cast<const float*>(data_
.get()) +
267 source_frame_offset
* channel_count_
;
268 for (int ch
= 0; ch
< channel_count_
; ++ch
) {
269 float* dest_data
= dest
->channel(ch
) + dest_frame_offset
;
270 for (int i
= 0, offset
= ch
; i
< frames_to_copy
;
271 ++i
, offset
+= channel_count_
) {
272 dest_data
[i
] = source_data
[offset
];
278 // Remaining formats are integer interleaved data. Use the deinterleaving code
279 // in AudioBus to copy the data.
280 DCHECK(sample_format_
== kSampleFormatU8
||
281 sample_format_
== kSampleFormatS16
||
282 sample_format_
== kSampleFormatS32
);
283 int bytes_per_channel
= SampleFormatToBytesPerChannel(sample_format_
);
284 int frame_size
= channel_count_
* bytes_per_channel
;
285 const uint8
* source_data
= data_
.get() + source_frame_offset
* frame_size
;
286 dest
->FromInterleavedPartial(
287 source_data
, dest_frame_offset
, frames_to_copy
, bytes_per_channel
);
290 template <class Target
, typename Dest
>
291 void InterleaveAndConvert(const std::vector
<uint8
*>& channel_data
,
292 size_t frames_to_copy
,
295 for (size_t ch
= 0; ch
< channel_data
.size(); ++ch
) {
296 const Target
* source_data
=
297 reinterpret_cast<const Target
*>(channel_data
[ch
]) + trim_start
;
298 for (size_t i
= 0, offset
= ch
; i
< frames_to_copy
;
299 ++i
, offset
+= channel_data
.size()) {
300 dest_data
[offset
] = ConvertSample
<Target
, Dest
>(source_data
[i
]);
305 template <typename Dest
>
306 void ReadFramesInterleaved(const std::vector
<uint8
*>& channel_data
,
308 SampleFormat sample_format
,
312 switch (sample_format
) {
313 case kSampleFormatU8
:
316 case kSampleFormatS16
:
317 InterleaveAndConvert
<int16
, Dest
>(
318 channel_data
, frames_to_copy
* channel_count
, trim_start
, dest_data
);
320 case kSampleFormatS32
:
321 InterleaveAndConvert
<int32
, Dest
>(
322 channel_data
, frames_to_copy
* channel_count
, trim_start
, dest_data
);
324 case kSampleFormatF32
:
325 InterleaveAndConvert
<float, Dest
>(
326 channel_data
, frames_to_copy
* channel_count
, trim_start
, dest_data
);
328 case kSampleFormatPlanarS16
:
329 InterleaveAndConvert
<int16
, Dest
>(channel_data
, frames_to_copy
,
330 trim_start
, dest_data
);
332 case kSampleFormatPlanarF32
:
333 InterleaveAndConvert
<float, Dest
>(channel_data
, frames_to_copy
,
334 trim_start
, dest_data
);
336 case kSampleFormatPlanarS32
:
337 InterleaveAndConvert
<int32
, Dest
>(channel_data
, frames_to_copy
,
338 trim_start
, dest_data
);
340 case kUnknownSampleFormat
:
346 void AudioBuffer::ReadFramesInterleavedS32(int frames_to_copy
,
348 DCHECK_LE(frames_to_copy
, adjusted_frame_count_
);
349 ReadFramesInterleaved
<int32
>(channel_data_
, channel_count_
, sample_format_
,
350 frames_to_copy
, trim_start_
, dest_data
);
353 void AudioBuffer::ReadFramesInterleavedS16(int frames_to_copy
,
355 DCHECK_LE(frames_to_copy
, adjusted_frame_count_
);
356 ReadFramesInterleaved
<int16
>(channel_data_
, channel_count_
, sample_format_
,
357 frames_to_copy
, trim_start_
, dest_data
);
360 void AudioBuffer::TrimStart(int frames_to_trim
) {
361 CHECK_GE(frames_to_trim
, 0);
362 CHECK_LE(frames_to_trim
, adjusted_frame_count_
);
364 // Adjust the number of frames in this buffer and where the start really is.
365 adjusted_frame_count_
-= frames_to_trim
;
366 trim_start_
+= frames_to_trim
;
368 // Adjust timestamp_ and duration_ to reflect the smaller number of frames.
369 const base::TimeDelta old_duration
= duration_
;
370 duration_
= CalculateDuration(adjusted_frame_count_
, sample_rate_
);
371 timestamp_
+= old_duration
- duration_
;
374 void AudioBuffer::TrimEnd(int frames_to_trim
) {
375 CHECK_GE(frames_to_trim
, 0);
376 CHECK_LE(frames_to_trim
, adjusted_frame_count_
);
378 // Adjust the number of frames and duration for this buffer.
379 adjusted_frame_count_
-= frames_to_trim
;
380 duration_
= CalculateDuration(adjusted_frame_count_
, sample_rate_
);
383 void AudioBuffer::TrimRange(int start
, int end
) {
385 CHECK_LE(end
, adjusted_frame_count_
);
387 const int frames_to_trim
= end
- start
;
388 CHECK_GE(frames_to_trim
, 0);
389 CHECK_LE(frames_to_trim
, adjusted_frame_count_
);
391 const int bytes_per_channel
= SampleFormatToBytesPerChannel(sample_format_
);
392 const int frames_to_copy
= adjusted_frame_count_
- end
;
393 if (frames_to_copy
> 0) {
394 switch (sample_format_
) {
395 case kSampleFormatPlanarS16
:
396 case kSampleFormatPlanarF32
:
397 case kSampleFormatPlanarS32
:
398 // Planar data must be shifted per channel.
399 for (int ch
= 0; ch
< channel_count_
; ++ch
) {
400 memmove(channel_data_
[ch
] + (trim_start_
+ start
) * bytes_per_channel
,
401 channel_data_
[ch
] + (trim_start_
+ end
) * bytes_per_channel
,
402 bytes_per_channel
* frames_to_copy
);
405 case kSampleFormatU8
:
406 case kSampleFormatS16
:
407 case kSampleFormatS32
:
408 case kSampleFormatF32
: {
409 // Interleaved data can be shifted all at once.
410 const int frame_size
= channel_count_
* bytes_per_channel
;
411 memmove(channel_data_
[0] + (trim_start_
+ start
) * frame_size
,
412 channel_data_
[0] + (trim_start_
+ end
) * frame_size
,
413 frame_size
* frames_to_copy
);
416 case kUnknownSampleFormat
:
417 NOTREACHED() << "Invalid sample format!";
420 CHECK_EQ(frames_to_copy
, 0);
423 // Trim the leftover data off the end of the buffer and update duration.
424 TrimEnd(frames_to_trim
);