Lynx: direct stream mode

This commit is contained in:
tildearrow 2024-10-17 15:51:04 -05:00
parent 3c892ada2a
commit 5eae36f092
2 changed files with 60 additions and 23 deletions

View file

@ -22,7 +22,7 @@
#include "../bsr.h"
#include <math.h>
#define rWrite(a,v) {if (!skipRegisterWrites) {mikey->write(a,v); if (dumpWrites) {addWrite(a,v);}}}
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}}
#define WRITE_VOLUME(ch,v) rWrite(0x20+(ch<<3),(v))
#define WRITE_FEEDBACK(ch,v) rWrite(0x21+(ch<<3),(v))
@ -123,40 +123,64 @@ const char** DivPlatformLynx::getRegisterSheet() {
return regCheatSheetLynx;
}
void DivPlatformLynx::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
for (int i=0; i<4; i++) {
if (chan[i].pcm && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
chan[i].sampleAccum-=chan[i].sampleFreq;
if (chan[i].sampleAccum<0) {
chan[i].sampleAccum+=rate;
DivSample* s=parent->getSample(chan[i].sample);
if (s!=NULL) {
if (isMuted[i]) {
void DivPlatformLynx::processDAC(int sRate) {
for (int i=0; i<4; i++) {
if (chan[i].pcm && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
chan[i].sampleAccum-=chan[i].sampleFreq;
while (chan[i].sampleAccum<0) {
chan[i].sampleAccum+=sRate;
DivSample* s=parent->getSample(chan[i].sample);
if (s!=NULL) {
if (isMuted[i]) {
WRITE_OUTPUT(i,0);
} else {
if (chan[i].samplePos<0 || chan[i].samplePos>=(int)s->samples) {
WRITE_OUTPUT(i,0);
} else {
if (chan[i].samplePos<0 || chan[i].samplePos>=(int)s->samples) {
WRITE_OUTPUT(i,0);
} else {
WRITE_OUTPUT(i,CLAMP((s->data8[chan[i].samplePos]*chan[i].outVol)>>7,-128,127));
}
WRITE_OUTPUT(i,CLAMP((s->data8[chan[i].samplePos]*chan[i].outVol)>>7,-128,127));
}
chan[i].samplePos++;
}
chan[i].samplePos++;
if (s->isLoopable() && chan[i].samplePos>=s->loopEnd) {
chan[i].samplePos=s->loopStart;
} else if (chan[i].samplePos>=(int)s->samples) {
chan[i].sample=-1;
}
if (s->isLoopable() && chan[i].samplePos>=s->loopEnd) {
chan[i].samplePos=s->loopStart;
} else if (chan[i].samplePos>=(int)s->samples) {
chan[i].sample=-1;
}
}
}
}
}
}
void DivPlatformLynx::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
processDAC(rate);
while (!writes.empty()) {
QueuedWrite& w=writes.front();
mikey->write(w.addr,w.val);
writes.pop_front();
}
mikey->sampleAudio(buf[0]+h,buf[1]+h,1,oscBuf);
}
}
void DivPlatformLynx::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
writes.clear();
for (size_t i=0; i<len; i++) {
processDAC(sRate);
while (!writes.empty()) {
QueuedWrite& w=writes.front();
stream.push_back(DivDelayedWrite(i,w.addr,w.val));
writes.pop_front();
}
}
regWrites.clear();
}
void DivPlatformLynx::tick(bool sysTick) {
for (int i=0; i<4; i++) {
chan[i].std.next();
@ -308,7 +332,9 @@ int DivPlatformLynx::dispatch(DivCommand c) {
} else {
chan[c.chan].samplePos=0;
}
if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].sample);
if (dumpWrites) {
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].sample);
}
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
@ -499,6 +525,7 @@ void DivPlatformLynx::reset() {
chan[i]=DivPlatformLynx::Channel();
chan[i].std.setEngine(parent);
}
writes.clear();
if (dumpWrites) {
addWrite(0xffffffff,0);
}

View file

@ -68,10 +68,20 @@ class DivPlatformLynx: public DivDispatch {
bool isMuted[4];
bool tuned;
std::unique_ptr<Lynx::Mikey> mikey;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(9) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
FixedQueue<QueuedWrite,512> writes;
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
void processDAC(int sRate);
public:
void acquire(short** buf, size_t len);
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
int dispatch(DivCommand c);
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);