NXEngine v1.0.0.4
[NXEngine.git] / sound / org.cpp
blobc2729338da3b4ab5589392df15f61c44324ebae5
2 #include <SDL/SDL.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <math.h>
7 #include <endian.h>
9 #include "../common/basics.h"
10 #include "org.h"
11 #include "pxt.h" // for loading drums
12 #include "sslib.h" // SAMPLE_RATE
13 #include "org.fdh"
15 //#define QUIET
16 #define DRUM_PXT
18 #ifdef DRUM_PXT
19 #define drumK 22050
20 #else
21 #define drumK 30050
22 #endif
24 static bool org_inited = false;
26 static stNoteChannel note_channel[16];
28 static stSong song;
30 static int cache_ahead_time = 2000; // approximate number of ms to cache ahead (is rounded to a # of beats)
32 static int buffer_beats; // # of beats to cache ahead in each buffer
33 static int buffer_samples; // how many samples are in each outbuffer
34 static int outbuffer_size_bytes; // length of each outbuffer, and of final_buffer, in bytes
36 static struct
38 signed short *samples; // pointer to the raw PCM sound data
39 int firstbeat; // beat # of the first beat contained in this chunk
40 } final_buffer[2];
42 static uint8_t current_buffer;
43 static bool buffers_full;
45 static int OrgVolume;
47 static struct
49 signed short samples[256];
50 } wavetable[100];
52 #ifdef DRUM_PXT
53 // sound effect numbers which correspond to the drums
54 static const unsigned char drum_pxt[] =
56 0x96, 0, 0x97, 0, 0x9a, 0x98,
57 0x99, 0, 0x9b, 0, 0, 0
59 #else
60 // names of the WAV files to load for each drum slot
61 static const char *drum_names[] =
63 "Bass01", "Bass02", "Snare01", "Snare02", "Tom01", "HiClose",
64 "HiOpen", "Crash", "Per01", "Per02", "Bass03", "Tom02"
66 #endif
68 static struct
70 signed short *samples;
71 int nsamples;
72 } drumtable[NUM_DRUMS];
74 static int pitch[NUM_NOTES];
77 static void init_pitch(void)
79 stat("Calculating pitch scale...");
81 for(int i=0;i<NUM_NOTES;i++)
83 pitch[i] = (int)(441.0*(pow(2.0,((i-19.0)/12.0))));
88 // given an instrument pitch and a note, returns the sampling rate that the
89 // wavetable sample should be played at in order to seem as if it is a recording of that note.
90 static double GetNoteSampleRate(int note, int instrument_pitch)
92 return ((instrument_pitch - 1000.0)/100.0 + pitch[note])*44100/1550;
95 // converts a time in milliseconds to that same time length in samples
96 static int MSToSamples(int ms)
98 return (int)(((double)SAMPLE_RATE / (double)1000) * (double)ms);
101 // converts a sample length to milliseconds
102 static int SamplesToMS(int samples)
104 return (int)(((double)samples * 1000) / SAMPLE_RATE);
108 static bool load_drumtable(const char *pxt_path) // pxt_path = the path where drum pxt files can be found
110 char fname[80];
111 int d;
112 FILE *fp;
113 static const char *drum_cache = "drum.pcm";
114 #define DRUM_VERSION 0x0001
115 uint16_t version;
117 #ifndef DRUM_PXT
118 for(d=0;d<NUM_DRUMS;d++)
120 sprintf(fname, "./drums/%s.wav", drum_names[d]);
121 if (load_drum(fname, d)) return 1;
123 #else
125 // try and load the drums from cache instead of synthing them
126 fp = fileopen(drum_cache, "rb");
127 if (fp)
129 // this also checks for correct endianness
130 fread(&version, sizeof(version), 1, fp);
131 if (version != DRUM_VERSION)
133 printf("%s: version incorrect\n", drum_cache);
135 else
137 for(d=0;d<NUM_DRUMS;d++)
139 drumtable[d].nsamples = fgetl(fp);
140 drumtable[d].samples = (signed short *)malloc(drumtable[d].nsamples * 2);
141 fread(drumtable[d].samples, drumtable[d].nsamples*2, 1, fp);
143 fclose(fp);
144 stat("-- Drums loaded from cache");
145 return 0;
149 stat("load_drumtable: cache gone; rebuilding drums...");
151 pxt_initsynth();
153 for(d=0;d<NUM_DRUMS;d++)
155 if (drum_pxt[d])
157 sprintf(fname, "%sfx%02x.pxt", pxt_path, drum_pxt[d]);
158 if (load_drum_pxt(fname, d)) return 1;
162 // cache the drums for next time
163 fp = fileopen(drum_cache, "wb");
164 if (fp)
166 version = DRUM_VERSION;
167 fwrite(&version, sizeof(version), 1, fp);
168 for(d=0;d<NUM_DRUMS;d++)
170 fputl(drumtable[d].nsamples, fp);
171 fwrite(drumtable[d].samples, drumtable[d].nsamples*2, 1, fp);
173 fclose(fp);
176 load_drumtable(pxt_path);
177 #endif
179 //for(d=0;d<256;d++) { lprintf("%d ", drumtable[0].samples[d]); if (d%32==0) lprintf("\n"); }
180 //lprintf("\n");
182 return 0;
185 #ifndef DRUM_PXT
187 static bool load_drum(char *fname, int d)
189 Mix_Chunk *chunk;
190 int i, read_pt;
191 int left,right;
192 signed short *abuf;
194 //stat("load_drum: loading %s into drum index %d", fname, d);
195 if (!(chunk = Mix_LoadWAV(fname)))
197 staterr("Missing drum sample: '%s'", fname);
198 return 1;
201 //stat("chunk: %d bytes in chunk", chunk->alen);
202 drumtable[d].nsamples = chunk->alen / 2 / 2; // 16-bit stereo sound
203 drumtable[d].samples = malloc(drumtable[d].nsamples * 2);
205 #ifndef QUIET
206 stat("drum0%X [%s]: %d samples", d, fname, drumtable[d].nsamples);
207 #endif
209 read_pt = 0;
210 abuf = (signed short *)chunk->abuf;
211 for(i=0;i<drumtable[d].nsamples;i++)
213 left = abuf[read_pt++]; right = abuf[read_pt++];
215 drumtable[d].samples[i] = (left + right) / 2;
216 drumtable[d].samples[i] += drumtable[d].samples[i]; // make drums louder--sounds better
219 Mix_FreeChunk(chunk);
220 return 0;
223 #else
225 static bool load_drum_pxt(char *fname, int d)
227 int i;
228 signed short sample;
229 stPXSound snd;
231 stat("load_drum: loading %s into drum index %d", fname, d);
233 if (pxt_load(fname, &snd)) return 1;
234 pxt_Render(&snd);
236 drumtable[d].nsamples = snd.final_size;
237 drumtable[d].samples = (signed short *)malloc(snd.final_size * 2); // *2 - it is 16-bit
239 #ifndef QUIET
240 stat("drum0%X [%s]: %d samples", d, fname, drumtable[d].nsamples);
241 #endif
243 // read data out of pxt's render result and put it into our drum sample table
244 for(i=0;i<drumtable[d].nsamples;i++)
246 sample = snd.final_buffer[i];
247 //i'm upscaling the 8-bit value to 16-bit;
248 //but this also sets volume of drums relative to music
249 sample *= 200;
251 drumtable[d].samples[i] = sample;
254 FreePXTBuf(&snd);
255 return 0;
258 #endif
263 static bool load_wavetable(const char *fname)
265 int wav, sampl;
266 FILE *fp;
267 #define BUF_SIZE (100 * 256)
268 signed char buffer[BUF_SIZE + 1];
269 signed char *ptr;
271 fp = fileopen(fname, "rb");
272 if (!fp)
274 stat("Unable to open wavetable.dat!!");
275 return 1;
278 fread(buffer, BUF_SIZE, 1, fp);
279 fclose(fp);
281 ptr = &buffer[0];
282 for(wav=0;wav<100;wav++)
284 for(sampl=0;sampl<256;sampl++)
286 // 256 = (32768 / 128)-- convert to 16-bit
287 wavetable[wav].samples[sampl] = (signed short)((int)(*ptr++) << 8);
291 return 0;
295 void c------------------------------() {}
299 int org_init(const char *wavetable_fname, const char *drum_pxt_dir, int org_volume)
301 int i;
303 SSReserveChannel(ORG_CHANNEL);
304 OrgVolume = org_volume;
306 // set all buffer pointers and things to NULL, so if something fails to load,
307 // we won't crash on org_close.
308 memset(drumtable, 0, sizeof(drumtable));
309 for(i=0;i<16;i++) note_channel[i].outbuffer = NULL;
310 for(i=0;i<2;i++) final_buffer[i].samples = NULL;
312 init_pitch();
313 if (load_wavetable(wavetable_fname)) return 1;
314 if (load_drumtable(drum_pxt_dir)) return 1;
316 song.playing = false;
317 org_inited = true;
318 return 0;
322 void org_close(void)
324 int d;
326 org_stop();
327 free_buffers();
329 for(d=0;d<NUM_DRUMS;d++)
330 if (drumtable[d].samples) free(drumtable[d].samples);
334 char org_load(char *fname)
336 static const char *magic = "Org-02";
337 char buf[8];
338 FILE *fp;
339 int i, j;
341 fp = fileopen(fname, "rb");
342 if (!fp) { visible_warning("org_load: no such file: '%s'", fname); return 1; }
344 for(i=0;i<6;i++) { buf[i] = fgetc(fp); } buf[i] = 0;
345 if (strcmp(buf, magic)) { visible_warning("org-load: not an org file (got '%s')", buf); fclose(fp); return 1; }
346 stat("%s: %s detected", fname, magic);
348 fseek(fp, 0x06, SEEK_SET);
350 song.ms_per_beat = fgeti(fp);
351 song.steps_per_bar = fgetc(fp);
352 song.beats_per_step = fgetc(fp);
353 song.loop_start = fgetl(fp);
354 song.loop_end = fgetl(fp);
356 //song.ms_per_beat = 500;
357 //song.loop_start = 64;
359 if (song.loop_end < song.loop_start)
361 visible_warning("org_load: loop end is before loop start");
362 fclose(fp);
363 return 1;
366 // compute how long the last beat of a note should be (it should not use up the whole beat)
367 song.ms_of_last_beat_of_note = song.ms_per_beat - (int)((double)song.ms_per_beat * 0.1);
369 // not actually used in this module, but the larger program might want to know this
370 song.beats_per_bar = (song.beats_per_step * song.steps_per_bar);
372 /*lprintf("tempo: %d ms/beat\n", song.ms_per_beat);
373 lprintf("beats_per_step: %d\n", song.beats_per_step);
374 lprintf("steps_per_bar: %d\n", song.steps_per_bar);
375 lprintf("loop begins on beat %d\n", song.loop_start);
376 lprintf("loop ends on beat %d\n", song.loop_end);*/
378 for(i=0;i<16;i++)
380 song.instrument[i].pitch = fgeti(fp);
381 song.instrument[i].wave = fgetc(fp);
382 song.instrument[i].pi = fgetc(fp);
383 song.instrument[i].nnotes = fgeti(fp);
385 if (song.instrument[i].nnotes >= MAX_SONG_LENGTH)
387 visible_warning(" * org_load: instrument %d has too many notes! (has %d, max %d)", i, song.instrument[i].nnotes, MAX_SONG_LENGTH);
388 fclose(fp);
389 return 1;
392 /*if (song.instrument[i].nnotes)
394 lprintf("Instrument %d: ", i);
395 lprintf(" Pitch: %d, ", song.instrument[i].pitch);
396 lprintf(" Wave: %d, ", song.instrument[i].wave);
397 lprintf(" Pi: %d, ", song.instrument[i].pi);
398 lprintf(" Nnotes: %d\n", song.instrument[i].nnotes);
401 // substitute unavailable drums
402 // credits track for one, has Per02 set which CS didn't actually have, I don't think
403 if (i >= 8)
405 switch(song.instrument[i].wave)
407 case 9: song.instrument[i].wave = 8; break;
412 for(i=0;i<16;i++)
414 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].beat = fgetl(fp);
415 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].note = fgetc(fp);
416 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].length = fgetc(fp);
417 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].volume = fgetc(fp);
418 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].panning = fgetc(fp);
421 fclose(fp);
422 return init_buffers();
426 void c------------------------------() {}
430 static bool init_buffers(void)
432 int i;
434 // free the old buffers, as we're probably going to change their size here in a sec
435 free_buffers();
437 /* figure some stuff out real quick about buffer lengths --- */
439 // convert the ms-per-beat stuff into samples
440 song.samples_per_beat = MSToSamples(song.ms_per_beat);
441 song.note_closing_samples = MSToSamples(song.ms_of_last_beat_of_note);
442 // take the suggestion on cache ahead time (which is in ms) and figure out how many beats that is
443 buffer_beats = (cache_ahead_time / song.ms_per_beat) + 1;
444 if (buffer_beats < 3) buffer_beats = 3;
446 // now figure out how many samples that is.
447 buffer_samples = (buffer_beats * song.samples_per_beat);
448 // now figure out how many bytes THAT is.
449 outbuffer_size_bytes = buffer_samples * 2 * 2; // @ 16-bits, and stereo sound
452 // initialize the per-channel output buffers
453 for(i=0;i<16;i++)
455 note_channel[i].outbuffer = (signed short *)malloc(outbuffer_size_bytes);
456 note_channel[i].number = i;
457 //memset(note_channel[i].outbuffer, 0, outbuffer_size_bytes);
460 // initialize the final (mixed) output buffers
461 for(i=0;i<2;i++)
463 final_buffer[i].samples = (signed short *)malloc(outbuffer_size_bytes);
464 //memset(final_buffer[i].samples, 0, outbuffer_size_bytes);
467 return 0;
470 static void free_buffers(void)
472 int i;
474 for(i=0;i<16;i++)
475 if (note_channel[i].outbuffer) free(note_channel[i].outbuffer);
477 for(i=0;i<2;i++)
478 if (final_buffer[i].samples) free(final_buffer[i].samples);
483 void c------------------------------() {}
487 // start the currently-loaded track playing at beat startbeat.
488 bool org_start(int startbeat)
490 org_stop(); // stop any old music
492 // set all the note-tracking stuff to starting values
493 song.beat = startbeat;
494 song.haslooped = false;
496 for(int i=0;i<16;i++)
498 song.instrument[i].curnote = 0;
499 note_channel[i].volume = ORG_MAX_VOLUME;
500 note_channel[i].panning = ORG_PAN_CENTERED;
501 note_channel[i].length = 0;
504 // fill the first buffer and play it to jumpstart the playback cycle
505 //lprintf(" ** org_start: Jumpstarting buffer cycle\n");
507 song.playing = true;
508 song.fading = false;
510 song.volume = OrgVolume;
511 SSSetVolume(ORG_CHANNEL, song.volume);
513 // kickstart the first buffer
514 current_buffer = 0;
515 generate_music();
516 queue_final_buffer();
517 buffers_full = 0; // tell org_run to generate the other buffer right away
519 return 0;
523 // pause/stop playback of the current song
524 void org_stop(void)
526 if (song.playing)
528 song.playing = false;
529 // cancel whichever buffer is playing
530 SSAbortChannel(ORG_CHANNEL);
534 bool org_is_playing(void)
536 return song.playing;
539 // resume a song paused with org_stop
540 /*void org_resume(void)
542 if (!song.playing)
544 /* lprintf("restarting buffer %d\n", last_played_buffer);
545 //StartOrgBuffer(last_played_buffer, &final_buffer[last_played_buffer].chunk);
546 song.playing = 1;
547 song.volume = ORG_VOLUME;*/
548 /* }
552 void org_fade(void)
554 stat("org_fade");
555 song.fading = true;
556 song.last_fade_time = 0;
559 void org_set_volume(int newvolume)
561 if (newvolume != song.volume)
563 song.volume = newvolume;
564 SSSetVolume(ORG_CHANNEL, newvolume);
568 static void runfade()
570 uint32_t curtime = SDL_GetTicks();
571 if ((curtime - song.last_fade_time) >= 25)
573 int newvol = (song.volume - 1);
574 if (newvol <= 0)
576 song.fading = false;
577 org_stop();
579 else
581 org_set_volume(newvol);
584 song.last_fade_time = curtime;
589 void c------------------------------() {}
592 // combines all of the individual channel output buffers into a single, final, buffer.
593 static void mix_buffers(void)
595 int i, cursample, len;
596 int mixed_sample;
597 signed short *final;
599 // lprintf("mix_buffers: mixing channels into final_buffer[%d]\n", current_buffer);
601 // go up to samples*2 because we're mixing the stereo audio output from calls to WAV_Synth
602 len = buffer_samples * 2;
603 final = final_buffer[current_buffer].samples;
605 //stat("mixing %d samples", len);
606 for(cursample=0;cursample<len;cursample++)
608 // first mix instruments
609 mixed_sample = note_channel[0].outbuffer[cursample];
610 for(i=1;i<16;i++) mixed_sample += note_channel[i].outbuffer[cursample];
612 if (mixed_sample > 32767) mixed_sample = 32767;
613 else if (mixed_sample < -32768) mixed_sample = -32768;
615 final[cursample] = htole16(mixed_sample);
619 // start whichever buffer is queued to play next, and flag the other one as needing
620 // to be filled
621 static void queue_final_buffer(void)
623 SSEnqueueChunk(ORG_CHANNEL, final_buffer[current_buffer].samples, buffer_samples,
624 current_buffer, OrgBufferFinished);
626 current_buffer ^= 1;
630 // callback from sslib when a buffer is finished playing.
631 static void OrgBufferFinished(int channel, int buffer_no)
633 buffers_full = false;
637 void c------------------------------() {}
641 // given a volume and a panning value, it returns three values
642 // between 0 and 1.00 which are how much to scale:
643 // the whole sound (volume_ratio)
644 // just the left channel (volume_left_ratio)
645 // just the right channel (volume_right_ratio)
646 static void ComputeVolumeRatios(int volume, int panning, double *volume_ratio, \
647 double *volume_left_ratio, double *volume_right_ratio)
649 *volume_ratio = ((double)volume / ORG_MAX_VOLUME);
651 // get volume ratios for left and right channels (panning)
652 if (panning < ORG_PAN_CENTERED)
653 { // panning left (make right channel quieter)
654 *volume_right_ratio = ((double)panning / ORG_PAN_CENTERED);
655 *volume_left_ratio = 1.00f;
657 else if (panning > ORG_PAN_CENTERED)
658 { // panning right (make left channel quieter)
659 *volume_left_ratio = ((double)(ORG_PAN_FULL_RIGHT - panning) / ORG_PAN_CENTERED);
660 *volume_right_ratio = 1.00f;
662 else
663 { // perfectly centered (both channels get the full volume)
664 *volume_left_ratio = 1.00f;
665 *volume_right_ratio = 1.00f;
670 // Interpolates a new sample from two samples which will be "in-between" the two samples.
671 // if ratio is 0.00, it will return exactly sample1.
672 // if ratio is 1.00, it will return exactly sample2.
673 // and if ratio is something like 0.5, it will mix the samples together.
674 static double Interpolate(int sample1, int sample2, double ratio)
676 double s1, s2;
677 s1 = ((double)sample1 * (1.00f - ratio));
678 s2 = ((double)sample2 * ratio);
679 return (s1 + s2);
683 // ensures that there are exactly desired_samples contained in the output buffer of instrument m.
684 // if there are fewer samples than desired, the gap is filled with silence.
685 // if there are more, the extra audio is truncated.
686 static void ForceSamplePos(int m, int desired_samples)
688 if (note_channel[m].samples_so_far != desired_samples)
690 if (desired_samples > note_channel[m].samples_so_far)
692 silence_gen(&note_channel[m], (desired_samples - note_channel[m].samples_so_far));
694 else
695 { // this should NEVER actually happen!!
696 stat("ForceSamplePos: WARNING: !!! truncated channel %d from %d to %d samples !!!", m, note_channel[m].samples_so_far, desired_samples);
697 note_channel[m].samples_so_far = desired_samples;
698 note_channel[m].outpos = desired_samples * 2;
704 // adds num_samples samples of silence to the output buffer of channel "m".
705 static void silence_gen(stNoteChannel *chan, int num_samples)
707 int clear_bytes;
709 //stat("silence_gen: making %d samples of silence", num_samples);
711 clear_bytes = (num_samples * 2 * 2); // clear twice as many shorts as = num_samples
712 memset(&chan->outbuffer[chan->outpos], 0, clear_bytes);
714 chan->samples_so_far += num_samples;
715 chan->outpos += (num_samples * 2);
718 // -------------------
719 // note_open
720 // -------------------
721 // initializes the synthesis of a new note.
722 // chan: the instrument channel the note will play on
723 // wave: the instrument no to play the note with
724 // pitch: the pitch variation of the instrument as set in the org
725 // note: the note # we'll be playing
726 // total_ms: the maximum length the note will play for (controls buffer allocation length)
727 static void note_open(stNoteChannel *chan, int wave, int pitch, int note)
729 double new_sample_rate;
730 #define samplK 11025 // constant is original sampling rate of the samples in the wavetable
732 // compute how quickly, or slowly, to play back the wavetable sample
733 new_sample_rate = GetNoteSampleRate(note, pitch);
734 chan->sample_inc = (new_sample_rate / (double)samplK);
736 chan->wave = wave;
737 chan->phaseacc = 0;
739 //lprintf("note_open: new note opened for channel %08x at sample_inc %.2f, using wave %d\n", chan, chan->sample_inc, chan->wave);
742 // -------------------
743 // note_gen
744 // -------------------
745 // Adds num_samples worth of audio data to the channel at the current frequency, volume,
746 // panning, and pitch settings, and at the note & wave spec'd in note_open.
747 static void note_gen(stNoteChannel *chan, int num_samples)
749 int i;
750 double audioval;
751 double master_volume_ratio, volume_left_ratio, volume_right_ratio;
752 int wave;
753 unsigned char pos1, pos2;
754 double iratio;
756 wave = chan->wave;
758 // compute volume ratios; unlike drums we have to do this every time
759 // since they can change in the middle of the note.
760 ComputeVolumeRatios(chan->volume, chan->panning,
761 &master_volume_ratio, &volume_left_ratio, &volume_right_ratio);
763 //statbuild("Entering note_gen with phaseacc=%.2f and sample_inc=%.2f", chan->phaseacc, chan->sample_inc);
764 //statbuild(", using buffer %08x\n", chan->outbuffer);
766 //stat("note_gen(%d, %d)", chan->number, num_samples);
768 // generate however many output samples we were asked for
769 for(i=0;i<num_samples;i++)
771 // interpolate a sample that's at the fractional "phaseacc" sample position in the wavetable form
772 pos1 = (int)chan->phaseacc;
773 pos2 = pos1 + 1; // since pos1&2 are chars, this wraps at 255
774 iratio = chan->phaseacc - (int)chan->phaseacc;
776 audioval = Interpolate(wavetable[wave].samples[pos1], wavetable[wave].samples[pos2], iratio);
777 audioval *= master_volume_ratio;
779 chan->outbuffer[chan->outpos++] = (int)(audioval * volume_left_ratio);
780 chan->outbuffer[chan->outpos++] = (int)(audioval * volume_right_ratio);
781 chan->samples_so_far++;
783 chan->phaseacc += chan->sample_inc;
784 if ((int)chan->phaseacc >= 256) chan->phaseacc -= 256;
789 // -------------------
790 // note_close
791 // -------------------
792 // ends a note smoothly by ensuring that it's wave stops near the 0-crossing point.
793 // this avoids a slight popping noise which can be caused by abruptly moving from
794 // a high sample value to a close-to-zero sample value.
795 // returns the # of extra samples generated.
796 static int note_close(stNoteChannel *chan)
798 if (chan->outpos == 0)
799 return 0;
801 int samples_made = 0;
802 while(chan->samples_so_far < buffer_samples) // avoid potential buffer overflow
804 // get the value of the last sample in the buffer and check
805 // if it's close enough to silence yet. if not, let the note
806 // run on a teeny bit longer than it's supposed to until it's wave
807 // hits the zero-crossing point, to avoid a click.
808 int last_sample = chan->outbuffer[chan->outpos - 1];
809 if (abs(last_sample) < 1000) break;
811 note_gen(chan, 1);
812 samples_made++;
815 return samples_made;
819 // set up to make a drum noise using drum "wave" at note "note" on channel "m_channel".
820 // the total number of samples the drum will last is returned.
821 static int drum_open(int m_channel, int wave, int note)
823 stNoteChannel *chan = &note_channel[m_channel];
824 double new_sample_rate;
825 int gen_samples;
827 //lprintf("drum_hit: playing drum %d[%s] on channel %d, note %02x volume %d panning %d\n", wave, drum_names[wave], m_channel, note, chan->volume, chan->panning);
829 new_sample_rate = GetNoteSampleRate(note, song.instrument[m_channel].pitch);
830 chan->sample_inc = (new_sample_rate / (double)drumK);
832 // get the new number of samples for the sound
833 gen_samples = (int)((double)drumtable[wave].nsamples / chan->sample_inc);
835 // precompute volume and panning values since they're the same over the length of the drum
836 ComputeVolumeRatios(chan->volume, chan->panning, &chan->master_volume_ratio, &chan->volume_left_ratio, &chan->volume_right_ratio);
838 chan->wave = wave;
839 chan->phaseacc = 0;
840 return gen_samples;
844 // generates "num_samples" of a drum noise previously set up via drum_open into the output
845 // buffer of the channel.
846 static void drum_gen(int m_channel, int num_samples)
848 stNoteChannel *chan = &note_channel[m_channel];
849 double volume_ratio, volume_left_ratio, volume_right_ratio;
850 int wave;
851 int pos1, pos2;
852 double iratio;
853 double audioval;
854 int i;
856 volume_ratio = chan->master_volume_ratio;
857 volume_left_ratio = chan->volume_left_ratio;
858 volume_right_ratio = chan->volume_right_ratio;
859 wave = chan->wave;
861 //stat("drum_gen(%d, %d)", m_channel, num_samples);
863 // generate the drum sound
864 for(i=0;i<num_samples;i++)
866 pos1 = (int)chan->phaseacc;
867 pos2 = pos1 + 1;
868 if (pos2 >= drumtable[wave].nsamples) pos2 = pos1;
870 iratio = chan->phaseacc - (int)chan->phaseacc;
872 audioval = Interpolate(drumtable[wave].samples[pos1], drumtable[wave].samples[pos2], iratio);
873 audioval *= volume_ratio;
875 chan->outbuffer[chan->outpos++] = (signed short)(audioval * volume_left_ratio);
876 chan->outbuffer[chan->outpos++] = (signed short)(audioval * volume_right_ratio);
877 chan->samples_so_far++;
879 chan->phaseacc += chan->sample_inc;
880 if ((int)chan->phaseacc > drumtable[wave].nsamples)
882 staterr(" **ERROR-phaseacc ran over end of drumsample %.2f %d", chan->phaseacc, drumtable[wave].nsamples);
883 break;
889 void org_run(void)
891 if (!song.playing)
892 return;
894 // keep both buffers queued. if one of them isn't queued, then it's time to
895 // generate more music for it and queue it back on.
896 if (!buffers_full)
898 generate_music(); // generate more music into current_buffer
900 queue_final_buffer(); // enqueue current_buffer and switch buffers
901 buffers_full = true; // both buffers full again until OrgBufferFinished called
904 if (song.fading) runfade();
908 // generate a buffer's worth of music and place it in the current final buffer.
909 static void generate_music(void)
911 int m;
912 int beats_left;
913 int out_position;
915 //stat("generate_music: cb=%d buffer_beats=%d", current_buffer, buffer_beats);
917 // save beat # of the first beat in buffer for calculating current beat for TrackFuncs
918 final_buffer[current_buffer].firstbeat = song.beat;
920 // clear all the channel buffers
921 for(m=0;m<16;m++)
923 note_channel[m].samples_so_far = 0;
924 note_channel[m].outpos = 0;
927 //stat("generate_music: generating %d beats of music\n", buffer_beats);
928 beats_left = buffer_beats;
929 out_position = 0;
931 while(beats_left)
933 out_position += song.samples_per_beat;
935 // for each channel...
936 for(m=0;m<16;m++)
938 // generate any music that's supposed to go into the current beat
939 NextBeat(m);
940 // ensure that exactly one beat of samples was added to the channel by inserting silence
941 // if needed. sometimes NextBeat may not actually generate a full beats worth, for
942 // example if there was no note playing on the track, of if it was the last beat of a note.
943 ForceSamplePos(m, out_position);
946 if (++song.beat >= song.loop_end)
948 song.beat = song.loop_start;
949 song.haslooped = true;
951 for(m=0;m<16;m++)
953 song.instrument[m].curnote = song.instrument[m].loop_note;
954 note_channel[m].length = 0;
958 beats_left--;
961 mix_buffers();
965 // generate up to a 1 beat worth of music from channel "m" at the song.beat cursor point.
966 // it may generate less.
967 static void NextBeat(int m)
969 stNoteChannel *chan = &note_channel[m];
970 stInstrument *track = &song.instrument[m];
971 //int volume, panning;
972 stNote *note;
973 int len;
975 // add notes as long as instrument has notes left to add
976 if (track->curnote < track->nnotes)
978 for(;;)
980 // when we hit the loop start point, record the note we were on for later
981 if (song.beat == song.loop_start)
983 track->loop_note = track->curnote;
986 // get a pointer to the note at current position in the song
987 note = &track->note[track->curnote];
989 // skip ahead if the song got ahead of us somehow
990 if (song.beat > note->beat)
992 if (++track->curnote >= track->nnotes)
993 return;
995 else break;
998 // 1st- start notes as we arrive at their beat
999 if (song.beat == note->beat)
1001 //stat(" Beat/Note: %d/%d Chan: %d Note: %d length=%d vol=%d pan=%d wave=%d", song.beat, curnote, m, note->note, note->length, note->volume, note->panning, song.instrument[m].wave);
1003 if (note->volume != 0xff) chan->volume = note->volume;
1004 if (note->panning != 0xff) chan->panning = note->panning;
1006 if (note->note != 0xff)
1008 if (m < 8)
1010 note_open(chan, track->wave, track->pitch, note->note);
1011 chan->length = note->length;
1013 else
1014 { // on percussion tracks the length works differently---drum_open returns the
1015 // number of samples the drum will take to finish playing.
1016 chan->length = drum_open(m, track->wave, note->note);
1020 track->curnote++;
1024 // 2nd- generate any notes which are running
1025 if (chan->length)
1027 if (m < 8)
1028 { // melody tracks
1029 if (track->pi)
1030 { // pi tracks always generate only 1024 samples for ANY note
1031 note_gen(chan, 1024);
1032 chan->length = 0;
1034 else
1036 if (chan->length > 1)
1037 { // generate a full beat of music
1038 note_gen(chan, song.samples_per_beat);
1040 else // generate only most of the beat--if there's a note immediately after
1041 { // this one they should not run together
1042 note_gen(chan, song.note_closing_samples);
1045 if (!--chan->length)
1047 note_close(chan);
1051 else
1052 { // percussion tracks
1053 // if less than a whole beats worth of samples is left to play on the drum, finish
1054 // whatever's left. Else generate only one beats worth right now.
1055 if (chan->length > song.samples_per_beat)
1056 len = song.samples_per_beat;
1057 else
1058 len = chan->length;
1060 drum_gen(m, len);
1062 chan->length -= len;
1069 void c------------------------------() {}
1072 int org_GetCurrentBeat(void)
1074 if (SSChannelPlaying(ORG_CHANNEL))
1076 int curbuffer;
1077 int elapsed;
1078 int sample_pos;
1079 int beat;
1081 // if we don't lockout the audio over both these calls, it's possible
1082 // for the first variable to be from one buffer and the second from another.
1083 SSLockAudio();
1085 curbuffer = SSGetCurUserData(ORG_CHANNEL);
1086 sample_pos = SSGetSamplePos(ORG_CHANNEL);
1088 SSUnlockAudio();
1090 elapsed = SamplesToMS(sample_pos);
1092 beat = elapsed / song.ms_per_beat;
1093 beat += final_buffer[curbuffer].firstbeat;
1094 // wrap at end of song
1095 while(beat >= song.loop_end)
1096 beat -= (song.loop_end - song.loop_start);
1098 return beat;
1101 return -1;
1104 // returns which org buffer is currently playing.
1105 int org_GetCurrentBuffer(void)
1107 if (!SSChannelPlaying(ORG_CHANNEL)) return -1;
1108 return SSGetCurUserData(ORG_CHANNEL);
1112 // returns the musical name of an org note number
1113 /*char *org_GetNoteName(int note)
1115 static char static_buffer[16];
1116 static const char *note_names[] =
1117 { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1119 sprintf(static_buffer, "%s%d", \
1120 note_names[note % KEYS_OCTAVE], \
1121 note / KEYS_OCTAVE);
1123 return static_buffer;
1126 // returns true if a note is a sharp note
1127 /*bool org_IsSharp(int note)
1129 static const bool sharps[] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };
1130 return (sharps[note % KEYS_OCTAVE]);