mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-03 10:12:45 +02:00
Update to v095r08 release.
byuu says: Changelog: - added preliminary WASAPI driver (it's really terrible, though. Patches most welcome.) - all of processor/ updated to auto fn() -> ret syntax - all of gb/ updated to auto fn() -> ret syntax If you want to test the WASAPI driver, then edit ui-tomoko/GNUmakefile, and replace audio.xaudio2 with audio.wasapi Note that the two drivers are incompatible and cannot co-exist (yet. We can probably make it work in the future.) All that's left for the auto fn() -> ret syntax is the NES core and the balanced/performance SNES components. This is kind of a big deal because this syntax change causes diffs between WIPs to go crazy. So the sooner we get this done and out of the way, the better. It's also nice from a consistency standpoint, of course.
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct Buffer {
|
||||
double** sample = nullptr;
|
||||
uint16_t rdoffset = 0;
|
||||
uint16_t wroffset = 0;
|
||||
unsigned channels = 0;
|
||||
Buffer() {
|
||||
}
|
||||
|
||||
void setChannels(unsigned channels) {
|
||||
~Buffer() {
|
||||
setChannels(0);
|
||||
}
|
||||
|
||||
auto setChannels(uint channels) -> void {
|
||||
if(sample) {
|
||||
for(unsigned c = 0; c < this->channels; c++) {
|
||||
for(auto c : range(this->channels)) {
|
||||
if(sample[c]) delete[] sample[c];
|
||||
}
|
||||
delete[] sample;
|
||||
@@ -18,22 +20,22 @@ struct Buffer {
|
||||
if(channels == 0) return;
|
||||
|
||||
sample = new double*[channels];
|
||||
for(unsigned c = 0; c < channels; c++) {
|
||||
for(auto c : range(channels)) {
|
||||
sample[c] = new double[65536]();
|
||||
}
|
||||
}
|
||||
|
||||
inline double& read(unsigned channel, signed offset = 0) {
|
||||
return sample[channel][(uint16_t)(rdoffset + offset)];
|
||||
inline auto read(uint channel, int offset = 0) -> double& {
|
||||
return sample[channel][(uint16)(rdoffset + offset)];
|
||||
}
|
||||
|
||||
inline double& write(unsigned channel, signed offset = 0) {
|
||||
return sample[channel][(uint16_t)(wroffset + offset)];
|
||||
inline auto write(uint channel, int offset = 0) -> double& {
|
||||
return sample[channel][(uint16)(wroffset + offset)];
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
for(unsigned c = 0; c < channels; c++) {
|
||||
for(unsigned n = 0; n < 65536; n++) {
|
||||
inline auto clear() -> void {
|
||||
for(auto c : range(channels)) {
|
||||
for(auto n : range(65536)) {
|
||||
sample[c][n] = 0;
|
||||
}
|
||||
}
|
||||
@@ -41,12 +43,10 @@ struct Buffer {
|
||||
wroffset = 0;
|
||||
}
|
||||
|
||||
Buffer() {
|
||||
}
|
||||
|
||||
~Buffer() {
|
||||
setChannels(0);
|
||||
}
|
||||
double** sample = nullptr;
|
||||
uint16 rdoffset = 0;
|
||||
uint16 wroffset = 0;
|
||||
uint channels = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -6,24 +6,22 @@
|
||||
|
||||
namespace nall {
|
||||
|
||||
//precision: can be float, double or long double
|
||||
#define real float
|
||||
|
||||
struct DSP;
|
||||
|
||||
struct Resampler {
|
||||
DSP& dsp;
|
||||
real frequency;
|
||||
|
||||
virtual void setFrequency() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void sample() = 0;
|
||||
Resampler(DSP& dsp) : dsp(dsp) {}
|
||||
virtual ~Resampler() {}
|
||||
|
||||
virtual auto setFrequency() -> void = 0;
|
||||
virtual auto clear() -> void = 0;
|
||||
virtual auto sample() -> void = 0;
|
||||
|
||||
DSP& dsp;
|
||||
double frequency = 44100.0;
|
||||
};
|
||||
|
||||
struct DSP {
|
||||
enum class ResampleEngine : unsigned {
|
||||
enum class ResampleEngine : uint {
|
||||
Nearest,
|
||||
Linear,
|
||||
Cosine,
|
||||
@@ -33,24 +31,48 @@ struct DSP {
|
||||
Sinc,
|
||||
};
|
||||
|
||||
inline void setChannels(unsigned channels);
|
||||
inline void setPrecision(unsigned precision);
|
||||
inline void setFrequency(real frequency); //inputFrequency
|
||||
inline void setVolume(real volume);
|
||||
inline void setBalance(real balance);
|
||||
|
||||
inline void setResampler(ResampleEngine resamplingEngine);
|
||||
inline void setResamplerFrequency(real frequency); //outputFrequency
|
||||
|
||||
inline void sample(signed channel[]);
|
||||
inline bool pending();
|
||||
inline void read(signed channel[]);
|
||||
|
||||
inline void clear();
|
||||
inline DSP();
|
||||
inline ~DSP();
|
||||
|
||||
inline auto setChannels(uint channels) -> void;
|
||||
inline auto setPrecision(uint precision) -> void;
|
||||
inline auto setFrequency(double frequency) -> void; //inputFrequency
|
||||
inline auto setVolume(double volume) -> void;
|
||||
inline auto setBalance(double balance) -> void;
|
||||
|
||||
inline auto setResampler(ResampleEngine resamplingEngine) -> void;
|
||||
inline auto setResamplerFrequency(double frequency) -> void; //outputFrequency
|
||||
|
||||
inline auto sample(int channel[]) -> void;
|
||||
inline auto pending() const -> bool;
|
||||
inline auto read(int channel[]) -> void;
|
||||
|
||||
inline auto clear() -> void;
|
||||
|
||||
protected:
|
||||
inline auto write(double channel[]) -> void;
|
||||
inline auto adjustVolume() -> void;
|
||||
inline auto adjustBalance() -> void;
|
||||
inline auto clamp(const uint bits, const int input) -> int;
|
||||
|
||||
struct Settings {
|
||||
uint channels;
|
||||
uint precision;
|
||||
double frequency;
|
||||
double volume;
|
||||
double balance;
|
||||
|
||||
//internal
|
||||
double intensity;
|
||||
double intensityInverse;
|
||||
} settings;
|
||||
|
||||
Resampler* resampler = nullptr;
|
||||
|
||||
#include "buffer.hpp"
|
||||
Buffer buffer;
|
||||
Buffer output;
|
||||
|
||||
friend class ResampleNearest;
|
||||
friend class ResampleLinear;
|
||||
friend class ResampleCosine;
|
||||
@@ -58,29 +80,6 @@ protected:
|
||||
friend class ResampleAverage;
|
||||
friend class ResampleHermite;
|
||||
friend class ResampleSinc;
|
||||
|
||||
struct Settings {
|
||||
unsigned channels;
|
||||
unsigned precision;
|
||||
real frequency;
|
||||
real volume;
|
||||
real balance;
|
||||
|
||||
//internal
|
||||
real intensity;
|
||||
real intensityInverse;
|
||||
} settings;
|
||||
|
||||
Resampler* resampler = nullptr;
|
||||
inline void write(real channel[]);
|
||||
|
||||
#include "buffer.hpp"
|
||||
Buffer buffer;
|
||||
Buffer output;
|
||||
|
||||
inline void adjustVolume();
|
||||
inline void adjustBalance();
|
||||
inline signed clamp(const unsigned bits, const signed x);
|
||||
};
|
||||
|
||||
#include "resample/nearest.hpp"
|
||||
@@ -92,59 +91,6 @@ protected:
|
||||
#include "resample/sinc.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
void DSP::sample(signed channel[]) {
|
||||
for(unsigned c = 0; c < settings.channels; c++) {
|
||||
buffer.write(c) = (real)channel[c] * settings.intensityInverse;
|
||||
}
|
||||
buffer.wroffset++;
|
||||
resampler->sample();
|
||||
}
|
||||
|
||||
bool DSP::pending() {
|
||||
return output.rdoffset != output.wroffset;
|
||||
}
|
||||
|
||||
void DSP::read(signed channel[]) {
|
||||
adjustVolume();
|
||||
adjustBalance();
|
||||
|
||||
for(unsigned c = 0; c < settings.channels; c++) {
|
||||
channel[c] = clamp(settings.precision, output.read(c) * settings.intensity);
|
||||
}
|
||||
output.rdoffset++;
|
||||
}
|
||||
|
||||
void DSP::write(real channel[]) {
|
||||
for(unsigned c = 0; c < settings.channels; c++) {
|
||||
output.write(c) = channel[c];
|
||||
}
|
||||
output.wroffset++;
|
||||
}
|
||||
|
||||
void DSP::adjustVolume() {
|
||||
for(unsigned c = 0; c < settings.channels; c++) {
|
||||
output.read(c) *= settings.volume;
|
||||
}
|
||||
}
|
||||
|
||||
void DSP::adjustBalance() {
|
||||
if(settings.channels != 2) return; //TODO: support > 2 channels
|
||||
if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
|
||||
if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
|
||||
}
|
||||
|
||||
signed DSP::clamp(const unsigned bits, const signed x) {
|
||||
const signed b = 1U << (bits - 1);
|
||||
const signed m = (1U << (bits - 1)) - 1;
|
||||
return (x > m) ? m : (x < -b) ? -b : x;
|
||||
}
|
||||
|
||||
void DSP::clear() {
|
||||
buffer.clear();
|
||||
output.clear();
|
||||
resampler->clear();
|
||||
}
|
||||
|
||||
DSP::DSP() {
|
||||
setResampler(ResampleEngine::Hermite);
|
||||
setResamplerFrequency(44100.0);
|
||||
@@ -162,7 +108,58 @@ DSP::~DSP() {
|
||||
if(resampler) delete resampler;
|
||||
}
|
||||
|
||||
#undef real
|
||||
auto DSP::sample(int channel[]) -> void {
|
||||
for(auto c : range(settings.channels)) {
|
||||
buffer.write(c) = (double)channel[c] * settings.intensityInverse;
|
||||
}
|
||||
buffer.wroffset++;
|
||||
resampler->sample();
|
||||
}
|
||||
|
||||
auto DSP::pending() const -> bool {
|
||||
return output.rdoffset != output.wroffset;
|
||||
}
|
||||
|
||||
auto DSP::read(int channel[]) -> void {
|
||||
adjustVolume();
|
||||
adjustBalance();
|
||||
|
||||
for(auto c : range(settings.channels)) {
|
||||
channel[c] = clamp(settings.precision, output.read(c) * settings.intensity);
|
||||
}
|
||||
output.rdoffset++;
|
||||
}
|
||||
|
||||
auto DSP::write(double channel[]) -> void {
|
||||
for(auto c : range(settings.channels)) {
|
||||
output.write(c) = channel[c];
|
||||
}
|
||||
output.wroffset++;
|
||||
}
|
||||
|
||||
auto DSP::adjustVolume() -> void {
|
||||
for(auto c : range(settings.channels)) {
|
||||
output.read(c) *= settings.volume;
|
||||
}
|
||||
}
|
||||
|
||||
auto DSP::adjustBalance() -> void {
|
||||
if(settings.channels != 2) return; //TODO: support > 2 channels
|
||||
if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance;
|
||||
if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance;
|
||||
}
|
||||
|
||||
auto DSP::clamp(const uint bits, const int x) -> int {
|
||||
const int b = 1U << (bits - 1);
|
||||
const int m = (1U << (bits - 1)) - 1;
|
||||
return (x > m) ? m : (x < -b) ? -b : x;
|
||||
}
|
||||
|
||||
auto DSP::clear() -> void {
|
||||
buffer.clear();
|
||||
output.clear();
|
||||
resampler->clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,46 +1,48 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleAverage : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
inline void sampleLinear();
|
||||
ResampleAverage(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
inline auto sampleLinear() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleAverage::setFrequency() {
|
||||
auto ResampleAverage::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleAverage::clear() {
|
||||
auto ResampleAverage::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleAverage::sample() {
|
||||
auto ResampleAverage::sample() -> void {
|
||||
//can only average if input frequency >= output frequency
|
||||
if(step < 1.0) return sampleLinear();
|
||||
|
||||
fraction += 1.0;
|
||||
|
||||
real scalar = 1.0;
|
||||
double scalar = 1.0;
|
||||
if(fraction > step) scalar = 1.0 - (fraction - step);
|
||||
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
dsp.output.write(c) += dsp.buffer.read(c) * scalar;
|
||||
}
|
||||
|
||||
if(fraction >= step) {
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
dsp.output.write(c) /= step;
|
||||
}
|
||||
dsp.output.wroffset++;
|
||||
|
||||
fraction -= step;
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
dsp.output.write(c) = dsp.buffer.read(c) * fraction;
|
||||
}
|
||||
}
|
||||
@@ -48,15 +50,15 @@ void ResampleAverage::sample() {
|
||||
dsp.buffer.rdoffset++;
|
||||
}
|
||||
|
||||
void ResampleAverage::sampleLinear() {
|
||||
auto ResampleAverage::sampleLinear() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -1);
|
||||
real b = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -1);
|
||||
double b = dsp.buffer.read(n, -0);
|
||||
|
||||
real mu = fraction;
|
||||
double mu = fraction;
|
||||
|
||||
channel[n] = a * (1.0 - mu) + b * mu;
|
||||
}
|
||||
|
@@ -1,33 +1,35 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleCosine : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
ResampleCosine(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleCosine::setFrequency() {
|
||||
auto ResampleCosine::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleCosine::clear() {
|
||||
auto ResampleCosine::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleCosine::sample() {
|
||||
auto ResampleCosine::sample() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -1);
|
||||
real b = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -1);
|
||||
double b = dsp.buffer.read(n, -0);
|
||||
|
||||
real mu = fraction;
|
||||
double mu = fraction;
|
||||
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
|
||||
|
||||
channel[n] = a * (1.0 - mu) + b * mu;
|
||||
|
@@ -1,40 +1,42 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleCubic : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
ResampleCubic(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleCubic::setFrequency() {
|
||||
auto ResampleCubic::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleCubic::clear() {
|
||||
auto ResampleCubic::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleCubic::sample() {
|
||||
auto ResampleCubic::sample() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -3);
|
||||
real b = dsp.buffer.read(n, -2);
|
||||
real c = dsp.buffer.read(n, -1);
|
||||
real d = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -3);
|
||||
double b = dsp.buffer.read(n, -2);
|
||||
double c = dsp.buffer.read(n, -1);
|
||||
double d = dsp.buffer.read(n, -0);
|
||||
|
||||
real mu = fraction;
|
||||
double mu = fraction;
|
||||
|
||||
real A = d - c - a + b;
|
||||
real B = a - b - A;
|
||||
real C = c - a;
|
||||
real D = b;
|
||||
double A = d - c - a + b;
|
||||
double B = a - b - A;
|
||||
double C = c - a;
|
||||
double D = b;
|
||||
|
||||
channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D;
|
||||
}
|
||||
|
@@ -1,38 +1,40 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleHermite : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
ResampleHermite(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleHermite::setFrequency() {
|
||||
auto ResampleHermite::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleHermite::clear() {
|
||||
auto ResampleHermite::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleHermite::sample() {
|
||||
auto ResampleHermite::sample() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -3);
|
||||
real b = dsp.buffer.read(n, -2);
|
||||
real c = dsp.buffer.read(n, -1);
|
||||
real d = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -3);
|
||||
double b = dsp.buffer.read(n, -2);
|
||||
double c = dsp.buffer.read(n, -1);
|
||||
double d = dsp.buffer.read(n, -0);
|
||||
|
||||
const real tension = 0.0; //-1 = low, 0 = normal, +1 = high
|
||||
const real bias = 0.0; //-1 = left, 0 = even, +1 = right
|
||||
const double tension = 0.0; //-1 = low, 0 = normal, +1 = high
|
||||
const double bias = 0.0; //-1 = left, 0 = even, +1 = right
|
||||
|
||||
real mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
|
||||
double mu1, mu2, mu3, m0, m1, a0, a1, a2, a3;
|
||||
|
||||
mu1 = fraction;
|
||||
mu2 = mu1 * mu1;
|
||||
|
@@ -1,33 +1,35 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleLinear : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
ResampleLinear(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleLinear::setFrequency() {
|
||||
auto ResampleLinear::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleLinear::clear() {
|
||||
auto ResampleLinear::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleLinear::sample() {
|
||||
auto ResampleLinear::sample() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -1);
|
||||
real b = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -1);
|
||||
double b = dsp.buffer.read(n, -0);
|
||||
|
||||
real mu = fraction;
|
||||
double mu = fraction;
|
||||
|
||||
channel[n] = a * (1.0 - mu) + b * mu;
|
||||
}
|
||||
|
@@ -1,33 +1,35 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
struct ResampleNearest : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
ResampleNearest(DSP& dsp) : Resampler(dsp) {}
|
||||
|
||||
real fraction;
|
||||
real step;
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
double fraction;
|
||||
double step;
|
||||
};
|
||||
|
||||
void ResampleNearest::setFrequency() {
|
||||
auto ResampleNearest::setFrequency() -> void {
|
||||
fraction = 0.0;
|
||||
step = dsp.settings.frequency / frequency;
|
||||
}
|
||||
|
||||
void ResampleNearest::clear() {
|
||||
auto ResampleNearest::clear() -> void {
|
||||
fraction = 0.0;
|
||||
}
|
||||
|
||||
void ResampleNearest::sample() {
|
||||
auto ResampleNearest::sample() -> void {
|
||||
while(fraction <= 1.0) {
|
||||
real channel[dsp.settings.channels];
|
||||
double channel[dsp.settings.channels];
|
||||
|
||||
for(unsigned n = 0; n < dsp.settings.channels; n++) {
|
||||
real a = dsp.buffer.read(n, -1);
|
||||
real b = dsp.buffer.read(n, -0);
|
||||
for(auto n : range(dsp.settings.channels)) {
|
||||
double a = dsp.buffer.read(n, -1);
|
||||
double b = dsp.buffer.read(n, -0);
|
||||
|
||||
real mu = fraction;
|
||||
double mu = fraction;
|
||||
|
||||
channel[n] = mu < 0.5 ? a : b;
|
||||
}
|
||||
|
@@ -3,51 +3,61 @@
|
||||
#include "lib/sinc.hpp"
|
||||
|
||||
struct ResampleSinc : Resampler {
|
||||
inline void setFrequency();
|
||||
inline void clear();
|
||||
inline void sample();
|
||||
inline ResampleSinc(DSP& dsp);
|
||||
inline ~ResampleSinc();
|
||||
|
||||
inline auto setFrequency() -> void;
|
||||
inline auto clear() -> void;
|
||||
inline auto sample() -> void;
|
||||
|
||||
private:
|
||||
inline void remakeSinc();
|
||||
SincResample* sinc_resampler[8];
|
||||
SincResample* sincResampler[8] = {0};
|
||||
};
|
||||
|
||||
void ResampleSinc::setFrequency() {
|
||||
ResampleSinc::ResampleSinc(DSP& dsp) : Resampler(dsp) {
|
||||
for(auto n : range(8)) {
|
||||
sincResampler[n] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ResampleSinc::~ResampleSinc() {
|
||||
for(auto n : range(8)) {
|
||||
if(sincResampler[n]) delete sincResampler[n];
|
||||
}
|
||||
}
|
||||
|
||||
auto ResampleSinc::setFrequency() -> void {
|
||||
remakeSinc();
|
||||
}
|
||||
|
||||
void ResampleSinc::clear() {
|
||||
auto ResampleSinc::clear() -> void {
|
||||
remakeSinc();
|
||||
}
|
||||
|
||||
void ResampleSinc::sample() {
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
sinc_resampler[c]->write(dsp.buffer.read(c));
|
||||
auto ResampleSinc::sample() -> void {
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
sincResampler[c]->write(dsp.buffer.read(c));
|
||||
}
|
||||
|
||||
if(sinc_resampler[0]->output_avail()) {
|
||||
if(sincResampler[0]->output_avail()) {
|
||||
do {
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
dsp.output.write(c) = sinc_resampler[c]->read();
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
dsp.output.write(c) = sincResampler[c]->read();
|
||||
}
|
||||
dsp.output.wroffset++;
|
||||
} while(sinc_resampler[0]->output_avail());
|
||||
} while(sincResampler[0]->output_avail());
|
||||
}
|
||||
|
||||
dsp.buffer.rdoffset++;
|
||||
}
|
||||
|
||||
ResampleSinc::ResampleSinc(DSP& dsp) : Resampler(dsp) {
|
||||
for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = nullptr;
|
||||
}
|
||||
|
||||
void ResampleSinc::remakeSinc() {
|
||||
auto ResampleSinc::remakeSinc() -> void {
|
||||
assert(dsp.settings.channels < 8);
|
||||
|
||||
for(unsigned c = 0; c < dsp.settings.channels; c++) {
|
||||
if(sinc_resampler[c]) delete sinc_resampler[c];
|
||||
sinc_resampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH);
|
||||
for(auto c : range(dsp.settings.channels)) {
|
||||
if(sincResampler[c]) delete sincResampler[c];
|
||||
sincResampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,35 +1,35 @@
|
||||
#ifdef NALL_DSP_INTERNAL_HPP
|
||||
|
||||
void DSP::setChannels(unsigned channels) {
|
||||
assert(channels > 0);
|
||||
auto DSP::setChannels(uint channels) -> void {
|
||||
channels = max(1u, channels);
|
||||
buffer.setChannels(channels);
|
||||
output.setChannels(channels);
|
||||
settings.channels = channels;
|
||||
}
|
||||
|
||||
void DSP::setPrecision(unsigned precision) {
|
||||
auto DSP::setPrecision(uint precision) -> void {
|
||||
settings.precision = precision;
|
||||
settings.intensity = 1 << (settings.precision - 1);
|
||||
settings.intensityInverse = 1.0 / settings.intensity;
|
||||
}
|
||||
|
||||
void DSP::setFrequency(real frequency) {
|
||||
auto DSP::setFrequency(double frequency) -> void {
|
||||
settings.frequency = frequency;
|
||||
resampler->setFrequency();
|
||||
}
|
||||
|
||||
void DSP::setVolume(real volume) {
|
||||
auto DSP::setVolume(double volume) -> void {
|
||||
settings.volume = volume;
|
||||
}
|
||||
|
||||
void DSP::setBalance(real balance) {
|
||||
auto DSP::setBalance(double balance) -> void {
|
||||
settings.balance = balance;
|
||||
}
|
||||
|
||||
void DSP::setResampler(ResampleEngine engine) {
|
||||
auto DSP::setResampler(ResampleEngine engine) -> void {
|
||||
if(resampler) delete resampler;
|
||||
|
||||
switch(engine) {
|
||||
switch(engine) { default:
|
||||
case ResampleEngine::Nearest: resampler = new ResampleNearest(*this); return;
|
||||
case ResampleEngine::Linear: resampler = new ResampleLinear (*this); return;
|
||||
case ResampleEngine::Cosine: resampler = new ResampleCosine (*this); return;
|
||||
@@ -38,11 +38,9 @@ void DSP::setResampler(ResampleEngine engine) {
|
||||
case ResampleEngine::Average: resampler = new ResampleAverage(*this); return;
|
||||
case ResampleEngine::Sinc: resampler = new ResampleSinc (*this); return;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
void DSP::setResamplerFrequency(real frequency) {
|
||||
auto DSP::setResamplerFrequency(double frequency) -> void {
|
||||
resampler->frequency = frequency;
|
||||
resampler->setFrequency();
|
||||
}
|
||||
|
Reference in New Issue
Block a user