From a5f351c23228fe8189654a55a770b2cdc0e26e31 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 28 Aug 2023 20:31:22 -0500 Subject: [PATCH] C219: new sample format (work in progress) --- src/engine/bsr.h | 61 ++++++++++++++++++++++++++++++ src/engine/fileOpsSample.cpp | 1 + src/engine/platform/c140.cpp | 7 ++-- src/engine/platform/lynx.cpp | 43 +-------------------- src/engine/sample.cpp | 72 ++++++++++++++++++++++++++++++++++++ src/engine/sample.h | 7 +++- src/engine/sysDef.cpp | 2 +- src/gui/guiConst.cpp | 2 +- 8 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 src/engine/bsr.h diff --git a/src/engine/bsr.h b/src/engine/bsr.h new file mode 100644 index 00000000..ac3da44d --- /dev/null +++ b/src/engine/bsr.h @@ -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 + +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 + diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index 4d4b3a0e..0cc3d5b5 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -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: diff --git a/src/engine/platform/c140.cpp b/src/engine/platform/c140.cpp index f6853157..af8ff2f4 100644 --- a/src/engine/platform/c140.cpp +++ b/src/engine/platform/c140.cpp @@ -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=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 { diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index c8a34d46..f06de041 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -19,6 +19,7 @@ #include "lynx.h" #include "../engine.h" +#include "../bsr.h" #include #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 - -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 vhi?hi:v); diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index c2ff85a6..b3b9345a 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -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>19)^0xff; } } + if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_C219)) { // C219 + if (!initInternal(DIV_SAMPLE_DEPTH_C219,samples)) return; + for (unsigned int i=0; i0) { + 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; } diff --git a/src/engine/sample.h b/src/engine/sample.h index bbf90d4f..cf2f9ef0 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -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