From 7d788578b2cfe454d5c266552411820b50075d08 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Sun, 20 Jan 2013 22:26:24 -0500 Subject: Initial 8-bit sound commit. For the lulz! --- source/nds/entry.cpp | 2 +- source/snes9x.h | 2 +- source/soundux.cpp | 132 +++++++++++++++++++++++++++++++-------------------- source/soundux.h | 2 + 4 files changed, 84 insertions(+), 54 deletions(-) diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp index 8cd5c06..792608a 100644 --- a/source/nds/entry.cpp +++ b/source/nds/entry.cpp @@ -370,6 +370,7 @@ void init_sfc_setting(void) //sound settings Settings.APUEnabled = Settings.NextAPUEnabled = TRUE; Settings.FixFrequency = 1; + S9xSetEightBitConsoleSound (TRUE); Settings.H_Max = SNES_CYCLES_PER_SCANLINE; @@ -377,7 +378,6 @@ void init_sfc_setting(void) Settings.ShutdownMaster = TRUE; Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; - Settings.DisableSampleCaching = FALSE; Settings.DisableMasterVolume = FALSE; Settings.Mouse = TRUE; Settings.SuperScope = TRUE; diff --git a/source/snes9x.h b/source/snes9x.h index 6c93855..ab70efa 100644 --- a/source/snes9x.h +++ b/source/snes9x.h @@ -337,11 +337,11 @@ struct SSettings{ #ifndef FOREVER_16_BIT_SOUND bool8 SixteenBitSound; #endif + bool8 EightBitConsoleSound; // due to caching, this needs S9xSetEightBitConsoleSound() int SoundBufferSize; int SoundMixInterval; bool8 SoundEnvelopeHeightReading; bool8 DisableSoundEcho; - bool8 DisableSampleCaching; bool8 DisableMasterVolume; bool8 SoundSync; bool8 InterpolatedSound; diff --git a/source/soundux.cpp b/source/soundux.cpp index acddd0a..45e303b 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -166,6 +166,21 @@ extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); #define LAST_SAMPLE 0xffffff #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) +const int16 SQUARE_WAVE_SAMPLE[16] = {32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768,}; + +void S9xSetEightBitConsoleSound (bool8 Enabled) +{ + if (Settings.EightBitConsoleSound != Enabled) + { + Settings.EightBitConsoleSound = Enabled; + int i; + for (i = 0; i < 8; i++) + { + SoundData.channels[i].needs_decode = TRUE; + } + } +} + STATIC inline uint8 *S9xGetSampleAddress (int sample_number) { uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff); @@ -804,7 +819,7 @@ void DecodeBlock (Channel *ch) signed char sample1, sample2; unsigned char i; bool invalid_header; - + if (Settings.AltSampleDecode) { if (Settings.AltSampleDecode < 3) @@ -820,74 +835,87 @@ void DecodeBlock (Channel *ch) ch->block = ch->decoded; return; } - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + if (Settings.EightBitConsoleSound) + { + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + ch->block = ch->decoded; + memcpy(ch->decoded, SQUARE_WAVE_SAMPLE, sizeof(SQUARE_WAVE_SAMPLE)); + } + else + { + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; + filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; - compressed++; - signed short *raw = ch->block = ch->decoded; + compressed++; + signed short *raw = ch->block = ch->decoded; - // Seperate out the header parts used for decoding + // Seperate out the header parts used for decoding - shift = filter >> 4; + shift = filter >> 4; - // Header validity check: if range(shift) is over 12, ignore - // all bits of the data for that block except for the sign bit of each - invalid_header = (shift >= 0xD); + // Header validity check: if range(shift) is over 12, ignore + // all bits of the data for that block except for the sign bit of each + invalid_header = (shift >= 0xD); - filter = filter&0x0c; + filter = filter&0x0c; - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - //Sample 2 = Bottom Nibble, Sign Extended. - sample2 >>= 4; - //Sample 1 = Top Nibble, shifted down and Sign Extended. - sample1 >>= 4; - if (invalid_header) { sample1>>=3; sample2>>=3; } + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + sample1 >>= 4; + if (invalid_header) { sample1>>=3; sample2>>=3; } - for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ - out=(((nybblesmp) ? sample2 : sample1) << shift); - out >>= 1; + for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ + out=(((nybblesmp) ? sample2 : sample1) << shift); + out >>= 1; - switch(filter) - { - case 0x00: - // Method0 - [Smp] - break; + switch(filter) + { + case 0x00: + // Method0 - [Smp] + break; - case 0x04: - // Method1 - [Delta]+[Smp-1](15/16) - out+=(prev0>>1)+((-prev0)>>5); - break; + case 0x04: + // Method1 - [Delta]+[Smp-1](15/16) + out+=(prev0>>1)+((-prev0)>>5); + break; - case 0x08: - // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) - out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); - break; + case 0x08: + // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) + out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); + break; - default: - // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) - out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); - break; + default: + // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) + out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); + break; + } + CLIP16(out); + *raw++ = (signed short)(out<<1); + prev1=(signed short)prev0; + prev0=(signed short)(out<<1); } - CLIP16(out); - *raw++ = (signed short)(out<<1); - prev1=(signed short)prev0; - prev0=(signed short)(out<<1); } + ch->previous [0] = prev0; + ch->previous [1] = prev1; } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - - ch->block_pointer += 9; + ch->block_pointer += 9; } diff --git a/source/soundux.h b/source/soundux.h index 8fb8396..224d24a 100644 --- a/source/soundux.h +++ b/source/soundux.h @@ -220,6 +220,8 @@ typedef struct EXTERN_C SSoundData SoundData; +void S9xSetEightBitConsoleSound (bool8 Enabled); + void S9xSetSoundVolume (int channel, short volume_left, short volume_right); void S9xSetSoundFrequency (int channel, int hertz); void S9xSetSoundHertz (int channel, int hertz); -- cgit v1.2.3 From 40596a7d6810c2d3bc2db28e8f9c2b825972d21d Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Mon, 21 Jan 2013 22:35:21 -0500 Subject: Triangle wave ALL the channels! --- source/soundux.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index 45e303b..a3103e7 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -166,8 +166,6 @@ extern "C" void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); #define LAST_SAMPLE 0xffffff #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) -const int16 SQUARE_WAVE_SAMPLE[16] = {32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, -32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768,}; - void S9xSetEightBitConsoleSound (bool8 Enabled) { if (Settings.EightBitConsoleSound != Enabled) @@ -838,13 +836,93 @@ void DecodeBlock (Channel *ch) if (Settings.EightBitConsoleSound) { - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - filter = *compressed; - if ((ch->last_block = filter & 1)) + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((ch->last_block = filter & 1)) ch->loop = (filter & 2) != 0; - ch->block = ch->decoded; - memcpy(ch->decoded, SQUARE_WAVE_SAMPLE, sizeof(SQUARE_WAVE_SAMPLE)); + + compressed++; + signed short *raw = ch->block = ch->decoded; + + // Seperate out the header parts used for decoding + + shift = filter >> 4; + + // Header validity check: if range(shift) is over 12, ignore + // all bits of the data for that block except for the sign bit of each + invalid_header = (shift >= 0xD); + + filter = filter&0x0c; + + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + + int16 amplitude = 0; + + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + //Sample 2 = Bottom Nibble, Sign Extended. + sample2 >>= 4; + //Sample 1 = Top Nibble, shifted down and Sign Extended. + sample1 >>= 4; + if (invalid_header) { sample1>>=3; sample2>>=3; } + + for (int nybblesmp = 0; nybblesmp<2; nybblesmp++){ + out=(((nybblesmp) ? sample2 : sample1) << shift); + out >>= 1; + + switch(filter) + { + case 0x00: + // Method0 - [Smp] + break; + + case 0x04: + // Method1 - [Delta]+[Smp-1](15/16) + out+=(prev0>>1)+((-prev0)>>5); + break; + + case 0x08: + // Method2 - [Delta]+[Smp-1](61/32)-[Smp-2](15/16) + out+=(prev0)+((-(prev0 +(prev0>>1)))>>5)-(prev1>>1)+(prev1>>5); + break; + + default: + // Method3 - [Delta]+[Smp-1](115/64)-[Smp-2](13/16) + out+=(prev0)+((-(prev0 + (prev0<<2) + (prev0<<3)))>>7)-(prev1>>1)+((prev1+(prev1>>1))>>4); + break; + + } + CLIP16(out); + int16 result = (signed short)(out<<1); + if (abs(result) > amplitude) + amplitude = abs(result); + prev1=(signed short)prev0; + prev0=(signed short)(out<<1); + } + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + // Make it a square wave with an amplitude equivalent to that + // of the highest amplitude sample of the block. + /* for (i = 0; i < 8; i++) + ch->decoded[i] = amplitude; + for (i = 8; i < 16; i++) + ch->decoded[i] = -amplitude; */ + // Make it a triangle wave with an amplitude equivalent to that + // of the highest amplitude sample of the block. + ch->decoded[0] = ch->decoded[8] = 0; + ch->decoded[1] = ch->decoded[7] = amplitude / 4; + ch->decoded[2] = ch->decoded[6] = amplitude / 2; + ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4; + ch->decoded[4] = amplitude; + ch->decoded[9] = ch->decoded[15] = -(amplitude / 4); + ch->decoded[10] = ch->decoded[14] = -(amplitude / 2); + ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4); + ch->decoded[12] = -amplitude; } else { -- cgit v1.2.3 From 0a2041d1ce3a5ce62df279371ce6857bb8b11205 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 8 Feb 2013 05:50:37 -0500 Subject: Add square waves for waves not matching sines or triangles. Add noise for drums exceeding a certain "randomness" threshold. For now that's defined as total variance from a sample to its neighbo(u)r in a block of 16 samples. --- source/soundux.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 17 deletions(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index d8ce223..b8df25a 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -840,6 +840,9 @@ void DecodeBlock (Channel *ch) filter = *compressed; if ((ch->last_block = filter & 1)) ch->loop = (filter & 2) != 0; + + int16 interim[16]; + uint8 interim_byte; compressed++; signed short *raw = ch->block = ch->decoded; @@ -899,29 +902,80 @@ void DecodeBlock (Channel *ch) int16 result = (signed short)(out<<1); if (abs(result) > amplitude) amplitude = abs(result); + interim[interim_byte++] = out; prev1=(signed short)prev0; prev0=(signed short)(out<<1); } } ch->previous [0] = prev0; ch->previous [1] = prev1; - // Make it a square wave with an amplitude equivalent to that - // of the highest amplitude sample of the block. - /* for (i = 0; i < 8; i++) - ch->decoded[i] = amplitude; - for (i = 8; i < 16; i++) - ch->decoded[i] = -amplitude; */ - // Make it a triangle wave with an amplitude equivalent to that - // of the highest amplitude sample of the block. - ch->decoded[0] = ch->decoded[8] = 0; - ch->decoded[1] = ch->decoded[7] = amplitude / 4; - ch->decoded[2] = ch->decoded[6] = amplitude / 2; - ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4; - ch->decoded[4] = amplitude; - ch->decoded[9] = ch->decoded[15] = -(amplitude / 4); - ch->decoded[10] = ch->decoded[14] = -(amplitude / 2); - ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4); - ch->decoded[12] = -amplitude; + + int32 total_deviation_from_previous = 0; + for (i = 1; i < 16; i++) + total_deviation_from_previous += abs(interim[i] - interim[i - 1]); + if (total_deviation_from_previous >= (int32) amplitude * 4) + { + /* Looks like noise. Generate noise. */ + for (i = 0; i < 16; i++) + { + int feedback = (noise_gen << 13) ^ (noise_gen << 14); + noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); + ch->decoded[i] = (noise_gen << 17) >> 17; + } + } + else if (interim[0] < interim[1] && interim[1] < interim[2] + && interim[2] < interim[3] + && interim[4] > interim[5] && interim[5] > interim[6] + && interim[6] > interim[7] && interim[7] > interim[8] + && interim[8] > interim[9] && interim[9] > interim[10] + && interim[10] > interim[11] + && interim[12] < interim[13] && interim[13] < interim[14] + && interim[14] < interim[15]) + { + /* Looks like a sine or triangle wave. Make it a + * triangle wave with an amplitude equivalent to that + * of the highest amplitude sample of the block. */ + ch->decoded[0] = ch->decoded[8] = 0; + ch->decoded[1] = ch->decoded[7] = amplitude / 4; + ch->decoded[2] = ch->decoded[6] = amplitude / 2; + ch->decoded[3] = ch->decoded[5] = amplitude * 3 / 4; + ch->decoded[4] = amplitude; + ch->decoded[9] = ch->decoded[15] = -(amplitude / 4); + ch->decoded[10] = ch->decoded[14] = -(amplitude / 2); + ch->decoded[11] = ch->decoded[13] = -(amplitude * 3 / 4); + ch->decoded[12] = -amplitude; + } + else if (interim[0] > interim[1] && interim[1] > interim[2] + && interim[2] > interim[3] + && interim[4] < interim[5] && interim[5] < interim[6] + && interim[6] < interim[7] && interim[7] < interim[8] + && interim[8] < interim[9] && interim[9] < interim[10] + && interim[10] < interim[11] + && interim[12] > interim[13] && interim[13] > interim[14] + && interim[14] > interim[15]) + { + /* Inverted triangle wave. */ + ch->decoded[0] = ch->decoded[8] = 0; + ch->decoded[1] = ch->decoded[7] = -(amplitude / 4); + ch->decoded[2] = ch->decoded[6] = -(amplitude / 2); + ch->decoded[3] = ch->decoded[5] = -(amplitude * 3 / 4); + ch->decoded[4] = -amplitude; + ch->decoded[9] = ch->decoded[15] = amplitude / 4; + ch->decoded[10] = ch->decoded[14] = amplitude / 2; + ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4; + ch->decoded[12] = amplitude; + } + else + { + // Make it a square wave with an amplitude equivalent to that + // of the highest amplitude sample of the block. + // But actually put half of the amplitude, because + // square waves are just loud. + for (i = 0; i < 8; i++) + ch->decoded[i] = amplitude / 2; + for (i = 8; i < 16; i++) + ch->decoded[i] = -amplitude / 2; + } } else { -- cgit v1.2.3 From 3834297fae931341c40bb293efb2f10cf7549d26 Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 8 Feb 2013 15:46:33 -0500 Subject: Fix write to uninitialised memory in 8-bit sound. --- source/soundux.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/soundux.cpp b/source/soundux.cpp index b8df25a..399b04b 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -842,7 +842,7 @@ void DecodeBlock (Channel *ch) ch->loop = (filter & 2) != 0; int16 interim[16]; - uint8 interim_byte; + uint8 interim_byte = 0; compressed++; signed short *raw = ch->block = ch->decoded; @@ -974,7 +974,7 @@ void DecodeBlock (Channel *ch) for (i = 0; i < 8; i++) ch->decoded[i] = amplitude / 2; for (i = 8; i < 16; i++) - ch->decoded[i] = -amplitude / 2; + ch->decoded[i] = -(amplitude / 2); } } else -- cgit v1.2.3 From 9ef4103ea59d3048f4a692c038a75dc933ff28ac Mon Sep 17 00:00:00 2001 From: Nebuleon Fumika Date: Fri, 8 Feb 2013 16:08:48 -0500 Subject: Add two more half-wave types to try to correct the pitch of notes that are one octave too high. --- source/soundux.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/source/soundux.cpp b/source/soundux.cpp index 399b04b..6998166 100644 --- a/source/soundux.cpp +++ b/source/soundux.cpp @@ -965,6 +965,48 @@ void DecodeBlock (Channel *ch) ch->decoded[11] = ch->decoded[13] = amplitude * 3 / 4; ch->decoded[12] = amplitude; } + else if (interim[0] < interim[1] && interim[1] < interim[2] + && interim[2] < interim[3] && interim[3] < interim[4] + && interim[4] < interim[5] && interim[5] < interim[6] + && interim[6] < interim[7] + && interim[8] > interim[9] && interim[9] > interim[10] + && interim[10] > interim[11] && interim[11] > interim[12] + && interim[12] > interim[13] && interim[13] > interim[14] + && interim[14] > interim[15]) + { + /* Looks like a V wave. Make it a half-triangle wave + * with an amplitude equivalent to that + * of the highest amplitude sample of the block. */ + ch->decoded[0] = 0; + ch->decoded[1] = ch->decoded[15] = amplitude / 8; + ch->decoded[2] = ch->decoded[14] = amplitude / 4; + ch->decoded[3] = ch->decoded[13] = amplitude * 3 / 8; + ch->decoded[4] = ch->decoded[12] = amplitude / 2; + ch->decoded[5] = ch->decoded[11] = amplitude * 5 / 8; + ch->decoded[6] = ch->decoded[10] = amplitude * 3 / 4; + ch->decoded[7] = ch->decoded[9] = amplitude * 7 / 8; + ch->decoded[8] = amplitude; + } + else if (interim[0] > interim[1] && interim[1] > interim[2] + && interim[2] > interim[3] && interim[3] > interim[4] + && interim[4] > interim[5] && interim[5] > interim[6] + && interim[6] > interim[7] + && interim[8] < interim[9] && interim[9] < interim[10] + && interim[10] < interim[11] && interim[11] < interim[12] + && interim[12] < interim[13] && interim[13] < interim[14] + && interim[14] < interim[15]) + { + /* Inverted V wave. */ + ch->decoded[0] = 0; + ch->decoded[1] = ch->decoded[15] = -(amplitude / 8); + ch->decoded[2] = ch->decoded[14] = -(amplitude / 4); + ch->decoded[3] = ch->decoded[13] = -(amplitude * 3 / 8); + ch->decoded[4] = ch->decoded[12] = -(amplitude / 2); + ch->decoded[5] = ch->decoded[11] = -(amplitude * 5 / 8); + ch->decoded[6] = ch->decoded[10] = -(amplitude * 3 / 4); + ch->decoded[7] = ch->decoded[9] = -(amplitude * 7 / 8); + ch->decoded[8] = -amplitude; + } else { // Make it a square wave with an amplitude equivalent to that -- cgit v1.2.3