#include #include "swis.h" #include #include "Sound.h" // SWI Registers extern _kernel_swi_regs inreg; extern _kernel_swi_regs outreg; int current_element = 0; int current_playback_element = 0; int composition_startcent = -1; struct CompositionElement composition[COMPOSITION_MAX]; struct pcmsample_s pcmsamples[PCMSAMPLE_MAX]; char *notes[] = {"AX","A#","BX","CX","C#","DX","D#","EX","FX","F#","GX","G#"}; void sound_on() { inreg.r[0] = 2; _kernel_swi(Sound_Enable,&inreg,&outreg); } void sound_composition_load(char* filename) { int length; // Attempt to get file info inreg.r[0] = 5; inreg.r[1] = (int) filename; _kernel_swi(OS_File,&inreg,&outreg); // Length will be in R4 if it exists length = outreg.r[4]; if(length > sizeof(composition)) { screen_nobuffer(); while(1) printf("Composition exceeds %d bytes (%d bytes)\n",sizeof(composition),length); } // Attempt to get file info inreg.r[0] = 16; inreg.r[1] = (int) filename; inreg.r[2] = (int) composition; inreg.r[3] = 0; _kernel_swi(OS_File,&inreg,&outreg); } void sound_voices(int num) { inreg.r[0] = num; inreg.r[1] = 0; inreg.r[2] = 0; inreg.r[3] = 0; inreg.r[4] = 0; _kernel_swi(Sound_Configure,&inreg,&outreg); } void sound_set_voice(int voicenum, char* voicename) { inreg.r[0] = voicenum; inreg.r[1] = (int) voicename; _kernel_swi(Sound_AttachNamedVoice,&inreg,&outreg); } void sound_play(unsigned char Channel, signed char Volume, unsigned char Note, unsigned short int Length) { inreg.r[0] = Channel; inreg.r[1] = Volume; inreg.r[2] = Note; inreg.r[3] = Length; _kernel_swi(Sound_Control,&inreg,&outreg); } void sound_composition_element_play(struct CompositionElement element) { sound_play(element.Channel, element.Volume, element.Note, element.Length); } void sound_composition_init() { int i; for(i = 0; i <= COMPOSITION_MAX; i++) { composition[i].Start = -1; } current_element = 0; } void sound_composition_element_add(int start, int channel, int note, int length) { composition[current_element].Start = start; composition[current_element].Note = note; composition[current_element].Volume = -10; composition[current_element].Channel = channel; composition[current_element].Length = length; current_element++; } void sound_composition_save(char *filename) { // Attempt to get file info inreg.r[0] = 10; inreg.r[1] = (int) filename; inreg.r[2] = 0xffd; inreg.r[4] = (int) composition; inreg.r[5] = (int) composition+(sizeof(composition[0]) * COMPOSITION_MAX); _kernel_swi(OS_File,&inreg,&outreg); } void sound_composition_debug() { int i; printf("------------------------------\n"); for(i = 0; i <= COMPOSITION_MAX; i++) { if(composition[i].Start >= 0) { printf("%5d: %3d %4d %3d %4d\n", composition[i].Start, composition[i].Note, composition[i].Volume, composition[i].Channel, composition[i].Length ); } } printf("------------------------------\n"); } void sound_composition_start(int cent) { composition_startcent = cent; current_playback_element = 0; } void sound_composition_stop() { current_playback_element = COMPOSITION_MAX; } void sound_composition_tick(int cents) { int offset_cents = cents - composition_startcent; int i; for(i = current_playback_element; i <= COMPOSITION_MAX; i++) { if(composition[i].Start <= offset_cents) { if(composition[i].Start >= 0) { sound_composition_element_play(composition[i]); current_playback_element = i + 1; } } } } int sound_note(char* note) { int octave = note[1] - 48; char *basenote = "ZZ"; int index = 1; int indexi = 0; int len = sizeof(notes)/sizeof(notes[0]); basenote[0] = note[0]; if(strlen(note) == 3) { basenote[1] = '#'; }else{ basenote[1] = 'X'; } for(indexi = 0; indexi < len; indexi++) { if(strcmp(notes[indexi],basenote) == 0) index = indexi; } return 41 + (4 * index) + ((octave - 2) * 48); } int sound_composition_incomplete() { if(composition[current_playback_element].Start < 0) return 0; else return 1; } void sound_pcm_unset(enum pcmchannel_e channel) { inreg.r[0] = channel; inreg.r[1] = 0; _kernel_swi (DataVox_Unset, &inreg, &outreg); } void sound_pcm_playsample(enum pcmchannel_e channel, enum pcmsample_e sample) { inreg.r[0] = channel; inreg.r[1] = pcmsamples[sample].data; inreg.r[2] = pcmsamples[sample].data + pcmsamples[sample].length; _kernel_swi (DataVox_SetMemory, &inreg, &outreg); // Unsigned 8-bit PCM inreg.r[0] = channel; inreg.r[1] = 1; _kernel_swi (DataVox_Type, &inreg, &outreg); // Not timed inreg.r[0] = channel; inreg.r[1] = 0; _kernel_swi (DataVox_Timed, &inreg, &outreg); // Bitrate inreg.r[0] = channel; inreg.r[1] = 4000; // I was expecting this to be 125 to 8KHz but.... No idea _kernel_swi (DataVox_Pitch, &inreg, &outreg); // Play it inreg.r[0] = channel; inreg.r[1] = -15; inreg.r[2] = 1; inreg.r[3] = 1; _kernel_swi (Sound_Control, &inreg, &outreg); } void sound_pcm_playsample_ifidle(enum pcmchannel_e channel, enum pcmsample_e sample) { inreg.r[0] = channel; _kernel_swi (DataVox_ReadAddress, &inreg, &outreg); if(!outreg.r[1]) sound_pcm_playsample(channel, sample); } void sound_pcm_loadsample(enum pcmsample_e sample, char* filename) { int length; // Attempt to get file info inreg.r[0] = 5; inreg.r[1] = (int) filename; _kernel_swi(OS_File,&inreg,&outreg); // Length will be in R4 if it exists length = outreg.r[4]; if(length > 100000) { screen_nobuffer(); while (1) printf("Sample exceeds %d bytes (%d bytes) object type is %d\n",100000,length,outreg.r[0]); } pcmsamples[sample].length = length; pcmsamples[sample].data = malloc(length); // Attempt to get file info inreg.r[0] = 16; inreg.r[1] = (int) filename; inreg.r[2] = (int) pcmsamples[sample].data; inreg.r[3] = 0; _kernel_swi(OS_File,&inreg,&outreg); }