commit 3f8b469efc47b43b22d4bfb9aed3b4df6cbbec43
parent b9038dfef78f01cb7dfefbd560e3b43426b4888e
Author: Friedolino <mkirchn@freenet.de>
Date: Fri, 27 Sep 2019 15:39:35 +0200
added addnote voice parameter to enable AA
Diffstat:
4 files changed, 61 insertions(+), 42 deletions(-)
diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp
@@ -152,6 +152,8 @@ static const Ports voicePorts = {
}},
rToggle(PVolumeminus, rShort("inv."), rDefault(false),
"Signal Inverter"), //do we really need this??
+ rToggle(PAAEnabled, rShort("enable"), rDefault(false),
+ "AntiAliasing Enable"),
rParamZyn(PAmpVelocityScaleFunction, rShort("sense"), rDefault(127),
"Velocity Sensing"),
rToggle(PAmpEnvelopeEnabled, rShort("enable"), rDefault(false),
@@ -570,6 +572,7 @@ void ADnoteVoiceParam::defaults()
PDelay = 0;
volume = -60.0f* (1.0f - 100.0f / 127.0f);
PVolumeminus = 0;
+ PAAEnabled = 0;
PPanning = 64; //center
PDetune = 8192; //8192=0
PCoarseDetune = 0;
diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h
@@ -218,6 +218,9 @@ struct ADnoteVoiceParam {
/* If the Volume negative */
unsigned char PVolumeminus;
+
+ /* if AntiAliasing is enabled */
+ bool PAAEnabled;
/* Velocity sensing */
unsigned char PAmpVelocityScaleFunction;
diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp
@@ -120,6 +120,8 @@ void ADnote::setupVoice(int nvoice)
voice.Enabled = OFF;
return; //the voice is disabled
}
+ NoteVoicePar[nvoice].AAEnabled =
+ pars.VoicePar[nvoice].PAAEnabled;
const int BendAdj = pars.VoicePar[nvoice].PBendAdjust - 64;
if (BendAdj % 24 == 0)
@@ -702,7 +704,10 @@ void ADnote::legatonote(LegatoParams lpars)
if(pars.VoicePar[nvoice].PVolumeminus != 0)
NoteVoicePar[nvoice].Volume = -NoteVoicePar[nvoice].Volume;
-
+
+ NoteVoicePar[nvoice].AAEnabled =
+ pars.VoicePar[nvoice].PAAEnabled;
+
if(pars.VoicePar[nvoice].PPanning == 0) {
NoteVoicePar[nvoice].Panning = getRandomFloat();
} else
@@ -1242,6 +1247,46 @@ inline void ADnote::fadein(float *smps) const
*/
inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
{
+ for(int k = 0; k < unison_size[nvoice]; ++k) {
+ int poshi = oscposhi[nvoice][k];
+ int poslo = oscposlo[nvoice][k] * (1<<24);
+ int freqhi = oscfreqhi[nvoice][k];
+ int freqlo = oscfreqlo[nvoice][k] * (1<<24);
+ float *smps = NoteVoicePar[nvoice].OscilSmp;
+ float *tw = tmpwave_unison[k];
+ assert(oscfreqlo[nvoice][k] < 1.0f);
+ for(int i = 0; i < synth.buffersize; ++i) {
+ tw[i] = (smps[poshi] * ((1<<24) - poslo) + smps[poshi + 1] * poslo)/(1.0f*(1<<24));
+ poslo += freqlo;
+ poshi += freqhi + (poslo>>24);
+ poslo &= 0xffffff;
+ poshi &= synth.oscilsize - 1;
+ }
+ oscposhi[nvoice][k] = poshi;
+ oscposlo[nvoice][k] = poslo/(1.0f*(1<<24));
+ }
+}
+
+
+/*
+ * Computes the Oscillator (Without Modulation) - windowed sinc Interpolation
+ */
+
+/* As the code here is a bit odd due to optimization, here is what happens
+ * First the current possition and frequency are retrieved from the running
+ * state. These are broken up into high and low portions to indicate how many
+ * samples are skipped in one step and how many fractional samples are skipped.
+ * Outside of this method the fractional samples are just handled with floating
+ * point code, but that's a bit slower than it needs to be. In this code the low
+ * portions are known to exist between 0.0 and 1.0 and it is known that they are
+ * stored in single precision floating point IEEE numbers. This implies that
+ * a maximum of 24 bits are significant. The below code does your standard
+ * linear interpolation that you'll see throughout this codebase, but by
+ * sticking to integers for tracking the overflow of the low portion, around 15%
+ * of the execution time was shaved off in the ADnote test.
+ */
+inline void ADnote::ComputeVoiceOscillator_SincInterpolation(int nvoice)
+{
// windowed sinc kernel factor Fs/4, rejection 80dB
const float_t kernel[21] = {
@@ -1286,10 +1331,6 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
float out = 0;
for(int i = 0; i < synth.buffersize; ++i) {
-
- // linear interpolated sampling of waveform for low frequencies
- //tw[i] = (smps[poshi] * ((1<<24) - poslo) + smps[poshi + 1] * poslo)/(1.0f*(1<<24));
-
ovsmpposlo = poslo - 10 * ovsmpfreqlo;
uflow = ovsmpposlo>>24;
ovsmpposhi = poshi - 10 * ovsmpfreqhi - ((0x00 - uflow) & 0xff);
@@ -1323,42 +1364,6 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
}
-
-/*
- * Computes the Oscillator (Without Modulation) - CubicInterpolation
- *
- The differences from the Linear are to little to deserve to be used. This is because I am using a large synth.oscilsize (>512)
-inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){
- int i,poshi;
- float poslo;
-
- poshi=oscposhi[nvoice];
- poslo=oscposlo[nvoice];
- float *smps=NoteVoicePar[nvoice].OscilSmp;
- float xm1,x0,x1,x2,a,b,c;
- for (i=0;i<synth.buffersize;i++){
- xm1=smps[poshi];
- x0=smps[poshi+1];
- x1=smps[poshi+2];
- x2=smps[poshi+3];
- a=(3.0f * (x0-x1) - xm1 + x2) / 2.0f;
- b = 2.0f*x1 + xm1 - (5.0f*x0 + x2) / 2.0f;
- c = (x1 - xm1) / 2.0f;
- tmpwave[i]=(((a * poslo) + b) * poslo + c) * poslo + x0;
- printf("a\n");
- //tmpwave[i]=smps[poshi]*(1.0f-poslo)+smps[poshi+1]*poslo;
- poslo+=oscfreqlo[nvoice];
- if (poslo>=1.0f) {
- poslo-=1.0f;
- poshi++;
- };
- poshi+=oscfreqhi[nvoice];
- poshi&=synth.oscilsize-1;
- };
- oscposhi[nvoice]=poshi;
- oscposlo[nvoice]=poslo;
-};
-*/
/*
* Computes the Oscillator (Mixing)
*/
@@ -1689,7 +1694,8 @@ int ADnote::noteout(float *outl, float *outr)
NoteVoicePar[nvoice].FMEnabled);
break;
default:
- ComputeVoiceOscillator_LinearInterpolation(nvoice);
+ if(NoteVoicePar[nvoice].AAEnabled) ComputeVoiceOscillator_SincInterpolation(nvoice);
+ else ComputeVoiceOscillator_LinearInterpolation(nvoice);
//if (config.cfg.Interpolation) ComputeVoiceOscillator_CubicInterpolation(nvoice);
}
break;
diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h
@@ -86,6 +86,10 @@ class ADnote:public SynthNote
/**Compute the Oscillator's samples.
* Affects tmpwave_unison and updates oscposhi/oscposlo
* @todo remove this declaration if it is commented out*/
+ inline void ComputeVoiceOscillator_SincInterpolation(int nvoice);
+ /**Compute the Oscillator's samples.
+ * Affects tmpwave_unison and updates oscposhi/oscposlo
+ * @todo remove this declaration if it is commented out*/
inline void ComputeVoiceOscillator_CubicInterpolation(int nvoice);
/**Computes the Oscillator samples with mixing.
* updates tmpwave_unison*/
@@ -172,6 +176,9 @@ class ADnote:public SynthNote
void kill(Allocator &memory, const SYNTH_T &synth);
/* If the voice is enabled */
ONOFFTYPE Enabled;
+
+ /* if AntiAliasing is enabled */
+ bool AAEnabled;
/* Voice Type (sound/noise)*/
int noisetype;