| Index: services/media/framework/lpcm_util.cc
|
| diff --git a/services/media/framework/lpcm_util.cc b/services/media/framework/lpcm_util.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca208079aaab9868841ac11377fcaadaad854be7
|
| --- /dev/null
|
| +++ b/services/media/framework/lpcm_util.cc
|
| @@ -0,0 +1,169 @@
|
| +// 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.
|
| +
|
| +#include "base/logging.h"
|
| +#include "services/media/framework/formatting.h"
|
| +#include "services/media/framework/lpcm_util.h"
|
| +
|
| +namespace mojo {
|
| +namespace media {
|
| +
|
| +// LpcmUtil implementation that processes samples of type T.
|
| +template<typename T>
|
| +class LpcmUtilImpl : public LpcmUtil {
|
| + public:
|
| + ~LpcmUtilImpl();
|
| +
|
| + void Silence(void* buffer, uint64_t frame_count) const override;
|
| +
|
| + void Copy(const void* in, void* out, uint64_t frame_count) const override;
|
| +
|
| + void Mix(const void* in, void* out, uint64_t frame_count) const override;
|
| +
|
| + void Interleave(
|
| + const void* in,
|
| + uint64_t in_byte_count,
|
| + void* out,
|
| + uint64_t frame_count) const override;
|
| +
|
| + private:
|
| + LpcmUtilImpl(const LpcmStreamType& stream_type);
|
| +
|
| + LpcmStreamType stream_type_;
|
| +
|
| + friend class LpcmUtil;
|
| +};
|
| +
|
| +std::unique_ptr<LpcmUtil> LpcmUtil::Create(const LpcmStreamType& stream_type) {
|
| + LpcmUtil* result;
|
| + switch (stream_type.sample_format()) {
|
| + case LpcmStreamType::SampleFormat::kUnsigned8:
|
| + case LpcmStreamType::SampleFormat::kAny:
|
| + result = new LpcmUtilImpl<uint8_t>(stream_type);
|
| + break;
|
| + case LpcmStreamType::SampleFormat::kSigned16:
|
| + result = new LpcmUtilImpl<int16_t>(stream_type);
|
| + break;
|
| + case LpcmStreamType::SampleFormat::kSigned24In32:
|
| + result = new LpcmUtilImpl<int32_t>(stream_type);
|
| + break;
|
| + case LpcmStreamType::SampleFormat::kFloat:
|
| + result = new LpcmUtilImpl<float>(stream_type);
|
| + break;
|
| + default:
|
| + NOTREACHED()
|
| + << "unsupported sample format " << stream_type.sample_format();
|
| + result = nullptr;
|
| + break;
|
| + }
|
| +
|
| + return std::unique_ptr<LpcmUtil>(result);
|
| +}
|
| +
|
| +template<typename T>
|
| +LpcmUtilImpl<T>::LpcmUtilImpl(const LpcmStreamType& stream_type) :
|
| + stream_type_(stream_type) {}
|
| +
|
| +template<typename T>
|
| +LpcmUtilImpl<T>::~LpcmUtilImpl() {}
|
| +
|
| +template<typename T>
|
| +void LpcmUtilImpl<T>::Silence(void* buffer, uint64_t frame_count) const {
|
| + T* sample = reinterpret_cast<T*>(buffer);
|
| + for (
|
| + uint64_t sample_countdown = frame_count * stream_type_.channels();
|
| + sample_countdown != 0;
|
| + --sample_countdown) {
|
| + *sample = 0;
|
| + sample++;
|
| + }
|
| +}
|
| +
|
| +template<>
|
| +void LpcmUtilImpl<uint8_t>::Silence(void* buffer, uint64_t frame_count) const {
|
| + std::memset(buffer, 0x80, frame_count * stream_type_.bytes_per_frame());
|
| +}
|
| +
|
| +template<>
|
| +void LpcmUtilImpl<int16_t>::Silence(void* buffer, uint64_t frame_count) const {
|
| + std::memset(buffer, 0, frame_count * stream_type_.bytes_per_frame());
|
| +}
|
| +
|
| +template<>
|
| +void LpcmUtilImpl<int32_t>::Silence(void* buffer, uint64_t frame_count) const {
|
| + std::memset(buffer, 0, frame_count * stream_type_.bytes_per_frame());
|
| +}
|
| +
|
| +template<typename T>
|
| +void LpcmUtilImpl<T>::Copy(const void* in, void* out, uint64_t frame_count)
|
| + const {
|
| + std::memcpy(out, in, stream_type_.min_buffer_size(frame_count));
|
| +}
|
| +
|
| +template<typename T>
|
| +void LpcmUtilImpl<T>::Mix(const void* in, void* out, uint64_t frame_count)
|
| + const {
|
| + const T* in_sample = reinterpret_cast<const T*>(in);
|
| + T* out_sample = reinterpret_cast<T*>(out);
|
| + for (
|
| + uint64_t sample_countdown = frame_count * stream_type_.channels();
|
| + sample_countdown != 0;
|
| + --sample_countdown) {
|
| + *out_sample += *in_sample; // TODO(dalesat): Limit.
|
| + out_sample++;
|
| + in_sample++;
|
| + }
|
| +}
|
| +
|
| +template<>
|
| +void LpcmUtilImpl<uint8_t>::Mix(const void* in, void* out, uint64_t frame_count)
|
| + const {
|
| + const uint8_t* in_sample = reinterpret_cast<const uint8_t*>(in);
|
| + uint8_t* out_sample = reinterpret_cast<uint8_t*>(out);
|
| + for (
|
| + uint64_t sample_countdown = frame_count * stream_type_.channels();
|
| + sample_countdown != 0;
|
| + --sample_countdown) {
|
| + *out_sample = uint8_t(uint16_t(*out_sample) + uint16_t(*in_sample) - 0x80);
|
| + // TODO(dalesat): Limit.
|
| + out_sample++;
|
| + in_sample++;
|
| + }
|
| +}
|
| +
|
| +template<typename T>
|
| +void LpcmUtilImpl<T>::Interleave(
|
| + const void* in,
|
| + uint64_t in_byte_count,
|
| + void* out,
|
| + uint64_t frame_count) const {
|
| + DCHECK(in);
|
| + DCHECK(in_byte_count);
|
| + DCHECK(out);
|
| + DCHECK(frame_count);
|
| +
|
| + uint32_t channels = stream_type_.channels();
|
| + DCHECK(channels);
|
| + DCHECK(in_byte_count % stream_type_.bytes_per_frame() == 0);
|
| + DCHECK(in_byte_count >= frame_count * stream_type_.bytes_per_frame());
|
| + uint64_t in_channel_stride = in_byte_count / stream_type_.bytes_per_frame();
|
| +
|
| + const T* in_channel = reinterpret_cast<const T*>(in);
|
| + T* out_channel = reinterpret_cast<T*>(out);
|
| +
|
| + for (uint32_t channel = channels; channel != 0; --channel) {
|
| + const T* in_sample = in_channel;
|
| + T* out_sample = out_channel;
|
| + for (uint64_t frame = frame_count; frame != 0; --frame) {
|
| + *out_sample = *in_sample;
|
| + ++in_sample;
|
| + out_sample += channels;
|
| + }
|
| + in_channel += in_channel_stride;
|
| + ++out_channel;
|
| + }
|
| +}
|
| +
|
| +} // namespace media
|
| +} // namespace mojo
|
|
|