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.
13 #include "base/atomicops.h"
14 #include "base/basictypes.h"
15 #include "base/logging.h"
16 #include "base/shared_memory.h"
18 #include "base/win/windows_version.h"
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"
26 #include "media/audio/win/audio_low_latency_input_win.h"
27 #include "media/audio/win/audio_low_latency_output_win.h"
30 using base::subtle::Atomic32
;
32 const uint32 kUnknownDataSize
= static_cast<uint32
>(-1);
36 // TODO(fbarchard): Convert to intrinsics for better efficiency.
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
,
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
);
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
,
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
);
102 // AdjustVolume() does an in place audio sample change.
103 bool AdjustVolume(void* buf
,
106 int bytes_per_sample
,
109 if (volume
< 0.0f
|| volume
> 1.0f
)
111 if (volume
== 1.0f
) {
113 } else if (volume
== 0.0f
) {
114 memset(buf
, 0, buflen
);
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
),
125 } else if (bytes_per_sample
== 2) {
126 AdjustVolume
<int16
, int32
, 0>(reinterpret_cast<int16
*>(buf
),
130 } else if (bytes_per_sample
== 4) {
131 AdjustVolume
<int32
, int64
, 0>(reinterpret_cast<int32
*>(buf
),
140 bool FoldChannels(void* buf
,
143 int bytes_per_sample
,
146 if (volume
< 0.0f
|| volume
> 1.0f
)
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
),
157 } else if (bytes_per_sample
== 2) {
158 FoldChannels
<int16
, int32
, -32768, 32767, 0>(
159 reinterpret_cast<int16
*>(buf
),
164 } else if (bytes_per_sample
== 4) {
165 FoldChannels
<int32
, int64
, 0x80000000, 0x7fffffff, 0>(
166 reinterpret_cast<int32
*>(buf
),
176 bool DeinterleaveAudioChannel(void* source
,
180 int bytes_per_sample
,
181 size_t number_of_frames
) {
182 switch (bytes_per_sample
) {
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);
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
;
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
;
222 void InterleaveFloatToInt16(const std::vector
<float*>& source
,
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)
233 else if (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.
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
);
257 // Hardware for Linux is nearly always 48KHz.
258 // TODO(crogers) : return correct value in rare non-48KHz cases.
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.
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
);
279 // Hardware for Linux is nearly always 48KHz.
280 // TODO(henrika): return correct value in rare non-48KHz cases.
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)
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.
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)
307 else if (mixing_sample_rate
== 44100)
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
),
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
;
368 bool IsWASAPISupported() {
369 // Note: that function correctly returns that Windows Server 2003 does not
371 return base::win::GetVersion() >= base::win::VERSION_VISTA
;