C219: new sample format (work in progress)
This commit is contained in:
parent
9cb239438e
commit
a5f351c232
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2023 tildearrow and contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
static inline int bsr(unsigned short v) {
|
||||
unsigned long idx;
|
||||
if (_BitScanReverse(&idx,(unsigned long)v)) {
|
||||
return idx;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined( __GNUC__ )
|
||||
|
||||
static inline int bsr(unsigned short v)
|
||||
{
|
||||
if (v) {
|
||||
return 32 - __builtin_clz(v);
|
||||
}
|
||||
else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int bsr(unsigned short v)
|
||||
{
|
||||
unsigned short mask = 0x8000;
|
||||
for (int i = 15; i >= 0; --i) {
|
||||
if (v&mask)
|
||||
return (int)i;
|
||||
mask>>=1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -395,6 +395,7 @@ DivSample* DivEngine::sampleFromFileRaw(const char* path, DivSampleDepth depth,
|
|||
break;
|
||||
case DIV_SAMPLE_DEPTH_8BIT:
|
||||
case DIV_SAMPLE_DEPTH_MULAW:
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
samples=lenDivided;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_BRR:
|
||||
|
|
|
@ -575,13 +575,12 @@ void DivPlatformC140::renderSamples(int sysID) {
|
|||
length=getSampleMemCapacity()-memPos;
|
||||
logW("out of C219 memory for sample %d!",i);
|
||||
}
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_MULAW) {
|
||||
if (s->depth==DIV_SAMPLE_DEPTH_C219) {
|
||||
for (unsigned int i=0; i<length; i++) {
|
||||
if (i>=s->lengthMuLaw) {
|
||||
if (i>=s->lengthC219) {
|
||||
sampleMem[i+memPos]=0;
|
||||
} else {
|
||||
unsigned char x=s->dataMuLaw[i]^0xff;
|
||||
sampleMem[i+memPos]=x;
|
||||
sampleMem[i+memPos]=s->dataC219[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "lynx.h"
|
||||
#include "../engine.h"
|
||||
#include "../bsr.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) {if (!skipRegisterWrites) {mikey->write(a,v); if (dumpWrites) {addWrite(a,v);}}}
|
||||
|
@ -36,48 +37,6 @@
|
|||
#define CHIP_DIVIDER 64
|
||||
#define CHIP_FREQBASE 16000000
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
static int bsr(uint16_t v) {
|
||||
unsigned long idx;
|
||||
if (_BitScanReverse(&idx,(unsigned long)v)) {
|
||||
return idx;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined( __GNUC__ )
|
||||
|
||||
static int bsr(uint16_t v)
|
||||
{
|
||||
if (v) {
|
||||
return 32 - __builtin_clz(v);
|
||||
}
|
||||
else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int bsr(uint16_t v)
|
||||
{
|
||||
uint16_t mask = 0x8000;
|
||||
for (int i = 15; i >= 0; --i) {
|
||||
if (v&mask)
|
||||
return (int)i;
|
||||
mask>>=1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int32_t clamp(int32_t v, int32_t lo, int32_t hi)
|
||||
{
|
||||
return v<lo?lo:(v>hi?hi:v);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "sfWrapper.h"
|
||||
#endif
|
||||
#include "filter.h"
|
||||
#include "bsr.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../../extern/adpcm/bs_codec.h"
|
||||
|
@ -272,6 +273,9 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
|||
case DIV_SAMPLE_DEPTH_MULAW:
|
||||
off=offset;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
off=offset;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_16BIT:
|
||||
off=offset*2;
|
||||
break;
|
||||
|
@ -323,6 +327,10 @@ int DivSample::getSampleOffset(int offset, int length, DivSampleDepth depth) {
|
|||
off=offset;
|
||||
len=length;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
off=offset;
|
||||
len=length;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_16BIT:
|
||||
off=offset*2;
|
||||
len=length*2;
|
||||
|
@ -375,6 +383,9 @@ int DivSample::getEndPosition(DivSampleDepth depth) {
|
|||
case DIV_SAMPLE_DEPTH_MULAW:
|
||||
off=lengthMuLaw;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
off=lengthC219;
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_16BIT:
|
||||
off=length16;
|
||||
break;
|
||||
|
@ -554,6 +565,12 @@ bool DivSample::initInternal(DivSampleDepth d, int count) {
|
|||
dataMuLaw=new unsigned char[(count+4095)&(~0xfff)];
|
||||
memset(dataMuLaw,0,(count+4095)&(~0xfff));
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_C219: // 8-bit C219 "μ-law"
|
||||
if (dataC219!=NULL) delete[] dataC219;
|
||||
lengthC219=count;
|
||||
dataC219=new unsigned char[(count+4095)&(~0xfff)];
|
||||
memset(dataC219,0,(count+4095)&(~0xfff));
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_16BIT: // 16-bit
|
||||
if (data16!=NULL) delete[] data16;
|
||||
length16=count*2;
|
||||
|
@ -1133,6 +1150,33 @@ union IntFloat {
|
|||
float f;
|
||||
};
|
||||
|
||||
const short c219Table[256]={
|
||||
0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 480,
|
||||
512, 576, 640, 704, 768, 832, 896, 960, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920,
|
||||
2048, 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072, 3200, 3328, 3456, 3584, 3712, 3840, 3968,
|
||||
4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680, 7936,
|
||||
8192, 8448, 8704, 8960, 9216, 9472, 9728, 9984, 10240, 10496, 10752, 11008, 11264, 11520, 11776, 12032,
|
||||
12288, 12544, 12800, 13056, 13312, 13568, 13824, 14080, 14336, 14592, 14848, 15104, 15360, 15616, 15872, 16128,
|
||||
16384, 16640, 16896, 17152, 17408, 17920, 18432, 18944, 19456, 19968, 20480, 20992, 21504, 22016, 22528, 23040,
|
||||
23552, 24064, 24576, 25088, 25600, 26112, 26624, 27136, 27648, 28160, 28672, 29184, 29696, 30208, 30720, 31232,
|
||||
-32, -64, -96, -128, -160, -192, -224, -256, -288, -320, -352, -384, -416, -448, -480, -512,
|
||||
-544, -608, -672, -736, -800, -864, -928, -992, -1056, -1184, -1312, -1440, -1568, -1696, -1824, -1952,
|
||||
-2080, -2208, -2336, -2464, -2592, -2720, -2848, -2976, -3104, -3232, -3360, -3488, -3616, -3744, -3872, -4000,
|
||||
-4128, -4384, -4640, -4896, -5152, -5408, -5664, -5920, -6176, -6432, -6688, -6944, -7200, -7456, -7712, -7968,
|
||||
-8224, -8480, -8736, -8992, -9248, -9504, -9760, -10016, -10272, -10528, -10784, -11040, -11296, -11552, -11808, -12064,
|
||||
-12320, -12576, -12832, -13088, -13344, -13600, -13856, -14112, -14368, -14624, -14880, -15136, -15392, -15648, -15904, -16160,
|
||||
-16416, -16672, -16928, -17184, -17440, -17952, -18464, -18976, -19488, -20000, -20512, -21024, -21536, -22048, -22560, -23072,
|
||||
-23584, -24096, -24608, -25120, -25632, -26144, -26656, -27168, -27680, -28192, -28704, -29216, -29728, -30240, -30752, -31264
|
||||
};
|
||||
|
||||
unsigned char c219HighBitPos[16]={
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 24, 24, 48, 48, 48, 48
|
||||
};
|
||||
|
||||
unsigned char c219ShiftToVal[16]={
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 8, 8, 8, 8
|
||||
};
|
||||
|
||||
void DivSample::render(unsigned int formatMask) {
|
||||
// step 1: convert to 16-bit if needed
|
||||
if (depth!=DIV_SAMPLE_DEPTH_16BIT) {
|
||||
|
@ -1184,6 +1228,12 @@ void DivSample::render(unsigned int formatMask) {
|
|||
data16[i]=(short)(s.f*128.0f);
|
||||
}
|
||||
break;
|
||||
case DIV_SAMPLE_DEPTH_C219: // 8-bit C219 "μ-law" PCM
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
data16[i]=c219Table[dataC219[i]&0x7f];
|
||||
if (dataC219[i]&0x80) data16[i]=-data16[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -1273,6 +1323,23 @@ void DivSample::render(unsigned int formatMask) {
|
|||
dataMuLaw[i]=(((data16[i]<0)?0x80:0)|(s.i&0x03f80000)>>19)^0xff;
|
||||
}
|
||||
}
|
||||
if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_C219)) { // C219
|
||||
if (!initInternal(DIV_SAMPLE_DEPTH_C219,samples)) return;
|
||||
for (unsigned int i=0; i<samples; i++) {
|
||||
short s=data16[i];
|
||||
unsigned char x=0;
|
||||
if (s>0) {
|
||||
if (s>17152) { // 100+
|
||||
x=((s-17152)>>9)+100;
|
||||
} else {
|
||||
int b=bsr(s)&15;
|
||||
x=(s>>c219ShiftToVal[b])+c219HighBitPos[b];
|
||||
}
|
||||
} else if (s<0) {
|
||||
}
|
||||
dataC219[i]=x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* DivSample::getCurBuf() {
|
||||
|
@ -1297,6 +1364,8 @@ void* DivSample::getCurBuf() {
|
|||
return dataVOX;
|
||||
case DIV_SAMPLE_DEPTH_MULAW:
|
||||
return dataMuLaw;
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
return dataC219;
|
||||
case DIV_SAMPLE_DEPTH_16BIT:
|
||||
return data16;
|
||||
default:
|
||||
|
@ -1327,6 +1396,8 @@ unsigned int DivSample::getCurBufLen() {
|
|||
return lengthVOX;
|
||||
case DIV_SAMPLE_DEPTH_MULAW:
|
||||
return lengthMuLaw;
|
||||
case DIV_SAMPLE_DEPTH_C219:
|
||||
return lengthC219;
|
||||
case DIV_SAMPLE_DEPTH_16BIT:
|
||||
return length16;
|
||||
default:
|
||||
|
@ -1437,4 +1508,5 @@ DivSample::~DivSample() {
|
|||
if (dataBRR) delete[] dataBRR;
|
||||
if (dataVOX) delete[] dataVOX;
|
||||
if (dataMuLaw) delete[] dataMuLaw;
|
||||
if (dataC219) delete[] dataC219;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ enum DivSampleDepth: unsigned char {
|
|||
DIV_SAMPLE_DEPTH_BRR=9,
|
||||
DIV_SAMPLE_DEPTH_VOX=10,
|
||||
DIV_SAMPLE_DEPTH_MULAW=11,
|
||||
DIV_SAMPLE_DEPTH_C219=12,
|
||||
DIV_SAMPLE_DEPTH_16BIT=16,
|
||||
DIV_SAMPLE_DEPTH_MAX // boundary for sample depth
|
||||
};
|
||||
|
@ -110,6 +111,7 @@ struct DivSample {
|
|||
// - 9: BRR (SNES)
|
||||
// - 10: VOX ADPCM
|
||||
// - 11: 8-bit µ-law PCM
|
||||
// - 12: C219 "µ-law" PCM
|
||||
// - 16: 16-bit PCM
|
||||
DivSampleDepth depth;
|
||||
bool loop, brrEmphasis, dither;
|
||||
|
@ -133,8 +135,9 @@ struct DivSample {
|
|||
unsigned char* dataBRR; // 9
|
||||
unsigned char* dataVOX; // 10
|
||||
unsigned char* dataMuLaw; // 11
|
||||
unsigned char* dataC219; // 12
|
||||
|
||||
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX, lengthMuLaw;
|
||||
unsigned int length8, length16, length1, lengthDPCM, lengthZ, lengthQSoundA, lengthA, lengthB, lengthBRR, lengthVOX, lengthMuLaw, lengthC219;
|
||||
|
||||
unsigned int samples;
|
||||
|
||||
|
@ -341,6 +344,7 @@ struct DivSample {
|
|||
dataBRR(NULL),
|
||||
dataVOX(NULL),
|
||||
dataMuLaw(NULL),
|
||||
dataC219(NULL),
|
||||
length8(0),
|
||||
length16(0),
|
||||
length1(0),
|
||||
|
@ -352,6 +356,7 @@ struct DivSample {
|
|||
lengthBRR(0),
|
||||
lengthVOX(0),
|
||||
lengthMuLaw(0),
|
||||
lengthC219(0),
|
||||
samples(0) {
|
||||
for (int i=0; i<DIV_MAX_CHIPS; i++) {
|
||||
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
|
||||
|
|
|
@ -1888,7 +1888,7 @@ void DivEngine::registerSystems() {
|
|||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_C219]=new DivSysDef(
|
||||
"Namco C219", NULL, 0xcf, 0, 16, false, true, 0x161, false, (1U<<DIV_SAMPLE_DEPTH_MULAW)|(1U<<DIV_SAMPLE_DEPTH_8BIT),
|
||||
"Namco C219", NULL, 0xcf, 0, 16, false, true, 0x161, false, (1U<<DIV_SAMPLE_DEPTH_C219)|(1U<<DIV_SAMPLE_DEPTH_8BIT),
|
||||
"Namco's PCM chip used in their NA1/2 hardware.",
|
||||
{"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"},
|
||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"},
|
||||
|
|
|
@ -197,7 +197,7 @@ const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={
|
|||
"BRR",
|
||||
"VOX",
|
||||
"8-bit µ-law PCM",
|
||||
NULL,
|
||||
"C219 PCM",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
Loading…
Reference in New Issue