diff options
Diffstat (limited to 'source/soundux.c')
-rw-r--r-- | source/soundux.c | 2845 |
1 files changed, 1429 insertions, 1416 deletions
diff --git a/source/soundux.c b/source/soundux.c index e021381..4e7fe57 100644 --- a/source/soundux.c +++ b/source/soundux.c @@ -1,6 +1,6 @@ /******************************************************************************* Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and Jerremy Koot (jkoot@snes9x.com) @@ -43,46 +43,46 @@ S-DD1 C emulator code (c) Copyright 2003 Brad Jorsch with research by Andreas Naive and John Weidman - + S-RTC C emulator code (c) Copyright 2001 John Weidman - + ST010 C++ emulator code (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - Super FX C emulator code + Super FX C emulator code (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + - Specific ports contains the works of other authors. See headers in individual files. - + Snes9x homepage: http://www.snes9x.com - + Permission to use, copy, modify and distribute Snes9x in both binary and source form, for non-commercial purposes, is hereby granted without fee, providing that this license information and copyright notice appear with all copies and any derived work. - + This software is provided 'as-is', without any express or implied warranty. In no event shall the authors be held liable for any damages arising from the use of this software. - + Snes9x is freeware for PERSONAL USE only. Commercial users should seek permission of the copyright holders first. Commercial use includes charging money for Snes9x or software derived from Snes9x. - + The copyright holders request that bug fixes and improvements to the code should be forwarded to them so everyone can benefit from the modifications in future versions. - + Super NES and Super Nintendo Entertainment System are trademarks of Nintendo Co., Limited and its subsidiary companies. *******************************************************************************/ @@ -98,31 +98,31 @@ #include <fcntl.h> #define CLIP16(v) \ - if ((v) < -32768) \ + if ((v) < -32768) \ (v) = -32768; \ - else \ - if ((v) > 32767) \ + else \ + if ((v) > 32767) \ (v) = 32767 #define CLIP16_latch(v,l) \ - if ((v) < -32768) \ + if ((v) < -32768) \ { (v) = -32768; (l)++; }\ - else \ - if ((v) > 32767) \ + else \ + if ((v) > 32767) \ { (v) = 32767; (l)++; } #define CLIP24(v) \ - if ((v) < -8388608) \ + if ((v) < -8388608) \ (v) = -8388608; \ - else \ - if ((v) > 8388607) \ + else \ + if ((v) > 8388607) \ (v) = 8388607 #define CLIP8(v) \ - if ((v) < -128) \ + if ((v) < -128) \ (v) = -128; \ - else \ - if ((v) > 127) \ + else \ + if ((v) > 127) \ (v) = 127 #include "snes9x.h" @@ -157,8 +157,8 @@ static int32 noise_gen; #define VOL_DIV16 0x0080 #define ENVX_SHIFT 24 -void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); -void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); +void DecodeBlockAsm(int8*, int16*, int32*, int32*); +void DecodeBlockAsm2(int8*, int16*, int32*, int32*); // F is channel's current frequency and M is the 16-bit modulation waveform // from the previous channel multiplied by the current envelope volume level. @@ -168,1186 +168,1192 @@ void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); #define LAST_SAMPLE 0xffffff #define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) -void S9xSetEightBitConsoleSound (bool8 Enabled) +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; - } - } + 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) +STATIC inline uint8* S9xGetSampleAddress(int sample_number) { - uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff); - return (IAPU.RAM + addr); + uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff); + return (IAPU.RAM + addr); } -void S9xAPUSetEndOfSample (int i, Channel *ch) +void S9xAPUSetEndOfSample(int i, Channel* ch) { - ch->state = SOUND_SILENT; - ch->mode = MODE_NONE; - APU.DSP [APU_ENDX] |= 1 << i; - APU.DSP [APU_KON] &= ~(1 << i); - APU.DSP [APU_KOFF] &= ~(1 << i); - APU.KeyedChannels &= ~(1 << i); + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + APU.DSP [APU_ENDX] |= 1 << i; + APU.DSP [APU_KON] &= ~(1 << i); + APU.DSP [APU_KOFF] &= ~(1 << i); + APU.KeyedChannels &= ~(1 << i); } #ifdef __DJGPP -END_OF_FUNCTION (S9xAPUSetEndOfSample) +END_OF_FUNCTION(S9xAPUSetEndOfSample) #endif -void S9xAPUSetEndX (int ch) +void S9xAPUSetEndX(int ch) { - APU.DSP [APU_ENDX] |= 1 << ch; + APU.DSP [APU_ENDX] |= 1 << ch; } #ifdef __DJGPP -END_OF_FUNCTION (S9xAPUSetEndX) +END_OF_FUNCTION(S9xAPUSetEndX) #endif -void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction, int target) +void S9xSetEnvRate(Channel* ch, unsigned long rate, int direction, int target) { - ch->envx_target = target; - - if (rate == ~0UL) - { - ch->direction = 0; - rate = 0; - } - else - ch->direction = direction; - - static int64 steps [] = - { - // 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 - 0, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 619, - (int64) FIXED_POINT * 1000 * 619, - (int64) FIXED_POINT * 1000 * 128, - (int64) FIXED_POINT * 1000 * 1, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 55, - (int64) FIXED_POINT * 1000 * 64, - (int64) FIXED_POINT * 1000 * 619 - }; - - if (rate == 0 || so.playback_rate == 0) - ch->erate = 0; - else - { - ch->erate = (unsigned long) - (steps [ch->state] / (rate * so.playback_rate)); - } + ch->envx_target = target; + + if (rate == ~0UL) + { + ch->direction = 0; + rate = 0; + } + else + ch->direction = direction; + + static int64 steps [] = + { + // 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 + 0, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 619, + (int64) FIXED_POINT * 1000 * 619, + (int64) FIXED_POINT * 1000 * 128, + (int64) FIXED_POINT * 1000 * 1, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 55, + (int64) FIXED_POINT * 1000 * 64, + (int64) FIXED_POINT * 1000 * 619 + }; + + if (rate == 0 || so.playback_rate == 0) + ch->erate = 0; + else + { + ch->erate = (unsigned long) + (steps [ch->state] / (rate * so.playback_rate)); + } } #ifdef __DJGPP END_OF_FUNCTION(S9xSetEnvRate); #endif -void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, - int target) +void S9xSetEnvelopeRate(int channel, unsigned long rate, int direction, + int target) { - S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target); + S9xSetEnvRate(&SoundData.channels [channel], rate, direction, target); } #ifdef __DJGPP END_OF_FUNCTION(S9xSetEnvelopeRate); #endif -void S9xSetSoundVolume (int channel, short volume_left, short volume_right) +void S9xSetSoundVolume(int channel, short volume_left, short volume_right) { - Channel *ch = &SoundData.channels[channel]; - ch->volume_left = volume_left; - ch->volume_right = volume_right; - ch-> left_vol_level = (ch->envx * volume_left) / 128; - ch->right_vol_level = (ch->envx * volume_right) / 128; + Channel* ch = &SoundData.channels[channel]; + ch->volume_left = volume_left; + ch->volume_right = volume_right; + ch-> left_vol_level = (ch->envx * volume_left) / 128; + ch->right_vol_level = (ch->envx * volume_right) / 128; } -void S9xSetMasterVolume (short volume_left, short volume_right) +void S9xSetMasterVolume(short volume_left, short volume_right) { - if (Settings.DisableMasterVolume || SNESGameFixes.EchoOnlyOutput) - { - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - } - else - { - SoundData.master_volume [0] = volume_left; - SoundData.master_volume [1] = volume_right; - } + if (Settings.DisableMasterVolume || SNESGameFixes.EchoOnlyOutput) + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + else + { + SoundData.master_volume [0] = volume_left; + SoundData.master_volume [1] = volume_right; + } } -void S9xSetEchoVolume (short volume_left, short volume_right) +void S9xSetEchoVolume(short volume_left, short volume_right) { - SoundData.echo_volume [0] = volume_left; - SoundData.echo_volume [1] = volume_right; + SoundData.echo_volume [0] = volume_left; + SoundData.echo_volume [1] = volume_right; } -void S9xSetEchoEnable (uint8 byte) +void S9xSetEchoEnable(uint8 byte) { - SoundData.echo_channel_enable = byte; - if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) - byte = 0; - if (byte && !SoundData.echo_enable) - { - memset (Echo, 0, sizeof (Echo)); - memset (Loop, 0, sizeof (Loop)); - } - - SoundData.echo_enable = byte; - int i; - for (i = 0; i < NUM_CHANNELS; i++) - { - if (byte & (1 << i)) - SoundData.channels [i].echo_buf_ptr = EchoBuffer; - else - SoundData.channels [i].echo_buf_ptr = DummyEchoBuffer; - } + SoundData.echo_channel_enable = byte; + if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) + byte = 0; + if (byte && !SoundData.echo_enable) + { + memset(Echo, 0, sizeof(Echo)); + memset(Loop, 0, sizeof(Loop)); + } + + SoundData.echo_enable = byte; + int i; + for (i = 0; i < NUM_CHANNELS; i++) + { + if (byte & (1 << i)) + SoundData.channels [i].echo_buf_ptr = EchoBuffer; + else + SoundData.channels [i].echo_buf_ptr = DummyEchoBuffer; + } } -void S9xSetEchoFeedback (int feedback) +void S9xSetEchoFeedback(int feedback) { - CLIP8(feedback); - SoundData.echo_feedback = feedback; + CLIP8(feedback); + SoundData.echo_feedback = feedback; } -void S9xSetEchoDelay (int delay) +void S9xSetEchoDelay(int delay) { - SoundData.echo_buffer_size = (512 * delay * so.playback_rate) / 32000; - SoundData.echo_buffer_size <<= 1; - if (SoundData.echo_buffer_size) - SoundData.echo_ptr %= SoundData.echo_buffer_size; - else - SoundData.echo_ptr = 0; - S9xSetEchoEnable (APU.DSP [APU_EON]); + SoundData.echo_buffer_size = (512 * delay * so.playback_rate) / 32000; + SoundData.echo_buffer_size <<= 1; + if (SoundData.echo_buffer_size) + SoundData.echo_ptr %= SoundData.echo_buffer_size; + else + SoundData.echo_ptr = 0; + S9xSetEchoEnable(APU.DSP [APU_EON]); } -void S9xSetEchoWriteEnable (uint8 byte) +void S9xSetEchoWriteEnable(uint8 byte) { - SoundData.echo_write_enabled = byte; - S9xSetEchoDelay (APU.DSP [APU_EDL] & 15); + SoundData.echo_write_enabled = byte; + S9xSetEchoDelay(APU.DSP [APU_EDL] & 15); } -void S9xSetFrequencyModulationEnable (uint8 byte) +void S9xSetFrequencyModulationEnable(uint8 byte) { - SoundData.pitch_mod = byte & ~1; + SoundData.pitch_mod = byte & ~1; } -void S9xSetSoundKeyOff (int channel) +void S9xSetSoundKeyOff(int channel) { - Channel *ch = &SoundData.channels[channel]; - - if (ch->state != SOUND_SILENT) - { - ch->state = SOUND_RELEASE; - ch->mode = MODE_RELEASE; - S9xSetEnvRate (ch, 8, -1, 0); - } + Channel* ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT) + { + ch->state = SOUND_RELEASE; + ch->mode = MODE_RELEASE; + S9xSetEnvRate(ch, 8, -1, 0); + } } -void S9xFixSoundAfterSnapshotLoad () +void S9xFixSoundAfterSnapshotLoad() { - SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); - SoundData.echo_channel_enable = APU.DSP [APU_EON]; - S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); - S9xSetEchoFeedback ((signed char) APU.DSP [APU_EFB]); - - S9xSetFilterCoefficient (0, (signed char) APU.DSP [APU_C0]); - S9xSetFilterCoefficient (1, (signed char) APU.DSP [APU_C1]); - S9xSetFilterCoefficient (2, (signed char) APU.DSP [APU_C2]); - S9xSetFilterCoefficient (3, (signed char) APU.DSP [APU_C3]); - S9xSetFilterCoefficient (4, (signed char) APU.DSP [APU_C4]); - S9xSetFilterCoefficient (5, (signed char) APU.DSP [APU_C5]); - S9xSetFilterCoefficient (6, (signed char) APU.DSP [APU_C6]); - S9xSetFilterCoefficient (7, (signed char) APU.DSP [APU_C7]); - int i; - for (i = 0; i < 8; i++) - { - SoundData.channels[i].needs_decode = TRUE; - S9xSetSoundFrequency (i, SoundData.channels[i].hertz); - SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; - SoundData.channels [i].next_sample = 0; - SoundData.channels [i].interpolate = 0; - SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0]; - SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1]; - } - IAPU.Scanline = 0; + SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); + SoundData.echo_channel_enable = APU.DSP [APU_EON]; + S9xSetEchoDelay(APU.DSP [APU_EDL] & 0xf); + S9xSetEchoFeedback((signed char) APU.DSP [APU_EFB]); + + S9xSetFilterCoefficient(0, (signed char) APU.DSP [APU_C0]); + S9xSetFilterCoefficient(1, (signed char) APU.DSP [APU_C1]); + S9xSetFilterCoefficient(2, (signed char) APU.DSP [APU_C2]); + S9xSetFilterCoefficient(3, (signed char) APU.DSP [APU_C3]); + S9xSetFilterCoefficient(4, (signed char) APU.DSP [APU_C4]); + S9xSetFilterCoefficient(5, (signed char) APU.DSP [APU_C5]); + S9xSetFilterCoefficient(6, (signed char) APU.DSP [APU_C6]); + S9xSetFilterCoefficient(7, (signed char) APU.DSP [APU_C7]); + int i; + for (i = 0; i < 8; i++) + { + SoundData.channels[i].needs_decode = TRUE; + S9xSetSoundFrequency(i, SoundData.channels[i].hertz); + SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; + SoundData.channels [i].next_sample = 0; + SoundData.channels [i].interpolate = 0; + SoundData.channels [i].previous [0] = (int32) + SoundData.channels [i].previous16 [0]; + SoundData.channels [i].previous [1] = (int32) + SoundData.channels [i].previous16 [1]; + } + IAPU.Scanline = 0; } -void S9xSetFilterCoefficient (int tap, int value) +void S9xSetFilterCoefficient(int tap, int value) { - FilterTaps [tap & 7] = value; - if (value == 0 || (tap == 0 && value == 127)) - FilterTapDefinitionBitfield &= ~(1 << (tap & 7)); - else - FilterTapDefinitionBitfield |= 1 << (tap & 7); + FilterTaps [tap & 7] = value; + if (value == 0 || (tap == 0 && value == 127)) + FilterTapDefinitionBitfield &= ~(1 << (tap & 7)); + else + FilterTapDefinitionBitfield |= 1 << (tap & 7); } -void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate, - int sustain_rate, int sustain_level, int release_rate) +void S9xSetSoundADSR(int channel, int attack_rate, int decay_rate, + int sustain_rate, int sustain_level, int release_rate) { - Channel *ch = &SoundData.channels[channel]; - ch->attack_rate = attack_rate; - ch->decay_rate = decay_rate; - ch->sustain_rate = sustain_rate; - ch->release_rate = release_rate; - ch->sustain_level = sustain_level + 1; - - switch (SoundData.channels[channel].state) - { - case SOUND_ATTACK: - S9xSetEnvRate (ch, attack_rate, 1, 127); - break; - - case SOUND_DECAY: - S9xSetEnvRate (ch, decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3); - break; - case SOUND_SUSTAIN: - S9xSetEnvRate (ch, sustain_rate, -1, 0); - break; - } + Channel* ch = &SoundData.channels[channel]; + ch->attack_rate = attack_rate; + ch->decay_rate = decay_rate; + ch->sustain_rate = sustain_rate; + ch->release_rate = release_rate; + ch->sustain_level = sustain_level + 1; + + switch (SoundData.channels[channel].state) + { + case SOUND_ATTACK: + S9xSetEnvRate(ch, attack_rate, 1, 127); + break; + + case SOUND_DECAY: + S9xSetEnvRate(ch, decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3); + break; + case SOUND_SUSTAIN: + S9xSetEnvRate(ch, sustain_rate, -1, 0); + break; + } } -void S9xSetEnvelopeHeight (int channel, int level) +void S9xSetEnvelopeHeight(int channel, int level) { - Channel *ch = &SoundData.channels[channel]; - - ch->envx = level; - ch->envxx = level << ENVX_SHIFT; - - ch->left_vol_level = (level * ch->volume_left) / 128; - ch->right_vol_level = (level * ch->volume_right) / 128; - - if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) - { - S9xAPUSetEndOfSample (channel, ch); - } + Channel* ch = &SoundData.channels[channel]; + + ch->envx = level; + ch->envxx = level << ENVX_SHIFT; + + ch->left_vol_level = (level * ch->volume_left) / 128; + ch->right_vol_level = (level * ch->volume_right) / 128; + + if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) + S9xAPUSetEndOfSample(channel, ch); } -int S9xGetEnvelopeHeight (int channel) +int S9xGetEnvelopeHeight(int channel) { - if ((Settings.SoundEnvelopeHeightReading || - SNESGameFixes.SoundEnvelopeHeightReading2) && - SoundData.channels[channel].state != SOUND_SILENT && - SoundData.channels[channel].state != SOUND_GAIN) - { - return (SoundData.channels[channel].envx); - } - - //siren fix from XPP - if (SNESGameFixes.SoundEnvelopeHeightReading2 && - SoundData.channels[channel].state != SOUND_SILENT) - { - return (SoundData.channels[channel].envx); - } - - return (0); + if ((Settings.SoundEnvelopeHeightReading || + SNESGameFixes.SoundEnvelopeHeightReading2) && + SoundData.channels[channel].state != SOUND_SILENT && + SoundData.channels[channel].state != SOUND_GAIN) + return (SoundData.channels[channel].envx); + + //siren fix from XPP + if (SNESGameFixes.SoundEnvelopeHeightReading2 && + SoundData.channels[channel].state != SOUND_SILENT) + return (SoundData.channels[channel].envx); + + return (0); } #if 1 -void S9xSetSoundSample (int channel, uint16 sample_number) +void S9xSetSoundSample(int channel, uint16 sample_number) { } #else -void S9xSetSoundSample (int channel, uint16 sample_number) +void S9xSetSoundSample(int channel, uint16 sample_number) { - register Channel *ch = &SoundData.channels[channel]; - - if (ch->state != SOUND_SILENT && - sample_number != ch->sample_number) - { - int keep = ch->state; - ch->state = SOUND_SILENT; - ch->sample_number = sample_number; - ch->loop = FALSE; - ch->needs_decode = TRUE; - ch->last_block = FALSE; - ch->previous [0] = ch->previous[1] = 0; - uint8 *dir = S9xGetSampleAddress (sample_number); - ch->block_pointer = READ_WORD (dir); - ch->sample_pointer = 0; - ch->state = keep; - } + register Channel* ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT && + sample_number != ch->sample_number) + { + int keep = ch->state; + ch->state = SOUND_SILENT; + ch->sample_number = sample_number; + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous [0] = ch->previous[1] = 0; + uint8* dir = S9xGetSampleAddress(sample_number); + ch->block_pointer = READ_WORD(dir); + ch->sample_pointer = 0; + ch->state = keep; + } } #endif -void S9xSetSoundFrequency (int channel, int hertz) +void S9xSetSoundFrequency(int channel, int hertz) { - if (so.playback_rate) - { - if (SoundData.channels[channel].type == SOUND_NOISE) - hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f]; - SoundData.channels[channel].frequency = (int) - (((int64) hertz * FIXED_POINT) / so.playback_rate); - if (Settings.FixFrequency) - { - SoundData.channels[channel].frequency = - (unsigned long) (SoundData.channels[channel].frequency * 49 / 50); - } - } + if (so.playback_rate) + { + if (SoundData.channels[channel].type == SOUND_NOISE) + hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f]; + SoundData.channels[channel].frequency = (int) + (((int64) hertz * FIXED_POINT) / so.playback_rate); + if (Settings.FixFrequency) + { + SoundData.channels[channel].frequency = + (unsigned long)(SoundData.channels[channel].frequency * 49 / 50); + } + } } -void S9xSetSoundHertz (int channel, int hertz) +void S9xSetSoundHertz(int channel, int hertz) { - SoundData.channels[channel].hertz = hertz; - S9xSetSoundFrequency (channel, hertz); + SoundData.channels[channel].hertz = hertz; + S9xSetSoundFrequency(channel, hertz); } -void S9xSetSoundType (int channel, int type_of_sound) +void S9xSetSoundType(int channel, int type_of_sound) { - SoundData.channels[channel].type = type_of_sound; + SoundData.channels[channel].type = type_of_sound; } -bool8 S9xSetSoundMute (bool8 mute) +bool8 S9xSetSoundMute(bool8 mute) { - bool8 old = so.mute_sound; - so.mute_sound = mute; - return (old); + bool8 old = so.mute_sound; + so.mute_sound = mute; + return (old); } -void AltDecodeBlock (Channel *ch) +void AltDecodeBlock(Channel* ch) { - if (ch->block_pointer >= 0x10000 - 9) - { - ch->last_block = TRUE; - ch->loop = FALSE; - ch->block = ch->decoded; - memset ((void *) ch->decoded, 0, sizeof (int16) * 16); - return; - } - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - unsigned char filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - + if (ch->block_pointer >= 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + memset((void*) ch->decoded, 0, sizeof(int16) * 16); + return; + } + signed char* compressed = (signed char*) &IAPU.RAM [ch->block_pointer]; + + unsigned char filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + #if (defined (USE_X86_ASM) && (defined (__i386__) || defined (__i486__) ||\ defined (__i586__) || defined (__WIN32__) || defined (__DJGPP))) - int16 *raw = ch->block = ch->decoded; - - if (Settings.AltSampleDecode == 1) - DecodeBlockAsm (compressed, raw, &ch->previous [0], &ch->previous [1]); - else - DecodeBlockAsm2 (compressed, raw, &ch->previous [0], &ch->previous [1]); + int16* raw = ch->block = ch->decoded; + + if (Settings.AltSampleDecode == 1) + DecodeBlockAsm(compressed, raw, &ch->previous [0], &ch->previous [1]); + else + DecodeBlockAsm2(compressed, raw, &ch->previous [0], &ch->previous [1]); #else - int32 out; - unsigned char shift; - signed char sample1, sample2; - unsigned int i; - - compressed++; - signed short *raw = ch->block = ch->decoded; - - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; - shift = filter >> 4; - - switch ((filter >> 2) & 3) - { - case 0: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - *raw++ = ((int32) sample1 << shift); - *raw++ = ((int32) sample2 << shift); - } - prev1 = *(raw - 2); - prev0 = *(raw - 1); - break; - case 1: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - prev0 = (int16) prev0; - *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4); - prev1 = (int16) prev1; - *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4); - } - break; - case 2: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - - out = (sample1 << shift) - prev1 + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - - (prev0 >> 4); - - out = (sample2 << shift) - prev1 + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - - (prev0 >> 4); - } - break; - case 3: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - out = (sample1 << shift); - - out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - - (prev0 >> 4) - (prev1 >> 6); - - out = (sample2 << shift); - out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - - (prev0 >> 4) - (prev1 >> 6); - } - break; - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; + int32 out; + unsigned char shift; + signed char sample1, sample2; + unsigned int i; + + compressed++; + signed short* raw = ch->block = ch->decoded; + + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + shift = filter >> 4; + + switch ((filter >> 2) & 3) + { + case 0: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + *raw++ = ((int32) sample1 << shift); + *raw++ = ((int32) sample2 << shift); + } + prev1 = *(raw - 2); + prev0 = *(raw - 1); + break; + case 1: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + prev0 = (int16) prev0; + *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4); + prev1 = (int16) prev1; + *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4); + } + break; + case 2: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + + out = (sample1 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + + out = (sample2 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + } + break; + case 3: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + out = (sample1 << shift); + + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + + out = (sample2 << shift); + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + } + break; + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; #endif - - ch->block_pointer += 9; + + ch->block_pointer += 9; } -void AltDecodeBlock2 (Channel *ch) +void AltDecodeBlock2(Channel* ch) { - int32 out; - unsigned char filter; - unsigned char shift; - signed char sample1, sample2; - unsigned char i; - - if (ch->block_pointer > 0x10000 - 9) - { - ch->last_block = TRUE; - ch->loop = FALSE; - ch->block = ch->decoded; - memset ((void *) ch->decoded, 0, sizeof (int16) * 16); - return; - } - - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - - compressed++; - signed short *raw = ch->block = ch->decoded; - - shift = filter >> 4; - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; - - if(shift > 12) - shift -= 4; - - switch ((filter >> 2) & 3) - { - case 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; - - out = (int32)(sample1 << shift); - - prev1 = prev0; - prev0 = out; - CLIP16(out); - *raw++ = (int16)out; - - out = (int32)(sample2 << shift); - - prev1 = prev0; - prev0 = out; - CLIP16(out); - *raw++ = (int16)out; - } - break; - case 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; - out = (int32)(sample1 << shift); - out += (int32)((double)prev0 * 15/16); - - prev1 = prev0; - prev0 = out; - CLIP16(out); - *raw++ = (int16)out; - - out = (int32)(sample2 << shift); - out += (int32)((double)prev0 * 15/16); - - prev1 = prev0; - prev0 = out; - CLIP16(out); - *raw++ = (int16)out; - } - break; - case 2: - 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; - - out = ((sample1 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; - - prev1 = prev0; - prev0 = (int16)out; - *raw++ = (int16)out; - - out = ((sample2 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; - - prev1 = prev0; - prev0 = (int16)out; - *raw++ = (int16)out; - } - break; - - case 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; - out = (int32)(sample1 << shift); - out += (int32)((double)prev0 * 115/64 - (double)prev1 * 13/16); - - prev1 = prev0; - prev0 = out; - - CLIP16(out); - *raw++ = (int16)out; - - out = (int32)(sample2 << shift); - out += (int32)((double)prev0 * 115/64 - (double)prev1 * 13/16); - - prev1 = prev0; - prev0 = out; - - CLIP16(out); - *raw++ = (int16)out; - } - break; - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - ch->block_pointer += 9; + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + unsigned char i; + + if (ch->block_pointer > 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + memset((void*) ch->decoded, 0, sizeof(int16) * 16); + return; + } + + signed char* compressed = (signed char*) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + + compressed++; + signed short* raw = ch->block = ch->decoded; + + shift = filter >> 4; + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + + if (shift > 12) + shift -= 4; + + switch ((filter >> 2) & 3) + { + case 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; + + out = (int32)(sample1 << shift); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16)out; + + out = (int32)(sample2 << shift); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16)out; + } + break; + case 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; + out = (int32)(sample1 << shift); + out += (int32)((double)prev0 * 15 / 16); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16)out; + + out = (int32)(sample2 << shift); + out += (int32)((double)prev0 * 15 / 16); + + prev1 = prev0; + prev0 = out; + CLIP16(out); + *raw++ = (int16)out; + } + break; + case 2: + 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; + + out = ((sample1 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; + + prev1 = prev0; + prev0 = (int16)out; + *raw++ = (int16)out; + + out = ((sample2 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; + + prev1 = prev0; + prev0 = (int16)out; + *raw++ = (int16)out; + } + break; + + case 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; + out = (int32)(sample1 << shift); + out += (int32)((double)prev0 * 115 / 64 - (double)prev1 * 13 / 16); + + prev1 = prev0; + prev0 = out; + + CLIP16(out); + *raw++ = (int16)out; + + out = (int32)(sample2 << shift); + out += (int32)((double)prev0 * 115 / 64 - (double)prev1 * 13 / 16); + + prev1 = prev0; + prev0 = out; + + CLIP16(out); + *raw++ = (int16)out; + } + break; + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + ch->block_pointer += 9; } -void DecodeBlock (Channel *ch) +void DecodeBlock(Channel* ch) { - int32 out; - unsigned char filter; - unsigned char shift; - signed char sample1, sample2; - unsigned char i; - bool invalid_header; - - if (Settings.AltSampleDecode) - { - if (Settings.AltSampleDecode < 3) - AltDecodeBlock (ch); - else - AltDecodeBlock2 (ch); - return; - } - if (ch->block_pointer > 0x10000 - 9) - { - ch->last_block = TRUE; - ch->loop = FALSE; - ch->block = ch->decoded; - return; - } - - 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; - - int16 interim[16]; - uint8 interim_byte = 0; - - 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; } - - int nybblesmp; - for (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); - interim[interim_byte++] = out; - prev1=(signed short)prev0; - prev0=(signed short)(out<<1); - } - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - - 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 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 - // 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 - { - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - - 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]; - - 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; } - + int32 out; + unsigned char filter; + unsigned char shift; + signed char sample1, sample2; + unsigned char i; + bool invalid_header; + + if (Settings.AltSampleDecode) + { + if (Settings.AltSampleDecode < 3) + AltDecodeBlock(ch); + else + AltDecodeBlock2(ch); + return; + } + if (ch->block_pointer > 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + return; + } + + 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; + + int16 interim[16]; + uint8 interim_byte = 0; + + 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; + } + + int nybblesmp; + for (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); + interim[interim_byte++] = out; + prev1 = (signed short)prev0; + prev0 = (signed short)(out << 1); + } + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + + 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 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 + // 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 + { + signed char* compressed = (signed char*) &IAPU.RAM [ch->block_pointer]; + + filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + + 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]; + + 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; + } + int nybblesmp; - for (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); - *raw++ = (signed short)(out<<1); - prev1=(signed short)prev0; - prev0=(signed short)(out<<1); - } - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - } - ch->block_pointer += 9; + for (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); + *raw++ = (signed short)(out << 1); + prev1 = (signed short)prev0; + prev0 = (signed short)(out << 1); + } + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + } + ch->block_pointer += 9; } -static inline void MixStereo (int sample_count) +static inline void MixStereo(int sample_count) { - static int32 wave[SOUND_BUFFER_SIZE]; + static int32 wave[SOUND_BUFFER_SIZE]; - int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; + int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; uint32 J; for (J = 0; J < NUM_CHANNELS; J++) - { - Channel *ch = &SoundData.channels[J]; + { + Channel* ch = &SoundData.channels[J]; - if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) - continue; + if (ch->state == SOUND_SILENT || !(so.sound_switch & (1 << J))) + continue; - int32 VL, VR; - unsigned long freq0 = ch->frequency; + int32 VL, VR; + unsigned long freq0 = ch->frequency; - // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux - freq0 = freq0 * 985/1000; + // freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux + freq0 = freq0 * 985 / 1000; - bool8 mod = pitch_mod & (1 << J); + bool8 mod = pitch_mod & (1 << J); - if (ch->needs_decode) - { - DecodeBlock(ch); - ch->needs_decode = FALSE; - ch->sample = ch->block[0]; - ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; - if (ch->sample_pointer == 0) - ch->sample_pointer = 1; - if (ch->sample_pointer > SOUND_DECODE_LENGTH) - ch->sample_pointer = SOUND_DECODE_LENGTH - 1; + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; + if (ch->sample_pointer == 0) + ch->sample_pointer = 1; + if (ch->sample_pointer > SOUND_DECODE_LENGTH) + ch->sample_pointer = SOUND_DECODE_LENGTH - 1; - ch->next_sample=ch->block[ch->sample_pointer]; - ch->interpolate = 0; + ch->next_sample = ch->block[ch->sample_pointer]; + ch->interpolate = 0; - if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq0) / (long) FIXED_POINT; - } - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; + if (Settings.InterpolatedSound && freq0 < FIXED_POINT && !mod) + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq0) / (long) FIXED_POINT; + } + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; uint32 I; for (I = 0; I < (uint32) sample_count; I += 2) - { - unsigned long freq = freq0; - - if (mod) - freq = PITCH_MOD(freq, wave [I / 2]); - - ch->env_error += ch->erate; - if (ch->env_error >= FIXED_POINT) - { - uint32 step = ch->env_error >> FIXED_POINT_SHIFT; - - switch (ch->state) - { - case SOUND_ATTACK: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_DECAY; - if (ch->sustain_level != 8) - { - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) - >> 3); - break; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_DECAY: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= ch->envx_target) - { - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - break; - - case SOUND_SUSTAIN: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_RELEASE: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_INCREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_INCREASE_BENT_LINE: - if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) - { - while (ch->env_error >= FIXED_POINT) - { - ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - } - else - { - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - } - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0); - } - break; - - case SOUND_DECREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx -= step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_DECREASE_EXPONENTIAL: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_GAIN: - S9xSetEnvRate (ch, 0, -1, 0); - break; - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - - ch->count += freq; - if (ch->count >= FIXED_POINT) - { - VL = ch->count >> FIXED_POINT_SHIFT; - ch->sample_pointer += VL; - ch->count &= FIXED_POINT_REMAINDER; - - ch->sample = ch->next_sample; - if (ch->sample_pointer >= SOUND_DECODE_LENGTH) - { - if (JUST_PLAYED_LAST_SAMPLE(ch)) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - do - { - ch->sample_pointer -= SOUND_DECODE_LENGTH; - if (ch->last_block) - { - if (!ch->loop) - { - ch->sample_pointer = LAST_SAMPLE; - ch->next_sample = ch->sample; - break; - } - else - { - S9xAPUSetEndX (J); - ch->last_block = FALSE; - uint8 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = READ_WORD(dir + 2); - } - } - DecodeBlock (ch); - } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); - if (!JUST_PLAYED_LAST_SAMPLE (ch)) - ch->next_sample = ch->block [ch->sample_pointer]; - } - else - ch->next_sample = ch->block [ch->sample_pointer]; - - if (ch->type == SOUND_SAMPLE) - { - if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) - { - ch->interpolate = ((ch->next_sample - ch->sample) * - (long) freq) / (long) FIXED_POINT; - ch->sample = (int16) (ch->sample + (((ch->next_sample - ch->sample) * - (long) (ch->count)) / (long) FIXED_POINT)); - } - else - ch->interpolate = 0; - } - else - { - // Snes9x 1.53's SPC_DSP.cpp, by blargg - int feedback = (noise_gen << 13) ^ (noise_gen << 14); - noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); - ch->sample = (noise_gen << 17) >> 17; - ch->interpolate = 0; - } - - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - else - { - if (ch->interpolate) - { - int32 s = (int32) ch->sample + ch->interpolate; - - CLIP16(s); - ch->sample = (int16) s; - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - } - - if (pitch_mod & (1 << (J + 1))) - wave [I / 2] = ch->sample * ch->envx; - - MixBuffer [I ] += VL; - MixBuffer [I + 1] += VR; - ch->echo_buf_ptr [I ] += VL; - ch->echo_buf_ptr [I + 1] += VR; - } -stereo_exit: ; - } + { + unsigned long freq = freq0; + + if (mod) + freq = PITCH_MOD(freq, wave [I / 2]); + + ch->env_error += ch->erate; + if (ch->env_error >= FIXED_POINT) + { + uint32 step = ch->env_error >> FIXED_POINT_SHIFT; + + switch (ch->state) + { + case SOUND_ATTACK: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_DECAY; + if (ch->sustain_level != 8) + { + S9xSetEnvRate(ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) + >> 3); + break; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate(ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_DECAY: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= ch->envx_target) + { + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate(ch, ch->sustain_rate, -1, 0); + } + break; + + case SOUND_SUSTAIN: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + break; + + case SOUND_RELEASE: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + break; + + case SOUND_INCREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate(ch, 0, -1, 0); + } + break; + + case SOUND_INCREASE_BENT_LINE: + if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) + { + while (ch->env_error >= FIXED_POINT) + { + ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + } + else + { + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + } + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate(ch, 0, -1, 0); + } + break; + + case SOUND_DECREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx -= step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + break; + + case SOUND_DECREASE_EXPONENTIAL: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + break; + + case SOUND_GAIN: + S9xSetEnvRate(ch, 0, -1, 0); + break; + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + + ch->count += freq; + if (ch->count >= FIXED_POINT) + { + VL = ch->count >> FIXED_POINT_SHIFT; + ch->sample_pointer += VL; + ch->count &= FIXED_POINT_REMAINDER; + + ch->sample = ch->next_sample; + if (ch->sample_pointer >= SOUND_DECODE_LENGTH) + { + if (JUST_PLAYED_LAST_SAMPLE(ch)) + { + S9xAPUSetEndOfSample(J, ch); + goto stereo_exit; + } + do + { + ch->sample_pointer -= SOUND_DECODE_LENGTH; + if (ch->last_block) + { + if (!ch->loop) + { + ch->sample_pointer = LAST_SAMPLE; + ch->next_sample = ch->sample; + break; + } + else + { + S9xAPUSetEndX(J); + ch->last_block = FALSE; + uint8* dir = S9xGetSampleAddress(ch->sample_number); + ch->block_pointer = READ_WORD(dir + 2); + } + } + DecodeBlock(ch); + } + while (ch->sample_pointer >= SOUND_DECODE_LENGTH); + if (!JUST_PLAYED_LAST_SAMPLE(ch)) + ch->next_sample = ch->block [ch->sample_pointer]; + } + else + ch->next_sample = ch->block [ch->sample_pointer]; + + if (ch->type == SOUND_SAMPLE) + { + if (Settings.InterpolatedSound && freq < FIXED_POINT && !mod) + { + ch->interpolate = ((ch->next_sample - ch->sample) * + (long) freq) / (long) FIXED_POINT; + ch->sample = (int16)(ch->sample + (((ch->next_sample - ch->sample) * + (long)(ch->count)) / (long) FIXED_POINT)); + } + else + ch->interpolate = 0; + } + else + { + // Snes9x 1.53's SPC_DSP.cpp, by blargg + int feedback = (noise_gen << 13) ^ (noise_gen << 14); + noise_gen = (feedback & 0x4000) ^ (noise_gen >> 1); + ch->sample = (noise_gen << 17) >> 17; + ch->interpolate = 0; + } + + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + else + { + if (ch->interpolate) + { + int32 s = (int32) ch->sample + ch->interpolate; + + CLIP16(s); + ch->sample = (int16) s; + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + } + + if (pitch_mod & (1 << (J + 1))) + wave [I / 2] = ch->sample * ch->envx; + + MixBuffer [I ] += VL; + MixBuffer [I + 1] += VR; + ch->echo_buf_ptr [I ] += VL; + ch->echo_buf_ptr [I + 1] += VR; + } +stereo_exit: + ; + } } #ifdef __DJGPP @@ -1355,368 +1361,375 @@ END_OF_FUNCTION(MixStereo); #endif #ifdef __sun -extern uint8 int2ulaw (int); +extern uint8 int2ulaw(int); #endif // For backwards compatibility with older port specific code -void S9xMixSamplesO (uint8 *buffer, int sample_count, int byte_offset) +void S9xMixSamplesO(uint8* buffer, int sample_count, int byte_offset) { - S9xMixSamples (buffer+byte_offset, sample_count); + S9xMixSamples(buffer + byte_offset, sample_count); } #ifdef __DJGPP END_OF_FUNCTION(S9xMixSamplesO); #endif -void S9xMixSamples (uint8 *buffer, int sample_count) +void S9xMixSamples(uint8* buffer, int sample_count) { - int J; - int I; - - if (!so.mute_sound) - { - if (SoundData.echo_enable) - memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0])); - memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0])); - MixStereo (sample_count); - } - - /* Mix and convert waveforms */ - int byte_count = sample_count << 1; - - // 16-bit sound - if (so.mute_sound) - { - memset (buffer, 0, byte_count); - } - else - { - if (SoundData.echo_enable && SoundData.echo_buffer_size) - { - // 16-bit stereo sound with echo enabled ... - if (FilterTapDefinitionBitfield == 0) - { - // ... but no filter defined. - for (J = 0; J < sample_count; J++) - { - int E = Echo [SoundData.echo_ptr]; - - Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + - EchoBuffer [J]; - - if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer [J] * - SoundData.master_volume [J & 1] + - E * SoundData.echo_volume [J & 1]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) buffer)[J] = I; - } - } - else - { - // ... with filter defined. - for (J = 0; J < sample_count; J++) - { - int E = Echo [SoundData.echo_ptr]; - - Loop [(Z - 0) & 15] = E; - E = E * FilterTaps [0]; - if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1]; - if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2]; - if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3]; - if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4]; - if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5]; - if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6]; - if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7]; - E /= 128; - Z++; - - Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + - EchoBuffer [J]; - - if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer [J] * - SoundData.master_volume [J & 1] + - E * SoundData.echo_volume [J & 1]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) buffer)[J] = I; - } - } - } - else - { - // 16-bit mono or stereo sound, no echo - for (J = 0; J < sample_count; J++) - { - I = (MixBuffer [J] * - SoundData.master_volume [J & 1]) / VOL_DIV16; - - CLIP16(I); - ((signed short *) buffer)[J] = I; - } - } - } + int J; + int I; + + if (!so.mute_sound) + { + if (SoundData.echo_enable) + memset(EchoBuffer, 0, sample_count * sizeof(EchoBuffer [0])); + memset(MixBuffer, 0, sample_count * sizeof(MixBuffer [0])); + MixStereo(sample_count); + } + + /* Mix and convert waveforms */ + int byte_count = sample_count << 1; + + // 16-bit sound + if (so.mute_sound) + memset(buffer, 0, byte_count); + else + { + if (SoundData.echo_enable && SoundData.echo_buffer_size) + { + // 16-bit stereo sound with echo enabled ... + if (FilterTapDefinitionBitfield == 0) + { + // ... but no filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo [SoundData.echo_ptr]; + + Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + + EchoBuffer [J]; + + if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer [J] * + SoundData.master_volume [J & 1] + + E * SoundData.echo_volume [J & 1]) / VOL_DIV16; + + CLIP16(I); + ((signed short*) buffer)[J] = I; + } + } + else + { + // ... with filter defined. + for (J = 0; J < sample_count; J++) + { + int E = Echo [SoundData.echo_ptr]; + + Loop [(Z - 0) & 15] = E; + E = E * FilterTaps [0]; + if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * + FilterTaps [1]; + if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * + FilterTaps [2]; + if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * + FilterTaps [3]; + if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * + FilterTaps [4]; + if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * + FilterTaps [5]; + if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * + FilterTaps [6]; + if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * + FilterTaps [7]; + E /= 128; + Z++; + + Echo [SoundData.echo_ptr] = (E * SoundData.echo_feedback) / 128 + + EchoBuffer [J]; + + if ((SoundData.echo_ptr += 1) >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer [J] * + SoundData.master_volume [J & 1] + + E * SoundData.echo_volume [J & 1]) / VOL_DIV16; + + CLIP16(I); + ((signed short*) buffer)[J] = I; + } + } + } + else + { + // 16-bit mono or stereo sound, no echo + for (J = 0; J < sample_count; J++) + { + I = (MixBuffer [J] * + SoundData.master_volume [J & 1]) / VOL_DIV16; + + CLIP16(I); + ((signed short*) buffer)[J] = I; + } + } + } } #ifdef __DJGPP END_OF_FUNCTION(S9xMixSamples); #endif -void S9xResetSound (bool8 full) +void S9xResetSound(bool8 full) { int i; - for (i = 0; i < 8; i++) - { - SoundData.channels[i].state = SOUND_SILENT; - SoundData.channels[i].mode = MODE_NONE; - SoundData.channels[i].type = SOUND_SAMPLE; - SoundData.channels[i].volume_left = 0; - SoundData.channels[i].volume_right = 0; - SoundData.channels[i].hertz = 0; - SoundData.channels[i].count = 0; - SoundData.channels[i].loop = FALSE; - SoundData.channels[i].envx_target = 0; - SoundData.channels[i].env_error = 0; - SoundData.channels[i].erate = 0; - SoundData.channels[i].envx = 0; - SoundData.channels[i].envxx = 0; - SoundData.channels[i].left_vol_level = 0; - SoundData.channels[i].right_vol_level = 0; - SoundData.channels[i].direction = 0; - SoundData.channels[i].attack_rate = 0; - SoundData.channels[i].decay_rate = 0; - SoundData.channels[i].sustain_rate = 0; - SoundData.channels[i].release_rate = 0; - SoundData.channels[i].sustain_level = 0; - SoundData.echo_ptr = 0; - SoundData.echo_feedback = 0; - SoundData.echo_buffer_size = 1; - } - FilterTaps [0] = 127; - FilterTaps [1] = 0; - FilterTaps [2] = 0; - FilterTaps [3] = 0; - FilterTaps [4] = 0; - FilterTaps [5] = 0; - FilterTaps [6] = 0; - FilterTaps [7] = 0; - FilterTapDefinitionBitfield = 0; - so.mute_sound = TRUE; - noise_gen = 1; - so.sound_switch = 255; - so.samples_mixed_so_far = 0; - so.play_position = 0; - so.err_counter = 0; - - if (full) - { - SoundData.echo_enable = 0; - SoundData.echo_write_enabled = 0; - SoundData.echo_channel_enable = 0; - SoundData.pitch_mod = 0; - SoundData.dummy[0] = 0; - SoundData.dummy[1] = 0; - SoundData.dummy[2] = 0; - SoundData.master_volume[0] = 0; - SoundData.master_volume[1] = 0; - SoundData.echo_volume[0] = 0; - SoundData.echo_volume[1] = 0; - SoundData.noise_hertz = 0; - } - - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - if (so.playback_rate) - so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate)); - else - so.err_rate = 0; + for (i = 0; i < 8; i++) + { + SoundData.channels[i].state = SOUND_SILENT; + SoundData.channels[i].mode = MODE_NONE; + SoundData.channels[i].type = SOUND_SAMPLE; + SoundData.channels[i].volume_left = 0; + SoundData.channels[i].volume_right = 0; + SoundData.channels[i].hertz = 0; + SoundData.channels[i].count = 0; + SoundData.channels[i].loop = FALSE; + SoundData.channels[i].envx_target = 0; + SoundData.channels[i].env_error = 0; + SoundData.channels[i].erate = 0; + SoundData.channels[i].envx = 0; + SoundData.channels[i].envxx = 0; + SoundData.channels[i].left_vol_level = 0; + SoundData.channels[i].right_vol_level = 0; + SoundData.channels[i].direction = 0; + SoundData.channels[i].attack_rate = 0; + SoundData.channels[i].decay_rate = 0; + SoundData.channels[i].sustain_rate = 0; + SoundData.channels[i].release_rate = 0; + SoundData.channels[i].sustain_level = 0; + SoundData.echo_ptr = 0; + SoundData.echo_feedback = 0; + SoundData.echo_buffer_size = 1; + } + FilterTaps [0] = 127; + FilterTaps [1] = 0; + FilterTaps [2] = 0; + FilterTaps [3] = 0; + FilterTaps [4] = 0; + FilterTaps [5] = 0; + FilterTaps [6] = 0; + FilterTaps [7] = 0; + FilterTapDefinitionBitfield = 0; + so.mute_sound = TRUE; + noise_gen = 1; + so.sound_switch = 255; + so.samples_mixed_so_far = 0; + so.play_position = 0; + so.err_counter = 0; + + if (full) + { + SoundData.echo_enable = 0; + SoundData.echo_write_enabled = 0; + SoundData.echo_channel_enable = 0; + SoundData.pitch_mod = 0; + SoundData.dummy[0] = 0; + SoundData.dummy[1] = 0; + SoundData.dummy[2] = 0; + SoundData.master_volume[0] = 0; + SoundData.master_volume[1] = 0; + SoundData.echo_volume[0] = 0; + SoundData.echo_volume[1] = 0; + SoundData.noise_hertz = 0; + } + + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + if (so.playback_rate) + so.err_rate = (uint32)(FIXED_POINT * SNES_SCANLINE_TIME / + (1.0 / so.playback_rate)); + else + so.err_rate = 0; } -void S9xSetPlaybackRate (uint32 playback_rate) +void S9xSetPlaybackRate(uint32 playback_rate) { - so.playback_rate = playback_rate; - so.err_rate = (uint32) (SNES_SCANLINE_TIME * FIXED_POINT / (1.0 / (double) so.playback_rate)); - S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); - int i; - for (i = 0; i < 8; i++) - S9xSetSoundFrequency (i, SoundData.channels [i].hertz); + so.playback_rate = playback_rate; + so.err_rate = (uint32)(SNES_SCANLINE_TIME * FIXED_POINT / (1.0 / + (double) so.playback_rate)); + S9xSetEchoDelay(APU.DSP [APU_EDL] & 0xf); + int i; + for (i = 0; i < 8; i++) + S9xSetSoundFrequency(i, SoundData.channels [i].hertz); } -bool8 S9xInitSound (int mode, bool8 stereo, int buffer_size) +bool8 S9xInitSound(int mode, bool8 stereo, int buffer_size) { - so.sound_fd = -1; - so.sound_switch = 255; - - so.playback_rate = 0; - so.buffer_size = 0; - so.encoded = FALSE; - - S9xResetSound (TRUE); - - if (!(mode & 7)) - return (1); - - S9xSetSoundMute (TRUE); - if (!S9xOpenSoundDevice (mode, stereo, buffer_size)) - { - S9xMessage (S9X_ERROR, S9X_SOUND_DEVICE_OPEN_FAILED, - "Sound device open failed"); - return (0); - } - - return (1); + so.sound_fd = -1; + so.sound_switch = 255; + + so.playback_rate = 0; + so.buffer_size = 0; + so.encoded = FALSE; + + S9xResetSound(TRUE); + + if (!(mode & 7)) + return (1); + + S9xSetSoundMute(TRUE); + if (!S9xOpenSoundDevice(mode, stereo, buffer_size)) + { + S9xMessage(S9X_ERROR, S9X_SOUND_DEVICE_OPEN_FAILED, + "Sound device open failed"); + return (0); + } + + return (1); } -bool8 S9xSetSoundMode (int channel, int mode) +bool8 S9xSetSoundMode(int channel, int mode) { - Channel *ch = &SoundData.channels[channel]; - - switch (mode) - { - case MODE_RELEASE: - if (ch->mode != MODE_NONE) - { - ch->mode = MODE_RELEASE; - return (TRUE); - } - break; - - case MODE_DECREASE_LINEAR: - case MODE_DECREASE_EXPONENTIAL: - case MODE_GAIN: - if (ch->mode != MODE_RELEASE) - { - ch->mode = mode; - if (ch->state != SOUND_SILENT) - ch->state = mode; - - return (TRUE); - } - break; - - case MODE_INCREASE_LINEAR: - case MODE_INCREASE_BENT_LINE: - if (ch->mode != MODE_RELEASE) - { - ch->mode = mode; - if (ch->state != SOUND_SILENT) - ch->state = mode; - - return (TRUE); - } - break; - - case MODE_ADSR: - if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) - { - ch->mode = mode; - return (TRUE); - } - } - - return (FALSE); + Channel* ch = &SoundData.channels[channel]; + + switch (mode) + { + case MODE_RELEASE: + if (ch->mode != MODE_NONE) + { + ch->mode = MODE_RELEASE; + return (TRUE); + } + break; + + case MODE_DECREASE_LINEAR: + case MODE_DECREASE_EXPONENTIAL: + case MODE_GAIN: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + return (TRUE); + } + break; + + case MODE_INCREASE_LINEAR: + case MODE_INCREASE_BENT_LINE: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + return (TRUE); + } + break; + + case MODE_ADSR: + if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) + { + ch->mode = mode; + return (TRUE); + } + } + + return (FALSE); } -void S9xSetSoundControl (int sound_switch) +void S9xSetSoundControl(int sound_switch) { - so.sound_switch = sound_switch; + so.sound_switch = sound_switch; } -void S9xPlaySample (int channel) +void S9xPlaySample(int channel) { - Channel *ch = &SoundData.channels[channel]; - - ch->state = SOUND_SILENT; - ch->mode = MODE_NONE; - ch->envx = 0; - ch->envxx = 0; - - S9xFixEnvelope (channel, - APU.DSP [APU_GAIN + (channel << 4)], - APU.DSP [APU_ADSR1 + (channel << 4)], - APU.DSP [APU_ADSR2 + (channel << 4)]); - - ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10]; - if (APU.DSP [APU_NON] & (1 << channel)) - ch->type = SOUND_NOISE; - else - ch->type = SOUND_SAMPLE; - - S9xSetSoundFrequency (channel, ch->hertz); - ch->loop = FALSE; - ch->needs_decode = TRUE; - ch->last_block = FALSE; - ch->previous [0] = ch->previous[1] = 0; - uint8 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = READ_WORD (dir); - ch->sample_pointer = 0; - ch->env_error = 0; - ch->next_sample = 0; - ch->interpolate = 0; - switch (ch->mode) - { - case MODE_ADSR: - if (ch->attack_rate == 0) - { - if (ch->decay_rate == 0 || ch->sustain_level == 8) - { - ch->state = SOUND_SUSTAIN; - ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0); - } - else - { - ch->state = SOUND_DECAY; - ch->envx = MAX_ENVELOPE_HEIGHT; - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3); - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - } - else - { - ch->state = SOUND_ATTACK; - ch->envx = 0; - ch->left_vol_level = 0; - ch->right_vol_level = 0; - S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT); - } - ch->envxx = ch->envx << ENVX_SHIFT; - break; - - case MODE_GAIN: - ch->state = SOUND_GAIN; - break; - - case MODE_INCREASE_LINEAR: - ch->state = SOUND_INCREASE_LINEAR; - break; - - case MODE_INCREASE_BENT_LINE: - ch->state = SOUND_INCREASE_BENT_LINE; - break; - - case MODE_DECREASE_LINEAR: - ch->state = SOUND_DECREASE_LINEAR; - break; - - case MODE_DECREASE_EXPONENTIAL: - ch->state = SOUND_DECREASE_EXPONENTIAL; - break; - - default: - break; - } - - S9xFixEnvelope (channel, - APU.DSP [APU_GAIN + (channel << 4)], - APU.DSP [APU_ADSR1 + (channel << 4)], - APU.DSP [APU_ADSR2 + (channel << 4)]); + Channel* ch = &SoundData.channels[channel]; + + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + ch->envx = 0; + ch->envxx = 0; + + S9xFixEnvelope(channel, + APU.DSP [APU_GAIN + (channel << 4)], + APU.DSP [APU_ADSR1 + (channel << 4)], + APU.DSP [APU_ADSR2 + (channel << 4)]); + + ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10]; + if (APU.DSP [APU_NON] & (1 << channel)) + ch->type = SOUND_NOISE; + else + ch->type = SOUND_SAMPLE; + + S9xSetSoundFrequency(channel, ch->hertz); + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous [0] = ch->previous[1] = 0; + uint8* dir = S9xGetSampleAddress(ch->sample_number); + ch->block_pointer = READ_WORD(dir); + ch->sample_pointer = 0; + ch->env_error = 0; + ch->next_sample = 0; + ch->interpolate = 0; + switch (ch->mode) + { + case MODE_ADSR: + if (ch->attack_rate == 0) + { + if (ch->decay_rate == 0 || ch->sustain_level == 8) + { + ch->state = SOUND_SUSTAIN; + ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; + S9xSetEnvRate(ch, ch->sustain_rate, -1, 0); + } + else + { + ch->state = SOUND_DECAY; + ch->envx = MAX_ENVELOPE_HEIGHT; + S9xSetEnvRate(ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3); + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + } + else + { + ch->state = SOUND_ATTACK; + ch->envx = 0; + ch->left_vol_level = 0; + ch->right_vol_level = 0; + S9xSetEnvRate(ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT); + } + ch->envxx = ch->envx << ENVX_SHIFT; + break; + + case MODE_GAIN: + ch->state = SOUND_GAIN; + break; + + case MODE_INCREASE_LINEAR: + ch->state = SOUND_INCREASE_LINEAR; + break; + + case MODE_INCREASE_BENT_LINE: + ch->state = SOUND_INCREASE_BENT_LINE; + break; + + case MODE_DECREASE_LINEAR: + ch->state = SOUND_DECREASE_LINEAR; + break; + + case MODE_DECREASE_EXPONENTIAL: + ch->state = SOUND_DECREASE_EXPONENTIAL; + break; + + default: + break; + } + + S9xFixEnvelope(channel, + APU.DSP [APU_GAIN + (channel << 4)], + APU.DSP [APU_ADSR1 + (channel << 4)], + APU.DSP [APU_ADSR2 + (channel << 4)]); } |