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(&note_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 = &note_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 = &note_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 = &note_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