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;