9 #include "../common/basics.h"
11 #include "pxt.h" // for loading drums
12 #include "sslib.h" // SAMPLE_RATE
24 static bool org_inited
= false;
26 static stNoteChannel note_channel
[16];
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
38 signed short *samples
; // pointer to the raw PCM sound data
39 int firstbeat
; // beat # of the first beat contained in this chunk
42 static uint8_t current_buffer
;
43 static bool buffers_full
;
49 signed short samples
[256];
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
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"
70 signed short *samples
;
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
113 static const char *drum_cache
= "drum.pcm";
114 #define DRUM_VERSION 0x0001
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;
125 // try and load the drums from cache instead of synthing them
126 fp
= fileopen(drum_cache
, "rb");
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
);
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
);
144 stat("-- Drums loaded from cache");
149 stat("load_drumtable: cache gone; rebuilding drums...");
153 for(d
=0;d
<NUM_DRUMS
;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");
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
);
176 load_drumtable(pxt_path
);
179 //for(d=0;d<256;d++) { lprintf("%d ", drumtable[0].samples[d]); if (d%32==0) lprintf("\n"); }
187 static bool load_drum(char *fname
, int d
)
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
);
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);
206 stat("drum0%X [%s]: %d samples", d
, fname
, drumtable
[d
].nsamples
);
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
);
225 static bool load_drum_pxt(char *fname
, int d
)
231 stat("load_drum: loading %s into drum index %d", fname
, d
);
233 if (pxt_load(fname
, &snd
)) return 1;
236 drumtable
[d
].nsamples
= snd
.final_size
;
237 drumtable
[d
].samples
= (signed short *)malloc(snd
.final_size
* 2); // *2 - it is 16-bit
240 stat("drum0%X [%s]: %d samples", d
, fname
, drumtable
[d
].nsamples
);
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
251 drumtable
[d
].samples
[i
] = sample
;
263 static bool load_wavetable(const char *fname
)
267 #define BUF_SIZE (100 * 256)
268 signed char buffer
[BUF_SIZE
+ 1];
271 fp
= fileopen(fname
, "rb");
274 stat("Unable to open wavetable.dat!!");
278 fread(buffer
, BUF_SIZE
, 1, fp
);
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);
295 void c------------------------------() {}
299 int org_init(const char *wavetable_fname
, const char *drum_pxt_dir
, int org_volume
)
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
;
313 if (load_wavetable(wavetable_fname
)) return 1;
314 if (load_drumtable(drum_pxt_dir
)) return 1;
316 song
.playing
= false;
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";
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");
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);*/
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
);
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
405 switch(song
.instrument
[i
].wave
)
407 case 9: song
.instrument
[i
].wave
= 8; break;
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
);
422 return init_buffers();
426 void c------------------------------() {}
430 static bool init_buffers(void)
434 // free the old buffers, as we're probably going to change their size here in a sec
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
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
463 final_buffer
[i
].samples
= (signed short *)malloc(outbuffer_size_bytes
);
464 //memset(final_buffer[i].samples, 0, outbuffer_size_bytes);
470 static void free_buffers(void)
475 if (note_channel
[i
].outbuffer
) free(note_channel
[i
].outbuffer
);
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");
510 song
.volume
= OrgVolume
;
511 SSSetVolume(ORG_CHANNEL
, song
.volume
);
513 // kickstart the first buffer
516 queue_final_buffer();
517 buffers_full
= 0; // tell org_run to generate the other buffer right away
523 // pause/stop playback of the current song
528 song
.playing
= false;
529 // cancel whichever buffer is playing
530 SSAbortChannel(ORG_CHANNEL
);
534 bool org_is_playing(void)
539 // resume a song paused with org_stop
540 /*void org_resume(void)
544 /* lprintf("restarting buffer %d\n", last_played_buffer);
545 //StartOrgBuffer(last_played_buffer, &final_buffer[last_played_buffer].chunk);
547 song.volume = ORG_VOLUME;*/
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);
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
;
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
621 static void queue_final_buffer(void)
623 SSEnqueueChunk(ORG_CHANNEL
, final_buffer
[current_buffer
].samples
, buffer_samples
,
624 current_buffer
, OrgBufferFinished
);
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
;
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
)
677 s1
= ((double)sample1
* (1.00f
- ratio
));
678 s2
= ((double)sample2
* ratio
);
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(¬e_channel
[m
], (desired_samples
- note_channel
[m
].samples_so_far
));
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
)
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 // -------------------
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
);
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 // -------------------
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
)
751 double master_volume_ratio
, volume_left_ratio
, volume_right_ratio
;
753 unsigned char pos1
, pos2
;
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 // -------------------
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)
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;
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
= ¬e_channel
[m_channel
];
824 double new_sample_rate
;
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
);
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
= ¬e_channel
[m_channel
];
849 double volume_ratio
, volume_left_ratio
, volume_right_ratio
;
856 volume_ratio
= chan
->master_volume_ratio
;
857 volume_left_ratio
= chan
->volume_left_ratio
;
858 volume_right_ratio
= chan
->volume_right_ratio
;
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
;
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
);
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.
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)
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
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
;
933 out_position
+= song
.samples_per_beat
;
935 // for each channel...
938 // generate any music that's supposed to go into the current beat
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;
953 song
.instrument
[m
].curnote
= song
.instrument
[m
].loop_note
;
954 note_channel
[m
].length
= 0;
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
= ¬e_channel
[m
];
970 stInstrument
*track
= &song
.instrument
[m
];
971 //int volume, panning;
975 // add notes as long as instrument has notes left to add
976 if (track
->curnote
< track
->nnotes
)
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
)
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)
1010 note_open(chan
, track
->wave
, track
->pitch
, note
->note
);
1011 chan
->length
= note
->length
;
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
);
1024 // 2nd- generate any notes which are running
1030 { // pi tracks always generate only 1024 samples for ANY note
1031 note_gen(chan
, 1024);
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
)
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
;
1062 chan
->length
-= len
;
1069 void c------------------------------() {}
1072 int org_GetCurrentBeat(void)
1074 if (SSChannelPlaying(ORG_CHANNEL
))
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.
1085 curbuffer
= SSGetCurUserData(ORG_CHANNEL
);
1086 sample_pos
= SSGetSamplePos(ORG_CHANNEL
);
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
);
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]);