+#include "sizedtypes.h"
#include "play.h"
-
+#include "synth.h"
+#include "song.h"
#include <cstdio>
#include <cstring>
-void play(void *songdata, uint8* stream, int len)
+#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)
{
- memset(stream, 0, len);
- //printf("Sound callback\n");
+ 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
+#ifndef SONG_H
+#define SONG_H
+
+#include "sizedtypes.h"
+
+// uncompressed song size ==
+// NUM_PATTERNS*NUM_CHANNELS
+// + NUM_TRACKS*TRACK_LENGTH
+// + INSTRUMENT_DATA_LENGTH
+// + PLAYLIST_LENGTH
+
+#define NUM_PATTERNS 20
+#define NUM_CHANNELS 10
+#define NUM_TRACKS 20
+#define TRACK_LENGTH 16
+#define INSTRUMENT_DATA_LENGTH 100
+#define PLAYLIST_LENGTH 50
+
+struct Track
+{
+ uint8 notes[TRACK_LENGTH];
+ uint8 instrument;
+};
+
+struct Song
+{
+ uint8 patterns[NUM_PATTERNS][NUM_CHANNELS];
+ Track tracks[NUM_TRACKS];
+ uint8 instrument_data[INSTRUMENT_DATA_LENGTH];
+ uint8 playlist[PLAYLIST_LENGTH];
+};
+
+
+
+#endif
+