| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "media/audio/audio_util.h" | 10 #include "media/audio/audio_util.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 } else if (bytes_per_sample == 4) { | 52 } else if (bytes_per_sample == 4) { |
| 53 AdjustVolumeInternal(reinterpret_cast<int32*>(buf), | 53 AdjustVolumeInternal(reinterpret_cast<int32*>(buf), |
| 54 sample_count, | 54 sample_count, |
| 55 volume); | 55 volume); |
| 56 return true; | 56 return true; |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 return false; | 59 return false; |
| 60 } | 60 } |
| 61 | 61 |
| 62 // Channel order for AAC |
| 63 // From http://www.hydrogenaudio.org/forums/lofiversion/index.php/t40046.html |
| 64 // And Quicktime Pro, Movie Inspector |
| 65 const int kChannel_C = 0; |
| 66 const int kChannel_L = 1; |
| 67 const int kChannel_R = 2; |
| 68 const int kChannel_SL = 3; |
| 69 const int kChannel_SR = 4; |
| 70 const int kChannel_LFE = 5; |
| 71 |
| 72 template<class Format> |
| 73 Format ChannelsClampInternal(float val, |
| 74 const Format min_value, |
| 75 const Format max_value) { |
| 76 if (val > static_cast<float>(max_value)) { |
| 77 return max_value; |
| 78 } |
| 79 if (val < static_cast<float>(min_value)) { |
| 80 return min_value; |
| 81 } |
| 82 return static_cast<Format>(val); |
| 83 } |
| 84 |
| 85 template<class Format> |
| 86 void FoldChannelsInternal(Format* buf_out, |
| 87 int sample_count, |
| 88 float volume, |
| 89 int channels, |
| 90 const int min_value, |
| 91 const int max_value) { |
| 92 Format* buf_in = buf_out; |
| 93 // mid_value is to adjust excess 128 notation in unsigned 8 bit samples |
| 94 // to signed before adding channels. |
| 95 const int mid_value = (max_value + min_value + 1) / 2; |
| 96 const float kHalfPerceived = 0.707f; // 1/sqrt(2) |
| 97 for (int i = 0; i < sample_count; ++i) { |
| 98 float center_half = static_cast<float>(buf_in[kChannel_C] - mid_value) * kHa
lfPerceived; |
| 99 float left = static_cast<float>(buf_in[kChannel_L] - mid_value); |
| 100 float right = static_cast<float>(buf_in[kChannel_R] - mid_value); |
| 101 float surround_left = static_cast<float>(buf_in[kChannel_SL] - mid_value); |
| 102 float surround_right = static_cast<float>(buf_in[kChannel_SR] - mid_value); |
| 103 buf_out[0] = ChannelsClampInternal( |
| 104 (left + surround_left + center_half) * volume + mid_value, |
| 105 static_cast<Format>(min_value), static_cast<Format>(max_value)); |
| 106 buf_out[1] = ChannelsClampInternal( |
| 107 (right + surround_right + center_half) * volume + mid_value, |
| 108 static_cast<Format>(min_value), static_cast<Format>(max_value)); |
| 109 buf_out += 2; |
| 110 buf_in += channels; |
| 111 } |
| 112 } |
| 113 |
| 114 bool FoldChannels(void* buf, |
| 115 size_t buflen, |
| 116 int channels, |
| 117 int bytes_per_sample, |
| 118 float volume) { |
| 119 DCHECK(buf); |
| 120 DCHECK(volume >= 0.0f && volume <= 1.0f); |
| 121 if (channels >= 5 && channels <= 6 && bytes_per_sample > 0) { |
| 122 int sample_count = buflen / (channels * bytes_per_sample); |
| 123 if (bytes_per_sample == 1) { |
| 124 FoldChannelsInternal(reinterpret_cast<uint8*>(buf), |
| 125 sample_count, |
| 126 volume, |
| 127 channels, |
| 128 0, 255); |
| 129 return true; |
| 130 } else if (bytes_per_sample == 2) { |
| 131 FoldChannelsInternal(reinterpret_cast<int16*>(buf), |
| 132 sample_count, |
| 133 volume, |
| 134 channels, |
| 135 -32768, |
| 136 32767); |
| 137 return true; |
| 138 } else if (bytes_per_sample == 4) { |
| 139 FoldChannelsInternal(reinterpret_cast<int32*>(buf), |
| 140 sample_count, |
| 141 volume, |
| 142 channels, |
| 143 0x80000000, |
| 144 0x7fffffff); |
| 145 return true; |
| 146 } |
| 147 } |
| 148 return false; |
| 149 } |
| 150 |
| 62 } // namespace media | 151 } // namespace media |
| OLD | NEW |