OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016 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 #ifndef MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ | |
6 #define MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ | |
7 | |
8 #include <cstdint> | |
9 #include <limits> | |
10 | |
11 // Provides one class per sample type. Each class satisfies a concept we call | |
12 // "SampleTypeTraits", which requires that the following publics are provided: | |
13 // * A typedef |ValueType| specifying the C++ type for storing sample values | |
14 // * A static method min_value() that returns the minimum sample value | |
15 // * A static method max_value() that returns the maximum sample value | |
16 // * A static method zero_point_value() that returns the sample value | |
17 // representing an amplitude of zero | |
18 // * A static method convert_from_float32() that takes a float32 sample value | |
19 // and converts it to |ValueType|. | |
20 // * A static method convert_to_float32() that takes a value of |ValueType| | |
21 // to a float32 sample value. | |
22 | |
23 namespace media { | |
24 | |
25 class Linear8BitUnsignedIntSampleTypeTraits { | |
26 public: | |
27 typedef uint8_t ValueType; | |
miu
2016/06/07 22:16:36
Chromium's preferring the new syntax for new code:
chfremer
2016/06/08 18:46:39
Done.
| |
28 static uint8_t min_value() { return 0; } | |
miu
2016/06/07 22:16:36
All the zero-arg static methods in these classes s
chfremer
2016/06/08 18:46:39
Done.
| |
29 static uint8_t max_value() { return 255; } | |
30 static uint8_t zero_point_value() { return 128; } | |
31 static uint8_t convert_from_float32(float source_value) { | |
32 // Apply clipping to avoid having out-of-range values wrap around in the | |
33 // uint8_t domain. | |
34 if (source_value <= -1.0f) { | |
35 return min_value(); | |
36 } | |
37 if (source_value >= 1.0f) { | |
38 return max_value(); | |
39 } | |
40 // Apply scaling and shift | |
41 return static_cast<uint8_t>( | |
42 (source_value * get_scale_factor(source_value)) + zero_point_value()); | |
43 } | |
44 static float convert_to_float32(uint8_t source_value) { | |
45 // Apply shift | |
46 float shifted_value = static_cast<float>(source_value) - zero_point_value(); | |
47 // Apply scaling | |
48 return shifted_value / get_scale_factor(shifted_value); | |
49 } | |
50 | |
51 private: | |
52 // Since zero_point_value() is not the exact center between | |
53 // min_value() and max_value(), we apply a different scaling for positive | |
54 // and negative values. | |
55 static float get_scale_factor(float input_value) { | |
56 return (input_value < 0.0f) ? scale_factor_for_negative() | |
57 : scale_factor_for_positive(); | |
58 } | |
59 static float scale_factor_for_positive() { | |
60 return max_value() - zero_point_value(); | |
61 } | |
62 static float scale_factor_for_negative() { | |
63 return zero_point_value() - min_value(); | |
64 } | |
65 }; | |
66 | |
67 class Linear16BitSignedIntSampleTypeTraits { | |
miu
2016/06/07 22:16:36
Seems all these classes for the integer types are
chfremer
2016/06/08 18:46:39
Thanks for this beautiful suggestion.
I will creat
| |
68 public: | |
69 typedef int16_t ValueType; | |
70 static int16_t min_value() { return std::numeric_limits<int16_t>::min(); } | |
71 static int16_t max_value() { return std::numeric_limits<int16_t>::max(); } | |
72 static int16_t zero_point_value() { return 0; } | |
73 | |
74 static int16_t convert_from_float32(float source_value) { | |
75 // Apply clipping to avoid having out-of-range values wrap around in the | |
76 // int16_t domain. | |
77 if (source_value <= -1.0f) { | |
78 return min_value(); | |
79 } | |
80 if (source_value >= 1.0f) { | |
81 return max_value(); | |
82 } | |
83 // Apply scaling and convert type. | |
84 return static_cast<int16_t>(source_value * get_scale_factor(source_value)); | |
85 } | |
86 | |
87 static float convert_to_float32(int16_t source_value) { | |
88 return source_value / get_scale_factor(source_value); | |
89 } | |
90 | |
91 private: | |
92 // Since zero_point_value() is not the exact center between | |
93 // min_value() and max_value(), we apply a different scaling for positive | |
94 // and negative values. | |
95 static float get_scale_factor(float input_value) { | |
96 return (input_value < 0.0f) ? (-static_cast<float>(min_value())) | |
97 : static_cast<float>(max_value()); | |
98 } | |
99 }; | |
100 | |
101 class Linear32BitSignedIntSampleTypeTraits { | |
102 public: | |
103 typedef int32_t ValueType; | |
104 static int32_t min_value() { return std::numeric_limits<int32_t>::min(); } | |
105 static int32_t max_value() { return std::numeric_limits<int32_t>::max(); } | |
106 static int32_t zero_point_value() { return 0; } | |
107 | |
108 static int32_t convert_from_float32(float source_value) { | |
109 // Note: Due to the limited precision, float cannot represent the integer | |
110 // std::numeric_limits<int32_t>::max(), which we want to use as the scaling | |
111 // factor for positive values. When converting to float, this scaling factor | |
112 // gets quantized to a neighboring value that float can represent. | |
113 // Not sure if this depends on the compiler or platform, but when tested on | |
114 // an example workstation, the quantized value came out as | |
115 // std::numeric_limits<int32_t>::max() + 1. When multiplied with a | |
116 // |source_value| of 1.0f and converted to int32_t, this would cause an | |
117 // overflow leading to a large negative value instead. | |
118 // To ensure this does not happen, we handle the case of |source_value| == | |
119 // 1.0 in the handling for clipping. | |
120 // For the case of |source_value| being the largest possible float value | |
121 // smaller than 1.0, multiplying by (numeric_limits<int32_t>::max() + 1) | |
122 // already results in a value smaller than numeric_limits<int32_t>::max(), | |
123 // so this does not cause any issue. | |
124 // For the negative case of std::numeric_limits<int32_t>::min() it turns out | |
125 // that the quantized value matches the desired value exactly, so there is | |
126 // no issue at all. | |
127 | |
128 // Apply clipping and handling of the 1.0f case | |
129 if (source_value <= -1.0f) { | |
130 return min_value(); | |
131 } | |
132 if (source_value >= 1.0f) { | |
133 return max_value(); | |
134 } | |
135 // Apply scaling and convert type. | |
136 return static_cast<int32_t>(source_value * get_scale_factor(source_value)); | |
137 } | |
138 | |
139 static float convert_to_float32(int32_t source_value) { | |
140 // Note: For the case of |source_value| == numeric_limits<int32_t>::max() | |
141 // what happens is that, before the division, |source_value| gets converted | |
142 // to float, which causes the same quantization error that we get for the | |
143 // scale factor. As a result, we obtain exactly 1.0f, which is what we want. | |
144 return source_value / get_scale_factor(source_value); | |
145 } | |
146 | |
147 private: | |
148 // Since zero_point_value() is not the exact center between | |
149 // min_value() and max_value(), we apply a different scaling for positive | |
150 // and negative values. | |
151 static float get_scale_factor(float input_value) { | |
152 return (input_value < 0.0f) ? (-static_cast<float>(min_value())) | |
153 : static_cast<float>(max_value()); | |
154 } | |
155 }; | |
156 | |
157 class Float32SampleTypeTraits { | |
158 public: | |
159 typedef float ValueType; | |
160 static float min_value() { return -1.0f; } | |
161 static float max_value() { return 1.0f; } | |
162 static float zero_point_value() { return 0.0f; } | |
163 static float convert_from_float32(float source_value) { return source_value; } | |
164 static float convert_to_float32(float source_value) { return source_value; } | |
165 }; | |
166 | |
167 } // namespace media | |
168 | |
169 #endif // MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ | |
OLD | NEW |