The Bit Rate Reduction sound encoding scheme, as interpreted by Butcha ______________________________________________________________________ __________________________________________________ __________ INTRODUCTION ____________ 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 ___ 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: xxxxxxxx ||||||||____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 help: 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[]; while(end==0) { 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 input&=0xF; 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 output[now]=input<