OLD | NEW |
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 #include "media/base/audio_bus.h" | 5 #include "media/base/audio_bus.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/audio/audio_parameters.h" | 10 #include "media/audio/audio_parameters.h" |
11 #include "media/base/limits.h" | 11 #include "media/base/limits.h" |
12 #include "media/base/vector_math.h" | 12 #include "media/base/vector_math.h" |
13 | 13 |
14 namespace media { | 14 namespace media { |
15 | 15 |
| 16 static const uint8 kUint8Bias = 128; |
| 17 static const int16 kUint8Min = -kUint8Bias; |
| 18 static const int16 kUint8Max = kUint8Bias - 1; |
| 19 |
16 static bool IsAligned(void* ptr) { | 20 static bool IsAligned(void* ptr) { |
17 return (reinterpret_cast<uintptr_t>(ptr) & | 21 return (reinterpret_cast<uintptr_t>(ptr) & |
18 (AudioBus::kChannelAlignment - 1)) == 0U; | 22 (AudioBus::kChannelAlignment - 1)) == 0U; |
19 } | 23 } |
20 | 24 |
21 // Calculates the required size for an AudioBus with the given params, sets | 25 // Calculates the required size for an AudioBus with the given params, sets |
22 // |aligned_frames| to the actual frame length of each channel array. | 26 // |aligned_frames| to the actual frame length of each channel array. |
23 static int CalculateMemorySizeInternal(int channels, int frames, | 27 static int CalculateMemorySizeInternal(int channels, int frames, |
24 int* out_aligned_frames) { | 28 int* out_aligned_frames) { |
25 // Choose a size such that each channel will be aligned by | 29 // Choose a size such that each channel will be aligned by |
26 // kChannelAlignment when stored in a contiguous block. | 30 // kChannelAlignment when stored in a contiguous block. |
27 int aligned_frames = | 31 int aligned_frames = |
28 ((frames * sizeof(float) + AudioBus::kChannelAlignment - 1) & | 32 ((frames * sizeof(float) + AudioBus::kChannelAlignment - 1) & |
29 ~(AudioBus::kChannelAlignment - 1)) / sizeof(float); | 33 ~(AudioBus::kChannelAlignment - 1)) / sizeof(float); |
30 | 34 |
31 if (out_aligned_frames) | 35 if (out_aligned_frames) |
32 *out_aligned_frames = aligned_frames; | 36 *out_aligned_frames = aligned_frames; |
33 | 37 |
34 return sizeof(float) * channels * aligned_frames; | 38 return sizeof(float) * channels * aligned_frames; |
35 } | 39 } |
36 | 40 |
37 // |Format| is the destination type, |Fixed| is a type larger than |Format| | 41 // |Format| is the destination type, |Fixed| is a type larger than |Format| |
38 // such that operations can be made without overflowing. | 42 // such that operations can be made without overflowing. |
39 template<class Format, class Fixed> | 43 template<class Format, class Fixed> |
40 static void FromInterleavedInternal(const void* src, int start_frame, | 44 static void FromInterleavedInternal(const void* src, int start_frame, |
41 int frames, AudioBus* dest) { | 45 int frames, AudioBus* dest, |
| 46 Format bias, float min, float max) { |
42 const Format* source = static_cast<const Format*>(src); | 47 const Format* source = static_cast<const Format*>(src); |
43 | 48 const int channels = dest->channels(); |
44 static const Fixed kBias = std::numeric_limits<Format>::is_signed ? 0 : | |
45 std::numeric_limits<Format>::max() / 2 + 1; | |
46 static const float kMaxScale = 1.0f / (kBias ? kBias - 1 : | |
47 std::numeric_limits<Format>::max()); | |
48 static const float kMinScale = 1.0f / (kBias ? kBias : | |
49 -static_cast<Fixed>(std::numeric_limits<Format>::min())); | |
50 | |
51 int channels = dest->channels(); | |
52 for (int ch = 0; ch < channels; ++ch) { | 49 for (int ch = 0; ch < channels; ++ch) { |
53 float* channel_data = dest->channel(ch); | 50 float* channel_data = dest->channel(ch); |
54 for (int i = start_frame, offset = ch; i < start_frame + frames; | 51 for (int i = start_frame, offset = ch; i < start_frame + frames; |
55 ++i, offset += channels) { | 52 ++i, offset += channels) { |
56 Fixed v = static_cast<Fixed>(source[offset]) - kBias; | 53 const Fixed v = static_cast<Fixed>(source[offset]) - bias; |
57 channel_data[i] = v * (v < 0 ? kMinScale : kMaxScale); | 54 channel_data[i] = v * (v < 0 ? -min : max); |
58 } | 55 } |
59 } | 56 } |
60 } | 57 } |
61 | 58 |
62 // |Format| is the destination type, |Fixed| is a type larger than |Format| | 59 // |Format| is the destination type, |Fixed| is a type larger than |Format| |
63 // such that operations can be made without overflowing. | 60 // such that operations can be made without overflowing. |
64 template<class Format, class Fixed> | 61 template<class Format, class Fixed> |
65 static void ToInterleavedInternal(const AudioBus* source, int start_frame, | 62 static void ToInterleavedInternal(const AudioBus* source, int start_frame, |
66 int frames, void* dst) { | 63 int frames, void* dst, |
| 64 Format bias, Fixed min, Fixed max) { |
67 Format* dest = static_cast<Format*>(dst); | 65 Format* dest = static_cast<Format*>(dst); |
68 | 66 const int channels = source->channels(); |
69 static const Format kBias = std::numeric_limits<Format>::is_signed ? 0 : | |
70 std::numeric_limits<Format>::max() / 2 + 1; | |
71 static const Fixed kMaxValue = kBias ? kBias - 1 : | |
72 std::numeric_limits<Format>::max(); | |
73 static const Fixed kMinValue = kBias ? -kBias : | |
74 std::numeric_limits<Format>::min(); | |
75 | |
76 int channels = source->channels(); | |
77 for (int ch = 0; ch < channels; ++ch) { | 67 for (int ch = 0; ch < channels; ++ch) { |
78 const float* channel_data = source->channel(ch); | 68 const float* channel_data = source->channel(ch); |
79 for (int i = start_frame, offset = ch; i < start_frame + frames; | 69 for (int i = start_frame, offset = ch; i < start_frame + frames; |
80 ++i, offset += channels) { | 70 ++i, offset += channels) { |
81 float v = channel_data[i]; | 71 const float v = channel_data[i]; |
82 Fixed sample = v * (v < 0 ? -kMinValue : kMaxValue); | |
83 | 72 |
84 if (sample > kMaxValue) | 73 Fixed sample; |
85 sample = kMaxValue; | 74 if (v < 0) |
86 else if (sample < kMinValue) | 75 sample = v <= -1 ? -min : static_cast<Fixed>(v * -min); |
87 sample = kMinValue; | 76 else |
| 77 sample = v >= 1 ? max : static_cast<Fixed>(v * max); |
88 | 78 |
89 dest[offset] = static_cast<Format>(sample) + kBias; | 79 dest[offset] = static_cast<Format>(sample) + bias; |
90 } | 80 } |
91 } | 81 } |
92 } | 82 } |
93 | 83 |
94 static void ValidateConfig(size_t channels, int frames) { | 84 static void ValidateConfig(size_t channels, int frames) { |
95 CHECK_GT(frames, 0); | 85 CHECK_GT(frames, 0); |
96 CHECK_LE(channels, static_cast<size_t>(limits::kMaxChannels)); | 86 CHECK_LE(channels, static_cast<size_t>(limits::kMaxChannels)); |
97 } | 87 } |
98 | 88 |
99 static void CheckOverflow(int start_frame, int frames, int total_frames) { | 89 static void CheckOverflow(int start_frame, int frames, int total_frames) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 for (int i = 0; i < channels; ++i) | 229 for (int i = 0; i < channels; ++i) |
240 channel_data_.push_back(data + i * aligned_frames); | 230 channel_data_.push_back(data + i * aligned_frames); |
241 } | 231 } |
242 | 232 |
243 // TODO(dalecurtis): See if intrinsic optimizations help any here. | 233 // TODO(dalecurtis): See if intrinsic optimizations help any here. |
244 void AudioBus::FromInterleavedPartial(const void* source, int start_frame, | 234 void AudioBus::FromInterleavedPartial(const void* source, int start_frame, |
245 int frames, int bytes_per_sample) { | 235 int frames, int bytes_per_sample) { |
246 CheckOverflow(start_frame, frames, frames_); | 236 CheckOverflow(start_frame, frames, frames_); |
247 switch (bytes_per_sample) { | 237 switch (bytes_per_sample) { |
248 case 1: | 238 case 1: |
249 FromInterleavedInternal<uint8, int16>(source, start_frame, frames, this); | 239 FromInterleavedInternal<uint8, int16>( |
| 240 source, start_frame, frames, this, |
| 241 kUint8Bias, 1.0f / kUint8Min, 1.0f / kUint8Max); |
250 break; | 242 break; |
251 case 2: | 243 case 2: |
252 FromInterleavedInternal<int16, int32>(source, start_frame, frames, this); | 244 FromInterleavedInternal<int16, int32>( |
| 245 source, start_frame, frames, this, |
| 246 0, 1.0f / kint16min, 1.0f / kint16max); |
253 break; | 247 break; |
254 case 4: | 248 case 4: |
255 FromInterleavedInternal<int32, int64>(source, start_frame, frames, this); | 249 FromInterleavedInternal<int32, int64>( |
| 250 source, start_frame, frames, this, |
| 251 0, 1.0f / kint32min, 1.0f / kint32max); |
256 break; | 252 break; |
257 default: | 253 default: |
258 NOTREACHED() << "Unsupported bytes per sample encountered."; | 254 NOTREACHED() << "Unsupported bytes per sample encountered."; |
259 ZeroFramesPartial(start_frame, frames); | 255 ZeroFramesPartial(start_frame, frames); |
260 return; | 256 return; |
261 } | 257 } |
262 | 258 |
263 // Don't clear remaining frames if this is a partial deinterleave. | 259 // Don't clear remaining frames if this is a partial deinterleave. |
264 if (!start_frame) { | 260 if (!start_frame) { |
265 // Zero any remaining frames. | 261 // Zero any remaining frames. |
(...skipping 10 matching lines...) Expand all Loading... |
276 void* dest) const { | 272 void* dest) const { |
277 ToInterleavedPartial(0, frames, bytes_per_sample, dest); | 273 ToInterleavedPartial(0, frames, bytes_per_sample, dest); |
278 } | 274 } |
279 | 275 |
280 // TODO(dalecurtis): See if intrinsic optimizations help any here. | 276 // TODO(dalecurtis): See if intrinsic optimizations help any here. |
281 void AudioBus::ToInterleavedPartial(int start_frame, int frames, | 277 void AudioBus::ToInterleavedPartial(int start_frame, int frames, |
282 int bytes_per_sample, void* dest) const { | 278 int bytes_per_sample, void* dest) const { |
283 CheckOverflow(start_frame, frames, frames_); | 279 CheckOverflow(start_frame, frames, frames_); |
284 switch (bytes_per_sample) { | 280 switch (bytes_per_sample) { |
285 case 1: | 281 case 1: |
286 ToInterleavedInternal<uint8, int16>(this, start_frame, frames, dest); | 282 ToInterleavedInternal<uint8, int16>( |
| 283 this, start_frame, frames, dest, |
| 284 kUint8Bias, kUint8Min, kUint8Max); |
287 break; | 285 break; |
288 case 2: | 286 case 2: |
289 ToInterleavedInternal<int16, int32>(this, start_frame, frames, dest); | 287 ToInterleavedInternal<int16, int32>( |
| 288 this, start_frame, frames, dest, 0, kint16min, kint16max); |
290 break; | 289 break; |
291 case 4: | 290 case 4: |
292 ToInterleavedInternal<int32, int64>(this, start_frame, frames, dest); | 291 ToInterleavedInternal<int32, int64>( |
| 292 this, start_frame, frames, dest, 0, kint32min, kint32max); |
293 break; | 293 break; |
294 default: | 294 default: |
295 NOTREACHED() << "Unsupported bytes per sample encountered."; | 295 NOTREACHED() << "Unsupported bytes per sample encountered."; |
296 memset(dest, 0, frames * bytes_per_sample); | 296 memset(dest, 0, frames * bytes_per_sample); |
297 return; | 297 return; |
298 } | 298 } |
299 } | 299 } |
300 | 300 |
301 void AudioBus::CopyTo(AudioBus* dest) const { | 301 void AudioBus::CopyTo(AudioBus* dest) const { |
302 CHECK_EQ(channels(), dest->channels()); | 302 CHECK_EQ(channels(), dest->channels()); |
303 CHECK_EQ(frames(), dest->frames()); | 303 CHECK_EQ(frames(), dest->frames()); |
304 | 304 |
305 // Since we don't know if the other AudioBus is wrapped or not (and we don't | 305 // Since we don't know if the other AudioBus is wrapped or not (and we don't |
306 // want to care), just copy using the public channel() accessors. | 306 // want to care), just copy using the public channel() accessors. |
307 for (int i = 0; i < channels(); ++i) | 307 for (int i = 0; i < channels(); ++i) |
308 memcpy(dest->channel(i), channel(i), sizeof(*channel(i)) * frames()); | 308 memcpy(dest->channel(i), channel(i), sizeof(*channel(i)) * frames()); |
309 } | 309 } |
310 | 310 |
311 void AudioBus::Scale(float volume) { | 311 void AudioBus::Scale(float volume) { |
312 if (volume > 0 && volume != 1) { | 312 if (volume > 0 && volume != 1) { |
313 for (int i = 0; i < channels(); ++i) | 313 for (int i = 0; i < channels(); ++i) |
314 vector_math::FMUL(channel(i), volume, frames(), channel(i)); | 314 vector_math::FMUL(channel(i), volume, frames(), channel(i)); |
315 } else if (volume == 0) { | 315 } else if (volume == 0) { |
316 Zero(); | 316 Zero(); |
317 } | 317 } |
318 } | 318 } |
319 | 319 |
320 } // namespace media | 320 } // namespace media |
OLD | NEW |