| Index: media/base/audio_sample_conversion.h
|
| diff --git a/media/base/audio_sample_conversion.h b/media/base/audio_sample_conversion.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..836120b6edd232ae3c64ea66a55a38125867b3fa
|
| --- /dev/null
|
| +++ b/media/base/audio_sample_conversion.h
|
| @@ -0,0 +1,163 @@
|
| +// Copyright 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_CONVERSION_H_
|
| +#define MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_
|
| +
|
| +#include <limits>
|
| +
|
| +namespace media {
|
| +
|
| +namespace internal {
|
| +
|
| +template <typename T>
|
| +struct IntegerSampleTraits {
|
| + typedef T promoted_type;
|
| + static const T bias = 0;
|
| + static promoted_type min() { return std::numeric_limits<T>::min(); }
|
| + static promoted_type max() { return std::numeric_limits<T>::max(); }
|
| +};
|
| +
|
| +template <>
|
| +struct IntegerSampleTraits<uint8_t> {
|
| + typedef int16_t promoted_type;
|
| + static const uint8_t bias = 128;
|
| + static promoted_type min() { return std::numeric_limits<int8_t>::min(); }
|
| + static promoted_type max() { return std::numeric_limits<int8_t>::max(); }
|
| +};
|
| +
|
| +struct FloatToIntRounded {
|
| + template <class T>
|
| + static T FromPositive(float x) {
|
| + return static_cast<T>(x + 0.5f);
|
| + }
|
| +
|
| + template <class T>
|
| + static T FromNegative(float x) {
|
| + return static_cast<T>(x - 0.5f);
|
| + }
|
| +};
|
| +
|
| +struct FloatToIntTruncated {
|
| + template <class T>
|
| + static T FromPositive(float x) {
|
| + return static_cast<T>(x);
|
| + }
|
| +
|
| + template <class T>
|
| + static T FromNegative(float x) {
|
| + return static_cast<T>(x);
|
| + }
|
| +};
|
| +
|
| +template <typename Format, typename Rounding>
|
| +struct InterleaveOneChannelHelper {
|
| + static void process(const float* channel_data,
|
| + int start_frame,
|
| + int frames,
|
| + Format* dest,
|
| + int channel_count,
|
| + int ch) {
|
| + using Traits = internal::IntegerSampleTraits<Format>;
|
| + using Promoted = typename Traits::promoted_type;
|
| +
|
| + const Promoted min = Traits::min();
|
| + const Promoted max = Traits::max();
|
| +
|
| + for (int i = start_frame, offset = ch; i < start_frame + frames;
|
| + ++i, offset += channel_count) {
|
| + const float v = channel_data[i];
|
| +
|
| + Promoted sample;
|
| + if (v < 0)
|
| + sample =
|
| + v <= -1 ? min : Rounding::template FromNegative<Promoted>(-v * min);
|
| + else
|
| + sample =
|
| + v >= 1 ? max : Rounding::template FromPositive<Promoted>(v * max);
|
| +
|
| + dest[offset] = static_cast<Format>(sample) + Traits::bias;
|
| + }
|
| + }
|
| +};
|
| +
|
| +template <typename Rounding>
|
| +struct InterleaveOneChannelHelper<float, Rounding> {
|
| + static void process(const float* channel_data,
|
| + int start_frame,
|
| + int frames,
|
| + float* dest,
|
| + int channel_count,
|
| + int ch) {
|
| + for (int i = start_frame, offset = ch; i < start_frame + frames;
|
| + ++i, offset += channel_count) {
|
| + dest[offset] = channel_data[i];
|
| + }
|
| + }
|
| +};
|
| +
|
| +} // namespace internal
|
| +
|
| +template <typename Format>
|
| +void DeinterleaveOneChannel(const Format* source,
|
| + int start_frame,
|
| + int frames,
|
| + float* channel_data,
|
| + int channel_count,
|
| + int ch) {
|
| + using Traits = internal::IntegerSampleTraits<Format>;
|
| + using Promoted = typename Traits::promoted_type;
|
| +
|
| + const float min = 1.0f / Traits::min();
|
| + const float max = 1.0f / Traits::max();
|
| +
|
| + for (int i = start_frame, offset = ch; i < start_frame + frames;
|
| + ++i, offset += channel_count) {
|
| + const Promoted v = static_cast<Promoted>(source[offset]) - Traits::bias;
|
| + channel_data[i] = v * (v < 0 ? -min : max);
|
| + }
|
| +}
|
| +
|
| +template <>
|
| +inline void DeinterleaveOneChannel<float>(const float* source,
|
| + int start_frame,
|
| + int frames,
|
| + float* channel_data,
|
| + int channel_count,
|
| + int ch) {
|
| + for (int i = start_frame, offset = ch; i < start_frame + frames;
|
| + ++i, offset += channel_count) {
|
| + channel_data[i] = source[offset];
|
| + }
|
| +}
|
| +
|
| +template <typename Format>
|
| +void InterleaveOneChannel(const float* channel_data,
|
| + int start_frame,
|
| + int frames,
|
| + Format* dest,
|
| + int channel_count,
|
| + int ch) {
|
| + internal::InterleaveOneChannelHelper<
|
| + Format, internal::FloatToIntTruncated>::process(channel_data, start_frame,
|
| + frames, dest,
|
| + channel_count, ch);
|
| +}
|
| +
|
| +template <typename Format>
|
| +void InterleaveOneChannelRounded(const float* channel_data,
|
| + int start_frame,
|
| + int frames,
|
| + Format* dest,
|
| + int channel_count,
|
| + int ch) {
|
| + internal::InterleaveOneChannelHelper<
|
| + Format, internal::FloatToIntRounded>::process(channel_data, start_frame,
|
| + frames, dest, channel_count,
|
| + ch);
|
| +}
|
| +
|
| +} // namespace media
|
| +
|
| +#endif // MEDIA_BASE_AUDIO_SAMPLE_CONVERSION_H_
|
|
|