From 872441ce20e3e118e449328afdc986b8849dcd46 Mon Sep 17 00:00:00 2001 From: mudlord Date: Tue, 4 Dec 2007 09:08:44 +0000 Subject: [PATCH] Added preliminary support for blargg's Gb_Apu --- Makefile | 7 +- VBA.vcproj | 384 ++++++++++++--------- src/gb/GB.cpp | 22 +- src/gb/gbSound.cpp | 816 ++++++--------------------------------------- src/gb/gbSound.h | 13 + 5 files changed, 359 insertions(+), 883 deletions(-) diff --git a/Makefile b/Makefile index 31a6d90b..ecddb5a5 100644 --- a/Makefile +++ b/Makefile @@ -32,11 +32,14 @@ MAINDIR=src SDLDIR=src/sdl DMGDIR=src/gb RESAMPLEDIR=src/libresample-0.1.3/src - +GBAPUDIR=src/gb/gb_apu ASMOBJ=${MAINDIR}/hq3x_16${OE} ${MAINDIR}/hq3x_32${OE} ${MAINDIR}/hq4x_16${OE} ${MAINDIR}/hq4x_32${OE} \ ${MAINDIR}/hq3x32${OE} +GBAPUOBJ=${GBAPUDIR}/Blip_Buffer${OE} ${GBAPUDIR}/Effects_Buffer${OE} ${GBAPUDIR}/Gb_Apu${OE} \ +${GBAPUDIR}/Gb_Apu_State${OE} ${GBAPUDIR}/Gb_Oscs${OE} ${GBAPUDIR}/Multi_Buffer${OE} + CALTERNOBJ=${MAINDIR}/hq3x16c${OE} ${MAINDIR}/hq3x32c${OE} ${MAINDIR}/hq4x16c${OE} ${MAINDIR}/hq4x32c${OE} \ ${MAINDIR}/hq_shared32${OE} @@ -58,7 +61,7 @@ ${DMGDIR}/gbSound${OE} SDLOBJ=${SDLDIR}/debugger${OE} ${SDLDIR}/SDL${OE} ${SDLDIR}/dummy${OE} -OBJECTS=${MAINOBJ} ${DMGOBJ} ${SDLOBJ} +OBJECTS=${MAINOBJ} ${DMGOBJ} ${SDLOBJ} ${GBAPUOBJ} LIB=${RESAMPLEDIR}/filterkit${OE} ${RESAMPLEDIR}/resample${OE} ${RESAMPLEDIR}/resamplesubs${OE} ifeq ($(USEASM),yes) diff --git a/VBA.vcproj b/VBA.vcproj index 09e76cb3..0f5197aa 100644 --- a/VBA.vcproj +++ b/VBA.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - @@ -548,6 +538,16 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> + + + @@ -623,16 +623,6 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> - - - @@ -643,6 +633,16 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> + + + @@ -667,16 +667,6 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> - - - @@ -687,6 +677,16 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> + + + @@ -711,16 +711,6 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> - - - @@ -731,6 +721,16 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> + + + @@ -755,16 +755,6 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> - - - @@ -775,6 +765,16 @@ Outputs=""$(IntDir)\$(InputName).obj"" /> + + + @@ -1015,6 +1015,66 @@ RelativePath=".\src\gb\gbSound.cpp" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = 0xff00) { + if ( address >= 0xFF10 && address <= 0xFF3F ) + return gbSoundRead( address ); + switch(address & 0x00ff) { case 0x00: { @@ -2057,8 +2061,8 @@ void gbSpeedSwitch() gbLcdLYIncrementTicksDelayed *= 2; gbLcdLYIncrementTicksDelayed--; gbSerialTicks *= 2; - SOUND_CLOCK_TICKS = soundQuality * 24 * 2; - soundTicks *= 2; + //SOUND_CLOCK_TICKS = soundQuality * 24 * 2; + //soundTicks *= 2; gbLine99Ticks = 3; } else { gbSpeed = 0; @@ -2080,8 +2084,8 @@ void gbSpeedSwitch() gbLcdLYIncrementTicksDelayed++; gbLcdLYIncrementTicksDelayed >>= 1; gbSerialTicks /= 2; - SOUND_CLOCK_TICKS = soundQuality * 24; - soundTicks /= 2; + //SOUND_CLOCK_TICKS = soundQuality * 24; + //soundTicks /= 2; gbLine99Ticks = 1; if (gbHardware & 8) gbLine99Ticks++; @@ -4312,8 +4316,8 @@ int gbGetNextEvent (int clockTicks) if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks)) clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1; - if(soundTicks && (soundTicks < clockTicks)) - clockTicks = soundTicks; + //if(soundTicks && (soundTicks < clockTicks)) + // clockTicks = soundTicks; if ((clockTicks<=0) || (gbInterruptWait)) clockTicks = 1; @@ -5205,7 +5209,9 @@ void gbEmulate(int ticksToStop) soundTicks -= clockTicks; - + if ( !gbSpeed ) + soundTicks -= clockTicks; + while(soundTicks < 0) { soundTicks += SOUND_CLOCK_TICKS; diff --git a/src/gb/gbSound.cpp b/src/gb/gbSound.cpp index 1113faba..4719de71 100644 --- a/src/gb/gbSound.cpp +++ b/src/gb/gbSound.cpp @@ -23,6 +23,12 @@ #include "gbGlobals.h" #include "gbSound.h" +#include "gb_apu/Gb_Apu.h" +#include "gb_apu/Effects_Buffer.h" + +static Gb_Apu* gb_apu; +static Simple_Effects_Buffer* stereo_buffer; + extern u8 soundBuffer[6][735]; extern u16 soundFinalWave[1470]; extern int soundVolume; @@ -134,6 +140,24 @@ extern bool soundOffFlag; bool gbDigitalSound = false; +static inline blip_time_t ticks_to_time( int ticks ) +{ + return ticks * 2; +} + +static inline blip_time_t blip_time() +{ + return ticks_to_time( SOUND_CLOCK_TICKS - soundTicks ); +} + +u8 gbSoundRead( u16 address ) +{ + if ( gb_apu && address >= NR10 && address <= 0xFF3F ) + return gb_apu->read_register( blip_time(), address ); + + return gbMemory[address]; +} + void gbSoundEvent(register u16 address, register int data) { int freq = 0; @@ -146,626 +170,118 @@ void gbSoundEvent(register u16 address, register int data) log("Sound event: %08lx %02x\n", address, data); } #endif - switch(address) { - case NR10: - gbMemory[address] = data | 0x80; - sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7); - sound1SweepSteps = data & 7; - sound1SweepUpDown = data & 0x08; - sound1SweepStep = 0; - break; - case NR11: - gbMemory[address] = data | 0x3f; - sound1Wave = soundWavePattern[data >> 6]; - sound1ATL = sound1ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR12: - sound1EnvelopeVolume = data >> 4; - sound1EnvelopeUpDown = data & 0x08; - sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7); - break; - case NR13: - gbMemory[address] = 0xff; - freq1low = data; - freq = ((((int)(freq1high & 7)) << 8) | freq1low); - sound1ATL = sound1ATLreload; - freq = 2048 - freq; - if(freq) { - sound1Skip = SOUND_MAGIC / freq; - } else - sound1Skip = 0; - break; - case NR14: - gbMemory[address] = data | 0xbf; - freq1high = data; - freq = ((((int)(freq1high & 7)) << 8) | freq1low); - freq = 2048 - freq; - sound1ATL = sound1ATLreload; - sound1Continue = data & 0x40; - if(freq) { - sound1Skip = SOUND_MAGIC / freq; - } else - sound1Skip = 0; - if(data & 0x80) { - gbMemory[NR52] |= 1; - sound1EnvelopeVolume = gbMemory[NR12] >> 4; - sound1EnvelopeUpDown = gbMemory[NR12] & 0x08; - sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7); - sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7); - sound1SweepSteps = gbMemory[NR10] & 7; - sound1SweepUpDown = gbMemory[NR10] & 0x08; - sound1SweepStep = 0; - sound1Index = 0; - sound1On = 1; - } - break; - case NR21: - gbMemory[address] = data | 0x3f; - sound2Wave = soundWavePattern[data >> 6]; - sound2ATL = sound2ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR22: - sound2EnvelopeVolume = data >> 4; - sound2EnvelopeUpDown = data & 0x08; - sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7); - break; - case NR23: - gbMemory[address] = 0xff; - freq2low = data; - freq = (((int)(freq2high & 7)) << 8) | freq2low; - sound2ATL = sound2ATLreload; - freq = 2048 - freq; - if(freq) { - sound2Skip = SOUND_MAGIC / freq; - } else - sound2Skip = 0; - break; - case NR24: - gbMemory[address] = data | 0xbf; - freq2high = data; - freq = (((int)(freq2high & 7)) << 8) | freq2low; - freq = 2048 - freq; - sound2ATL = sound2ATLreload; - sound2Continue = data & 0x40; - if(freq) { - sound2Skip = SOUND_MAGIC / freq; - } else - sound2Skip = 0; - if(data & 0x80) { - gbMemory[NR52] |= 2; - sound2EnvelopeVolume = gbMemory[NR22] >> 4; - sound2EnvelopeUpDown = gbMemory[NR22] & 0x08; - sound2ATL = sound2ATLreload; - sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7); - - sound2Index = 0; - sound2On = 1; - } - break; - case NR30: - gbMemory[address] = data | 0x7f; - if(!(data & 0x80)) { - gbMemory[NR52] &= 0xfb; - sound3On = 0; - } - break; - case NR31: - gbMemory[address] = 0xff; - sound3ATL = sound3ATLreload = 172 * (256-data); - break; - case NR32: - gbMemory[address] = data | 0x9f; - sound3OutputLevel = (data >> 5) & 3; - break; - case NR33: - gbMemory[address] = 0xff; - freq3low = data; - freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); - if(freq) { - sound3Skip = SOUND_MAGIC_2 / freq; - } else - sound3Skip = 0; - break; - case NR34: - gbMemory[address] = data | 0xbf; - freq3high = data; - freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); - if(freq) { - sound3Skip = SOUND_MAGIC_2 / freq; - } else { - sound3Skip = 0; - } - sound3Continue = data & 0x40; - if((data & 0x80) && (gbMemory[NR30] & 0x80)) { - gbMemory[NR52] |= 4; - sound3ATL = sound3ATLreload; - sound3Index = 0; - sound3On = 1; - } - break; - case NR41: - sound4ATL = sound4ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR42: - sound4EnvelopeVolume = data >> 4; - sound4EnvelopeUpDown = data & 0x08; - sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7); - break; - case NR43: - freq = freq4 = soundFreqRatio[data & 7]; - sound4NSteps = data & 0x08; - - sound4Skip = (freq << 8) / NOISE_MAGIC; - - sound4Clock = data >> 4; - - freq = freq / soundShiftClock[sound4Clock]; - - sound4ShiftSkip = (freq << 8) / NOISE_MAGIC; - - break; - case NR44: - gbMemory[address] = data | 0xbf; - sound4Continue = data & 0x40; - if(data & 0x80) { - gbMemory[NR52] |= 8; - sound4EnvelopeVolume = gbMemory[NR42] >> 4; - sound4EnvelopeUpDown = gbMemory[NR42] & 0x08; - sound4ATL = sound4ATLreload; - sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7); - - sound4On = 1; - - sound4Index = 0; - sound4ShiftIndex = 0; - - if(sound4NSteps) - sound4ShiftRight = 0x7fff; - else - sound4ShiftRight = 0x7f; - } - break; - case NR50: - soundVIN = data & 0x88; - soundLevel1 = data & 7; - soundLevel2 = (data >> 4) & 7; - break; - case NR51: - soundBalance = (data & soundEnableFlag); - break; - case NR52: - soundMasterOn = data & 0x80; - if(!(data & 0x80)) { - sound1On = 0; - sound2On = 0; - sound3On = 0; - sound4On = 0; - gbMemory[address] &= 0xf0; - } - gbMemory[address] = data & 0x80 | 0x70 | (gbMemory[address] & 0xf); - break; - } - - gbDigitalSound = true; - - if(sound1On && sound1EnvelopeVolume != 0) - gbDigitalSound = false; - if(sound2On && sound2EnvelopeVolume != 0) - gbDigitalSound = false; - if(sound3On && sound3OutputLevel != 0) - gbDigitalSound = false; - if(sound4On && sound4EnvelopeVolume != 0) - gbDigitalSound = false; + if ( gb_apu && address >= NR10 && address <= 0xFF3F ) + gb_apu->write_register( blip_time(), address, data ); } - void gbSoundChannel1() +void gbSoundChannel1() { - int vol = sound1EnvelopeVolume; - - int freq = 0; - - int value = 0; - - if(sound1On && (sound1ATL || !sound1Continue)) { - sound1Index += soundQuality*sound1Skip; - sound1Index &= 0x1fffffff; - - value = ((s8)sound1Wave[sound1Index>>24]) * vol; - } - - soundBuffer[0][soundIndex] = value; - - - if(sound1On) { - if(sound1ATL) { - sound1ATL-=soundQuality; - - if(sound1ATL <=0 && sound1Continue) { - gbMemory[NR52] &= 0xfe; - sound1On = 0; - } - } - - if(sound1EnvelopeATL) { - sound1EnvelopeATL-=soundQuality; - - if(sound1EnvelopeATL<=0) { - if(sound1EnvelopeUpDown) { - if(sound1EnvelopeVolume < 15) - sound1EnvelopeVolume++; - } else { - if(sound1EnvelopeVolume) - sound1EnvelopeVolume--; - } - - sound1EnvelopeATL += sound1EnvelopeATLReload; - } - } - - if(sound1SweepATL) { - sound1SweepATL-=soundQuality; - - if(sound1SweepATL<=0) { - freq = (((int)(freq1high & 7)) << 8) | freq1low; - - int updown = 1; - - if(sound1SweepUpDown) - updown = -1; - - int newfreq = 0; - if(sound1SweepSteps) { - newfreq = freq + updown * freq / (1 << sound1SweepSteps); - if(newfreq == freq) - newfreq = 0; - } else - newfreq = freq; - - if(newfreq < 0) { - sound1SweepATL += sound1SweepATLReload; - } else if(newfreq > 2047) { - sound1SweepATL = 0; - sound1On = 0; - gbMemory[NR52] &= 0xfe; - } else { - sound1SweepATL += sound1SweepATLReload; - sound1Skip = SOUND_MAGIC/(2048 - newfreq); - - freq1low = newfreq & 0xff; - freq1high = (freq1high & 0xf8) |((newfreq >> 8) & 7); - } - } - } - } } void gbSoundChannel2() { - // int freq = 0; - int vol = sound2EnvelopeVolume; - - int value = 0; - - if(sound2On && (sound2ATL || !sound2Continue)) { - sound2Index += soundQuality*sound2Skip; - sound2Index &= 0x1fffffff; - - value = ((s8)sound2Wave[sound2Index>>24]) * vol; - } - - soundBuffer[1][soundIndex] = value; - - if(sound2On) { - if(sound2ATL) { - sound2ATL-=soundQuality; - - if(sound2ATL <= 0 && sound2Continue) { - gbMemory[NR52] &= 0xfd; - sound2On = 0; - } - } - - if(sound2EnvelopeATL) { - sound2EnvelopeATL-=soundQuality; - - if(sound2EnvelopeATL <= 0) { - if(sound2EnvelopeUpDown) { - if(sound2EnvelopeVolume < 15) - sound2EnvelopeVolume++; - } else { - if(sound2EnvelopeVolume) - sound2EnvelopeVolume--; - } - sound2EnvelopeATL += sound2EnvelopeATLReload; - } - } - } } void gbSoundChannel3() { - int value = 0; - - if(sound3On && (sound3ATL || !sound3Continue)) { - - value = sound3Last; - - sound3Index += soundQuality*sound3Skip; - sound3Index &= 0x1fffffff; - - value = gbMemory[0xff30 + (sound3Index>>25)]; - - if( (sound3Index & 0x01000000)) { - value &= 0x0f; - } else { - value >>= 4; - } - - value -= 8; - - switch(sound3OutputLevel) { - case 0: - value = 0; - break; - case 1: - break; - case 2: - value = (value >> 1); - break; - case 3: - value = (value >> 2); - break; - } - sound3Last = value; - } - - soundBuffer[2][soundIndex] = value; - - if(sound3On) { - if(sound3ATL) { - sound3ATL-=soundQuality; - - if(sound3ATL <= 0 && sound3Continue) { - gbMemory[NR52] &= 0xfb; - sound3On = 0; - } - } - } } void gbSoundChannel4() { - int vol = sound4EnvelopeVolume; - - int value = 0; - - if(sound4Clock <= 0x0c) { - if(sound4On && (sound4ATL || !sound4Continue)) { - sound4Index += soundQuality*sound4Skip; - sound4ShiftIndex += soundQuality*sound4ShiftSkip; - - if(sound4NSteps) { - while(sound4ShiftIndex > 0x1fffff) { - sound4ShiftRight = (((sound4ShiftRight << 6) ^ - (sound4ShiftRight << 5)) & 0x40) | - (sound4ShiftRight >> 1); - sound4ShiftIndex -= 0x200000; - } - } else { - while(sound4ShiftIndex > 0x1fffff) { - sound4ShiftRight = (((sound4ShiftRight << 14) ^ - (sound4ShiftRight << 13)) & 0x4000) | - (sound4ShiftRight >> 1); - - sound4ShiftIndex -= 0x200000; - } - } - - sound4Index &= 0x1fffff; - sound4ShiftIndex &= 0x1fffff; - - value = ((sound4ShiftRight & 1)*2-1) * vol; - } else { - value = 0; - } - } - - soundBuffer[3][soundIndex] = value; - - if(sound4On) { - if(sound4ATL) { - sound4ATL-=soundQuality; - - if(sound4ATL <= 0 && sound4Continue) { - gbMemory[NR52] &= 0xf7; - sound4On = 0; - } - } - - if(sound4EnvelopeATL) { - sound4EnvelopeATL-=soundQuality; - - if(sound4EnvelopeATL <= 0) { - if(sound4EnvelopeUpDown) { - if(sound4EnvelopeVolume < 15) - sound4EnvelopeVolume++; - } else { - if(sound4EnvelopeVolume) - sound4EnvelopeVolume--; - } - sound4EnvelopeATL += sound4EnvelopeATLReload; - } - } - } } -void gbSoundMix() +static void end_frame( blip_time_t time ) { - int res = 0; + gb_apu->end_frame( time ); + stereo_buffer->end_frame( time ); +} - if(soundBalance & 16) { - res += ((s8)soundBuffer[0][soundIndex]); - } - if(soundBalance & 32) { - res += ((s8)soundBuffer[1][soundIndex]); - } - if(soundBalance & 64) { - res += ((s8)soundBuffer[2][soundIndex]); - } - if(soundBalance & 128) { - res += ((s8)soundBuffer[3][soundIndex]); - } +static void flush_samples() +{ + int const out_buf_size = soundBufferLen / sizeof *soundFinalWave; + + while ( stereo_buffer->samples_avail() >= out_buf_size ) + { + stereo_buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size ); + if(systemSoundOn) + { + if(soundPaused) + soundResume(); - if(gbDigitalSound) - res *= soundLevel1*256; - else - res *= soundLevel1*60; + systemWriteDataToSoundBuffer(); + } + soundIndex = 0; + soundBufferIndex = 0; + } +} - if(soundEcho) { - res *= 2; - res += soundFilter[soundEchoIndex]; - res /= 2; - soundFilter[soundEchoIndex++] = res; - } +int const chan_count = 4; - if(soundLowPass) { - soundLeft[4] = soundLeft[3]; - soundLeft[3] = soundLeft[2]; - soundLeft[2] = soundLeft[1]; - soundLeft[1] = soundLeft[0]; - soundLeft[0] = res; - res = (soundLeft[4] + 2*soundLeft[3] + 8*soundLeft[2] + 2*soundLeft[1] + - soundLeft[0])/14; - } +gb_effects_config_t gb_effects_config; +static gb_effects_config_t gb_effects_config_current; - switch(soundVolume) { - case 0: - case 1: - case 2: - case 3: - res *= (soundVolume+1); - break; - case 4: - res >>= 2; - break; - case 5: - res >>= 1; - break; - } - - if(res > 32767) - res = 32767; - if(res < -32768) - res = -32768; - - if(soundReverse) - soundFinalWave[++soundBufferIndex] = res; - else - soundFinalWave[soundBufferIndex++] = res; - - res = 0; - - if(soundBalance & 1) { - res += ((s8)soundBuffer[0][soundIndex]); - } - if(soundBalance & 2) { - res += ((s8)soundBuffer[1][soundIndex]); - } - if(soundBalance & 4) { - res += ((s8)soundBuffer[2][soundIndex]); - } - if(soundBalance & 8) { - res += ((s8)soundBuffer[3][soundIndex]); - } - - if(gbDigitalSound) - res *= soundLevel2*256; - else - res *= soundLevel2*60; - - if(soundEcho) { - res *= 2; - res += soundFilter[soundEchoIndex]; - res /= 2; - soundFilter[soundEchoIndex++] = res; - - if(soundEchoIndex >= 4000) - soundEchoIndex = 0; - } - - if(soundLowPass) { - soundRight[4] = soundRight[3]; - soundRight[3] = soundRight[2]; - soundRight[2] = soundRight[1]; - soundRight[1] = soundRight[0]; - soundRight[0] = res; - res = (soundRight[4] + 2*soundRight[3] + 8*soundRight[2] + 2*soundRight[1] + - soundRight[0])/14; - } - - switch(soundVolume) { - case 0: - case 1: - case 2: - case 3: - res *= (soundVolume+1); - break; - case 4: - res >>= 2; - break; - case 5: - res >>= 1; - break; - } - - if(res > 32767) - res = 32767; - if(res < -32768) - res = -32768; - - if(soundReverse) - soundFinalWave[-1+soundBufferIndex++] = res; - else - soundFinalWave[soundBufferIndex++] = res; +static void apply_effects() +{ + gb_effects_config_current = gb_effects_config; + + stereo_buffer->config().enabled = gb_effects_config_current.enabled; + stereo_buffer->config().echo = gb_effects_config_current.echo; + stereo_buffer->config().stereo = gb_effects_config_current.stereo; + stereo_buffer->config().surround = gb_effects_config_current.surround; + stereo_buffer->apply_config(); + + for ( int i = 0; i < chan_count; i++ ) + { + Multi_Buffer::channel_t ch = stereo_buffer->channel( i ); + gb_apu->set_output( ch.center, ch.left, ch.right, i ); + } } void gbSoundTick() { - if(systemSoundOn) { - if(soundMasterOn) { - gbSoundChannel1(); - gbSoundChannel2(); - gbSoundChannel3(); - gbSoundChannel4(); + if(systemSoundOn && gb_apu && stereo_buffer) + { + end_frame( ticks_to_time( SOUND_CLOCK_TICKS ) ); + flush_samples(); + + // Update effects config if it was changed + if ( memcmp( &gb_effects_config_current, &gb_effects_config, + sizeof gb_effects_config ) ) + apply_effects(); + } +} - gbSoundMix(); - } else { - soundFinalWave[soundBufferIndex++] = 0; - soundFinalWave[soundBufferIndex++] = 0; - } - - soundIndex++; - - if(2*soundBufferIndex >= soundBufferLen) { - if(systemSoundOn) { - if(soundPaused) { - soundResume(); - } - - systemWriteDataToSoundBuffer(); - } - soundIndex = 0; - soundBufferIndex = 0; - } - } +static void remake_stereo_buffer() +{ + if ( !gb_apu ) + gb_apu = new Gb_Apu; + + delete stereo_buffer; + stereo_buffer = 0; + + stereo_buffer = new Simple_Effects_Buffer; + stereo_buffer->set_sample_rate( 44100 / soundQuality ); + stereo_buffer->clock_rate( gb_apu->clock_rate ); + + static int const chan_types [chan_count] = { + Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, + Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 + }; + stereo_buffer->set_channel_count( chan_count, chan_types ); + + apply_effects(); + + gb_apu->reset( gb_apu->mode_cgb ); } void gbSoundReset() -{ +{ + remake_stereo_buffer(); + soundPaused = 1; soundPlay = 0; - SOUND_CLOCK_TICKS = soundQuality * 24; + SOUND_CLOCK_TICKS = 20000; soundTicks = SOUND_CLOCK_TICKS; soundNextPosition = 0; soundMasterOn = 1; @@ -891,144 +407,22 @@ void gbSoundSetQuality(int quality) soundNextPosition = 0; if(!soundOffFlag) soundInit(); - SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality; + //SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality; soundIndex = 0; soundBufferIndex = 0; } else { soundNextPosition = 0; - SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality; + //SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality; soundIndex = 0; soundBufferIndex = 0; } + remake_stereo_buffer(); } -variable_desc gbSoundSaveStruct[] = { - { &soundPaused, sizeof(int) }, - { &soundPlay, sizeof(int) }, - { &soundTicks, sizeof(int) }, - { &SOUND_CLOCK_TICKS, sizeof(int) }, - { &soundLevel1, sizeof(int) }, - { &soundLevel2, sizeof(int) }, - { &soundBalance, sizeof(int) }, - { &soundMasterOn, sizeof(int) }, - { &soundIndex, sizeof(int) }, - { &soundVIN, sizeof(int) }, - { &sound1On, sizeof(int) }, - { &sound1ATL, sizeof(int) }, - { &sound1Skip, sizeof(int) }, - { &sound1Index, sizeof(int) }, - { &sound1Continue, sizeof(int) }, - { &sound1EnvelopeVolume, sizeof(int) }, - { &sound1EnvelopeATL, sizeof(int) }, - { &sound1EnvelopeATLReload, sizeof(int) }, - { &sound1EnvelopeUpDown, sizeof(int) }, - { &sound1SweepATL, sizeof(int) }, - { &sound1SweepATLReload, sizeof(int) }, - { &sound1SweepSteps, sizeof(int) }, - { &sound1SweepUpDown, sizeof(int) }, - { &sound1SweepStep, sizeof(int) }, - { &sound2On, sizeof(int) }, - { &sound2ATL, sizeof(int) }, - { &sound2Skip, sizeof(int) }, - { &sound2Index, sizeof(int) }, - { &sound2Continue, sizeof(int) }, - { &sound2EnvelopeVolume, sizeof(int) }, - { &sound2EnvelopeATL, sizeof(int) }, - { &sound2EnvelopeATLReload, sizeof(int) }, - { &sound2EnvelopeUpDown, sizeof(int) }, - { &sound3On, sizeof(int) }, - { &sound3ATL, sizeof(int) }, - { &sound3Skip, sizeof(int) }, - { &sound3Index, sizeof(int) }, - { &sound3Continue, sizeof(int) }, - { &sound3OutputLevel, sizeof(int) }, - { &sound4On, sizeof(int) }, - { &sound4ATL, sizeof(int) }, - { &sound4Skip, sizeof(int) }, - { &sound4Index, sizeof(int) }, - { &sound4Clock, sizeof(int) }, - { &sound4ShiftRight, sizeof(int) }, - { &sound4ShiftSkip, sizeof(int) }, - { &sound4ShiftIndex, sizeof(int) }, - { &sound4NSteps, sizeof(int) }, - { &sound4CountDown, sizeof(int) }, - { &sound4Continue, sizeof(int) }, - { &sound4EnvelopeVolume, sizeof(int) }, - { &sound4EnvelopeATL, sizeof(int) }, - { &sound4EnvelopeATLReload, sizeof(int) }, - { &sound4EnvelopeUpDown, sizeof(int) }, - { &soundEnableFlag, sizeof(int) }, - { NULL, 0 } -}; - void gbSoundSaveGame(gzFile gzFile) { - utilWriteData(gzFile, gbSoundSaveStruct); - - utilWriteInt(gzFile, sound1ATLreload); - utilWriteInt(gzFile, freq1low); - utilWriteInt(gzFile, freq1high); - utilWriteInt(gzFile, sound2ATLreload); - utilWriteInt(gzFile, freq2low); - utilWriteInt(gzFile, freq2high); - utilWriteInt(gzFile, sound3ATLreload); - utilWriteInt(gzFile, freq3low); - utilWriteInt(gzFile, freq3high); - utilWriteInt(gzFile, sound4ATLreload); - utilWriteInt(gzFile, freq4); - - utilGzWrite(gzFile, soundBuffer, 4*735); - utilGzWrite(gzFile, soundFinalWave, 2*735); - utilGzWrite(gzFile, &soundQuality, sizeof(int)); } void gbSoundReadGame(int version,gzFile gzFile) { - utilReadData(gzFile, gbSoundSaveStruct); - - if (version<11) - { - sound1ATLreload = 172 * (64 - (gbMemory[NR11] & 0x3f)); - freq1low = gbMemory[NR13]; - freq1high = gbMemory[NR14] & 7; - sound2ATLreload = 172 * (64 - (gbMemory[NR21] & 0x3f)); - freq2low = gbMemory[NR23]; - freq2high = gbMemory[NR24] & 7; - sound3ATLreload = 172 * (256 - gbMemory[NR31]); - freq3low = gbMemory[NR33]; - freq3high = gbMemory[NR34] & 7; - sound4ATLreload = 172 * (64 - (gbMemory[NR41] & 0x3f)); - freq4 = soundFreqRatio[gbMemory[NR43] & 7]; - } - else - { - sound1ATLreload = utilReadInt(gzFile); - freq1low = utilReadInt(gzFile); - freq1high = utilReadInt(gzFile); - sound2ATLreload = utilReadInt(gzFile); - freq2low = utilReadInt(gzFile); - freq2high = utilReadInt(gzFile); - sound3ATLreload = utilReadInt(gzFile); - freq3low = utilReadInt(gzFile); - freq3high = utilReadInt(gzFile); - sound4ATLreload = utilReadInt(gzFile); - freq4 = utilReadInt(gzFile); - } - - soundBufferIndex = soundIndex * 2; - - utilGzRead(gzFile, soundBuffer, 4*735); - utilGzRead(gzFile, soundFinalWave, 2*735); - - if(version >=7) { - int quality = 1; - utilGzRead(gzFile, &quality, sizeof(int)); - gbSoundSetQuality(quality); - } else { - soundQuality = -1; - gbSoundSetQuality(1); - } - - sound1Wave = soundWavePattern[gbMemory[NR11] >> 6]; - sound2Wave = soundWavePattern[gbMemory[NR21] >> 6]; } diff --git a/src/gb/gbSound.h b/src/gb/gbSound.h index 50658b24..1bd715f5 100644 --- a/src/gb/gbSound.h +++ b/src/gb/gbSound.h @@ -54,6 +54,19 @@ extern void gbSoundReadGame(int,gzFile); extern void gbSoundEvent(register u16, register int); extern void gbSoundSetQuality(int); +extern u8 gbSoundRead(u16 address); + extern int soundTicks; extern int soundQuality; extern int SOUND_CLOCK_TICKS; + +struct gb_effects_config_t +{ + bool enabled; // false = disable all effects + float echo; // 0.0 = none, 1.0 = lots + float stereo; // 0.0 = channels in center, 1.0 = channels on left/right + bool surround; // true = put some channels in back +}; +// Can be changed at any time, probably from another thread too. +// Sound will notice changes during next 1/100 second. +extern gb_effects_config_t gb_effects_config;