prepare BRR encoding/decoding

This commit is contained in:
tildearrow 2022-09-24 04:27:53 -05:00
parent b7e618e91d
commit 8eaddcf070
6 changed files with 158 additions and 4 deletions

View file

@ -444,6 +444,7 @@ src/engine/platform/ym2608Interface.cpp
src/engine/platform/ym2610Interface.cpp src/engine/platform/ym2610Interface.cpp
src/engine/blip_buf.c src/engine/blip_buf.c
src/engine/brrUtils.c
src/engine/safeReader.cpp src/engine/safeReader.cpp
src/engine/safeWriter.cpp src/engine/safeWriter.cpp
src/engine/config.cpp src/engine/config.cpp

82
src/engine/brrUtils.c Normal file
View file

@ -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<len; i+=9) {
unsigned char control=buf[0];
for (unsigned char j=1; j<9; j++) {
next=buf[j]&15;
DO_ONE_SAMPLE;
next=buf[j]>>4;
DO_ONE_SAMPLE;
}
// end bit
if (control&1) break;
buf+=9;
}
}

50
src/engine/brrUtils.h Normal file
View file

@ -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

View file

@ -24,7 +24,7 @@
#define CHIP_FREQBASE 131072 #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 chWrite(c,a,v) {rWrite((a)+(c)*16,v)}
#define sampleTableAddr(c) (sampleTableBase+(c)*4) #define sampleTableAddr(c) (sampleTableBase+(c)*4)
#define waveTableAddr(c) (sampleTableBase+8*4+(c)*9*16) #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 out[2];
short chOut[16]; short chOut[16];
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
// TODO: delay
if (!writes.empty()) {
QueuedWrite w=writes.front();
dsp.write(w.addr,w.val);
regPool[w.addr&0x7f]=w.val;
writes.pop();
}
dsp.set_output(out,1); dsp.set_output(out,1);
dsp.run(32); dsp.run(32);
dsp.get_voice_outputs(chOut); dsp.get_voice_outputs(chOut);
@ -407,7 +415,9 @@ void DivPlatformSNES::reset() {
dsp.set_output(NULL,0); dsp.set_output(NULL,0);
memset(regPool,0,128); memset(regPool,0,128);
// TODO more initial values // TODO more initial values
sampleTableBase=0x100; // hack: this can't be 0 or channel 1 won't play?? // this can't be 0 or channel 1 won't play
// this can't be 0x100 either as that's used by SPC700 page 1 and the stack
sampleTableBase=0x200;
rWrite(0x5d,sampleTableBase>>8); rWrite(0x5d,sampleTableBase>>8);
rWrite(0x0c,127); // global volume left rWrite(0x0c,127); // global volume left
rWrite(0x1c,127); // global volume right rWrite(0x1c,127); // global volume right

View file

@ -73,6 +73,13 @@ class DivPlatformSNES: public DivDispatch {
signed char gblVolL, gblVolR; signed char gblVolL, gblVolR;
size_t sampleTableBase; size_t sampleTableBase;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
signed char sampleMem[65536]; signed char sampleMem[65536];
size_t sampleMemLen; size_t sampleMemLen;
unsigned char regPool[0x80]; unsigned char regPool[0x80];

View file

@ -33,6 +33,7 @@ extern "C" {
#include "../../extern/adpcm/ymb_codec.h" #include "../../extern/adpcm/ymb_codec.h"
#include "../../extern/adpcm/ymz_codec.h" #include "../../extern/adpcm/ymz_codec.h"
} }
#include "brrUtils.h"
DivSampleHistory::~DivSampleHistory() { DivSampleHistory::~DivSampleHistory() {
if (data!=NULL) delete[] data; if (data!=NULL) delete[] data;
@ -851,7 +852,7 @@ void DivSample::render() {
} }
break; break;
case DIV_SAMPLE_DEPTH_BRR: // BRR case DIV_SAMPLE_DEPTH_BRR: // BRR
// TODO! brrDecode(dataBRR,data16,samples);
break; break;
case DIV_SAMPLE_DEPTH_VOX: // VOX case DIV_SAMPLE_DEPTH_VOX: // VOX
oki_decode(dataVOX,data16,samples); oki_decode(dataVOX,data16,samples);
@ -908,7 +909,10 @@ void DivSample::render() {
data8[i]=data16[i]>>8; 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 (depth!=DIV_SAMPLE_DEPTH_VOX) { // VOX
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);