#ifndef RESAMPLER_MULTICHANNEL_RESAMPLER_H
#define RESAMPLER_MULTICHANNEL_RESAMPLER_H
#include <memory>
#include <vector>
#include <sys/types.h>
#include <unistd.h>
#ifndef MCR_USE_KAISER
#define MCR_USE_KAISER 0
#endif
#if MCR_USE_KAISER
#include "KaiserWindow.h"
#else
#include "HyperbolicCosineWindow.h"
#endif
#include "ResamplerDefinitions.h"
namespace RESAMPLER_OUTER_NAMESPACE::resampler {
class MultiChannelResampler {
public:
enum class Quality : int32_t {
Fastest,
Low,
Medium,
High,
Best,
};
class Builder {
public:
MultiChannelResampler *build();
Builder *setNumTaps(int32_t numTaps) {
mNumTaps = numTaps;
return this;
}
Builder *setChannelCount(int32_t channelCount) {
mChannelCount = channelCount;
return this;
}
Builder *setInputRate(int32_t inputRate) {
mInputRate = inputRate;
return this;
}
Builder *setOutputRate(int32_t outputRate) {
mOutputRate = outputRate;
return this;
}
Builder *setNormalizedCutoff(float normalizedCutoff) {
mNormalizedCutoff = normalizedCutoff;
return this;
}
int32_t getNumTaps() const {
return mNumTaps;
}
int32_t getChannelCount() const {
return mChannelCount;
}
int32_t getInputRate() const {
return mInputRate;
}
int32_t getOutputRate() const {
return mOutputRate;
}
float getNormalizedCutoff() const {
return mNormalizedCutoff;
}
protected:
int32_t mChannelCount = 1;
int32_t mNumTaps = 16;
int32_t mInputRate = 48000;
int32_t mOutputRate = 48000;
float mNormalizedCutoff = kDefaultNormalizedCutoff;
};
virtual ~MultiChannelResampler() = default;
static MultiChannelResampler *make(int32_t channelCount,
int32_t inputRate,
int32_t outputRate,
Quality quality);
bool isWriteNeeded() const {
return mIntegerPhase >= mDenominator;
}
void writeNextFrame(const float *frame) {
writeFrame(frame);
advanceWrite();
}
void readNextFrame(float *frame) {
readFrame(frame);
advanceRead();
}
int getNumTaps() const {
return mNumTaps;
}
int getChannelCount() const {
return mChannelCount;
}
static float hammingWindow(float radians, float spread);
static float sinc(float radians);
protected:
explicit MultiChannelResampler(const MultiChannelResampler::Builder &builder);
virtual void writeFrame(const float *frame);
virtual void readFrame(float *frame) = 0;
void advanceWrite() {
mIntegerPhase -= mDenominator;
}
void advanceRead() {
mIntegerPhase += mNumerator;
}
void generateCoefficients(int32_t inputRate,
int32_t outputRate,
int32_t numRows,
double phaseIncrement,
float normalizedCutoff);
int32_t getIntegerPhase() {
return mIntegerPhase;
}
static constexpr int kMaxCoefficients = 8 * 1024;
std::vector<float> mCoefficients;
const int mNumTaps;
int mCursor = 0;
std::vector<float> mX; std::vector<float> mSingleFrame; int32_t mIntegerPhase = 0;
int32_t mNumerator = 0;
int32_t mDenominator = 0;
private:
#if MCR_USE_KAISER
KaiserWindow mKaiserWindow;
#else
HyperbolicCosineWindow mCoshWindow;
#endif
static constexpr float kDefaultNormalizedCutoff = 0.70f;
const int mChannelCount;
};
}
#endif