blob: 4b972b90a1abda47c363b0cd46c7c8362ca60ee2 [file] [log] [blame]
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +01001// 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.
4
5#include "media/base/audio_buffer.h"
6
7#include "base/logging.h"
8#include "media/base/audio_bus.h"
9#include "media/base/buffers.h"
10#include "media/base/limits.h"
11
12namespace media {
13
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010014AudioBuffer::AudioBuffer(SampleFormat sample_format,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000015 ChannelLayout channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +010016 int channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000017 int sample_rate,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010018 int frame_count,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010019 bool create_buffer,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010020 const uint8* const* data,
21 const base::TimeDelta timestamp,
22 const base::TimeDelta duration)
23 : sample_format_(sample_format),
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000024 channel_layout_(channel_layout),
Ben Murdocheffb81e2014-03-31 11:51:25 +010025 channel_count_(channel_count),
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000026 sample_rate_(sample_rate),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010027 adjusted_frame_count_(frame_count),
28 trim_start_(0),
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010029 end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010030 timestamp_(timestamp),
31 duration_(duration) {
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000032 CHECK_GE(channel_count_, 0);
33 CHECK_LE(channel_count_, limits::kMaxChannels);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010034 CHECK_GE(frame_count, 0);
Ben Murdocheffb81e2014-03-31 11:51:25 +010035 DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
36 ChannelLayoutToChannelCount(channel_layout) == channel_count);
37
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010038 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
39 DCHECK_LE(bytes_per_channel, kChannelAlignment);
40 int data_size = frame_count * bytes_per_channel;
41
42 // Empty buffer?
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010043 if (!create_buffer)
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010044 return;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010045
46 if (sample_format == kSampleFormatPlanarF32 ||
47 sample_format == kSampleFormatPlanarS16) {
48 // Planar data, so need to allocate buffer for each channel.
49 // Determine per channel data size, taking into account alignment.
50 int block_size_per_channel =
51 (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1);
52 DCHECK_GE(block_size_per_channel, data_size);
53
54 // Allocate a contiguous buffer for all the channel data.
55 data_.reset(static_cast<uint8*>(base::AlignedAlloc(
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000056 channel_count_ * block_size_per_channel, kChannelAlignment)));
57 channel_data_.reserve(channel_count_);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010058
59 // Copy each channel's data into the appropriate spot.
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000060 for (int i = 0; i < channel_count_; ++i) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010061 channel_data_.push_back(data_.get() + i * block_size_per_channel);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010062 if (data)
63 memcpy(channel_data_[i], data[i], data_size);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010064 }
65 return;
66 }
67
68 // Remaining formats are interleaved data.
69 DCHECK(sample_format_ == kSampleFormatU8 ||
70 sample_format_ == kSampleFormatS16 ||
71 sample_format_ == kSampleFormatS32 ||
72 sample_format_ == kSampleFormatF32) << sample_format_;
73 // Allocate our own buffer and copy the supplied data into it. Buffer must
74 // contain the data for all channels.
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000075 data_size *= channel_count_;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010076 data_.reset(
77 static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment)));
Torne (Richard Coles)3551c9c2013-08-23 16:39:15 +010078 channel_data_.reserve(1);
79 channel_data_.push_back(data_.get());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010080 if (data)
81 memcpy(data_.get(), data[0], data_size);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010082}
83
84AudioBuffer::~AudioBuffer() {}
85
86// static
87scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
88 SampleFormat sample_format,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000089 ChannelLayout channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +010090 int channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000091 int sample_rate,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010092 int frame_count,
93 const uint8* const* data,
94 const base::TimeDelta timestamp,
95 const base::TimeDelta duration) {
96 // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010097 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010098 CHECK(data[0]);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010099 return make_scoped_refptr(new AudioBuffer(sample_format,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000100 channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100101 channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000102 sample_rate,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100103 frame_count,
104 true,
105 data,
106 timestamp,
107 duration));
108}
109
110// static
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000111scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
112 SampleFormat sample_format,
113 ChannelLayout channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100114 int channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000115 int sample_rate,
116 int frame_count) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100117 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
118 return make_scoped_refptr(new AudioBuffer(sample_format,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000119 channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100120 channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000121 sample_rate,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100122 frame_count,
123 true,
124 NULL,
125 kNoTimestamp(),
126 kNoTimestamp()));
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100127}
128
129// static
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100130scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000131 ChannelLayout channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100132 int channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000133 int sample_rate,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100134 int frame_count,
135 const base::TimeDelta timestamp,
136 const base::TimeDelta duration) {
137 CHECK_GT(frame_count, 0); // Otherwise looks like an EOF buffer.
138 // Since data == NULL, format doesn't matter.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100139 return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000140 channel_layout,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100141 channel_count,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000142 sample_rate,
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100143 frame_count,
144 false,
145 NULL,
146 timestamp,
147 duration));
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100148}
149
150// static
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100151scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000152 return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
153 CHANNEL_LAYOUT_NONE,
154 0,
155 0,
Ben Murdocheffb81e2014-03-31 11:51:25 +0100156 0,
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000157 false,
158 NULL,
159 kNoTimestamp(),
160 kNoTimestamp()));
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100161}
162
163// Convert int16 values in the range [kint16min, kint16max] to [-1.0, 1.0].
164static inline float ConvertS16ToFloat(int16 value) {
165 return value * (value < 0 ? -1.0f / kint16min : 1.0f / kint16max);
166}
167
168void AudioBuffer::ReadFrames(int frames_to_copy,
169 int source_frame_offset,
170 int dest_frame_offset,
171 AudioBus* dest) {
172 // Deinterleave each channel (if necessary) and convert to 32bit
173 // floating-point with nominal range -1.0 -> +1.0 (if necessary).
174
175 // |dest| must have the same number of channels, and the number of frames
176 // specified must be in range.
177 DCHECK(!end_of_stream());
178 DCHECK_EQ(dest->channels(), channel_count_);
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100179 DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100180 DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());
181
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100182 // Move the start past any frames that have been trimmed.
183 source_frame_offset += trim_start_;
184
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100185 if (!data_) {
186 // Special case for an empty buffer.
187 dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
188 return;
189 }
190
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100191 if (sample_format_ == kSampleFormatPlanarF32) {
192 // Format is planar float32. Copy the data from each channel as a block.
193 for (int ch = 0; ch < channel_count_; ++ch) {
194 const float* source_data =
195 reinterpret_cast<const float*>(channel_data_[ch]) +
196 source_frame_offset;
197 memcpy(dest->channel(ch) + dest_frame_offset,
198 source_data,
199 sizeof(float) * frames_to_copy);
200 }
201 return;
202 }
203
204 if (sample_format_ == kSampleFormatPlanarS16) {
205 // Format is planar signed16. Convert each value into float and insert into
206 // output channel data.
207 for (int ch = 0; ch < channel_count_; ++ch) {
208 const int16* source_data =
209 reinterpret_cast<const int16*>(channel_data_[ch]) +
210 source_frame_offset;
211 float* dest_data = dest->channel(ch) + dest_frame_offset;
212 for (int i = 0; i < frames_to_copy; ++i) {
213 dest_data[i] = ConvertS16ToFloat(source_data[i]);
214 }
215 }
216 return;
217 }
218
219 if (sample_format_ == kSampleFormatF32) {
220 // Format is interleaved float32. Copy the data into each channel.
221 const float* source_data = reinterpret_cast<const float*>(data_.get()) +
222 source_frame_offset * channel_count_;
223 for (int ch = 0; ch < channel_count_; ++ch) {
224 float* dest_data = dest->channel(ch) + dest_frame_offset;
225 for (int i = 0, offset = ch; i < frames_to_copy;
226 ++i, offset += channel_count_) {
227 dest_data[i] = source_data[offset];
228 }
229 }
230 return;
231 }
232
233 // Remaining formats are integer interleaved data. Use the deinterleaving code
234 // in AudioBus to copy the data.
235 DCHECK(sample_format_ == kSampleFormatU8 ||
236 sample_format_ == kSampleFormatS16 ||
237 sample_format_ == kSampleFormatS32);
238 int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
239 int frame_size = channel_count_ * bytes_per_channel;
240 const uint8* source_data = data_.get() + source_frame_offset * frame_size;
241 dest->FromInterleavedPartial(
242 source_data, dest_frame_offset, frames_to_copy, bytes_per_channel);
243}
244
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100245void AudioBuffer::TrimStart(int frames_to_trim) {
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100246 CHECK_GE(frames_to_trim, 0);
247 CHECK_LE(frames_to_trim, adjusted_frame_count_);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100248
249 // Adjust timestamp_ and duration_ to reflect the smaller number of frames.
250 double offset = static_cast<double>(duration_.InMicroseconds()) *
251 frames_to_trim / adjusted_frame_count_;
252 base::TimeDelta offset_as_time =
253 base::TimeDelta::FromMicroseconds(static_cast<int64>(offset));
254 timestamp_ += offset_as_time;
255 duration_ -= offset_as_time;
256
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100257 // Finally adjust the number of frames in this buffer and where the start
258 // really is.
259 adjusted_frame_count_ -= frames_to_trim;
260 trim_start_ += frames_to_trim;
261}
262
263void AudioBuffer::TrimEnd(int frames_to_trim) {
264 CHECK_GE(frames_to_trim, 0);
265 CHECK_LE(frames_to_trim, adjusted_frame_count_);
266
267 // Adjust duration_ only to reflect the smaller number of frames.
268 double offset = static_cast<double>(duration_.InMicroseconds()) *
269 frames_to_trim / adjusted_frame_count_;
270 base::TimeDelta offset_as_time =
271 base::TimeDelta::FromMicroseconds(static_cast<int64>(offset));
272 duration_ -= offset_as_time;
273
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100274 // Finally adjust the number of frames in this buffer.
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100275 adjusted_frame_count_ -= frames_to_trim;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100276}
277
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100278} // namespace media