Real Lossless Codec: Difference between revisions
(Add to lossless audio codecs category.) |
(fixes) |
||
(14 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
* FOURCCs: ralf | * FOURCCs: ralf | ||
* Company: [[Real|RealNetworks]] | * Company: [[Real|RealNetworks]] | ||
* Samples: http://samples.libav.org/A-codecs/lossless/ (luckynight.rmvb) | |||
This is RealNetworks lossless audio codec. | This is RealNetworks lossless audio codec. | ||
Line 7: | Line 7: | ||
Audio header in rm files is different from other Real audio codecs; the interface of the binary decoder is also different. | Audio header in rm files is different from other Real audio codecs; the interface of the binary decoder is also different. | ||
[[ | |||
== Extradata format == | |||
Numbers are stored big-endian. | |||
bytes 0- 3 - codec FOURCC, always "LSD:" | |||
bytes 4- 5 - version | |||
bytes 8- 9 - number of channels | |||
bytes 10-11 - bits per sample | |||
bytes 12-15 - sampling rate | |||
bytes 16-19 - block size in samples? | |||
bytes 20-23 - ignored? | |||
Known decoder support only 1/2 channel 16-bit audio with sampling rate up to 96 kHz. | |||
== Frame format == | |||
Data is read MSB. | |||
block header | |||
channel data 1 | |||
if (stereo) | |||
channel data 2 | |||
Each channel is then restored by applying filter and in stereo case channels are recombined. | |||
=== Block header === | |||
get frame length code | |||
if (stereo) | |||
decoding_mode = get_bits(2) + 1; | |||
else | |||
decoding_mode = 0; | |||
Frame length code: | |||
64 - 111110 | |||
128 - 111111 | |||
256 - 11110 | |||
512 - 1110 | |||
1024 - 110 | |||
2048 - 10 | |||
4096 - 0 | |||
Decoding mode specifies table sets, bits and channel recombining: | |||
{| border="1" cellpadding="5" style="border-collapse: collapse; border-style: dashed; border-color: #2f6fab;" | |||
|- bgcolor="#f0f0f0" | | |||
! Mode !! tableset1 !! bits1 !! tableset2 !! bits2 !! Channel decoupling | |||
|- | |||
| align="center" | 0 || align="center" | 0 || align="center" | 16 || align="center" | n/a || align="center" | n/a || align="center" | mono | |||
|- | |||
| align="center" | 1 || align="center" | 0 || align="center" | 16 || align="center" | 0 || align="center" | 16 || align="center" | L, R | |||
|- | |||
| align="center" | 2 || align="center" | 0 || align="center" | 16 || align="center" | 2 || align="center" | 17 || align="center" | L+R, R | |||
|- | |||
| align="center" | 3 || align="center" | 1 || align="center" | 16 || align="center" | 2 || align="center" | 17 || align="center" | L, R-L | |||
|- | |||
| align="center" | 4 || align="center" | 2 || align="center" | 17 || align="center" | 2 || align="center" | 17 || align="center" | (L+R)/2, (L-R)/2 | |||
|} | |||
=== Block data === | |||
==== Variable-length codes ==== | |||
RALF uses hybrid coding scheme for signed integers: coded value in range <code>1..N-1</code> maps to <code>-N/2+1..N/2-1</code> and values <code>0</code> and <code>N</code> are used as escape values. | |||
In case an escape value is occurred, an additional Elias Gamma code (aka exp-Golomb) is read and added to or subtracted from the result. | |||
Also some low bits can be read explicitly. | |||
extend_code(code, range, add_bits) | |||
{ | |||
if (code == 0) { | |||
len = get_unary(); // 000...001 | |||
code = -range + 1 - get_bits(len + 1); | |||
} else if (code == range*2) { | |||
len = get_unary(); // 000...001 | |||
code = range - 1 + get_bits(len + 1); | |||
} else { | |||
code -= range; | |||
} | |||
if (add_bits > 0) | |||
code = (code << add_bits) | get_bits(add_bits); | |||
return code; | |||
} | |||
==== Channel data ==== | |||
Channel data is organised that way: | |||
filter_parameter = get_vlc(filter_parameter_table); | |||
if (filter_parameter == 642) { | |||
bias_val = 0; | |||
all samples are coded raw | |||
} | |||
bias_val = get_vlc(bias_table); | |||
bias_val = extend_code(bias_val, 127, 4); // input is 0..254, make it signed, read escape values if needed and low 4 bits | |||
if (filter_parameter == 0) { | |||
all samples are zero | |||
return | |||
} | |||
if (filter_parameter > 1) { | |||
filter_bits = (filter_parameter - 2) >> 6; // range 0..9 | |||
filter_len = filter_parameter - 1 - (filter_bits << 6); // range 1..64 | |||
coeff = 0; | |||
coeff_mode = 0; | |||
for (i = 0; i < filter_len; i++) { | |||
t = get_vlc(filt_coef_table[filter_bits][coeff_mode + 5]); | |||
t = extend_code(t, 21, filter_bits); | |||
if (coeff_mode == 0) | |||
coeff -= 12 << filter_bits; | |||
coeff = t - coeff; | |||
filter[i] = coeff; | |||
coeff_mode = coeff >> filter_bits; | |||
if (coeff_mode < 0) | |||
coeff_mode = max(-5, -1 - log2(-coeff_mode)); | |||
else if (coeff_mode > 0) | |||
coeff_mode = min(5, 1 + log2(coeff_mode)); | |||
} | |||
} | |||
coding_mode = get_vlc(coding_mode_tree); | |||
if (coding_mode >= 15) { // big codes | |||
bits = (coding_mode / 5 - 3) / 2; | |||
if (bits > 9) { | |||
bits = 9; | |||
if ((coding_mode % 5) == 2) | |||
bits++; | |||
} | |||
for (i = 0; i < num_samples; i += 2) { | |||
t = get_vlc(long_codes_trees[coding_mode - 15]); | |||
val1 = t / 21; | |||
val2 = t - val1 * 21; | |||
val1 = extend_code(val1, 10, 0); | |||
val2 = extend_code(val2, 10, 0); | |||
if (bits == 0) { | |||
dst[i] = val1; | |||
dst[i + 1] = val2; | |||
} else { | |||
dst[i] = (val1 << bits) | get_bits(bits); | |||
dst[i + 1] = (val2 << bits) | get_bits(bits); | |||
} | |||
} | |||
} else { | |||
for (i = 0; i < num_samples; i += 2) { | |||
t = get_vlc(short_codes_trees[coding_mode]); | |||
val1 = t / 13; | |||
val2 = t - val1 * 13; | |||
val1 = extend_code(val1, 6, 0); | |||
val2 = extend_code(val2, 6, 0); | |||
dst[i] = val1; | |||
dst[i + 1] = val2; | |||
} | |||
} | |||
=== Restoring channel data === | |||
* apply LPC filter | |||
* add bias value to all samples | |||
* re-correlate stereo channels if needed | |||
==== LPC filter ==== | |||
filter_bits = ((filter_parameter - 2) >> 6) + 3; | |||
range_bits = bits_in_channel; // i.e. 16 or 17 | |||
bias = 1 << (filter_bits - 1); | |||
pos_clip = (1 << range_bits) - 1; | |||
neg_clip = ~pos_clip; | |||
for (i = 0; i < num_samples; i++) { | |||
acc = 0; | |||
for (j = 0; j < min(i, filter_length); j++) | |||
acc += filter[j] * src[i - j - 1]; | |||
if (acc < 0) | |||
val = (acc + bias - 1) >> filter_bits; | |||
else | |||
val = (acc + bias) >> filter_bits; | |||
val = clip(val, neg_clip, pos_clip); | |||
src[i] += val; | |||
} | |||
[[Category:Lossless Audio Codecs]] | [[Category:Lossless Audio Codecs]] | ||
[[Category:Audio Codecs]] |
Latest revision as of 01:54, 17 March 2012
- FOURCCs: ralf
- Company: RealNetworks
- Samples: http://samples.libav.org/A-codecs/lossless/ (luckynight.rmvb)
This is RealNetworks lossless audio codec.
Audio header in rm files is different from other Real audio codecs; the interface of the binary decoder is also different.
Extradata format
Numbers are stored big-endian.
bytes 0- 3 - codec FOURCC, always "LSD:" bytes 4- 5 - version bytes 8- 9 - number of channels bytes 10-11 - bits per sample bytes 12-15 - sampling rate bytes 16-19 - block size in samples? bytes 20-23 - ignored?
Known decoder support only 1/2 channel 16-bit audio with sampling rate up to 96 kHz.
Frame format
Data is read MSB.
block header channel data 1 if (stereo) channel data 2
Each channel is then restored by applying filter and in stereo case channels are recombined.
Block header
get frame length code if (stereo) decoding_mode = get_bits(2) + 1; else decoding_mode = 0;
Frame length code:
64 - 111110 128 - 111111 256 - 11110 512 - 1110 1024 - 110 2048 - 10 4096 - 0
Decoding mode specifies table sets, bits and channel recombining:
Mode | tableset1 | bits1 | tableset2 | bits2 | Channel decoupling |
---|---|---|---|---|---|
0 | 0 | 16 | n/a | n/a | mono |
1 | 0 | 16 | 0 | 16 | L, R |
2 | 0 | 16 | 2 | 17 | L+R, R |
3 | 1 | 16 | 2 | 17 | L, R-L |
4 | 2 | 17 | 2 | 17 | (L+R)/2, (L-R)/2 |
Block data
Variable-length codes
RALF uses hybrid coding scheme for signed integers: coded value in range 1..N-1
maps to -N/2+1..N/2-1
and values 0
and N
are used as escape values.
In case an escape value is occurred, an additional Elias Gamma code (aka exp-Golomb) is read and added to or subtracted from the result.
Also some low bits can be read explicitly.
extend_code(code, range, add_bits) { if (code == 0) { len = get_unary(); // 000...001 code = -range + 1 - get_bits(len + 1); } else if (code == range*2) { len = get_unary(); // 000...001 code = range - 1 + get_bits(len + 1); } else { code -= range; } if (add_bits > 0) code = (code << add_bits) | get_bits(add_bits); return code; }
Channel data
Channel data is organised that way:
filter_parameter = get_vlc(filter_parameter_table); if (filter_parameter == 642) { bias_val = 0; all samples are coded raw } bias_val = get_vlc(bias_table); bias_val = extend_code(bias_val, 127, 4); // input is 0..254, make it signed, read escape values if needed and low 4 bits if (filter_parameter == 0) { all samples are zero return } if (filter_parameter > 1) { filter_bits = (filter_parameter - 2) >> 6; // range 0..9 filter_len = filter_parameter - 1 - (filter_bits << 6); // range 1..64 coeff = 0; coeff_mode = 0; for (i = 0; i < filter_len; i++) { t = get_vlc(filt_coef_table[filter_bits][coeff_mode + 5]); t = extend_code(t, 21, filter_bits); if (coeff_mode == 0) coeff -= 12 << filter_bits; coeff = t - coeff; filter[i] = coeff; coeff_mode = coeff >> filter_bits; if (coeff_mode < 0) coeff_mode = max(-5, -1 - log2(-coeff_mode)); else if (coeff_mode > 0) coeff_mode = min(5, 1 + log2(coeff_mode)); } } coding_mode = get_vlc(coding_mode_tree); if (coding_mode >= 15) { // big codes bits = (coding_mode / 5 - 3) / 2; if (bits > 9) { bits = 9; if ((coding_mode % 5) == 2) bits++; } for (i = 0; i < num_samples; i += 2) { t = get_vlc(long_codes_trees[coding_mode - 15]); val1 = t / 21; val2 = t - val1 * 21; val1 = extend_code(val1, 10, 0); val2 = extend_code(val2, 10, 0); if (bits == 0) { dst[i] = val1; dst[i + 1] = val2; } else { dst[i] = (val1 << bits) | get_bits(bits); dst[i + 1] = (val2 << bits) | get_bits(bits); } } } else { for (i = 0; i < num_samples; i += 2) { t = get_vlc(short_codes_trees[coding_mode]); val1 = t / 13; val2 = t - val1 * 13; val1 = extend_code(val1, 6, 0); val2 = extend_code(val2, 6, 0); dst[i] = val1; dst[i + 1] = val2; } }
Restoring channel data
- apply LPC filter
- add bias value to all samples
- re-correlate stereo channels if needed
LPC filter
filter_bits = ((filter_parameter - 2) >> 6) + 3; range_bits = bits_in_channel; // i.e. 16 or 17 bias = 1 << (filter_bits - 1); pos_clip = (1 << range_bits) - 1; neg_clip = ~pos_clip; for (i = 0; i < num_samples; i++) { acc = 0; for (j = 0; j < min(i, filter_length); j++) acc += filter[j] * src[i - j - 1]; if (acc < 0) val = (acc + bias - 1) >> filter_bits; else val = (acc + bias) >> filter_bits; val = clip(val, neg_clip, pos_clip); src[i] += val; }