First filter test. Sounds weird :P
authorslack <slack@codemaniacs.com>
Fri, 12 Jun 2009 14:40:23 +0000 (16:40 +0200)
committerslack <slack@codemaniacs.com>
Fri, 12 Jun 2009 14:40:23 +0000 (16:40 +0200)
play.c
synth.c
synth.h
thesong.h

diff --git a/play.c b/play.c
index 7f7a9db5f902137b3f2a80fb3daf7f4a48662750..d07f2073f86f588903d330f31171b04923561066 100644 (file)
--- a/play.c
+++ b/play.c
@@ -70,7 +70,7 @@ void play(void *s, uint8 *stream, int len)
 
                     uint8 j = last_voice_used; 
                     last_voice_used = (last_voice_used + 1) % NUM_VOICES;
-                    voices[j].pitch = 440.0f*detune(note-21,0);
+                    voices[j].pitch = detune(440.0f,note-21,0);
                     voices[j].pos = buf_start;
                     voices[j].ins = &song->instrument_data[cur_trk->instrument];
                     voices[j].vol = 0.19921875f*vol;
diff --git a/synth.c b/synth.c
index d7774c70b840e682ebe57d3e900aec04a30caaa0..77cfc825c44e4b0299b00688a4da04351c4ad525 100644 (file)
--- a/synth.c
+++ b/synth.c
@@ -2,11 +2,10 @@
 #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)
@@ -21,15 +20,25 @@ 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;
             }
@@ -47,7 +56,56 @@ uint8 synth(Voice *v, int len, float *mix_buf)
                 }
                 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;
         }
diff --git a/synth.h b/synth.h
index 17660d77105ae69af03d486f84ee3be93a847ac1..32611be1da5567eac897015c004aaf3ce1296a48 100644 (file)
--- a/synth.h
+++ b/synth.h
@@ -6,6 +6,9 @@
 #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
@@ -30,10 +33,10 @@ typedef struct
         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];
@@ -41,10 +44,12 @@ typedef struct
 
 #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);
 
 
 
index 77abaeeb3a6042d86e1110e928e9a62bb0a48bca..93bf344034743fe87fcdee66cb12d974d6baab52 100644 (file)
--- a/thesong.h
+++ b/thesong.h
@@ -8,11 +8,9 @@ Song thesong={
         {{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