Page 1 of 1

BRR encoding

Posted: Wed Sep 02, 2009 10:03 am
by mic_
Are there any docs out there that explains the BRR encoding process? I've seen some sites that talk about decoding, but nothing about encoding.

Posted: Wed Sep 02, 2009 10:52 am
by koitsu
The BRR format should already be documented, both officially and unofficially.

http://www.emulatronia.com/doctec/consolas/snes/brr.txt
http://www.pikensoft.com/old/docs/SNES_ ... cha%29.txt

If you need something "more official" I can scan some pages from the development manual.

Posted: Wed Sep 02, 2009 10:59 am
by mic_
Unless I'm missing something, that doc describes how to decode BRR samples to raw PCM. I want want to do the opposite; encode raw PCM to BRR.

Posted: Wed Sep 02, 2009 3:22 pm
by tepples
mic_ wrote:Unless I'm missing something, that doc describes how to decode BRR samples to raw PCM. I want want to do the opposite; encode raw PCM to BRR.
To understand my explanation, first look up IMA ADPCM and how it's encoded and decoded. Encoding BRR or VAG is rawther similar.

In BRR, each sample y is the sum of a prediction p and a residue r. The prediction is a linear function of the two previous samples.
y[t] = p[t] + r[t]
filter 0: p[t] = y[n - 1] * 0/64 - y[n - 2] * 0/16
filter 1: p[t] = y[n - 1] * 60/64 - y[n - 2] * 0/16
filter 2: p[t] = y[n - 1] * 122/64 - y[n - 2] * 15/16
filter 3: p[t] = y[n - 1] * 115/64 - y[n - 2] * 13/16
I added multiplications by 0 to make parallels among the filters more obvious.

For each block of 16 samples, you need to first find the appropriate filter and range and then encode the block. To find the best filter and range:
  1. Compute r[t] = y[t] - p[t] for all four filters.
  2. Compute the peak residue for each filter, as max(abs(r[t])).
  3. Find the filter with the smallest peak residue.
  4. Set the range to the smallest value that doesn't cause slope overload when encoding the peak residue with this filter.
Then for each sample in the block:
  1. Compute p[t] based on the filter, y[n - 1], and y[n - 2].
  2. Compute the residue r[t] = y[t] - p[t].
  3. Quantize the residue based on the range, and output this scaled residue: rscaled[t] = r[t] >> range.
  4. Recompute y[t] based on the scaled residue: y[t] = p[t] + (rscaled[t] << range).

Posted: Wed Sep 02, 2009 5:48 pm
by kode54
I wrote a brute force encoder ages ago, based on the IMA ADPCM encoder from SoX. I uploaded a copy of that here. There's probably a better way of doing it, but at least this way ensures the closest representation of the original data.

Basically, the encoder calculates each sample nibble, then calculates what the decoded result would be quantized to. It uses this for the sample history when encoding using the filters. It also uses this to calculate the mean square error, which is used by the brute force encoding loop. It picks the filter set and scale value that produce the least mean square error for each given block.

Oh, and it also has an addition for encoding looping samples. Basically, it can optionally factor in the last two samples of the block before the loop start when encoding the last block in the sample, to try to make the loop match up without forcing the encoder to use a filter of 0 for the loop start block.

Anyway, have fun and good luck.