Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure capture is always processed #590

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions desmume/src/SPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,22 @@ void SPU_struct::KeyOn(int channel)
thischan.status = CHANSTAT_STOPPED;
}
}

// If we are targetting data that is being played back by a
// channel, then make sure to delay it by at least 4 samples
// so that we don't get ourselves into buffer overrun.
// This (and the corresponding fixup in ProbeCapture()) are a
// nasty hack, but it's about all we can do, really :/
if(channel == 1 || channel == 3) {
const SPU_struct::REGS::CAP *cap = &regs.cap[(channel == 1) ? 0 : 1];
if(cap->active && (cap->runtime.maxdad - cap->len*4) == thischan.addr) {
// We are assuming that the channel and capture have the same length
int capLen_shifted = cap->len * (32 / (cap->bits8 ? 8 : 16));
int d = cap->runtime.sampcntInt - thischan.sampcntInt;
if(d < 0) d += capLen_shifted;
if(d < 4) thischan.sampcntInt -= 4 - d;
}
}
}

//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -767,6 +783,15 @@ void SPU_struct::ProbeCapture(int which)
cap.runtime.maxdad = cap.dad + len*4;
cap.runtime.sampcntFrac = cap.runtime.sampcntInt = 0;
cap.runtime.fifo.reset();

// Fix playback position for feedback capture - see notes in KeyProbe()
const channel_struct *ch = &channels[(which == 0) ? 1 : 3];
if(ch->status == CHANSTAT_PLAY && ch->addr == cap.dad) {
int capLen_shifted = cap.len * (32 / (cap.bits8 ? 8 : 16));
int d = cap.runtime.sampcntInt - ch->sampcntInt; // cap.runtime.sampcntInt - ch->sampcntInt, wrapped around
if(d < 0) d += capLen_shifted;
if(d < 4) cap.runtime.sampcntInt += 4 - d;
}
}

void SPU_struct::WriteByte(u32 addr, u8 val)
Expand Down Expand Up @@ -1465,22 +1490,15 @@ static void SPU_MixAudio_Advanced(bool actuallyMix, SPU_struct *SPU, int length)
//Instead, what we do here is delay the capture by 16 samples to create a similar effect.
//Subjectively, it seems to be working.

//Don't do anything until the fifo is filled, so as to delay it
if (cap.runtime.fifo.size < 16)
{
cap.runtime.fifo.enqueue(capout[capchan]);
continue;
}

//(actually capture sample from fifo instead of most recently generated)
u32 multiplier;
s32 sample = cap.runtime.fifo.dequeue();
//Fetch the FIFO-buffered sample and enqueue the most recently generated sample
s32 sample = (cap.runtime.fifo.size >= 16) ? cap.runtime.fifo.dequeue() : 0;
cap.runtime.fifo.enqueue(capout[capchan]);

//static FILE* fp = NULL;
//if(!fp) fp = fopen("d:\\capout.raw","wb");
//fwrite(&sample,2,1,fp);

u32 multiplier;
if (cap.bits8)
{
s8 sample8 = sample >> 8;
Expand Down