GA20: acquireDirect optimizations, part 1

buggy, slow and glitchy
output is good but chan osc is now broken

from 1.5 to 0.4 seconds
This commit is contained in:
tildearrow 2025-03-02 20:29:28 -05:00
parent 2c75555fae
commit 8f54445625
5 changed files with 52 additions and 77 deletions

View file

@ -52,39 +52,23 @@ inline void DivPlatformGA20::chWrite(unsigned char ch, unsigned int addr, unsign
} }
void DivPlatformGA20::acquire(short** buf, size_t len) { void DivPlatformGA20::acquire(short** buf, size_t len) {
if (ga20BufLen<len) { thread_local short ga20Buf[4];
ga20BufLen=len;
for (int i=0; i<4; i++) {
delete[] ga20Buf[i];
ga20Buf[i]=new short[ga20BufLen];
}
}
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
oscBuf[i]->begin(len); oscBuf[i]->begin(len);
} }
for (size_t h=0; h<len; h++) { for (size_t h=0; h<len; h++) {
if ((--delay)<=0) { if (!writes.empty()) {
delay=MAX(0,delay); QueuedWrite& w=writes.front();
if (!writes.empty()) { ga20.write(w.addr,w.val);
QueuedWrite& w=writes.front(); regPool[w.addr]=w.val;
ga20.write(w.addr,w.val); writes.pop();
regPool[w.addr]=w.val;
writes.pop();
delay=1;
}
} }
short *buffer[4]={ ga20.sound_stream_update(ga20Buf,1);
&ga20Buf[0][h], buf[0][h]=(signed int)(ga20Buf[0]+ga20Buf[1]+ga20Buf[2]+ga20Buf[3])>>2;
&ga20Buf[1][h],
&ga20Buf[2][h],
&ga20Buf[3][h]
};
ga20.sound_stream_update(buffer,1);
buf[0][h]=(signed int)(ga20Buf[0][h]+ga20Buf[1][h]+ga20Buf[2][h]+ga20Buf[3][h])>>2;
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
oscBuf[i]->putSample(h,ga20Buf[i][h]>>1); oscBuf[i]->putSample(h,ga20Buf[i]>>1);
} }
} }
@ -94,43 +78,42 @@ void DivPlatformGA20::acquire(short** buf, size_t len) {
} }
void DivPlatformGA20::acquireDirect(blip_buffer_t** bb, size_t off, size_t len) { void DivPlatformGA20::acquireDirect(blip_buffer_t** bb, size_t off, size_t len) {
if (ga20BufLen<len) { thread_local short ga20Buf[4];
ga20BufLen=len;
for (int i=0; i<4; i++) {
delete[] ga20Buf[i];
ga20Buf[i]=new short[ga20BufLen];
}
}
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
oscBuf[i]->begin(len); oscBuf[i]->begin(len);
} }
for (size_t h=off; h<off+len; h++) { for (size_t h=off; h<off+len; h++) {
if ((--delay)<=0) { size_t advance=0;
delay=MAX(0,delay); if (!writes.empty()) {
if (!writes.empty()) { QueuedWrite& w=writes.front();
QueuedWrite& w=writes.front(); ga20.write(w.addr,w.val);
ga20.write(w.addr,w.val); regPool[w.addr]=w.val;
regPool[w.addr]=w.val; writes.pop();
writes.pop(); } else {
delay=1; // heuristic
advance=off+len-h-1;
for (int i=0; i<4; i++) {
if (!ga20.m_channel[i].play) continue;
if (ga20.m_channel[i].hot) {
advance=0;
break;
}
const size_t newAdvance=ga20.m_channel[i].counter-ga20.m_channel[i].rate-1;
if (newAdvance<advance) advance=newAdvance;
} }
} }
short *buffer[4]={ ga20.sound_stream_update(ga20Buf,advance+1);
&ga20Buf[0][h], h+=advance;
&ga20Buf[1][h], const int out=(signed int)(ga20Buf[0]+ga20Buf[1]+ga20Buf[2]+ga20Buf[3])>>2;
&ga20Buf[2][h],
&ga20Buf[3][h]
};
ga20.sound_stream_update(buffer,1);
const int out=(signed int)(ga20Buf[0][h]+ga20Buf[1][h]+ga20Buf[2][h]+ga20Buf[3][h])>>2;
if (out!=oldOut) { if (out!=oldOut) {
blip_add_delta(bb[0],h,out-oldOut); blip_add_delta(bb[0],h,out-oldOut);
oldOut=out; oldOut=out;
} }
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
oscBuf[i]->putSample(h,ga20Buf[i][h]>>1); oscBuf[i]->putSample(h,ga20Buf[i]>>1);
} }
} }
@ -420,7 +403,6 @@ void DivPlatformGA20::reset() {
writes.clear(); writes.clear();
memset(regPool,0,32); memset(regPool,0,32);
ga20.device_reset(); ga20.device_reset();
delay=0;
oldOut=0; oldOut=0;
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
chan[i]=DivPlatformGA20::Channel(); chan[i]=DivPlatformGA20::Channel();
@ -561,7 +543,6 @@ int DivPlatformGA20::init(DivEngine* p, int channels, int sugRate, const DivConf
} }
sampleMem=new unsigned char[getSampleMemCapacity()]; sampleMem=new unsigned char[getSampleMemCapacity()];
sampleMemLen=0; sampleMemLen=0;
delay=0;
setFlags(flags); setFlags(flags);
ga20BufLen=65536; ga20BufLen=65536;
for (int i=0; i<4; i++) ga20Buf[i]=new short[ga20BufLen]; for (int i=0; i<4; i++) ga20Buf[i]=new short[ga20BufLen];

View file

@ -58,7 +58,6 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf {
unsigned int sampleOffGA20[256]; unsigned int sampleOffGA20[256];
bool sampleLoaded[256]; bool sampleLoaded[256];
int delay;
int oldOut; int oldOut;
short* ga20Buf[4]; short* ga20Buf[4];

View file

@ -89,35 +89,32 @@ void iremga20_device::device_reset()
// sound_stream_update - handle a stream update // sound_stream_update - handle a stream update
//------------------------------------------------- //-------------------------------------------------
void iremga20_device::sound_stream_update(short** outputs, int len) void iremga20_device::sound_stream_update(short* outputs, int len)
{ {
for (int i = 0; i < len; i++) for (int j = 0; j < 4; j++)
{ {
for (int j = 0; j < 4; j++) channel_def &ch = m_channel[j];
if (ch.play)
{ {
channel_def &ch = m_channel[j]; if (ch.sample == 0x00) // check for sample end marker
if (ch.play) ch.play = false;
else
{ {
if (ch.sample == 0x00) // check for sample end marker if (ch.hot) {
ch.play = false; ch.hot=false;
else ch.output = ch.mute ? 0 : (ch.sample - 0x80) * (s32)ch.volume;
}
ch.counter-=len;
if (ch.counter <= ch.rate)
{ {
if (ch.hot) { ch.pos++;
ch.hot=false; ch.counter = 0x100;
ch.output = ch.mute ? 0 : (ch.sample - 0x80) * (s32)ch.volume; ch.sample = m_intf.read_byte(ch.pos);
} ch.hot=true;
ch.counter--;
if (ch.counter <= ch.rate)
{
ch.pos++;
ch.counter = 0x100;
ch.sample = m_intf.read_byte(ch.pos);
ch.hot=true;
}
} }
} }
outputs[j][i] = ch.output;
} }
outputs[j] = ch.output;
} }
} }

View file

@ -6,7 +6,7 @@
DISCLAIMER DISCLAIMER
- This file is modified for suitable in furnace. - This file is modified for suitable in furnace.
- modified by cam900 - modified by cam900 and tildearrow
*********************************************************/ *********************************************************/
#ifndef MAME_SOUND_IREMGA20_H #ifndef MAME_SOUND_IREMGA20_H
@ -50,10 +50,9 @@ public:
void device_reset(); void device_reset();
// sound stream update overrides // sound stream update overrides
void sound_stream_update(short** outputs, int len); void sound_stream_update(short* outputs, int len);
private:
struct channel_def struct channel_def
{ {
channel_def() : channel_def() :

View file

@ -521,7 +521,6 @@ void putDispatchChip(void* data, int type) {
DivPlatformGA20* ch=(DivPlatformGA20*)data; DivPlatformGA20* ch=(DivPlatformGA20*)data;
ImGui::Text("> GA20"); ImGui::Text("> GA20");
COMMON_CHIP_DEBUG; COMMON_CHIP_DEBUG;
ImGui::Text("- delay: %.2x",ch->delay);
COMMON_CHIP_DEBUG_BOOL; COMMON_CHIP_DEBUG_BOOL;
break; break;
} }