From a545cbce2bde793ed9c511f189fdc98a406283eb Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 27 Sep 2022 03:44:16 -0500 Subject: [PATCH] update brrUtils --- src/engine/brrUtils.c | 330 +++++++++++++++++++++++++++++++++++------- 1 file changed, 281 insertions(+), 49 deletions(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index e4463571..8c1a3cc9 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -21,6 +21,39 @@ */ #include "brrUtils.h" +#include + +#define DO_ONE_DEC(r) \ + if (nextDec&8) nextDec|=0xfffffff0; \ +\ + if (r>=13) { /* invalid shift */ \ + nextDec=(nextDec<0)?0xfffff800:0; \ + } else { \ + nextDec<<=r; /* range */ \ + nextDec>>=1; \ + } \ +\ + switch (filter) { /* filter */ \ + case 0: \ + break; \ + case 1: \ + nextDec+=last1+((-last1)>>4); \ + break; \ + case 2: \ + nextDec+=last1*2+((-last1*3)>>5)-last2+(last2>>4); \ + break; \ + case 3: \ + nextDec+=last1*2+((-last1*13)>>6)-last2+((last2*3)>>4); \ + break; \ + } \ +\ + if (nextDec>32767) nextDec=32767; \ + if (nextDec<-32768) nextDec=-32768; \ + nextDec&=0x7fff; \ + if (nextDec&0x4000) nextDec|=0xffff8000; \ +\ + last2=last1; \ + last1=nextDec; \ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { if (len==0) return 0; @@ -28,72 +61,274 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { // encoding process: // 1. read next group of 16 samples // 2. is this the first block? - // - if yes, don't filter. output and then go to 1 + // - if yes, don't filter. output and then go to 1 // 3. is this the loop block? - // - if yes, don't filter. output and then go to 1 + // - if yes, don't filter. output and then go to 1 // 4. try encoding using 4 filters + // - perform linear prediction + // - calculate range + // - decode and apply correction to achieve low error // 5. which one of these yields the least amount of error? // 6. output the one which does // 7. is this the last block? - // - if yes, mark end and finish + // - if yes, mark end and finish // 8. go to 1 long total=0; - unsigned char next[9]; + unsigned char next0[8]; + unsigned char next1[8]; + unsigned char next2[8]; + unsigned char next3[8]; unsigned char filter=0; - unsigned char range=0; + unsigned char range0=0; + unsigned char range1=0; + unsigned char range2=0; + unsigned char range3=0; unsigned char o=0; + int pred1[16]; + int pred2[16]; + int pred3[16]; + short o1=0; + short o2=0; short o0=0; + int last1=0; + int last2=0; + int nextDec=0; + int maxError[4]; + int avgError[4]; + len&=~15; loopStart&=~15; for (long i=0; i>13); if (s<0) s=-s; - while (range<12 && s>((8<((8<=len)?((loopStart>=0)?3:1):0); - switch (filter) { - case 0: - for (int j=0; j<16; j++) { - short s=buf[j]-(buf[j]>>13); - o0=s>>range; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - if (range>=12) if (o0<-7) o0=-7; - o=o0&15; - if (j&1) { - next[1+(j>>1)]|=o; - } else { - next[1+(j>>1)]=o<<4; - } - } - break; - case 1: - break; - case 2: - break; - case 3: - break; + for (int j=0; j<16; j++) { + short s=buf[j]-(buf[j]>>13); + o0=s>>range0; + if (range0) if (s&(1<<(range1>>1))) o0++; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + if (range0>=12) if (o0<-7) o0=-7; + o=o0&15; + if (j&1) { + next0[j>>1]|=o; + } else { + next0[j>>1]=o<<4; + } } - out[0]=next[0]; - out[1]=next[1]; - out[2]=next[2]; - out[3]=next[3]; - out[4]=next[4]; - out[5]=next[5]; - out[6]=next[6]; - out[7]=next[7]; - out[8]=next[8]; + // encode with filter + if (i && i!=loopStart) { + // 1: x = o0 - o1 * 15/16 + // 2: x = o0 + o2 * 15/16 - o1 * 61/32 + // 3: x = o0 + o2 * 13/16 - o1 * 115/64 + range1=0; + range2=0; + range3=0; + for (int j=0; j<16; j++) { + int s=buf[j]-(buf[j]>>13); + + pred1[j]=s-(((int)o1*15)>>4); + if (pred1[j]<-32768) pred1[j]=-32768; + if (pred1[j]>32767) pred1[j]=32767; + + pred2[j]=s+(((int)o2*15)>>4)-(((int)o1*61)>>5); + if (pred2[j]<-32768) pred2[j]=-32768; + if (pred2[j]>32767) pred2[j]=32767; + + pred3[j]=s+(((int)o2*13)>>4)-(((int)o1*115)>>6); + if (pred3[j]<-32768) pred3[j]=-32768; + if (pred3[j]>32767) pred3[j]=32767; + + o2=o1; + o1=s; + } + for (int j=0; j<16; j++) { + short s=pred1[j]; + if (s<0) s=-s; + while (range1<10 && s>((8<((8<((8<>range1; + if (range1) if (s&(1<<(range1>>1))) o0++; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + if (range1>=12) if (o0<-7) o0=-7; + o=o0&15; + if (j&1) { + next1[j>>1]|=o; + } else { + next1[j>>1]=o<<4; + } + + s=pred2[j]; + o0=s>>range2; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + if (range2>=12) if (o0<-7) o0=-7; + o=o0&15; + if (j&1) { + next2[j>>1]|=o; + } else { + next2[j>>1]=o<<4; + } + + s=pred3[j]; + o0=s>>range3; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + if (range3>=12) if (o0<-7) o0=-7; + o=o0&15; + if (j&1) { + next3[j>>1]|=o; + } else { + next3[j>>1]=o<<4; + } + } + } + + if (i && i!=loopStart) { + // find best filter + int prevLast1=last1; + int prevLast2=last2; + int error=0; + + maxError[0]=0; + maxError[1]=0; + maxError[2]=0; + maxError[3]=0; + avgError[0]=0; + avgError[1]=0; + avgError[2]=0; + avgError[3]=0; + + // test filter 0 + filter=0; + for (int j=0; j<16; j++) { + int s=buf[j]-(buf[j]>>13); + if (j&1) { + nextDec=next0[j>>1]&15; + } else { + nextDec=next0[j>>1]>>4; + } + DO_ONE_DEC(range0); + error=s-(nextDec<<1); + if (error<0) error=-error; + avgError[0]+=error; + if (error>maxError[0]) maxError[0]=error; + } + avgError[0]>>=4; + last1=prevLast1; + last2=prevLast2; + + // test filter 1 + filter=1; + for (int j=0; j<16; j++) { + int s=buf[j]-(buf[j]>>13); + if (j&1) { + nextDec=next1[j>>1]&15; + } else { + nextDec=next1[j>>1]>>4; + } + DO_ONE_DEC(range1); + error=s-(nextDec<<1); + if (error<0) error=-error; + avgError[1]+=error; + if (error>maxError[1]) maxError[1]=error; + //printf("%6d | %6d => %6d\n",s,nextDec<<1,error); + } + avgError[1]>>=4; + last1=prevLast1; + last2=prevLast2; + + // pick best filter + int candError=0x7fffffff; + for (int j=0; j<2; j++) { + if (avgError[j] %d\n",i>>4,avgError[0],avgError[1],filter); + } else { + // don't filter on the first or loop block + filter=0; + } + + switch (filter) { + case 0: + nextDec=next0[7]>>4; + DO_ONE_DEC(range0); + o2=nextDec<<1; + + nextDec=next0[7]&15; + DO_ONE_DEC(range0); + o1=nextDec<<1; + + out[0]=(range0<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + out[1]=next0[0]; + out[2]=next0[1]; + out[3]=next0[2]; + out[4]=next0[3]; + out[5]=next0[4]; + out[6]=next0[5]; + out[7]=next0[6]; + out[8]=next0[7]; + break; + case 1: + for (int j=0; j<8; j++) { + nextDec=next1[j]>>4; + DO_ONE_DEC(range1); + nextDec=next1[j]&15; + DO_ONE_DEC(range1); + } + out[0]=(range1<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + out[1]=next1[0]; + out[2]=next1[1]; + out[3]=next1[2]; + out[4]=next1[3]; + out[5]=next1[4]; + out[6]=next1[5]; + out[7]=next1[6]; + out[8]=next1[7]; + break; + case 2: + out[0]=(range2<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + out[1]=next2[0]; + out[2]=next2[1]; + out[3]=next2[2]; + out[4]=next2[3]; + out[5]=next2[4]; + out[6]=next2[5]; + out[7]=next2[6]; + out[8]=next2[7]; + break; + case 3: + out[0]=(range3<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + out[1]=next3[0]; + out[2]=next3[1]; + out[3]=next3[2]; + out[4]=next3[3]; + out[5]=next3[4]; + out[6]=next3[5]; + out[7]=next3[6]; + out[8]=next3[7]; + break; + } buf+=16; out+=9; total+=9; @@ -135,9 +370,6 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { *out=next<<1; \ out++; -// TODO: -// - what happens during overflow? -// - what happens when range values 12 to 15 are used? long brrDecode(unsigned char* buf, short* out, long len) { if (len==0) return 0;