mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 14:33:01 +00:00
C140: help µ-law ISN'T WORKING
This commit is contained in:
parent
0311d712b1
commit
27e454e7aa
7 changed files with 66 additions and 11 deletions
|
@ -219,6 +219,7 @@ size | description
|
||||||
| - 0xcb: Casio PV-1000 - 3 channels
|
| - 0xcb: Casio PV-1000 - 3 channels
|
||||||
| - 0xcc: K053260 - 4 channels
|
| - 0xcc: K053260 - 4 channels
|
||||||
| - 0xcd: TED - 2 channels
|
| - 0xcd: TED - 2 channels
|
||||||
|
| - 0xce: Namco C140 - 24 channels
|
||||||
| - 0xde: YM2610B extended - 19 channels
|
| - 0xde: YM2610B extended - 19 channels
|
||||||
| - 0xe0: QSound - 19 channels
|
| - 0xe0: QSound - 19 channels
|
||||||
| - 0xfc: Pong - 1 channel
|
| - 0xfc: Pong - 1 channel
|
||||||
|
|
|
@ -143,7 +143,7 @@ void DivPlatformC140::tick(bool sysTick) {
|
||||||
chan[i].freq=(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE));
|
chan[i].freq=(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE));
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||||
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0);
|
ctrl|=(chan[i].active?0x80:0)|((s->isLoopable())?0x10:0)|((s->depth==DIV_SAMPLE_DEPTH_MULAW)?0x08:0);
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
unsigned int bank=0;
|
unsigned int bank=0;
|
||||||
unsigned int start=0;
|
unsigned int start=0;
|
||||||
|
@ -174,7 +174,6 @@ void DivPlatformC140::tick(bool sysTick) {
|
||||||
chan[i].volChangedL=true;
|
chan[i].volChangedL=true;
|
||||||
chan[i].volChangedR=true;
|
chan[i].volChangedR=true;
|
||||||
}
|
}
|
||||||
chan[i].keyOn=false;
|
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff) {
|
if (chan[i].keyOff) {
|
||||||
chan[i].keyOff=false;
|
chan[i].keyOff=false;
|
||||||
|
@ -184,7 +183,10 @@ void DivPlatformC140::tick(bool sysTick) {
|
||||||
rWrite(0x03+(i<<4),chan[i].freq&0xff);
|
rWrite(0x03+(i<<4),chan[i].freq&0xff);
|
||||||
chan[i].freqChanged=false;
|
chan[i].freqChanged=false;
|
||||||
}
|
}
|
||||||
rWrite(0x05+(i<<4),ctrl);
|
if (chan[i].keyOn) {
|
||||||
|
rWrite(0x05+(i<<4),ctrl);
|
||||||
|
chan[i].keyOn=false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,10 +439,20 @@ void DivPlatformC140::renderSamples(int sysID) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (memPos+length>=(getSampleMemCapacity())) {
|
if (memPos+length>=(getSampleMemCapacity())) {
|
||||||
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,(getSampleMemCapacity())-memPos);
|
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,(getSampleMemCapacity())-memPos);
|
||||||
|
}
|
||||||
logW("out of C140 memory for sample %d!",i);
|
logW("out of C140 memory for sample %d!",i);
|
||||||
} else {
|
} else {
|
||||||
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length);
|
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||||
|
for (unsigned int i=0; i<length; i++) {
|
||||||
|
sampleMem[i+(memPos/sizeof(short))]=(s->dataMuLaw[i]<<8)^0xff00;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(sampleMem+(memPos/sizeof(short)),s->data16,length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sampleOff[i]=memPos>>1;
|
sampleOff[i]=memPos>>1;
|
||||||
sampleLoaded[i]=true;
|
sampleLoaded[i]=true;
|
||||||
|
|
|
@ -269,6 +269,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
off=(offset+1)/2;
|
off=(offset+1)/2;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW:
|
||||||
|
off=offset;
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=offset*2;
|
off=offset*2;
|
||||||
break;
|
break;
|
||||||
|
@ -316,6 +319,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
||||||
off=(offset+1)/2;
|
off=(offset+1)/2;
|
||||||
len=(length+1)/2;
|
len=(length+1)/2;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW:
|
||||||
|
off=offset;
|
||||||
|
len=length;
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=offset*2;
|
off=offset*2;
|
||||||
len=length*2;
|
len=length*2;
|
||||||
|
@ -365,6 +372,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) {
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
off=lengthVOX;
|
off=lengthVOX;
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW:
|
||||||
|
off=lengthMuLaw;
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
off=length16;
|
off=length16;
|
||||||
break;
|
break;
|
||||||
|
@ -538,6 +548,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) {
|
||||||
dataVOX=new unsigned char[lengthVOX];
|
dataVOX=new unsigned char[lengthVOX];
|
||||||
memset(dataVOX,0,lengthVOX);
|
memset(dataVOX,0,lengthVOX);
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW: // 8-bit µ-law
|
||||||
|
if (dataMuLaw!=NULL) delete[] dataMuLaw;
|
||||||
|
lengthMuLaw=count;
|
||||||
|
dataMuLaw=new unsigned char[(count+4095)&(~0xfff)];
|
||||||
|
memset(dataMuLaw,0,(count+4095)&(~0xfff));
|
||||||
|
break;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT: // 16-bit
|
case DIV_SAMPLE_DEPTH_16BIT: // 16-bit
|
||||||
if (data16!=NULL) delete[] data16;
|
if (data16!=NULL) delete[] data16;
|
||||||
length16=count*2;
|
length16=count*2;
|
||||||
|
@ -1155,6 +1171,13 @@ void DivSample::render(unsigned int formatMask) {
|
||||||
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
case DIV_SAMPLE_DEPTH_VOX: // VOX
|
||||||
oki_decode(dataVOX,data16,samples);
|
oki_decode(dataVOX,data16,samples);
|
||||||
break;
|
break;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW: // 8-bit µ-law PCM
|
||||||
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
|
unsigned int s=(dataMuLaw[i]^0xff);
|
||||||
|
s=0x3f800000+(((s<<24)&0x80000000)|((s&0x7f)<<19));
|
||||||
|
data16[i]=(short)((*(float*)&s)*128.0f);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1233,6 +1256,16 @@ void DivSample::render(unsigned int formatMask) {
|
||||||
if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return;
|
if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return;
|
||||||
oki_encode(data16,dataVOX,samples);
|
oki_encode(data16,dataVOX,samples);
|
||||||
}
|
}
|
||||||
|
if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_MULAW)) { // µ-law
|
||||||
|
if (!initInternal(DIV_SAMPLE_DEPTH_MULAW,samples)) return;
|
||||||
|
for (unsigned int i=0; i<samples; i++) {
|
||||||
|
float s=(float)-data16[i];
|
||||||
|
s/=32768.0f;
|
||||||
|
unsigned int si=*(unsigned int*)&s;
|
||||||
|
si-=0x3f800000;
|
||||||
|
dataMuLaw[i]=(((si&0x80000000)>>24)|((si&0x03f80000)>>19))^0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivSample::getCurBuf() {
|
void* DivSample::getCurBuf() {
|
||||||
|
@ -1255,6 +1288,8 @@ void* DivSample::getCurBuf() {
|
||||||
return dataBRR;
|
return dataBRR;
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
return dataVOX;
|
return dataVOX;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW:
|
||||||
|
return dataMuLaw;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return data16;
|
return data16;
|
||||||
default:
|
default:
|
||||||
|
@ -1283,6 +1318,8 @@ unsigned int DivSample::getCurBufLen() {
|
||||||
return lengthBRR;
|
return lengthBRR;
|
||||||
case DIV_SAMPLE_DEPTH_VOX:
|
case DIV_SAMPLE_DEPTH_VOX:
|
||||||
return lengthVOX;
|
return lengthVOX;
|
||||||
|
case DIV_SAMPLE_DEPTH_MULAW:
|
||||||
|
return lengthMuLaw;
|
||||||
case DIV_SAMPLE_DEPTH_16BIT:
|
case DIV_SAMPLE_DEPTH_16BIT:
|
||||||
return length16;
|
return length16;
|
||||||
default:
|
default:
|
||||||
|
@ -1392,4 +1429,5 @@ DivSample::~DivSample() {
|
||||||
if (dataB) delete[] dataB;
|
if (dataB) delete[] dataB;
|
||||||
if (dataBRR) delete[] dataBRR;
|
if (dataBRR) delete[] dataBRR;
|
||||||
if (dataVOX) delete[] dataVOX;
|
if (dataVOX) delete[] dataVOX;
|
||||||
|
if (dataMuLaw) delete[] dataMuLaw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ enum DivSampleDepth: unsigned char {
|
||||||
DIV_SAMPLE_DEPTH_8BIT=8,
|
DIV_SAMPLE_DEPTH_8BIT=8,
|
||||||
DIV_SAMPLE_DEPTH_BRR=9,
|
DIV_SAMPLE_DEPTH_BRR=9,
|
||||||
DIV_SAMPLE_DEPTH_VOX=10,
|
DIV_SAMPLE_DEPTH_VOX=10,
|
||||||
|
DIV_SAMPLE_DEPTH_MULAW=11,
|
||||||
DIV_SAMPLE_DEPTH_16BIT=16,
|
DIV_SAMPLE_DEPTH_16BIT=16,
|
||||||
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
||||||
};
|
};
|
||||||
|
@ -108,6 +109,7 @@ struct DivSample {
|
||||||
// - 8: 8-bit PCM
|
// - 8: 8-bit PCM
|
||||||
// - 9: BRR (SNES)
|
// - 9: BRR (SNES)
|
||||||
// - 10: VOX ADPCM
|
// - 10: VOX ADPCM
|
||||||
|
// - 11: 8-bit µ-law PCM
|
||||||
// - 16: 16-bit PCM
|
// - 16: 16-bit PCM
|
||||||
DivSampleDepth depth;
|
DivSampleDepth depth;
|
||||||
bool loop, brrEmphasis, dither;
|
bool loop, brrEmphasis, dither;
|
||||||
|
@ -130,8 +132,9 @@ struct DivSample {
|
||||||
unsigned char* dataB; // 6
|
unsigned char* dataB; // 6
|
||||||
unsigned char* dataBRR; // 9
|
unsigned char* dataBRR; // 9
|
||||||
unsigned char* dataVOX; // 10
|
unsigned char* dataVOX; // 10
|
||||||
|
unsigned char* dataMuLaw; // 11
|
||||||
|
|
||||||
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX;
|
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX, lengthMuLaw;
|
||||||
|
|
||||||
unsigned int samples;
|
unsigned int samples;
|
||||||
|
|
||||||
|
@ -337,6 +340,7 @@ struct DivSample {
|
||||||
dataB(NULL),
|
dataB(NULL),
|
||||||
dataBRR(NULL),
|
dataBRR(NULL),
|
||||||
dataVOX(NULL),
|
dataVOX(NULL),
|
||||||
|
dataMuLaw(NULL),
|
||||||
length8(0),
|
length8(0),
|
||||||
length16(0),
|
length16(0),
|
||||||
length1(0),
|
length1(0),
|
||||||
|
@ -347,6 +351,7 @@ struct DivSample {
|
||||||
lengthB(0),
|
lengthB(0),
|
||||||
lengthBRR(0),
|
lengthBRR(0),
|
||||||
lengthVOX(0),
|
lengthVOX(0),
|
||||||
|
lengthMuLaw(0),
|
||||||
samples(0) {
|
samples(0) {
|
||||||
for (int i=0; i<DIV_MAX_CHIPS; i++) {
|
for (int i=0; i<DIV_MAX_CHIPS; i++) {
|
||||||
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
|
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
|
||||||
|
|
|
@ -1872,10 +1872,9 @@ void DivEngine::registerSystems() {
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Custom sample format
|
|
||||||
sysDefs[DIV_SYSTEM_C140]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_C140]=new DivSysDef(
|
||||||
"Namco C140", NULL, 0xfe/*Placeholder*/, 0, 24, false, true, 0x161, false, 1U<<DIV_SAMPLE_DEPTH_8BIT,
|
"Namco C140", NULL, 0xce, 0, 24, false, true, 0x161, false, (1U<<DIV_SAMPLE_DEPTH_MULAW)|(1U<<DIV_SAMPLE_DEPTH_8BIT),
|
||||||
"Namco's first PCM chip arrived from 1987.",
|
"Namco's first PCM chip from 1987.",
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24"},
|
||||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"},
|
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"},
|
||||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||||
|
|
|
@ -192,7 +192,7 @@ const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={
|
||||||
"8-bit PCM",
|
"8-bit PCM",
|
||||||
"BRR",
|
"BRR",
|
||||||
"VOX",
|
"VOX",
|
||||||
NULL,
|
"8-bit µ-law PCM",
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
|
@ -1608,7 +1608,7 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
}
|
}
|
||||||
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767);
|
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767);
|
||||||
if (posX>=0) {
|
if (posX>=0) {
|
||||||
statusBar2=fmt::sprintf("(%d, %d)",posX,posY);
|
statusBar2=fmt::sprintf("(%d, %d) $%.2x",posX,posY,((unsigned char*)sample->getCurBuf())[posX]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue