Marian's A-pac: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
(technical description) |
||
Line 1: | Line 1: | ||
* Description: [http://www.rarewares.org/rrw/apac.php apac] | * Description: [http://www.rarewares.org/rrw/apac.php apac] | ||
* Homepage: [http://www.marian.de/english/downloads.htm#APAC APAC] | * Homepage: [http://www.marian.de/english/downloads.htm#APAC APAC] | ||
This is a simple lossless audio codec that uses prediction and fixed bit fields coding in very small blocks. | |||
=== File format === | |||
4 bytes - "APAC" | |||
4 bytes - file size minus 8 bytes | |||
4 bytes - "PROF" | |||
4 bytes - "NAD " (chunk for the original file headers) | |||
4 bytes - chunk size | |||
N bytes - e.g. RIFF WAVE header up to 'data' chunk | |||
4 bytes - "PFRT" (packed audio format chunk) | |||
4 bytes - chunk size | |||
2 bytes - unknown | |||
2 bytes - number of channels | |||
4 bytes - sampling rate | |||
2 bytes - source format [[TwoCC]] | |||
2 bytes - bits per sample | |||
4 bytes - probably CRC | |||
N bytes - zero-terminated original file name | |||
4 bytes - "PAD " (packed audio data chunk) | |||
4 bytes - chunk size | |||
N bytes - packed audio | |||
=== Compression algorithm === | |||
Audio is packed as small blocks (8 samples by default) and the second derivative of the prediction (the change from the last difference between predicted and actual sample) is coded as bit fields of fixed size that may change between blocks. Blocks have the following header: | |||
0 - no changes in parameters | |||
100 - decrease bit length by one | |||
101 - increase bit length by one | |||
110 - read 5-bit new bit length | |||
111 - read 4-bit new block length and read the header again (for possible bit length change) | |||
Overall decoding goes like this: | |||
last_sample = 0; | |||
last_delta = 0; | |||
bit_length = bits_per_sample; // 8 or 16 | |||
block_length = 8; | |||
while (data left) { | |||
mode = get_code(); | |||
switch (mode) { | |||
case "0": break; | |||
case "100": bit_length--; break; | |||
case "101": bit_length++; break; | |||
case "110": bit_length = get_bits(5); break; | |||
case "111": block_length = get_bits(4); continue; | |||
} | |||
for (i = 0; i < block_length; i++) { | |||
val = get_bits(bit_length); | |||
delta = (val & 1) ? ~(val >> 1) : (val >> 1); | |||
delta += last_delta; | |||
sample = last_sample + delta; | |||
last_delta = delta; | |||
last_sample = sample; | |||
} | |||
} | |||
[[Category: Audio Codecs]] | [[Category: Audio Codecs]] | ||
[[Category: Lossless Audio Codecs]] | [[Category: Lossless Audio Codecs]] | ||
Latest revision as of 08:59, 19 September 2022
This is a simple lossless audio codec that uses prediction and fixed bit fields coding in very small blocks.
File format
4 bytes - "APAC" 4 bytes - file size minus 8 bytes 4 bytes - "PROF" 4 bytes - "NAD " (chunk for the original file headers) 4 bytes - chunk size N bytes - e.g. RIFF WAVE header up to 'data' chunk 4 bytes - "PFRT" (packed audio format chunk) 4 bytes - chunk size 2 bytes - unknown 2 bytes - number of channels 4 bytes - sampling rate 2 bytes - source format TwoCC 2 bytes - bits per sample 4 bytes - probably CRC N bytes - zero-terminated original file name 4 bytes - "PAD " (packed audio data chunk) 4 bytes - chunk size N bytes - packed audio
Compression algorithm
Audio is packed as small blocks (8 samples by default) and the second derivative of the prediction (the change from the last difference between predicted and actual sample) is coded as bit fields of fixed size that may change between blocks. Blocks have the following header:
0 - no changes in parameters 100 - decrease bit length by one 101 - increase bit length by one 110 - read 5-bit new bit length 111 - read 4-bit new block length and read the header again (for possible bit length change)
Overall decoding goes like this:
last_sample = 0; last_delta = 0; bit_length = bits_per_sample; // 8 or 16 block_length = 8; while (data left) { mode = get_code(); switch (mode) { case "0": break; case "100": bit_length--; break; case "101": bit_length++; break; case "110": bit_length = get_bits(5); break; case "111": block_length = get_bits(4); continue; } for (i = 0; i < block_length; i++) { val = get_bits(bit_length); delta = (val & 1) ? ~(val >> 1) : (val >> 1); delta += last_delta; sample = last_sample + delta; last_delta = delta; last_sample = sample; } }