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 <cstdio>
#include <cstring>
#include <cassert>
#include <stdint.h>

#include "../globals.h"
#include "../Misc/Util.h"
@@ -38,7 +40,7 @@ ADnote::ADnote(ADnoteParameters *pars,
int portamento_,
int midinote_,
bool besilent)
:SynthNote(freq, velocity, portamento_, midinote, besilent)
:SynthNote(freq, velocity, portamento_, midinote_, besilent)
{
tmpwavel = new float [synth->buffersize];
tmpwaver = new float [synth->buffersize];
@@ -139,7 +141,13 @@ ADnote::ADnote(ADnoteParameters *pars,
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 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;
for(int k = 0; k < unison; ++k) {
@@ -1102,30 +1110,39 @@ inline void ADnote::fadein(float *smps) const
/*
* 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)
{
int i, poshi;
float poslo;

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];
float freqlo = oscfreqlo[nvoice][k];
int freqlo = oscfreqlo[nvoice][k] * (1<<24);
float *smps = NoteVoicePar[nvoice].OscilSmp;
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;
if(poslo >= 1.0f) {
poslo -= 1.0f;
poshi++;
}
poshi += freqhi;
poshi += freqhi + (poslo>>24);
poslo &= 0xffffff;
poshi &= synth->oscilsize - 1;
}
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
*/
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)
{
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) {
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 bw,
float gain);
inline float SubFilter(bpfilter &filter, float input) const;
inline void filter(bpfilter &filter, float *smps);

bpfilter *lfilter, *rfilter;


Loading…
Cancel
Save