blob: 1dff1a7594b9b812c8a521f9d3ff25e386fe5f5b [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_MIXER_UTILS_H_
#define GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_MIXER_UTILS_H_
#include <type_traits>
#include "garnet/bin/media/audio_core/mixer/constants.h"
#include "garnet/bin/media/audio_core/mixer/gain.h"
namespace media {
namespace audio {
namespace mixer {
// mixer_utils.h is a collection of inline templated utility functions meant to
// be used by mixer implementations and expanded/optimized at compile time in
// order to produce efficient inner mixing loops for all of the different
// variations of source/destination sample type/channel counts.
//
// ScalerType
//
// Enum used to differentiate between different scaling optimization types.
enum class ScalerType {
MUTED, // Massive attenuation. Just skip data.
NE_UNITY, // Non-unity non-zero gain. Scaling is needed.
EQ_UNITY, // Unity gain. Scaling is not needed.
RAMPING, // Scaling is needed, using a non-constant scaler value
};
//
// SampleNormalizer
//
// Template to read and normalize samples into float32 [ -1.0 , 1.0 ] format.
template <typename SrcSampleType, typename Enable = void>
class SampleNormalizer;
template <typename SrcSampleType>
class SampleNormalizer<SrcSampleType,
typename std::enable_if<
std::is_same<SrcSampleType, uint8_t>::value>::type> {
public:
static inline float Read(const SrcSampleType* src) {
return kInt8ToFloat * (static_cast<int32_t>(*src) - kOffsetInt8ToUint8);
}
};
template <typename SrcSampleType>
class SampleNormalizer<SrcSampleType,
typename std::enable_if<
std::is_same<SrcSampleType, int16_t>::value>::type> {
public:
static inline float Read(const SrcSampleType* src) {
return kInt16ToFloat * (*src);
}
};
template <typename SrcSampleType>
class SampleNormalizer<SrcSampleType,
typename std::enable_if<
std::is_same<SrcSampleType, int32_t>::value>::type> {
public:
static inline float Read(const SrcSampleType* src) {
return kInt24In32ToFloat * (*src);
}
};
template <typename SrcSampleType>
class SampleNormalizer<
SrcSampleType,
typename std::enable_if<std::is_same<SrcSampleType, float>::value>::type> {
public:
static inline float Read(const SrcSampleType* src) { return *src; }
};
//
// SampleScaler
//
// Template used to scale normalized sample vals by supplied amplitude scalers.
template <ScalerType ScaleType, typename Enable = void>
class SampleScaler;
template <ScalerType ScaleType>
class SampleScaler<ScaleType, typename std::enable_if<(
ScaleType == ScalerType::MUTED)>::type> {
public:
static inline float Scale(float, Gain::AScale) { return 0.0f; }
};
template <ScalerType ScaleType>
class SampleScaler<ScaleType, typename std::enable_if<
(ScaleType == ScalerType::NE_UNITY) ||
(ScaleType == ScalerType::RAMPING)>::type> {
public:
static inline float Scale(float val, Gain::AScale scale) {
return scale * val;
}
};
template <ScalerType ScaleType>
class SampleScaler<ScaleType, typename std::enable_if<(
ScaleType == ScalerType::EQ_UNITY)>::type> {
public:
static inline float Scale(float val, Gain::AScale) { return val; }
};
//
// SrcReader
//
// Template to read normalized source samples, and combine channels if required.
template <typename SrcSampleType, size_t SrcChanCount, size_t DestChanCount,
typename Enable = void>
class SrcReader;
template <typename SrcSampleType, size_t SrcChanCount, size_t DestChanCount>
class SrcReader<
SrcSampleType, SrcChanCount, DestChanCount,
typename std::enable_if<(SrcChanCount == DestChanCount) ||
((SrcChanCount == 1) && (DestChanCount == 2)),
void>::type> {
public:
static constexpr size_t DestPerSrc = DestChanCount / SrcChanCount;
static inline float Read(const SrcSampleType* src) {
return SampleNormalizer<SrcSampleType>::Read(src);
}
};
template <typename SrcSampleType, size_t SrcChanCount, size_t DestChanCount>
class SrcReader<SrcSampleType, SrcChanCount, DestChanCount,
typename std::enable_if<(SrcChanCount == 2) &&
(DestChanCount == 1)>::type> {
public:
static constexpr size_t DestPerSrc = 1;
static inline float Read(const SrcSampleType* src) {
return 0.5f * (SampleNormalizer<SrcSampleType>::Read(src + 0) +
SampleNormalizer<SrcSampleType>::Read(src + 1));
}
};
//
// DestMixer
//
// Template to mix normalized destination samples with normalized source samples
// based on scaling and accumulation policy.
template <ScalerType ScaleType, bool DoAccumulate, typename Enable = void>
class DestMixer;
template <ScalerType ScaleType, bool DoAccumulate>
class DestMixer<ScaleType, DoAccumulate,
typename std::enable_if<DoAccumulate == false>::type> {
public:
static inline constexpr float Mix(float, float sample, Gain::AScale scale) {
return SampleScaler<ScaleType>::Scale(sample, scale);
}
};
template <ScalerType ScaleType, bool DoAccumulate>
class DestMixer<ScaleType, DoAccumulate,
typename std::enable_if<DoAccumulate == true>::type> {
public:
static inline constexpr float Mix(float dest, float sample,
Gain::AScale scale) {
return SampleScaler<ScaleType>::Scale(sample, scale) + dest;
}
};
} // namespace mixer
} // namespace audio
} // namespace media
#endif // GARNET_BIN_MEDIA_AUDIO_CORE_MIXER_MIXER_UTILS_H_