The Bit Rate Reduction Sound Encoding Scheme


Due to the requests of several people, the lack of documentation in this area,
and a hope to spring the SNES emulation "scene" forward, I am going to try to
describe the BRR encoding scheme in this doc.  Everything here, I either read
in publicly available documentation, or discovered myself through trial and
error.  I cannot guarantee the accuracy of this doc, and I will not be
responsible for errors, either typographical or otherwise.  However, if you
are satisfied with the output of SNESSOR, the SNES SOund Ripper, then this doc
should work for you.


BRR, or Bit Rate Reduction, is the sound encoding scheme used by the SPC700,
the sound chip in the SNES.  It has a compression ratio of 32:9, meaning that
for every 32 bytes of 16-bit PCM there are 9 bytes of BRR.  These 9 bytes
consist of 1 header byte, and 16 nybbles of data, as follows:

|       | byte
|Header |  1
|       |
|data 1 | byte
| - - - |  2
|data 2 |
|data 3 | byte 
| - - - |  3
|data 4 |
/       /
/       /
|data 15| byte
| - - - |  9
|data 16|

The header byte is decoded as follows:
 ||||||||____END  bit - determines the end of a sample
 |||||||_____LOOP bit - determines whether a sample will loop
 |||||_______>FILTER bits - determines which filter to apply (described later)
 ||__________ >RANGE bits - see below

The END bit is clear for every 9-byte block until the last block of a sample.
When you encounter this bit, you should finish reading the following 8 bytes,
then stop.

The LOOP bit is set in every single 9-byte block of a sample that loops, and
is clear in every single block of a sample that doesn't.  Proper use of this
bit requires a loop point, however there is no standard way to store this
outside of the SPC itself.  For more info concerning loop points, consult an
SPC hardware doc.

The FILTER bits are described below.

The RANGE bits tell how to read each nybble of data.  Basically, you take the
nybble, and you shift it left RANGE times.  The nybble is signed, and this
must be taken into account.  Note that a RANGE greater than 12 would shift the
nybble past a 16-bit value, so RANGE values from 12 to 15 are invalid, and it
is on this that the SNESSOR sample search is based, among other things.

If that wasn't especially clear, I'm sorry.  Let's try some example code to

int range, end=0, loop, filter, counter, temp; // Size of these doesn't matter
short input, output[MAXSAMPLEN];    // These must be 16-bit
int now=0;      // Pointer to where we are in output[];

        range=GetNextByte();    // Let's just put the header here for now
        end=range&1;            // END bit is bit 0
        loop=range&2;           // LOOP bit is bit 1
        filter=(range>>2)&3;    // FILTER is bits 2 and 3
        range>>=4;              // RANGE is the upper 4 bits

        for(counter=0;counter<8;counter++)      // Get the next 8 bytes
                temp=GetNextByte();     // Wherever you want to get this from
                input=temp>>4;  // Get the first nybble of the byte
                if(input>8)             // The nybble is negative, so make the 
                        input|=0xFFF0;  // 16-bit value negative
                output[now]=input<8)             // The nybble is negative, so make the 
                        input|=0xFFF0;  // 16-bit value negative