Real Lossless Codec: Difference between revisions

From MultimediaWiki
Jump to navigation Jump to search
No edit summary
(fixes)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
* FOURCCs: ralf
* FOURCCs: ralf
* Company: [[Real|RealNetworks]]
* Company: [[Real|RealNetworks]]
* Samples: http://samples.mplayerhq.hu/A-codecs/lossless/ (luckynight.rmvb)
* Samples: http://samples.libav.org/A-codecs/lossless/ (luckynight.rmvb)


This is RealNetworks lossless audio codec.
This is RealNetworks lossless audio codec.
Line 22: Line 22:
Known decoder support only 1/2 channel 16-bit audio with sampling rate up to 96 kHz.
Known decoder support only 1/2 channel 16-bit audio with sampling rate up to 96 kHz.


[[Category:Undiscovered Audio Codecs]]
== 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]]
[[Category:Audio Codecs]]

Latest revision as of 01:54, 17 March 2012

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;
 }