+++ /dev/null
-PROJECT(lolailo)
-cmake_minimum_required(VERSION 2.6)
-FIND_PACKAGE(Qt4 REQUIRED)
-FIND_PACKAGE(SDL REQUIRED)
-INCLUDE( ${QT_USE_FILE} )
-
-SET(LOLAILO_MOC_HDRS
- mainwindow.h
- trackerwindow.h
-)
-
-SET(LOLAILO_SOURCES
- lolailo.cpp
- mainwindow.cpp
- play.cpp
- synth.cpp
- trackerwindow.cpp
-)
-
-QT4_WRAP_CPP(LOLAILO_MOC_SRCS ${LOLAILO_MOC_HDRS})
-ADD_EXECUTABLE(lolailo ${LOLAILO_SOURCES} ${LOLAILO_MOC_SRCS})
-TARGET_LINK_LIBRARIES(lolailo ${QT_LIBRARIES} ${SDL_LIBRARY} SDLmain)
-
--- /dev/null
+CC=gcc -m32
+
+CFLAGS=-std=c99 -Os -Wall -s
+LDFLAGS=-lSDL-1.2 -nostartfiles
+
+all: lolailo
+ bash print_sizes.sh
+ ls -l lolailo
+ gzip -c lolailo > lolailo.gz
+ ls -l lolailo.gz
+
+lolailo: lolailo.o synth.o play.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
+
+clean:
+ rm -f *.o lolailo lolailo.gz
+
+.PHONY: clean
+.SILENT:
-#include <QtGui/QApplication>
+//#include <QtGui/QApplication>
#include <SDL/SDL.h>
-#include "mainwindow.h"
+//#include "mainwindow.h"
#include "synth.h"
#include "play.h"
-Song song;
+#include "thesong.h"
SDL_AudioSpec desired={44100,
AUDIO_S16SYS,
0,
0,
(void (*)(void *, Uint8 *, int)) play,
- &song};
-
+ &thesong};
+#ifdef DEBUG
int main(int argc, char *argv[])
+#else
+void _start()
+#endif
{
SDL_Init(SDL_INIT_AUDIO);
SDL_OpenAudio(&desired, NULL);
SDL_PauseAudio(0);
- QApplication a(argc, argv);
- MainWindow w(NULL);
- w.show();
- int error = a.exec();
+ //QApplication a(argc, argv);
+ //MainWindow w(NULL);
+ //w.show();
+ //int error = a.exec();
+ getchar();
SDL_Quit();
- return error;
+ //return error;
}
--- /dev/null
+#include "sizedtypes.h"
+#include "play.h"
+#include "synth.h"
+#include "song.h"
+#include <stdio.h>
+#include <string.h>
+
+
+#define NUM_VOICES 1
+
+float row_duration=60.0/360.0; // denominator == RPM
+Voice voices[NUM_VOICES];
+float mix_buf[BUFFER_SIZE]={0};
+uint8 last_voice_used=0;
+
+float current_time=0.0f;
+uint32 rows_played=0; // total of rows played
+uint8 cur_pos= 0; // current position in the pattern playlist
+uint8 cur_row=-1; // current row in the current pattern
+
+void play(void *s, uint8 *stream, int len)
+{
+ Song *song = (Song*) s;
+ int num_samples=len>>1;
+ int16 *buf=(int16 *)stream;
+ current_time += num_samples/SAMPLE_RATE;
+
+ memset(mix_buf, 0, BUFFER_SIZE*sizeof(float));
+
+ if ((current_time - rows_played * row_duration) > row_duration ) {
+ ++rows_played;
+ ++cur_row;
+ int buf_start = ((current_time - rows_played * row_duration)*SAMPLE_RATE)-num_samples;
+
+ if (cur_row == TRACK_LENGTH) { // end of track
+ cur_row=0;
+ ++cur_pos;
+ }
+ if (song->playlist[cur_pos]==255) { // loop at end of song
+ cur_pos=0;
+ }
+
+ uint8 cur_ptn=song->playlist[cur_pos];
+
+ /*
+ for (i=0; i<NUM_RHYTHM_CHANNELS; ++i) {
+ int steps;
+ steps = song->rhythms[i];
+ if (steps & (1<<(15-cur_row))) {
+ voices[i].pitch = 440.0f*detune(song->rhythm_notes[i]-45,0);
+ voices[i].pos = buf_start;
+ voices[i].ins = &song->insts[song->rhythm_insts[i]];
+ voices[i].vol = 0.1796875f;
+ voices[i].active = 1;
+ }
+ }
+ */
+
+ for (uint8 i=0; i<NUM_CHANNELS; ++i) {
+ unsigned int chanval=song->patterns[cur_ptn][i];
+ if (chanval) {
+ unsigned int trknum=(chanval & 0x0F)-1;
+ Track *cur_trk = &song->tracks[trknum];
+ uint8 trans = (chanval) >> 4;
+
+ unsigned int note = (cur_trk->notes[cur_row] & 0x0F);
+ if (note) {
+ float vol = ((cur_trk->notes[cur_row])>>4) * 0.0625f;
+ note+=trans;
+
+ 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].pos = buf_start;
+ voices[j].ins = &song->instrument_data[cur_trk->instrument];
+ voices[j].vol = 0.19921875f*vol;
+ voices[j].active = 1;
+ }
+ }
+ }
+
+
+ }
+ // Ahora vamos sintetizando las voces
+ for (int i=0; i < NUM_VOICES; ++i)
+ {
+ if (voices[i].active)
+ {
+ voices[i].active=synth(&voices[i], num_samples, mix_buf);
+ }
+ }
+
+ // convertimos a Sint16
+ for (int i=0; i<num_samples; ++i)
+ {
+ float tmp = mix_buf[i];
+ if (tmp>1.0f) tmp=1.0f;
+ else if(tmp<-1.0f) tmp=-1.0f;
+ buf[i]=(int16)(tmp*32640.0f);
+ }
+
+#ifdef OUTFILE
+ fwrite(buf, sizeof(int16), num_samples, fout);
+#endif
+
+}
+
+++ /dev/null
-#include "sizedtypes.h"
-#include "play.h"
-#include "synth.h"
-#include "song.h"
-#include <cstdio>
-#include <cstring>
-
-#define NUM_VOICES 32
-
-float row_duration=60.0/90.0; // denominator == BPM
-Voice voices[NUM_VOICES];
-float mix_buf[BUFFER_SIZE]={0};
-uint8 last_voice_used=0;
-
-float current_time=0.0f;
-uint32 rows_played=0; // total of rows played
-uint8 cur_pos= 0; // current position in the pattern playlist
-uint8 cur_row=-1; // current row in the current pattern
-
-void play(void *s, uint8 *stream, int len)
-{
- Song *song = (Song*) s;
- unsigned int num_samples=len>>1;
- int16 *buf=(int16 *)stream;
- current_time += num_samples/SAMPLE_RATE;
-
- memset(mix_buf, 0, BUFFER_SIZE*sizeof(float));
-
- if ((current_time - rows_played * row_duration) > row_duration ) {
- ++rows_played;
- ++cur_row;
- int buf_start = ((current_time - rows_played * row_duration)*SAMPLE_RATE)-num_samples;
-
- if (cur_row == TRACK_LENGTH) { // end of track
- cur_row=0;
- ++cur_pos;
- }
- if (song->playlist[cur_pos]==255) { // loop at end of song
- cur_pos=0;
- }
-
- uint8 cur_ptn=song->playlist[cur_pos];
-
- /*
- for (i=0; i<NUM_RHYTHM_CHANNELS; ++i) {
- int steps;
- steps = song->rhythms[i];
- if (steps & (1<<(15-cur_row))) {
- voices[i].pitch = 440.0f*detune(song->rhythm_notes[i]-45,0);
- voices[i].pos = buf_start;
- voices[i].ins = &song->insts[song->rhythm_insts[i]];
- voices[i].vol = 0.1796875f;
- voices[i].active = 1;
- }
- }
- */
-
- for (uint8 i=0; i<NUM_CHANNELS; ++i) {
- unsigned int chanval=song->patterns[cur_ptn][i];
- unsigned int trknum=chanval & 0x0F;
- Track *cur_trk = &song->tracks[trknum];
- uint8 trans = (chanval) >> 4;
-
- unsigned int note = (cur_trk->notes[cur_row] & 0x0F);
- float vol = ((cur_trk->notes[cur_row])>>4) * 0.0625f;
- if (chanval)
- {
- note+=trans;
-
- uint8 j = last_voice_used;
- last_voice_used = (last_voice_used + 1) % NUM_VOICES;
- voices[j].pitch = 440.0f*detune(note-45,0);
- voices[j].pos = buf_start;
- voices[j].ins = &song->instrument_data[cur_trk->instrument];
- voices[j].vol = 0.19921875f*vol;
- voices[j].active = 1;
- }
- }
-
-
- }
- // Ahora vamos sintetizando las voces
- for (int i=0; i < NUM_VOICES; ++i)
- {
- if (voices[i].active)
- {
- voices[i].active=synth(&voices[i], num_samples, mix_buf);
- }
- }
-
- // convertimos a Sint16
- for (int i=0; i<num_samples; ++i)
- {
- float tmp = mix_buf[i];
- if (tmp>1.0f) tmp=1.0f;
- else if(tmp<-1.0f) tmp=-1.0f;
- buf[i]=(int16)(tmp*32640.0f);
- }
-
-#ifdef OUTFILE
- fwrite(buf, sizeof(int16), num_samples, fout);
-#endif
-
-}
-
--- /dev/null
+#!/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'"
+
// + PLAYLIST_LENGTH
#define NUM_PATTERNS 20
-#define NUM_CHANNELS 10
-#define NUM_TRACKS 20
+#define NUM_CHANNELS 4
+#define NUM_TRACKS 15
#define TRACK_LENGTH 16
#define INSTRUMENT_DATA_LENGTH 100
#define PLAYLIST_LENGTH 50
-struct Track
+typedef struct
{
uint8 notes[TRACK_LENGTH];
uint8 instrument;
-};
+} Track;
-struct Song
+typedef struct
{
uint8 patterns[NUM_PATTERNS][NUM_CHANNELS];
Track tracks[NUM_TRACKS];
uint8 instrument_data[INSTRUMENT_DATA_LENGTH];
uint8 playlist[PLAYLIST_LENGTH];
-};
+} Song;
--- /dev/null
+#include "synth.h"
+#include <string.h>
+#include <math.h>
+
+#define PI 3.1415926535897931
+
+float detune(int coarse, int fine)
+{
+ return powf(2.0f, (coarse+(fine/100.0f))/12.0f);
+}
+
+uint8 synth(Voice *v, int len, float *mix_buf)
+{
+ if (v->pos < 0) {
+ mix_buf -= v->pos;
+ len += v->pos;
+ v->pos = 0;
+ }
+
+ int iPC=0; // instrument program counter
+ int wave=0;
+ while (1) {
+ uint8 op = v->ins[iPC++];
+
+ switch (op) {
+ case 1: // SINE
+ {
+ uint8 coarse = v->ins[iPC++];
+ uint8 fine = v->ins[iPC++];
+ float pitch = v->pitch*detune(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);
+ }
+ 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];
+ else
+ v->waves[wave][i] = v->waves[wave1][i]*v->waves[wave2][i];
+ }
+ break;
+ }
+
+ default:
+ goto end;
+ }
+
+ ++wave;
+ }
+
+end:
+ v->pos+=len;
+ for (int i=0; i<len; i++)
+ mix_buf[i] += v->waves[wave-1][i];
+ return 1;
+}
+
+
+++ /dev/null
-#include "synth.h"
-#include <cstring>
-#include <cmath>
-
-const float detune(int coarse, int fine)
-{
- return powf(2.0f, (coarse+(fine/100.0f))/12.0f);
-}
-
-bool synth(Voice *v, int len, float *mix_buf)
-{
- memset(mix_buf, 0, len*sizeof(float));
- return false;
-}
-
-
operation ends the sequence.
*/
-struct Voice
+typedef struct
{
float pitch;
float vol;
// buffers generated by wave operations
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 RING(a,b) 3,a,b
-extern bool synth(Voice *v, int len, float *mix_buf);
-extern const float detune(int coarse, int fine);
+extern uint8 synth(Voice *v, int len, float *mix_buf);
+extern float detune(int coarse, int fine);
--- /dev/null
+#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(1,10),
+ //SINE(3,1),
+ RING(0,1),
+ RING(1,2),
+ 255,
+ }, // end instrument data
+ { // begin playlist
+ 0,255,
+ }, // end playlist
+};
+