Chromium Code Reviews| 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_ |