Index: services/media/audio/platform/generic/mixers/point_sampler.cc |
diff --git a/services/media/audio/platform/generic/mixers/point_sampler.cc b/services/media/audio/platform/generic/mixers/point_sampler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c3496785cf1215e802fce85b1fb92b3d5ca5141d |
--- /dev/null |
+++ b/services/media/audio/platform/generic/mixers/point_sampler.cc |
@@ -0,0 +1,179 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <limits> |
+#include <type_traits> |
+ |
+#include "base/logging.h" |
+#include "services/media/audio/audio_track_impl.h" |
+#include "services/media/audio/platform/generic/mixers/mixer_utils.h" |
+#include "services/media/audio/platform/generic/mixers/point_sampler.h" |
+ |
+namespace mojo { |
+namespace media { |
+namespace audio { |
+namespace mixers { |
+ |
+// Point Sample Mixer implementation. |
+template <typename DType, |
+ size_t DChCount, |
+ typename SType, |
+ size_t SChCount> |
+class PointSamplerImpl : public PointSampler { |
+ public: |
+ PointSamplerImpl() {} |
+ |
+ bool Mix(void* dst, |
+ uint32_t dst_frames, |
+ uint32_t* dst_offset, |
+ const void* src, |
+ uint32_t frac_src_frames, |
+ uint32_t* frac_src_offset, |
+ uint32_t frac_step_size, |
+ bool accumulate) override; |
+ |
+ private: |
+ template <bool DoAccumulate> |
+ static inline bool Mix(void* dst, |
+ uint32_t dst_frames, |
+ uint32_t* dst_offset, |
+ const void* src, |
+ uint32_t frac_src_frames, |
+ uint32_t* frac_src_offset, |
+ uint32_t frac_step_size); |
+}; |
+ |
+template <typename DType, |
+ size_t DChCount, |
+ typename SType, |
+ size_t SChCount> |
+template <bool DoAccumulate> |
+inline bool PointSamplerImpl<DType, DChCount, SType, SChCount>::Mix( |
+ void* dst_void, |
+ uint32_t dst_frames, |
+ uint32_t* dst_offset, |
+ const void* src_void, |
+ uint32_t frac_src_frames, |
+ uint32_t* frac_src_offset, |
+ uint32_t frac_step_size) { |
+ using SR = utils::SrcReader<SType, SChCount, DChCount>; |
+ using DM = utils::DstMixer<DType, DoAccumulate>; |
+ |
+ const SType* src = static_cast<const SType*>(src_void); |
+ DType* dst = static_cast<DType*>(dst_void); |
+ uint32_t doff = *dst_offset; |
+ uint32_t soff = *frac_src_offset; |
+ |
+ DCHECK_LT(doff, dst_frames); |
+ DCHECK_LT(soff, frac_src_frames); |
+ |
+ while ((doff < dst_frames) && (soff < frac_src_frames)) { |
+ uint32_t S = (soff >> AudioTrackImpl::PTS_FRACTIONAL_BITS) * SChCount; |
jeffbrown
2015/11/04 23:43:34
variables shouldn't be uppercase
johngro
2015/11/06 02:20:27
Done.
|
+ DType* out = dst + (doff * DChCount); |
+ |
+ for (size_t D = 0; D < DChCount; ++D) { |
jeffbrown
2015/11/04 23:43:34
We could handle all of the specialization for accu
johngro
2015/11/06 02:20:27
I disagree. I don't want to write two versions of
|
+ int32_t sample = SR::Read(src + S + (D / SR::DstPerSrc)); |
+ out[D] = DM::Mix(out + D, sample); |
+ } |
+ |
+ doff += 1; |
+ soff += frac_step_size; |
+ } |
+ |
+ *dst_offset = doff; |
+ *frac_src_offset = soff; |
+ |
+ return (soff >= frac_src_frames); |
+} |
+ |
+template <typename DType, |
+ size_t DChCount, |
+ typename SType, |
+ size_t SChCount> |
+bool PointSamplerImpl<DType, DChCount, SType, SChCount>::Mix( |
+ void* dst, |
+ uint32_t dst_frames, |
+ uint32_t* dst_offset, |
+ const void* src, |
+ uint32_t frac_src_frames, |
+ uint32_t* frac_src_offset, |
+ uint32_t frac_step_size, |
+ bool accumulate) { |
+ return accumulate ? Mix<true>(dst, dst_frames, dst_offset, |
+ src, frac_src_frames, frac_src_offset, |
+ frac_step_size) |
+ : Mix<false>(dst, dst_frames, dst_offset, |
+ src, frac_src_frames, frac_src_offset, |
+ frac_step_size); |
+} |
+ |
+// Templates used to expand all of the different combinations of the possible |
+// Point Sampler Mixer configurations. |
+template <typename DType, |
+ size_t DChCount, |
+ typename SType, |
+ size_t SChCount> |
+static inline MixerPtr SelectPSM(const LpcmMediaTypeDetailsPtr& src_format, |
+ const LpcmMediaTypeDetailsPtr& dst_format) { |
+ return MixerPtr(new PointSamplerImpl<DType, DChCount, SType, SChCount>()); |
+} |
+ |
+template <typename DType, |
+ size_t DChCount, |
+ typename SType> |
+static inline MixerPtr SelectPSM(const LpcmMediaTypeDetailsPtr& src_format, |
+ const LpcmMediaTypeDetailsPtr& dst_format) { |
+ switch (src_format->samples_per_frame) { |
+ case 1: |
+ return SelectPSM<DType, DChCount, SType, 1>(src_format, dst_format); |
+ case 2: |
+ return SelectPSM<DType, DChCount, SType, 2>(src_format, dst_format); |
+ default: |
+ return nullptr; |
+ } |
+} |
+ |
+template <typename DType, |
+ size_t DChCount> |
+static inline MixerPtr SelectPSM(const LpcmMediaTypeDetailsPtr& src_format, |
+ const LpcmMediaTypeDetailsPtr& dst_format) { |
+ switch (src_format->sample_format) { |
+ case LpcmSampleFormat::UNSIGNED_8: |
+ return SelectPSM<DType, DChCount, uint8_t>(src_format, dst_format); |
+ case LpcmSampleFormat::SIGNED_16: |
+ return SelectPSM<DType, DChCount, int16_t>(src_format, dst_format); |
+ default: |
+ return nullptr; |
+ } |
+} |
+ |
+template <typename DType> |
+static inline MixerPtr SelectPSM(const LpcmMediaTypeDetailsPtr& src_format, |
+ const LpcmMediaTypeDetailsPtr& dst_format) { |
+ switch (dst_format->samples_per_frame) { |
+ case 1: |
+ return SelectPSM<DType, 1>(src_format, dst_format); |
+ case 2: |
+ return SelectPSM<DType, 2>(src_format, dst_format); |
+ default: |
+ return nullptr; |
+ } |
+} |
+ |
+MixerPtr PointSampler::Select(const LpcmMediaTypeDetailsPtr& src_format, |
+ const LpcmMediaTypeDetailsPtr& dst_format) { |
+ switch (dst_format->sample_format) { |
+ case LpcmSampleFormat::UNSIGNED_8: |
+ return SelectPSM<uint8_t>(src_format, dst_format); |
+ case LpcmSampleFormat::SIGNED_16: |
+ return SelectPSM<int16_t>(src_format, dst_format); |
+ default: |
+ return nullptr; |
+ } |
+} |
+ |
+} // namespace mixers |
+} // namespace audio |
+} // namespace media |
+} // namespace mojo |