Index: media/base/audio_sample_types.h |
diff --git a/media/base/audio_sample_types.h b/media/base/audio_sample_types.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..324e9b38f508045e2b7f022fe12cf72addb6f7b2 |
--- /dev/null |
+++ b/media/base/audio_sample_types.h |
@@ -0,0 +1,169 @@ |
+// Copyright (c) 2016 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. |
+ |
+#ifndef MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ |
+#define MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ |
+ |
+#include <cstdint> |
+#include <limits> |
+ |
+// Provides one class per sample type. Each class satisfies a concept we call |
+// "SampleTypeTraits", which requires that the following publics are provided: |
+// * A typedef |ValueType| specifying the C++ type for storing sample values |
+// * A static method min_value() that returns the minimum sample value |
+// * A static method max_value() that returns the maximum sample value |
+// * A static method zero_point_value() that returns the sample value |
+// representing an amplitude of zero |
+// * A static method convert_from_float32() that takes a float32 sample value |
+// and converts it to |ValueType|. |
+// * A static method convert_to_float32() that takes a value of |ValueType| |
+// to a float32 sample value. |
+ |
+namespace media { |
+ |
+class Linear8BitUnsignedIntSampleTypeTraits { |
+ public: |
+ 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.
|
+ 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.
|
+ static uint8_t max_value() { return 255; } |
+ static uint8_t zero_point_value() { return 128; } |
+ static uint8_t convert_from_float32(float source_value) { |
+ // Apply clipping to avoid having out-of-range values wrap around in the |
+ // uint8_t domain. |
+ if (source_value <= -1.0f) { |
+ return min_value(); |
+ } |
+ if (source_value >= 1.0f) { |
+ return max_value(); |
+ } |
+ // Apply scaling and shift |
+ return static_cast<uint8_t>( |
+ (source_value * get_scale_factor(source_value)) + zero_point_value()); |
+ } |
+ static float convert_to_float32(uint8_t source_value) { |
+ // Apply shift |
+ float shifted_value = static_cast<float>(source_value) - zero_point_value(); |
+ // Apply scaling |
+ return shifted_value / get_scale_factor(shifted_value); |
+ } |
+ |
+ private: |
+ // Since zero_point_value() is not the exact center between |
+ // min_value() and max_value(), we apply a different scaling for positive |
+ // and negative values. |
+ static float get_scale_factor(float input_value) { |
+ return (input_value < 0.0f) ? scale_factor_for_negative() |
+ : scale_factor_for_positive(); |
+ } |
+ static float scale_factor_for_positive() { |
+ return max_value() - zero_point_value(); |
+ } |
+ static float scale_factor_for_negative() { |
+ return zero_point_value() - min_value(); |
+ } |
+}; |
+ |
+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
|
+ public: |
+ typedef int16_t ValueType; |
+ static int16_t min_value() { return std::numeric_limits<int16_t>::min(); } |
+ static int16_t max_value() { return std::numeric_limits<int16_t>::max(); } |
+ static int16_t zero_point_value() { return 0; } |
+ |
+ static int16_t convert_from_float32(float source_value) { |
+ // Apply clipping to avoid having out-of-range values wrap around in the |
+ // int16_t domain. |
+ if (source_value <= -1.0f) { |
+ return min_value(); |
+ } |
+ if (source_value >= 1.0f) { |
+ return max_value(); |
+ } |
+ // Apply scaling and convert type. |
+ return static_cast<int16_t>(source_value * get_scale_factor(source_value)); |
+ } |
+ |
+ static float convert_to_float32(int16_t source_value) { |
+ return source_value / get_scale_factor(source_value); |
+ } |
+ |
+ private: |
+ // Since zero_point_value() is not the exact center between |
+ // min_value() and max_value(), we apply a different scaling for positive |
+ // and negative values. |
+ static float get_scale_factor(float input_value) { |
+ return (input_value < 0.0f) ? (-static_cast<float>(min_value())) |
+ : static_cast<float>(max_value()); |
+ } |
+}; |
+ |
+class Linear32BitSignedIntSampleTypeTraits { |
+ public: |
+ typedef int32_t ValueType; |
+ static int32_t min_value() { return std::numeric_limits<int32_t>::min(); } |
+ static int32_t max_value() { return std::numeric_limits<int32_t>::max(); } |
+ static int32_t zero_point_value() { return 0; } |
+ |
+ static int32_t convert_from_float32(float source_value) { |
+ // Note: Due to the limited precision, float cannot represent the integer |
+ // std::numeric_limits<int32_t>::max(), which we want to use as the scaling |
+ // factor for positive values. When converting to float, this scaling factor |
+ // gets quantized to a neighboring value that float can represent. |
+ // Not sure if this depends on the compiler or platform, but when tested on |
+ // an example workstation, the quantized value came out as |
+ // std::numeric_limits<int32_t>::max() + 1. When multiplied with a |
+ // |source_value| of 1.0f and converted to int32_t, this would cause an |
+ // overflow leading to a large negative value instead. |
+ // To ensure this does not happen, we handle the case of |source_value| == |
+ // 1.0 in the handling for clipping. |
+ // For the case of |source_value| being the largest possible float value |
+ // smaller than 1.0, multiplying by (numeric_limits<int32_t>::max() + 1) |
+ // already results in a value smaller than numeric_limits<int32_t>::max(), |
+ // so this does not cause any issue. |
+ // For the negative case of std::numeric_limits<int32_t>::min() it turns out |
+ // that the quantized value matches the desired value exactly, so there is |
+ // no issue at all. |
+ |
+ // Apply clipping and handling of the 1.0f case |
+ if (source_value <= -1.0f) { |
+ return min_value(); |
+ } |
+ if (source_value >= 1.0f) { |
+ return max_value(); |
+ } |
+ // Apply scaling and convert type. |
+ return static_cast<int32_t>(source_value * get_scale_factor(source_value)); |
+ } |
+ |
+ static float convert_to_float32(int32_t source_value) { |
+ // Note: For the case of |source_value| == numeric_limits<int32_t>::max() |
+ // what happens is that, before the division, |source_value| gets converted |
+ // to float, which causes the same quantization error that we get for the |
+ // scale factor. As a result, we obtain exactly 1.0f, which is what we want. |
+ return source_value / get_scale_factor(source_value); |
+ } |
+ |
+ private: |
+ // Since zero_point_value() is not the exact center between |
+ // min_value() and max_value(), we apply a different scaling for positive |
+ // and negative values. |
+ static float get_scale_factor(float input_value) { |
+ return (input_value < 0.0f) ? (-static_cast<float>(min_value())) |
+ : static_cast<float>(max_value()); |
+ } |
+}; |
+ |
+class Float32SampleTypeTraits { |
+ public: |
+ typedef float ValueType; |
+ static float min_value() { return -1.0f; } |
+ static float max_value() { return 1.0f; } |
+ static float zero_point_value() { return 0.0f; } |
+ static float convert_from_float32(float source_value) { return source_value; } |
+ static float convert_to_float32(float source_value) { return source_value; } |
+}; |
+ |
+} // namespace media |
+ |
+#endif // MEDIA_BASE_AUDIO_SAMPLE_TYPES_H_ |