audio_buffer.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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.
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
14AudioBuffer::AudioBuffer(SampleFormat sample_format,
15                         ChannelLayout channel_layout,
16                         int channel_count,
17                         int sample_rate,
18                         int frame_count,
19                         bool create_buffer,
20                         const uint8* const* data,
21                         const base::TimeDelta timestamp,
22                         const base::TimeDelta duration)
23    : sample_format_(sample_format),
24      channel_layout_(channel_layout),
25      channel_count_(channel_count),
26      sample_rate_(sample_rate),
27      adjusted_frame_count_(frame_count),
28      trim_start_(0),
29      end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
30      timestamp_(timestamp),
31      duration_(duration) {
32  CHECK_GE(channel_count_, 0);
33  CHECK_LE(channel_count_, limits::kMaxChannels);
34  CHECK_GE(frame_count, 0);
35  DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
36         ChannelLayoutToChannelCount(channel_layout) == channel_count);
37
38  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?
43  if (!create_buffer)
44    return;
45
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(
56        channel_count_ * block_size_per_channel, kChannelAlignment)));
57    channel_data_.reserve(channel_count_);
58
59    // Copy each channel's data into the appropriate spot.
60    for (int i = 0; i < channel_count_; ++i) {
61      channel_data_.push_back(data_.get() + i * block_size_per_channel);
62      if (data)
63        memcpy(channel_data_[i], data[i], data_size);
64    }
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.
75  data_size *= channel_count_;
76  data_.reset(
77      static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment)));
78  channel_data_.reserve(1);
79  channel_data_.push_back(data_.get());
80  if (data)
81    memcpy(data_.get(), data[0], data_size);
82}
83
84AudioBuffer::~AudioBuffer() {}
85
86// static
87scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
88    SampleFormat sample_format,
89    ChannelLayout channel_layout,
90    int channel_count,
91    int sample_rate,
92    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.
97  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
98  CHECK(data[0]);
99  return make_scoped_refptr(new AudioBuffer(sample_format,
100                                            channel_layout,
101                                            channel_count,
102                                            sample_rate,
103                                            frame_count,
104                                            true,
105                                            data,
106                                            timestamp,
107                                            duration));
108}
109
110// static
111scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
112    SampleFormat sample_format,
113    ChannelLayout channel_layout,
114    int channel_count,
115    int sample_rate,
116    int frame_count) {
117  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
118  return make_scoped_refptr(new AudioBuffer(sample_format,
119                                            channel_layout,
120                                            channel_count,
121                                            sample_rate,
122                                            frame_count,
123                                            true,
124                                            NULL,
125                                            kNoTimestamp(),
126                                            kNoTimestamp()));
127}
128
129// static
130scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
131    ChannelLayout channel_layout,
132    int channel_count,
133    int sample_rate,
134    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.
139  return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
140                                            channel_layout,
141                                            channel_count,
142                                            sample_rate,
143                                            frame_count,
144                                            false,
145                                            NULL,
146                                            timestamp,
147                                            duration));
148}
149
150// static
151scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
152  return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
153                                            CHANNEL_LAYOUT_NONE,
154                                            0,
155                                            0,
156                                            0,
157                                            false,
158                                            NULL,
159                                            kNoTimestamp(),
160                                            kNoTimestamp()));
161}
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_);
179  DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
180  DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());
181
182  // Move the start past any frames that have been trimmed.
183  source_frame_offset += trim_start_;
184
185  if (!data_) {
186    // Special case for an empty buffer.
187    dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
188    return;
189  }
190
191  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
245void AudioBuffer::TrimStart(int frames_to_trim) {
246  CHECK_GE(frames_to_trim, 0);
247  CHECK_LE(frames_to_trim, adjusted_frame_count_);
248
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
257  // 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
274  // Finally adjust the number of frames in this buffer.
275  adjusted_frame_count_ -= frames_to_trim;
276}
277
278}  // namespace media
279