Merge branch 'tildearrow:master' into master

This commit is contained in:
TheDuccinator 2022-12-18 00:56:35 -08:00 committed by GitHub
commit 0a7d631065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 2 deletions

View File

@ -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.");

View File

@ -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.

View File

@ -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) {

View File

@ -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);

View File

@ -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;