the PSG emulator already comes with heuristics... I stripped them off
for Furnace but now that we have acquireDirect() we can give it our
blip_buf and handle everything there
from 40-70% to 10% CPU usage on my phone, and highest quality!
TODO:
- PCM
- chan osc (should be very easy)
in your init or setFlags function,
instead of `oscBuf[i]->rate=rate;` do `oscBuf[i]->setRate(rate)`. this is necessary as it sets the appropriate needle multiplier for it to remain 65536Hz.
if your dispatch submits to the osc buffers at a slower rate (check out nes.cpp for an example), do not divide the rate anymore. it will work regardless.
this ends the notes (hopefully)
copy-paste from Discord
the new DivDispatch::acquireDirect() function allows optimizing emulation cores by only rendering what is needed (such as state changes in PC Speaker).
it gives DivDispatch direct access to blip_buf structures in order to allow that.
however, this requires changes to the chan osc buffer API since we're not gonna fill entire bufs anymore with acquireDirect
the accommodations consist of:
- new functions to fill a chan osc buffer
- the sample `-1` means "no changes" (don't worry, the new funcs will handle this for you), and
- all chan osc bufs now run at 65536Hz (as opposed to a rate defined by the dispatch). this also avoids buffer overruns and maybe glitches when audio buf size is too large.
if you've been working on a DivDispatch (in other words, a new chip or system), make sure to adapt your code to the new API. here are some guidelines:
1. in your acquire() function, call begin(len) of all DivDispatchOscBuffers before you run emu code and fill the out buffer.
2. replace `oscBuf[]->data[oscBuf[]->needle++]=val` with `oscBuf[]->putSample(h,val)`. `h` is the position of the buffer iterator (e.g. in the `for (size_t h=0; h<len; h++)` function). yes, this API is positional...
3. after emulation code runs and you fill the out buf (including all osc bufs), call end(len). this will advance the needle and all.
here's some sample code.
```
int DivPlatformDango::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
buf[0][h]=dango.tick();
for (int i=0; i<16; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=dango.getChOut(i);
}
}
}
```
```
int DivPlatformDango::acquire(short** buf, size_t len) {
for (int i=0; i<16; i++) {
oscBuf[i]->begin(len);
}
for (size_t h=0; h<len; h++) {
buf[0][h]=dango.tick();
for (int i=0; i<16; i++) {
oscBuf[i]->putSample(h,dango.getChOut(i));
}
}
for (int i=0; i<16; i++) {
oscBuf[i]->end(len);
}
}
```
thanks and sorry for any trouble this may cause
i kept running into the character limit