srpcgen: Use 'const char*' for string parameters
[chromium-blink-merge.git] / media / audio / audio_util.cc
blob9e1c8186401cefa796132db068e981927c6324f4
1 // Copyright (c) 2011 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 // Software adjust volume of samples, allows each audio stream its own
6 // volume without impacting master volume for chrome and other applications.
8 // Implemented as templates to allow 8, 16 and 32 bit implementations.
9 // 8 bit is unsigned and biased by 128.
11 #include <algorithm>
13 #include "base/atomicops.h"
14 #include "base/basictypes.h"
15 #include "base/logging.h"
16 #include "base/shared_memory.h"
17 #if defined(OS_WIN)
18 #include "base/win/windows_version.h"
19 #endif
20 #include "media/audio/audio_util.h"
21 #if defined(OS_MACOSX)
22 #include "media/audio/mac/audio_low_latency_input_mac.h"
23 #include "media/audio/mac/audio_low_latency_output_mac.h"
24 #endif
25 #if defined(OS_WIN)
26 #include "media/audio/win/audio_low_latency_input_win.h"
27 #include "media/audio/win/audio_low_latency_output_win.h"
28 #endif
30 using base::subtle::Atomic32;
32 const uint32 kUnknownDataSize = static_cast<uint32>(-1);
34 namespace media {
36 // TODO(fbarchard): Convert to intrinsics for better efficiency.
37 template<class Fixed>
38 static int ScaleChannel(int channel, int volume) {
39 return static_cast<int>((static_cast<Fixed>(channel) * volume) >> 16);
42 template<class Format, class Fixed, int bias>
43 static void AdjustVolume(Format* buf_out,
44 int sample_count,
45 int fixed_volume) {
46 for (int i = 0; i < sample_count; ++i) {
47 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias,
48 fixed_volume) + bias);
52 static const int kChannel_L = 0;
53 static const int kChannel_R = 1;
54 static const int kChannel_C = 2;
56 template<class Fixed, int min_value, int max_value>
57 static int AddChannel(int val, int adder) {
58 Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder);
59 if (sum > max_value)
60 return max_value;
61 if (sum < min_value)
62 return min_value;
63 return static_cast<int>(sum);
66 // FoldChannels() downmixes multichannel (ie 5.1 Surround Sound) to Stereo.
67 // Left and Right channels are preserved asis, and Center channel is
68 // distributed equally to both sides. To be perceptually 1/2 volume on
69 // both channels, 1/sqrt(2) is used instead of 1/2.
70 // Fixed point math is used for efficiency. 16 bits of fraction and 8,16 or 32
71 // bits of integer are used.
72 // 8 bit samples are unsigned and 128 represents 0, so a bias is removed before
73 // doing calculations, then readded for the final output.
74 template<class Format, class Fixed, int min_value, int max_value, int bias>
75 static void FoldChannels(Format* buf_out,
76 int sample_count,
77 const float volume,
78 int channels) {
79 Format* buf_in = buf_out;
80 const int center_volume = static_cast<int>(volume * 0.707f * 65536);
81 const int fixed_volume = static_cast<int>(volume * 65536);
83 for (int i = 0; i < sample_count; ++i) {
84 int center = static_cast<int>(buf_in[kChannel_C] - bias);
85 int left = static_cast<int>(buf_in[kChannel_L] - bias);
86 int right = static_cast<int>(buf_in[kChannel_R] - bias);
88 center = ScaleChannel<Fixed>(center, center_volume);
89 left = ScaleChannel<Fixed>(left, fixed_volume);
90 right = ScaleChannel<Fixed>(right, fixed_volume);
92 buf_out[0] = static_cast<Format>(
93 AddChannel<Fixed, min_value, max_value>(left, center) + bias);
94 buf_out[1] = static_cast<Format>(
95 AddChannel<Fixed, min_value, max_value>(right, center) + bias);
97 buf_out += 2;
98 buf_in += channels;
102 // AdjustVolume() does an in place audio sample change.
103 bool AdjustVolume(void* buf,
104 size_t buflen,
105 int channels,
106 int bytes_per_sample,
107 float volume) {
108 DCHECK(buf);
109 if (volume < 0.0f || volume > 1.0f)
110 return false;
111 if (volume == 1.0f) {
112 return true;
113 } else if (volume == 0.0f) {
114 memset(buf, 0, buflen);
115 return true;
117 if (channels > 0 && channels <= 8 && bytes_per_sample > 0) {
118 int sample_count = buflen / bytes_per_sample;
119 const int fixed_volume = static_cast<int>(volume * 65536);
120 if (bytes_per_sample == 1) {
121 AdjustVolume<uint8, int32, 128>(reinterpret_cast<uint8*>(buf),
122 sample_count,
123 fixed_volume);
124 return true;
125 } else if (bytes_per_sample == 2) {
126 AdjustVolume<int16, int32, 0>(reinterpret_cast<int16*>(buf),
127 sample_count,
128 fixed_volume);
129 return true;
130 } else if (bytes_per_sample == 4) {
131 AdjustVolume<int32, int64, 0>(reinterpret_cast<int32*>(buf),
132 sample_count,
133 fixed_volume);
134 return true;
137 return false;
140 bool FoldChannels(void* buf,
141 size_t buflen,
142 int channels,
143 int bytes_per_sample,
144 float volume) {
145 DCHECK(buf);
146 if (volume < 0.0f || volume > 1.0f)
147 return false;
148 if (channels > 2 && channels <= 8 && bytes_per_sample > 0) {
149 int sample_count = buflen / (channels * bytes_per_sample);
150 if (bytes_per_sample == 1) {
151 FoldChannels<uint8, int32, -128, 127, 128>(
152 reinterpret_cast<uint8*>(buf),
153 sample_count,
154 volume,
155 channels);
156 return true;
157 } else if (bytes_per_sample == 2) {
158 FoldChannels<int16, int32, -32768, 32767, 0>(
159 reinterpret_cast<int16*>(buf),
160 sample_count,
161 volume,
162 channels);
163 return true;
164 } else if (bytes_per_sample == 4) {
165 FoldChannels<int32, int64, 0x80000000, 0x7fffffff, 0>(
166 reinterpret_cast<int32*>(buf),
167 sample_count,
168 volume,
169 channels);
170 return true;
173 return false;
176 bool DeinterleaveAudioChannel(void* source,
177 float* destination,
178 int channels,
179 int channel_index,
180 int bytes_per_sample,
181 size_t number_of_frames) {
182 switch (bytes_per_sample) {
183 case 1:
185 uint8* source8 = static_cast<uint8*>(source) + channel_index;
186 const float kScale = 1.0f / 128.0f;
187 for (unsigned i = 0; i < number_of_frames; ++i) {
188 destination[i] = kScale * (static_cast<int>(*source8) - 128);
189 source8 += channels;
191 return true;
194 case 2:
196 int16* source16 = static_cast<int16*>(source) + channel_index;
197 const float kScale = 1.0f / 32768.0f;
198 for (unsigned i = 0; i < number_of_frames; ++i) {
199 destination[i] = kScale * *source16;
200 source16 += channels;
202 return true;
205 case 4:
207 int32* source32 = static_cast<int32*>(source) + channel_index;
208 const float kScale = 1.0f / (1L << 31);
209 for (unsigned i = 0; i < number_of_frames; ++i) {
210 destination[i] = kScale * *source32;
211 source32 += channels;
213 return true;
216 default:
217 break;
219 return false;
222 void InterleaveFloatToInt16(const std::vector<float*>& source,
223 int16* destination,
224 size_t number_of_frames) {
225 const float kScale = 32768.0f;
226 int channels = source.size();
227 for (int i = 0; i < channels; ++i) {
228 float* channel_data = source[i];
229 for (size_t j = 0; j < number_of_frames; ++j) {
230 float sample = kScale * channel_data[j];
231 if (sample < -32768.0)
232 sample = -32768.0;
233 else if (sample > 32767.0)
234 sample = 32767.0;
236 destination[j * channels + i] = static_cast<int16>(sample);
241 double GetAudioHardwareSampleRate() {
242 #if defined(OS_MACOSX)
243 // Hardware sample-rate on the Mac can be configured, so we must query.
244 return AUAudioOutputStream::HardwareSampleRate();
245 #elif defined(OS_WIN)
246 if (!IsWASAPISupported()) {
247 // Fall back to Windows Wave implementation on Windows XP or lower
248 // and use 48kHz as default input sample rate.
249 return 48000.0;
252 // Hardware sample-rate on Windows can be configured, so we must query.
253 // TODO(henrika): improve possibility to specify audio endpoint.
254 // Use the default device (same as for Wave) for now to be compatible.
255 return WASAPIAudioOutputStream::HardwareSampleRate(eConsole);
256 #else
257 // Hardware for Linux is nearly always 48KHz.
258 // TODO(crogers) : return correct value in rare non-48KHz cases.
259 return 48000.0;
260 #endif
263 double GetAudioInputHardwareSampleRate() {
264 #if defined(OS_MACOSX)
265 // Hardware sample-rate on the Mac can be configured, so we must query.
266 return AUAudioInputStream::HardwareSampleRate();
267 #elif defined(OS_WIN)
268 if (!IsWASAPISupported()) {
269 // Fall back to Windows Wave implementation on Windows XP or lower
270 // and use 48kHz as default input sample rate.
271 return 48000.0;
274 // Hardware sample-rate on Windows can be configured, so we must query.
275 // TODO(henrika): improve possibility to specify audio endpoint.
276 // Use the default device (same as for Wave) for now to be compatible.
277 return WASAPIAudioInputStream::HardwareSampleRate(eConsole);
278 #else
279 // Hardware for Linux is nearly always 48KHz.
280 // TODO(henrika): return correct value in rare non-48KHz cases.
281 return 48000.0;
282 #endif
285 size_t GetAudioHardwareBufferSize() {
286 // The sizes here were determined by experimentation and are roughly
287 // the lowest value (for low latency) that still allowed glitch-free
288 // audio under high loads.
290 // For Mac OS X and Windows the chromium audio backend uses a low-latency
291 // Core Audio API, so a low buffer size is possible. For Linux, further
292 // tuning may be needed.
293 #if defined(OS_MACOSX)
294 return 128;
295 #elif defined(OS_WIN)
296 if (!IsWASAPISupported()) {
297 // Fall back to Windows Wave implementation on Windows XP or lower
298 // and assume 48kHz as default sample rate.
299 return 2048;
301 // This call must be done on a COM thread configured as MTA.
302 // TODO(tommi): http://code.google.com/p/chromium/issues/detail?id=103835.
303 int mixing_sample_rate =
304 static_cast<int>(WASAPIAudioOutputStream::HardwareSampleRate(eConsole));
305 if (mixing_sample_rate == 48000)
306 return 480;
307 else if (mixing_sample_rate == 44100)
308 return 448;
309 else
310 return 960;
311 #else
312 return 2048;
313 #endif
316 // When transferring data in the shared memory, first word is size of data
317 // in bytes. Actual data starts immediately after it.
319 uint32 TotalSharedMemorySizeInBytes(uint32 packet_size) {
320 // Need to reserve extra 4 bytes for size of data.
321 return packet_size + sizeof(Atomic32);
324 uint32 PacketSizeSizeInBytes(uint32 shared_memory_created_size) {
325 return shared_memory_created_size - sizeof(Atomic32);
328 uint32 GetActualDataSizeInBytes(base::SharedMemory* shared_memory,
329 uint32 shared_memory_size) {
330 char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size;
331 DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3);
333 // Actual data size stored at the end of the buffer.
334 uint32 actual_data_size =
335 base::subtle::Acquire_Load(reinterpret_cast<volatile Atomic32*>(ptr));
336 return std::min(actual_data_size, shared_memory_size);
339 void SetActualDataSizeInBytes(base::SharedMemory* shared_memory,
340 uint32 shared_memory_size,
341 uint32 actual_data_size) {
342 char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size;
343 DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3);
345 // Set actual data size at the end of the buffer.
346 base::subtle::Release_Store(reinterpret_cast<volatile Atomic32*>(ptr),
347 actual_data_size);
350 void SetUnknownDataSize(base::SharedMemory* shared_memory,
351 uint32 shared_memory_size) {
352 SetActualDataSizeInBytes(shared_memory, shared_memory_size, kUnknownDataSize);
355 bool IsUnknownDataSize(base::SharedMemory* shared_memory,
356 uint32 shared_memory_size) {
357 char* ptr = static_cast<char*>(shared_memory->memory()) + shared_memory_size;
358 DCHECK_EQ(0u, reinterpret_cast<size_t>(ptr) & 3);
360 // Actual data size stored at the end of the buffer.
361 uint32 actual_data_size =
362 base::subtle::Acquire_Load(reinterpret_cast<volatile Atomic32*>(ptr));
363 return actual_data_size == kUnknownDataSize;
366 #if defined(OS_WIN)
368 bool IsWASAPISupported() {
369 // Note: that function correctly returns that Windows Server 2003 does not
370 // support WASAPI.
371 return base::win::GetVersion() >= base::win::VERSION_VISTA;
374 #endif
376 } // namespace media