diff --git a/CMakeLists.txt b/CMakeLists.txt index fec191a6e..2aae13d9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -444,6 +444,7 @@ src/engine/platform/ym2608Interface.cpp src/engine/platform/ym2610Interface.cpp src/engine/blip_buf.c +src/engine/brrUtils.c src/engine/safeReader.cpp src/engine/safeWriter.cpp src/engine/config.cpp diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c new file mode 100644 index 000000000..9f0c20bc7 --- /dev/null +++ b/src/engine/brrUtils.c @@ -0,0 +1,82 @@ +/* brrUtils - BRR audio codec utilities + * Copyright (C) 2022 tildearrow + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "brrUtils.h" + +void brrEncode(short* buf, unsigned char* out, long len) { + if (len==0) return; + // TODO +} + +#define DO_ONE_SAMPLE \ + if (next&8) next|=0xfff8; \ +\ + next<<=(buf[0]>>4); /* range */ \ +\ + switch (control&0xc) { /* filter */ \ + case 0: \ + break; \ + case 4: \ + next+=(last1*15)/16; \ + break; \ + case 8: \ + next+=(last1*61)/32-(last2*15)/16; \ + break; \ + case 12: \ + next+=(last1*115)/64-(last2*13)/16; \ + break; \ + } \ +\ + if (next>32767) next=32767; \ + if (next<-32768) next=-32768; \ +\ + last2=last1; \ + last1=next; \ + *out=next; \ + out++; + +void brrDecode(unsigned char* buf, short* out, long len) { + if (len==0) return; + + int last1=0; + int last2=0; + int next=0; + + // don't read out of bounds + len-=8; + + for (long i=0; i>4; + DO_ONE_SAMPLE; + } + + // end bit + if (control&1) break; + buf+=9; + } +} \ No newline at end of file diff --git a/src/engine/brrUtils.h b/src/engine/brrUtils.h new file mode 100644 index 000000000..85192e45a --- /dev/null +++ b/src/engine/brrUtils.h @@ -0,0 +1,50 @@ +/* brrUtils - BRR audio codec utilities + * Copyright (C) 2022 tildearrow + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _BRR_UTILS_H +#define _BRR_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * read len samples from buf, encode in BRR and output to out. + * @param buf input data. + * @param out output buffer. shall be at least 9*(len/16) shorts in size. + * @param len input length (should be a multiple of 16. if it isn't, the output will be padded). + */ +void brrEncode(short* buf, unsigned char* out, long len); + +/** + * read len bytes from buf, decode BRR and output to out. + * @param buf input data. + * @param out output buffer. shall be at least 16*(len/9) shorts in size. + * @param len input length (shall be a multiple of 9). + */ +void brrDecode(unsigned char* buf, short* out, long len); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 2f3e972f9..ca722a419 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -24,7 +24,7 @@ #define CHIP_FREQBASE 131072 -#define rWrite(a,v) {dsp.write(a,v); regPool[(a)&0x7f]=v; } +#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } #define chWrite(c,a,v) {rWrite((a)+(c)*16,v)} #define sampleTableAddr(c) (sampleTableBase+(c)*4) #define waveTableAddr(c) (sampleTableBase+8*4+(c)*9*16) @@ -69,6 +69,14 @@ void DivPlatformSNES::acquire(short* bufL, short* bufR, size_t start, size_t len short out[2]; short chOut[16]; for (size_t h=start; h>8); rWrite(0x0c,127); // global volume left rWrite(0x1c,127); // global volume right diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 65c8a6656..5deb30c59 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -73,6 +73,13 @@ class DivPlatformSNES: public DivDispatch { signed char gblVolL, gblVolR; size_t sampleTableBase; + struct QueuedWrite { + unsigned char addr; + unsigned char val; + QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {} + }; + std::queue writes; + signed char sampleMem[65536]; size_t sampleMemLen; unsigned char regPool[0x80]; diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 5697176cd..cc24b9110 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -33,6 +33,7 @@ extern "C" { #include "../../extern/adpcm/ymb_codec.h" #include "../../extern/adpcm/ymz_codec.h" } +#include "brrUtils.h" DivSampleHistory::~DivSampleHistory() { if (data!=NULL) delete[] data; @@ -851,7 +852,7 @@ void DivSample::render() { } break; case DIV_SAMPLE_DEPTH_BRR: // BRR - // TODO! + brrDecode(dataBRR,data16,samples); break; case DIV_SAMPLE_DEPTH_VOX: // VOX oki_decode(dataVOX,data16,samples); @@ -908,7 +909,10 @@ void DivSample::render() { data8[i]=data16[i]>>8; } } - // TODO: BRR! + if (depth!=DIV_SAMPLE_DEPTH_VOX) { // BRR + if (!initInternal(DIV_SAMPLE_DEPTH_BRR,samples)) return; + brrEncode(data16,dataBRR,samples); + } if (depth!=DIV_SAMPLE_DEPTH_VOX) { // VOX if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return; oki_encode(data16,dataVOX,samples);