A Y P C M

This commit is contained in:
tildearrow 2022-09-23 20:15:20 -05:00
parent e82374fcde
commit b72b5bf0e6
4 changed files with 133 additions and 57 deletions

View file

@ -81,16 +81,39 @@ const char** DivPlatformAY8910::getRegisterSheet() {
return intellivision?regCheatSheetAY8914:regCheatSheetAY; return intellivision?regCheatSheetAY8914:regCheatSheetAY;
} }
void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) { /* C program to generate this table:
if (ayBufLen<len) {
ayBufLen=len; #include <stdio.h>
for (int i=0; i<3; i++) { #include <math.h>
delete[] ayBuf[i];
ayBuf[i]=new short[ayBufLen]; int main(int argc, char** argv) {
} for (int i=0; i<256; i++) {
if ((i&15)==0) printf("\n ");
printf(" %d,",(int)round(pow((double)i/255.0,0.36)*15.0));
} }
// TODO: try to fit this into the actual loop }
// PCM part */
const unsigned char dacLogTableAY[256]={
0, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
};
void DivPlatformAY8910::runDAC() {
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) { if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) {
chan[i].dac.period+=chan[i].dac.rate; chan[i].dac.period+=chan[i].dac.rate;
@ -105,9 +128,8 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
end=true; end=true;
break; break;
} }
// Partially unsigned char dacData=dacLogTableAY[(unsigned char)s->data8[chan[i].dac.pos]^0x80];
unsigned char dacData=(((unsigned char)s->data8[chan[i].dac.pos]^0x80)>>4); chan[i].dac.out=MAX(0,dacData-(15-chan[i].outVol));
chan[i].dac.out=MAX(0,MIN(15,(dacData*chan[i].outVol)/15));
if (prevOut!=chan[i].dac.out) { if (prevOut!=chan[i].dac.out) {
prevOut=chan[i].dac.out; prevOut=chan[i].dac.out;
changed=true; changed=true;
@ -130,7 +152,9 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
} }
} }
} }
}
void DivPlatformAY8910::checkWrites() {
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
if (intellivision) { if (intellivision) {
@ -143,8 +167,22 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
regPool[w.addr&0x0f]=w.val; regPool[w.addr&0x0f]=w.val;
writes.pop(); writes.pop();
} }
}
void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) {
if (ayBufLen<len) {
ayBufLen=len;
for (int i=0; i<3; i++) {
delete[] ayBuf[i];
ayBuf[i]=new short[ayBufLen];
}
}
if (sunsoft) { if (sunsoft) {
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
runDAC();
checkWrites();
ay->sound_stream_update(ayBuf,1); ay->sound_stream_update(ayBuf,1);
bufL[i+start]=ayBuf[0][0]; bufL[i+start]=ayBuf[0][0];
bufR[i+start]=bufL[i+start]; bufR[i+start]=bufL[i+start];
@ -154,22 +192,22 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
oscBuf[2]->data[oscBuf[2]->needle++]=sunsoftVolTable[31-((ay->lastIndx>>10)&31)]>>3; oscBuf[2]->data[oscBuf[2]->needle++]=sunsoftVolTable[31-((ay->lastIndx>>10)&31)]>>3;
} }
} else { } else {
ay->sound_stream_update(ayBuf,len); for (size_t i=0; i<len; i++) {
if (stereo) { runDAC();
for (size_t i=0; i<len; i++) { checkWrites();
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8);
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i]; ay->sound_stream_update(ayBuf,1);
} if (stereo) {
} else { bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8);
for (size_t i=0; i<len; i++) { bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0];
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i]; } else {
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0];
bufR[i+start]=bufL[i+start]; bufR[i+start]=bufL[i+start];
} }
}
for (int ch=0; ch<3; ch++) { oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2;
for (size_t i=0; i<len; i++) { oscBuf[1]->data[oscBuf[1]->needle++]=ayBuf[1][0]<<2;
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2; oscBuf[2]->data[oscBuf[2]->needle++]=ayBuf[2][0]<<2;
}
} }
} }
} }
@ -291,7 +329,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
off=8363.0/(double)s->centerRate; off=8363.0/(double)s->centerRate;
} }
} }
chan[i].dac.rate=((double)chipClock*4096.0)/(double)(MAX(1,off*chan[i].freq)); chan[i].dac.rate=((double)rate*16.0)/(double)(MAX(1,off*chan[i].freq));
if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate);
} }
if (chan[i].freq>4095) chan[i].freq=4095; if (chan[i].freq>4095) chan[i].freq=4095;

View file

@ -145,6 +145,8 @@ class DivPlatformAY8910: public DivDispatch {
short* ayBuf[3]; short* ayBuf[3];
size_t ayBufLen; size_t ayBufLen;
void runDAC();
void checkWrites();
void updateOutSel(bool immediate=false); void updateOutSel(bool immediate=false);
friend void putDispatchChip(void*,int); friend void putDispatchChip(void*,int);

View file

@ -77,22 +77,45 @@ const char** DivPlatformAY8930::getRegisterSheet() {
return regCheatSheetAY8930; return regCheatSheetAY8930;
} }
void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) { /* C program to generate this table:
if (ayBufLen<len) {
ayBufLen=len; #include <stdio.h>
for (int i=0; i<3; i++) { #include <math.h>
delete[] ayBuf[i];
ayBuf[i]=new short[ayBufLen]; int main(int argc, char** argv) {
} for (int i=0; i<256; i++) {
if ((i&15)==0) printf("\n ");
printf(" %d,",(int)round(pow((double)i/255.0,0.3)*31.0));
} }
// TODO: try to fit this into the actual loop }
// PCM part */
for (int i=0; i<3; i++) {
const unsigned char dacLogTableAY8930[256]={
0, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13,
14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19,
19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
};
void DivPlatformAY8930::runDAC() {
for (int i=0; i<3; i++) {
if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) { if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) {
chan[i].dac.period+=chan[i].dac.rate; chan[i].dac.period+=chan[i].dac.rate;
bool end=false; bool end=false;
bool changed=false; bool changed=false;
int prev_out = chan[i].dac.out; int prevOut=chan[i].dac.out;
while (chan[i].dac.period>rate && !end) { while (chan[i].dac.period>rate && !end) {
DivSample* s=parent->getSample(chan[i].dac.sample); DivSample* s=parent->getSample(chan[i].dac.sample);
if (s->samples<=0) { if (s->samples<=0) {
@ -101,11 +124,10 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
end=true; end=true;
break; break;
} }
// Partially unsigned char dacData=dacLogTableAY8930[(unsigned char)s->data8[chan[i].dac.pos]^0x80];
unsigned char dacData=(((unsigned char)s->data8[chan[i].dac.pos]^0x80)>>3); chan[i].dac.out=MAX(0,dacData-(31-chan[i].outVol));
chan[i].dac.out=MAX(0,MIN(31,(dacData*chan[i].outVol)/31)); if (prevOut!=chan[i].dac.out) {
if (prev_out!=chan[i].dac.out) { prevOut=chan[i].dac.out;
prev_out=chan[i].dac.out;
changed=true; changed=true;
} }
chan[i].dac.pos++; chan[i].dac.pos++;
@ -126,7 +148,9 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
} }
} }
} }
}
void DivPlatformAY8930::checkWrites() {
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
ay->address_w(w.addr); ay->address_w(w.addr);
@ -138,23 +162,33 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
} }
writes.pop(); writes.pop();
} }
ay->sound_stream_update(ayBuf,len); }
if (stereo) {
for (size_t i=0; i<len; i++) { void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8); if (ayBufLen<len) {
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i]; ayBufLen=len;
} for (int i=0; i<3; i++) {
} else { delete[] ayBuf[i];
for (size_t i=0; i<len; i++) { ayBuf[i]=new short[ayBufLen];
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
bufR[i+start]=bufL[i+start];
} }
} }
for (int ch=0; ch<3; ch++) { for (size_t i=0; i<len; i++) {
for (size_t i=0; i<len; i++) { runDAC();
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2; checkWrites();
ay->sound_stream_update(ayBuf,1);
if (stereo) {
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8);
bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0];
} else {
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0];
bufR[i+start]=bufL[i+start];
} }
oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2;
oscBuf[1]->data[oscBuf[1]->needle++]=ayBuf[1][0]<<2;
oscBuf[2]->data[oscBuf[2]->needle++]=ayBuf[2][0]<<2;
} }
} }
@ -294,7 +328,7 @@ void DivPlatformAY8930::tick(bool sysTick) {
off=8363.0/(double)s->centerRate; off=8363.0/(double)s->centerRate;
} }
} }
chan[i].dac.rate=((double)chipClock*16384.0)/(double)(MAX(1,off*chan[i].freq)); chan[i].dac.rate=((double)chipClock*4.0)/(double)(MAX(1,off*chan[i].freq));
if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate); if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate);
} }
if (chan[i].freq>65535) chan[i].freq=65535; if (chan[i].freq>65535) chan[i].freq=65535;

View file

@ -148,6 +148,8 @@ class DivPlatformAY8930: public DivDispatch {
short* ayBuf[3]; short* ayBuf[3];
size_t ayBufLen; size_t ayBufLen;
void runDAC();
void checkWrites();
void updateOutSel(bool immediate=false); void updateOutSel(bool immediate=false);
void immWrite(unsigned char a, unsigned char v); void immWrite(unsigned char a, unsigned char v);