decals-svnlog Mailing List for Decals
Status: Inactive
Brought to you by:
jbr79
You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(5) |
Sep
|
Oct
|
Nov
|
Dec
|
---|
From: <jb...@us...> - 2007-08-20 00:20:27
|
Revision: 5 http://decals.svn.sourceforge.net/decals/?rev=5&view=rev Author: jbr79 Date: 2007-08-19 17:20:25 -0700 (Sun, 19 Aug 2007) Log Message: ----------- add documentation license Modified Paths: -------------- doc/mp4-als_format_notes.txt Modified: doc/mp4-als_format_notes.txt =================================================================== --- doc/mp4-als_format_notes.txt 2007-08-20 00:13:31 UTC (rev 4) +++ doc/mp4-als_format_notes.txt 2007-08-20 00:20:25 UTC (rev 5) @@ -1,4 +1,10 @@ +This work is licensed under the Creative Commons Attribution-Share Alike 3.0 +License. To view a copy of this license, visit +http://creativecommons.org/licenses/by-sa/3.0/ +or send a letter to Creative Commons, 171 Second Street, Suite 300, +San Francisco, California, 94105, USA. + MPEG-4 Audio Lossless Coding (ALS) Documentation ------------------------------------------------ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2007-08-20 00:13:36
|
Revision: 4 http://decals.svn.sourceforge.net/decals/?rev=4&view=rev Author: jbr79 Date: 2007-08-19 17:13:31 -0700 (Sun, 19 Aug 2007) Log Message: ----------- initial import with directory structure Added Paths: ----------- doc/ doc/mp4-als_format_notes.txt src/ src/COPYING src/Makefile src/alsdec.c src/alsdec.h src/alstab.h src/bitreader.c src/bitreader.h src/bswap.h src/common.h src/config.h src/config.mak src/main.c Added: doc/mp4-als_format_notes.txt =================================================================== --- doc/mp4-als_format_notes.txt (rev 0) +++ doc/mp4-als_format_notes.txt 2007-08-20 00:13:31 UTC (rev 4) @@ -0,0 +1,635 @@ + +MPEG-4 Audio Lossless Coding (ALS) Documentation +------------------------------------------------ + + +MPEG-4 Audio Lossless Coding[1][2], also called MP4-ALS, is one of the lossless +audio coding formats which is part of the MPEG-4 audio specification. It is +based on the LPAC audio codec[3] by Tilman Liebchen. This document covers the +raw ALS format, which consists of the ALS header and a sequence of frames. + + + +KEY CONCEPTS +============ + +Original file preservation +-------------------------- +The ALS header can provide everything that is needed to reconstruct the +original WAVE, AIFF, or raw audio file. This includes the file type, +sample rate, number of channels, bits-per-sample, sample type, and byte order. +The original header and/or footer are also preserved exactly in the ALS +header. The ALS format only supports from 8-bit to 32-bit audio in 8-bit +increments. Either integer or IEEE-floating-point sample types are supported. + + +Frame size and block switching +------------------------------ +The ALS frame size (number of audio samples) is fixed for a given stream or +file. All audio samples for a single channel in a frame is referred to as a +block. In order to adapt to transient signals, each block can be divided +into recursive subblocks. Each subblock can be split into 2 smaller subblocks, +down to 1/32 of the original frame size. + + +Random access +------------- +Seeking is an important feature for any audio format. It allows the decoder to +jump forward or backward to the start of a frame without having to decode all +frames in between. In the ALS format, the encoder can optionally include +so called "random access" frames to achieve this goal. The ALS header +specifies a random access interval from 0 to 255. A value of 0 indicates no +random access frames, 1 means every frame is a random access frame, 2 means +every other frame, etc... Each set of frames between random access frames is +call a random access unit. The encoder indicates the size of each random +access unit by either writing them all in the header or by writing it at the +start of each random access frame. The ra_location field in the ALS header +tells which of the 2 locations are used. + +I'm going to go ahead and gripe here about this design. The problem I see is +that using random access frames is optional, and that there is no unique +identifier for frame boundaries. This prevents a decoder from finding random +frames without both a reference point and either random access information or +by decoding every frame between the reference and the destination. + + +Channels +-------- +ALS has 2 different ways of reducing redundancy between multiple channels. The +first method is joint stereo coding. The encoder calculates the difference +between 2 channels and selects 2 of left+right, left+diff, or right+diff. For +files with more than 2 channels, joint stereo can still be used by grouping the +channels into sets of pairs and individual channels. For example, encoding of +standard 5.1 audio could be done as L+R, C, LFE, LS+RS. The format allows for +reordering of the channels from their original positions in order to pair them +together if necessary. + +The 2nd method is called multi-channel correlation, or MCC. This method uses +adaptive subtraction to compare the prediction residual of reference channels +to the remaining channels. This is a more complex procedure which I will +descibe later once I fully understand the math behind it. + + +Forward Prediction +------------------ +The primary prediction method in ALS is forward linear predictive coding, or +LPC[4][5]. There are several ways to select good prediction coefficients. The +recommended method for ALS is Levinson-Durbin Recursion[6][7]. This is a good +method for 2 reasons. First of all, it sequentially produces higher order +coefficients, which is ideal for adapting the prediction order for each block. +Secondly, it produces parcor (reflection) coefficients as an intermediate +result, which are the values that are quantized and written to the ALS +bitstream. The standard defines a bit-exact method for transforming the +quantized parcor coefficients into the LPC coefficients used for linear +prediction. + +One of the unique features of the ALS format is that it uses progressively +increasing prediction orders for the first samples in random access frames, +which cannot reference previous samples. Other formats, such as FLAC, write the +first samples directly, then proceed with prediction using the full number of +coefficients. In ALS, the first sample is written directly, but each subsequent +sample is predicted using increasingly higher orders until the full prediction +order is reached. + + +Long-Term Prediction +-------------------- +Also called pitch coding, long-term prediction as implemented in ALS reduces +signal redundancy by predicting the value of an LPC residual sample using the +average value of 5 residual samples at a specified time lag with a specified +gain value. The optimal lag and gain values are determined for each frame by the +encoder. This is called pitch coding because the frequency, or pitch, of a +signal leads to periodic redundancy. If the period is calculated, it can be +exploited in order to remove that redundancy from the encoded output. This +algorithm is typically used in speech codecs, such as Speex. + + +RLSLMS (Recursive Least Squares, Least Mean Square) backward prediction +----------------------------------------------------------------------- +ALS has an alternative backward prediction mode, which uses the recursive least +squares algorithm[8]. + +Entropy Coding +-------------- +In ALS, both the prediction coefficients and the residual signal are compressed +using entropy coding. The encoder can choose between 2 different methods, +Golomb-Rice Coding[9] and Block Gilbert-Moore Coding (BGMC). Rice coding is a +form of Huffman coding, while BGMC, also called Shannon-Fano-Elias coding, is a +precursor of arithmetic coding. + + +Floating-Point Data +------------------- +The ALS format provides the ability to losslessly encode floating-point[10] +audio. The floating-point signal is basically broken down into an integer signal +plus the residual signal. The integer signal is encoded using the standard ALS +algorithm, while the residual is encoded using the Masked-Lempel-Ziv +dictionary-based compression scheme[11]. + + +References +---------- +[1] http://www.nue.tu-berlin.de/forschung/projekte/lossless/mp4als.html +[2] http://en.wikipedia.org/wiki/Audio_Lossless_Coding +[3] http://www.nue.tu-berlin.de/wer/liebchen/lpac.html +[4] http://en.wikipedia.org/wiki/Linear_predictive_coding +[5] http://en.wikipedia.org/wiki/Linear_prediction +[6] http://en.wikipedia.org/wiki/Levinson_recursion +[7] http://en.wikipedia.org/wiki/Autocorrelation +[8] http://en.wikipedia.org/wiki/Recursive_least_squares_filter +[9] http://en.wikipedia.org/wiki/Golomb_coding +[10] http://en.wikipedia.org/wiki/IEEE_floating-point_standard +[11] http://en.wikipedia.org/wiki/Dictionary_coder + + + +BITSTREAM FORMAT +================ + +ALS Header +---------- +In the raw ALS file format, the ALS header is located at the beginning of the +bitstream, and is transmitted only once. It contains information about the +audio and global properties of the encoded ALS bitstream. + +als_header() { + fixed_portion() 22 bytes + if(channel_config) { + ch_config 16 bits + } + if(channel_reorder) { + // number of bits used to code each channel position + ch_bits = max(1, ceil(log2(channels))) + for(i=0; i<channels; i++) { + channel_position[i] ch_bits + } + } + header_size 32 bits + trailer_size 32 bits + header() header_size + trailer() trailer_size +} + +The fixed portion of the ALS header is always 22 bytes long. The field layout is +given in Table 1. If the channel configuration flag is indicated, the +configuration data is written. The channel configuration data is currently not +used, and neither its purpose nor its format are given in the draft spec or in +the reference software. If the channel reorder flag is indicated, the channel +layout is written. The number of bits used to encode the position of each +channel is determined as the minimum number of bits needed to encode the +highest channel index. Next, the header size and trailer size (in bytes) are +written. These sizes are used by the decoder to read the original header and +trailer, which make up the last 2 fields of the ALS header. + +Table 1 : 22-byte fixed portion of the ALS header ++------------------------------------------------------------------------------+ +|bits |parameter |description | +|==========+==================+================================================| +|32 |magic number |"ALS\0" or 0x414C5300. Indicates that this is | +| | |an ALS file | +|----------+------------------+------------------------------------------------| +|32 |sample rate |Audio sampling frequency, e.g. 44100 | +|----------+------------------+------------------------------------------------| +|32 |samples |Total number of samples in the file | +|----------+------------------+------------------------------------------------| +|16 |channels |Number of channels - 1 | +|----------+------------------+------------------------------------------------| +|3 |file type |Type of the original audio file | +| | |0=raw/unknown 1=WAVE 2=AIFF | +|----------+------------------+------------------------------------------------| +|3 |resolution |Bits-per-sample/8 - 1 | +|----------+------------------+------------------------------------------------| +|1 |sample type |0=integer samples 1=floating-point samples | +|----------+------------------+------------------------------------------------| +|1 |source order |Source sample endianness 0=little 1=big | +|----------+------------------+------------------------------------------------| +|16 |frame size |Source frame size - 1 (measured in samples) | +|----------+------------------+------------------------------------------------| +|8 |random access |Random access frame interval 0=no RA frames | +|----------+------------------+------------------------------------------------| +|2 |ra location |Random access data location | +| | |0=none 1=frames 2=header | +|----------+------------------+------------------------------------------------| +|1 |adapt |Indicates use of adaptive LPC order | +|----------+------------------+------------------------------------------------| +|2 |coef table |Selects 1 of the 3 tables of Rice code | +| | |parameters used to encode parcor coefficients. | +| | |Selection is generally based on the sample rate.| +| | |3=use 7-bit quantizer instead of Rice coding. | +| | |See Tables 2, 3, and 4 | +|----------+------------------+------------------------------------------------| +|1 |long-term pred |Indicates use of long-term prediction | +|----------+------------------+------------------------------------------------| +|10 |max order |Maximum LPC order | +|----------+------------------+------------------------------------------------| +|2 |block switching |Indicates use of block switching and maximum | +| | |level of block division | +|----------+------------------+------------------------------------------------| +|1 |entropy coder |Type of entropy coder used 0=Rice 1=BGMC | +|----------+------------------+------------------------------------------------| +|1 |subblock part |Indicates partitioned entropy coding | +|----------+------------------+------------------------------------------------| +|1 |joint stereo |Indicates use of joint stereo coding | +|----------+------------------+------------------------------------------------| +|1 |mcc |Indicates use of multi-channel correlation | +|----------+------------------+------------------------------------------------| +|1 |channel config |Indicates presence of channel configuration | +|----------+------------------+------------------------------------------------| +|1 |channel reorder |Indicates presence of channel reordering | +|----------+------------------+------------------------------------------------| +|1 |has crc |Indicates presence of reference CRC checksum | +|----------+------------------+------------------------------------------------| +|1 |rlslms |Indicates use of RLSLMS backward prediction | +|----------+------------------+------------------------------------------------| +|5 |reserved |Not used | +|----------+------------------+------------------------------------------------| +|1 |aux enabled |Indicates presence of auxilliary data | ++------------------------------------------------------------------------------+ + +Table 2 : Coef table 0 : Rice code params for encoding of parcor coefficients + Recommended for 44kHz and 48kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-52 |4 | +|------------+-------+-----------| +|1 |-29 |5 | +|------------+-------+-----------| +|2 |-31 |4 | +|------------+-------+-----------| +|3 |19 |4 | +|------------+-------+-----------| +|4 |-16 |4 | +|------------+-------+-----------| +|5 |12 |3 | +|------------+-------+-----------| +|6 |-7 |3 | +|------------+-------+-----------| +|7 |9 |3 | +|------------+-------+-----------| +|8 |-5 |3 | +|------------+-------+-----------| +|9 |6 |3 | +|------------+-------+-----------| +|10 |-4 |3 | +|------------+-------+-----------| +|11 |3 |3 | +|------------+-------+-----------| +|12 |-3 |2 | +|------------+-------+-----------| +|13 |3 |2 | +|------------+-------+-----------| +|14 |-2 |2 | +|------------+-------+-----------| +|15 |3 |2 | +|------------+-------+-----------| +|16 |-1 |2 | +|------------+-------+-----------| +|17 |2 |2 | +|------------+-------+-----------| +|18 |-1 |2 | +|------------+-------+-----------| +|19 |2 |2 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + +Table 3 : Coef table 1 : Rice code params for encoding of parcor coefficients + Recommended for 96kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-58 |3 | +|------------+-------+-----------| +|1 |-42 |4 | +|------------+-------+-----------| +|2 |-46 |4 | +|------------+-------+-----------| +|3 |37 |5 | +|------------+-------+-----------| +|4 |-36 |4 | +|------------+-------+-----------| +|5 |29 |4 | +|------------+-------+-----------| +|6 |-29 |4 | +|------------+-------+-----------| +|7 |25 |4 | +|------------+-------+-----------| +|8 |-23 |4 | +|------------+-------+-----------| +|9 |20 |4 | +|------------+-------+-----------| +|10 |-17 |4 | +|------------+-------+-----------| +|11 |16 |4 | +|------------+-------+-----------| +|12 |-12 |4 | +|------------+-------+-----------| +|13 |12 |3 | +|------------+-------+-----------| +|14 |-10 |3 | +|------------+-------+-----------| +|15 |7 |3 | +|------------+-------+-----------| +|16 |-4 |3 | +|------------+-------+-----------| +|17 |3 |3 | +|------------+-------+-----------| +|18 |-1 |3 | +|------------+-------+-----------| +|19 |1 |3 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + +Table 4 : Coef table 2 : Rice code params for encoding of parcor coefficients + Recommended for 192kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-59 |3 | +|------------+-------+-----------| +|1 |-45 |5 | +|------------+-------+-----------| +|2 |-50 |4 | +|------------+-------+-----------| +|3 |38 |4 | +|------------+-------+-----------| +|4 |-39 |4 | +|------------+-------+-----------| +|5 |32 |4 | +|------------+-------+-----------| +|6 |-30 |4 | +|------------+-------+-----------| +|7 |25 |3 | +|------------+-------+-----------| +|8 |-23 |3 | +|------------+-------+-----------| +|9 |20 |3 | +|------------+-------+-----------| +|10 |-20 |3 | +|------------+-------+-----------| +|11 |16 |3 | +|------------+-------+-----------| +|12 |-13 |3 | +|------------+-------+-----------| +|13 |10 |3 | +|------------+-------+-----------| +|14 |-7 |3 | +|------------+-------+-----------| +|15 |3 |3 | +|------------+-------+-----------| +|16 |0 |3 | +|------------+-------+-----------| +|17 |-1 |3 | +|------------+-------+-----------| +|18 |2 |3 | +|------------+-------+-----------| +|19 |-1 |3 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + + +ALS Frame +--------- +if(RA is enabled, RA location is in frames, and current frame is an RA frame) { + * random access unit size, 32 bits +} +if(MCC is enabled) { + if(joint stereo is not enabled) { + * use MCC for this frame + } else { + * read 8 bits to determine if this frame uses MCC + seems only 1 bit should be needed. not sure what the other 7 bits are + used for... + } +} +if(MCC is not enabled and RLS-LMS is not enabled) { + for each channel or channel pair { + + * enabled coupled block switching if joint stereo is enabled, this is + the first channel in a pair, and this is not the last channel + + if(block switching is enabled) { + * read block switch flags (8-bit, 16-bit or 32-bit) + coupled block switching can be explicitly turned off here + } else { + * use only 1 subblock at full frame size + } + + if(coupled block switching is enabled) { + for each subblock { + * decode subblock for 1st channel in pair + * decode subblock for 2nd channel in pair + * restore original signal if one of the pair is difference signal + } + } else { + for each subblock { + * decode subblock. + * if coupled block switching is explicitly disabled for this, + pair, reconstruct the difference signal after reading the 2nd + channel in the pair. this is for use as predictor context for + the next frame. + } + } + } +} else if(RLS-LMS is enabled) { + TODO: complete this section +} else if(MCC is enabled) { + TODO: complete this section +} + +Block switch flags +------------------ +The block switch value in the header indicates the number of flag bits that are +contained in each block. If all 32 bits are not used, the flag bits are left +aligned in a 32-bit integer. This 32-bit integer making up the block switch +flags is treated as an array of 1-bit values containing a binary tree. Index 0 +(the high bit) indicates if channel coupling is turned off in order to do +independent block switching. The root node is located at index 1. The layout +follows the standard binary-tree-in-array implementation. For a node at index i, +the parent node is at i/2, the first child is at i*2, and the second child is at +i*2+1. If a node has a value of 1, the corresponding subblock is split into 2 +smaller equal-sized subblocks. If a node has a value of 0, the subblock is not +split. The smallest subblock size is 1/32 of the original frame size. For the +last frame in the stream, which may be smaller than all the other frames, the +subblocks are divided as if it were a full-size frame, but only the number of +subblocks which are needed to fit the final number of samples are used, with +the last subblock being truncated if needed. + + +ALS Subblock +------------ +* align bitstream to 8-bit boundary +* 1-bit frame type. 0=zero or constant, 1=normal +if(frame type is zero or constant) { + * 1-bit frame type. 0=zero, 1=constant +} +* 1-bit difference flag indicates if this subblock contains a normal + signal or a difference signal. +if(frame type is constant) { + * align bitstream to 8-bit boundary + * read 1 sample. size based on sample resolution in the ALS header. +} else if(frame type is normal) { + // determine entropy partitioning and read entropy coding parameters + if(coding type is Rice) { + if(entropy partitioning is enabled) { + * 1-bit partition flag. 0=1 partition, 1=4 partitions + } else { + * only 1 partition + } + * read 1st Rice parameter (4-bit if depth<=16-bit, 5-bit if >16-bit) + if(partitioning is enabled) { + * read 3 remaining delta-encoded Rice parameters. deltas are Rice + encoded using parameter=0. + } + } else if(coding type is BGMC) { + if(entropy partitioning is enabled) { + * 2-bit partition order. 2^x partitions (1, 2, 4, or 8) + } else { + * 1-bit partition flag. 0=1 partition, 1=4 partitions + } + * read 1st BGMC parameter (8-bit if depth<=16-bit, 9-bit if >16-bit) + * read remaining delta-encoded Rice parameters. deltas are Rice + encoded using parameter=2. + * separate grouped BGMC parameters: + s = p >> 4 + sx = p & 0x0F + } + // shift (unused LSB's) + * read 1-bit shift flag + if(shift flag) { + * read 4-bit shift value, add 1. this is the number of unused LSB's. + } + // decode and reconstruct LPC coefficients + if(using LPC prediction [not RLS-LMS]) { + // determine LPC order + * order = fixed/max prediction order (from ALS header) + if(adaptive prediction order is used) { + * limit max order to range [1 ... (subblock size / 8) - 1] + * read order for this subblock using number of bits required to + store max order. + } + // decode quantized coefficients + if(not using a coefficient table [ct=3]) { + * read each quantized coefficient as 7-bit value - 64 + } else { + * read quantized coefficients from bitstream using rice params from + the coefficient table. + * apply the offsets from the coefficient table + } + // reconstruct parcor coefficients + * reconstruct 1st coefficient from the quantized coefficient using the + scale parcor coefficient formula below: + where qc has a range of -64 to 63, + coeff = 32 + ((qc+64)*(qc+65)*128) - (1 << 20) + * reconstruct the 2nd coefficient the same way, then reverse the sign. + * reconstruct remaining coefficients using + coeff = (qc << (Q-6)) + (1 << (Q-7)), where Q=20 + = (qc << 14) + (1 << 13) + = (qc * 16384) + 8192 + } else if(using RLS-LMS) { + * order = 10 + } + if(using LTP) { + // decode 5 LTP coefficients and lag + c0 = signed rice code (rp=1) + c1 = signed rice code (rp=2) + c2 = unsigned rice code (rp=2) + c3 = signed rice code (rp=2) + c4 = signed rice code (rp=1) + lag = x-bit unsigned value, where x = 8 + (samplerate / 96000) + } + // decode residual for this subblock + if(no random access for this frame) { + for(each entropy coding partition) { + if(coding type is Rice) + * decode residual for partition using Rice parameters + if(coding type is BGMC) + * decode residual for partition using BGMC parameters + } + } else { + // in RA frames, first residual values are larger because they are + // progressively predicted, so a different entropy coding is used in + // order to encode more efficiently + * decode up to 3 residuals separately, up to prediction order. + r0 = signed rice code (rp=bitdepth-4 [e.g. 16-4=12]) + r1 = signed rice code (rp=1st rice parameter + 3 [max=31]) + r2 = signed rice code (rp=1st rice parameter + 1 [max=31]) + this will make the 1st partition shorter + for(each entropy coding partition) { + if(coding type is Rice) + * decode residual for partition using Rice parameters + if(coding type is BGMC) + * decode residual for partition using BGMC parameters + } + } +} +if(using RLS-LMS prediction) { + // TODO: RLS-LMS parameter decoding +} +if(using MCC) { + // TODO: decode MCC reference channels and weighting factors +} + + +Reconstructing the signal (LPC mode, no MCC) +-------------------------------------------- +When LPC is used, each subblock contains its own set of LPC coefficients. +After the residual has been decoded, the signal can be reconstructed using +inverse linear prediction. When decoding the 1st subblock of a random access +frame, progressive linear prediction is used because of the lack of access to +previous "warm-up" samples. + +if(frame type is zero) { + * set all samples for the subblock to zero +} else if(frame type is constant) { + * set all samples for the subblock to previously decoded constant value +} else if(frame type is normal) { + * temporarily apply shift to warm-up samples from previous block + if(using LTP) { + * reconstruct final residual by reversing LTP + } + if(not a random access frame) { + * convert parcor coefficients to LPC coefficients using pseudo-code + below. keep in mind the need to avoid integer data type overflow. + for(m=0; m<pred_order; m++) { + for(i=0; i<m/2; i++) { + temp = lpc[ i] + (((par[m] * lpc[m-i]) + (1<<19)) >> 20); + temp2 = lpc[m-i] + (((par[m] * lpc[ i]) + (1<<19)) >> 20); + lpc[m-i] = temp2; + lpc[ i] = temp; + } + lpc[m] = par[m]; + } + * inverse linear prediction using code below + note that samples below index 0 are from the previous subblock + for(each sample, at index n, in the subblock) { + sum = 0; + for(i=0; i<pred_order; i++) + sum += lpc[i] * signal[n-i-1]; + signal[n] = residual[n] - ((sum + (1 << 19)) >> 20); + } + } else if(random access frame) { + // TODO: RA inverse LPC (progressive prediction) + } + * undo shift from warm-up samples and block samples +} + + +TODO: Reconstructing the signal (RLS-LMS mode) + +TODO: Reconstructing the signal (MCC mode) Added: src/COPYING =================================================================== --- src/COPYING (rev 0) +++ src/COPYING 2007-08-20 00:13:31 UTC (rev 4) @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + Added: src/Makefile =================================================================== --- src/Makefile (rev 0) +++ src/Makefile 2007-08-20 00:13:31 UTC (rev 4) @@ -0,0 +1,37 @@ +## +# Makefile for Decals +## + +include config.mak + +LDFLAGS = +LIBOBJS = +LIBS = -lm + +PROGS = decals$(EXEEXT) + +decals_OBJS = alsdec.o bitreader.o main.o +decals_SRCS = $(alsdec_OBJS:.o=.c) +decals_LDFLAGS = + +all: dep $(PROGS) + +.c.o: + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -c $< + +decals$(EXEEXT): $(decals_OBJS) + $(CC) $(CFLAGS) -o $@ $(decals_LDFLAGS) $(decals_OBJS) $(LIBOBJS) $(LIBS) + +clean: + $(RM) decals$(EXEEXT) *.o .depend + +dep: depend + +depend: .depend + +.depend: $(decals_SRCS) + $(CC) -MM $(CFLAGS) $^ 1>.depend + +ifneq ($(wildcard .depend),) +include .depend +endif Added: src/alsdec.c =================================================================== --- src/alsdec.c (rev 0) +++ src/alsdec.c 2007-08-20 00:13:31 UTC (rev 4) @@ -0,0 +1,708 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * internal frame buffering is from FFmpeg/libavcodec/flac.c + * Copyright (c) 2003 Alex Bergszaszi + * fast_realloc() is from FFmpeg/libavcodec/utils.c + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alsdec.c + * ALS decoder + */ + +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "bitreader.h" +#include "alsdec.h" +#include "alstab.h" + +static void * +fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) +{ + if(min_size < *size) + return ptr; + + *size = MAX(17*min_size/16 + 32, min_size); + + return realloc(ptr, *size); +} + +static int +read_als_header(AlsDecodeContext *ctx) +{ + int magic; + + // read header fields from bitstream + magic = get_bits(&ctx->gbc, 32); + ctx->sample_rate = get_bits(&ctx->gbc, 32); + ctx->samples = get_bits(&ctx->gbc, 32); + ctx->channels = get_bits(&ctx->gbc, 16) + 1; + ctx->file_type = get_bits(&ctx->gbc, 3); + ctx->bps = get_bits(&ctx->gbc, 3) * 8 + 8; + ctx->sample_type = get_bits1(&ctx->gbc); + ctx->source_order = get_bits1(&ctx->gbc); + ctx->frame_size = get_bits(&ctx->gbc, 16) + 1; + ctx->random_access = get_bits(&ctx->gbc, 8); + ctx->ra_location = get_bits(&ct... [truncated message content] |
From: <jb...@us...> - 2007-08-20 00:12:42
|
Revision: 3 http://decals.svn.sourceforge.net/decals/?rev=3&view=rev Author: jbr79 Date: 2007-08-19 17:12:41 -0700 (Sun, 19 Aug 2007) Log Message: ----------- revert initial import Removed Paths: ------------- Makefile alsdec.c alsdec.h alstab.h bitreader.c bitreader.h bswap.h common.h config.h config.mak main.c mp4-als_format_notes.txt Deleted: Makefile =================================================================== --- Makefile 2007-08-20 00:08:12 UTC (rev 2) +++ Makefile 2007-08-20 00:12:41 UTC (rev 3) @@ -1,37 +0,0 @@ -## -# Makefile for Decals -## - -include config.mak - -LDFLAGS = -LIBOBJS = -LIBS = -lm - -PROGS = decals$(EXEEXT) - -decals_OBJS = alsdec.o bitreader.o main.o -decals_SRCS = $(alsdec_OBJS:.o=.c) -decals_LDFLAGS = - -all: dep $(PROGS) - -.c.o: - $(CC) -DHAVE_CONFIG_H $(CFLAGS) -c $< - -decals$(EXEEXT): $(decals_OBJS) - $(CC) $(CFLAGS) -o $@ $(decals_LDFLAGS) $(decals_OBJS) $(LIBOBJS) $(LIBS) - -clean: - $(RM) decals$(EXEEXT) *.o .depend - -dep: depend - -depend: .depend - -.depend: $(decals_SRCS) - $(CC) -MM $(CFLAGS) $^ 1>.depend - -ifneq ($(wildcard .depend),) -include .depend -endif Deleted: alsdec.c =================================================================== --- alsdec.c 2007-08-20 00:08:12 UTC (rev 2) +++ alsdec.c 2007-08-20 00:12:41 UTC (rev 3) @@ -1,708 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * internal frame buffering is from FFmpeg/libavcodec/flac.c - * Copyright (c) 2003 Alex Bergszaszi - * fast_realloc() is from FFmpeg/libavcodec/utils.c - * Copyright (c) 2001 Fabrice Bellard - * Copyright (c) 2002-2004 Michael Niedermayer - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file alsdec.c - * ALS decoder - */ - -#include "common.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -#include "bitreader.h" -#include "alsdec.h" -#include "alstab.h" - -static void * -fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) -{ - if(min_size < *size) - return ptr; - - *size = MAX(17*min_size/16 + 32, min_size); - - return realloc(ptr, *size); -} - -static int -read_als_header(AlsDecodeContext *ctx) -{ - int magic; - - // read header fields from bitstream - magic = get_bits(&ctx->gbc, 32); - ctx->sample_rate = get_bits(&ctx->gbc, 32); - ctx->samples = get_bits(&ctx->gbc, 32); - ctx->channels = get_bits(&ctx->gbc, 16) + 1; - ctx->file_type = get_bits(&ctx->gbc, 3); - ctx->bps = get_bits(&ctx->gbc, 3) * 8 + 8; - ctx->sample_type = get_bits1(&ctx->gbc); - ctx->source_order = get_bits1(&ctx->gbc); - ctx->frame_size = get_bits(&ctx->gbc, 16) + 1; - ctx->random_access = get_bits(&ctx->gbc, 8); - ctx->ra_location = get_bits(&ctx->gbc, 2); - ctx->adapt_order = get_bits1(&ctx->gbc); - ctx->coef_table = get_bits(&ctx->gbc, 2); - ctx->ltp = get_bits1(&ctx->gbc); - ctx->pred_order = get_bits(&ctx->gbc, 10); - ctx->blksw = get_bits(&ctx->gbc, 2); - ctx->coding_type = get_bits1(&ctx->gbc); - ctx->coding_part = get_bits1(&ctx->gbc); - ctx->joint_stereo = get_bits1(&ctx->gbc); - ctx->mcc = get_bits1(&ctx->gbc); - ctx->ch_config = get_bits1(&ctx->gbc); - ctx->ch_reorder = get_bits1(&ctx->gbc); - ctx->has_crc = get_bits1(&ctx->gbc); - ctx->rlslms = get_bits1(&ctx->gbc); - get_bits(&ctx->gbc, 5); - ctx->has_aux = get_bits1(&ctx->gbc); - - // check for validity - if(magic != 0x414C5300) { - fprintf(stderr, "ALS header not found\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->sample_rate == 0) { - fprintf(stderr, "invalid ALS header: sample rate cannot be 0\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->samples == 0) { - fprintf(stderr, "invalid ALS header: sample count cannot be 0\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->file_type > 2) { - fprintf(stderr, "invalid ALS header: unknown file type: %d\n", - ctx->file_type); - return ALS_ERROR_GENERAL; - } - if(ctx->bps > 32) { - fprintf(stderr, "invalid ALS header: reserved bit depth: %d \n", - ctx->bps); - return ALS_ERROR_GENERAL; - } - if(ctx->coef_table == 3) { - fprintf(stderr, "invalid ALS header: invalid coefficient table: 3\n"); - return ALS_ERROR_GENERAL; - } - - // calculate frame count - ctx->last_samples = ctx->samples % ctx->frame_size; - ctx->frames = ctx->samples / ctx->frame_size; - if(ctx->last_samples) - ctx->frames++; - - // calculate bits for channel index - ctx->bpc = MAX(1, ceil(LOG2(ctx->channels))); - - // calculate random access frame count - if(ctx->random_access) { - ctx->ra_units = ctx->frames / ctx->random_access; - if(ctx->frames % ctx->random_access) - ctx->ra_units++; - ctx->ra_index = 0; - } - - // calculate block switch flag bits - if(ctx->blksw) - ctx->blksw = 1 << (ctx->blksw + 2); - - return ALS_OK; -} - -static int -read_channel_order(AlsDecodeContext *ctx, FILE *fp) -{ - GetBitContext gbc; - uint8_t *buf; - int i, size; - - ctx->ch_pos = calloc(ctx->channels, 1); - if(!ctx->ch_pos) - return ALS_ERROR_MEMORY; - size = ((ctx->bpc * ctx->channels) + 7) / 8; - buf = calloc(1, size); - if(!buf) - return ALS_ERROR_MEMORY; - if(fread(buf, 1, size, fp) != size) - return ALS_ERROR_EOF; - init_get_bits(&gbc, buf, size * 8); - - for(i=0; i<ctx->channels; i++) { - ctx->ch_pos[i] = get_bits(&gbc, ctx->bpc); - } - free(buf); - return ALS_OK; -} - -int -als_decode_init(AlsDecodeContext *ctx, FILE *fp) -{ - uint8_t buf[22]; - int i, ret; - - memset(ctx, 0, sizeof(*ctx)); - - // ALS header - if(fread(buf, 1, 22, fp) != 22) - return ALS_ERROR_EOF; - init_get_bits(&ctx->gbc, buf, 176); - ret = read_als_header(ctx); - if(ret) - return ret; - - // channel configuration (unused) - if(ctx->ch_config) - if(fread(buf, 2, 1, fp) != 1) - return ALS_ERROR_EOF; - - // channel reordering - if(ctx->ch_reorder) { - ret = read_channel_order(ctx, fp); - if(ret) - return ret; - } - - // source file header and trailer - if(fread(&ctx->header_size, 1, 4, fp) != 4) - return ALS_ERROR_EOF; - ctx->header_size = be2me_32(ctx->header_size); - if(fread(&ctx->trailer_size, 1, 4, fp) != 4) - return ALS_ERROR_EOF; - ctx->trailer_size = be2me_32(ctx->trailer_size); - if(ctx->header_size > 0) { - ctx->header = calloc(ctx->header_size, 1); - if(!ctx->header) - return ALS_ERROR_MEMORY; - if(fread(ctx->header, 1, ctx->header_size, fp) != ctx->header_size) - return ALS_ERROR_EOF; - } - if(ctx->trailer_size > 0) { - ctx->trailer = calloc(ctx->trailer_size, 1); - if(!ctx->trailer) - return ALS_ERROR_MEMORY; - if(fread(ctx->trailer, 1, ctx->trailer_size, fp) != ctx->trailer_size) - return ALS_ERROR_EOF; - } - - // CRC-32 - if(ctx->has_crc) { - if(fread(&ctx->ref_crc, 1, 4, fp) != 4) - return ALS_ERROR_EOF; - ctx->ref_crc = be2me_32(ctx->ref_crc); - ctx->crc = 0xFFFFFFFF; - } - - // random access units - if(ctx->random_access) { - ctx->ra_sizes = calloc(ctx->ra_units, sizeof(uint32_t)); - if(!ctx->ra_sizes) - return ALS_ERROR_MEMORY; - if(ctx->ra_location == RA_LOCATION_HEADER) { - if(fread(ctx->ra_sizes, 4, ctx->ra_units, fp) != ctx->ra_units) - return ALS_ERROR_EOF; - for(i=0; i<ctx->ra_units; i++) { - ctx->ra_sizes[i] = be2me_32(ctx->ra_sizes[i]); - } - } - } - - // auxilliary data - if(ctx->has_aux) { - if(fread(&ctx->aux_size, 1, 4, fp) != 4) - return ALS_ERROR_EOF; - ctx->aux_size = be2me_32(ctx->aux_size); - ctx->aux = calloc(1, ctx->aux_size); - if(!ctx->aux) - return ALS_ERROR_MEMORY; - if(fread(ctx->aux, 1, ctx->aux_size, fp) != ctx->aux_size) - return ALS_ERROR_EOF; - } - - // allocate blocks - /*ctx->frame.blocks = calloc(ctx->channels, sizeof(AlsBlock)); - if(!ctx->frame.blocks) - return ALS_ERROR_MEMORY;*/ - - // allocated decoded audio - ctx->decoded = calloc(ctx->channels, sizeof(int32_t *)); - for(i=0; i<ctx->channels; i++) { - ctx->decoded[i] = calloc(ctx->frame_size, sizeof(int32_t)); - } - - // allocate buffer - ctx->max_frame_bytes = (ctx->channels * ctx->bps * ctx->frame_size + 7) / 8; - ctx->bitstream = fast_realloc(ctx->bitstream, - &ctx->allocated_bitstream_size, - ctx->max_frame_bytes); - - return ALS_OK; -} - -/** - * Parses block switch flags to determine subblock count and sizes. - * @return Returns the number of subblocks - */ -static int -parse_subblock_sizes(uint32_t flags, int fs, int sub_sizes[32]) -{ - int b; - int i, j, k, l, m, n; - int sh; - uint8_t lvl[5][16]; - - // parse flags into binary tree - sh = 30; - for(l=0; l<5; l++) { - n = 1 << l; - for(i=0; i<n; i++) { - lvl[l][i] = (flags >> sh) & 1; - sh--; - } - } - - // traverse binary tree to determine subblock count and sizes - b = 0; - l = 0; // level 0 - if(!lvl[l][0]) { - sub_sizes[b++] = fs; - } else { - for(i=0; i<2; i++) { - l = 1; // level 1 - if(!lvl[l][i]) { - sub_sizes[b++] = fs >> l; - } else { - for(j=0; j<2; j++) { - l = 2; // level 2 - if(!lvl[l][j]) { - sub_sizes[b++] = fs >> l; - } else { - for(k=0; k<2; k++) { - l = 3; // level 3 - if(!lvl[l][k]) { - sub_sizes[b++] = fs >> l; - } else { - for(m=0; m<2; m++) { - l = 4; // level 4 - if(!lvl[l][m]) { - sub_sizes[b++] = fs >> l; - } else { - l = 5; // level 5 - sub_sizes[b++] = fs >> l; - sub_sizes[b++] = fs >> l; - } - } - } - } - } - } - } - } - } - - // return number of subblocks - return b; -} - -static int -decode_subblock(AlsDecodeContext *ctx, int ch, int sb) -{ - int i; - int sb_size = ctx->frame.subblock_sizes[sb]; - fprintf(stderr, "channel=%d subblock=%d\n", ch, sb); - - align_get_bits(&ctx->gbc); - if(get_bits1(&ctx->gbc)) { - ctx->frame.block_type = BLOCK_TYPE_NORMAL; - } else { - if(get_bits1(&ctx->gbc)) - ctx->frame.block_type = BLOCK_TYPE_CONSTANT; - else - ctx->frame.block_type = BLOCK_TYPE_ZERO; - } - /*ctx->frame.block_type = get_bits(&ctx->gbc, 2); - if(ctx->frame.block_type == 3) - ctx->frame.block_type = BLOCK_TYPE_NORMAL;*/ - fprintf(stderr, "block type: "); - switch(ctx->frame.block_type) { - case BLOCK_TYPE_ZERO: fprintf(stderr, "ZERO\n"); break; - case BLOCK_TYPE_CONSTANT: fprintf(stderr, "CONSTANT\n"); break; - case BLOCK_TYPE_NORMAL: fprintf(stderr, "NORMAL\n"); break; - } - ctx->frame.diff_flag = get_bits1(&ctx->gbc); - fprintf(stderr, "difference signal: %s\n", ctx->frame.diff_flag?"yes":"no"); - - if(ctx->frame.block_type == BLOCK_TYPE_CONSTANT) { - align_get_bits(&ctx->gbc); - get_bits(&ctx->gbc, ctx->bps); - } else if(ctx->frame.block_type == BLOCK_TYPE_NORMAL) { - if(ctx->coding_type == CODING_TYPE_RICE) { - // determine entropy partitioning - ctx->frame.ec_part = 1; - if(ctx->coding_part && get_bits1(&ctx->gbc)) - ctx->frame.ec_part = 4; - fprintf(stderr, "ec partitions: %d\n", ctx->frame.ec_part); - - // read Rice parameters for each partition - ctx->frame.rice_params[0] = get_bits(&ctx->gbc, 4+(ctx->bps>16)); - for(i=1; i<ctx->frame.ec_part; i++) { - ctx->frame.rice_params[i] = ctx->frame.rice_params[i-1]; - ctx->frame.rice_params[i] += get_rice(&ctx->gbc, 0); - } - fprintf(stderr, "rice params:"); - for(i=0; i<ctx->frame.ec_part; i++) { - fprintf(stderr, " %d", ctx->frame.rice_params[i]); - } - fprintf(stderr, "\n"); - } else if(ctx->coding_type == CODING_TYPE_BGMC) { - // determine entropy partitioning - if(ctx->coding_part) { - ctx->frame.ec_part = 1 << get_bits(&ctx->gbc, 2); - } else if(get_bits1(&ctx->gbc)) { - ctx->frame.ec_part = 4; - } - - // read BGMC parameters for each partition - ctx->frame.bgmc_rice[0] = get_bits(&ctx->gbc, 8+(ctx->bps>16)); - for(i=1; i<ctx->frame.ec_part; i++) { - ctx->frame.bgmc_rice[i] = ctx->frame.rice_params[i-1]; - ctx->frame.bgmc_rice[i] += get_rice(&ctx->gbc, 2); - } - - // separate grouped BGMC parameters - for(i=1; i<ctx->frame.ec_part; i++) { - ctx->frame.bgmc_freq[i] = ctx->frame.bgmc_rice[i] & 0x0F; - ctx->frame.bgmc_rice[i] >>= 4; - } - } - - // shift for unused LSB's - ctx->frame.lsb_shift = get_bits1(&ctx->gbc); - if(ctx->frame.lsb_shift) - ctx->frame.lsb_shift += get_bits(&ctx->gbc, 4); - fprintf(stderr, "shift: %d\n", ctx->frame.lsb_shift); - - // decode LPC coefficients - if(!ctx->rlslms) { - // determine LPC order - int p = ctx->pred_order; - if(ctx->adapt_order) { - int max_order = CLIP(p, 1, (sb_size>>3)-1); - int obits = MAX(1, ceil(LOG2(max_order))); - p = get_bits(&ctx->gbc, obits); - } - ctx->frame.pred_order = p; - fprintf(stderr, "lpc order: %d\n", p); - - // decode quantized coefficients - if(ctx->coef_table == 3) { - for(i=0; i<p; i++) { - ctx->frame.parcor_coefs[i] = get_bits(&ctx->gbc, 7) - 64; - } - } else { - const ParcorVars *pv = parcor_vars[ctx->coef_table]; - i = 0; - for(; i<MIN(p, 20); i++) { - ctx->frame.parcor_coefs[i] = pv[i].offset + get_rice(&ctx->gbc, pv[i].param); - } - for(; i<MIN(p, 127); i++) { - ctx->frame.parcor_coefs[i] = (i & 1) + get_rice(&ctx->gbc, 2); - } - for(; i<p; i++) { - ctx->frame.parcor_coefs[i] = get_rice(&ctx->gbc, 1); - } - } - fprintf(stderr, "qpar:"); - for(i=0; i<p; i++) { - fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); - } - fprintf(stderr, "\n"); - - // compute scaled parcor coefficients - for(i=0; i<p; i++) { - int qc = ctx->frame.parcor_coefs[i]; - int coef; - if(i < 2) { - coef = 32 + ((qc + 64) * (qc + 65) << 7) - (1 << 20); - if(i == 2) - coef = -coef; - } else { - coef = (qc << 14) + (1 << 13); - } - ctx->frame.parcor_coefs[i] = coef; - } - fprintf(stderr, "par:"); - for(i=0; i<p; i++) { - fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); - } - fprintf(stderr, "\n"); - } else { - // default prediction order for RLS-LMS - ctx->frame.pred_order = 10; - } - - // no LTP - - // decode residual - if(ctx->frame.is_ra_frame && sb == 0) { - // get residual signal, random access - int j, prog; - - prog = MIN(3, ctx->frame.pred_order); - if(prog > 0) - get_rice(&ctx->gbc, ctx->bps-4); - if(prog > 1) - get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+3, 31)); - if(prog > 2) - get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+1, 31)); - - if(ctx->coding_type == CODING_TYPE_RICE) { - int part_size = sb_size / ctx->frame.ec_part; - for(j=0; j<part_size-prog; j++) { - get_rice(&ctx->gbc, ctx->frame.rice_params[0]); - } - for(i=1; i<ctx->frame.ec_part; i++) { - for(j=0; j<part_size; j++) { - get_rice(&ctx->gbc, ctx->frame.rice_params[i]); - } - } - } else if(ctx->coding_type == CODING_TYPE_BGMC) { - fprintf(stderr, "BGMC decoding unsupported\n"); - return ALS_ERROR_GENERAL; - } - } else { - // get residual signal, no random access - int j; - if(ctx->coding_type == CODING_TYPE_RICE) { - int part_size = sb_size / ctx->frame.ec_part; - fprintf(stderr, "partition size: %d\n", part_size); - for(i=0; i<ctx->frame.ec_part; i++) { - fprintf(stderr, "res[%d]:", i); - for(j=0; j<part_size; j++) { - int r = get_rice(&ctx->gbc, ctx->frame.rice_params[i]); - fprintf(stderr, " %d", r); - } - fprintf(stderr, "\n"); - } - } else if(ctx->coding_type == CODING_TYPE_BGMC) { - fprintf(stderr, "BGMC decoding unsupported\n"); - return ALS_ERROR_GENERAL; - } - } - } - - // no RLS-LMS - - // no MCC - - return ALS_OK; -} - -static int -decode_single_block(AlsDecodeContext *ctx, int ch) -{ - int sb; - - ctx->frame.coupled_block = 0; - ctx->frame.num_subblocks = 1; - ctx->frame.subblock_sizes[0] = ctx->frame_size; - if(ctx->frame_index == ctx->frames) - ctx->frame.subblock_sizes[0] = ctx->last_samples; - - for(sb=0; sb<ctx->frame.num_subblocks; sb++) { - decode_subblock(ctx, ch, sb); - } - - return ALS_OK; -} - -static int -decode_joint_block(AlsDecodeContext *ctx, int ch0) -{ - int ch1 = ch0 + 1; - return ALS_OK; -} - -static int -decode_frame(AlsDecodeContext *ctx, int alloc_data_size) -{ - int ch; - - // read random access unit size - ctx->frame.is_ra_frame = 0; - if(ctx->random_access) { - ctx->frame.is_ra_frame = !(ctx->frame_index % ctx->random_access); - if(ctx->frame.is_ra_frame && ctx->ra_location == RA_LOCATION_FRAME) { - ctx->ra_sizes[ctx->ra_index] = get_bits(&ctx->gbc, 32); - } - } - - // determine if MCC is used - ctx->frame.use_mcc = 0; - if(ctx->mcc) { - if(ctx->joint_stereo) - ctx->frame.use_mcc = get_bits(&ctx->gbc, 8); - else - ctx->frame.use_mcc = 1; - } - - // currently unsupported features - if(ctx->frame.use_mcc) { - fprintf(stderr, "MCC unsupported\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->joint_stereo) { - fprintf(stderr, "Joint Stereo unsupported\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->blksw) { - fprintf(stderr, "Block Switching unsupported\n"); - return ALS_ERROR_GENERAL; - } - if(ctx->rlslms) { - fprintf(stderr, "RLS-LMS unsupported\n"); - return ALS_ERROR_GENERAL; - } - - for(ch=0; ch<ctx->channels; ch++) { - decode_single_block(ctx, ch); - } - - // increment indices - if(ctx->frame.is_ra_frame) { - ctx->ra_index++; - } - ctx->frame_index++; - - return ALS_OK; -} - -int -als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, - uint8_t *buf, int buf_size) -{ - int input_buf_size = 0; - int32_t *samples = data; - int alloc_data_size = *data_size; - int frame_size; - int i, ch; - - *data_size = 0; - - assert(ctx->max_frame_bytes > 0); - - fprintf(stderr, "decoding frame %d\n", ctx->frame_index); - - // copy input bytes to internal buffer - buf_size = MAX(MIN(buf_size, ctx->max_frame_bytes - ctx->bitstream_size), 0); - input_buf_size = buf_size; - if(ctx->bitstream_index + ctx->bitstream_size + buf_size > ctx->allocated_bitstream_size) { - memmove(ctx->bitstream, &ctx->bitstream[ctx->bitstream_index], ctx->bitstream_size); - ctx->bitstream_index = 0; - } - memcpy(&ctx->bitstream[ctx->bitstream_index + ctx->bitstream_size], buf, buf_size); - buf = &ctx->bitstream[ctx->bitstream_index]; - ctx->bitstream_size += buf_size; - if(ctx->bitstream_size < ctx->max_frame_bytes) { - // need more data - if(ctx->frame_index != ctx->frames-1) { - fprintf(stderr, "need more data...\n"); - return input_buf_size; - } - } - init_get_bits(&ctx->gbc, buf, ctx->bitstream_size*8); - - // decode ALS frame to ctx->decoded - if(decode_frame(ctx, alloc_data_size)) { - fprintf(stderr, "decode_frame() failed\n"); - ctx->bitstream_size = 0; - ctx->bitstream_index = 0; - return -1; - } - fprintf(stderr, "\n"); - - if(ctx->frame_index == ctx->frames) - frame_size = ctx->last_samples; - else - frame_size = ctx->frame_size; - - // copy/interleave ctx->decoded to samples - for(i=0; i<frame_size; i++) { - for(ch=0; ch<ctx->channels; ch++) { - *(samples++) = ctx->decoded[ch][i]; - } - } - - *data_size = (int8_t *)samples - (int8_t *)data; - - i = (get_bits_count(&ctx->gbc) + 7) / 8; - if(i > buf_size) { - fprintf(stderr, "frame size too large (max_frame_bytes too low)\n"); - ctx->bitstream_size = 0; - ctx->bitstream_index = 0; - return -1; - } - - if(ctx->bitstream_size) { - ctx->bitstream_index += i; - ctx->bitstream_size -= i; - return input_buf_size; - } else { - return i; - } -} - -int -als_decode_close(AlsDecodeContext *ctx) -{ - int i; - if(ctx) { - if(ctx->ch_pos) - free(ctx->ch_pos); - if(ctx->header) - free(ctx->header); - if(ctx->trailer) - free(ctx->trailer); - if(ctx->ra_sizes) - free(ctx->ra_sizes); - if(ctx->aux) - free(ctx->aux); - //if(ctx->frame.blocks) - // free(ctx->frame.blocks); - if(ctx->decoded) { - for(i=0; i<ctx->channels; i++) { - if(ctx->decoded[i]) - free(ctx->decoded[i]); - } - free(ctx->decoded); - } - if(ctx->bitstream) - free(ctx->bitstream); - } - return ALS_OK; -} Deleted: alsdec.h =================================================================== --- alsdec.h 2007-08-20 00:08:12 UTC (rev 2) +++ alsdec.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,170 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file alsdec.h - * ALS decoder header - */ - -#ifndef ALSDEC_H -#define ALSDEC_H - -#include "common.h" - -#include <stdio.h> -#include <string.h> - -#include "bitreader.h" - -enum { - ALS_OK = 0, - ALS_ERROR_GENERAL = -1, - ALS_ERROR_MEMORY = -2, - ALS_ERROR_EOF = -3 -} AlsError; - -enum { - FILE_TYPE_RAW = 0, - FILE_TYPE_WAVE = 1, - FILE_TYPE_AIFF = 2 -} FileType; - -enum { - SAMPLE_TYPE_INT = 0, - SAMPLE_TYPE_FLOAT = 1 -} SampleType; - -enum { - SRC_ORDER_LE = 0, - SRC_ORDER_BE = 1 -} SourceOrder; - -enum { - RA_LOCATION_NONE = 0, - RA_LOCATION_FRAME = 1, - RA_LOCATION_HEADER = 2 -} RaLocation; - -enum { - CODING_TYPE_RICE = 0, - CODING_TYPE_BGMC = 1 -} CodingType; - -enum { - BLOCK_TYPE_ZERO = 0, - BLOCK_TYPE_CONSTANT, - BLOCK_TYPE_NORMAL -} BlockType; - -typedef struct { - /* frame */ - int is_ra_frame; ///< flag is on if current frame is an RA frame - int use_mcc; ///< flag is on if current frame uses MCC - - /* block */ - int num_subblocks; ///< number of subblocks for the current block - int subblock_sizes[32]; ///< list containing the size of each subblock - int coupled_block; ///< indicates if this is a coupled block - - /* subblock */ - int block_type; ///< indicates normal, zero, or constant block type - int diff_flag; ///< for zero and constant blocks, indicates if the - ///< block contains a difference signal or a normal - ///< signal - int ec_part; ///< number of entropy coding partitions - int rice_params[4]; ///< Rice parameters for each partition - int bgmc_rice[8]; ///< for BGMC, Rice parameters for coding tail - int bgmc_freq[8]; ///< for BGMC, frequency indices for coding MSB - int lsb_shift; ///< optional shift level for unused LSB's - int pred_order; ///< current prediction order - int parcor_coefs[1023]; ///< decoded parcor coefficients -} AlsFrame; - -typedef struct { - - GetBitContext gbc; - - /* from ALS header */ - uint32_t sample_rate; ///< sampling frequency - uint32_t samples; ///< number of audio samples in the file - int channels; ///< number of channels - int file_type; ///< source file type (original file format) - int bps; ///< bits-per-sample - int sample_type; ///< source sample type (integer or floating-point) - int source_order; ///< source sample byte order - int frame_size; ///< number of samples in each frame - int random_access; ///< random access frame interval - int ra_location; ///< where the RA frames are located - int adapt_order; ///< uses adaptive (non-fixed) prediction order - int coef_table; ///< which coefficient table to use - int ltp; ///< uses long term prediction - int pred_order; ///< maximum or fixed prediction order - int blksw; ///< block switching - int coding_type; ///< entropy coding type (Rice or BGMC) - int coding_part; ///< coded blocks are partitioned - int joint_stereo; ///< uses joint stereo channel correlation - int mcc; ///< uses multi-channel correlation - int ch_config; ///< has channel configuration - int ch_reorder; ///< has channel reordering - int has_crc; ///< has CRC error checking - int rlslms; ///< uses RLSLMS - int has_aux; ///< has auxiliary data - int *ch_pos; ///< channel positions, if reordering - int header_size; ///< source header size - int trailer_size; ///< source trailer size - - /* derived values */ - int bpc; ///< bits used to reference channel positions - int last_samples; ///< number of samples in the final frame - int frames; ///< number of frames in the file - int ra_units; ///< number of random access units - uint32_t *ra_sizes; ///< sizes, in bytes, of random access units - int aux_size; ///< auxilliary data size - uint8_t *aux; ///< auxilliary data - int header_pos; ///< file position of source header - uint8_t *header; ///< source header - int trailer_pos; ///< file position of source trailer - uint8_t *trailer; ///< source trailer - int start_pos; ///< file position of first ALS frame - uint32_t ref_crc; ///< reference CRC-32 checksum - - /* global fields */ - AlsFrame frame; ///< current frame data - int frame_index; ///< frame index number - int ra_index; ///< random access index number - uint32_t crc; ///< running CRC-32 checksum of decoded audio - - /* internal buffers */ - int32_t **decoded; ///< decoded audio data - int max_frame_bytes; ///< estimated maximum coded bytes in a frame - uint8_t *bitstream; ///< internal bitstream buffer - int bitstream_size; ///< current buffer size - int bitstream_index; ///< current buffer index - unsigned int allocated_bitstream_size; ///< total buffer size - -} AlsDecodeContext; - -extern int als_decode_init(AlsDecodeContext *ctx, FILE *fp); - -extern int als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, - uint8_t *buf, int buf_size); - -extern int als_decode_close(AlsDecodeContext *ctx); - -#endif /* ALSDEC_H */ Deleted: alstab.h =================================================================== --- alstab.h 2007-08-20 00:08:12 UTC (rev 2) +++ alstab.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,52 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file alstab.h - * ALS tables - */ - -#ifndef ALSTAB_H -#define ALSTAB_H - -/* rice code parameters for each coeff: */ -typedef struct { - int offset; - int param; -} ParcorVars; - -static const ParcorVars parcor_vars[3][20] = { - // samplerate is 44.1kHz or 48kHz - { {-52, 4}, {-29, 5}, {-31, 4}, { 19, 4}, {-16, 4}, - { 12, 3}, { -7, 3}, { 9, 3}, { -5, 3}, { 6, 3}, - { -4, 3}, { 3, 3}, { -3, 2}, { 3, 2}, { -2, 2}, - { 3, 2}, { -1, 2}, { 2, 2}, { -1, 2}, { 2, 2} }, - // samplerate is 96kHz - { {-58, 3}, {-42, 4}, {-46, 4}, { 37, 5}, {-36, 4}, - { 29, 4}, {-29, 4}, { 25, 4}, {-23, 4}, { 20, 4}, - {-17, 4}, { 16, 4}, {-12, 4}, { 12, 3}, {-10, 4}, - { 7, 3}, { -4, 4}, { 3, 3}, { -1, 3}, { 1, 3} }, - // samplerate is 192kHz - { {-59, 3}, {-45, 5}, {-50, 4}, { 38, 4}, {-39, 4}, - { 32, 4}, {-30, 4}, { 25, 3}, {-23, 3}, { 20, 3}, - {-20, 3}, { 16, 3}, {-13, 3}, { 10, 3}, { -7, 3}, - { 3, 3}, { 0, 3}, { -1, 3}, { 2, 3}, { -1, 2} } -}; - -#endif /* ALSTAB_H */ Deleted: bitreader.c =================================================================== --- bitreader.c 2007-08-20 00:08:12 UTC (rev 2) +++ bitreader.c 2007-08-20 00:12:41 UTC (rev 3) @@ -1,213 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * This file is derived from libvorbis. - * Copyright (c) 2002, Xiph.org Foundation - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file bitreader.c - * Memory-based bitwise reader - */ - -#include "bitreader.h" - -#include <stdlib.h> -#include <string.h> - -static const uint32_t mask[33] = { - 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, - 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, - 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, - 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, - 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, - 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, - 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF -}; - -/* Bit Reader Functions */ - -void -init_get_bits(GetBitContext *b, uint8_t *buf, int bits) -{ - memset(b, 0, sizeof(*b)); - b->buffer = b->ptr = buf; - b->storage = (bits + 7) / 8; -} - -void -seek_bits(GetBitContext *b, int bitpos) -{ - int bytepos = bitpos >> 3; - if(bytepos < 0 || bytepos > b->storage) return; - b->ptr = &b->buffer[bytepos]; - b->endbyte = 0; - b->endbit = 0; -} - -void -skip_bits(GetBitContext *b, int bits) -{ - bits += b->endbit; - b->ptr += (bits >> 3); - b->endbyte += (bits >> 3); - b->endbit = (bits & 7); -} - -void -skip_bits1(GetBitContext *b) -{ - if(++(b->endbit) > 7) { - b->endbit = 0; - b->ptr++; - b->endbyte++; - } -} - -/* Read in bits without advancing the bitptr; bits <= 32 */ -uint32_t -look_bits(GetBitContext *b, int bits) -{ - unsigned long ret; - int m = 32-bits; - - bits += b->endbit; - - if(((b->endbyte+4)>=b->storage) && ((b->endbyte*8+bits)>(b->storage*8))) { - return 0; - } - - ret = b->ptr[0] << (24+b->endbit); - if(bits > 8) { - ret |= b->ptr[1] << (16+b->endbit); - if(bits > 16) { - ret |= b->ptr[2] << (8+b->endbit); - if(bits > 24) { - ret |= b->ptr[3] << (b->endbit); - if(bits>32 && b->endbit) { - ret|=b->ptr[4]>>(8-b->endbit); - } - } - } - } - return (uint32_t)(((ret&0xFFFFFFFF)>>(m>>1))>>((m+1)>>1)); -} - -/* bits <= 32 */ -uint32_t -get_bits(GetBitContext *b, int bits) -{ - long ret; - long m = 32 - bits; - - bits += b->endbit; - - if(b->endbyte+4 >= b->storage) { - // not the main path - ret = 0; - if((b->endbyte * 8 + bits) > (b->storage * 8)) { - goto overflow; - } - } - - ret = b->ptr[0] << (24+b->endbit); - if(bits > 8) { - ret |= b->ptr[1] << (16+b->endbit); - if(bits > 16) { - ret |= b->ptr[2] << (8+b->endbit); - if(bits > 24) { - ret |= b->ptr[3] << (b->endbit); - if(bits > 32 && b->endbit) { - ret |= b->ptr[4] >> (8-b->endbit); - } - } - } - } - ret = ((ret & 0xFFFFFFFFUL)>>(m>>1))>>((m+1)>>1); - - overflow: - b->ptr += (bits >> 3); - b->endbyte += (bits >> 3); - b->endbit = (bits & 7); - return (uint32_t)ret; -} - -long -get_bits1(GetBitContext *b) -{ - long ret; - - if(b->endbyte >= b->storage) { - // not the main path - ret=-1L; - goto overflow; - } - - ret = (b->ptr[0] >> (7-b->endbit)) & 1; - - overflow: - - b->endbit++; - if(b->endbit > 7) { - b->endbit = 0; - b->ptr++; - b->endbyte++; - } - return ret; -} - -void -align_get_bits(GetBitContext *b) -{ - if(b->endbit) { - b->endbit = 0; - b->ptr++; - b->endbyte++; - } -} - -long -get_bits_count(GetBitContext *b) -{ - return (b->endbyte*8+b->endbit); -} - -int32_t -get_rice(GetBitContext *b, int rp) -{ - uint32_t j, k; - int32_t v; - - k = 0; - while(get_bits1(b)) - k++; - if(rp) { - j = get_bits(b, rp); - if(j & (1 << (rp-1))) - v = (k << (rp-1)) | (j & ((1 << (rp-1)) -1)); - else - v = -((k << (rp-1)) | j) - 1; - } else { - // special case for rice param == 0 - if(k & 1) - v = (-(int)k-1) >> 1; - else - v = k >> 1; - } - return v; -} Deleted: bitreader.h =================================================================== --- bitreader.h 2007-08-20 00:08:12 UTC (rev 2) +++ bitreader.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,61 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * This file is derived from libvorbis. - * Copyright (c) 2002, Xiph.org Foundation - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file bitreader.h - * Memory-based bitwise reader - */ - -#ifndef BITREADER_H -#define BITREADER_H - -#include <stdint.h> - -typedef struct { - long endbyte; - int endbit; - uint8_t *buffer; - uint8_t *ptr; - long storage; -} GetBitContext; - -extern void init_get_bits(GetBitContext *b, uint8_t *buf, int bits); - -extern void seek_bits(GetBitContext *b, int bitpos); - -extern void skip_bits(GetBitContext *b, int bits); - -extern void skip_bits1(GetBitContext *b); - -extern uint32_t look_bits(GetBitContext *b, int bits); - -extern uint32_t get_bits(GetBitContext *b, int bits); - -extern long get_bits1(GetBitContext *b); - -extern void align_get_bits(GetBitContext *b); - -extern long get_bits_count(GetBitContext *b); - -extern int32_t get_rice(GetBitContext *b, int rp); - -#endif /* BITREADER_H */ Deleted: bswap.h =================================================================== --- bswap.h 2007-08-20 00:08:12 UTC (rev 2) +++ bswap.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,79 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * This file is based on FFmpeg/libavutil/bswap.h - * Copyright (c) 2006 Michael Niedermayer - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file bswap.h - * Byte swap - */ - -#ifndef BSWAP_H -#define BSWAP_H - -#include "common.h" - -#ifdef HAVE_BYTESWAP_H -#include <byteswap.h> -#else - -static inline uint16_t bswap_16(uint16_t x){ - return (x>>8) | (x<<8); -} - -static inline uint32_t bswap_32(uint32_t x){ - x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); - return (x>>16) | (x<<16); -} - -static inline uint64_t bswap_64(uint64_t x) -{ - union { - uint64_t ll; - uint32_t l[2]; - } w, r; - w.ll = x; - r.l[0] = bswap_32(w.l[1]); - r.l[1] = bswap_32(w.l[0]); - return r.ll; -} - -#endif /* !HAVE_BYTESWAP_H */ - -// be2me ... BigEndian to MachineEndian -// le2me ... LittleEndian to MachineEndian - -#ifdef WORDS_BIGENDIAN -#define be2me_16(x) (x) -#define be2me_32(x) (x) -#define be2me_64(x) (x) -#define le2me_16(x) bswap_16(x) -#define le2me_32(x) bswap_32(x) -#define le2me_64(x) bswap_64(x) -#else -#define be2me_16(x) bswap_16(x) -#define be2me_32(x) bswap_32(x) -#define be2me_64(x) bswap_64(x) -#define le2me_16(x) (x) -#define le2me_32(x) (x) -#define le2me_64(x) (x) -#endif - -#endif /* BSWAP_H */ Deleted: common.h =================================================================== --- common.h 2007-08-20 00:08:12 UTC (rev 2) +++ common.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,120 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file common.h - * Common header file - */ - -#ifndef COMMON_H -#define COMMON_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <math.h> - -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#else -#if defined(_WIN32) && defined(_MSC_VER) - -// integer types -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -// limits -#define INT8_MIN _I8_MIN -#define INT8_MAX _I8_MAX -#define UINT8_MAX _UI8_MAX -#define INT16_MIN _I16_MIN -#define INT16_MAX _I16_MAX -#define UINT16_MAX _UI16_MAX -#define INT32_MIN _I32_MIN -#define INT32_MAX _I32_MAX -#define UINT32_MAX _UI32_MAX -#define INT64_MIN _I64_MIN -#define INT64_MAX _I64_MAX -#define UINT64_MAX _UI64_MAX - -// fprintf macros -#define PRId8 "d" -#define PRIi8 "i" -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" - -#endif -#endif /* EMULATE_INTTYPES */ - -#if __GNUC__ && !__INTEL_COMPILER -#define ALIGN16(x) x __attribute__((aligned(16))) -#else -#if defined(_MSC_VER) || defined(__INTEL_COMPILER) -#define ALIGN16(x) __declspec(align(16)) x -#else -#define ALIGN16(x) x -#endif -#endif - -#ifdef _WIN32 -#define CDECL __cdecl -#ifdef _MSC_VER -#define inline __inline -#endif /* _MSC_VER */ -#else -#define CDECL -#endif - -#define LOG2(a) (log((a)) / log(2.0)) - -#define ABS(a) ((a) >= 0 ? (a) : (-(a))) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define MIN(a,b) ((a) > (b) ? (b) : (a)) -#define CLIP(x,min,max) MAX(MIN((x), (max)), (min)) - -#include "bswap.h" - -#endif /* COMMON_H */ Deleted: config.h =================================================================== --- config.h 2007-08-20 00:08:12 UTC (rev 2) +++ config.h 2007-08-20 00:12:41 UTC (rev 3) @@ -1,2 +0,0 @@ -#define HAVE_INTTYPES_H 1 -// #define WORDS_BIGENDIAN Deleted: config.mak =================================================================== --- config.mak 2007-08-20 00:08:12 UTC (rev 2) +++ config.mak 2007-08-20 00:12:41 UTC (rev 3) @@ -1,17 +0,0 @@ -# set these to your liking - -CC = gcc - -RM = rm -f - -MAKE = make - -DEBUG_CFLAGS = -g - -EXTRA_CFLAGS = -O3 -fomit-frame-pointer - -WARNING_CFLAGS = -Wall -pedantic -std=c99 - -CFLAGS = $(DEBUG_CFLAGS) $(EXTRA_CFLAGS) $(WARNING_CFLAGS) - -EXEEXT = Deleted: main.c =================================================================== --- main.c 2007-08-20 00:08:12 UTC (rev 2) +++ main.c 2007-08-20 00:12:41 UTC (rev 3) @@ -1,184 +0,0 @@ -/* - * MPEG-4 Audio Lossless Coding (ALS) decoder - * Copyright (c) 2007 Justin Ruggles - * - * Decals is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * Decals is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Decals; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file main.c - * commandline front-end - */ - -#include "common.h" - -#include <stdlib.h> -#include <stdio.h> - -#include "alsdec.h" - -static void -print_als_header(AlsDecodeContext *ctx) -{ - fprintf(stderr, "** ALS HEADER **\n"); - fprintf(stderr, "sample rate: %u\n", ctx->sample_rate); - fprintf(stderr, "sample count: %u\n", ctx->samples); - fprintf(stderr, "channels: %d\n", ctx->channels); - switch(ctx->file_type) { - case FILE_TYPE_RAW: fprintf(stderr, "source file type: raw\n"); break; - case FILE_TYPE_WAVE: fprintf(stderr, "source file type: wave\n"); break; - case FILE_TYPE_AIFF: fprintf(stderr, "source file type: aiff\n"); break; - } - fprintf(stderr, "bits-per-sample: %d\n", ctx->bps); - switch(ctx->sample_type) { - case SAMPLE_TYPE_INT: fprintf(stderr, "sample type: integer\n"); break; - case SAMPLE_TYPE_FLOAT: fprintf(stderr, "sample type: floating-point\n"); break; - } - switch(ctx->source_order) { - case SRC_ORDER_LE: fprintf(stderr, "source byte order: little-endian\n"); break; - case SRC_ORDER_BE: fprintf(stderr, "source byte order: big-endian\n"); break; - } - fprintf(stderr, "frame size: %d\n", ctx->frame_size); - fprintf(stderr, "frame count: %d\n", ctx->frames); - if(ctx->random_access) { - fprintf(stderr, "random access: yes\n"); - fprintf(stderr, " ra interval: %d\n", ctx->random_access); - switch(ctx->ra_location) { - case RA_LOCATION_FRAME: fprintf(stderr, " ra location: frames\n"); break; - case RA_LOCATION_HEADER: fprintf(stderr, " ra location: header\n"); break; - } - fprintf(stderr, " number of ra units: %d\n", ctx->ra_units); - if(ctx->ra_location == RA_LOCATION_HEADER) { - int i; - for(i=0; i<ctx->ra_units; i++) { - fprintf(stderr, " %04d : %u\n", i, ctx->ra_sizes[i]); - } - } - } else { - fprintf(stderr, "random access: no\n"); - } - fprintf(stderr, "adaptive pred order: %s\n", ctx->adapt_order?"yes":"no"); - fprintf(stderr, "coefficient table: %d\n", ctx->coef_table); - fprintf(stderr, "long-term prediction: %s\n", ctx->ltp?"yes":"no"); - fprintf(stderr, "%sprediction order: %d\n", ctx->adapt_order?"max ":"", - ctx->pred_order); - fprintf(stderr, "block switching: %s\n", ctx->blksw?"yes":"no"); - switch(ctx->coding_type) { - case CODING_TYPE_RICE: fprintf(stderr, "entropy coding type: rice\n"); break; - case CODING_TYPE_BGMC: fprintf(stderr, "entropy coding type: bgmc\n"); break; - } - fprintf(stderr, "entropy partitioning: %s\n", ctx->coding_part?"yes":"no"); - fprintf(stderr, "joint stereo: %s\n", ctx->joint_stereo?"yes":"no"); - fprintf(stderr, "multi-channel correlation: %s\n", ctx->mcc?"yes":"no"); - fprintf(stderr, "channel configuration: %s\n", ctx->ch_config?"yes":"no"); - fprintf(stderr, "channel reordering: %s\n", ctx->ch_reorder?"yes":"no"); - if(ctx->ch_reorder) { - int ch; - for(ch=0; ch<ctx->channels; ch++) { - fprintf(stderr, " %d -> %d\n", ch, ctx->ch_pos[ch]); - } - } - if(ctx->has_crc) fprintf(stderr, "CRC: 0x%08X\n", ctx->ref_crc); - else fprintf(stderr, "CRC: none\n"); - fprintf(stderr, "rls-lms prediction: %s\n", ctx->rlslms?"yes":"no"); - if(ctx->has_aux) fprintf(stderr, "auxiliary data: %d\n", ctx->aux_size); - else fprintf(stderr, "auxiliary data: none\n"); - fprintf(stderr, "header size: %d\n", ctx->header_size); - fprintf(stderr, "trailer size: %d\n", ctx->trailer_size); - fprintf(stderr, "\n"); -} - -int -main(int argc, char **argv) -{ - FILE *fp; - char *fname; - AlsDecodeContext ctx; - int err=0; - uint8_t *data=NULL; - int data_size; - uint8_t *buf=NULL; - int buf_size; - int sample_count=0; - - if(argc != 2) { - fprintf(stderr, "\nusage: decals input.als\n"); - return 0; - } - fname = argv[1]; - fp = fopen(fname, "rb"); - if(!fp) { - fprintf(stderr, "cannot open file: %s\n", fname); - return 1; - } - - err = als_decode_init(&ctx, fp); - switch(err) { - case ALS_ERROR_GENERAL: fprintf(stderr, "error reading ALS header\n"); break; - case ALS_ERROR_MEMORY: fprintf(stderr, "out-of-memory error\n"); break; - case ALS_ERROR_EOF: fprintf(stderr, "end-of-file error\n"); break; - } - if(err) { - goto cleanup; - } - print_als_header(&ctx); - - data = calloc(ctx.channels * ctx.frame_size, sizeof(int32_t)); - if(!data) { - fprintf(stderr, "out-of-memory error\n"); - goto cleanup; - } - - buf_size = 16384; - buf = calloc(buf_size, 1); - if(!buf) { - fprintf(stderr, "out-of-memory error\n"); - goto cleanup; - } - - - do { - int consumed = 0; - data_size = 0; - do { - err = fread(buf, 1, buf_size, fp); - if(err > 0) { - consumed = als_decode_frame(&ctx, data, &data_size, buf, err); - data_size /= (sizeof(int32_t) * ctx.channels); - //fprintf(stderr, "consumed = %d\n", consumed); - } - } while(err > 0 && data_size == 0); - if(err > 0) { - sample_count += data_size; - fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); - while(data_size > 0 && (!ctx.samples || sample_count < ctx.samples)) { - consumed = als_decode_frame(&ctx, data, &data_size, NULL, 0); - data_size /= (sizeof(int32_t) * ctx.channels); - //fprintf(stderr, "consumed = %d\n", consumed); - if(data_size > 0) { - sample_count += data_size; - fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); - } - } - } - } while(err > 0 && (!ctx.samples || sample_count < ctx.samples)); - -cleanup: - if(data) free(data); - if(buf) free(buf); - fclose(fp); - als_decode_close(&ctx); - return err; -} Deleted: mp4-als_format_notes.txt =================================================================== --- mp4-als_format_notes.txt 2007-08-20 00:08:12 UTC (rev 2) +++ mp4-als_format_notes.txt 2007-08-20 00:12:41 UTC (rev 3) @@ -1,635 +0,0 @@ - -MPEG-4 Audio Lossless Coding (ALS) Documentation ------------------------------------------------- - - -MPEG-4 Audio Lossless Coding[1][2], also called MP4-ALS, is one of the lossless -audio coding formats which is part of the MPEG-4 audio specification. It is -based on the LPAC audio codec[3] by Tilman Liebchen. This document covers the -raw ALS format, which consists of the ALS header and a sequence of frames. - - - -KEY CONCEPTS -============ - -Original file preservation --------------------------- -The ALS header can provide everything that is needed to reconstruct the -original WAVE, AIFF, or raw audio file. This includes the file type, -sample rate, number of channels, bits-per-sample, sample type, and byte order. -The original header and/or footer are also preserved exactly in the ALS -header. The ALS format only supports from 8-bit to 32-bit audio in 8-bit -increments. Either integer or IEEE-floating-point sample types are supported. - - -Frame size and block switching ------------------------------- -The ALS frame size (number of audio samples) is fixed for a given stream or -file. All audio samples for a single channel in a frame is referred to as a -block. In order to adapt to transient signals, each block can be divided -into recursive subblocks. Each subblock can be split into 2 smaller subblocks, -down to 1/32 of the original frame size. - - -Random access -------------- -Seeking is an important feature for any audio format. It allows the decoder to -jump forward or backward to the start of a frame without having to decode all -frames in between. In the ALS format, the encoder can optionally include -so called "random access" frames to achieve this goal. The ALS header -specifies a random access interval from 0 to 255. A value of 0 indicates no -random access frames, 1 means every frame is a random access frame, 2 means -every other frame, etc... Each set of frames between random access frames is -call a random access unit. The encoder indicates the size of each random -access unit by either writing them all in the header or by writing it at the -start of each random access frame. The ra_location field in the ALS header -tells which of the 2 locations are used. - -I'm going to go ahead and gripe here about this design. The problem I see is -that using random access frames is optional, and that there is no unique -identifier for frame boundaries. This prevents a decoder from finding random -frames without both a reference point and either random access information or -by decoding every frame between the reference and the destination. - - -Channels --------- -ALS has 2 different ways of reducing redundancy between multiple channels. The -first method is joint stereo coding. The encoder calculates the difference -between 2 channels and selects 2 of left+right, left+diff, or right+diff. For -files with more than 2 channels, joint stereo can still be used by grouping the -channels into sets of pairs and individual channels. For example, encoding of -standard 5.1 audio could be done as L+R, C, LFE, LS+RS. The format allows for -reordering of the channels from their original positions in order to pair them -together if necessary. - -The 2nd method is called multi-channel correlation, or MCC. This method uses -adaptive subtraction to compare the prediction residual of reference channels -to the remaining channels. This is a more complex procedure which I will -descibe later once I fully understand the math behind it. - - -Forward Prediction ------------------- -The primary prediction method in ALS is forward linear predictive coding, or -LPC[4][5]. There are several ways to select good prediction coefficients. The -recommended method for ALS is Levinson-Durbin Recursion[6][7]. This is a good -method for 2 reasons. First of all, it sequentially produces higher order -coefficients, which is ideal for adapting the prediction order for each block. -Secondly, it produces parcor (reflection) coefficients as an intermediate -result, which are the values that are quantized and written to the ALS -bitstream. The standard defines a bit-exact method for transforming the -quantized parcor coefficients into the LPC coefficients used for linear -prediction. - -One of the unique features of the ALS format is that it uses progressively -increasing prediction orders for the first samples in random access frames, -which cannot reference previous samples. Other formats, such as FLAC, write the -first samples directly, then proceed with prediction using the full number of -coefficients. In ALS, the first sample is written directly, but each subsequent -sample is predicted using increasingly higher orders until the full prediction -order is reached. - - -Long-Term Prediction --------------------- -Also called pitch coding, long-term prediction as implemented in ALS reduces -signal redundancy by predicting the value of an LPC residual sample using the -average value of 5 residual samples at a specified time lag with a specified -gain value. The optimal lag and gain values are determined for each frame by the -encoder. This is called pitch coding because the frequency, or pitch, of a -signal leads to periodic redundancy. If the period is calculated, it can be -exploited in order to remove that redundancy from the encoded output. This -algorithm is typically used in speech codecs, such as Speex. - - -RLSLMS (Recursive Least Squares, Least Mean Square) backward prediction ------------------------------------------------------------------------ -ALS has an alternative backward prediction mode, which uses the recursive least -squares algorithm[8]. - -Entropy Coding --------------- -In ALS, both the prediction coefficients and the residual signal are compressed -using entropy coding. The encoder can choose between 2 different methods, -Golomb-Rice Coding[9] and Block Gilbert-Moore Coding (BGMC). Rice coding is a -form of Huffman coding, while BGMC, also called Shannon-Fano-Elias coding, is a -precursor of arithmetic coding. - - -Floating-Point Data -------------------- -The ALS format provides the ability to losslessly encode floating-point[10] -audio. The floating-point signal is basically broken down into an integer signal -plus the residual signal. The integer signal is encoded using the standard ALS -algorithm, while the... [truncated message content] |
From: <jb...@us...> - 2007-08-20 00:08:13
|
Revision: 2 http://decals.svn.sourceforge.net/decals/?rev=2&view=rev Author: jbr79 Date: 2007-08-19 17:08:12 -0700 (Sun, 19 Aug 2007) Log Message: ----------- initial SVN import Added Paths: ----------- Makefile alsdec.c alsdec.h alstab.h bitreader.c bitreader.h bswap.h common.h config.h config.mak main.c Added: Makefile =================================================================== --- Makefile (rev 0) +++ Makefile 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,37 @@ +## +# Makefile for Decals +## + +include config.mak + +LDFLAGS = +LIBOBJS = +LIBS = -lm + +PROGS = decals$(EXEEXT) + +decals_OBJS = alsdec.o bitreader.o main.o +decals_SRCS = $(alsdec_OBJS:.o=.c) +decals_LDFLAGS = + +all: dep $(PROGS) + +.c.o: + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -c $< + +decals$(EXEEXT): $(decals_OBJS) + $(CC) $(CFLAGS) -o $@ $(decals_LDFLAGS) $(decals_OBJS) $(LIBOBJS) $(LIBS) + +clean: + $(RM) decals$(EXEEXT) *.o .depend + +dep: depend + +depend: .depend + +.depend: $(decals_SRCS) + $(CC) -MM $(CFLAGS) $^ 1>.depend + +ifneq ($(wildcard .depend),) +include .depend +endif Added: alsdec.c =================================================================== --- alsdec.c (rev 0) +++ alsdec.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,708 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * internal frame buffering is from FFmpeg/libavcodec/flac.c + * Copyright (c) 2003 Alex Bergszaszi + * fast_realloc() is from FFmpeg/libavcodec/utils.c + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alsdec.c + * ALS decoder + */ + +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "bitreader.h" +#include "alsdec.h" +#include "alstab.h" + +static void * +fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) +{ + if(min_size < *size) + return ptr; + + *size = MAX(17*min_size/16 + 32, min_size); + + return realloc(ptr, *size); +} + +static int +read_als_header(AlsDecodeContext *ctx) +{ + int magic; + + // read header fields from bitstream + magic = get_bits(&ctx->gbc, 32); + ctx->sample_rate = get_bits(&ctx->gbc, 32); + ctx->samples = get_bits(&ctx->gbc, 32); + ctx->channels = get_bits(&ctx->gbc, 16) + 1; + ctx->file_type = get_bits(&ctx->gbc, 3); + ctx->bps = get_bits(&ctx->gbc, 3) * 8 + 8; + ctx->sample_type = get_bits1(&ctx->gbc); + ctx->source_order = get_bits1(&ctx->gbc); + ctx->frame_size = get_bits(&ctx->gbc, 16) + 1; + ctx->random_access = get_bits(&ctx->gbc, 8); + ctx->ra_location = get_bits(&ctx->gbc, 2); + ctx->adapt_order = get_bits1(&ctx->gbc); + ctx->coef_table = get_bits(&ctx->gbc, 2); + ctx->ltp = get_bits1(&ctx->gbc); + ctx->pred_order = get_bits(&ctx->gbc, 10); + ctx->blksw = get_bits(&ctx->gbc, 2); + ctx->coding_type = get_bits1(&ctx->gbc); + ctx->coding_part = get_bits1(&ctx->gbc); + ctx->joint_stereo = get_bits1(&ctx->gbc); + ctx->mcc = get_bits1(&ctx->gbc); + ctx->ch_config = get_bits1(&ctx->gbc); + ctx->ch_reorder = get_bits1(&ctx->gbc); + ctx->has_crc = get_bits1(&ctx->gbc); + ctx->rlslms = get_bits1(&ctx->gbc); + get_bits(&ctx->gbc, 5); + ctx->has_aux = get_bits1(&ctx->gbc); + + // check for validity + if(magic != 0x414C5300) { + fprintf(stderr, "ALS header not found\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->sample_rate == 0) { + fprintf(stderr, "invalid ALS header: sample rate cannot be 0\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->samples == 0) { + fprintf(stderr, "invalid ALS header: sample count cannot be 0\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->file_type > 2) { + fprintf(stderr, "invalid ALS header: unknown file type: %d\n", + ctx->file_type); + return ALS_ERROR_GENERAL; + } + if(ctx->bps > 32) { + fprintf(stderr, "invalid ALS header: reserved bit depth: %d \n", + ctx->bps); + return ALS_ERROR_GENERAL; + } + if(ctx->coef_table == 3) { + fprintf(stderr, "invalid ALS header: invalid coefficient table: 3\n"); + return ALS_ERROR_GENERAL; + } + + // calculate frame count + ctx->last_samples = ctx->samples % ctx->frame_size; + ctx->frames = ctx->samples / ctx->frame_size; + if(ctx->last_samples) + ctx->frames++; + + // calculate bits for channel index + ctx->bpc = MAX(1, ceil(LOG2(ctx->channels))); + + // calculate random access frame count + if(ctx->random_access) { + ctx->ra_units = ctx->frames / ctx->random_access; + if(ctx->frames % ctx->random_access) + ctx->ra_units++; + ctx->ra_index = 0; + } + + // calculate block switch flag bits + if(ctx->blksw) + ctx->blksw = 1 << (ctx->blksw + 2); + + return ALS_OK; +} + +static int +read_channel_order(AlsDecodeContext *ctx, FILE *fp) +{ + GetBitContext gbc; + uint8_t *buf; + int i, size; + + ctx->ch_pos = calloc(ctx->channels, 1); + if(!ctx->ch_pos) + return ALS_ERROR_MEMORY; + size = ((ctx->bpc * ctx->channels) + 7) / 8; + buf = calloc(1, size); + if(!buf) + return ALS_ERROR_MEMORY; + if(fread(buf, 1, size, fp) != size) + return ALS_ERROR_EOF; + init_get_bits(&gbc, buf, size * 8); + + for(i=0; i<ctx->channels; i++) { + ctx->ch_pos[i] = get_bits(&gbc, ctx->bpc); + } + free(buf); + return ALS_OK; +} + +int +als_decode_init(AlsDecodeContext *ctx, FILE *fp) +{ + uint8_t buf[22]; + int i, ret; + + memset(ctx, 0, sizeof(*ctx)); + + // ALS header + if(fread(buf, 1, 22, fp) != 22) + return ALS_ERROR_EOF; + init_get_bits(&ctx->gbc, buf, 176); + ret = read_als_header(ctx); + if(ret) + return ret; + + // channel configuration (unused) + if(ctx->ch_config) + if(fread(buf, 2, 1, fp) != 1) + return ALS_ERROR_EOF; + + // channel reordering + if(ctx->ch_reorder) { + ret = read_channel_order(ctx, fp); + if(ret) + return ret; + } + + // source file header and trailer + if(fread(&ctx->header_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->header_size = be2me_32(ctx->header_size); + if(fread(&ctx->trailer_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->trailer_size = be2me_32(ctx->trailer_size); + if(ctx->header_size > 0) { + ctx->header = calloc(ctx->header_size, 1); + if(!ctx->header) + return ALS_ERROR_MEMORY; + if(fread(ctx->header, 1, ctx->header_size, fp) != ctx->header_size) + return ALS_ERROR_EOF; + } + if(ctx->trailer_size > 0) { + ctx->trailer = calloc(ctx->trailer_size, 1); + if(!ctx->trailer) + return ALS_ERROR_MEMORY; + if(fread(ctx->trailer, 1, ctx->trailer_size, fp) != ctx->trailer_size) + return ALS_ERROR_EOF; + } + + // CRC-32 + if(ctx->has_crc) { + if(fread(&ctx->ref_crc, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->ref_crc = be2me_32(ctx->ref_crc); + ctx->crc = 0xFFFFFFFF; + } + + // random access units + if(ctx->random_access) { + ctx->ra_sizes = calloc(ctx->ra_units, sizeof(uint32_t)); + if(!ctx->ra_sizes) + return ALS_ERROR_MEMORY; + if(ctx->ra_location == RA_LOCATION_HEADER) { + if(fread(ctx->ra_sizes, 4, ctx->ra_units, fp) != ctx->ra_units) + return ALS_ERROR_EOF; + for(i=0; i<ctx->ra_units; i++) { + ctx->ra_sizes[i] = be2me_32(ctx->ra_sizes[i]); + } + } + } + + // auxilliary data + if(ctx->has_aux) { + if(fread(&ctx->aux_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->aux_size = be2me_32(ctx->aux_size); + ctx->aux = calloc(1, ctx->aux_size); + if(!ctx->aux) + return ALS_ERROR_MEMORY; + if(fread(ctx->aux, 1, ctx->aux_size, fp) != ctx->aux_size) + return ALS_ERROR_EOF; + } + + // allocate blocks + /*ctx->frame.blocks = calloc(ctx->channels, sizeof(AlsBlock)); + if(!ctx->frame.blocks) + return ALS_ERROR_MEMORY;*/ + + // allocated decoded audio + ctx->decoded = calloc(ctx->channels, sizeof(int32_t *)); + for(i=0; i<ctx->channels; i++) { + ctx->decoded[i] = calloc(ctx->frame_size, sizeof(int32_t)); + } + + // allocate buffer + ctx->max_frame_bytes = (ctx->channels * ctx->bps * ctx->frame_size + 7) / 8; + ctx->bitstream = fast_realloc(ctx->bitstream, + &ctx->allocated_bitstream_size, + ctx->max_frame_bytes); + + return ALS_OK; +} + +/** + * Parses block switch flags to determine subblock count and sizes. + * @return Returns the number of subblocks + */ +static int +parse_subblock_sizes(uint32_t flags, int fs, int sub_sizes[32]) +{ + int b; + int i, j, k, l, m, n; + int sh; + uint8_t lvl[5][16]; + + // parse flags into binary tree + sh = 30; + for(l=0; l<5; l++) { + n = 1 << l; + for(i=0; i<n; i++) { + lvl[l][i] = (flags >> sh) & 1; + sh--; + } + } + + // traverse binary tree to determine subblock count and sizes + b = 0; + l = 0; // level 0 + if(!lvl[l][0]) { + sub_sizes[b++] = fs; + } else { + for(i=0; i<2; i++) { + l = 1; // level 1 + if(!lvl[l][i]) { + sub_sizes[b++] = fs >> l; + } else { + for(j=0; j<2; j++) { + l = 2; // level 2 + if(!lvl[l][j]) { + sub_sizes[b++] = fs >> l; + } else { + for(k=0; k<2; k++) { + l = 3; // level 3 + if(!lvl[l][k]) { + sub_sizes[b++] = fs >> l; + } else { + for(m=0; m<2; m++) { + l = 4; // level 4 + if(!lvl[l][m]) { + sub_sizes[b++] = fs >> l; + } else { + l = 5; // level 5 + sub_sizes[b++] = fs >> l; + sub_sizes[b++] = fs >> l; + } + } + } + } + } + } + } + } + } + + // return number of subblocks + return b; +} + +static int +decode_subblock(AlsDecodeContext *ctx, int ch, int sb) +{ + int i; + int sb_size = ctx->frame.subblock_sizes[sb]; + fprintf(stderr, "channel=%d subblock=%d\n", ch, sb); + + align_get_bits(&ctx->gbc); + if(get_bits1(&ctx->gbc)) { + ctx->frame.block_type = BLOCK_TYPE_NORMAL; + } else { + if(get_bits1(&ctx->gbc)) + ctx->frame.block_type = BLOCK_TYPE_CONSTANT; + else + ctx->frame.block_type = BLOCK_TYPE_ZERO; + } + /*ctx->frame.block_type = get_bits(&ctx->gbc, 2); + if(ctx->frame.block_type == 3) + ctx->frame.block_type = BLOCK_TYPE_NORMAL;*/ + fprintf(stderr, "block type: "); + switch(ctx->frame.block_type) { + case BLOCK_TYPE_ZERO: fprintf(stderr, "ZERO\n"); break; + case BLOCK_TYPE_CONSTANT: fprintf(stderr, "CONSTANT\n"); break; + case BLOCK_TYPE_NORMAL: fprintf(stderr, "NORMAL\n"); break; + } + ctx->frame.diff_flag = get_bits1(&ctx->gbc); + fprintf(stderr, "difference signal: %s\n", ctx->frame.diff_flag?"yes":"no"); + + if(ctx->frame.block_type == BLOCK_TYPE_CONSTANT) { + align_get_bits(&ctx->gbc); + get_bits(&ctx->gbc, ctx->bps); + } else if(ctx->frame.block_type == BLOCK_TYPE_NORMAL) { + if(ctx->coding_type == CODING_TYPE_RICE) { + // determine entropy partitioning + ctx->frame.ec_part = 1; + if(ctx->coding_part && get_bits1(&ctx->gbc)) + ctx->frame.ec_part = 4; + fprintf(stderr, "ec partitions: %d\n", ctx->frame.ec_part); + + // read Rice parameters for each partition + ctx->frame.rice_params[0] = get_bits(&ctx->gbc, 4+(ctx->bps>16)); + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.rice_params[i] = ctx->frame.rice_params[i-1]; + ctx->frame.rice_params[i] += get_rice(&ctx->gbc, 0); + } + fprintf(stderr, "rice params:"); + for(i=0; i<ctx->frame.ec_part; i++) { + fprintf(stderr, " %d", ctx->frame.rice_params[i]); + } + fprintf(stderr, "\n"); + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + // determine entropy partitioning + if(ctx->coding_part) { + ctx->frame.ec_part = 1 << get_bits(&ctx->gbc, 2); + } else if(get_bits1(&ctx->gbc)) { + ctx->frame.ec_part = 4; + } + + // read BGMC parameters for each partition + ctx->frame.bgmc_rice[0] = get_bits(&ctx->gbc, 8+(ctx->bps>16)); + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.bgmc_rice[i] = ctx->frame.rice_params[i-1]; + ctx->frame.bgmc_rice[i] += get_rice(&ctx->gbc, 2); + } + + // separate grouped BGMC parameters + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.bgmc_freq[i] = ctx->frame.bgmc_rice[i] & 0x0F; + ctx->frame.bgmc_rice[i] >>= 4; + } + } + + // shift for unused LSB's + ctx->frame.lsb_shift = get_bits1(&ctx->gbc); + if(ctx->frame.lsb_shift) + ctx->frame.lsb_shift += get_bits(&ctx->gbc, 4); + fprintf(stderr, "shift: %d\n", ctx->frame.lsb_shift); + + // decode LPC coefficients + if(!ctx->rlslms) { + // determine LPC order + int p = ctx->pred_order; + if(ctx->adapt_order) { + int max_order = CLIP(p, 1, (sb_size>>3)-1); + int obits = MAX(1, ceil(LOG2(max_order))); + p = get_bits(&ctx->gbc, obits); + } + ctx->frame.pred_order = p; + fprintf(stderr, "lpc order: %d\n", p); + + // decode quantized coefficients + if(ctx->coef_table == 3) { + for(i=0; i<p; i++) { + ctx->frame.parcor_coefs[i] = get_bits(&ctx->gbc, 7) - 64; + } + } else { + const ParcorVars *pv = parcor_vars[ctx->coef_table]; + i = 0; + for(; i<MIN(p, 20); i++) { + ctx->frame.parcor_coefs[i] = pv[i].offset + get_rice(&ctx->gbc, pv[i].param); + } + for(; i<MIN(p, 127); i++) { + ctx->frame.parcor_coefs[i] = (i & 1) + get_rice(&ctx->gbc, 2); + } + for(; i<p; i++) { + ctx->frame.parcor_coefs[i] = get_rice(&ctx->gbc, 1); + } + } + fprintf(stderr, "qpar:"); + for(i=0; i<p; i++) { + fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); + } + fprintf(stderr, "\n"); + + // compute scaled parcor coefficients + for(i=0; i<p; i++) { + int qc = ctx->frame.parcor_coefs[i]; + int coef; + if(i < 2) { + coef = 32 + ((qc + 64) * (qc + 65) << 7) - (1 << 20); + if(i == 2) + coef = -coef; + } else { + coef = (qc << 14) + (1 << 13); + } + ctx->frame.parcor_coefs[i] = coef; + } + fprintf(stderr, "par:"); + for(i=0; i<p; i++) { + fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); + } + fprintf(stderr, "\n"); + } else { + // default prediction order for RLS-LMS + ctx->frame.pred_order = 10; + } + + // no LTP + + // decode residual + if(ctx->frame.is_ra_frame && sb == 0) { + // get residual signal, random access + int j, prog; + + prog = MIN(3, ctx->frame.pred_order); + if(prog > 0) + get_rice(&ctx->gbc, ctx->bps-4); + if(prog > 1) + get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+3, 31)); + if(prog > 2) + get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+1, 31)); + + if(ctx->coding_type == CODING_TYPE_RICE) { + int part_size = sb_size / ctx->frame.ec_part; + for(j=0; j<part_size-prog; j++) { + get_rice(&ctx->gbc, ctx->frame.rice_params[0]); + } + for(i=1; i<ctx->frame.ec_part; i++) { + for(j=0; j<part_size; j++) { + get_rice(&ctx->gbc, ctx->frame.rice_params[i]); + } + } + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + fprintf(stderr, "BGMC decoding unsupported\n"); + return ALS_ERROR_GENERAL; + } + } else { + // get residual signal, no random access + int j; + if(ctx->coding_type == CODING_TYPE_RICE) { + int part_size = sb_size / ctx->frame.ec_part; + fprintf(stderr, "partition size: %d\n", part_size); + for(i=0; i<ctx->frame.ec_part; i++) { + fprintf(stderr, "res[%d]:", i); + for(j=0; j<part_size; j++) { + int r = get_rice(&ctx->gbc, ctx->frame.rice_params[i]); + fprintf(stderr, " %d", r); + } + fprintf(stderr, "\n"); + } + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + fprintf(stderr, "BGMC decoding unsupported\n"); + return ALS_ERROR_GENERAL; + } + } + } + + // no RLS-LMS + + // no MCC + + return ALS_OK; +} + +static int +decode_single_block(AlsDecodeContext *ctx, int ch) +{ + int sb; + + ctx->frame.coupled_block = 0; + ctx->frame.num_subblocks = 1; + ctx->frame.subblock_sizes[0] = ctx->frame_size; + if(ctx->frame_index == ctx->frames) + ctx->frame.subblock_sizes[0] = ctx->last_samples; + + for(sb=0; sb<ctx->frame.num_subblocks; sb++) { + decode_subblock(ctx, ch, sb); + } + + return ALS_OK; +} + +static int +decode_joint_block(AlsDecodeContext *ctx, int ch0) +{ + int ch1 = ch0 + 1; + return ALS_OK; +} + +static int +decode_frame(AlsDecodeContext *ctx, int alloc_data_size) +{ + int ch; + + // read random access unit size + ctx->frame.is_ra_frame = 0; + if(ctx->random_access) { + ctx->frame.is_ra_frame = !(ctx->frame_index % ctx->random_access); + if(ctx->frame.is_ra_frame && ctx->ra_location == RA_LOCATION_FRAME) { + ctx->ra_sizes[ctx->ra_index] = get_bits(&ctx->gbc, 32); + } + } + + // determine if MCC is used + ctx->frame.use_mcc = 0; + if(ctx->mcc) { + if(ctx->joint_stereo) + ctx->frame.use_mcc = get_bits(&ctx->gbc, 8); + else + ctx->frame.use_mcc = 1; + } + + // currently unsupported features + if(ctx->frame.use_mcc) { + fprintf(stderr, "MCC unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->joint_stereo) { + fprintf(stderr, "Joint Stereo unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->blksw) { + fprintf(stderr, "Block Switching unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->rlslms) { + fprintf(stderr, "RLS-LMS unsupported\n"); + return ALS_ERROR_GENERAL; + } + + for(ch=0; ch<ctx->channels; ch++) { + decode_single_block(ctx, ch); + } + + // increment indices + if(ctx->frame.is_ra_frame) { + ctx->ra_index++; + } + ctx->frame_index++; + + return ALS_OK; +} + +int +als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + int input_buf_size = 0; + int32_t *samples = data; + int alloc_data_size = *data_size; + int frame_size; + int i, ch; + + *data_size = 0; + + assert(ctx->max_frame_bytes > 0); + + fprintf(stderr, "decoding frame %d\n", ctx->frame_index); + + // copy input bytes to internal buffer + buf_size = MAX(MIN(buf_size, ctx->max_frame_bytes - ctx->bitstream_size), 0); + input_buf_size = buf_size; + if(ctx->bitstream_index + ctx->bitstream_size + buf_size > ctx->allocated_bitstream_size) { + memmove(ctx->bitstream, &ctx->bitstream[ctx->bitstream_index], ctx->bitstream_size); + ctx->bitstream_index = 0; + } + memcpy(&ctx->bitstream[ctx->bitstream_index + ctx->bitstream_size], buf, buf_size); + buf = &ctx->bitstream[ctx->bitstream_index]; + ctx->bitstream_size += buf_size; + if(ctx->bitstream_size < ctx->max_frame_bytes) { + // need more data + if(ctx->frame_index != ctx->frames-1) { + fprintf(stderr, "need more data...\n"); + return input_buf_size; + } + } + init_get_bits(&ctx->gbc, buf, ctx->bitstream_size*8); + + // decode ALS frame to ctx->decoded + if(decode_frame(ctx, alloc_data_size)) { + fprintf(stderr, "decode_frame() failed\n"); + ctx->bitstream_size = 0; + ctx->bitstream_index = 0; + return -1; + } + fprintf(stderr, "\n"); + + if(ctx->frame_index == ctx->frames) + frame_size = ctx->last_samples; + else + frame_size = ctx->frame_size; + + // copy/interleave ctx->decoded to samples + for(i=0; i<frame_size; i++) { + for(ch=0; ch<ctx->channels; ch++) { + *(samples++) = ctx->decoded[ch][i]; + } + } + + *data_size = (int8_t *)samples - (int8_t *)data; + + i = (get_bits_count(&ctx->gbc) + 7) / 8; + if(i > buf_size) { + fprintf(stderr, "frame size too large (max_frame_bytes too low)\n"); + ctx->bitstream_size = 0; + ctx->bitstream_index = 0; + return -1; + } + + if(ctx->bitstream_size) { + ctx->bitstream_index += i; + ctx->bitstream_size -= i; + return input_buf_size; + } else { + return i; + } +} + +int +als_decode_close(AlsDecodeContext *ctx) +{ + int i; + if(ctx) { + if(ctx->ch_pos) + free(ctx->ch_pos); + if(ctx->header) + free(ctx->header); + if(ctx->trailer) + free(ctx->trailer); + if(ctx->ra_sizes) + free(ctx->ra_sizes); + if(ctx->aux) + free(ctx->aux); + //if(ctx->frame.blocks) + // free(ctx->frame.blocks); + if(ctx->decoded) { + for(i=0; i<ctx->channels; i++) { + if(ctx->decoded[i]) + free(ctx->decoded[i]); + } + free(ctx->decoded); + } + if(ctx->bitstream) + free(ctx->bitstream); + } + return ALS_OK; +} Added: alsdec.h =================================================================== --- alsdec.h (rev 0) +++ alsdec.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,170 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alsdec.h + * ALS decoder header + */ + +#ifndef ALSDEC_H +#define ALSDEC_H + +#include "common.h" + +#include <stdio.h> +#include <string.h> + +#include "bitreader.h" + +enum { + ALS_OK = 0, + ALS_ERROR_GENERAL = -1, + ALS_ERROR_MEMORY = -2, + ALS_ERROR_EOF = -3 +} AlsError; + +enum { + FILE_TYPE_RAW = 0, + FILE_TYPE_WAVE = 1, + FILE_TYPE_AIFF = 2 +} FileType; + +enum { + SAMPLE_TYPE_INT = 0, + SAMPLE_TYPE_FLOAT = 1 +} SampleType; + +enum { + SRC_ORDER_LE = 0, + SRC_ORDER_BE = 1 +} SourceOrder; + +enum { + RA_LOCATION_NONE = 0, + RA_LOCATION_FRAME = 1, + RA_LOCATION_HEADER = 2 +} RaLocation; + +enum { + CODING_TYPE_RICE = 0, + CODING_TYPE_BGMC = 1 +} CodingType; + +enum { + BLOCK_TYPE_ZERO = 0, + BLOCK_TYPE_CONSTANT, + BLOCK_TYPE_NORMAL +} BlockType; + +typedef struct { + /* frame */ + int is_ra_frame; ///< flag is on if current frame is an RA frame + int use_mcc; ///< flag is on if current frame uses MCC + + /* block */ + int num_subblocks; ///< number of subblocks for the current block + int subblock_sizes[32]; ///< list containing the size of each subblock + int coupled_block; ///< indicates if this is a coupled block + + /* subblock */ + int block_type; ///< indicates normal, zero, or constant block type + int diff_flag; ///< for zero and constant blocks, indicates if the + ///< block contains a difference signal or a normal + ///< signal + int ec_part; ///< number of entropy coding partitions + int rice_params[4]; ///< Rice parameters for each partition + int bgmc_rice[8]; ///< for BGMC, Rice parameters for coding tail + int bgmc_freq[8]; ///< for BGMC, frequency indices for coding MSB + int lsb_shift; ///< optional shift level for unused LSB's + int pred_order; ///< current prediction order + int parcor_coefs[1023]; ///< decoded parcor coefficients +} AlsFrame; + +typedef struct { + + GetBitContext gbc; + + /* from ALS header */ + uint32_t sample_rate; ///< sampling frequency + uint32_t samples; ///< number of audio samples in the file + int channels; ///< number of channels + int file_type; ///< source file type (original file format) + int bps; ///< bits-per-sample + int sample_type; ///< source sample type (integer or floating-point) + int source_order; ///< source sample byte order + int frame_size; ///< number of samples in each frame + int random_access; ///< random access frame interval + int ra_location; ///< where the RA frames are located + int adapt_order; ///< uses adaptive (non-fixed) prediction order + int coef_table; ///< which coefficient table to use + int ltp; ///< uses long term prediction + int pred_order; ///< maximum or fixed prediction order + int blksw; ///< block switching + int coding_type; ///< entropy coding type (Rice or BGMC) + int coding_part; ///< coded blocks are partitioned + int joint_stereo; ///< uses joint stereo channel correlation + int mcc; ///< uses multi-channel correlation + int ch_config; ///< has channel configuration + int ch_reorder; ///< has channel reordering + int has_crc; ///< has CRC error checking + int rlslms; ///< uses RLSLMS + int has_aux; ///< has auxiliary data + int *ch_pos; ///< channel positions, if reordering + int header_size; ///< source header size + int trailer_size; ///< source trailer size + + /* derived values */ + int bpc; ///< bits used to reference channel positions + int last_samples; ///< number of samples in the final frame + int frames; ///< number of frames in the file + int ra_units; ///< number of random access units + uint32_t *ra_sizes; ///< sizes, in bytes, of random access units + int aux_size; ///< auxilliary data size + uint8_t *aux; ///< auxilliary data + int header_pos; ///< file position of source header + uint8_t *header; ///< source header + int trailer_pos; ///< file position of source trailer + uint8_t *trailer; ///< source trailer + int start_pos; ///< file position of first ALS frame + uint32_t ref_crc; ///< reference CRC-32 checksum + + /* global fields */ + AlsFrame frame; ///< current frame data + int frame_index; ///< frame index number + int ra_index; ///< random access index number + uint32_t crc; ///< running CRC-32 checksum of decoded audio + + /* internal buffers */ + int32_t **decoded; ///< decoded audio data + int max_frame_bytes; ///< estimated maximum coded bytes in a frame + uint8_t *bitstream; ///< internal bitstream buffer + int bitstream_size; ///< current buffer size + int bitstream_index; ///< current buffer index + unsigned int allocated_bitstream_size; ///< total buffer size + +} AlsDecodeContext; + +extern int als_decode_init(AlsDecodeContext *ctx, FILE *fp); + +extern int als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, + uint8_t *buf, int buf_size); + +extern int als_decode_close(AlsDecodeContext *ctx); + +#endif /* ALSDEC_H */ Added: alstab.h =================================================================== --- alstab.h (rev 0) +++ alstab.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,52 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alstab.h + * ALS tables + */ + +#ifndef ALSTAB_H +#define ALSTAB_H + +/* rice code parameters for each coeff: */ +typedef struct { + int offset; + int param; +} ParcorVars; + +static const ParcorVars parcor_vars[3][20] = { + // samplerate is 44.1kHz or 48kHz + { {-52, 4}, {-29, 5}, {-31, 4}, { 19, 4}, {-16, 4}, + { 12, 3}, { -7, 3}, { 9, 3}, { -5, 3}, { 6, 3}, + { -4, 3}, { 3, 3}, { -3, 2}, { 3, 2}, { -2, 2}, + { 3, 2}, { -1, 2}, { 2, 2}, { -1, 2}, { 2, 2} }, + // samplerate is 96kHz + { {-58, 3}, {-42, 4}, {-46, 4}, { 37, 5}, {-36, 4}, + { 29, 4}, {-29, 4}, { 25, 4}, {-23, 4}, { 20, 4}, + {-17, 4}, { 16, 4}, {-12, 4}, { 12, 3}, {-10, 4}, + { 7, 3}, { -4, 4}, { 3, 3}, { -1, 3}, { 1, 3} }, + // samplerate is 192kHz + { {-59, 3}, {-45, 5}, {-50, 4}, { 38, 4}, {-39, 4}, + { 32, 4}, {-30, 4}, { 25, 3}, {-23, 3}, { 20, 3}, + {-20, 3}, { 16, 3}, {-13, 3}, { 10, 3}, { -7, 3}, + { 3, 3}, { 0, 3}, { -1, 3}, { 2, 3}, { -1, 2} } +}; + +#endif /* ALSTAB_H */ Added: bitreader.c =================================================================== --- bitreader.c (rev 0) +++ bitreader.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,213 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is derived from libvorbis. + * Copyright (c) 2002, Xiph.org Foundation + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bitreader.c + * Memory-based bitwise reader + */ + +#include "bitreader.h" + +#include <stdlib.h> +#include <string.h> + +static const uint32_t mask[33] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, + 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, + 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, + 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; + +/* Bit Reader Functions */ + +void +init_get_bits(GetBitContext *b, uint8_t *buf, int bits) +{ + memset(b, 0, sizeof(*b)); + b->buffer = b->ptr = buf; + b->storage = (bits + 7) / 8; +} + +void +seek_bits(GetBitContext *b, int bitpos) +{ + int bytepos = bitpos >> 3; + if(bytepos < 0 || bytepos > b->storage) return; + b->ptr = &b->buffer[bytepos]; + b->endbyte = 0; + b->endbit = 0; +} + +void +skip_bits(GetBitContext *b, int bits) +{ + bits += b->endbit; + b->ptr += (bits >> 3); + b->endbyte += (bits >> 3); + b->endbit = (bits & 7); +} + +void +skip_bits1(GetBitContext *b) +{ + if(++(b->endbit) > 7) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +uint32_t +look_bits(GetBitContext *b, int bits) +{ + unsigned long ret; + int m = 32-bits; + + bits += b->endbit; + + if(((b->endbyte+4)>=b->storage) && ((b->endbyte*8+bits)>(b->storage*8))) { + return 0; + } + + ret = b->ptr[0] << (24+b->endbit); + if(bits > 8) { + ret |= b->ptr[1] << (16+b->endbit); + if(bits > 16) { + ret |= b->ptr[2] << (8+b->endbit); + if(bits > 24) { + ret |= b->ptr[3] << (b->endbit); + if(bits>32 && b->endbit) { + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + } + return (uint32_t)(((ret&0xFFFFFFFF)>>(m>>1))>>((m+1)>>1)); +} + +/* bits <= 32 */ +uint32_t +get_bits(GetBitContext *b, int bits) +{ + long ret; + long m = 32 - bits; + + bits += b->endbit; + + if(b->endbyte+4 >= b->storage) { + // not the main path + ret = 0; + if((b->endbyte * 8 + bits) > (b->storage * 8)) { + goto overflow; + } + } + + ret = b->ptr[0] << (24+b->endbit); + if(bits > 8) { + ret |= b->ptr[1] << (16+b->endbit); + if(bits > 16) { + ret |= b->ptr[2] << (8+b->endbit); + if(bits > 24) { + ret |= b->ptr[3] << (b->endbit); + if(bits > 32 && b->endbit) { + ret |= b->ptr[4] >> (8-b->endbit); + } + } + } + } + ret = ((ret & 0xFFFFFFFFUL)>>(m>>1))>>((m+1)>>1); + + overflow: + b->ptr += (bits >> 3); + b->endbyte += (bits >> 3); + b->endbit = (bits & 7); + return (uint32_t)ret; +} + +long +get_bits1(GetBitContext *b) +{ + long ret; + + if(b->endbyte >= b->storage) { + // not the main path + ret=-1L; + goto overflow; + } + + ret = (b->ptr[0] >> (7-b->endbit)) & 1; + + overflow: + + b->endbit++; + if(b->endbit > 7) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } + return ret; +} + +void +align_get_bits(GetBitContext *b) +{ + if(b->endbit) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } +} + +long +get_bits_count(GetBitContext *b) +{ + return (b->endbyte*8+b->endbit); +} + +int32_t +get_rice(GetBitContext *b, int rp) +{ + uint32_t j, k; + int32_t v; + + k = 0; + while(get_bits1(b)) + k++; + if(rp) { + j = get_bits(b, rp); + if(j & (1 << (rp-1))) + v = (k << (rp-1)) | (j & ((1 << (rp-1)) -1)); + else + v = -((k << (rp-1)) | j) - 1; + } else { + // special case for rice param == 0 + if(k & 1) + v = (-(int)k-1) >> 1; + else + v = k >> 1; + } + return v; +} Added: bitreader.h =================================================================== --- bitreader.h (rev 0) +++ bitreader.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,61 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is derived from libvorbis. + * Copyright (c) 2002, Xiph.org Foundation + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bitreader.h + * Memory-based bitwise reader + */ + +#ifndef BITREADER_H +#define BITREADER_H + +#include <stdint.h> + +typedef struct { + long endbyte; + int endbit; + uint8_t *buffer; + uint8_t *ptr; + long storage; +} GetBitContext; + +extern void init_get_bits(GetBitContext *b, uint8_t *buf, int bits); + +extern void seek_bits(GetBitContext *b, int bitpos); + +extern void skip_bits(GetBitContext *b, int bits); + +extern void skip_bits1(GetBitContext *b); + +extern uint32_t look_bits(GetBitContext *b, int bits); + +extern uint32_t get_bits(GetBitContext *b, int bits); + +extern long get_bits1(GetBitContext *b); + +extern void align_get_bits(GetBitContext *b); + +extern long get_bits_count(GetBitContext *b); + +extern int32_t get_rice(GetBitContext *b, int rp); + +#endif /* BITREADER_H */ Added: bswap.h =================================================================== --- bswap.h (rev 0) +++ bswap.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,79 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is based on FFmpeg/libavutil/bswap.h + * Copyright (c) 2006 Michael Niedermayer + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bswap.h + * Byte swap + */ + +#ifndef BSWAP_H +#define BSWAP_H + +#include "common.h" + +#ifdef HAVE_BYTESWAP_H +#include <byteswap.h> +#else + +static inline uint16_t bswap_16(uint16_t x){ + return (x>>8) | (x<<8); +} + +static inline uint32_t bswap_32(uint32_t x){ + x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); + return (x>>16) | (x<<16); +} + +static inline uint64_t bswap_64(uint64_t x) +{ + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32(w.l[1]); + r.l[1] = bswap_32(w.l[0]); + return r.ll; +} + +#endif /* !HAVE_BYTESWAP_H */ + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif /* BSWAP_H */ Added: common.h =================================================================== --- common.h (rev 0) +++ common.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,120 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file common.h + * Common header file + */ + +#ifndef COMMON_H +#define COMMON_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else +#if defined(_WIN32) && defined(_MSC_VER) + +// integer types +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +// limits +#define INT8_MIN _I8_MIN +#define INT8_MAX _I8_MAX +#define UINT8_MAX _UI8_MAX +#define INT16_MIN _I16_MIN +#define INT16_MAX _I16_MAX +#define UINT16_MAX _UI16_MAX +#define INT32_MIN _I32_MIN +#define INT32_MAX _I32_MAX +#define UINT32_MAX _UI32_MAX +#define INT64_MIN _I64_MIN +#define INT64_MAX _I64_MAX +#define UINT64_MAX _UI64_MAX + +// fprintf macros +#define PRId8 "d" +#define PRIi8 "i" +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" + +#endif +#endif /* EMULATE_INTTYPES */ + +#if __GNUC__ && !__INTEL_COMPILER +#define ALIGN16(x) x __attribute__((aligned(16))) +#else +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define ALIGN16(x) __declspec(align(16)) x +#else +#define ALIGN16(x) x +#endif +#endif + +#ifdef _WIN32 +#define CDECL __cdecl +#ifdef _MSC_VER +#define inline __inline +#endif /* _MSC_VER */ +#else +#define CDECL +#endif + +#define LOG2(a) (log((a)) / log(2.0)) + +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define CLIP(x,min,max) MAX(MIN((x), (max)), (min)) + +#include "bswap.h" + +#endif /* COMMON_H */ Added: config.h =================================================================== --- config.h (rev 0) +++ config.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,2 @@ +#define HAVE_INTTYPES_H 1 +// #define WORDS_BIGENDIAN Added: config.mak =================================================================== --- config.mak (rev 0) +++ config.mak 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,17 @@ +# set these to your liking + +CC = gcc + +RM = rm -f + +MAKE = make + +DEBUG_CFLAGS = -g + +EXTRA_CFLAGS = -O3 -fomit-frame-pointer + +WARNING_CFLAGS = -Wall -pedantic -std=c99 + +CFLAGS = $(DEBUG_CFLAGS) $(EXTRA_CFLAGS) $(WARNING_CFLAGS) + +EXEEXT = Added: main.c =================================================================== --- main.c (rev 0) +++ main.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,184 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file main.c + * commandline front-end + */ + +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> + +#include "alsdec.h" + +static void +print_als_header(AlsDecodeContext *ctx) +{ + fprintf(stderr, "** ALS HEADER **\n"); + fprintf(stderr, "sample rate: %u\n", ctx->sample_rate); + fprintf(stderr, "sample count: %u\n", ctx->samples); + fprintf(stderr, "channels: %d\n", ctx->channels); + switch(ctx->file_type) { + case FILE_TYPE_RAW: fprintf(stderr, "source file type: raw\n"); break; + case FILE_TYPE_WAVE: fprintf(stderr, "source file type: wave\n"); break; + case FILE_TYPE_AIFF: fprintf(stderr, "source file type: aiff\n"); break; + } + fprintf(stderr, "bits-per-sample: %d\n", ctx->bps); + switch(ctx->sample_type) { + case SAMPLE_TYPE_INT: fprintf(stderr, "sample type: integer\n"); break; + case SAMPLE_TYPE_FLOAT: fprintf(stderr, "sample type: floating-point\n"); break; + } + switch(ctx->source_order) { + case SRC_ORDER_LE: fprintf(stderr, "source byte order: little-endian\n"); break; + case SRC_ORDER_BE: fprintf(stderr, "source byte order: big-endian\n"); break; + } + fprintf(stderr, "frame size: %d\n", ctx->frame_size); + fprintf(stderr, "frame count: %d\n", ctx->frames); + if(ctx->random_access) { + fprintf(stderr, "random access: yes\n"); + fprintf(stderr, " ra interval: %d\n", ctx->random_access); + switch(ctx->ra_location) { + case RA_LOCATION_FRAME: fprintf(stderr, " ra location: frames\n"); break; + case RA_LOCATION_HEADER: fprintf(stderr, " ra location: header\n"); break; + } + fprintf(stderr, " number of ra units: %d\n", ctx->ra_units); + if(ctx->ra_location == RA_LOCATION_HEADER) { + int i; + for(i=0; i<ctx->ra_units; i++) { + fprintf(stderr, " %04d : %u\n", i, ctx->ra_sizes[i]); + } + } + } else { + fprintf(stderr, "random access: no\n"); + } + fprintf(stderr, "adaptive pred order: %s\n", ctx->adapt_order?"yes":"no"); + fprintf(stderr, "coefficient table: %d\n", ctx->coef_table); + fprintf(stderr, "long-term prediction: %s\n", ctx->ltp?"yes":"no"); + fprintf(stderr, "%sprediction order: %d\n", ctx->adapt_order?"max ":"", + ctx->pred_order); + fprintf(stderr, "block switching: %s\n", ctx->blksw?"yes":"no"); + switch(ctx->coding_type) { + case CODING_TYPE_RICE: fprintf(stderr, "entropy coding type: rice\n"); break; + case CODING_TYPE_BGMC: fprintf(stderr, "entropy coding type: bgmc\n"); break; + } + fprintf(stderr, "entropy partitioning: %s\n", ctx->coding_part?"yes":"no"); + fprintf(stderr, "joint stereo: %s\n", ctx->joint_stereo?"yes":"no"); + fprintf(stderr, "multi-channel correlation: %s\n", ctx->mcc?"yes":"no"); + fprintf(stderr, "channel configuration: %s\n", ctx->ch_config?"yes":"no"); + fprintf(stderr, "channel reordering: %s\n", ctx->ch_reorder?"yes":"no"); + if(ctx->ch_reorder) { + int ch; + for(ch=0; ch<ctx->channels; ch++) { + fprintf(stderr, " %d -> %d\n", ch, ctx->ch_pos[ch]); + } + } + if(ctx->has_crc) fprintf(stderr, "CRC: 0x%08X\n", ctx->ref_crc); + else fprintf(stderr, "CRC: none\n"); + fprintf(stderr, "rls-lms prediction: %s\n", ctx->rlslms?"yes":"no"); + if(ctx->has_aux) fprintf(stderr, "auxiliary data: %d\n", ctx->aux_size); + else fprintf(stderr, "auxiliary data: none\n"); + fprintf(stderr, "header size: %d\n", ctx->header_size); + fprintf(stderr, "trailer size: %d\n", ctx->trailer_size); + fprintf(stderr, "\n"); +} + +int +main(int argc, char **argv) +{ + FILE *fp; + char *fname; + AlsDecodeContext ctx; + int err=0; + uint8_t *data=NULL; + int data_size; + uint8_t *buf=NULL; + int buf_size; + int sample_count=0; + + if(argc != 2) { + fprintf(stderr, "\nusage: decals input.als\n"); + return 0; + } + fname = argv[1]; + fp = fopen(fname, "rb"); + if(!fp) { + fprintf(stderr, "cannot open file: %s\n", fname); + return 1; + } + + err = als_decode_init(&ctx, fp); + switch(err) { + case ALS_ERROR_GENERAL: fprintf(stderr, "error reading ALS header\n"); break; + case ALS_ERROR_MEMORY: fprintf(stderr, "out-of-memory error\n"); break; + case ALS_ERROR_EOF: fprintf(stderr, "end-of-file error\n"); break; + } + if(err) { + goto cleanup; + } + print_als_header(&ctx); + + data = calloc(ctx.channels * ctx.frame_size, sizeof(int32_t)); + if(!data) { + fprintf(stderr, "out-of-memory error\n"); + goto cleanup; + } + + buf_size = 16384; + buf = calloc(buf_size, 1); + if(!buf) { + fprintf(stderr, "out-of-memory error\n"); + goto cleanup; + } + + + do { + int consumed = 0; + data_size = 0; + do { + err = fread(buf, 1, buf_size, fp); + if(err > 0) { + consumed = als_decode_frame(&ctx, data, &data_size, buf, err); + data_size /= (sizeof(int32_t) * ctx.channels); + //fprintf(stderr, "consumed = %d\n", consumed); + } + } while(err > 0 && data_size == 0); + if(err > 0) { + sample_count += data_size; + fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); + while(data_size > 0 && (!ctx.samples || sample_count < ctx.samples)) { + consumed = als_decode_frame(&ctx, data, &data_size, NULL, 0); + data_size /= (sizeof(int32_t) * ctx.channels); + //fprintf(stderr, "consumed = %d\n", consumed); + if(data_size > 0) { + sample_count += data_size; + fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); + } + } + } + } while(err > 0 && (!ctx.samples || sample_count < ctx.samples)); + +cleanup: + if(data) free(data); + if(buf) free(buf); + fclose(fp); + als_decode_close(&ctx); + return err; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jb...@us...> - 2007-08-20 00:07:56
|
Revision: 1 http://decals.svn.sourceforge.net/decals/?rev=1&view=rev Author: jbr79 Date: 2007-08-19 17:07:52 -0700 (Sun, 19 Aug 2007) Log Message: ----------- initial SVN import Added Paths: ----------- mp4-als_format_notes.txt Added: mp4-als_format_notes.txt =================================================================== --- mp4-als_format_notes.txt (rev 0) +++ mp4-als_format_notes.txt 2007-08-20 00:07:52 UTC (rev 1) @@ -0,0 +1,635 @@ + +MPEG-4 Audio Lossless Coding (ALS) Documentation +------------------------------------------------ + + +MPEG-4 Audio Lossless Coding[1][2], also called MP4-ALS, is one of the lossless +audio coding formats which is part of the MPEG-4 audio specification. It is +based on the LPAC audio codec[3] by Tilman Liebchen. This document covers the +raw ALS format, which consists of the ALS header and a sequence of frames. + + + +KEY CONCEPTS +============ + +Original file preservation +-------------------------- +The ALS header can provide everything that is needed to reconstruct the +original WAVE, AIFF, or raw audio file. This includes the file type, +sample rate, number of channels, bits-per-sample, sample type, and byte order. +The original header and/or footer are also preserved exactly in the ALS +header. The ALS format only supports from 8-bit to 32-bit audio in 8-bit +increments. Either integer or IEEE-floating-point sample types are supported. + + +Frame size and block switching +------------------------------ +The ALS frame size (number of audio samples) is fixed for a given stream or +file. All audio samples for a single channel in a frame is referred to as a +block. In order to adapt to transient signals, each block can be divided +into recursive subblocks. Each subblock can be split into 2 smaller subblocks, +down to 1/32 of the original frame size. + + +Random access +------------- +Seeking is an important feature for any audio format. It allows the decoder to +jump forward or backward to the start of a frame without having to decode all +frames in between. In the ALS format, the encoder can optionally include +so called "random access" frames to achieve this goal. The ALS header +specifies a random access interval from 0 to 255. A value of 0 indicates no +random access frames, 1 means every frame is a random access frame, 2 means +every other frame, etc... Each set of frames between random access frames is +call a random access unit. The encoder indicates the size of each random +access unit by either writing them all in the header or by writing it at the +start of each random access frame. The ra_location field in the ALS header +tells which of the 2 locations are used. + +I'm going to go ahead and gripe here about this design. The problem I see is +that using random access frames is optional, and that there is no unique +identifier for frame boundaries. This prevents a decoder from finding random +frames without both a reference point and either random access information or +by decoding every frame between the reference and the destination. + + +Channels +-------- +ALS has 2 different ways of reducing redundancy between multiple channels. The +first method is joint stereo coding. The encoder calculates the difference +between 2 channels and selects 2 of left+right, left+diff, or right+diff. For +files with more than 2 channels, joint stereo can still be used by grouping the +channels into sets of pairs and individual channels. For example, encoding of +standard 5.1 audio could be done as L+R, C, LFE, LS+RS. The format allows for +reordering of the channels from their original positions in order to pair them +together if necessary. + +The 2nd method is called multi-channel correlation, or MCC. This method uses +adaptive subtraction to compare the prediction residual of reference channels +to the remaining channels. This is a more complex procedure which I will +descibe later once I fully understand the math behind it. + + +Forward Prediction +------------------ +The primary prediction method in ALS is forward linear predictive coding, or +LPC[4][5]. There are several ways to select good prediction coefficients. The +recommended method for ALS is Levinson-Durbin Recursion[6][7]. This is a good +method for 2 reasons. First of all, it sequentially produces higher order +coefficients, which is ideal for adapting the prediction order for each block. +Secondly, it produces parcor (reflection) coefficients as an intermediate +result, which are the values that are quantized and written to the ALS +bitstream. The standard defines a bit-exact method for transforming the +quantized parcor coefficients into the LPC coefficients used for linear +prediction. + +One of the unique features of the ALS format is that it uses progressively +increasing prediction orders for the first samples in random access frames, +which cannot reference previous samples. Other formats, such as FLAC, write the +first samples directly, then proceed with prediction using the full number of +coefficients. In ALS, the first sample is written directly, but each subsequent +sample is predicted using increasingly higher orders until the full prediction +order is reached. + + +Long-Term Prediction +-------------------- +Also called pitch coding, long-term prediction as implemented in ALS reduces +signal redundancy by predicting the value of an LPC residual sample using the +average value of 5 residual samples at a specified time lag with a specified +gain value. The optimal lag and gain values are determined for each frame by the +encoder. This is called pitch coding because the frequency, or pitch, of a +signal leads to periodic redundancy. If the period is calculated, it can be +exploited in order to remove that redundancy from the encoded output. This +algorithm is typically used in speech codecs, such as Speex. + + +RLSLMS (Recursive Least Squares, Least Mean Square) backward prediction +----------------------------------------------------------------------- +ALS has an alternative backward prediction mode, which uses the recursive least +squares algorithm[8]. + +Entropy Coding +-------------- +In ALS, both the prediction coefficients and the residual signal are compressed +using entropy coding. The encoder can choose between 2 different methods, +Golomb-Rice Coding[9] and Block Gilbert-Moore Coding (BGMC). Rice coding is a +form of Huffman coding, while BGMC, also called Shannon-Fano-Elias coding, is a +precursor of arithmetic coding. + + +Floating-Point Data +------------------- +The ALS format provides the ability to losslessly encode floating-point[10] +audio. The floating-point signal is basically broken down into an integer signal +plus the residual signal. The integer signal is encoded using the standard ALS +algorithm, while the residual is encoded using the Masked-Lempel-Ziv +dictionary-based compression scheme[11]. + + +References +---------- +[1] http://www.nue.tu-berlin.de/forschung/projekte/lossless/mp4als.html +[2] http://en.wikipedia.org/wiki/Audio_Lossless_Coding +[3] http://www.nue.tu-berlin.de/wer/liebchen/lpac.html +[4] http://en.wikipedia.org/wiki/Linear_predictive_coding +[5] http://en.wikipedia.org/wiki/Linear_prediction +[6] http://en.wikipedia.org/wiki/Levinson_recursion +[7] http://en.wikipedia.org/wiki/Autocorrelation +[8] http://en.wikipedia.org/wiki/Recursive_least_squares_filter +[9] http://en.wikipedia.org/wiki/Golomb_coding +[10] http://en.wikipedia.org/wiki/IEEE_floating-point_standard +[11] http://en.wikipedia.org/wiki/Dictionary_coder + + + +BITSTREAM FORMAT +================ + +ALS Header +---------- +In the raw ALS file format, the ALS header is located at the beginning of the +bitstream, and is transmitted only once. It contains information about the +audio and global properties of the encoded ALS bitstream. + +als_header() { + fixed_portion() 22 bytes + if(channel_config) { + ch_config 16 bits + } + if(channel_reorder) { + // number of bits used to code each channel position + ch_bits = max(1, ceil(log2(channels))) + for(i=0; i<channels; i++) { + channel_position[i] ch_bits + } + } + header_size 32 bits + trailer_size 32 bits + header() header_size + trailer() trailer_size +} + +The fixed portion of the ALS header is always 22 bytes long. The field layout is +given in Table 1. If the channel configuration flag is indicated, the +configuration data is written. The channel configuration data is currently not +used, and neither its purpose nor its format are given in the draft spec or in +the reference software. If the channel reorder flag is indicated, the channel +layout is written. The number of bits used to encode the position of each +channel is determined as the minimum number of bits needed to encode the +highest channel index. Next, the header size and trailer size (in bytes) are +written. These sizes are used by the decoder to read the original header and +trailer, which make up the last 2 fields of the ALS header. + +Table 1 : 22-byte fixed portion of the ALS header ++------------------------------------------------------------------------------+ +|bits |parameter |description | +|==========+==================+================================================| +|32 |magic number |"ALS\0" or 0x414C5300. Indicates that this is | +| | |an ALS file | +|----------+------------------+------------------------------------------------| +|32 |sample rate |Audio sampling frequency, e.g. 44100 | +|----------+------------------+------------------------------------------------| +|32 |samples |Total number of samples in the file | +|----------+------------------+------------------------------------------------| +|16 |channels |Number of channels - 1 | +|----------+------------------+------------------------------------------------| +|3 |file type |Type of the original audio file | +| | |0=raw/unknown 1=WAVE 2=AIFF | +|----------+------------------+------------------------------------------------| +|3 |resolution |Bits-per-sample/8 - 1 | +|----------+------------------+------------------------------------------------| +|1 |sample type |0=integer samples 1=floating-point samples | +|----------+------------------+------------------------------------------------| +|1 |source order |Source sample endianness 0=little 1=big | +|----------+------------------+------------------------------------------------| +|16 |frame size |Source frame size - 1 (measured in samples) | +|----------+------------------+------------------------------------------------| +|8 |random access |Random access frame interval 0=no RA frames | +|----------+------------------+------------------------------------------------| +|2 |ra location |Random access data location | +| | |0=none 1=frames 2=header | +|----------+------------------+------------------------------------------------| +|1 |adapt |Indicates use of adaptive LPC order | +|----------+------------------+------------------------------------------------| +|2 |coef table |Selects 1 of the 3 tables of Rice code | +| | |parameters used to encode parcor coefficients. | +| | |Selection is generally based on the sample rate.| +| | |3=use 7-bit quantizer instead of Rice coding. | +| | |See Tables 2, 3, and 4 | +|----------+------------------+------------------------------------------------| +|1 |long-term pred |Indicates use of long-term prediction | +|----------+------------------+------------------------------------------------| +|10 |max order |Maximum LPC order | +|----------+------------------+------------------------------------------------| +|2 |block switching |Indicates use of block switching and maximum | +| | |level of block division | +|----------+------------------+------------------------------------------------| +|1 |entropy coder |Type of entropy coder used 0=Rice 1=BGMC | +|----------+------------------+------------------------------------------------| +|1 |subblock part |Indicates partitioned entropy coding | +|----------+------------------+------------------------------------------------| +|1 |joint stereo |Indicates use of joint stereo coding | +|----------+------------------+------------------------------------------------| +|1 |mcc |Indicates use of multi-channel correlation | +|----------+------------------+------------------------------------------------| +|1 |channel config |Indicates presence of channel configuration | +|----------+------------------+------------------------------------------------| +|1 |channel reorder |Indicates presence of channel reordering | +|----------+------------------+------------------------------------------------| +|1 |has crc |Indicates presence of reference CRC checksum | +|----------+------------------+------------------------------------------------| +|1 |rlslms |Indicates use of RLSLMS backward prediction | +|----------+------------------+------------------------------------------------| +|5 |reserved |Not used | +|----------+------------------+------------------------------------------------| +|1 |aux enabled |Indicates presence of auxilliary data | ++------------------------------------------------------------------------------+ + +Table 2 : Coef table 0 : Rice code params for encoding of parcor coefficients + Recommended for 44kHz and 48kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-52 |4 | +|------------+-------+-----------| +|1 |-29 |5 | +|------------+-------+-----------| +|2 |-31 |4 | +|------------+-------+-----------| +|3 |19 |4 | +|------------+-------+-----------| +|4 |-16 |4 | +|------------+-------+-----------| +|5 |12 |3 | +|------------+-------+-----------| +|6 |-7 |3 | +|------------+-------+-----------| +|7 |9 |3 | +|------------+-------+-----------| +|8 |-5 |3 | +|------------+-------+-----------| +|9 |6 |3 | +|------------+-------+-----------| +|10 |-4 |3 | +|------------+-------+-----------| +|11 |3 |3 | +|------------+-------+-----------| +|12 |-3 |2 | +|------------+-------+-----------| +|13 |3 |2 | +|------------+-------+-----------| +|14 |-2 |2 | +|------------+-------+-----------| +|15 |3 |2 | +|------------+-------+-----------| +|16 |-1 |2 | +|------------+-------+-----------| +|17 |2 |2 | +|------------+-------+-----------| +|18 |-1 |2 | +|------------+-------+-----------| +|19 |2 |2 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + +Table 3 : Coef table 1 : Rice code params for encoding of parcor coefficients + Recommended for 96kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-58 |3 | +|------------+-------+-----------| +|1 |-42 |4 | +|------------+-------+-----------| +|2 |-46 |4 | +|------------+-------+-----------| +|3 |37 |5 | +|------------+-------+-----------| +|4 |-36 |4 | +|------------+-------+-----------| +|5 |29 |4 | +|------------+-------+-----------| +|6 |-29 |4 | +|------------+-------+-----------| +|7 |25 |4 | +|------------+-------+-----------| +|8 |-23 |4 | +|------------+-------+-----------| +|9 |20 |4 | +|------------+-------+-----------| +|10 |-17 |4 | +|------------+-------+-----------| +|11 |16 |4 | +|------------+-------+-----------| +|12 |-12 |4 | +|------------+-------+-----------| +|13 |12 |3 | +|------------+-------+-----------| +|14 |-10 |3 | +|------------+-------+-----------| +|15 |7 |3 | +|------------+-------+-----------| +|16 |-4 |3 | +|------------+-------+-----------| +|17 |3 |3 | +|------------+-------+-----------| +|18 |-1 |3 | +|------------+-------+-----------| +|19 |1 |3 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + +Table 4 : Coef table 2 : Rice code params for encoding of parcor coefficients + Recommended for 192kHz ++--------------------------------+ +|coef number |offset |rice param | +|============+=======+===========| +|0 |-59 |3 | +|------------+-------+-----------| +|1 |-45 |5 | +|------------+-------+-----------| +|2 |-50 |4 | +|------------+-------+-----------| +|3 |38 |4 | +|------------+-------+-----------| +|4 |-39 |4 | +|------------+-------+-----------| +|5 |32 |4 | +|------------+-------+-----------| +|6 |-30 |4 | +|------------+-------+-----------| +|7 |25 |3 | +|------------+-------+-----------| +|8 |-23 |3 | +|------------+-------+-----------| +|9 |20 |3 | +|------------+-------+-----------| +|10 |-20 |3 | +|------------+-------+-----------| +|11 |16 |3 | +|------------+-------+-----------| +|12 |-13 |3 | +|------------+-------+-----------| +|13 |10 |3 | +|------------+-------+-----------| +|14 |-7 |3 | +|------------+-------+-----------| +|15 |3 |3 | +|------------+-------+-----------| +|16 |0 |3 | +|------------+-------+-----------| +|17 |-1 |3 | +|------------+-------+-----------| +|18 |2 |3 | +|------------+-------+-----------| +|19 |-1 |3 | +|------------+-------+-----------| +|2k, k>=10 |0 |2 | +|------------+-------+-----------| +|2k+1, k>=10 |1 |2 | +|------------+-------+-----------| +|k>=127 |0 |1 | ++--------------------------------+ + + +ALS Frame +--------- +if(RA is enabled, RA location is in frames, and current frame is an RA frame) { + * random access unit size, 32 bits +} +if(MCC is enabled) { + if(joint stereo is not enabled) { + * use MCC for this frame + } else { + * read 8 bits to determine if this frame uses MCC + seems only 1 bit should be needed. not sure what the other 7 bits are + used for... + } +} +if(MCC is not enabled and RLS-LMS is not enabled) { + for each channel or channel pair { + + * enabled coupled block switching if joint stereo is enabled, this is + the first channel in a pair, and this is not the last channel + + if(block switching is enabled) { + * read block switch flags (8-bit, 16-bit or 32-bit) + coupled block switching can be explicitly turned off here + } else { + * use only 1 subblock at full frame size + } + + if(coupled block switching is enabled) { + for each subblock { + * decode subblock for 1st channel in pair + * decode subblock for 2nd channel in pair + * restore original signal if one of the pair is difference signal + } + } else { + for each subblock { + * decode subblock. + * if coupled block switching is explicitly disabled for this, + pair, reconstruct the difference signal after reading the 2nd + channel in the pair. this is for use as predictor context for + the next frame. + } + } + } +} else if(RLS-LMS is enabled) { + TODO: complete this section +} else if(MCC is enabled) { + TODO: complete this section +} + +Block switch flags +------------------ +The block switch value in the header indicates the number of flag bits that are +contained in each block. If all 32 bits are not used, the flag bits are left +aligned in a 32-bit integer. This 32-bit integer making up the block switch +flags is treated as an array of 1-bit values containing a binary tree. Index 0 +(the high bit) indicates if channel coupling is turned off in order to do +independent block switching. The root node is located at index 1. The layout +follows the standard binary-tree-in-array implementation. For a node at index i, +the parent node is at i/2, the first child is at i*2, and the second child is at +i*2+1. If a node has a value of 1, the corresponding subblock is split into 2 +smaller equal-sized subblocks. If a node has a value of 0, the subblock is not +split. The smallest subblock size is 1/32 of the original frame size. For the +last frame in the stream, which may be smaller than all the other frames, the +subblocks are divided as if it were a full-size frame, but only the number of +subblocks which are needed to fit the final number of samples are used, with +the last subblock being truncated if needed. + + +ALS Subblock +------------ +* align bitstream to 8-bit boundary +* 1-bit frame type. 0=zero or constant, 1=normal +if(frame type is zero or constant) { + * 1-bit frame type. 0=zero, 1=constant +} +* 1-bit difference flag indicates if this subblock contains a normal + signal or a difference signal. +if(frame type is constant) { + * align bitstream to 8-bit boundary + * read 1 sample. size based on sample resolution in the ALS header. +} else if(frame type is normal) { + // determine entropy partitioning and read entropy coding parameters + if(coding type is Rice) { + if(entropy partitioning is enabled) { + * 1-bit partition flag. 0=1 partition, 1=4 partitions + } else { + * only 1 partition + } + * read 1st Rice parameter (4-bit if depth<=16-bit, 5-bit if >16-bit) + if(partitioning is enabled) { + * read 3 remaining delta-encoded Rice parameters. deltas are Rice + encoded using parameter=0. + } + } else if(coding type is BGMC) { + if(entropy partitioning is enabled) { + * 2-bit partition order. 2^x partitions (1, 2, 4, or 8) + } else { + * 1-bit partition flag. 0=1 partition, 1=4 partitions + } + * read 1st BGMC parameter (8-bit if depth<=16-bit, 9-bit if >16-bit) + * read remaining delta-encoded Rice parameters. deltas are Rice + encoded using parameter=2. + * separate grouped BGMC parameters: + s = p >> 4 + sx = p & 0x0F + } + // shift (unused LSB's) + * read 1-bit shift flag + if(shift flag) { + * read 4-bit shift value, add 1. this is the number of unused LSB's. + } + // decode and reconstruct LPC coefficients + if(using LPC prediction [not RLS-LMS]) { + // determine LPC order + * order = fixed/max prediction order (from ALS header) + if(adaptive prediction order is used) { + * limit max order to range [1 ... (subblock size / 8) - 1] + * read order for this subblock using number of bits required to + store max order. + } + // decode quantized coefficients + if(not using a coefficient table [ct=3]) { + * read each quantized coefficient as 7-bit value - 64 + } else { + * read quantized coefficients from bitstream using rice params from + the coefficient table. + * apply the offsets from the coefficient table + } + // reconstruct parcor coefficients + * reconstruct 1st coefficient from the quantized coefficient using the + scale parcor coefficient formula below: + where qc has a range of -64 to 63, + coeff = 32 + ((qc+64)*(qc+65)*128) - (1 << 20) + * reconstruct the 2nd coefficient the same way, then reverse the sign. + * reconstruct remaining coefficients using + coeff = (qc << (Q-6)) + (1 << (Q-7)), where Q=20 + = (qc << 14) + (1 << 13) + = (qc * 16384) + 8192 + } else if(using RLS-LMS) { + * order = 10 + } + if(using LTP) { + // decode 5 LTP coefficients and lag + c0 = signed rice code (rp=1) + c1 = signed rice code (rp=2) + c2 = unsigned rice code (rp=2) + c3 = signed rice code (rp=2) + c4 = signed rice code (rp=1) + lag = x-bit unsigned value, where x = 8 + (samplerate / 96000) + } + // decode residual for this subblock + if(no random access for this frame) { + for(each entropy coding partition) { + if(coding type is Rice) + * decode residual for partition using Rice parameters + if(coding type is BGMC) + * decode residual for partition using BGMC parameters + } + } else { + // in RA frames, first residual values are larger because they are + // progressively predicted, so a different entropy coding is used in + // order to encode more efficiently + * decode up to 3 residuals separately, up to prediction order. + r0 = signed rice code (rp=bitdepth-4 [e.g. 16-4=12]) + r1 = signed rice code (rp=1st rice parameter + 3 [max=31]) + r2 = signed rice code (rp=1st rice parameter + 1 [max=31]) + this will make the 1st partition shorter + for(each entropy coding partition) { + if(coding type is Rice) + * decode residual for partition using Rice parameters + if(coding type is BGMC) + * decode residual for partition using BGMC parameters + } + } +} +if(using RLS-LMS prediction) { + // TODO: RLS-LMS parameter decoding +} +if(using MCC) { + // TODO: decode MCC reference channels and weighting factors +} + + +Reconstructing the signal (LPC mode, no MCC) +-------------------------------------------- +When LPC is used, each subblock contains its own set of LPC coefficients. +After the residual has been decoded, the signal can be reconstructed using +inverse linear prediction. When decoding the 1st subblock of a random access +frame, progressive linear prediction is used because of the lack of access to +previous "warm-up" samples. + +if(frame type is zero) { + * set all samples for the subblock to zero +} else if(frame type is constant) { + * set all samples for the subblock to previously decoded constant value +} else if(frame type is normal) { + * temporarily apply shift to warm-up samples from previous block + if(using LTP) { + * reconstruct final residual by reversing LTP + } + if(not a random access frame) { + * convert parcor coefficients to LPC coefficients using pseudo-code + below. keep in mind the need to avoid integer data type overflow. + for(m=0; m<pred_order; m++) { + for(i=0; i<m/2; i++) { + temp = lpc[ i] + (((par[m] * lpc[m-i]) + (1<<19)) >> 20); + temp2 = lpc[m-i] + (((par[m] * lpc[ i]) + (1<<19)) >> 20); + lpc[m-i] = temp2; + lpc[ i] = temp; + } + lpc[m] = par[m]; + } + * inverse linear prediction using code below + note that samples below index 0 are from the previous subblock + for(each sample, at index n, in the subblock) { + sum = 0; + for(i=0; i<pred_order; i++) + sum += lpc[i] * signal[n-i-1]; + signal[n] = residual[n] - ((sum + (1 << 19)) >> 20); + } + } else if(random access frame) { + // TODO: RA inverse LPC (progressive prediction) + } + * undo shift from warm-up samples and block samples +} + + +TODO: Reconstructing the signal (RLS-LMS mode) + +TODO: Reconstructing the signal (MCC mode) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |