OK there is already a few programms that allows you to convert to BRR, but most of them aren't widely spread and are glitchy / lack options I'd like them to have.
So I decided to start to code a java BRR->WAV converter (in the scope to add a WAV->BRR converter to it once it'll function).
It seems to work fine for "normal" samples, but my issue is that the samples that are supposed to be noisy aren't noisy, even tough I use the supposely accurate anomie's algorithms. I tried looking into Snes9x's sourcecode, but it was a huge mess and I doubt it's accuracy as well.
I've uploaded the sources and binaries. In addition to normal decoding it also allows you to decode samples while looping and test their stability on loop point (which isn't complete yet).
For people who just feel too lazy to download here is the "hot" part of decoding :
So I decided to start to code a java BRR->WAV converter (in the scope to add a WAV->BRR converter to it once it'll function).
It seems to work fine for "normal" samples, but my issue is that the samples that are supposed to be noisy aren't noisy, even tough I use the supposely accurate anomie's algorithms. I tried looking into Snes9x's sourcecode, but it was a huge mess and I doubt it's accuracy as well.
I've uploaded the sources and binaries. In addition to normal decoding it also allows you to decode samples while looping and test their stability on loop point (which isn't complete yet).
For people who just feel too lazy to download here is the "hot" part of decoding :
Code:
static short[] DecodeBRR (byte[] Data) { //Decode a string of BRR bytes
int Filter = (Data[0] & 0x0c)>>2;
int ShiftAmount = Data[0]>>4; //Read filter & shift amount
if(ShiftAmount<0) ShiftAmount+=0x10; //This is needed because of the stupid way Java handles neg numbers
short[] out = new short[(Data.length-1)<<1]; //Output string of 16-bit samples
for(int i=0; i<Data.length-1; i++) { //Loop for each byte
DecodeSample((short)(Data[i+1]>>4), ShiftAmount, Filter); //Decode high nybble
out[i<<1]=p1;
DecodeSample((short)(Data[i+1]&0x0f), ShiftAmount, Filter); //Decode low nybble
out[(i<<1)+1]=p1;
}
return out;
}
static void DecodeSample (short s, int ShiftAmount, int Filter) {
if (s>=8) s-=0x10; //Fix numbers that should be negative
s =(short)(s << ShiftAmount);
int a;
switch(Filter) {
case 0 :
a = s;
break;
case 1 :
a = s + p1 + (-p1>>4);
break;
case 2 :
a = s + (p1<<1) + ((-((p1<<1)+p1))>>5) - p2 + (p2>>4);
break;
default :
a = s + (p1<<1) + ((-(p1+(p1<<2)+(p1<<3)))>>6) - p2 + (((p2<<1) + p2)>>4);
}
if(a>Short.MAX_VALUE) a=Short.MAX_VALUE;
if(a<Short.MIN_VALUE) a=Short.MIN_VALUE; //Clamp to 16-bit
a &= 0xFFFE; //Clip to 15-bit
p2 = p1;
p1 = (short)a;
}
int Filter = (Data[0] & 0x0c)>>2;
int ShiftAmount = Data[0]>>4; //Read filter & shift amount
if(ShiftAmount<0) ShiftAmount+=0x10; //This is needed because of the stupid way Java handles neg numbers
short[] out = new short[(Data.length-1)<<1]; //Output string of 16-bit samples
for(int i=0; i<Data.length-1; i++) { //Loop for each byte
DecodeSample((short)(Data[i+1]>>4), ShiftAmount, Filter); //Decode high nybble
out[i<<1]=p1;
DecodeSample((short)(Data[i+1]&0x0f), ShiftAmount, Filter); //Decode low nybble
out[(i<<1)+1]=p1;
}
return out;
}
static void DecodeSample (short s, int ShiftAmount, int Filter) {
if (s>=8) s-=0x10; //Fix numbers that should be negative
s =(short)(s << ShiftAmount);
int a;
switch(Filter) {
case 0 :
a = s;
break;
case 1 :
a = s + p1 + (-p1>>4);
break;
case 2 :
a = s + (p1<<1) + ((-((p1<<1)+p1))>>5) - p2 + (p2>>4);
break;
default :
a = s + (p1<<1) + ((-(p1+(p1<<2)+(p1<<3)))>>6) - p2 + (((p2<<1) + p2)>>4);
}
if(a>Short.MAX_VALUE) a=Short.MAX_VALUE;
if(a<Short.MIN_VALUE) a=Short.MIN_VALUE; //Clamp to 16-bit
a &= 0xFFFE; //Clip to 15-bit
p2 = p1;
p1 = (short)a;
}