mirror of
https://github.com/stevenhowes/CTheEscape.git
synced 2026-05-27 00:03:27 +01:00
317 lines
6.6 KiB
C
317 lines
6.6 KiB
C
#include <stdio.h>
|
|
#include "swis.h"
|
|
#include <kernel.h>
|
|
#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_nullsamples()
|
|
{
|
|
int i;
|
|
for(i=0; i<PCMSAMPLE_MAX; i++)
|
|
{
|
|
pcmsamples[i].data = NULL;
|
|
pcmsamples[i].length = -1;
|
|
}
|
|
}
|
|
|
|
void sound_pcm_clearsamples()
|
|
{
|
|
int i;
|
|
for(i = 0; i < PCMSAMPLE_MAX; i++)
|
|
{
|
|
if(pcmsamples[i].data)
|
|
{
|
|
free(pcmsamples[i].data);
|
|
pcmsamples[i].data = NULL;
|
|
pcmsamples[i].length = -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)
|
|
{
|
|
if(!pcmsamples[sample].data)
|
|
{
|
|
screen_nobuffer();
|
|
while(1)
|
|
printf("PCM sample %d played without load\n",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)
|
|
{
|
|
if(!pcmsamples[sample].data)
|
|
{
|
|
screen_nobuffer();
|
|
while(1)
|
|
printf("PCM sample %d played without load\n",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;
|
|
|
|
if(pcmsamples[sample].data)
|
|
return;
|
|
|
|
// 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 > 96000)
|
|
{
|
|
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);
|
|
}
|