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 // Software adjust volume of samples, allows each audio stream its own | 5 // Software adjust volume of samples, allows each audio stream its own |
6 // volume without impacting master volume for chrome and other applications. | 6 // volume without impacting master volume for chrome and other applications. |
7 | 7 |
8 // Implemented as templates to allow 8, 16 and 32 bit implementations. | 8 // Implemented as templates to allow 8, 16 and 32 bit implementations. |
9 // 8 bit is unsigned and biased by 128. | 9 // 8 bit is unsigned and biased by 128. |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 template<class Format, class Fixed, int bias> | 63 template<class Format, class Fixed, int bias> |
64 static void AdjustVolume(Format* buf_out, | 64 static void AdjustVolume(Format* buf_out, |
65 int sample_count, | 65 int sample_count, |
66 int fixed_volume) { | 66 int fixed_volume) { |
67 for (int i = 0; i < sample_count; ++i) { | 67 for (int i = 0; i < sample_count; ++i) { |
68 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias, | 68 buf_out[i] = static_cast<Format>(ScaleChannel<Fixed>(buf_out[i] - bias, |
69 fixed_volume) + bias); | 69 fixed_volume) + bias); |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 static const int kChannel_L = 0; | |
74 static const int kChannel_R = 1; | |
75 static const int kChannel_C = 2; | |
76 | |
77 template<class Fixed, int min_value, int max_value> | |
78 static int AddSaturated(int val, int adder) { | |
79 Fixed sum = static_cast<Fixed>(val) + static_cast<Fixed>(adder); | |
80 if (sum > max_value) | |
81 return max_value; | |
82 if (sum < min_value) | |
83 return min_value; | |
84 return static_cast<int>(sum); | |
85 } | |
86 | |
87 // AdjustVolume() does an in place audio sample change. | 73 // AdjustVolume() does an in place audio sample change. |
88 bool AdjustVolume(void* buf, | 74 bool AdjustVolume(void* buf, |
89 size_t buflen, | 75 size_t buflen, |
90 int channels, | 76 int channels, |
91 int bytes_per_sample, | 77 int bytes_per_sample, |
92 float volume) { | 78 float volume) { |
93 DCHECK(buf); | 79 DCHECK(buf); |
94 if (volume < 0.0f || volume > 1.0f) | 80 if (volume < 0.0f || volume > 1.0f) |
95 return false; | 81 return false; |
96 if (volume == 1.0f) { | 82 if (volume == 1.0f) { |
(...skipping 18 matching lines...) Expand all Loading... |
115 } else if (bytes_per_sample == 4) { | 101 } else if (bytes_per_sample == 4) { |
116 AdjustVolume<int32, int64, 0>(reinterpret_cast<int32*>(buf), | 102 AdjustVolume<int32, int64, 0>(reinterpret_cast<int32*>(buf), |
117 sample_count, | 103 sample_count, |
118 fixed_volume); | 104 fixed_volume); |
119 return true; | 105 return true; |
120 } | 106 } |
121 } | 107 } |
122 return false; | 108 return false; |
123 } | 109 } |
124 | 110 |
125 // TODO(enal): use template specialization and size-specific intrinsics. | |
126 // Call is on the time-critical path, and by using SSE/AVX | |
127 // instructions we can speed things up by ~4-8x, more for the case | |
128 // when we have to adjust volume as well. | |
129 template<class Format, class Fixed, int min_value, int max_value, int bias> | |
130 static void MixStreams(Format* dst, Format* src, int count, float volume) { | |
131 if (volume == 0.0f) | |
132 return; | |
133 if (volume == 1.0f) { | |
134 // Most common case -- no need to adjust volume. | |
135 for (int i = 0; i < count; ++i) { | |
136 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
137 src[i] - bias); | |
138 dst[i] = static_cast<Format>(value + bias); | |
139 } | |
140 } else { | |
141 // General case -- have to adjust volume before mixing. | |
142 const int fixed_volume = static_cast<int>(volume * 65536); | |
143 for (int i = 0; i < count; ++i) { | |
144 Fixed adjusted_src = ScaleChannel<Fixed>(src[i] - bias, fixed_volume); | |
145 Fixed value = AddSaturated<Fixed, min_value, max_value>(dst[i] - bias, | |
146 adjusted_src); | |
147 dst[i] = static_cast<Format>(value + bias); | |
148 } | |
149 } | |
150 } | |
151 | |
152 void MixStreams(void* dst, | |
153 void* src, | |
154 size_t buflen, | |
155 int bytes_per_sample, | |
156 float volume) { | |
157 DCHECK(dst); | |
158 DCHECK(src); | |
159 DCHECK_GE(volume, 0.0f); | |
160 DCHECK_LE(volume, 1.0f); | |
161 switch (bytes_per_sample) { | |
162 case 1: | |
163 MixStreams<uint8, int32, kint8min, kint8max, 128>( | |
164 static_cast<uint8*>(dst), | |
165 static_cast<uint8*>(src), | |
166 buflen, | |
167 volume); | |
168 break; | |
169 case 2: | |
170 DCHECK_EQ(0u, buflen % 2); | |
171 MixStreams<int16, int32, kint16min, kint16max, 0>( | |
172 static_cast<int16*>(dst), | |
173 static_cast<int16*>(src), | |
174 buflen / 2, | |
175 volume); | |
176 break; | |
177 case 4: | |
178 DCHECK_EQ(0u, buflen % 4); | |
179 MixStreams<int32, int64, kint32min, kint32max, 0>( | |
180 static_cast<int32*>(dst), | |
181 static_cast<int32*>(src), | |
182 buflen / 4, | |
183 volume); | |
184 break; | |
185 default: | |
186 NOTREACHED() << "Illegal bytes per sample"; | |
187 break; | |
188 } | |
189 } | |
190 | |
191 int GetAudioHardwareSampleRate() { | 111 int GetAudioHardwareSampleRate() { |
192 #if defined(OS_MACOSX) | 112 #if defined(OS_MACOSX) |
193 // Hardware sample-rate on the Mac can be configured, so we must query. | 113 // Hardware sample-rate on the Mac can be configured, so we must query. |
194 return AUAudioOutputStream::HardwareSampleRate(); | 114 return AUAudioOutputStream::HardwareSampleRate(); |
195 #elif defined(OS_WIN) | 115 #elif defined(OS_WIN) |
196 if (!CoreAudioUtil::IsSupported()) { | 116 if (!CoreAudioUtil::IsSupported()) { |
197 // Fall back to Windows Wave implementation on Windows XP or lower | 117 // Fall back to Windows Wave implementation on Windows XP or lower |
198 // and use 48kHz as default input sample rate. | 118 // and use 48kHz as default input sample rate. |
199 return 48000; | 119 return 48000; |
200 } | 120 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 // out performance was degraded compared to XP. | 296 // out performance was degraded compared to XP. |
377 // - The regression was fixed in Windows 7 and most configurations will work | 297 // - The regression was fixed in Windows 7 and most configurations will work |
378 // with 2, but some (e.g., some Sound Blasters) still need 3. | 298 // with 2, but some (e.g., some Sound Blasters) still need 3. |
379 // - Some XP configurations (even multi-processor ones) also need 3. | 299 // - Some XP configurations (even multi-processor ones) also need 3. |
380 return (base::win::GetVersion() == base::win::VERSION_VISTA) ? 4 : 3; | 300 return (base::win::GetVersion() == base::win::VERSION_VISTA) ? 4 : 3; |
381 } | 301 } |
382 | 302 |
383 #endif | 303 #endif |
384 | 304 |
385 } // namespace media | 305 } // namespace media |
OLD | NEW |