From 6fb0c7a7a53e1eba7a0f5dc5b1ade312a0d76119 Mon Sep 17 00:00:00 2001 From: Toad King Date: Thu, 14 Jun 2012 03:21:06 -0400 Subject: initial pocketsnes commit --- src/soundux.h | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 src/soundux.h (limited to 'src/soundux.h') diff --git a/src/soundux.h b/src/soundux.h new file mode 100644 index 0000000..4b313df --- /dev/null +++ b/src/soundux.h @@ -0,0 +1,337 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code 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. + */ +#ifndef _SOUND_H_ +#define _SOUND_H_ + +enum { SOUND_SAMPLE = 0, SOUND_NOISE, SOUND_EXTRA_NOISE, SOUND_MUTE }; +enum { SOUND_SILENT, SOUND_ATTACK, SOUND_DECAY, SOUND_SUSTAIN, + SOUND_RELEASE, SOUND_GAIN, SOUND_INCREASE_LINEAR, + SOUND_INCREASE_BENT_LINE, SOUND_DECREASE_LINEAR, + SOUND_DECREASE_EXPONENTIAL}; + +enum { MODE_NONE = SOUND_SILENT, MODE_ADSR, MODE_RELEASE = SOUND_RELEASE, + MODE_GAIN, MODE_INCREASE_LINEAR, MODE_INCREASE_BENT_LINE, + MODE_DECREASE_LINEAR, MODE_DECREASE_EXPONENTIAL}; + +#define MAX_ENVELOPE_HEIGHT 127 +#define ENVELOPE_SHIFT 7 +#define MAX_VOLUME 127 +#define VOLUME_SHIFT 7 +#define VOL_DIV 128 +#define SOUND_DECODE_LENGTH 16 + +#define NUM_CHANNELS 8 +#define SOUND_BUFFER_SIZE (2*44100/50) +#define MAX_BUFFER_SIZE SOUND_BUFFER_SIZE + +#define SOUND_BUFS 4 + +typedef struct { + int playback_rate; + bool8 stereo; + bool8 mute_sound; + uint8 sound_switch; + int noise_gen; + uint32 freqbase; // notaz +} SoundStatus; + +EXTERN_C SoundStatus so; + +typedef struct { + int state; // 0x00 + int type; // 0x04 + short volume_left; // 0x08 + short volume_right; // 0x0A + uint32 hertz; // 0x0C + uint32 frequency; // 0x10 + uint32 count; // 0x14 + bool32 loop; // 0x18 + int envx; // 0x1C + short left_vol_level; // 0x20 + short right_vol_level; // 0x22 + short envx_target; // 0x24 + short padding; // 0x26 + unsigned long int env_error; // 0x28 + unsigned long erate; // 0x2C + int direction; // 0x30 + unsigned long attack_rate; // 0x34 + unsigned long decay_rate; // 0x38 + unsigned long sustain_rate; // 0x3C + unsigned long release_rate; // 0x40 + unsigned long sustain_level; // 0x44 + signed short sample; // 0x48 + signed short decoded [16]; + signed short previous16 [2]; + signed short *block; + uint16 sample_number; + bool8 last_block; + bool8 needs_decode; + uint32 block_pointer; + uint32 sample_pointer; + int *echo_buf_ptr; + int mode; + int32 envxx; + signed short next_sample; + int32 interpolate; + int32 previous [2]; + // notaz + uint8 env_ind_attack; + uint8 env_ind_decay; + uint8 env_ind_sustain; + uint8 dummy1; + // Just incase they are needed in the future, for snapshot compatibility. + uint32 dummy [7]; + //I'll use Fatl's recovery on savestates. + short gaussian[8]; + int g_index; + unsigned short last_valid_header; + uint8 padding2[256-212]; // Last time I checked it, it was 212 bytes long +} Channel; + +typedef struct +{ + short master_volume_left; // 0x00 + short master_volume_right; // 0x02 + short echo_volume_left; // 0x04 + short echo_volume_right; // 0x06 + int echo_enable; // 0x08 + int echo_feedback; // 0x0C + int echo_ptr; // 0x10 + int echo_buffer_size; // 0x14 + int echo_write_enabled; // 0x18 + int echo_channel_enable; // 0x1C + int pitch_mod; // 0x20 + // Just incase they are needed in the future, for snapshot compatibility. + uint32 dummy [3]; // 0x24, 0x28, 0x2C + Channel channels [NUM_CHANNELS]; // 0x30 + bool8 no_filter; + int master_volume [2]; + int echo_volume [2]; + int noise_hertz; +} SSoundData; + +EXTERN_C SSoundData SoundData; + +void S9xSetEnvelopeHeight (int channel, int height); +void S9xSetSoundKeyOff (int channel); +void S9xSetSoundDecayMode (int channel); +void S9xSetSoundAttachMode (int channel); +void S9xSoundStartEnvelope (Channel *); +void S9xSetSoundSample (int channel, uint16 sample_number); +void S9xSetEchoDelay (int byte); +void S9xResetSound (bool8 full); +void S9xFixSoundAfterSnapshotLoad (); +void S9xPlaybackSoundSetting (int channel); +void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2); +void S9xStartSample (int channel); + +EXTERN_C void S9xMixSamples (signed short *buffer, int sample_count); +EXTERN_C void S9xMixSamplesO(signed short *buffer, int sample_count, int sample_offset); +void S9xSetPlaybackRate (uint32 rate); +bool8 S9xInitSound (void); +#endif + + + +// notaz: some stuff from soundux.cpp to enable their inlining +#include "apu.h" +//#define DEBUG +//#include + +extern int Echo [24000]; +extern int Loop [16]; +extern int FilterTaps [8]; +extern int EchoBuffer [SOUND_BUFFER_SIZE]; +extern int NoiseFreq [32]; + +// precalculated env rates for S9xSetEnvRate +extern unsigned long AttackERate [16][10]; +extern unsigned long DecayERate [8][10]; +extern unsigned long SustainERate [32][10]; +extern unsigned long IncreaseERate [32][10]; +extern unsigned long DecreaseERateExp[32][10]; +extern unsigned long KeyOffERate[10]; + + +#define FIXED_POINT 0x10000UL +#define CLIP8(v) \ +if ((v) < -128) \ + (v) = -128; \ +else \ +if ((v) > 127) \ + (v) = 127 + +static inline void S9xSetSoundMute (bool8 mute) +{ + //bool8 old = so.mute_sound; + so.mute_sound = mute; + //return (old); +} + +static inline void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction, int target, unsigned int mode) +{ + ch->envx_target = target; + + if (rate == ~0UL) + { + ch->direction = 0; + rate = 0; + } + else + ch->direction = direction; + + + if (rate == 0 || so.playback_rate == 0) + ch->erate = 0; + else + { + switch(mode >> 28) { + case 0: // attack + ch->erate = AttackERate[ch->env_ind_attack][ch->state]; + break; + + case 1: // Decay + ch->erate = DecayERate[ch->env_ind_decay][ch->state]; + break; + + case 2: // Sustain + ch->erate = SustainERate[ch->env_ind_sustain][ch->state]; + break; + + case 3: // Increase + ch->erate = IncreaseERate[mode&0x1f][ch->state]; + break; + + case 4: // DecreaseExp + ch->erate = DecreaseERateExp[mode&0x1f][ch->state]; + break; + + case 5: // KeyOff + ch->erate = KeyOffERate[ch->state]; + break; + } + } + +#if 0 + static int steps [] = + { +// 0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 + 0, 64, 619, 619, 128, 1, 64, 55, 64, 619 + }; + + if (rate == 0 || so.playback_rate == 0) + ch->erate = 0; + else + { + ch->erate = (unsigned long) + (((int64) FIXED_POINT * 1000 * steps [ch->state]) / + (rate * so.playback_rate)); + } +#endif +} + +static inline 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; + for (int i = 0; i < 8; i++) + { + if (byte & (1 << i)) + SoundData.channels [i].echo_buf_ptr = EchoBuffer; + else + SoundData.channels [i].echo_buf_ptr = 0; + } +} + +static inline void S9xSetEchoFeedback (int feedback) +{ + CLIP8(feedback); + SoundData.echo_feedback = feedback; +} + +static inline void S9xSetFilterCoefficient (int tap, int value) +{ + FilterTaps [tap & 7] = value; + SoundData.no_filter = (FilterTaps [0] == 127 || FilterTaps [0] == 0) && + FilterTaps [1] == 0 && + FilterTaps [2] == 0 && + FilterTaps [3] == 0 && + FilterTaps [4] == 0 && + FilterTaps [5] == 0 && + FilterTaps [6] == 0 && + FilterTaps [7] == 0; +} + +static inline uint16 *S9xGetSampleAddress (int sample_number) +{ + uint32 addr = (((APU.DSP[APU_DIR] << 8) + (sample_number << 2)) & 0xffff); + return (uint16 *)(IAPU.RAM + addr); +} + +static inline void S9xSetSoundFrequency (int channel, int hertz) // hertz [0~64K<<1] +{ + if (so.playback_rate) + { + if (SoundData.channels[channel].type == SOUND_NOISE) + hertz = NoiseFreq [APU.DSP [APU_FLG] & 0x1f]; +#if 0 // notaz: this compiles to something awful + SoundData.channels[channel].frequency = (int) + (((int64) hertz * FIXED_POINT) / so.playback_rate); +#else + SoundData.channels[channel].frequency = (hertz * so.freqbase) >> 11; +#endif + + /* if (Settings.FixFrequency) + { + SoundData.channels[channel].frequency = + (unsigned long) ((double) SoundData.channels[channel].frequency * 0.980); + }*/ + } +} + -- cgit v1.2.3