CC=gcc -m32
-CFLAGS=-std=c99 -Os -Wall -s \
+CFLAGS=-std=c99 -Os -Wall -g \
-march=pentium4 -ffast-math -nodefaultlibs \
-fomit-frame-pointer -fno-strict-aliasing -fno-common \
-fpeephole2 -fexpensive-optimizations -frerun-cse-after-loop \
gzip -c lolailo > lolailo.gz
ls -l lolailo.gz
-lolailo: lolailo.o synth.o play.o
+lolailo: lolailo.o synth.o play.o thesong.o
lolailo.o: lolailo.c synth.h sizedtypes.h play.h thesong.h song.h
play.o: play.c sizedtypes.h play.h synth.h song.h
synth.o: synth.c synth.h sizedtypes.h
+thesong.o: thesong.c thesong.h song.h sizedtypes.h
clean:
rm -f *.o lolailo lolailo.gz
uint8 j = last_voice_used;
last_voice_used = (last_voice_used + 1) % NUM_VOICES;
+ memset(&voices[j], 0, sizeof(Voice));
voices[j].pitch = detune(440.0f,note-21,0);
voices[j].pos = buf_start;
voices[j].ins = &song->instrument_data[cur_trk->instrument];
#!/bin/bash
-python -c "print 'play() ->', 0x$(objdump -t play.o | grep play$ | awk '{print $5}'), 'bytes'"
-python -c "print 'synth() ->', 0x$(objdump -t synth.o | grep synth$ | awk '{print $5}'), 'bytes'"
-python -c "print 'thesong ->', 0x$(objdump -t lolailo.o | grep thesong$ | awk '{print $5}'), 'bytes'"
+for i in *.o; do
+ objcopy -O binary $i $i.bin
+ ORIG_SIZE=$(cat $i.bin | wc -c)
+ 7z a -tGZIP -mx=9 -mfb=64 $i.bin.gz $i.bin > /dev/null
+ COMPRESSED_SIZE=$(cat $i.bin.gz | wc -c)
+ printf "%10s: %4d -> %4d bytes\n" ${i%.o} $ORIG_SIZE $COMPRESSED_SIZE
+done
+cat *.bin > all.bin
+ORIG_SIZE=$(cat all.bin | wc -c)
+7z a -tGZIP -mx=9 -mfb=64 all.bin.gz all.bin > /dev/null
+COMPRESSED_SIZE=$(cat all.bin.gz | wc -c)
+printf "%10s: %d -> %d bytes\n" TOTAL $ORIG_SIZE $COMPRESSED_SIZE
+rm *.bin
+rm *.bin.gz
#include "synth.h"
#include <string.h>
#include <math.h>
-
+#include <stdlib.h>
float detune(float base, int coarse, int fine)
{
int iPC=0; // instrument program counter
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++) {
+ uint8 ins = v->ins[iPC++];
+ uint8 op1 = v->ins[iPC++];
+ uint8 op2 = v->ins[iPC++];
+ //printf("wave %d, ins=%d (%d, %d)\n", wave, ins, op1, op2);
+ for (int i=0; i<len; i++) {
+ float time=(v->pos+i)*invSAMPLE_RATE;
+ switch (ins) {
+ case CONST:
+ {
+ float value = ((int8) op1/100.0);
v->waves[wave][i] = value;
+ break;
}
- }
- */
- case 1: // SINE
- {
- 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*TWOPI_samplerate*(v->pos+i));
+
+ case SINE:
+ {
+ // op1: signed coarse detune, op2: signed fine detune
+ float pitch = detune(v->pitch, (int8) op1, (int8) op2);
+ v->waves[wave][i] = sinf(pitch*TWOPI*time);
+ break;
}
- break;
- }
-
- case 2: // SUM
- case 3: // RING
- {
- uint8 wave1 = v->ins[iPC++];
- uint8 wave2 = v->ins[iPC++];
- for (int i=0; i<len; i++) {
- if (op == 2)
- v->waves[wave][i] = v->waves[wave1][i]+v->waves[wave2][i];
+
+ case SQUARE:
+ {
+ float pitch = detune(v->pitch, (int8) op1, 0);
+ float pw = op2/100.0f;
+ float period = 1.0/pitch;
+ if (fmodf(time, period) > (period*pw))
+ v->waves[wave][i] = 1.0f;
else
- v->waves[wave][i] = v->waves[wave1][i]*v->waves[wave2][i];
+ v->waves[wave][i] = -1.0f;
+ break;
+ }
+ case NOISE:
+ v->waves[wave][i] = rand()/(float)RAND_MAX;
+ break;
+ /*
+ case TO_0_1:
+ v->waves[wave][i] = v->waves[wave][i-1]*0.5f+0.5f;
+ break;
+ */
+
+ case SUM:
+ case MUL:
+ {
+ // op1,2: wave indices to sum/mul
+ if (ins == SUM)
+ v->waves[wave][i] = v->waves[op1][i]+v->waves[op2][i];
+ else
+ v->waves[wave][i] = v->waves[op1][i]*v->waves[op2][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++) {
+ case LPF:
+ case HPF:
+ {
+ // TODO: cutoff should be a wave
+ // op1, op2: cutoff, resonance
+ float cutoff = detune(1.0f, op1, 0);
+ float r = (op2)/100.0f;
+
+ //printf("op1=%d, op2=%d, cutoff=%f; r=%f\n", op1, op2, cutoff, r);
+
float sample = v->waves[wave-1][i];
// Compute filter coefficients
// Extraemos algunos calculos que son redundantes en HP y LP
float param_tan = PI_samplerate * cutoff;
- if (op==4) { // Low-pass
+ if (ins==LPF) { // Low-pass
c=1.0f / tanf(param_tan);
c2 = c*c;
data[1]=data[0];
v->waves[wave][i] = data[0];
+ break;
}
- break;
+ default:
+ goto end;
}
- default:
- goto end;
}
-
++wave;
}
#define SAMPLE_RATE 44100.0f
#define MAX_OPS 30
#define PI 3.1415926535897931f
+#define TWOPI 6.2831853071795862f
#define PI_samplerate 7.10487365723e-05f
#define TWOPI_samplerate 0.000142097473145f
+#define invSAMPLE_RATE 0.000022675736961451248f
/*
An instrument is defined a FORTH-like stack of several operations between
float waves[MAX_OPS][BUFFER_SIZE];
} Voice;
-#define SINE(detune_coarse, detune_fine) 1,detune_coarse,detune_fine
-#define SUM(a,b) 2,a,b
-#define MUL(a,b) 3,a,b
-#define LPF(cutoff, resonance) 4, cutoff,resonance
-#define HPF(cutoff, resonance) 5, cutoff,resonance
+#define CONST 0
+#define SINE 1
+#define SQUARE 2
+#define SAW 3
+#define SUM 4
+#define MUL 5
+#define LPF 6
+#define HPF 7
+#define TO_0_1 8
+#define NOISE 9
+#define END 255
extern uint8 synth(Voice *v, int len, float *mix_buf);
extern float detune(float base, int coarse, int fine);
--- /dev/null
+#include "thesong.h"
+#include "synth.h"
+
+Song thesong={
+ { // begin patterns
+ {0x01, 0x00, 0x00, 0x00},
+ }, // end patterns
+ { // begin tracks
+ {{45,0,0,0,43,0,0,0,41,0,0,0,40,0,0,0}, 0},
+ }, // end tracks
+ { // begin instrument data
+ SINE,-70,0,
+ NOISE,0,0,
+ MUL,0,1,
+ END,
+ }, // end instrument data
+ { // begin playlist
+ 0,255,
+ }, // end playlist
+};
+
+
+#ifndef THESONG_H
+#define THESONG_H
+
#include "song.h"
-Song thesong={
- { // begin patterns
- {0x01, 0x00, 0x00, 0x00},
- }, // end patterns
- { // begin tracks
- {{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(-70,0), // LFO
- MUL(0,1),
- 255,
- }, // end instrument data
- { // begin playlist
- 0,255,
- }, // end playlist
-};
+extern Song thesong;
+
+#endif