#include <string.h>
#include <math.h>
-#define PI 3.1415926535897931
-float detune(int coarse, int fine)
+float detune(float base, int coarse, int fine)
{
- return powf(2.0f, (coarse+(fine/100.0f))/12.0f);
+ return base*powf(2.0f, (coarse+(fine/100.0f))/12.0f);
}
uint8 synth(Voice *v, int len, float *mix_buf)
int wave=0;
while (1) {
uint8 op = v->ins[iPC++];
+ //printf("wave %d, op=%d\n", wave, op);
switch (op) {
+ /*
+ case 0: // CONSTANT
+ {
+ float value = ((int8) v->ins[iPC++]/127.0);
+ for (int i=0; i<len; i++) {
+ v->waves[wave][i] = value;
+ }
+ }
+ */
case 1: // SINE
{
- uint8 coarse = v->ins[iPC++];
- uint8 fine = v->ins[iPC++];
- float pitch = v->pitch*detune(coarse, fine);
+ int8 coarse = v->ins[iPC++];
+ int8 fine = v->ins[iPC++];
+ float pitch = detune(v->pitch, coarse, fine);
for (int i=0; i<len; i++) {
- v->waves[wave][i] = 0.5f*sinf(pitch*2.0f*PI*(v->pos+i)/SAMPLE_RATE);
+ v->waves[wave][i] = 0.5f*sinf(pitch*TWOPI_samplerate*(v->pos+i));
}
break;
}
}
break;
}
+
+ case 4: // LPF
+ case 5: // HPF
+ {
+ // TODO: cutoff should be a wave
+ float cutoff = detune(440.0f, v->ins[iPC++], 0);
+ float r = 1.0f/(v->ins[iPC++]);
+
+ for (int i=0; i<len; i++) {
+ float sample = v->waves[wave-1][i];
+
+ // Compute filter coefficients
+ float c, c2,a1,a2,b1,b2;
+
+ // Extraemos algunos calculos que son redundantes en HP y LP
+ float param_tan = PI_samplerate * cutoff;
+ if (op==4) { // Low-pass
+ c=1.0f / tanf(param_tan);
+ c2 = c*c;
+
+ a1 = 1.0f / ( 1.0f + r * c + c2);
+ a2 = 2.0f * a1;
+ b1 = 2.0f * ( 1.0f - c2) * a1;
+ } else { // High-pass
+ c = tanf(-param_tan);
+ c2 = c*c;
+
+ a1 = 1.0f / ( 1.0f + r * c + c2);
+ a2 = -2*a1;
+ b1 = 2.0f * ( c2 - 1.0f) * a1;
+ }
+
+ b2 = ( 1.0f - r*c + c2) * a1;
+
+ // data [0,1,2] = y(0), y(-1), y(-2)
+ // data [3,4] = x(-1), x(-2)
+ float *data = (float*)v->data[wave];
+ data[0] = a1*sample + a2*data[3] + a1*data[4] -
+ b1*data[1] - b2*data[2];
+
+ data[4]=data[3];
+ data[3]=sample;
+ data[2]=data[1];
+ data[1]=data[0];
+
+ v->waves[wave][i] = data[0];
+ }
+ break;
+ }
default:
goto end;
}
#define BUFFER_SIZE 1024
#define SAMPLE_RATE 44100.0f
#define MAX_OPS 30
+#define PI 3.1415926535897931f
+#define PI_samplerate 7.10487365723e-05f
+#define TWOPI_samplerate 0.000142097473145f
/*
An instrument is defined a FORTH-like stack of several operations between
int pos; // position in samples since the start
uint8 active; // { 0 ==> inactive, (not 0) ==> active }
- // data buffer to store, for example, previous inputs/outputs for filtering.
- // 50 bytes should be enough for everyone. Anyway, voices will be created
- // at bss, so they don't count for the file size :)
- uint8 status[50];
+ // data buffer to store, for example, previous inputs/outputs for
+ // filtering. It is as big as the wave buffer. Anyway, voices will be
+ // created at bss, so they don't count for the file size :)
+ uint8 data[MAX_OPS][BUFFER_SIZE*sizeof(float)];
// buffers generated by wave operations
float waves[MAX_OPS][BUFFER_SIZE];
#define SINE(detune_coarse, detune_fine) 1,detune_coarse,detune_fine
#define SUM(a,b) 2,a,b
-#define RING(a,b) 3,a,b
+#define MUL(a,b) 3,a,b
+#define LPF(cutoff, resonance) 4, cutoff,resonance
+#define HPF(cutoff, resonance) 5, cutoff,resonance
extern uint8 synth(Voice *v, int len, float *mix_buf);
-extern float detune(int coarse, int fine);
+extern float detune(float base, int coarse, int fine);
{{45,0,0,0,43,0,0,0,41,0,0,0,40,0,0,0}, 0},
}, // end tracks
{ // begin instrument data
- SINE(0,0),
- SINE(1,10),
- //SINE(3,1),
- RING(0,1),
- RING(1,2),
+ SINE(0,0),
+ SINE(-70,0), // LFO
+ MUL(0,1),
255,
}, // end instrument data
{ // begin playlist