mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-18 06:20:17 +00:00
Merge branch 'tildearrow:master' into master
This commit is contained in:
commit
0a7d631065
5 changed files with 101 additions and 2 deletions
|
@ -24,6 +24,7 @@
|
|||
|
||||
float* DivFilterTables::cubicTable=NULL;
|
||||
float* DivFilterTables::sincTable=NULL;
|
||||
float* DivFilterTables::sincTable8=NULL;
|
||||
float* DivFilterTables::sincIntegralTable=NULL;
|
||||
|
||||
// portions from Schism Tracker (scripts/lutgen.c)
|
||||
|
@ -44,7 +45,7 @@ float* DivFilterTables::getCubicTable() {
|
|||
return cubicTable;
|
||||
}
|
||||
|
||||
float* DivFilterTables:: getSincTable() {
|
||||
float* DivFilterTables::getSincTable() {
|
||||
if (sincTable==NULL) {
|
||||
logD("initializing sinc table.");
|
||||
sincTable=new float[65536];
|
||||
|
@ -64,6 +65,26 @@ float* DivFilterTables:: getSincTable() {
|
|||
return sincTable;
|
||||
}
|
||||
|
||||
float* DivFilterTables::getSincTable8() {
|
||||
if (sincTable8==NULL) {
|
||||
logD("initializing sinc table (8).");
|
||||
sincTable8=new float[32768];
|
||||
|
||||
sincTable8[0]=1.0f;
|
||||
for (int i=1; i<32768; i++) {
|
||||
int mapped=((i&8191)<<2)|(i>>13);
|
||||
double x=(double)i*M_PI/8192.0;
|
||||
sincTable8[mapped]=sin(x)/x;
|
||||
}
|
||||
|
||||
for (int i=0; i<32768; i++) {
|
||||
int mapped=((i&8191)<<2)|(i>>13);
|
||||
sincTable8[mapped]*=pow(cos(M_PI*(double)i/65536.0),2.0);
|
||||
}
|
||||
}
|
||||
return sincTable8;
|
||||
}
|
||||
|
||||
float* DivFilterTables::getSincIntegralTable() {
|
||||
if (sincIntegralTable==NULL) {
|
||||
logD("initializing sinc integral table.");
|
||||
|
|
|
@ -21,6 +21,7 @@ class DivFilterTables {
|
|||
public:
|
||||
static float* cubicTable;
|
||||
static float* sincTable;
|
||||
static float* sincTable8;
|
||||
static float* sincIntegralTable;
|
||||
|
||||
/**
|
||||
|
@ -35,6 +36,12 @@ class DivFilterTables {
|
|||
*/
|
||||
static float* getSincTable();
|
||||
|
||||
/**
|
||||
* get a 8192x4 one-side sine-windowed sinc table.
|
||||
* @return the table.
|
||||
*/
|
||||
static float* getSincTable8();
|
||||
|
||||
/**
|
||||
* get a 8192x8 one-side sine-windowed sinc integral table.
|
||||
* @return the table.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#include "pcmdac.h"
|
||||
#include "../engine.h"
|
||||
#include "../filter.h"
|
||||
#include <math.h>
|
||||
|
||||
// to ease the driver, freqency register is a 8.16 counter relative to output sample rate
|
||||
|
@ -103,7 +104,50 @@ void DivPlatformPCMDAC::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
if (chan[0].audPos>=0 && chan[0].audPos<(int)s->samples) {
|
||||
output=s->data16[chan[0].audPos];
|
||||
int s_4=((chan[0].audPos-4)>=0)?s->data16[chan[0].audPos-4]:0;
|
||||
int s_3=((chan[0].audPos-3)>=0)?s->data16[chan[0].audPos-3]:0;
|
||||
int s_2=((chan[0].audPos-2)>=0)?s->data16[chan[0].audPos-2]:0;
|
||||
int s_1=((chan[0].audPos-1)>=0)?s->data16[chan[0].audPos-1]:0;
|
||||
int s0=s->data16[chan[0].audPos];
|
||||
int s1=((chan[0].audPos+1)<(int)s->samples)?s->data16[chan[0].audPos+1]:0;
|
||||
int s2=((chan[0].audPos+2)<(int)s->samples)?s->data16[chan[0].audPos+2]:0;
|
||||
int s3=((chan[0].audPos+3)<(int)s->samples)?s->data16[chan[0].audPos+3]:0;
|
||||
switch (interp) {
|
||||
case 1: // linear
|
||||
output=s0+((s1-s0)*(chan[0].audSub&0xffff)>>16);
|
||||
break;
|
||||
case 2: { // cubic
|
||||
float* cubicTable=DivFilterTables::getCubicTable();
|
||||
float* t=&cubicTable[((chan[0].audSub&0xffff)>>6)<<2];
|
||||
float result=(float)s_1*t[0]+(float)s0*t[1]+(float)s1*t[2]+(float)s2*t[3];
|
||||
if (result<-32768) result=-32768;
|
||||
if (result>32767) result=32767;
|
||||
output=result;
|
||||
break;
|
||||
}
|
||||
case 3: { // sinc
|
||||
float* sincTable=DivFilterTables::getSincTable8();
|
||||
float* t1=&sincTable[(8191-((chan[0].audSub&0xffff)>>3))<<2];
|
||||
float* t2=&sincTable[((chan[0].audSub&0xffff)>>3)<<2];
|
||||
float result=(
|
||||
s_4*t2[3]+
|
||||
s_3*t2[2]+
|
||||
s_2*t2[1]+
|
||||
s_1*t2[0]+
|
||||
s0*t1[0]+
|
||||
s1*t1[1]+
|
||||
s2*t1[2]+
|
||||
s3*t1[3]
|
||||
);
|
||||
if (result<-32768) result=-32768;
|
||||
if (result>32767) result=32767;
|
||||
output=result;
|
||||
break;
|
||||
}
|
||||
default: // none
|
||||
output=s0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
chan[0].sample=-1;
|
||||
|
@ -398,6 +442,7 @@ void DivPlatformPCMDAC::setFlags(const DivConfig& flags) {
|
|||
chipClock=rate;
|
||||
outDepth=(flags.getInt("outDepth",15))&15;
|
||||
outStereo=flags.getBool("stereo",true);
|
||||
interp=flags.getInt("interpolation",0);
|
||||
}
|
||||
|
||||
int DivPlatformPCMDAC::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
|
|
|
@ -55,6 +55,12 @@ class DivPlatformPCMDAC: public DivDispatch {
|
|||
DivDispatchOscBuffer* oscBuf;
|
||||
bool isMuted;
|
||||
int outDepth;
|
||||
// valid values:
|
||||
// - 0: none
|
||||
// - 1: linear
|
||||
// - 2: cubic spline
|
||||
// - 3: sinc
|
||||
int interp;
|
||||
bool outStereo;
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
|
|
@ -1227,6 +1227,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
// default to 44100Hz 16-bit stereo
|
||||
int sampRate=flags.getInt("rate",44100);
|
||||
int bitDepth=flags.getInt("outDepth",15)+1;
|
||||
int interpolation=flags.getInt("interpolation",0);
|
||||
bool stereo=flags.getBool("stereo",false);
|
||||
|
||||
ImGui::Text("Output rate:");
|
||||
|
@ -1245,11 +1246,30 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
altered=true;
|
||||
}
|
||||
|
||||
ImGui::Text("Interpolation:");
|
||||
if (ImGui::RadioButton("None",interpolation==0)) {
|
||||
interpolation=0;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("Linear",interpolation==1)) {
|
||||
interpolation=1;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("Cubic",interpolation==2)) {
|
||||
interpolation=2;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("Sinc",interpolation==3)) {
|
||||
interpolation=3;
|
||||
altered=true;
|
||||
}
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("rate",sampRate);
|
||||
flags.set("outDepth",bitDepth-1);
|
||||
flags.set("stereo",stereo);
|
||||
flags.set("interpolation",interpolation);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue