| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <limits> | 5 #include <limits> |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "services/media/audio/platform/generic/mixers/linear_sampler.h" | 8 #include "services/media/audio/platform/generic/mixers/linear_sampler.h" |
| 9 #include "services/media/audio/platform/generic/mixers/mixer_utils.h" | 9 #include "services/media/audio/platform/generic/mixers/mixer_utils.h" |
| 10 | 10 |
| 11 namespace mojo { | 11 namespace mojo { |
| 12 namespace media { | 12 namespace media { |
| 13 namespace audio { | 13 namespace audio { |
| 14 namespace mixers { | 14 namespace mixers { |
| 15 | 15 |
| 16 template <typename DType, | 16 template <size_t DChCount, |
| 17 size_t DChCount, | |
| 18 typename SType, | 17 typename SType, |
| 19 size_t SChCount> | 18 size_t SChCount> |
| 20 class LinearSamplerImpl : public LinearSampler { | 19 class LinearSamplerImpl : public LinearSampler { |
| 21 public: | 20 public: |
| 22 LinearSamplerImpl() | 21 LinearSamplerImpl() |
| 23 : LinearSampler(FRAC_ONE - 1, FRAC_ONE - 1) { | 22 : LinearSampler(FRAC_ONE - 1, FRAC_ONE - 1) { |
| 24 Reset(); | 23 Reset(); |
| 25 } | 24 } |
| 26 | 25 |
| 27 bool Mix(void* dst, | 26 bool Mix(int32_t* dst, |
| 28 uint32_t dst_frames, | 27 uint32_t dst_frames, |
| 29 uint32_t* dst_offset, | 28 uint32_t* dst_offset, |
| 30 const void* src, | 29 const void* src, |
| 31 uint32_t frac_src_frames, | 30 uint32_t frac_src_frames, |
| 32 int32_t* frac_src_offset, | 31 int32_t* frac_src_offset, |
| 33 uint32_t frac_step_size, | 32 uint32_t frac_step_size, |
| 34 bool accumulate) override; | 33 bool accumulate) override; |
| 35 | 34 |
| 36 void Reset() override { | 35 void Reset() override { |
| 37 ::memset(filter_data_, 0, sizeof(filter_data_)); | 36 ::memset(filter_data_, 0, sizeof(filter_data_)); |
| 38 } | 37 } |
| 39 | 38 |
| 40 private: | 39 private: |
| 41 template <bool DoAccumulate> | 40 template <bool DoAccumulate> |
| 42 inline bool Mix(void* dst, | 41 inline bool Mix(int32_t* dst, |
| 43 uint32_t dst_frames, | 42 uint32_t dst_frames, |
| 44 uint32_t* dst_offset, | 43 uint32_t* dst_offset, |
| 45 const void* src, | 44 const void* src, |
| 46 uint32_t frac_src_frames, | 45 uint32_t frac_src_frames, |
| 47 int32_t* frac_src_offset, | 46 int32_t* frac_src_offset, |
| 48 uint32_t frac_step_size); | 47 uint32_t frac_step_size); |
| 49 | 48 |
| 50 static inline int32_t Interpolate(int32_t A, int32_t B, uint32_t alpha) { | 49 static inline int32_t Interpolate(int32_t A, int32_t B, uint32_t alpha) { |
| 51 return ((A * static_cast<int32_t>(FRAC_ONE - alpha)) | 50 return ((A * static_cast<int32_t>(FRAC_ONE - alpha)) |
| 52 + (B * static_cast<int32_t>(alpha))) | 51 + (B * static_cast<int32_t>(alpha))) |
| 53 >> AudioTrackImpl::PTS_FRACTIONAL_BITS; | 52 >> AudioTrackImpl::PTS_FRACTIONAL_BITS; |
| 54 } | 53 } |
| 55 | 54 |
| 56 int32_t filter_data_[2 * DChCount]; | 55 int32_t filter_data_[2 * DChCount]; |
| 57 }; | 56 }; |
| 58 | 57 |
| 59 template <typename DType, | 58 template <size_t DChCount, |
| 60 size_t DChCount, | |
| 61 typename SType, | 59 typename SType, |
| 62 size_t SChCount> | 60 size_t SChCount> |
| 63 template <bool DoAccumulate> | 61 template <bool DoAccumulate> |
| 64 inline bool LinearSamplerImpl<DType, DChCount, SType, SChCount>::Mix( | 62 inline bool LinearSamplerImpl<DChCount, SType, SChCount>::Mix( |
| 65 void* dst_void, | 63 int32_t* dst, |
| 66 uint32_t dst_frames, | 64 uint32_t dst_frames, |
| 67 uint32_t* dst_offset, | 65 uint32_t* dst_offset, |
| 68 const void* src_void, | 66 const void* src_void, |
| 69 uint32_t frac_src_frames, | 67 uint32_t frac_src_frames, |
| 70 int32_t* frac_src_offset, | 68 int32_t* frac_src_offset, |
| 71 uint32_t frac_step_size) { | 69 uint32_t frac_step_size) { |
| 72 using SR = utils::SrcReader<SType, SChCount, DChCount>; | 70 using SR = utils::SrcReader<SType, SChCount, DChCount>; |
| 73 using DM = utils::DstMixer<DType, DoAccumulate>; | 71 using DM = utils::DstMixer<DoAccumulate>; |
| 74 const SType* src = static_cast<const SType*>(src_void); | 72 const SType* src = static_cast<const SType*>(src_void); |
| 75 DType* dst = static_cast<DType*>(dst_void); | |
| 76 uint32_t doff = *dst_offset; | 73 uint32_t doff = *dst_offset; |
| 77 int32_t soff = *frac_src_offset; | 74 int32_t soff = *frac_src_offset; |
| 78 | 75 |
| 79 DCHECK_LT(doff, dst_frames); | 76 DCHECK_LT(doff, dst_frames); |
| 80 DCHECK_GE(frac_src_frames, FRAC_ONE); | 77 DCHECK_GE(frac_src_frames, FRAC_ONE); |
| 81 DCHECK_LE(frac_src_frames, | 78 DCHECK_LE(frac_src_frames, |
| 82 static_cast<uint32_t>(std::numeric_limits<int32_t>::max())); | 79 static_cast<uint32_t>(std::numeric_limits<int32_t>::max())); |
| 83 | 80 |
| 84 if (soff < 0) { | 81 if (soff < 0) { |
| 85 DCHECK_LT(static_cast<uint32_t>(-soff), FRAC_ONE); | 82 DCHECK_LT(static_cast<uint32_t>(-soff), FRAC_ONE); |
| 86 | 83 |
| 87 for (size_t D = 0; D < DChCount; ++D) { | 84 for (size_t D = 0; D < DChCount; ++D) { |
| 88 filter_data_[DChCount + D] = SR::Read(src + (D / SR::DstPerSrc)); | 85 filter_data_[DChCount + D] = SR::Read(src + (D / SR::DstPerSrc)); |
| 89 } | 86 } |
| 90 | 87 |
| 91 do { | 88 do { |
| 92 DType* out = dst + (doff * DChCount); | 89 int32_t* out = dst + (doff * DChCount); |
| 93 | 90 |
| 94 for (size_t D = 0; D < DChCount; ++D) { | 91 for (size_t D = 0; D < DChCount; ++D) { |
| 95 int32_t sample = Interpolate(filter_data_[DChCount + D], | 92 int32_t sample = Interpolate(filter_data_[DChCount + D], |
| 96 filter_data_[D], | 93 filter_data_[D], |
| 97 -soff); | 94 -soff); |
| 98 out[D] = DM::Mix(out + D, sample); | 95 out[D] = DM::Mix(out[D], sample); |
| 99 } | 96 } |
| 100 | 97 |
| 101 doff += 1; | 98 doff += 1; |
| 102 soff += frac_step_size; | 99 soff += frac_step_size; |
| 103 } while ((doff < dst_frames) && (soff < 0)); | 100 } while ((doff < dst_frames) && (soff < 0)); |
| 104 } | 101 } |
| 105 | 102 |
| 106 int32_t source_end = static_cast<int32_t>(frac_src_frames - FRAC_ONE); | 103 int32_t source_end = static_cast<int32_t>(frac_src_frames - FRAC_ONE); |
| 107 while ((doff < dst_frames) && (soff < source_end)) { | 104 while ((doff < dst_frames) && (soff < source_end)) { |
| 108 uint32_t S = (soff >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; | 105 uint32_t S = (soff >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; |
| 109 DType* out = dst + (doff * DChCount); | 106 int32_t* out = dst + (doff * DChCount); |
| 110 | 107 |
| 111 for (size_t D = 0; D < DChCount; ++D) { | 108 for (size_t D = 0; D < DChCount; ++D) { |
| 112 int32_t s1 = SR::Read(src + S + (D / SR::DstPerSrc)); | 109 int32_t s1 = SR::Read(src + S + (D / SR::DstPerSrc)); |
| 113 int32_t s2 = SR::Read(src + S + (D / SR::DstPerSrc) + SChCount); | 110 int32_t s2 = SR::Read(src + S + (D / SR::DstPerSrc) + SChCount); |
| 114 int32_t sample = Interpolate(s1, s2, soff & FRAC_MASK); | 111 int32_t sample = Interpolate(s1, s2, soff & FRAC_MASK); |
| 115 out[D] = DM::Mix(out + D, sample); | 112 out[D] = DM::Mix(out[D], sample); |
| 116 } | 113 } |
| 117 | 114 |
| 118 doff += 1; | 115 doff += 1; |
| 119 soff += frac_step_size; | 116 soff += frac_step_size; |
| 120 } | 117 } |
| 121 | 118 |
| 122 // If we have room to produce one more sample, and our sampling position hits | 119 // If we have room to produce one more sample, and our sampling position hits |
| 123 // the position input buffer's final frame exactly, go ahead and sample the | 120 // the position input buffer's final frame exactly, go ahead and sample the |
| 124 // final frame into the output buffer. | 121 // final frame into the output buffer. |
| 125 if ((doff < dst_frames) && (soff == source_end)) { | 122 if ((doff < dst_frames) && (soff == source_end)) { |
| 126 uint32_t S = (soff >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; | 123 uint32_t S = (soff >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; |
| 127 DType* out = dst + (doff * DChCount); | 124 int32_t* out = dst + (doff * DChCount); |
| 128 | 125 |
| 129 for (size_t D = 0; D < DChCount; ++D) { | 126 for (size_t D = 0; D < DChCount; ++D) { |
| 130 int32_t sample = SR::Read(src + S + (D / SR::DstPerSrc)); | 127 int32_t sample = SR::Read(src + S + (D / SR::DstPerSrc)); |
| 131 out[D] = DM::Mix(out + D, sample); | 128 out[D] = DM::Mix(out[D], sample); |
| 132 } | 129 } |
| 133 | 130 |
| 134 doff += 1; | 131 doff += 1; |
| 135 soff += frac_step_size; | 132 soff += frac_step_size; |
| 136 } | 133 } |
| 137 | 134 |
| 138 *dst_offset = doff; | 135 *dst_offset = doff; |
| 139 *frac_src_offset = soff; | 136 *frac_src_offset = soff; |
| 140 | 137 |
| 141 if (soff >= source_end) { | 138 if (soff >= source_end) { |
| 142 uint32_t S = (source_end >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; | 139 uint32_t S = (source_end >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; |
| 143 for (size_t D = 0; D < DChCount; ++D) { | 140 for (size_t D = 0; D < DChCount; ++D) { |
| 144 filter_data_[D] = SR::Read(src + S + (D / SR::DstPerSrc)); | 141 filter_data_[D] = SR::Read(src + S + (D / SR::DstPerSrc)); |
| 145 } | 142 } |
| 146 return (doff < dst_frames); | 143 return (doff < dst_frames); |
| 147 } | 144 } |
| 148 | 145 |
| 149 return false; | 146 return false; |
| 150 } | 147 } |
| 151 | 148 |
| 152 template <typename DType, | 149 template <size_t DChCount, |
| 153 size_t DChCount, | |
| 154 typename SType, | 150 typename SType, |
| 155 size_t SChCount> | 151 size_t SChCount> |
| 156 bool LinearSamplerImpl<DType, DChCount, SType, SChCount>::Mix( | 152 bool LinearSamplerImpl<DChCount, SType, SChCount>::Mix( |
| 157 void* dst, | 153 int32_t* dst, |
| 158 uint32_t dst_frames, | 154 uint32_t dst_frames, |
| 159 uint32_t* dst_offset, | 155 uint32_t* dst_offset, |
| 160 const void* src, | 156 const void* src, |
| 161 uint32_t frac_src_frames, | 157 uint32_t frac_src_frames, |
| 162 int32_t* frac_src_offset, | 158 int32_t* frac_src_offset, |
| 163 uint32_t frac_step_size, | 159 uint32_t frac_step_size, |
| 164 bool accumulate) { | 160 bool accumulate) { |
| 165 return accumulate ? Mix<true>(dst, dst_frames, dst_offset, | 161 return accumulate ? Mix<true>(dst, dst_frames, dst_offset, |
| 166 src, frac_src_frames, frac_src_offset, | 162 src, frac_src_frames, frac_src_offset, |
| 167 frac_step_size) | 163 frac_step_size) |
| 168 : Mix<false>(dst, dst_frames, dst_offset, | 164 : Mix<false>(dst, dst_frames, dst_offset, |
| 169 src, frac_src_frames, frac_src_offset, | 165 src, frac_src_frames, frac_src_offset, |
| 170 frac_step_size); | 166 frac_step_size); |
| 171 } | 167 } |
| 172 | 168 |
| 173 // Templates used to expand all of the different combinations of the possible | 169 // Templates used to expand all of the different combinations of the possible |
| 174 // Linear Sampler Mixer configurations. | 170 // Linear Sampler Mixer configurations. |
| 175 template <typename DType, | 171 template <size_t DChCount, |
| 176 size_t DChCount, | |
| 177 typename SType, | 172 typename SType, |
| 178 size_t SChCount> | 173 size_t SChCount> |
| 179 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, | 174 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, |
| 180 const LpcmMediaTypeDetailsPtr& dst_format) { | 175 const LpcmMediaTypeDetailsPtr& dst_format) { |
| 181 return MixerPtr(new LinearSamplerImpl<DType, DChCount, SType, SChCount>()); | 176 return MixerPtr(new LinearSamplerImpl<DChCount, SType, SChCount>()); |
| 182 } | 177 } |
| 183 | 178 |
| 184 template <typename DType, | 179 template <size_t DChCount, |
| 185 size_t DChCount, | |
| 186 typename SType> | 180 typename SType> |
| 187 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, | 181 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, |
| 188 const LpcmMediaTypeDetailsPtr& dst_format) { | 182 const LpcmMediaTypeDetailsPtr& dst_format) { |
| 189 switch (src_format->channels) { | 183 switch (src_format->channels) { |
| 190 case 1: | 184 case 1: |
| 191 return SelectLSM<DType, DChCount, SType, 1>(src_format, dst_format); | 185 return SelectLSM<DChCount, SType, 1>(src_format, dst_format); |
| 192 case 2: | 186 case 2: |
| 193 return SelectLSM<DType, DChCount, SType, 2>(src_format, dst_format); | 187 return SelectLSM<DChCount, SType, 2>(src_format, dst_format); |
| 194 default: | 188 default: |
| 195 return nullptr; | 189 return nullptr; |
| 196 } | 190 } |
| 197 } | 191 } |
| 198 | 192 |
| 199 template <typename DType, | 193 template <size_t DChCount> |
| 200 size_t DChCount> | |
| 201 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, | 194 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, |
| 202 const LpcmMediaTypeDetailsPtr& dst_format) { | 195 const LpcmMediaTypeDetailsPtr& dst_format) { |
| 203 switch (src_format->sample_format) { | 196 switch (src_format->sample_format) { |
| 204 case LpcmSampleFormat::UNSIGNED_8: | 197 case LpcmSampleFormat::UNSIGNED_8: |
| 205 return SelectLSM<DType, DChCount, uint8_t>(src_format, dst_format); | 198 return SelectLSM<DChCount, uint8_t>(src_format, dst_format); |
| 206 case LpcmSampleFormat::SIGNED_16: | 199 case LpcmSampleFormat::SIGNED_16: |
| 207 return SelectLSM<DType, DChCount, int16_t>(src_format, dst_format); | 200 return SelectLSM<DChCount, int16_t>(src_format, dst_format); |
| 208 default: | |
| 209 return nullptr; | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 template <typename DType> | |
| 214 static inline MixerPtr SelectLSM(const LpcmMediaTypeDetailsPtr& src_format, | |
| 215 const LpcmMediaTypeDetailsPtr& dst_format) { | |
| 216 switch (dst_format->channels) { | |
| 217 case 1: | |
| 218 return SelectLSM<DType, 1>(src_format, dst_format); | |
| 219 case 2: | |
| 220 return SelectLSM<DType, 2>(src_format, dst_format); | |
| 221 default: | 201 default: |
| 222 return nullptr; | 202 return nullptr; |
| 223 } | 203 } |
| 224 } | 204 } |
| 225 | 205 |
| 226 MixerPtr LinearSampler::Select(const LpcmMediaTypeDetailsPtr& src_format, | 206 MixerPtr LinearSampler::Select(const LpcmMediaTypeDetailsPtr& src_format, |
| 227 const LpcmMediaTypeDetailsPtr& dst_format) { | 207 const LpcmMediaTypeDetailsPtr& dst_format) { |
| 228 switch (dst_format->sample_format) { | 208 switch (dst_format->channels) { |
| 229 case LpcmSampleFormat::UNSIGNED_8: | 209 case 1: |
| 230 return SelectLSM<uint8_t>(src_format, dst_format); | 210 return SelectLSM<1>(src_format, dst_format); |
| 231 case LpcmSampleFormat::SIGNED_16: | 211 case 2: |
| 232 return SelectLSM<int16_t>(src_format, dst_format); | 212 return SelectLSM<2>(src_format, dst_format); |
| 233 default: | 213 default: |
| 234 return nullptr; | 214 return nullptr; |
| 235 } | 215 } |
| 236 } | 216 } |
| 237 | 217 |
| 238 } // namespace mixers | 218 } // namespace mixers |
| 239 } // namespace audio | 219 } // namespace audio |
| 240 } // namespace media | 220 } // namespace media |
| 241 } // namespace mojo | 221 } // namespace mojo |
| OLD | NEW |