1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6
7 #include "../nx.h"
8 #include "../common/basics.h"
9 #include "org.h"
10 #include "pxt.h" // for loading drums
11 #include "sslib.h" // SAMPLE_RATE
12 #include "org.fdh"
13
14 #include "libretro_shared.h"
15
16 #define DRUM_PXT
17
18 #define drumK 22050
19
20 static bool org_inited = false;
21
22 static stNoteChannel note_channel[16];
23
24 static stSong song;
25
26 static int cache_ahead_time = 17; // approximate number of ms to cache ahead (is rounded to a # of beats)
27
28 static int buffer_beats; // # of beats to cache ahead in each buffer
29 static int buffer_samples; // how many samples are in each outbuffer
30 static int outbuffer_size_bytes; // length of each outbuffer, and of final_buffer, in bytes
31
32 static struct
33 {
34 signed short *samples; // pointer to the raw PCM sound data
35 int firstbeat; // beat # of the first beat contained in this chunk
36 } final_buffer[2];
37
38 static uint8_t current_buffer;
39 static bool buffers_full;
40
41 static int OrgVolume;
42
43 signed short wavetable[100][256];
44
45 // sound effect numbers which correspond to the drums
46 static const unsigned char drum_pxt[] =
47 {
48 0x96, 0, 0x97, 0, 0x9a, 0x98,
49 0x99, 0, 0x9b, 0, 0, 0
50 };
51
52 static struct
53 {
54 signed short *samples;
55 int nsamples;
56 } drumtable[NUM_DRUMS];
57
58 static int pitch[NUM_NOTES];
59
60
init_pitch(void)61 static void init_pitch(void)
62 {
63 NX_LOG("Calculating pitch scale...\n");
64
65 for(int i=0;i<NUM_NOTES;i++)
66 {
67 pitch[i] = (int)(441.0*(pow(2.0,((i-19.0)/12.0))));
68 }
69 }
70
71
72 // given an instrument pitch and a note, returns the sampling rate that the
73 // wavetable sample should be played at in order to seem as if it is a recording of that note.
GetNoteSampleRate(int note,int instrument_pitch)74 static float_type GetNoteSampleRate(int note, int instrument_pitch)
75 {
76 return ((instrument_pitch - 1000.0)/100.0 + pitch[note])*44100/1550;
77 }
78
79 // converts a time in milliseconds to that same time length in samples
MSToSamples(int ms)80 static int MSToSamples(int ms)
81 {
82 return (int)(((float_type)SAMPLE_RATE / (float_type)1000) * (float_type)ms);
83 }
84
85 // converts a sample length to milliseconds
SamplesToMS(int samples)86 static int SamplesToMS(int samples)
87 {
88 return (int)(((float_type)samples * 1000) / SAMPLE_RATE);
89 }
90
load_drum_pxt(FILE * fd,int s,int d)91 static bool load_drum_pxt(FILE *fd, int s, int d)
92 {
93 int i;
94 signed short sample;
95 stPXSound snd;
96
97 if (pxt_load(fd, &snd, s)) return 1;
98 pxt_Render(&snd);
99
100 drumtable[d].nsamples = snd.final_size;
101 drumtable[d].samples = (signed short *)malloc(snd.final_size * 2); // *2 - it is 16-bit
102
103 // read data out of pxt's render result and put it into our drum sample table
104 for(i=0;i<drumtable[d].nsamples;i++)
105 {
106 sample = snd.final_buffer[i];
107 //i'm upscaling the 8-bit value to 16-bit;
108 //but this also sets volume of drums relative to music
109 sample *= 200;
110
111 drumtable[d].samples[i] = sample;
112 }
113
114 FreePXTBuf(&snd);
115 return 0;
116 }
117
load_drumtable(FILE * fp)118 static bool load_drumtable(FILE *fp) // pxt_path = the path where drum pxt files can be found
119 {
120 NX_LOG("load_drumtable: cache gone; rebuilding drums...\n");
121
122 pxt_initsynth();
123
124 for (int d = 0; d < NUM_DRUMS; d++)
125 {
126 if (drum_pxt[d])
127 if (load_drum_pxt(fp, drum_pxt[d], d)) return 1;
128 }
129
130 return 0;
131 }
132
133
134 /*
135 void c------------------------------() {}
136 */
137
138 extern bool extract_org(FILE *exefp);
139
org_init(FILE * fp,int org_volume)140 int org_init(FILE *fp, int org_volume)
141 {
142 int i;
143
144 SSReserveChannel(ORG_CHANNEL);
145 OrgVolume = org_volume;
146
147 // set all buffer pointers and things to NULL, so if something fails to load,
148 // we won't crash on org_close.
149 memset(drumtable, 0, sizeof(drumtable));
150 for(i=0;i<16;i++)
151 note_channel[i].outbuffer = NULL;
152 for(i=0;i<2;i++)
153 final_buffer[i].samples = NULL;
154
155 extract_org(fp);
156
157 init_pitch();
158 if (load_drumtable(fp))
159 {
160 return 1;
161 }
162
163 song.playing = false;
164 org_inited = true;
165 return 0;
166 }
167
168
org_close(void)169 void org_close(void)
170 {
171 int d;
172
173 org_stop();
174 free_buffers();
175
176 for(d=0;d<NUM_DRUMS;d++)
177 if (drumtable[d].samples) free(drumtable[d].samples);
178 }
179
mgetc(char ** fp)180 int mgetc(char **fp)
181 {
182 unsigned char volatile *f = *((unsigned char volatile **)fp);
183 unsigned char volatile c = *f;
184 (*fp)++;
185 return c;
186 }
187
mgeti(char ** fp)188 uint16_t mgeti(char **fp)
189 {
190 uint16_t a, b;
191 a = mgetc(fp);
192 b = mgetc(fp);
193 return (b << 8) | a;
194 }
195
mgetl(char ** fp)196 uint32_t mgetl(char **fp)
197 {
198 uint32_t a, b, c, d;
199 a = mgetc(fp);
200 b = mgetc(fp);
201 c = mgetc(fp);
202 d = mgetc(fp);
203 return (d<<24)|(c<<16)|(b<<8)|(a);
204 }
205
206 extern char *org_data[42];
207
org_load(int songno)208 char org_load(int songno)
209 {
210 static const char *magic = "Org-02";
211 char buf[8];
212 char *f;
213 char **fp;
214 int i, j;
215
216 f = org_data[songno];
217 fp = &f;
218 if (!fp) {
219 NX_WARN("org_load: no such file: '%d'\n", songno);
220 return 1;
221 }
222
223 for(i=0;i<6;i++) { buf[i] = mgetc(fp); } buf[i] = 0;
224 if (strcmp(buf, magic)) {
225 NX_WARN("org-load: not an org file (got '%s')\n", buf);
226 //fclose(fp);
227 return 1;
228 }
229 NX_LOG("%d: %s detected\n", songno, magic);
230
231 //fseek(fp, 0x06, SEEK_SET);
232
233 song.ms_per_beat = mgeti(fp);
234 song.steps_per_bar = mgetc(fp);
235 song.beats_per_step = mgetc(fp);
236 song.loop_start = mgetl(fp);
237 song.loop_end = mgetl(fp);
238
239 //song.ms_per_beat = 500;
240 //song.loop_start = 64;
241
242 if (song.loop_end < song.loop_start)
243 {
244 visible_warning("org_load: loop end is before loop start");
245 //fclose(fp);
246 return 1;
247 }
248
249 // compute how long the last beat of a note should be (it should not use up the whole beat)
250 song.ms_of_last_beat_of_note = song.ms_per_beat - (int)((float_type)song.ms_per_beat * 0.1);
251
252 // not actually used in this module, but the larger program might want to know this
253 song.beats_per_bar = (song.beats_per_step * song.steps_per_bar);
254
255 /*lprintf("tempo: %d ms/beat\n", song.ms_per_beat);
256 lprintf("beats_per_step: %d\n", song.beats_per_step);
257 lprintf("steps_per_bar: %d\n", song.steps_per_bar);
258 lprintf("loop begins on beat %d\n", song.loop_start);
259 lprintf("loop ends on beat %d\n", song.loop_end);*/
260
261 for(i=0;i<16;i++)
262 {
263 song.instrument[i].pitch = mgeti(fp);
264 song.instrument[i].wave = mgetc(fp);
265 song.instrument[i].pi = mgetc(fp);
266 song.instrument[i].nnotes = mgeti(fp);
267
268 if (song.instrument[i].nnotes >= MAX_SONG_LENGTH)
269 {
270 visible_warning(" * org_load: instrument %d has too many notes! (has %d, max %d)", i, song.instrument[i].nnotes, MAX_SONG_LENGTH);
271 //fclose(fp);
272 return 1;
273 }
274
275 /*if (song.instrument[i].nnotes)
276 {
277 lprintf("Instrument %d: ", i);
278 lprintf(" Pitch: %d, ", song.instrument[i].pitch);
279 lprintf(" Wave: %d, ", song.instrument[i].wave);
280 lprintf(" Pi: %d, ", song.instrument[i].pi);
281 lprintf(" Nnotes: %d\n", song.instrument[i].nnotes);
282 }*/
283
284 // substitute unavailable drums
285 // credits track for one, has Per02 set which CS didn't actually have, I don't think
286 if (i >= 8)
287 {
288 switch(song.instrument[i].wave)
289 {
290 case 9: song.instrument[i].wave = 8; break;
291 }
292 }
293 }
294
295 for(i=0;i<16;i++)
296 {
297 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].beat = mgetl(fp);
298 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].note = mgetc(fp);
299 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].length = mgetc(fp);
300 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].volume = mgetc(fp);
301 for(j=0;j<song.instrument[i].nnotes;j++) song.instrument[i].note[j].panning = mgetc(fp);
302 }
303
304 //fclose(fp);
305 return init_buffers();
306 }
307
308 /*
309 void c------------------------------() {}
310 */
311
312
init_buffers(void)313 static bool init_buffers(void)
314 {
315 int i;
316
317 // free the old buffers, as we're probably going to change their size here in a sec
318 free_buffers();
319
320 /* figure some stuff out real quick about buffer lengths --- */
321
322 // convert the ms-per-beat stuff into samples
323 song.samples_per_beat = MSToSamples(song.ms_per_beat);
324 song.note_closing_samples = MSToSamples(song.ms_of_last_beat_of_note);
325 // take the suggestion on cache ahead time (which is in ms) and figure out how many beats that is
326 buffer_beats = (cache_ahead_time / song.ms_per_beat) + 1;
327
328 #ifndef MIN_AUDIO_PROCESSING_PER_FRAME
329 if (buffer_beats < 3) buffer_beats = 3;
330 #endif
331
332 // now figure out how many samples that is.
333 buffer_samples = (buffer_beats * song.samples_per_beat);
334 // now figure out how many bytes THAT is.
335 outbuffer_size_bytes = buffer_samples * 2 * 2; // @ 16-bits, and stereo sound
336
337
338 // initialize the per-channel output buffers
339 for(i=0;i<16;i++)
340 {
341 note_channel[i].outbuffer = (signed short *)malloc(outbuffer_size_bytes);
342 note_channel[i].number = i;
343 //memset(note_channel[i].outbuffer, 0, outbuffer_size_bytes);
344 }
345
346 // initialize the final (mixed) output buffers
347 for(i=0;i<2;i++)
348 {
349 final_buffer[i].samples = (signed short *)malloc(outbuffer_size_bytes);
350 //memset(final_buffer[i].samples, 0, outbuffer_size_bytes);
351 }
352
353 return 0;
354 }
355
free_buffers(void)356 static void free_buffers(void)
357 {
358 int i;
359
360 for(i=0;i<16;i++)
361 if (note_channel[i].outbuffer) free(note_channel[i].outbuffer);
362
363 for(i=0;i<2;i++)
364 if (final_buffer[i].samples) free(final_buffer[i].samples);
365 }
366
367
368 /*
369 void c------------------------------() {}
370 */
371
372
373 // start the currently-loaded track playing at beat startbeat.
org_start(int startbeat)374 bool org_start(int startbeat)
375 {
376 org_stop(); // stop any old music
377
378 // set all the note-tracking stuff to starting values
379 song.beat = startbeat;
380 song.haslooped = false;
381
382 for(int i=0;i<16;i++)
383 {
384 song.instrument[i].curnote = 0;
385 note_channel[i].volume = ORG_MAX_VOLUME;
386 note_channel[i].panning = ORG_PAN_CENTERED;
387 note_channel[i].length = 0;
388 }
389
390 // fill the first buffer and play it to jumpstart the playback cycle
391 //lprintf(" ** org_start: Jumpstarting buffer cycle\n");
392
393 song.playing = true;
394 song.fading = false;
395
396 song.volume = OrgVolume;
397 SSSetVolume(ORG_CHANNEL, song.volume);
398
399 // kickstart the first buffer
400 current_buffer = 0;
401 generate_music();
402 queue_final_buffer();
403 buffers_full = 0; // tell org_run to generate the other buffer right away
404
405 return 0;
406 }
407
408
409 // pause/stop playback of the current song
org_stop(void)410 void org_stop(void)
411 {
412 if (song.playing)
413 {
414 song.playing = false;
415 // cancel whichever buffer is playing
416 SSAbortChannel(ORG_CHANNEL);
417 }
418 }
419
org_is_playing(void)420 bool org_is_playing(void)
421 {
422 return song.playing;
423 }
424
org_fade(void)425 void org_fade(void)
426 {
427 NX_LOG("org_fade\n");
428 song.fading = true;
429 song.last_fade_time = 0;
430 }
431
org_set_volume(int newvolume)432 void org_set_volume(int newvolume)
433 {
434 if (newvolume != song.volume)
435 {
436 song.volume = newvolume;
437 SSSetVolume(ORG_CHANNEL, newvolume);
438 }
439 }
440
441 unsigned retro_get_tick(void);
442
runfade()443 static void runfade()
444 {
445 uint32_t curtime = retro_get_tick();
446 if ((curtime - song.last_fade_time) >= 25)
447 {
448 int newvol = (song.volume - 1);
449 if (newvol <= 0)
450 {
451 song.fading = false;
452 org_stop();
453 }
454 else
455 {
456 org_set_volume(newvol);
457 }
458
459 song.last_fade_time = curtime;
460 }
461 }
462
463 /*
464 void c------------------------------() {}
465 */
466
467 // combines all of the individual channel output buffers into a single, final, buffer.
mix_buffers(void)468 static void mix_buffers(void)
469 {
470 int i, cursample, len;
471 int mixed_sample;
472 signed short *final;
473
474 // go up to samples*2 because we're mixing the stereo audio output from calls to WAV_Synth
475 len = buffer_samples * 2;
476 final = final_buffer[current_buffer].samples;
477
478 //NX_LOG("mixing %d samples\n", len);
479 for(cursample=0;cursample<len;cursample++)
480 {
481 // first mix instruments
482 mixed_sample = note_channel[0].outbuffer[cursample];
483 for(i=1;i<16;i++)
484 mixed_sample += note_channel[i].outbuffer[cursample];
485
486 CLAMP16(mixed_sample);
487
488 final[cursample] = mixed_sample;
489 }
490 }
491
492 // start whichever buffer is queued to play next, and flag the other one as needing
493 // to be filled
queue_final_buffer(void)494 static void queue_final_buffer(void)
495 {
496 SSEnqueueChunk(ORG_CHANNEL, final_buffer[current_buffer].samples, buffer_samples,
497 current_buffer, OrgBufferFinished);
498
499 current_buffer ^= 1;
500 }
501
502
503 // callback from sslib when a buffer is finished playing.
OrgBufferFinished(int channel,int buffer_no)504 static void OrgBufferFinished(int channel, int buffer_no)
505 {
506 buffers_full = false;
507 }
508
509 /*
510 void c------------------------------() {}
511 */
512
513
514 /* given a volume and a panning value, it returns three values
515 between 0 and 1.00 which are how much to scale:
516 the whole sound (volume_ratio)
517 just the left channel (volume_left_ratio)
518 just the right channel (volume_right_ratio) */
ComputeVolumeRatios(int volume,int panning,float_type * volume_ratio,float_type * volume_left_ratio,float_type * volume_right_ratio)519 static void ComputeVolumeRatios(int volume, int panning, float_type *volume_ratio, \
520 float_type *volume_left_ratio, float_type *volume_right_ratio)
521 {
522 *volume_ratio = ((float_type)volume / ORG_MAX_VOLUME);
523
524 // get volume ratios for left and right channels (panning)
525 if (panning < ORG_PAN_CENTERED)
526 { // panning left (make right channel quieter)
527 *volume_right_ratio = ((float_type)panning / ORG_PAN_CENTERED);
528 *volume_left_ratio = 1.00f;
529 }
530 else if (panning > ORG_PAN_CENTERED)
531 { // panning right (make left channel quieter)
532 *volume_left_ratio = ((float_type)(ORG_PAN_FULL_RIGHT - panning) / ORG_PAN_CENTERED);
533 *volume_right_ratio = 1.00f;
534 }
535 else
536 { // perfectly centered (both channels get the full volume)
537 *volume_left_ratio = 1.00f;
538 *volume_right_ratio = 1.00f;
539 }
540 }
541
542
543 // Interpolates a new sample from two samples which will be "in-between" the two samples.
544 // if ratio is 0.00, it will return exactly sample1.
545 // if ratio is 1.00, it will return exactly sample2.
546 // and if ratio is something like 0.5, it will mix the samples together.
Interpolate(int sample1,int sample2,float_type ratio)547 static float_type Interpolate(int sample1, int sample2, float_type ratio)
548 {
549 float_type s1, s2;
550 s1 = ((float_type)sample1 * (1.00f - ratio));
551 s2 = ((float_type)sample2 * ratio);
552 return (s1 + s2);
553 }
554
555
556 // ensures that there are exactly desired_samples contained in the output buffer of instrument m.
557 // if there are fewer samples than desired, the gap is filled with silence.
558 // if there are more, the extra audio is truncated.
ForceSamplePos(int m,int desired_samples)559 static void ForceSamplePos(int m, int desired_samples)
560 {
561 if (note_channel[m].samples_so_far != desired_samples)
562 {
563 if (desired_samples > note_channel[m].samples_so_far)
564 {
565 silence_gen(¬e_channel[m], (desired_samples - note_channel[m].samples_so_far));
566 }
567 else
568 { // this should NEVER actually happen!!
569 NX_WARN("ForceSamplePos: WARNING: !!! truncated channel %d from %d to %d samples !!!\n", m, note_channel[m].samples_so_far, desired_samples);
570 note_channel[m].samples_so_far = desired_samples;
571 note_channel[m].outpos = desired_samples * 2;
572 }
573 }
574 }
575
576
577 // adds num_samples samples of silence to the output buffer of channel "m".
silence_gen(stNoteChannel * chan,int num_samples)578 static void silence_gen(stNoteChannel *chan, int num_samples)
579 {
580 int clear_bytes;
581
582 //NX_LOG("silence_gen: making %d samples of silence\n", num_samples);
583
584 clear_bytes = (num_samples * 2 * 2); // clear twice as many shorts as = num_samples
585 memset(&chan->outbuffer[chan->outpos], 0, clear_bytes);
586
587 chan->samples_so_far += num_samples;
588 chan->outpos += (num_samples * 2);
589 }
590
591 // -------------------
592 // note_open
593 // -------------------
594 // initializes the synthesis of a new note.
595 // chan: the instrument channel the note will play on
596 // wave: the instrument no to play the note with
597 // pitch: the pitch variation of the instrument as set in the org
598 // note: the note # we'll be playing
599 // total_ms: the maximum length the note will play for (controls buffer allocation length)
note_open(stNoteChannel * chan,int wave,int pitch,int note)600 static void note_open(stNoteChannel *chan, int wave, int pitch, int note)
601 {
602 float_type new_sample_rate;
603 #define samplK 11025 // constant is original sampling rate of the samples in the wavetable
604
605 // compute how quickly, or slowly, to play back the wavetable sample
606 new_sample_rate = GetNoteSampleRate(note, pitch);
607 chan->sample_inc = (new_sample_rate / (float_type)samplK);
608
609 chan->wave = wave;
610 chan->phaseacc = 0;
611
612 //lprintf("note_open: new note opened for channel %08x at sample_inc %.2f, using wave %d\n", chan, chan->sample_inc, chan->wave);
613 }
614
615 // -------------------
616 // note_gen
617 // -------------------
618 // Adds num_samples worth of audio data to the channel at the current frequency, volume,
619 // panning, and pitch settings, and at the note & wave spec'd in note_open.
note_gen(stNoteChannel * chan,int num_samples)620 static void note_gen(stNoteChannel *chan, int num_samples)
621 {
622 int i;
623 float_type audioval;
624 float_type master_volume_ratio, volume_left_ratio, volume_right_ratio;
625 int wave;
626 unsigned char pos1, pos2;
627 float_type iratio;
628
629 wave = chan->wave;
630
631 // compute volume ratios; unlike drums we have to do this every time
632 // since they can change in the middle of the note.
633 ComputeVolumeRatios(chan->volume, chan->panning,
634 &master_volume_ratio, &volume_left_ratio, &volume_right_ratio);
635
636 //statbuild("Entering note_gen with phaseacc=%.2f and sample_inc=%.2f", chan->phaseacc, chan->sample_inc);
637 //statbuild(", using buffer %08x\n", chan->outbuffer);
638
639 //NX_LOG("note_gen(%d, %d)\n", chan->number, num_samples);
640
641 // generate however many output samples we were asked for
642 for(i=0;i<num_samples;i++)
643 {
644 // interpolate a sample that's at the fractional "phaseacc" sample position in the wavetable form
645 pos1 = (int)chan->phaseacc;
646 pos2 = pos1 + 1; // since pos1&2 are chars, this wraps at 255
647 iratio = chan->phaseacc - (int)chan->phaseacc;
648
649 audioval = Interpolate(wavetable[wave][pos1], wavetable[wave][pos2], iratio);
650 audioval *= master_volume_ratio;
651
652 chan->outbuffer[chan->outpos++] = (int)(audioval * volume_left_ratio);
653 chan->outbuffer[chan->outpos++] = (int)(audioval * volume_right_ratio);
654 chan->samples_so_far++;
655
656 chan->phaseacc += chan->sample_inc;
657 if ((int)chan->phaseacc >= 256) chan->phaseacc -= 256;
658 }
659 }
660
661
662 // -------------------
663 // note_close
664 // -------------------
665 // ends a note smoothly by ensuring that it's wave stops near the 0-crossing point.
666 // this avoids a slight popping noise which can be caused by abruptly moving from
667 // a high sample value to a close-to-zero sample value.
668 // returns the # of extra samples generated.
note_close(stNoteChannel * chan)669 static int note_close(stNoteChannel *chan)
670 {
671 if (chan->outpos == 0)
672 return 0;
673
674 int samples_made = 0;
675 while(chan->samples_so_far < buffer_samples) // avoid potential buffer overflow
676 {
677 // get the value of the last sample in the buffer and check
678 // if it's close enough to silence yet. if not, let the note
679 // run on a teeny bit longer than it's supposed to until it's wave
680 // hits the zero-crossing point, to avoid a click.
681 int last_sample = chan->outbuffer[chan->outpos - 1];
682 if (abs(last_sample) < 1000) break;
683
684 note_gen(chan, 1);
685 samples_made++;
686 }
687
688 return samples_made;
689 }
690
691
692 // set up to make a drum noise using drum "wave" at note "note" on channel "m_channel".
693 // the total number of samples the drum will last is returned.
drum_open(int m_channel,int wave,int note)694 static int drum_open(int m_channel, int wave, int note)
695 {
696 stNoteChannel *chan = ¬e_channel[m_channel];
697 float_type new_sample_rate;
698 int gen_samples;
699
700 //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);
701
702 new_sample_rate = GetNoteSampleRate(note, song.instrument[m_channel].pitch);
703 chan->sample_inc = (new_sample_rate / (float_type)drumK);
704
705 // get the new number of samples for the sound
706 gen_samples = (int)((float_type)drumtable[wave].nsamples / chan->sample_inc);
707
708 // precompute volume and panning values since they're the same over the length of the drum
709 ComputeVolumeRatios(chan->volume, chan->panning, &chan->master_volume_ratio, &chan->volume_left_ratio, &chan->volume_right_ratio);
710
711 chan->wave = wave;
712 chan->phaseacc = 0;
713 return gen_samples;
714 }
715
716
717 // generates "num_samples" of a drum noise previously set up via drum_open into the output
718 // buffer of the channel.
drum_gen(int m_channel,int num_samples)719 static void drum_gen(int m_channel, int num_samples)
720 {
721 stNoteChannel *chan = ¬e_channel[m_channel];
722 float_type volume_ratio, volume_left_ratio, volume_right_ratio;
723 int wave;
724 int pos1, pos2;
725 float_type iratio;
726 float_type audioval;
727 int i;
728
729 volume_ratio = chan->master_volume_ratio;
730 volume_left_ratio = chan->volume_left_ratio;
731 volume_right_ratio = chan->volume_right_ratio;
732 wave = chan->wave;
733
734 //NX_LOG("drum_gen(%d, %d)\n", m_channel, num_samples);
735
736 // generate the drum sound
737 for(i=0;i<num_samples;i++)
738 {
739 pos1 = (int)chan->phaseacc;
740 pos2 = pos1 + 1;
741 if (pos2 >= drumtable[wave].nsamples) pos2 = pos1;
742
743 iratio = chan->phaseacc - (int)chan->phaseacc;
744
745 audioval = Interpolate(drumtable[wave].samples[pos1], drumtable[wave].samples[pos2], iratio);
746 audioval *= volume_ratio;
747
748 chan->outbuffer[chan->outpos++] = (signed short)(audioval * volume_left_ratio);
749 chan->outbuffer[chan->outpos++] = (signed short)(audioval * volume_right_ratio);
750 chan->samples_so_far++;
751
752 chan->phaseacc += chan->sample_inc;
753 if ((int)chan->phaseacc > drumtable[wave].nsamples)
754 {
755 NX_ERR(" **ERROR-phaseacc ran over end of drumsample %.2f %d\n", chan->phaseacc, drumtable[wave].nsamples);
756 break;
757 }
758 }
759 }
760
761
org_run(void)762 void org_run(void)
763 {
764 if (!song.playing)
765 return;
766
767 // keep both buffers queued. if one of them isn't queued, then it's time to
768 // generate more music for it and queue it back on.
769 if (!buffers_full)
770 {
771 generate_music(); // generate more music into current_buffer
772
773 queue_final_buffer(); // enqueue current_buffer and switch buffers
774 buffers_full = true; // both buffers full again until OrgBufferFinished called
775 }
776
777 if (song.fading) runfade();
778 }
779
780
781 // generate a buffer's worth of music and place it in the current final buffer.
generate_music(void)782 static void generate_music(void)
783 {
784 int m;
785 int beats_left;
786 int out_position;
787
788 //NX_LOG("generate_music: cb=%d buffer_beats=%d\n", current_buffer, buffer_beats);
789
790 // save beat # of the first beat in buffer for calculating current beat for TrackFuncs
791 final_buffer[current_buffer].firstbeat = song.beat;
792
793 // clear all the channel buffers
794 for(m=0;m<16;m++)
795 {
796 note_channel[m].samples_so_far = 0;
797 note_channel[m].outpos = 0;
798 }
799
800 //NX_LOG("generate_music: generating %d beats of music\n", buffer_beats);
801 beats_left = buffer_beats;
802 out_position = 0;
803
804 while(beats_left)
805 {
806 out_position += song.samples_per_beat;
807
808 // for each channel...
809 for(m=0;m<16;m++)
810 {
811 // generate any music that's supposed to go into the current beat
812 NextBeat(m);
813 // ensure that exactly one beat of samples was added to the channel by inserting silence
814 // if needed. sometimes NextBeat may not actually generate a full beats worth, for
815 // example if there was no note playing on the track, of if it was the last beat of a note.
816 ForceSamplePos(m, out_position);
817 }
818
819 if (++song.beat >= song.loop_end)
820 {
821 song.beat = song.loop_start;
822 song.haslooped = true;
823
824 for(m=0;m<16;m++)
825 {
826 song.instrument[m].curnote = song.instrument[m].loop_note;
827 note_channel[m].length = 0;
828 }
829 }
830
831 beats_left--;
832 }
833
834 mix_buffers();
835 }
836
837
838 // generate up to a 1 beat worth of music from channel "m" at the song.beat cursor point.
839 // it may generate less.
NextBeat(int m)840 static void NextBeat(int m)
841 {
842 stNoteChannel *chan = ¬e_channel[m];
843 stInstrument *track = &song.instrument[m];
844 //int volume, panning;
845 stNote *note;
846 int len;
847
848 // add notes as long as instrument has notes left to add
849 if (track->curnote < track->nnotes)
850 {
851 for(;;)
852 {
853 // when we hit the loop start point, record the note we were on for later
854 if (song.beat == song.loop_start)
855 {
856 track->loop_note = track->curnote;
857 }
858
859 // get a pointer to the note at current position in the song
860 note = &track->note[track->curnote];
861
862 // skip ahead if the song got ahead of us somehow
863 if (song.beat > note->beat)
864 {
865 if (++track->curnote >= track->nnotes)
866 return;
867 }
868 else break;
869 }
870
871 // 1st- start notes as we arrive at their beat
872 if (song.beat == note->beat)
873 {
874 //NX_LOG(" Beat/Note: %d/%d Chan: %d Note: %d length=%d vol=%d pan=%d wave=%d\n", song.beat, curnote, m, note->note, note->length, note->volume, note->panning, song.instrument[m].wave);
875
876 if (note->volume != 0xff) chan->volume = note->volume;
877 if (note->panning != 0xff) chan->panning = note->panning;
878
879 if (note->note != 0xff)
880 {
881 if (m < 8)
882 {
883 note_open(chan, track->wave, track->pitch, note->note);
884 chan->length = note->length;
885 }
886 else
887 { // on percussion tracks the length works differently---drum_open returns the
888 // number of samples the drum will take to finish playing.
889 chan->length = drum_open(m, track->wave, note->note);
890 }
891 }
892
893 track->curnote++;
894 }
895 }
896
897 // 2nd- generate any notes which are running
898 if (chan->length)
899 {
900 if (m < 8)
901 { // melody tracks
902 if (track->pi)
903 { // pi tracks always generate only 1024 samples for ANY note
904 note_gen(chan, 1024);
905 chan->length = 0;
906 }
907 else
908 {
909 if (chan->length > 1)
910 { // generate a full beat of music
911 note_gen(chan, song.samples_per_beat);
912 }
913 else // generate only most of the beat--if there's a note immediately after
914 { // this one they should not run together
915 note_gen(chan, song.note_closing_samples);
916 }
917
918 if (!--chan->length)
919 {
920 note_close(chan);
921 }
922 }
923 }
924 else
925 { // percussion tracks
926 // if less than a whole beats worth of samples is left to play on the drum, finish
927 // whatever's left. Else generate only one beats worth right now.
928 if (chan->length > song.samples_per_beat)
929 len = song.samples_per_beat;
930 else
931 len = chan->length;
932
933 drum_gen(m, len);
934
935 chan->length -= len;
936 }
937 }
938
939 }
940
941 /*
942 void c------------------------------() {}
943 */
944
org_GetCurrentBeat(void)945 int org_GetCurrentBeat(void)
946 {
947 if (SSChannelPlaying(ORG_CHANNEL))
948 {
949 int curbuffer;
950 int elapsed;
951 int sample_pos;
952 int beat;
953
954 curbuffer = SSGetCurUserData(ORG_CHANNEL);
955 sample_pos = SSGetSamplePos(ORG_CHANNEL);
956
957 elapsed = SamplesToMS(sample_pos);
958
959 beat = elapsed / song.ms_per_beat;
960 beat += final_buffer[curbuffer].firstbeat;
961 // wrap at end of song
962 while(beat >= song.loop_end)
963 beat -= (song.loop_end - song.loop_start);
964
965 return beat;
966 }
967
968 return -1;
969 }
970
971 // returns which org buffer is currently playing.
org_GetCurrentBuffer(void)972 int org_GetCurrentBuffer(void)
973 {
974 if (!SSChannelPlaying(ORG_CHANNEL)) return -1;
975 return SSGetCurUserData(ORG_CHANNEL);
976 }
977