X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsound.cpp;fp=src%2Fsound.cpp;h=930de351e081505acd3f19a3513c2e70590c8bd3;hb=44a4bdffcaf520bc1681fcc0fd330460cd49129f;hp=0000000000000000000000000000000000000000;hpb=a7c3ff9deab4cefbc76ac52d38b67e7033c63cf6;p=thunder diff --git a/src/sound.cpp b/src/sound.cpp new file mode 100644 index 0000000..930de35 --- /dev/null +++ b/src/sound.cpp @@ -0,0 +1,296 @@ +// +// Sound Handler +// +// by James Hammons +// (C) 2014 Underground Software +// +// JLH = James Hammons +// +// Who When What +// --- ---------- ----------------------------------------------------------- +// JLH 04/18/2014 Created this file +// + +#include "sound.h" +#include +#include "resource.h" + +// Function prototypes +void SoundFunc(void *, Uint8 *, int); + +// Vars +extern uint8_t voice_rom[]; // PCM data pointer + +static bool soundInitialized = false; +const float sampleBase = 22050.0/6000.0; // Btwn 5512.5 and 6000 +bool snd_go = false; +bool chan1_go = false, chan2_go = false, chan3_go = false; +bool chan4_go = false, chan5_go = false, chan6_go = false; +uint8_t * sndp1, * sndp2, * sndp3, * sndp4, * sndp5, * sndp6; +uint32_t rom_pos, end_pos; +uint32_t spos1, end_pos1; +uint32_t spos2, end_pos2; +uint32_t spos3, end_pos3; +uint32_t spos4, end_pos4; +uint32_t spos5, end_pos5; +uint32_t spos6, end_pos6; +float sample1; +uint8_t prevSamp1; +int8_t delta_x1; +float sample2; +uint8_t prevSamp2; +int8_t delta_x2; +uint16_t snd_num; +uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H +uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen }; + + +void InitSound(void) +{ + SDL_AudioSpec desired, obtained; + desired.freq = 22050; + desired.format = AUDIO_U8; + desired.channels = 1; + desired.samples = 1024; + desired.callback = SoundFunc; + desired.userdata = NULL; + // Also, should check to see if it got the hardware it needed, correct sample size, etc. + if (SDL_OpenAudio(&desired, &obtained) < 0) + { + soundInitialized = false; + printf("Couldn't open audio: %s\n", SDL_GetError()); + return; + } + + // Get that audio going! + SDL_PauseAudio(0); + soundInitialized = true; +} + + +void SpawnSound(int type, int snd, int channel/* = 0*/) +{ + extern uint32_t psg_lens[16]; + extern uint8_t * psg_adrs[16]; + extern uint32_t voc_lens[32]; + extern uint8_t * voc_adrs[32]; + extern uint32_t fm_lens[14]; + extern uint8_t * fm_adrs[14]; + + if (!soundInitialized) + return; + + snd_num = snd; +// SpawnMsg(MSHOWNUMS); + + if (type == GAMESOUND) + { + // Will that do it??? Yes!!! + snd--; + + if (channel == 0) + { + // 00 nn ss (nn # of repeats of sample ss) + uint32_t st = 0; + + if (snd & 0x40) + { + st = 0x10000; + snd &= 0x0F; + } + + spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1]; + spos1 += st; // Need to add start somewhere... + prevSamp1 = 128; + sample1 = 0; + chan1_go = true; + } + else + { + uint32_t st = 0; + + if (snd & 0x40) + { + st = 0x10000; + snd &= 0x0F; + } + + spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1]; + spos2 += st; // Need to add start somewhere... + prevSamp2 = 128; + sample2 = 0; + chan2_go = true; + } + } + else if (type == PSGSOUND) + { + if (snd_num & 0x10) // Second channel? + { + spos3 = 0; + end_pos3 = psg_lens[snd_num & 0x0F]; + sndp3 = psg_adrs[snd_num & 0x0F]; + chan3_go = true; + + if (spos3 == end_pos3) + chan3_go = false; // No sound loaded, so don't do it! + } + else // First channel + { + spos4 = 0; + end_pos4 = psg_lens[snd_num & 0x0F]; + sndp4 = psg_adrs[snd_num & 0x0F]; + chan4_go = true; + + if (spos4 == end_pos4) + chan4_go = false; // No sound loaded, so don't do it! + } + } + else if (type == FMSOUND) + { + spos5 = 0; + end_pos5 = fm_lens[snd_num]; + sndp5 = fm_adrs[snd_num]; + chan5_go = true; + + if (spos5 == end_pos5) + chan5_go = false; // No sound loaded, so don't do it! + } + else if (type == USERSOUND) + { + spos6 = 0; + end_pos6 = snd_lens[snd_num]; // User sound + sndp6 = snd_array[snd_num]; // Load pointer + chan6_go = true; + } +} + + +void SoundFunc(void * userdata, Uint8 * buff, int num) +{ + // 0-22 different sounds... + uint16_t cnt = 0, sample; + uint8_t start_samp1, end_samp1, start_samp2, end_samp2; + uint8_t samp1 = 128, samp2 = 128, samp3 = 128, + samp4 = 128, samp5 = 128, samp6 = 128; // Zero samples... + + // Kill sound... + memset(buff, 128, num); + + if (chan1_go || chan2_go || chan3_go || chan4_go || chan5_go || chan6_go) + { + while (cnt != num) + { + if (chan1_go) + { + if (sample1 < 1) + { + samp1 = voice_rom[spos1++]; + + // Kill channel 1 if done... + if (samp1 == 0xFF) + { + chan1_go = false; + samp1 = 128; + } + // RLE compression... + else if (samp1 == 0x00) + { + // # of repeats + sample1 += (float)voice_rom[spos1++] * sampleBase; + // Get last good sample + samp1 = prevSamp1; + } + else + // Keep fractional part intact + sample1 += sampleBase; + } + + prevSamp1 = samp1; // Save last sample value + sample1 -= 1.0; // Decrement repeat counter + } + +// Stretching 5KHz samples to 22KHz: +// numRepeats = 4; +// 6KHz -> 22KHz: 22/6 repeats... + if (chan2_go) + { + if (sample2 < 1) + { + samp2 = voice_rom[spos2++]; + + if (samp2 == 0xFF) + { + chan2_go = false; + samp2 = 128; // Kill channel 2 if done... + } + else if (samp2 == 0x00) // RLE compression... + { + sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats + samp2 = prevSamp2; + } + else + sample2 += sampleBase; + } + +// Delta-X values were making the samples sound like crap... +// start_samp2 += delta_x2; + prevSamp2 = samp2; + sample2 -= 1.0; + } + + if (chan3_go) + { + samp3 = sndp3[spos3++]; + + if (spos3 == end_pos3) + { + chan3_go = false; + samp3 = 128; // Kill channel 3 if done... + } + } + + if (chan4_go) + { + samp4 = sndp4[spos4++]; + + if (spos4 == end_pos4) + { + chan4_go = false; + samp4 = 128; // Kill channel 4 if done... + } + } + + if (chan5_go) + { + samp5 = sndp5[spos5++]; + + if (spos5 == end_pos5) + { + chan5_go = false; + samp5 = 128; // Kill channel 5 if done... + } + } + + if (chan6_go) + { + samp6 = sndp6[spos6++]; + + if (spos6 == end_pos6) + { + chan6_go = false; + samp6 = 128; // Kill channel 6... + } + } + + // Mix 'em... + sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640; + + // If it overflowed, clip it + if (sample & 0xFF00) + sample = (sample & 0x8000 ? 0x00 : 0xFF); + + buff[cnt++] = sample; + } + } +} +