Browse Source

part 4

tags/1.9.4
falkTX 10 years ago
parent
commit
8aeefdc5f0
3 changed files with 62 additions and 33 deletions
  1. +33
    -16
      source/modules/native-plugins/zynaddsubfx/Synth/ADnote.cpp
  2. +29
    -16
      source/modules/native-plugins/zynaddsubfx/Synth/SUBnote.cpp
  3. +0
    -1
      source/modules/native-plugins/zynaddsubfx/Synth/SUBnote.h

+ 33
- 16
source/modules/native-plugins/zynaddsubfx/Synth/ADnote.cpp View File

@@ -23,6 +23,8 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <cassert>
#include <stdint.h>


#include "../globals.h" #include "../globals.h"
#include "../Misc/Util.h" #include "../Misc/Util.h"
@@ -38,7 +40,7 @@ ADnote::ADnote(ADnoteParameters *pars,
int portamento_, int portamento_,
int midinote_, int midinote_,
bool besilent) bool besilent)
:SynthNote(freq, velocity, portamento_, midinote, besilent)
:SynthNote(freq, velocity, portamento_, midinote_, besilent)
{ {
tmpwavel = new float [synth->buffersize]; tmpwavel = new float [synth->buffersize];
tmpwaver = new float [synth->buffersize]; tmpwaver = new float [synth->buffersize];
@@ -139,7 +141,13 @@ ADnote::ADnote(ADnoteParameters *pars,
for(int k = 0; k < unison; ++k) { for(int k = 0; k < unison; ++k) {
float step = (k / (float) (unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform float step = (k / (float) (unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform
float val = step + (RND * 2.0f - 1.0f) / (unison - 1); float val = step + (RND * 2.0f - 1.0f) / (unison - 1);
unison_values[k] = limit(val, min, max);
unison_values[k] = val;
if (min > val) {
min = val;
}
if (max < val) {
max = val;
}
} }
float diff = max - min; float diff = max - min;
for(int k = 0; k < unison; ++k) { for(int k = 0; k < unison; ++k) {
@@ -1102,30 +1110,39 @@ inline void ADnote::fadein(float *smps) const
/* /*
* Computes the Oscillator (Without Modulation) - LinearInterpolation * Computes the Oscillator (Without Modulation) - LinearInterpolation
*/ */

/* 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_LinearInterpolation(int nvoice) inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice)
{ {
int i, poshi;
float poslo;

for(int k = 0; k < unison_size[nvoice]; ++k) { for(int k = 0; k < unison_size[nvoice]; ++k) {
poshi = oscposhi[nvoice][k];
poslo = oscposlo[nvoice][k];
int poshi = oscposhi[nvoice][k];
int poslo = oscposlo[nvoice][k] * (1<<24);
int freqhi = oscfreqhi[nvoice][k]; int freqhi = oscfreqhi[nvoice][k];
float freqlo = oscfreqlo[nvoice][k];
int freqlo = oscfreqlo[nvoice][k] * (1<<24);
float *smps = NoteVoicePar[nvoice].OscilSmp; float *smps = NoteVoicePar[nvoice].OscilSmp;
float *tw = tmpwave_unison[k]; float *tw = tmpwave_unison[k];
for(i = 0; i < synth->buffersize; ++i) {
tw[i] = smps[poshi] * (1.0f - poslo) + smps[poshi + 1] * poslo;
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; poslo += freqlo;
if(poslo >= 1.0f) {
poslo -= 1.0f;
poshi++;
}
poshi += freqhi;
poshi += freqhi + (poslo>>24);
poslo &= 0xffffff;
poshi &= synth->oscilsize - 1; poshi &= synth->oscilsize - 1;
} }
oscposhi[nvoice][k] = poshi; oscposhi[nvoice][k] = poshi;
oscposlo[nvoice][k] = poslo;
oscposlo[nvoice][k] = poslo/(1.0f*(1<<24));
} }
} }




+ 29
- 16
source/modules/native-plugins/zynaddsubfx/Synth/SUBnote.cpp View File

@@ -322,30 +322,43 @@ void SUBnote::initfilter(bpfilter &filter,
/* /*
* Do the filtering * Do the filtering
*/ */
inline float SUBnote::SubFilter(bpfilter &filter, const float input) const

inline void SubFilterA(const float coeff[4], float &src, float work[4])
{ {
const float out = input * filter.b0 + filter.b2 * filter.xn2
- filter.a1 * filter.yn1 - filter.a2 * filter.yn2;
filter.xn2 = filter.xn1;
filter.xn1 = input;
filter.yn2 = filter.yn1;
filter.yn1 = out;
return out;
work[3] = src*coeff[0]+work[1]*coeff[1]+work[2]*coeff[2]+work[3]*coeff[3];
work[1] = src;
src = work[3];
} }


inline void SubFilterB(const float coeff[4], float &src, float work[4])
{
work[2] = src*coeff[0]+work[0]*coeff[1]+work[3]*coeff[2]+work[2]*coeff[3];
work[0] = src;
src = work[2];
}

//This dance is designed to minimize unneeded memory operations which can result
//in quite a bit of wasted time
void SUBnote::filter(bpfilter &filter, float *smps) void SUBnote::filter(bpfilter &filter, float *smps)
{ {
assert(synth->buffersize % 8 == 0); assert(synth->buffersize % 8 == 0);
float coeff[4] = {filter.b0, filter.b2, -filter.a1, -filter.a2};
float work[4] = {filter.xn1, filter.xn2, filter.yn1, filter.yn2};

for(int i = 0; i < synth->buffersize; i += 8) { for(int i = 0; i < synth->buffersize; i += 8) {
smps[i] = SubFilter(filter, smps[i]);
smps[i + 1] = SubFilter(filter, smps[i + 1]);
smps[i + 2] = SubFilter(filter, smps[i + 2]);
smps[i + 3] = SubFilter(filter, smps[i + 3]);
smps[i + 4] = SubFilter(filter, smps[i + 4]);
smps[i + 5] = SubFilter(filter, smps[i + 5]);
smps[i + 6] = SubFilter(filter, smps[i + 6]);
smps[i + 7] = SubFilter(filter, smps[i + 7]);
SubFilterA(coeff, smps[i + 0], work);
SubFilterB(coeff, smps[i + 1], work);
SubFilterA(coeff, smps[i + 2], work);
SubFilterB(coeff, smps[i + 3], work);
SubFilterA(coeff, smps[i + 4], work);
SubFilterB(coeff, smps[i + 5], work);
SubFilterA(coeff, smps[i + 6], work);
SubFilterB(coeff, smps[i + 7], work);
} }
filter.xn1 = work[0];
filter.xn2 = work[1];
filter.yn1 = work[2];
filter.yn2 = work[3];
} }


/* /*


+ 0
- 1
source/modules/native-plugins/zynaddsubfx/Synth/SUBnote.h View File

@@ -95,7 +95,6 @@ class SUBnote:public SynthNote
float freq, float freq,
float bw, float bw,
float gain); float gain);
inline float SubFilter(bpfilter &filter, float input) const;
inline void filter(bpfilter &filter, float *smps); inline void filter(bpfilter &filter, float *smps);


bpfilter *lfilter, *rfilter; bpfilter *lfilter, *rfilter;


Loading…
Cancel
Save