update brrUtils
This commit is contained in:
parent
8564f65428
commit
a545cbce2b
|
@ -21,6 +21,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "brrUtils.h"
|
#include "brrUtils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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) {
|
long brrEncode(short* buf, unsigned char* out, long len, long loopStart) {
|
||||||
if (len==0) return 0;
|
if (len==0) return 0;
|
||||||
|
@ -28,72 +61,274 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) {
|
||||||
// encoding process:
|
// encoding process:
|
||||||
// 1. read next group of 16 samples
|
// 1. read next group of 16 samples
|
||||||
// 2. is this the first block?
|
// 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?
|
// 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
|
// 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?
|
// 5. which one of these yields the least amount of error?
|
||||||
// 6. output the one which does
|
// 6. output the one which does
|
||||||
// 7. is this the last block?
|
// 7. is this the last block?
|
||||||
// - if yes, mark end and finish
|
// - if yes, mark end and finish
|
||||||
// 8. go to 1
|
// 8. go to 1
|
||||||
long total=0;
|
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 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;
|
unsigned char o=0;
|
||||||
|
int pred1[16];
|
||||||
|
int pred2[16];
|
||||||
|
int pred3[16];
|
||||||
|
short o1=0;
|
||||||
|
short o2=0;
|
||||||
short o0=0;
|
short o0=0;
|
||||||
|
|
||||||
|
int last1=0;
|
||||||
|
int last2=0;
|
||||||
|
int nextDec=0;
|
||||||
|
int maxError[4];
|
||||||
|
int avgError[4];
|
||||||
|
|
||||||
len&=~15;
|
len&=~15;
|
||||||
loopStart&=~15;
|
loopStart&=~15;
|
||||||
for (long i=0; i<len; i+=16) {
|
for (long i=0; i<len; i+=16) {
|
||||||
// don't filter on the first or loop block
|
range0=0;
|
||||||
if (i && i!=loopStart) {
|
// encode with no filter
|
||||||
|
|
||||||
} else {
|
|
||||||
filter=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
range=0;
|
|
||||||
for (int j=0; j<16; j++) {
|
for (int j=0; j<16; j++) {
|
||||||
short s=buf[j]-(buf[j]>>13);
|
short s=buf[j]-(buf[j]>>13);
|
||||||
if (s<0) s=-s;
|
if (s<0) s=-s;
|
||||||
while (range<12 && s>((8<<range)-1)) range++;
|
while (range0<12 && s>((8<<range0)-1)) range0++;
|
||||||
}
|
}
|
||||||
next[0]=(range<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0);
|
for (int j=0; j<16; j++) {
|
||||||
switch (filter) {
|
short s=buf[j]-(buf[j]>>13);
|
||||||
case 0:
|
o0=s>>range0;
|
||||||
for (int j=0; j<16; j++) {
|
if (range0) if (s&(1<<(range1>>1))) o0++;
|
||||||
short s=buf[j]-(buf[j]>>13);
|
if (o0>7) o0=7;
|
||||||
o0=s>>range;
|
if (o0<-8) o0=-8;
|
||||||
if (o0>7) o0=7;
|
if (range0>=12) if (o0<-7) o0=-7;
|
||||||
if (o0<-8) o0=-8;
|
o=o0&15;
|
||||||
if (range>=12) if (o0<-7) o0=-7;
|
if (j&1) {
|
||||||
o=o0&15;
|
next0[j>>1]|=o;
|
||||||
if (j&1) {
|
} else {
|
||||||
next[1+(j>>1)]|=o;
|
next0[j>>1]=o<<4;
|
||||||
} else {
|
}
|
||||||
next[1+(j>>1)]=o<<4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out[0]=next[0];
|
// encode with filter
|
||||||
out[1]=next[1];
|
if (i && i!=loopStart) {
|
||||||
out[2]=next[2];
|
// 1: x = o0 - o1 * 15/16
|
||||||
out[3]=next[3];
|
// 2: x = o0 + o2 * 15/16 - o1 * 61/32
|
||||||
out[4]=next[4];
|
// 3: x = o0 + o2 * 13/16 - o1 * 115/64
|
||||||
out[5]=next[5];
|
range1=0;
|
||||||
out[6]=next[6];
|
range2=0;
|
||||||
out[7]=next[7];
|
range3=0;
|
||||||
out[8]=next[8];
|
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<<range1)-1)) range1++;
|
||||||
|
|
||||||
|
s=pred2[j];
|
||||||
|
if (s<0) s=-s;
|
||||||
|
while (range2<7 && s>((8<<range2)-1)) range2++;
|
||||||
|
|
||||||
|
s=pred3[j];
|
||||||
|
if (s<0) s=-s;
|
||||||
|
while (range3<7 && s>((8<<range3)-1)) range3++;
|
||||||
|
}
|
||||||
|
for (int j=0; j<16; j++) {
|
||||||
|
short s=pred1[j];
|
||||||
|
o0=s>>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]<candError) {
|
||||||
|
candError=avgError[j];
|
||||||
|
filter=j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("block %ld: %8d %8d -> %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;
|
buf+=16;
|
||||||
out+=9;
|
out+=9;
|
||||||
total+=9;
|
total+=9;
|
||||||
|
@ -135,9 +370,6 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) {
|
||||||
*out=next<<1; \
|
*out=next<<1; \
|
||||||
out++;
|
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) {
|
long brrDecode(unsigned char* buf, short* out, long len) {
|
||||||
if (len==0) return 0;
|
if (len==0) return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue