spu: fix the ancient bug in looping adpcm sounds which slew performance. this is what made the adpcm caching option necessary as a workaround. so--get rid of adpcm caching.
This commit is contained in:
parent
715b2a0c4c
commit
451366ab66
|
@ -429,7 +429,6 @@ extern struct TCommonSettings {
|
||||||
, DebugConsole(false)
|
, DebugConsole(false)
|
||||||
, single_core(true)
|
, single_core(true)
|
||||||
, spuInterpolationMode(SPUInterpolation_Linear)
|
, spuInterpolationMode(SPUInterpolation_Linear)
|
||||||
, spuAdpcmCache(false)
|
|
||||||
, gfx3d_flushMode(0)
|
, gfx3d_flushMode(0)
|
||||||
, manualBackupType(0)
|
, manualBackupType(0)
|
||||||
{
|
{
|
||||||
|
@ -464,7 +463,6 @@ extern struct TCommonSettings {
|
||||||
} wifi;
|
} wifi;
|
||||||
|
|
||||||
SPUInterpolationMode spuInterpolationMode;
|
SPUInterpolationMode spuInterpolationMode;
|
||||||
bool spuAdpcmCache;
|
|
||||||
|
|
||||||
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
|
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
|
||||||
int gfx3d_flushMode;
|
int gfx3d_flushMode;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#define M_PI 3.1415926535897932386
|
#define M_PI 3.1415926535897932386
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define K_ADPCM_LOOPING_RECOVERY_INDEX 99999
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "MMU.h"
|
#include "MMU.h"
|
||||||
#include "SPU.h"
|
#include "SPU.h"
|
||||||
|
@ -106,157 +108,6 @@ static FORCEINLINE T MinMax(T val, T min, T max)
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class ADPCMCacheItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ADPCMCacheItem()
|
|
||||||
: raw_copy(NULL)
|
|
||||||
, decoded(NULL)
|
|
||||||
, next(NULL)
|
|
||||||
, prev(NULL)
|
|
||||||
, lockCount(0)
|
|
||||||
{}
|
|
||||||
~ADPCMCacheItem() {
|
|
||||||
delete[] raw_copy;
|
|
||||||
delete[] decoded;
|
|
||||||
}
|
|
||||||
void unlock() {
|
|
||||||
lockCount--;
|
|
||||||
}
|
|
||||||
void lock() {
|
|
||||||
lockCount++;
|
|
||||||
}
|
|
||||||
u32 addr;
|
|
||||||
s8* raw_copy; //for memcmp
|
|
||||||
u32 raw_len;
|
|
||||||
u32 decode_len;
|
|
||||||
s16* decoded; //s16 decoded samples
|
|
||||||
ADPCMCacheItem *next, *prev; //double linked list
|
|
||||||
int lockCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
//notes on the cache:
|
|
||||||
//I am really unhappy with the ref counting. this needs to be automatic.
|
|
||||||
//We could do something better than a linear search through cache items, but it may not be worth it.
|
|
||||||
//Also we may need to rescan more often (every time a sample loops)
|
|
||||||
class ADPCMCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ADPCMCache()
|
|
||||||
: list_front(NULL)
|
|
||||||
, list_back(NULL)
|
|
||||||
, cache_size(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ADPCMCacheItem *list_front, *list_back;
|
|
||||||
|
|
||||||
//this ought to be enough for anyone
|
|
||||||
static const u32 kMaxCacheSize = 8*1024*1024;
|
|
||||||
//this is not really precise, it is off by a constant factor
|
|
||||||
u32 cache_size;
|
|
||||||
|
|
||||||
void evict(const u32 target = kMaxCacheSize) {
|
|
||||||
//evicts old cache items until it is less than the max cache size
|
|
||||||
//this means we actually can exceed the cache by the size of the next item.
|
|
||||||
//if we really wanted to hold ourselves to it, we could evict to kMaxCacheSize-nextItemSize
|
|
||||||
while(cache_size > target)
|
|
||||||
{
|
|
||||||
ADPCMCacheItem *oldest = list_back;
|
|
||||||
while(oldest && oldest->lockCount>0) oldest = oldest->prev; //find an unlocked one
|
|
||||||
if(!oldest)
|
|
||||||
{
|
|
||||||
//nothing we can do, everything in the cache is locked. maybe we're leaking.
|
|
||||||
//just quit trying to evict
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
list_remove(oldest);
|
|
||||||
cache_size -= oldest->raw_len*2;
|
|
||||||
//printf("evicting! totalsize:%d\n",cache_size);
|
|
||||||
delete oldest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//DO NOT USE THIS METHOD WITHOUT MAKING SURE YOU HAVE
|
|
||||||
//FREED THE CURRENT ADPCMCacheItem FIRST!
|
|
||||||
//we should do this with some kind of smart pointers, but i am too lazy
|
|
||||||
ADPCMCacheItem* scan(channel_struct *chan)
|
|
||||||
{
|
|
||||||
u32 addr = chan->addr;
|
|
||||||
s8* raw = chan->buf8;
|
|
||||||
u32 raw_len = chan->totlength * 4;
|
|
||||||
for(ADPCMCacheItem* curr = list_front;curr;curr=curr->next)
|
|
||||||
{
|
|
||||||
if(curr->addr != addr) continue;
|
|
||||||
if(curr->raw_len != raw_len) continue;
|
|
||||||
if(memcmp(curr->raw_copy,raw,raw_len))
|
|
||||||
{
|
|
||||||
//we found a cached item for the current address, but the data is stale.
|
|
||||||
//for a variety of complicated reasons, we need to throw it out right this instant.
|
|
||||||
list_remove(curr);
|
|
||||||
delete curr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr->lock();
|
|
||||||
list_remove(curr);
|
|
||||||
list_push_front(curr);
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//item was not found. recruit an existing one (the oldest), or create a new one
|
|
||||||
evict(); //reduce the size of the cache if necessary
|
|
||||||
ADPCMCacheItem* newitem = new ADPCMCacheItem();
|
|
||||||
newitem->lock();
|
|
||||||
newitem->addr = addr;
|
|
||||||
newitem->raw_len = raw_len;
|
|
||||||
newitem->raw_copy = new s8[raw_len];
|
|
||||||
memcpy(newitem->raw_copy,chan->buf8,raw_len);
|
|
||||||
u32 decode_len = newitem->decode_len = raw_len*2;
|
|
||||||
cache_size += newitem->decode_len;
|
|
||||||
newitem->decoded = new s16[decode_len];
|
|
||||||
|
|
||||||
int index = chan->buf8[2] & 0x7F;
|
|
||||||
s16 pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]);
|
|
||||||
s16 pcm16b_last = pcm16b;
|
|
||||||
|
|
||||||
for(u32 i = 8; i < decode_len; i++)
|
|
||||||
{
|
|
||||||
const u32 shift = (i&1)<<2;
|
|
||||||
const u32 data4bit = (((u32)chan->buf8[i >> 1]) >> shift);
|
|
||||||
|
|
||||||
const s32 diff = precalcdifftbl[index][data4bit & 0xF];
|
|
||||||
index = precalcindextbl[index][data4bit & 0x7];
|
|
||||||
|
|
||||||
pcm16b_last = pcm16b;
|
|
||||||
pcm16b = MinMax(pcm16b+diff, -0x8000, 0x7FFF);
|
|
||||||
newitem->decoded[i] = pcm16b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("new cacheitem! totalsize:%d\n",cache_size);
|
|
||||||
list_push_front(newitem);
|
|
||||||
return newitem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_remove(ADPCMCacheItem* item) {
|
|
||||||
if(item->next) item->next->prev = item->prev;
|
|
||||||
if(item->prev) item->prev->next = item->next;
|
|
||||||
if(item == list_front) list_front = item->next;
|
|
||||||
if(item == list_back) list_back = item->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
void list_push_front(ADPCMCacheItem* item)
|
|
||||||
{
|
|
||||||
item->next = list_front;
|
|
||||||
if(list_front) list_front->prev = item;
|
|
||||||
else list_back = item;
|
|
||||||
item->prev = NULL;
|
|
||||||
list_front = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
} adpcmCache;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int SPU_ChangeSoundCore(int coreid, int buffersize)
|
int SPU_ChangeSoundCore(int coreid, int buffersize)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -380,9 +231,6 @@ void SPU_Reset(void)
|
||||||
//todo - check success?
|
//todo - check success?
|
||||||
}
|
}
|
||||||
|
|
||||||
//keep the cache tidy
|
|
||||||
adpcmCache.evict(0);
|
|
||||||
|
|
||||||
// Reset Registers
|
// Reset Registers
|
||||||
for (i = 0x400; i < 0x51D; i++)
|
for (i = 0x400; i < 0x51D; i++)
|
||||||
T1WriteByte(MMU.ARM7_REG, i, 0);
|
T1WriteByte(MMU.ARM7_REG, i, 0);
|
||||||
|
@ -395,12 +243,6 @@ void SPU_struct::reset()
|
||||||
memset(sndbuf,0,bufsize*2*4);
|
memset(sndbuf,0,bufsize*2*4);
|
||||||
memset(outbuf,0,bufsize*2*2);
|
memset(outbuf,0,bufsize*2*2);
|
||||||
|
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if(channels[i].cacheItem)
|
|
||||||
channels[i].cacheItem->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
memset((void *)channels, 0, sizeof(channel_struct) * 16);
|
memset((void *)channels, 0, sizeof(channel_struct) * 16);
|
||||||
|
|
||||||
for(int i = 0; i < 16; i++)
|
for(int i = 0; i < 16; i++)
|
||||||
|
@ -425,11 +267,6 @@ SPU_struct::~SPU_struct()
|
||||||
{
|
{
|
||||||
if(sndbuf) delete[] sndbuf;
|
if(sndbuf) delete[] sndbuf;
|
||||||
if(outbuf) delete[] outbuf;
|
if(outbuf) delete[] outbuf;
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if(channels[i].cacheItem)
|
|
||||||
channels[i].cacheItem->unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPU_DeInit(void)
|
void SPU_DeInit(void)
|
||||||
|
@ -484,13 +321,9 @@ void SPU_struct::KeyOn(int channel)
|
||||||
thischan.index = thischan.buf8[2] & 0x7F;
|
thischan.index = thischan.buf8[2] & 0x7F;
|
||||||
thischan.lastsampcnt = 7;
|
thischan.lastsampcnt = 7;
|
||||||
thischan.sampcnt = 8;
|
thischan.sampcnt = 8;
|
||||||
|
thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX;
|
||||||
// thischan.loopstart = thischan.loopstart << 3;
|
// thischan.loopstart = thischan.loopstart << 3;
|
||||||
// thischan.length = (thischan.length << 3) + thischan.loopstart;
|
// thischan.length = (thischan.length << 3) + thischan.loopstart;
|
||||||
if(thischan.cacheItem) thischan.cacheItem->unlock();
|
|
||||||
thischan.cacheItem = NULL;
|
|
||||||
if(CommonSettings.spuAdpcmCache)
|
|
||||||
if(this != SPU_core)
|
|
||||||
thischan.cacheItem = adpcmCache.scan(&thischan);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: // PSG
|
case 3: // PSG
|
||||||
|
@ -701,10 +534,10 @@ template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void Fetch8Bi
|
||||||
*data = (s32)chan->buf8[loc] << 8;
|
*data = (s32)chan->buf8[loc] << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<SPUInterpolationMode INTERPOLATE_MODE, bool ADPCM_CACHED> static FORCEINLINE void Fetch16BitData(const channel_struct * const chan, s32 *data)
|
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void Fetch16BitData(const channel_struct * const chan, s32 *data)
|
||||||
{
|
{
|
||||||
const s16* const buf16 = ADPCM_CACHED ? chan->cacheItem->decoded : chan->buf16;
|
const s16* const buf16 = chan->buf16;
|
||||||
const int shift = ADPCM_CACHED ? 3 : 1;
|
const int shift = 1;
|
||||||
if(INTERPOLATE_MODE != SPUInterpolation_None)
|
if(INTERPOLATE_MODE != SPUInterpolation_None)
|
||||||
{
|
{
|
||||||
u32 loc = sputrunc(chan->sampcnt);
|
u32 loc = sputrunc(chan->sampcnt);
|
||||||
|
@ -720,13 +553,8 @@ template<SPUInterpolationMode INTERPOLATE_MODE, bool ADPCM_CACHED> static FORCEI
|
||||||
*data = (s32)buf16[sputrunc(chan->sampcnt)];
|
*data = (s32)buf16[sputrunc(chan->sampcnt)];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<SPUInterpolationMode INTERPOLATE_MODE, bool ADPCM_CACHED> static FORCEINLINE void FetchADPCMData(channel_struct * const chan, s32 * const data)
|
template<SPUInterpolationMode INTERPOLATE_MODE> static FORCEINLINE void FetchADPCMData(channel_struct * const chan, s32 * const data)
|
||||||
{
|
{
|
||||||
if(ADPCM_CACHED)
|
|
||||||
{
|
|
||||||
return Fetch16BitData<INTERPOLATE_MODE,true>(chan, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No sense decoding, just return the last sample
|
// No sense decoding, just return the last sample
|
||||||
if (chan->lastsampcnt != sputrunc(chan->sampcnt)){
|
if (chan->lastsampcnt != sputrunc(chan->sampcnt)){
|
||||||
|
|
||||||
|
@ -741,6 +569,12 @@ template<SPUInterpolationMode INTERPOLATE_MODE, bool ADPCM_CACHED> static FORCEI
|
||||||
|
|
||||||
chan->pcm16b_last = chan->pcm16b;
|
chan->pcm16b_last = chan->pcm16b;
|
||||||
chan->pcm16b = MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF);
|
chan->pcm16b = MinMax(chan->pcm16b+diff, -0x8000, 0x7FFF);
|
||||||
|
|
||||||
|
if(i == (chan->loopstart<<3)) {
|
||||||
|
if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n");
|
||||||
|
chan->loop_pcm16b = chan->pcm16b;
|
||||||
|
chan->loop_index = chan->index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->lastsampcnt = sputrunc(chan->sampcnt);
|
chan->lastsampcnt = sputrunc(chan->sampcnt);
|
||||||
|
@ -851,12 +685,21 @@ static FORCEINLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan)
|
||||||
{
|
{
|
||||||
while (chan->sampcnt > chan->double_totlength_shifted)
|
while (chan->sampcnt > chan->double_totlength_shifted)
|
||||||
chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << 3);
|
chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << 3);
|
||||||
//chan->sampcnt = (double)(chan->loopstart << 3);
|
|
||||||
|
if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX)
|
||||||
|
{
|
||||||
chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]);
|
chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]);
|
||||||
chan->index = chan->buf8[2] & 0x7F;
|
chan->index = chan->buf8[2] & 0x7F;
|
||||||
chan->lastsampcnt = 7;
|
chan->lastsampcnt = 7;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
chan->pcm16b = chan->loop_pcm16b;
|
||||||
|
chan->index = chan->loop_index;
|
||||||
|
chan->lastsampcnt = (chan->loopstart << 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
chan->status = CHANSTAT_STOPPED;
|
chan->status = CHANSTAT_STOPPED;
|
||||||
if(SPU == SPU_core)
|
if(SPU == SPU_core)
|
||||||
|
@ -876,8 +719,8 @@ template<int CHANNELS> FORCEINLINE static void SPU_Mix(SPU_struct* SPU, channel_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS, bool CACHED>
|
template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS>
|
||||||
FORCEINLINE static void _____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan)
|
FORCEINLINE static void ____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan)
|
||||||
{
|
{
|
||||||
for (; SPU->bufpos < SPU->buflength; SPU->bufpos++)
|
for (; SPU->bufpos < SPU->buflength; SPU->bufpos++)
|
||||||
{
|
{
|
||||||
|
@ -887,8 +730,8 @@ template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS, bool C
|
||||||
switch(FORMAT)
|
switch(FORMAT)
|
||||||
{
|
{
|
||||||
case 0: Fetch8BitData<INTERPOLATE_MODE>(chan, &data); break;
|
case 0: Fetch8BitData<INTERPOLATE_MODE>(chan, &data); break;
|
||||||
case 1: Fetch16BitData<INTERPOLATE_MODE,false>(chan, &data); break;
|
case 1: Fetch16BitData<INTERPOLATE_MODE>(chan, &data); break;
|
||||||
case 2: FetchADPCMData<INTERPOLATE_MODE,CACHED>(chan, &data); break;
|
case 2: FetchADPCMData<INTERPOLATE_MODE>(chan, &data); break;
|
||||||
case 3: FetchPSGData(chan, &data); break;
|
case 3: FetchPSGData(chan, &data); break;
|
||||||
}
|
}
|
||||||
SPU_Mix<CHANNELS>(SPU, chan, data);
|
SPU_Mix<CHANNELS>(SPU, chan, data);
|
||||||
|
@ -902,14 +745,6 @@ template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS, bool C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, int CHANNELS>
|
|
||||||
FORCEINLINE static void ____SPU_ChanUpdate(SPU_struct* const SPU, channel_struct* const chan)
|
|
||||||
{
|
|
||||||
if(FORMAT == 2 && chan->cacheItem)
|
|
||||||
_____SPU_ChanUpdate<FORMAT,INTERPOLATE_MODE,CHANNELS,true>(SPU,chan);
|
|
||||||
else _____SPU_ChanUpdate<FORMAT,INTERPOLATE_MODE,CHANNELS,false>(SPU,chan);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE>
|
template<int FORMAT, SPUInterpolationMode INTERPOLATE_MODE>
|
||||||
FORCEINLINE static void ___SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan)
|
FORCEINLINE static void ___SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan)
|
||||||
{
|
{
|
||||||
|
@ -1238,7 +1073,7 @@ void WAV_WavSoundUpdate(void* soundData, int numSamples)
|
||||||
void spu_savestate(EMUFILE* os)
|
void spu_savestate(EMUFILE* os)
|
||||||
{
|
{
|
||||||
//version
|
//version
|
||||||
write32le(2,os);
|
write32le(3,os);
|
||||||
|
|
||||||
SPU_struct *spu = SPU_core;
|
SPU_struct *spu = SPU_core;
|
||||||
|
|
||||||
|
@ -1297,7 +1132,7 @@ bool spu_loadstate(EMUFILE* is, int size)
|
||||||
read32le(&chan.length,is);
|
read32le(&chan.length,is);
|
||||||
chan.totlength = chan.length + chan.loopstart;
|
chan.totlength = chan.length + chan.loopstart;
|
||||||
chan.double_totlength_shifted = (double)(chan.totlength << format_shift[chan.format]);
|
chan.double_totlength_shifted = (double)(chan.totlength << format_shift[chan.format]);
|
||||||
if(version != 1)
|
if(version >= 2)
|
||||||
{
|
{
|
||||||
read64le(&temp64,is); chan.sampcnt = u64_to_double(temp64);
|
read64le(&temp64,is); chan.sampcnt = u64_to_double(temp64);
|
||||||
read64le(&temp64,is); chan.sampinc = u64_to_double(temp64);
|
read64le(&temp64,is); chan.sampinc = u64_to_double(temp64);
|
||||||
|
@ -1314,31 +1149,20 @@ bool spu_loadstate(EMUFILE* is, int size)
|
||||||
read16le(&chan.x,is);
|
read16le(&chan.x,is);
|
||||||
read16le(&chan.psgnoise_last,is);
|
read16le(&chan.psgnoise_last,is);
|
||||||
|
|
||||||
|
//hopefully trigger a recovery of the adpcm looping system
|
||||||
|
chan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX;
|
||||||
|
|
||||||
//fixup the pointers which we had are supposed to keep cached
|
//fixup the pointers which we had are supposed to keep cached
|
||||||
chan.buf8 = (s8*)&MMU.MMU_MEM[1][(chan.addr>>20)&0xFF][(chan.addr & MMU.MMU_MASK[1][(chan.addr >> 20) & 0xFF])];
|
chan.buf8 = (s8*)&MMU.MMU_MEM[1][(chan.addr>>20)&0xFF][(chan.addr & MMU.MMU_MASK[1][(chan.addr >> 20) & 0xFF])];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version==2) {
|
if(version>=2) {
|
||||||
read64le(&temp64,is); samples = u64_to_double(temp64);
|
read64le(&temp64,is); samples = u64_to_double(temp64);
|
||||||
}
|
}
|
||||||
|
|
||||||
//copy the core spu (the more accurate) to the user spu
|
//copy the core spu (the more accurate) to the user spu
|
||||||
if(SPU_user) {
|
if(SPU_user) {
|
||||||
for(int i=0;i<16;i++)
|
|
||||||
{
|
|
||||||
channel_struct &chan = SPU_user->channels[i];
|
|
||||||
if(chan.cacheItem) chan.cacheItem->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(SPU_user->channels,SPU_core->channels,sizeof(SPU_core->channels));
|
memcpy(SPU_user->channels,SPU_core->channels,sizeof(SPU_core->channels));
|
||||||
|
|
||||||
if(CommonSettings.spuAdpcmCache)
|
|
||||||
for(int i=0;i<16;i++)
|
|
||||||
{
|
|
||||||
channel_struct &chan = SPU_user->channels[i];
|
|
||||||
if(chan.format == 2)
|
|
||||||
chan.cacheItem = adpcmCache.scan(&chan);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -68,12 +68,9 @@ extern SoundInterface_struct SNDDummy;
|
||||||
extern SoundInterface_struct SNDFile;
|
extern SoundInterface_struct SNDFile;
|
||||||
extern int SPU_currentCoreNum;
|
extern int SPU_currentCoreNum;
|
||||||
|
|
||||||
class ADPCMCacheItem;
|
|
||||||
|
|
||||||
struct channel_struct
|
struct channel_struct
|
||||||
{
|
{
|
||||||
channel_struct()
|
channel_struct()
|
||||||
: cacheItem(NULL)
|
|
||||||
{}
|
{}
|
||||||
u32 num;
|
u32 num;
|
||||||
u8 vol;
|
u8 vol;
|
||||||
|
@ -99,10 +96,11 @@ struct channel_struct
|
||||||
// ADPCM specific
|
// ADPCM specific
|
||||||
u32 lastsampcnt;
|
u32 lastsampcnt;
|
||||||
s16 pcm16b, pcm16b_last;
|
s16 pcm16b, pcm16b_last;
|
||||||
|
s16 loop_pcm16b;
|
||||||
int index;
|
int index;
|
||||||
|
int loop_index;
|
||||||
u16 x;
|
u16 x;
|
||||||
s16 psgnoise_last;
|
s16 psgnoise_last;
|
||||||
ADPCMCacheItem *cacheItem;
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
class SPU_struct
|
class SPU_struct
|
||||||
|
|
|
@ -2151,7 +2151,6 @@ int _main()
|
||||||
sndcoretype = GetPrivateProfileInt("Sound","SoundCore2", SNDCORE_DIRECTX, IniName);
|
sndcoretype = GetPrivateProfileInt("Sound","SoundCore2", SNDCORE_DIRECTX, IniName);
|
||||||
sndbuffersize = GetPrivateProfileInt("Sound","SoundBufferSize", 735 * 4, IniName);
|
sndbuffersize = GetPrivateProfileInt("Sound","SoundBufferSize", 735 * 4, IniName);
|
||||||
CommonSettings.spuInterpolationMode = (SPUInterpolationMode)GetPrivateProfileInt("Sound","SPUInterpolation", 1, IniName);
|
CommonSettings.spuInterpolationMode = (SPUInterpolationMode)GetPrivateProfileInt("Sound","SPUInterpolation", 1, IniName);
|
||||||
CommonSettings.spuAdpcmCache = GetPrivateProfileInt("Sound","SPUAdpcmCache",0,IniName)!=0;
|
|
||||||
|
|
||||||
EnterCriticalSection(&win_execute_sync);
|
EnterCriticalSection(&win_execute_sync);
|
||||||
int spu_ret = SPU_ChangeSoundCore(sndcoretype, sndbuffersize);
|
int spu_ret = SPU_ChangeSoundCore(sndcoretype, sndbuffersize);
|
||||||
|
@ -4816,9 +4815,6 @@ LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARA
|
||||||
SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_ADDSTRING, 0, (LPARAM)"Cosine (slowest, sounds best)");
|
SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_ADDSTRING, 0, (LPARAM)"Cosine (slowest, sounds best)");
|
||||||
SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_SETCURSEL, (int)CommonSettings.spuInterpolationMode, 0);
|
SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_SETCURSEL, (int)CommonSettings.spuInterpolationMode, 0);
|
||||||
|
|
||||||
//setup cache setting
|
|
||||||
CheckDlgButton(hDlg, IDC_SPU_CACHE, CommonSettings.spuAdpcmCache?BST_CHECKED:BST_UNCHECKED );
|
|
||||||
|
|
||||||
// Setup Sound Buffer Size Edit Text
|
// Setup Sound Buffer Size Edit Text
|
||||||
sprintf(tempstr, "%d", sndbuffersize);
|
sprintf(tempstr, "%d", sndbuffersize);
|
||||||
SetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr);
|
SetDlgItemText(hDlg, IDC_SOUNDBUFFERET, tempstr);
|
||||||
|
@ -4880,10 +4876,6 @@ LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARA
|
||||||
CommonSettings.spuInterpolationMode = (SPUInterpolationMode)SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_GETCURSEL, 0, 0);
|
CommonSettings.spuInterpolationMode = (SPUInterpolationMode)SendDlgItemMessage(hDlg, IDC_SPU_INTERPOLATION_CB, CB_GETCURSEL, 0, 0);
|
||||||
WritePrivateProfileInt("Sound","SPUInterpolation",(int)CommonSettings.spuInterpolationMode, IniName);
|
WritePrivateProfileInt("Sound","SPUInterpolation",(int)CommonSettings.spuInterpolationMode, IniName);
|
||||||
|
|
||||||
//write cache setting
|
|
||||||
CommonSettings.spuAdpcmCache = IsDlgButtonChecked(hDlg, IDC_SPU_CACHE) != 0;
|
|
||||||
WritePrivateProfileInt("Sound","SPUAdpcmCache",CommonSettings.spuAdpcmCache?1:0, IniName);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue