Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: media/base/audio_sample_types.h

Issue 2024993004: AudioBus: Add a ToInterleavedFloat() method to AudioBus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added unit tests Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
mcasas 2016/06/12 09:41:48 No (c) -- got removed this (last?) year https://ww
chfremer 2016/06/13 17:44:12 Done.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_
6 #define MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_
7
8 #include <cstdint>
9 #include <limits>
10 #include <type_traits>
11
12 // To specify different sample formats, we provide a class for each sample
13 // format that knows certain things about it, such as the C++ data type used
14 // to store sample values, min and max values, as well as how to convert to
15 // and from floating point formats. Each class must satisfy a concept we call
16 // "SampleTypeTraits", which requires that the following publics are provided:
17 // * A type |ValueType| specifying the C++ type for storing sample values
18 // * A static constant kMinValue which specifies the minimum sample value
19 // * A static constant kMaxValue which specifies the maximum sample value
20 // * A static constant kZeroPointValue which specifies the sample value
21 // representing an amplitude of zero
22 // * A static method ConvertFromFloat() that takes a float sample value and
23 // converts it to the corresponding ValueType
24 // * A static method ConvertFromDouble() that takes a double sample value and
25 // converts it to the corresponding ValueType
26 // * A static method ConvertToFloat() that takes a ValueType sample value and
27 // converts it to the corresponding float value
28 // * A static method ConvertToDouble() that takes a ValueType sample value and
29 // converts it to the corresponding double value
30
31 namespace media {
32
33 // For float or double.
34 // See also the aliases for commonly used types at the bottom of this file.
35 template <typename SampleType>
36 class FloatSampleTypeTraits {
37 static_assert(std::is_floating_point<SampleType>::value,
38 "Template is only valid for float types.");
39
40 public:
41 using ValueType = SampleType;
42
43 static constexpr SampleType kMinValue = -1.0f;
44 static constexpr SampleType kMaxValue = +1.0f;
45 static constexpr SampleType kZeroPointValue = 0.0f;
46
47 static SampleType ConvertFromFloat(float source_value) {
48 return ConvertFromFloatType<float>(source_value);
49 }
50 static float ConvertToFloat(SampleType source_value) {
51 return ConvertToFloatType<float>(source_value);
52 }
53 static SampleType ConvertFromDouble(double source_value) {
54 return ConvertFromFloatType<double>(source_value);
55 }
56 static double ConvertToDouble(SampleType source_value) {
57 return ConvertToFloatType<double>(source_value);
58 }
59
60 private:
61 template <typename FloatType>
62 static SampleType ConvertFromFloatType(FloatType source_value) {
63 return static_cast<SampleType>(source_value);
64 }
65
66 template <typename FloatType>
67 static FloatType ConvertToFloatType(SampleType source_value) {
mcasas 2016/06/12 09:41:48 When writing e.g. mojo traits or MediaStream trait
chfremer 2016/06/13 17:44:12 Done.
68 return static_cast<FloatType>(source_value);
69 }
70 };
71
72 // For uint8_t, int16_t, int32_t...
73 // See also the aliases for commonly used types at the bottom of this file.
74 template <typename SampleType>
75 class FixedSampleTypeTraits {
76 static_assert(std::numeric_limits<SampleType>::is_integer,
77 "Template is only valid for integer types.");
78
79 public:
80 using ValueType = SampleType;
81
82 static constexpr SampleType kMinValue =
83 std::numeric_limits<SampleType>::min();
84 static constexpr SampleType kMaxValue =
85 std::numeric_limits<SampleType>::max();
86 static constexpr SampleType kZeroPointValue =
87 (kMinValue == 0) ? (kMaxValue / 2 + 1) : 0;
88
89 static SampleType ConvertFromFloat(float source_value) {
90 return ConvertFromFloatType<float>(source_value);
91 }
92 static float ConvertToFloat(SampleType source_value) {
93 return ConvertToFloatType<float>(source_value);
94 }
95 static SampleType ConvertFromDouble(double source_value) {
96 return ConvertFromFloatType<double>(source_value);
97 }
98 static double ConvertToDouble(SampleType source_value) {
99 return ConvertToFloatType<double>(source_value);
100 }
101
102 private:
103 // We pre-compute the scaling factors for conversion at compile-time in order
104 // to save computation time during runtime.
105 template <typename FloatType>
106 struct ScalingFactors {
107 // Since zero_point_value() is not the exact center between
108 // min_value() and max_value(), we apply a different scaling for positive
109 // and negative values.
110 // Note that due to the limited precision, the FloatType values may not
111 // always be able to represent the max and min values of the integer
112 // SampleType exactly. This is a concern when using these scale factors for
113 // scaling input sample values for conversion. However, since the min value
114 // of SampleType is usually of the form -2^N and the max value is usually of
115 // the form (+2^N)-1, and due to the fact that the float types store a
116 // significand value plus a binary exponent it just so happens that
117 // FloatType can usually represent the min value exactly and its
118 // representation of the max value is only off by 1, i.e. it quantizes to
119 // (+2^N) instead of (+2^N-1).
120
121 static constexpr FloatType kForPositiveInput =
122 static_cast<FloatType>(kMaxValue) -
123 static_cast<FloatType>(kZeroPointValue);
124
125 // Note: In the below expression, it is important that we cast kMinValue to
126 // FloatType _before_ taking the negative of it. For example, for SampleType
127 // int32_t, the expression (- kMinValue) would evaluate to
128 // -numeric_limits<int32_t>::min(), which falls outside the numeric
129 // range, wraps around, and ends up being the same as
130 // +numeric_limits<int32_t>::min().
131 static constexpr FloatType kForNegativeInput =
132 static_cast<FloatType>(kZeroPointValue) -
133 static_cast<FloatType>(kMinValue);
134
135 static constexpr FloatType kInverseForPositiveInput =
136 1.0f / kForPositiveInput;
137
138 static constexpr FloatType kInverseForNegativeInput =
139 1.0f / kForNegativeInput;
140 };
141
142 template <typename FloatType>
143 static SampleType ConvertFromFloatType(FloatType source_value) {
144 // Note, that the for the case of |source_value| == 1.0, the imprecision of
145 // |kScalingFactorForPositive| can lead to a product that is larger than the
146 // maximum possible value of SampleType. To ensure this does not happen, we
147 // handle the case of |source_value| == 1.0 as part of the clipping check.
148 // For all FloatType values smaller than 1.0, the imprecision of
149 // |kScalingFactorForPositive| is small enough to not push the scaled
150 // |source_value| outside the numeric range of SampleType.
151
152 // Note: This nested if/else structure appears to compile to a
153 // better-performing release binary compared to handling the clipping for
154 // both positive and negative values first.
155 FloatType scaling_factor;
156 if (source_value < 0) {
157 // Apply clipping (aka. clamping).
158 if (source_value <= -1) {
mcasas 2016/06/12 09:41:48 s/-1/-1.0/ ? And/or shouldn't it be called |Float
chfremer 2016/06/13 17:44:12 Thanks for catching that. Fixed.
159 return kMinValue;
160 }
mcasas 2016/06/12 09:41:48 1-line bodies are usually not in {} here and elsew
chfremer 2016/06/13 17:44:12 Done.
161 scaling_factor = ScalingFactors<FloatType>::kForNegativeInput;
162 } else {
163 // Apply clipping (aka. clamping).
164 // As mentioned above, here we must include the case |source_value| == 1.
165 if (source_value >= 1) {
mcasas 2016/06/12 09:41:48 Same here, this smells like a 1.0f constant :)
chfremer 2016/06/13 17:44:12 Done.
166 return kMaxValue;
167 }
168 scaling_factor = ScalingFactors<FloatType>::kForPositiveInput;
169 }
170
171 // Note: It is important to have the cast to SampleType take place _after_
172 // adding |kZeroPointValue|, because the scaled source value may be negative
173 // and SampleType may be an unsigned integer type. The result of casting a
174 // negative float to an unsigned integer is undefined.
175 return static_cast<SampleType>((source_value * scaling_factor) +
176 static_cast<FloatType>(kZeroPointValue));
177 }
178
179 template <typename FloatType>
180 static FloatType ConvertToFloatType(SampleType source_value) {
181 FloatType offset_value =
182 static_cast<FloatType>(source_value - kZeroPointValue);
183
184 // We multiply with the inverse scaling factor instead of dividing by the
185 // scaling factor, because multiplication performs faster than division
186 // on many platforms.
187 return (offset_value < 0.0f)
188 ? (offset_value *
189 ScalingFactors<FloatType>::kInverseForNegativeInput)
190 : (offset_value *
191 ScalingFactors<FloatType>::kInverseForPositiveInput);
192 }
193 };
194
195 // Aliases for commonly used sample formats.
196 using Float32SampleTypeTraits = FloatSampleTypeTraits<float>;
197 using Float64SampleTypeTraits = FloatSampleTypeTraits<double>;
198 using UnsignedInt8SampleTypeTraits = FixedSampleTypeTraits<uint8_t>;
199 using SignedInt16SampleTypeTraits = FixedSampleTypeTraits<int16_t>;
200 using SignedInt32SampleTypeTraits = FixedSampleTypeTraits<int32_t>;
201
202 } // namespace media
203
204 #endif // MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698