Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <limits> | |
| 6 #include <type_traits> | |
| 7 | |
| 8 #include "base/logging.h" | |
| 9 #include "mojo/services/media/common/cpp/linear_transform.h" | |
| 10 #include "services/media/audio/platform/generic/output_formatter.h" | |
| 11 | |
| 12 namespace mojo { | |
| 13 namespace media { | |
| 14 namespace audio { | |
| 15 | |
| 16 // Template to produce destination samples from normalized samples. | |
| 17 template <typename DType, typename Enable = void> class DstConverter; | |
| 18 | |
| 19 template <typename DType> | |
| 20 class DstConverter<DType, | |
| 21 typename std::enable_if< | |
| 22 std::is_same<DType, int16_t>::value, | |
| 23 void>::type> { | |
| 24 public: | |
| 25 static inline constexpr DType Convert(int32_t sample) { | |
| 26 return static_cast<DType>(sample); | |
| 27 } | |
| 28 }; | |
| 29 | |
|
dalesat
2016/01/24 19:07:39
Can we just define a template function and special
johngro
2016/01/25 18:12:32
Its been a while, but this can fail in some cases
| |
| 30 template <typename DType> | |
| 31 class DstConverter<DType, | |
| 32 typename std::enable_if< | |
| 33 std::is_same<DType, uint8_t>::value, | |
| 34 void>::type> { | |
| 35 public: | |
| 36 static inline constexpr DType Convert(int32_t sample) { | |
| 37 return static_cast<DType>((sample >> 8) + 0x80); | |
| 38 } | |
| 39 }; | |
| 40 | |
| 41 // Template to fill samples with silence based on sample type. | |
| 42 template <typename DType, typename Enable = void> class SilenceMaker; | |
| 43 | |
| 44 template <typename DType> | |
| 45 class SilenceMaker<DType, | |
| 46 typename std::enable_if< | |
| 47 std::is_same<DType, int16_t>::value, | |
| 48 void>::type> { | |
| 49 public: | |
| 50 static inline void Fill(void* dest, size_t samples) { | |
| 51 ::memset(dest, 0, samples * sizeof(DType)); | |
| 52 } | |
| 53 }; | |
| 54 | |
| 55 template <typename DType> | |
| 56 class SilenceMaker<DType, | |
| 57 typename std::enable_if< | |
| 58 std::is_same<DType, uint8_t>::value, | |
| 59 void>::type> { | |
| 60 public: | |
| 61 static inline void Fill(void* dest, size_t samples) { | |
| 62 ::memset(dest, 0x80, samples * sizeof(DType)); | |
| 63 } | |
| 64 }; | |
| 65 | |
| 66 // A templated class which implements the ProduceOutput and FillWithSilence | |
| 67 // methods of OutputFormatter | |
| 68 template <typename DType, uint32_t DChCount> | |
| 69 class OutputFormatterImpl : public OutputFormatter { | |
| 70 public: | |
| 71 explicit OutputFormatterImpl(const LpcmMediaTypeDetailsPtr& format) | |
| 72 : OutputFormatter(format, sizeof(DType), DChCount) {} | |
| 73 | |
| 74 void ProduceOutput(const int32_t* source, | |
| 75 void* dest_void, | |
| 76 uint32_t frames) const override { | |
| 77 using DC = DstConverter<DType>; | |
| 78 DType* dest = static_cast<DType*>(dest_void); | |
| 79 | |
| 80 for (size_t i = 0; i < (static_cast<size_t>(frames) * DChCount); ++i) { | |
| 81 register int32_t val = source[i]; | |
|
jeffbrown
2015/12/01 22:13:30
Does the register keyword even do anything these d
johngro
2016/01/25 18:12:32
probably not, but it does not hurt either. It has
| |
| 82 if (val > std::numeric_limits<int16_t>::max()) { | |
| 83 dest[i] = DC::Convert(std::numeric_limits<int16_t>::max()); | |
| 84 } else if (val < std::numeric_limits<int16_t>::min()) { | |
| 85 dest[i] = DC::Convert(std::numeric_limits<int16_t>::min()); | |
| 86 } else { | |
| 87 dest[i] = DC::Convert(val); | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 void FillWithSilence(void* dest, uint32_t frames) const override { | |
| 93 SilenceMaker<DType>::Fill(dest, frames * DChCount); | |
| 94 } | |
| 95 }; | |
| 96 | |
| 97 // Constructor/destructor for the bommon OutputFormatter base class. | |
|
jeffbrown
2015/12/01 22:13:30
common
johngro
2016/01/25 18:12:32
Done.
| |
| 98 OutputFormatter::OutputFormatter(const LpcmMediaTypeDetailsPtr& format, | |
| 99 uint32_t bytes_per_sample, | |
| 100 uint32_t channels) | |
| 101 : format_(format.Clone()), | |
| 102 channels_(channels), | |
| 103 bytes_per_sample_(bytes_per_sample), | |
| 104 bytes_per_frame_(bytes_per_sample * channels) {} | |
| 105 | |
| 106 OutputFormatter::~OutputFormatter() {} | |
| 107 | |
| 108 // Selection routines which will instantiate a particular templatized version of | |
| 109 // the output formatter. | |
| 110 template <typename DType> | |
| 111 static inline OutputFormatterPtr SelectOF( | |
| 112 const LpcmMediaTypeDetailsPtr& format) { | |
| 113 switch (format->channels) { | |
| 114 case 1: | |
| 115 return OutputFormatterPtr(new OutputFormatterImpl<DType, 1>(format)); | |
| 116 case 2: | |
| 117 return OutputFormatterPtr(new OutputFormatterImpl<DType, 2>(format)); | |
| 118 default: | |
| 119 LOG(ERROR) << "Unsupported output channels " | |
| 120 << format->channels; | |
| 121 return nullptr; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 OutputFormatterPtr OutputFormatter::Select( | |
| 126 const LpcmMediaTypeDetailsPtr& format) { | |
| 127 DCHECK(format); | |
| 128 | |
| 129 switch (format->sample_format) { | |
| 130 case LpcmSampleFormat::UNSIGNED_8: | |
| 131 return SelectOF<uint8_t>(format); | |
| 132 case LpcmSampleFormat::SIGNED_16: | |
| 133 return SelectOF<int16_t>(format); | |
| 134 default: | |
| 135 LOG(ERROR) << "Unsupported output sample format " | |
| 136 << format->sample_format; | |
| 137 return nullptr; | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 } // namespace audio | |
| 142 } // namespace media | |
| 143 } // namespace mojo | |
| OLD | NEW |