Sound code optimizations based on results of code profiling. Also contains some #ifdef'd out experimental

optimized code for sound filtering
This commit is contained in:
DJRobX 2007-11-05 07:13:08 +00:00
parent a8953de9da
commit b5745f7a39
8 changed files with 302 additions and 144 deletions

View File

@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\libpng.vcp
{34DC39BF-F93A-4573-85BF-789B90B63179} = {34DC39BF-F93A-4573-85BF-789B90B63179}
EndProjectSection
EndProject
Project("{4CAA2610-1955-4629-BDC1-8133FE0B2087}") = "profiler", "..\profiler\profiler.aqt", "{7260A190-9B72-4227-B01C-29E53BA53413}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32

View File

@ -3906,7 +3906,7 @@ void CPULoop(int ticks)
// mute sound
soundTicks -= clockTicks;
if(soundTicks <= 0) {
soundTick();
psoundTickfn();
soundTicks += SOUND_CLOCK_TICKS;
}
timerOverflow = 0;

View File

@ -115,7 +115,7 @@ int soundBufferLen = 1470;
int soundBufferTotalLen = 14700;
int soundQuality = 2;
int soundInterpolation = 0;
int soundPaused = 1;
bool soundPaused = true;
int soundPlay = 0;
int soundTicks = soundQuality * USE_TICKS_AS;
int SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;
@ -300,6 +300,103 @@ variable_desc soundSaveStructV2[] = {
{ NULL, 0 }
};
// *** Begin snd_interp code
// and here is the implementation specific code, in a messier state than the stuff above
extern bool timer0On;
extern int timer0Reload;
extern int timer0ClockReload;
extern bool timer1On;
extern int timer1Reload;
extern int timer1ClockReload;
extern int SOUND_CLOCK_TICKS;
extern int soundInterpolation;
inline double calc_rate(int timer)
{
if (timer ? timer1On : timer0On)
{
return double(SOUND_CLOCK_TICKS) /
double((0x10000 - (timer ? timer1Reload : timer0Reload)) *
(timer ? timer1ClockReload : timer0ClockReload));
}
else
{
return 1.;
}
}
static foo_interpolate * interp[2];
class foo_interpolate_setup
{
public:
foo_interpolate_setup()
{
for (int i = 0; i < 2; i++)
{
interp[i] = get_filter(0);
}
}
~foo_interpolate_setup()
{
for (int i = 0; i < 2; i++)
{
delete interp[i];
}
}
};
static foo_interpolate_setup blah;
static int interpolation = 0;
void interp_switch(int which)
{
for (int i = 0; i < 2; i++)
{
delete interp[i];
interp[i] = get_filter(which);
}
interpolation = which;
}
void interp_reset(int ch)
{
setSoundFn();
#ifdef ENHANCED_RATE
interp[ch]->reset();
#else
interp[ch]->reset(calc_rate(ch ? soundDSATimer : soundDSBTimer));
#endif
}
inline void interp_push(int ch, int sample)
{
interp[ch]->push(sample);
}
#ifdef ENHANCED_RATE
inline int interp_pop(int ch, double rate)
{
return interp[ch]->pop(rate);
#else
inline int interp_pop(int ch)
{
return interp[ch]->pop();
#endif
}
// *** End snd_interp code
static void soundEventGB(u32 address, u8 data)
{
if ( apu )
@ -479,7 +576,7 @@ u8 soundRead(u32 address)
case 0x9c:
case 0x9e:
soundEventGB(0xFF30 + (address & 14), data);
soundEventGB(0xFF31 + (address & 14), data >> 8);
soundEventGB(0xFF31 + (address & 14), 0); // data >> 8);
break;
}
}
@ -540,7 +637,7 @@ void soundEvent(u32 address, u16 data)
case 0x9a:
case 0x9c:
case 0x9e:
soundEventGB(0xFF30 + (address & 14), data);
soundEventGB(0xFF30 + (address & 14), data & 0xff);
soundEventGB(0xFF31 + (address & 14), data >> 8);
break;
}
@ -562,9 +659,33 @@ void soundChannel4()
{
}
void soundDirectSoundA()
#include <stdio.h>
inline void soundDirectSoundA()
{
directBuffer[0][soundIndex] = interp_pop(0, calc_rate(soundDSATimer)); //soundDSAValue;
#ifdef ENHANCED_RATE
double cr = calc_rate(soundDSATimer);
static int cnt = 0;
static double lastcr = 0;
static FILE *fp = NULL;
if (fp==NULL)
fp=fopen("C:\\cr.txt", "at");
if (cr!=lastcr)
{
fprintf(fp, "%f %d\n", lastcr, cnt);
cnt=0;
lastcr=cr;
}
else
cnt++;
directBuffer[0][soundIndex] = interp_pop(0, calc_rate(soundDSATimer)); //soundDSAValue;
#else
directBuffer[0][soundIndex] = interp_pop(0); //soundDSAValue;
#endif
}
void soundDirectSoundATimer()
@ -592,9 +713,13 @@ void soundDirectSoundATimer()
soundDSAValue = 0;
}
void soundDirectSoundB()
inline void soundDirectSoundB()
{
directBuffer[1][soundIndex] = interp_pop(1, calc_rate(soundDSBTimer)); //soundDSBValue;
#ifdef ENHANCED_RATE
directBuffer[1][soundIndex] = interp_pop(1, calc_rate(soundDSBTimer)); //soundDSBValue;
#else
directBuffer[1][soundIndex] = interp_pop(1); //soundDSBValue;
#endif
}
void soundDirectSoundBTimer()
@ -811,14 +936,31 @@ void soundMix()
soundFinalWave[soundBufferIndex++] = res;
}
// soundTick gets called a lot
// if we are operating normally
// call normalSoundTick to avoid
// all the comparison checks.
void normalsoundTick()
{
soundDirectSoundA();
soundDirectSoundB();
soundMix();
soundIndex++;
if(2*soundBufferIndex >= soundBufferLen)
{
systemWriteDataToSoundBuffer();
soundIndex = 0;
soundBufferIndex = 0;
}
}
void soundTick()
{
if(systemSoundOn) {
if(soundMasterOn && !stopState) {
/*soundChannel1();
soundChannel2();
soundChannel3();
soundChannel4();*/
soundDirectSoundA();
soundDirectSoundB();
soundMix();
@ -833,6 +975,7 @@ void soundTick()
if(systemSoundOn) {
if(soundPaused) {
soundResume();
setSoundFn();
}
systemWriteDataToSoundBuffer();
@ -843,6 +986,41 @@ void soundTick()
}
}
void (*psoundTickfn)()=soundTick;
void setSoundFn()
{
if (systemSoundOn && !soundPaused && soundMasterOn)
psoundTickfn = normalsoundTick;
else
psoundTickfn = soundTick;
if (soundInterpolation != interpolation)
interp_switch(soundInterpolation);
}
void setsystemSoundOn(bool value)
{
systemSoundOn = value;
setSoundFn();
}
void setsoundPaused(bool value)
{
soundPaused = value;
setSoundFn();
}
void setsoundMasterOn(bool value)
{
soundMasterOn = value;
setSoundFn();
}
void soundShutdown()
{
systemSoundShutdown();
@ -868,13 +1046,13 @@ void soundShutdown()
void soundPause()
{
systemSoundPause();
soundPaused = 1;
setsoundPaused(true);
}
void soundResume()
{
systemSoundResume();
soundPaused = 0;
setsoundPaused(false);
}
void soundEnable(int channels)
@ -918,12 +1096,12 @@ void soundReset()
{
systemSoundReset();
soundPaused = 1;
setsoundPaused(true);
soundPlay = 0;
SOUND_CLOCK_TICKS = soundQuality * USE_TICKS_AS;
soundTicks = SOUND_CLOCK_TICKS;
soundNextPosition = 0;
soundMasterOn = 1;
setsoundMasterOn(true);
soundIndex = 0;
soundBufferIndex = 0;
soundLevel1 = 7;
@ -1099,7 +1277,7 @@ bool soundInit(bool gba)
}
}
soundPaused = true;
setsoundPaused(true);
return true;
}
return false;

View File

@ -47,7 +47,8 @@
#define FIFOB_L 0xa4
#define FIFOB_H 0xa6
extern void soundTick();
extern void setSoundFn();
extern void (*psoundTickfn)();
extern void soundShutdown();
extern bool soundInit(bool gba=true);
extern void soundPause();
@ -62,6 +63,10 @@ extern void soundEvent(u32, u8);
extern void soundEvent(u32, u16);
extern void soundTimerOverflow(int);
extern void soundSetQuality(int);
extern void setsystemSoundOn(bool value);
extern void setsoundPaused(bool value);
extern void setsoundMasterOn(bool value);
//extern int SOUND_TICKS;
extern int SOUND_CLOCK_TICKS;
@ -69,8 +74,8 @@ extern u8 soundRead(u32);
extern u16 soundRead16(u32);
extern u32 soundRead32(u32);
extern int soundTicks;
extern int soundPaused;
extern bool soundOffFlag;
extern bool soundPaused;
extern int soundQuality;
extern int soundBufferLen;
extern int soundBufferTotalLen;

View File

@ -43,7 +43,7 @@ extern u8 soundWavePattern[4][32];
extern int soundBufferLen;
extern int soundBufferTotalLen;
extern int soundQuality;
extern int soundPaused;
extern bool soundPaused;
extern int soundPlay;
extern int soundTicks;
extern int SOUND_CLOCK_TICKS;

View File

@ -202,14 +202,20 @@ public:
foo_null() : sample(0) {}
~foo_null() {}
#ifdef ENHANCED_RATE
void reset() {}
#endif
void push(int psample)
{
sample = psample;
}
#ifdef ENHANCED_RATE
int pop(double rate)
#else
int pop()
#endif
{
return sample;
}
@ -234,20 +240,33 @@ public:
~foo_linear() {}
#ifdef ENHANCED_RATE
void reset()
{
#else
void reset(double rate)
{
foo_interpolate::reset(rate);
#endif
position = 0;
samples.clear();
}
void push(int sample)
{
samples.push_back(sample);
}
#ifdef ENHANCED_RATE
int pop(double rate)
{
int ret, lrate;
int lrate;
#else
int pop()
{
#endif
int ret;
if (position > 0x7fff)
{
@ -262,6 +281,7 @@ public:
ret += smp(1) * position;
ret >>= 15;
#ifdef ENHANCED_RATE
// wahoo, takes care of drifting
if (samples.size() > 2)
{
@ -269,6 +289,10 @@ public:
}
lrate = (int)(32768. * rate);
#else
if (samples.size() > 2)
position+=1;
#endif
position += lrate;
return ret;
@ -308,9 +332,15 @@ public:
samples.push_back(sample);
}
#ifdef ENHANCED_RATE
int pop(double rate)
{
int ret, lrate;
int lrate;
#else
int pop()
{
#endif
int ret;
if (position > 0x7fff)
{
@ -338,10 +368,14 @@ public:
// wahoo, takes care of drifting
if (samples.size() > 8)
{
#ifdef ENHANCED_RATE
rate += (.5 / 32768.);
}
lrate = (int)(32768. * rate);
#else
position+=1;
}
#endif
position += lrate;
return ret;
@ -367,8 +401,14 @@ public:
~foo_fir() {}
#ifdef ENHANCED_RATE
void reset()
{
#else
void reset(double rate)
{
foo_interpolate::reset(rate);
#endif
position = 0;
samples.clear();
}
@ -378,9 +418,15 @@ public:
samples.push_back(sample);
}
#ifdef ENHANCED_RATE
int pop(double rate)
{
int ret, lrate;
int lrate;
#else
int pop()
{
#endif
int ret;
if (position > 0x7fff)
{
@ -404,6 +450,7 @@ public:
if (ret > 32767) ret = 32767;
else if (ret < -32768) ret = -32768;
#ifdef ENHANCED_RATE
// wahoo, takes care of drifting
if (samples.size() > 16)
{
@ -412,7 +459,12 @@ public:
lrate = (int)(32768. * rate);
position += lrate;
#else
if (samples.size() > 16)
position+=1;
position+=9929;
#endif
return ret;
}
};
@ -431,11 +483,22 @@ public:
~foo_libresample()
{
#ifdef ENHANCED_RATE
reset();
#else
reset(1);
#endif
}
#ifdef ENHANCED_RATE
void reset()
{
#else
void reset(double rate)
{
foo_interpolate::reset(rate);
#endif
samples.clear();
if (resampler)
{
@ -449,10 +512,14 @@ public:
samples.push_back(float(sample));
}
#ifdef ENHANCED_RATE
int pop(double rate)
{
#else
int pop()
{
#endif
int ret;
if (!resampler)
{
resampler = resample_open(0, .25, 44100. / 4000.);
@ -469,8 +536,11 @@ public:
in[used] = samples[used];
}
#ifdef ENHANCED_RATE
returned = resample_process(resampler, 1. / rate, in, count, 0, &used, &out, 1);
#else
returned = resample_process(resampler, lrate / 32767, in, count, 0, &used, &out, 1);
#endif
if (used)
{
samples.erase(used);
@ -506,114 +576,3 @@ foo_interpolate * get_filter(int which)
return new foo_libresample;
}
}
// and here is the implementation specific code, in a messier state than the stuff above
extern bool timer0On;
extern int timer0Reload;
extern int timer0ClockReload;
extern bool timer1On;
extern int timer1Reload;
extern int timer1ClockReload;
extern int SOUND_CLOCK_TICKS;
extern int soundInterpolation;
double calc_rate(int timer)
{
if (timer ? timer1On : timer0On)
{
return double(SOUND_CLOCK_TICKS) /
double((0x10000 - (timer ? timer1Reload : timer0Reload)) *
(timer ? timer1ClockReload : timer0ClockReload));
}
else
{
return 1.;
}
}
static foo_interpolate * interp[2];
class foo_interpolate_setup
{
public:
foo_interpolate_setup()
{
for (int i = 0; i < 2; i++)
{
interp[i] = get_filter(0);
}
}
~foo_interpolate_setup()
{
for (int i = 0; i < 2; i++)
{
delete interp[i];
}
}
};
static foo_interpolate_setup blah;
class critical_section
{
CRITICAL_SECTION cs;
public:
critical_section() { InitializeCriticalSection(&cs); }
~critical_section() { DeleteCriticalSection(&cs); }
void enter() { EnterCriticalSection(&cs); }
void leave() { LeaveCriticalSection(&cs); }
};
static critical_section interp_sync;
static int interpolation = 0;
class scopelock
{
critical_section * cs;
public:
scopelock(critical_section & pcs) { cs = &pcs; cs->enter(); }
~scopelock() { cs->leave(); }
};
void interp_switch(int which)
{
scopelock sl(interp_sync);
for (int i = 0; i < 2; i++)
{
delete interp[i];
interp[i] = get_filter(which);
}
interpolation = which;
}
void interp_reset(int ch)
{
scopelock sl(interp_sync);
if (soundInterpolation != interpolation) interp_switch(soundInterpolation);
interp[ch]->reset();
}
void interp_push(int ch, int sample)
{
scopelock sl(interp_sync);
if (soundInterpolation != interpolation) interp_switch(soundInterpolation);
interp[ch]->push(sample);
}
int interp_pop(int ch, double rate)
{
scopelock sl(interp_sync);
if (soundInterpolation != interpolation) interp_switch(soundInterpolation);
return interp[ch]->pop(rate);
}

View File

@ -2,6 +2,7 @@
#define __SND_INTERP_H__
// simple interface that could easily be recycled
#define ENHANCED_RATE
class foo_interpolate
{
@ -9,22 +10,36 @@ public:
foo_interpolate() {}
virtual ~foo_interpolate() {};
#ifdef ENHANCED_RATE
virtual void reset() = 0;
#else
long lrate;
virtual void reset(double rate)
{
lrate = (int)(32768. * rate);
};
#endif
virtual void push(int sample) = 0;
#ifdef ENHANCED_RATE
virtual int pop(double rate) = 0;
#else
virtual int pop() = 0;
#endif
};
foo_interpolate * get_filter(int which);
extern foo_interpolate * get_filter(int which);
/*
// complicated, synced interface, specific to this implementation
double calc_rate(int timer);
void interp_switch(int which);
void interp_reset(int ch);
void interp_push(int ch, int sample);
int interp_pop(int ch, double rate);
inline void interp_push(int ch, int sample);
inline int interp_pop(int ch, double rate); */
#endif

View File

@ -242,8 +242,7 @@ bool DirectSound::init()
return false;
}
systemSoundOn = true;
setsystemSoundOn(true);
return true;
}
@ -343,7 +342,7 @@ void DirectSound::write()
}
}
} else {
soundPaused = 1;
setsoundPaused(true);
}
}
// Obtain memory address of write block. This will be in two parts