ref: 20faadc49d21f56dc1b9a50a5b76774e39153166
parent: 7caf982e9711c30024db3149fca39c6ae5fbee6f
author: corrados <corrados>
date: Sun Jul 4 08:12:05 EDT 2004
made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set) implemented HCR tool, VCB11, CRC, scalable bitstream order note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32 960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
--- a/include/faac.h
+++ b/include/faac.h
@@ -16,7 +16,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: faac.h,v 1.32 2003/11/24 18:10:32 knik Exp $
+ * $Id: faac.h,v 1.33 2004/07/04 12:12:05 corrados Exp $
*/
#ifndef _FAAC_H_
@@ -48,6 +48,10 @@
typedef void *faacEncHandle;
+
+#ifndef HAVE_INT32_T
+typedef int int32_t;
+#endif
/*
Allows an application to get FAAC version info. This is intended
--- a/include/faaccfg.h
+++ b/include/faaccfg.h
@@ -16,7 +16,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: faaccfg.h,v 1.2 2003/10/29 10:31:24 stux Exp $
+ * $Id: faaccfg.h,v 1.3 2004/07/04 12:12:05 corrados Exp $
*/
#ifndef _FAACCFG_H_
@@ -29,10 +29,10 @@
#define MPEG4 0
/* AAC object types */
-#define MAIN 0
-#define LOW 1
-#define SSR 2
-#define LTP 3
+#define MAIN 1
+#define LOW 2
+#define SSR 3
+#define LTP 4
/* Input Formats */
#define FAAC_INPUT_NULL 0
--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -17,7 +17,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: aacquant.c,v 1.29 2003/12/17 21:00:22 knik Exp $
+ * $Id: aacquant.c,v 1.30 2004/07/04 12:10:52 corrados Exp $
*/
#include <math.h>
@@ -229,6 +229,11 @@
/* place the codewords and their respective lengths in arrays data[] and len[] respectively */
/* there are 'counter' elements in each array, and these are variable length arrays depending on the input */
+#ifdef DRM
+ coderInfo->iLenReordSpData = 0; /* init length of reordered spectral data */
+ coderInfo->iLenLongestCW = 0; /* init length of longest codeword */
+ coderInfo->cur_cw = 0; /* init codeword counter */
+#endif
coderInfo->spectral_count = 0;
sb = 0;
for(i = 0; i < coderInfo->nr_of_sfb; i++) {
@@ -239,9 +244,10 @@
coderInfo->sfb_offset[i],
coderInfo->sfb_offset[i+1]-coderInfo->sfb_offset[i]);
- if (coderInfo->book_vector[i])
- sb = i;
+ if (coderInfo->book_vector[i])
+ sb = i;
}
+
// FIXME: Check those max_sfb/nr_of_sfb. Isn't it the same?
coderInfo->max_sfb = coderInfo->nr_of_sfb = sb + 1;
@@ -598,7 +604,7 @@
{
int i,j,ii;
int index = 0;
- double xr_tmp[1024];
+ double xr_tmp[FRAME_LEN];
int group_offset=0;
int k=0;
int windowOffset = 0;
@@ -626,13 +632,13 @@
for (k=0; k<*nr_of_sfb; k++) {
for (j=0; j < window_group_length[i]; j++) {
for (ii=0;ii< sfb_width_table[k];ii++)
- xr_tmp[index++] = xr[ii+ sfb_offset[k] + 128*j +group_offset];
+ xr_tmp[index++] = xr[ii+ sfb_offset[k] + BLOCK_LEN_SHORT*j +group_offset];
}
}
- group_offset += 128*window_group_length[i];
+ group_offset += BLOCK_LEN_SHORT*window_group_length[i];
}
- for (k=0; k<1024; k++){
+ for (k=0; k<FRAME_LEN; k++){
xr[k] = xr_tmp[k];
}
--- a/libfaac/bitstream.c
+++ b/libfaac/bitstream.c
@@ -24,7 +24,7 @@
Copyright (c) 1997.
**********************************************************************/
/*
- * $Id: bitstream.c,v 1.27 2003/10/14 15:23:44 menno Exp $
+ * $Id: bitstream.c,v 1.28 2004/07/04 12:10:52 corrados Exp $
*/
#include <stdio.h>
@@ -99,9 +99,19 @@
int numBit);
static int ByteAlign(BitStream* bitStream,
int writeFlag);
+#ifdef DRM
+static int PutBitHcr(BitStream *bitStream,
+ unsigned long curpos,
+ unsigned long data,
+ int numBit);
+static int rewind_word(int W, int len);
+static int WriteReorderedSpectralData(CoderInfo *coderInfo,
+ BitStream *bitStream,
+ int writeFlag);
+static void calc_CRC(BitStream *bitStream, int len);
+#endif
-
static int WriteFAACStr(BitStream *bitStream, char *version, int write)
{
int i;
@@ -430,6 +440,7 @@
{
int bits = 0;
+#ifndef DRM
if (writeFlag) {
/* write Single Element Channel (SCE) identifier */
PutBit(bitStream, ID_SCE, LEN_SE_ID);
@@ -440,6 +451,7 @@
bits += LEN_SE_ID;
bits += LEN_TAG;
+#endif
/* Write an Individual Channel Stream element */
bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
@@ -510,7 +522,13 @@
PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBL);
}
bits += LEN_MAX_SFBL;
-
+#ifdef DRM
+ }
+ if (writeFlag) {
+ PutBit(bitStream,coderInfo->tnsInfo.tnsDataPresent,LEN_TNS_PRES);
+ }
+ bits += LEN_TNS_PRES;
+#endif
if (objectType == LTP)
{
bits++;
@@ -527,7 +545,9 @@
bits += WritePredictorData(coderInfo, bitStream, writeFlag);
}
+#ifndef DRM
}
+#endif
return bits;
}
@@ -542,10 +562,12 @@
/* returns the number of bits written to the bitstream */
int bits = 0;
+#ifndef DRM
/* Write the 8-bit global_gain */
if (writeFlag)
PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN);
bits += LEN_GLOB_GAIN;
+#endif
/* Write ics information */
if (!commonWindow) {
@@ -552,12 +574,41 @@
bits += WriteICSInfo(coderInfo, bitStream, objectType, commonWindow, writeFlag);
}
+#ifdef DRM
+ /* Write the 8-bit global_gain */
+ if (writeFlag)
+ PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN);
+ bits += LEN_GLOB_GAIN;
+#endif
+
bits += SortBookNumbers(coderInfo, bitStream, writeFlag);
bits += WriteScalefactors(coderInfo, bitStream, writeFlag);
+#ifdef DRM
+ if (writeFlag) {
+ /* length_of_reordered_spectral_data */
+ PutBit(bitStream, coderInfo->iLenReordSpData, LEN_HCR_REORDSD);
+
+ /* length_of_longest_codeword */
+ PutBit(bitStream, coderInfo->iLenLongestCW, LEN_HCR_LONGCW);
+ }
+ bits += LEN_HCR_REORDSD + LEN_HCR_LONGCW;
+#else
bits += WritePulseData(coderInfo, bitStream, writeFlag);
+#endif
bits += WriteTNSData(coderInfo, bitStream, writeFlag);
+#ifndef DRM
bits += WriteGainControlData(coderInfo, bitStream, writeFlag);
+#endif
+
+#ifdef DRM
+ /* DRM CRC calculation */
+ if (writeFlag)
+ calc_CRC(bitStream, bits);
+
+ bits += WriteReorderedSpectralData(coderInfo, bitStream, writeFlag);
+#else
bits += WriteSpectralData(coderInfo, bitStream, writeFlag);
+#endif
/* Return number of bits */
return bits;
@@ -675,10 +726,12 @@
TnsInfo* tnsInfoPtr = &coderInfo->tnsInfo;
+#ifndef DRM
if (writeFlag) {
PutBit(bitStream,tnsInfoPtr->tnsDataPresent,LEN_TNS_PRES);
}
bits += LEN_TNS_PRES;
+#endif
/* If TNS is not present, bail */
if (!tnsInfoPtr->tnsDataPresent) {
@@ -875,8 +928,14 @@
bitStream = AllocMemory(sizeof(BitStream));
bitStream->size = size;
+#ifdef DRM
+ /* skip first byte for CRC */
+ bitStream->numBit = 8;
+ bitStream->currentBit = 8;
+#else
bitStream->numBit = 0;
bitStream->currentBit = 0;
+#endif
bitStream->data = buffer;
SetMemory(bitStream->data, 0, size);
@@ -905,8 +964,10 @@
idx = (bitStream->currentBit / BYTE_NUMBIT) % bitStream->size;
numUsed = bitStream->currentBit % BYTE_NUMBIT;
+#ifndef DRM
if (numUsed == 0)
bitStream->data[idx] = 0;
+#endif
bitStream->data[idx] |= (data & ((1<<numBit)-1)) <<
(BYTE_NUMBIT-numUsed-numBit);
bitStream->currentBit += numBit;
@@ -958,3 +1019,343 @@
return j;
}
+#ifdef DRM
+/*
+ ****************************************************************************
+ The following code was written by Volker Fischer (c) 2004
+
+ The GNU Lesser General Public License as published by the
+ Free Software Foundation applies to this code.
+ ****************************************************************************
+*/
+#define LEN_PRESORT_CODEBOOK 22
+static const unsigned short PresortedCodebook_VCB11[] = {11, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 9, 7, 5, 3, 1};
+static const int maxCwLen[32] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, 49,
+ 0, 0, 0, 0, 14, 17, 21, 21, 25, 25, 29, 29, 29, 29, 33, 33, 33, 37, 37, 41}; /* 8.5.3.3.3.1 */
+
+typedef struct { /* segment parameters */
+ unsigned int left; /* left start of free space in segment */
+ unsigned int right; /* right position of free space in segment */
+ unsigned int len; /* length of free space in segment */
+} segment_t;
+
+typedef struct { /* codeword parameters */
+ unsigned int cw_offset; /* offset in actual codeword data vector */
+ unsigned short window; /* which window belongs to this codeword */
+ unsigned short cb; /* codebook */
+ unsigned short num_sl_cw; /* number of spectral lines per codeword */
+ unsigned int cw_nr; /* codeword number in the window */
+ unsigned short cw_len; /* codeword lenght */
+ unsigned short num_data; /* number of data cells for codeword */
+} cw_info_t;
+
+static int PutBitHcr(BitStream *bitStream,
+ unsigned long curpos,
+ unsigned long data,
+ int numBit)
+{ /* data can be written at an arbitrary position in the bitstream */
+ bitStream->currentBit = curpos;
+ return PutBit(bitStream, data, numBit);
+}
+
+static int rewind_word(int W, int len)
+{ /* rewind len (max. 32) bits so that the MSB becomes LSB */
+ short i;
+ int tmp_W = 0;
+
+ for (i = 0; i < len; i++) {
+ tmp_W <<= 1;
+ if (W & (1<<i)) tmp_W |= 1;
+ }
+ return tmp_W;
+}
+
+static int WriteReorderedSpectralData(CoderInfo *coderInfo,
+ BitStream *bitStream,
+ int writeFlag)
+{
+ int i, j;
+ int cursegmsize, accsegmsize = 0;
+ int segmcnt = 0;
+ long startbitpos;
+ segment_t segment[FRAME_LEN];
+ int* window_group_length = coderInfo->window_group_length;
+ int* sfb_offset = coderInfo->sfb_offset;
+
+ cw_info_t cw_info[FRAME_LEN];
+ cw_info_t cw_info_preso[FRAME_LEN];
+
+ int num_cw = coderInfo->cur_cw;
+ int window_cw_cnt[MAX_SHORT_WINDOWS] = {0,0,0,0,0,0,0,0};
+
+ int presort, set, num_sets;
+
+ unsigned short cur_cb, cw_cnt;
+ short is_backwards;
+ int diff, tmp_data, cw_part_cnt, cur_cw_part;
+
+ int cur_cw_len, cur_data;
+ int sfb_cnt, win_cnt, acc_win_cnt, win_grp_cnt;
+ int coeff_cnt, last_sfb, cur_sfb_len;
+
+ /* set up local pointers to data and len */
+ /* data array contains data to be written */
+ /* len array contains lengths of data words */
+ int* data = coderInfo->data;
+ int* len = coderInfo->len;
+ int* num_data = coderInfo->num_data_cw;
+
+ if (writeFlag) {
+ /* build offset table */
+ cur_data = 0;
+ cw_info[0].cw_offset = 0;
+ for (i = 0; i < num_cw; i++) {
+ cur_cw_len = 0;
+ for (j = 0; j < num_data[i]; j++) {
+ cur_cw_len += len[cur_data++];
+ }
+
+ cw_info[i].num_data = num_data[i];
+ cw_info[i].cw_len = cur_cw_len;
+ if (i > 0) /* calculate offset (codeword info parameter) */
+ cw_info[i].cw_offset = cw_info[i - 1].cw_offset + num_data[i - 1];
+ }
+
+ /* presort codewords ------------------------------------------------ */
+ /* classify codewords first */
+ sfb_cnt = win_cnt = win_grp_cnt = coeff_cnt = last_sfb = acc_win_cnt = 0;
+ cur_sfb_len = sfb_offset[1] / window_group_length[0];
+ cur_cb = coderInfo->book_vector[0];
+ for (i = 0; i < num_cw; i++) {
+ /* Set codeword info parameters */
+ cw_info[i].cb = cur_cb;
+ cw_info[i].num_sl_cw = (cur_cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN;
+
+ cw_info[i].window = acc_win_cnt + win_cnt;
+ cw_info[i].cw_nr = window_cw_cnt[cw_info[i].window];
+ window_cw_cnt[cw_info[i].window]++;
+
+ coeff_cnt += cw_info[i].num_sl_cw;
+ if (coeff_cnt - last_sfb >= cur_sfb_len) {
+ last_sfb += cur_sfb_len;
+
+ win_cnt++; /* next window */
+ if (win_cnt == window_group_length[win_grp_cnt]) {
+ win_cnt = 0;
+
+ sfb_cnt++; /* next sfb */
+ if (sfb_cnt == coderInfo->all_sfb) {
+ sfb_cnt = 0;
+
+ acc_win_cnt += window_group_length[win_grp_cnt];
+ win_grp_cnt++; /* next window group */
+ }
+
+ /* new codebook and sfb length */
+ cur_cb = coderInfo->book_vector[sfb_cnt];
+ if (last_sfb < FRAME_LEN) {
+ cur_sfb_len = (sfb_offset[sfb_cnt + 1] - sfb_offset[sfb_cnt])
+ / window_group_length[win_grp_cnt];
+ }
+ }
+ }
+ }
+
+ /* presorting (first presorting step) */
+ /* only needed for short windows */
+ if (coderInfo->block_type == ONLY_SHORT_WINDOW) {
+ for (i = 0; i < MAX_SHORT_WINDOWS; i++)
+ window_cw_cnt[i] = 0; /* reset all counters */
+
+ win_cnt = 0;
+ cw_cnt = 0;
+ for (i = 0; i < num_cw; i++) {
+ for (j = 0; j < num_cw; j++) {
+ if (cw_info[j].window == win_cnt) {
+ if (cw_info[j].cw_nr == window_cw_cnt[win_cnt]) {
+ cw_info_preso[cw_cnt++] = cw_info[j];
+ window_cw_cnt[win_cnt]++;
+
+ /* check if two one-dimensional codewords */
+ if (cw_info[j].num_sl_cw == PAIR_LEN) {
+ cw_info_preso[cw_cnt++] = cw_info[j + 1];
+ window_cw_cnt[win_cnt]++;
+ }
+
+ win_cnt++; /* next window */
+ if (win_cnt == MAX_SHORT_WINDOWS)
+ win_cnt = 0;
+ }
+ }
+ }
+ }
+ } else {
+ for (i = 0; i < num_cw; i++) {
+ cw_info_preso[i] = cw_info[i]; /* just copy */
+ }
+ }
+
+ /* presorting (second presorting step) */
+ cw_cnt = 0;
+ for (presort = 0; presort < LEN_PRESORT_CODEBOOK; presort++) {
+ /* next codebook that has to be processed according to presorting */
+ unsigned short nextCB = PresortedCodebook_VCB11[presort];
+
+ for (i = 0; i < num_cw; i++) {
+ /* process only codewords that are due now */
+ if ((cw_info_preso[i].cb == nextCB) ||
+ ((nextCB < ESC_HCB) && (cw_info_preso[i].cb == nextCB + 1)))
+ {
+ cw_info[cw_cnt++] = cw_info_preso[i];
+ }
+ }
+ }
+
+ /* init segments */
+ accsegmsize = 0;
+ for (i = 0; i < num_cw; i++) {
+ /* 8.5.3.3.3.2 Derivation of segment width */
+ cursegmsize = min(maxCwLen[cw_info[i].cb], coderInfo->iLenLongestCW);
+
+ if (accsegmsize + cursegmsize > coderInfo->iLenReordSpData) {
+ /* the last segment is extended until iLenReordSpData */
+ segment[segmcnt - 1].right = coderInfo->iLenReordSpData - 1;
+ segment[segmcnt - 1].len = coderInfo->iLenReordSpData - segment[segmcnt - 1].left;
+ break;
+ }
+
+ segment[segmcnt].left = accsegmsize;
+ segment[segmcnt].right = accsegmsize + cursegmsize - 1;
+ segment[segmcnt++].len = cursegmsize;
+ accsegmsize += cursegmsize;
+ }
+
+ /* store current bit position */
+ startbitpos = bitStream->currentBit;
+
+ /* write write priority codewords (PCWs) and nonPCWs ---------------- */
+ num_sets = num_cw / segmcnt; /* number of sets */
+
+ for (set = 0; set <= num_sets; set++) {
+ int trial;
+
+ /* ever second set the bit order is reversed */
+ is_backwards = set % 2;
+
+ for (trial = 0; trial < segmcnt; trial++) {
+ int codewordBase;
+ int set_encoded = segmcnt;
+
+ if (set == num_sets)
+ set_encoded = num_cw - set * segmcnt; /* last set is shorter than the rest */
+
+ for (codewordBase = 0; codewordBase < segmcnt; codewordBase++) {
+ int segment_index = (trial + codewordBase) % segmcnt;
+ int codeword_index = codewordBase + set * segmcnt;
+
+ if (codeword_index >= num_cw)
+ break;
+
+ if ((cw_info[codeword_index].cw_len > 0) && (segment[segment_index].len > 0)) {
+ /* codeword is not yet written (completely) */
+ /* space left in this segment */
+ short tmplen;
+
+ /* how many bits can be written? */
+ if (segment[segment_index].len >= cw_info[codeword_index].cw_len) {
+ tmplen = cw_info[codeword_index].cw_len;
+ set_encoded--; /* CW fits into segment */
+ } else {
+ tmplen = segment[segment_index].len;
+ }
+
+ /* Adjust lengths */
+ cw_info[codeword_index].cw_len -= tmplen;
+ segment[segment_index].len -= tmplen;
+
+ /* write codewords to bitstream */
+ for (cw_part_cnt = 0; cw_part_cnt < cw_info[codeword_index].num_data; cw_part_cnt++) {
+ cur_cw_part = cw_info[codeword_index].cw_offset + cw_part_cnt;
+
+ if (len[cur_cw_part] <= tmplen) {
+ /* write complete data, no partitioning */
+ if (is_backwards) {
+ /* write data in reversed bit-order */
+ PutBitHcr(bitStream, startbitpos + segment[segment_index].right - len[cur_cw_part] + 1,
+ rewind_word(data[cur_cw_part], len[cur_cw_part]), len[cur_cw_part]);
+
+ segment[segment_index].right -= len[cur_cw_part];
+ } else {
+ PutBitHcr(bitStream, startbitpos + segment[segment_index].left,
+ data[cur_cw_part], len[cur_cw_part]);
+
+ segment[segment_index].left += len[cur_cw_part];
+ }
+
+ tmplen -= len[cur_cw_part];
+ len[cur_cw_part] = 0;
+ } else {
+ /* codeword part must be partitioned */
+ /* data must be taken from the left side */
+ tmp_data = data[cur_cw_part];
+
+ diff = len[cur_cw_part] - tmplen;
+ tmp_data >>= diff;
+
+ /* remove bits which are already used */
+ data[cur_cw_part] &= (1 << diff) - 1 /* diff number of ones */;
+ len[cur_cw_part] = diff;
+
+ if (is_backwards) {
+ /* write data in reversed bit-order */
+ PutBitHcr(bitStream, startbitpos + segment[segment_index].right - tmplen + 1,
+ rewind_word(tmp_data, tmplen), tmplen);
+
+ segment[segment_index].right -= tmplen;
+ } else {
+ PutBitHcr(bitStream, startbitpos + segment[segment_index].left,
+ tmp_data, tmplen);
+
+ segment[segment_index].left += tmplen;
+ }
+
+ tmplen = 0;
+ }
+
+ if (tmplen == 0)
+ break; /* all data written for this segment trial */
+ }
+ }
+ } /* of codewordBase */
+
+ if (set_encoded == 0)
+ break; /* no unencoded codewords left in this set */
+ } /* of trial */
+ }
+
+ /* set parameter for bit stream to current correct position */
+ bitStream->currentBit = startbitpos + coderInfo->iLenReordSpData;
+ bitStream->numBit = bitStream->currentBit;
+ }
+
+ return coderInfo->iLenReordSpData;
+}
+
+static void calc_CRC(BitStream *bitStream, int len)
+{
+ int i;
+ unsigned char r = 255; /* Initialize to all ones */
+
+ /* CRC polynome used x^8 + x^4 + x^3 + x^2 +1 */
+#define GPOLY 0435
+
+ for (i = 8; i < len + 8; i++) {
+ r = ( (r << 1) ^ (( (
+ ( bitStream->data[i / 8] >> (7 - (i % 8)) )
+ & 1) ^ ((r >> 7) & 1)) * GPOLY )) & 0xFF;
+ }
+
+ /* CRC is stored inverted, per definition at first byte in stream */
+ bitStream->data[0] = ~r;
+}
+#endif
--- a/libfaac/bitstream.h
+++ b/libfaac/bitstream.h
@@ -32,7 +32,7 @@
Copyright (c) 1996.
**********************************************************************/
/*
- * $Id: bitstream.h,v 1.13 2002/08/19 16:35:53 knik Exp $
+ * $Id: bitstream.h,v 1.14 2004/07/04 12:10:52 corrados Exp $
*/
#ifndef BITSTREAM_H
@@ -103,6 +103,15 @@
#define LEN_PC_COMM 8
+#ifdef DRM
+# define LEN_HCR_REORDSD 14
+# define LEN_HCR_LONGCW 6
+# define FIRST_PAIR_HCB 5
+# define QUAD_LEN 4
+# define PAIR_LEN 2
+# define ESC_HCB 11
+#endif
+
#define ID_SCE 0
#define ID_CPE 1
#define ID_CCE 2
@@ -118,10 +127,10 @@
#define MPEG4 0
/* AAC object types */
-#define MAIN 0
-#define LOW 1
-#define SSR 2
-#define LTP 3
+#define MAIN 1
+#define LOW 2
+#define SSR 3
+#define LTP 4
#define BYTE_NUMBIT 8 /* bits in byte (char) */
--- a/libfaac/coder.h
+++ b/libfaac/coder.h
@@ -16,7 +16,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: coder.h,v 1.11 2003/06/26 19:19:51 knik Exp $
+ * $Id: coder.h,v 1.12 2004/07/04 12:10:52 corrados Exp $
*/
#ifndef CODER_H
@@ -26,15 +26,24 @@
extern "C" {
#endif /* __cplusplus */
+/* Allow encoding of Digital Radio Mondiale (DRM) */
+//#define DRM
#define MAX_CHANNELS 64
-#define FRAME_LEN 1024
+#ifdef DRM
+# define FRAME_LEN 1024//960 // not working with 960, fixme
+# define BLOCK_LEN_LONG 1024//960
+# define BLOCK_LEN_SHORT 128//120
+#else
+# define FRAME_LEN 1024
+# define BLOCK_LEN_LONG 1024
+# define BLOCK_LEN_SHORT 128
+#endif
+
#define NSFB_LONG 51
#define NSFB_SHORT 15
#define MAX_SHORT_WINDOWS 8
-#define BLOCK_LEN_LONG 1024
-#define BLOCK_LEN_SHORT 128
#define MAX_SCFAC_BANDS ((NSFB_SHORT+1)*MAX_SHORT_WINDOWS)
enum WINDOW_TYPE {
@@ -153,6 +162,15 @@
/* Lengths of spectral bitstream elements */
int *len;
+
+#ifdef DRM
+ int *num_data_cw;
+ int cur_cw;
+ int all_sfb;
+
+ int iLenLongestCW;
+ int iLenReordSpData;
+#endif
/* Holds the requantized spectrum */
double *requantFreq;
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: frame.c,v 1.61 2004/05/03 11:37:16 danchr Exp $
+ * $Id: frame.c,v 1.62 2004/07/04 12:10:52 corrados Exp $
*/
/*
@@ -188,6 +188,14 @@
int rate; // per channel at 44100 sampling frequency
int cutoff;
} rates[] = {
+#ifdef DRM
+ /* DRM needs lower bit-rates. We've chosen higher bandwidth values and
+ decrease the quantizer quality at the same time to preserve the
+ low bit-rate */
+ {7000, 1500},
+ {15000, 3000},
+ {23000, 4000},
+#endif
{29500, 5000},
{37500, 7000},
{47000, 10000},
@@ -199,7 +207,11 @@
int f0, f1;
int r0, r1;
- config->quantqual = 100;
+#ifdef DRM
+ config->quantqual = 40; /* init with a lower value for DRM */
+#else
+ config->quantqual = 100;
+#endif
config->bitRate = (double)config->bitRate * 44100 / hEncoder->sampleRate;
@@ -218,19 +230,19 @@
if (config->bitRate > r1)
config->bitRate = r1;
- if (config->bitRate < r0)
- config->bitRate = r0;
+ if (config->bitRate < r0)
+ config->bitRate = r0;
if (f1 > f0)
- config->bandWidth =
- pow((double)config->bitRate / r1,
- log((double)f1 / f0) / log ((double)r1 / r0)) * (double)f1;
+ config->bandWidth =
+ pow((double)config->bitRate / r1,
+ log((double)f1 / f0) / log ((double)r1 / r0)) * (double)f1;
else
config->bandWidth = f1;
config->bandWidth =
(double)config->bandWidth * hEncoder->sampleRate / 44100;
- config->bitRate = (double)config->bitRate * hEncoder->sampleRate / 44100;
+ config->bitRate = (double)config->bitRate * hEncoder->sampleRate / 44100;
if (config->bandWidth > bwbase)
config->bandWidth = bwbase;
@@ -240,7 +252,7 @@
if (!config->bandWidth)
{
- config->bandWidth = (config->quantqual - 100) * bwmult + bwbase;
+ config->bandWidth = (config->quantqual - 100) * bwmult + bwbase;
}
hEncoder->config.bandWidth = config->bandWidth;
@@ -289,9 +301,13 @@
unsigned int channel;
faacEncHandle hEncoder;
- *inputSamples = 1024*numChannels;
+ *inputSamples = FRAME_LEN*numChannels;
*maxOutputBytes = (6144/8)*numChannels;
+#ifdef DRM
+ *maxOutputBytes += 1; /* for CRC */
+#endif
+
hEncoder = (faacEncStruct*)AllocMemory(sizeof(faacEncStruct));
SetMemory(hEncoder, 0, sizeof(faacEncStruct));
@@ -770,7 +786,7 @@
/* If short window, reconstruction not needed for prediction */
if ((coderInfo[channel].block_type == ONLY_SHORT_WINDOW)) {
int sind;
- for (sind = 0; sind < 1024; sind++) {
+ for (sind = 0; sind < BLOCK_LEN_LONG; sind++) {
coderInfo[channel].requantFreq[sind] = 0.0;
}
} else {
@@ -816,12 +832,11 @@
if (hEncoder->config.bitRate)
{
double fix;
- int desbits = numChannels * (hEncoder->config.bitRate * 1024)
+ int desbits = numChannels * (hEncoder->config.bitRate * FRAME_LEN)
/ hEncoder->sampleRate;
int diff = (frameBytes * 8) - desbits;
hEncoder->bitDiff += diff;
-
fix = (double)hEncoder->bitDiff / desbits;
fix *= 0.01;
fix = max(fix, -0.2);
@@ -832,8 +847,15 @@
hEncoder->aacquantCfg.quality *= (1.0 - fix);
if (hEncoder->aacquantCfg.quality > 300)
hEncoder->aacquantCfg.quality = 300;
- if (hEncoder->aacquantCfg.quality < 50)
- hEncoder->aacquantCfg.quality = 50;
+#ifdef DRM
+ /* since we have very low bit-rates in DRM, we have to decrease the
+ bandwidth and also decrease the quality */
+ if (hEncoder->aacquantCfg.quality < 10)
+ hEncoder->aacquantCfg.quality = 10;
+#else
+ if (hEncoder->aacquantCfg.quality < 50)
+ hEncoder->aacquantCfg.quality = 50;
+#endif
}
}
@@ -948,6 +970,18 @@
/*
$Log: frame.c,v $
+Revision 1.62 2004/07/04 12:10:52 corrados
+made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
+implemented HCR tool, VCB11, CRC, scalable bitstream order
+note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
+960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
+
+Revision 1.62 2004/07/ corrados
+made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
+implemented HCR tool, VCB11, CRC, scalable bitstream order
+note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
+960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
+
Revision 1.61 2004/05/03 11:37:16 danchr
bump version to unstable 1.24+
--- a/libfaac/huffman.c
+++ b/libfaac/huffman.c
@@ -23,7 +23,7 @@
***********/
/*
- * $Id: huffman.c,v 1.8 2002/08/30 16:22:46 knik Exp $
+ * $Id: huffman.c,v 1.9 2004/07/04 12:10:52 corrados Exp $
*/
#include <math.h>
@@ -43,6 +43,10 @@
for (channel = 0; channel < numChannels; channel++) {
coderInfo[channel].data = (int*)AllocMemory(5*FRAME_LEN*sizeof(int));
coderInfo[channel].len = (int*)AllocMemory(5*FRAME_LEN*sizeof(int));
+
+#ifdef DRM
+ coderInfo[channel].num_data_cw = (int*)AllocMemory(FRAME_LEN*sizeof(int));
+#endif
}
}
@@ -88,7 +92,7 @@
*/
{
- int i,j,k,n;
+ int i,j,k;
int hop;
int min_book_choice[112][3];
int bit_stats[240][3];
@@ -349,7 +353,6 @@
OutputBits() is called, counter starts at the value it left off from the previous call.
*/
-
int esc_sequence;
int len_esc;
int index;
@@ -359,8 +362,12 @@
int counter;
/* Set up local pointers to coderInfo elements data and len */
- int* data= coderInfo->data;
- int* len= coderInfo->len;
+ int* data= coderInfo->data;
+ int* len= coderInfo->len;
+#ifdef DRM
+ int* num_data = coderInfo->num_data_cw;
+ int cur_cw_len;
+#endif
counter = coderInfo->spectral_count;
@@ -368,10 +375,18 @@
case 0:
case INTENSITY_HCB2:
case INTENSITY_HCB:
+#ifdef DRM
+ for(i=offset;i<offset+length;i=i+4){
+#endif
/* This case also applies to intensity stereo encoding */
coderInfo->data[counter] = 0;
coderInfo->len[counter++] = 0;
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
+
+#ifdef DRM
+ num_data[coderInfo->cur_cw++] = 1;
+ }
+#endif
return(bits);
case 1:
for(i=offset;i<offset+length;i=i+4){
@@ -381,6 +396,12 @@
bits += tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw++] = 1;
+ coderInfo->iLenReordSpData += tmp;
+ if (tmp > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = tmp;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -392,6 +413,12 @@
bits += tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw++] = 1;
+ coderInfo->iLenReordSpData += tmp;
+ if (tmp > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = tmp;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -403,18 +430,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<4;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -426,18 +472,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<4;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -449,6 +514,12 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw++] = 1;
+ coderInfo->iLenReordSpData += tmp;
+ if (tmp > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = tmp;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -460,6 +531,12 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw++] = 1;
+ coderInfo->iLenReordSpData += tmp;
+ if (tmp > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = tmp;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -471,18 +548,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<2;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -494,18 +590,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<2;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -517,19 +632,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
-
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<2;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -541,19 +674,37 @@
bits = bits + tmp;
data[counter] = codebook;
len[counter++] = tmp;
-
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
for(j=0;j<2;j++){
if(quant[i+j] > 0) { /* send out '0' if a positive value */
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
@@ -581,6 +732,10 @@
bits += tmp;
data[counter] = codebook;
len[counter++] = tmp;
+#ifdef DRM
+ num_data[coderInfo->cur_cw] = 1;
+ cur_cw_len = tmp;
+#endif
/* Take care of the sign bits */
for(j=0;j<2;j++){
@@ -588,11 +743,19 @@
data[counter] = 0;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
} else
if(quant[i+j] < 0) { /* send out '1' if a negative value */
data[counter] = 1;
len[counter++] = 1;
bits += 1;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += 1;
+#endif
}
}
@@ -603,6 +766,10 @@
bits += len_esc;
data[counter] = esc_sequence;
len[counter++] = len_esc;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += len_esc;
+#endif
/* then code and transmit the second escape_sequence */
esc_sequence = CalculateEscSequence(quant[i+1],&len_esc);
@@ -609,6 +776,10 @@
bits += len_esc;
data[counter] = esc_sequence;
len[counter++] = len_esc;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += len_esc;
+#endif
}
else if (ABS(quant[i]) >= 16) { /* the first codeword was above 16, not the second one */
/* code and transmit the escape_sequence */
@@ -616,6 +787,10 @@
bits += len_esc;
data[counter] = esc_sequence;
len[counter++] = len_esc;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += len_esc;
+#endif
}
else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */
/* code and transmit the escape_sequence */
@@ -623,9 +798,20 @@
bits += len_esc;
data[counter] = esc_sequence;
len[counter++] = len_esc;
+#ifdef DRM
+ num_data[coderInfo->cur_cw]++;
+ cur_cw_len += len_esc;
+#endif
}
+#ifdef DRM
+ coderInfo->iLenReordSpData += cur_cw_len;
+ if (cur_cw_len > coderInfo->iLenLongestCW)
+ coderInfo->iLenLongestCW = cur_cw_len;
+
+ coderInfo->cur_cw++;
+#endif
}
- coderInfo -> spectral_count = counter; /* send the current count back to the outside world */
+ coderInfo->spectral_count = counter; /* send the current count back to the outside world */
return(bits);
}
return 0;
@@ -809,10 +995,15 @@
int previous;
int max, bit_len/*,sfbs*/;
int max_sfb,g,band;
+ int sect_cb_bits = 4;
/* Set local pointers to coderInfo elements */
int* book_vector = coderInfo->book_vector;
+#ifdef DRM
+ sect_cb_bits = 5; /* 5 bits in case of VCB11 */
+#endif
+
if (coderInfo->block_type == ONLY_SHORT_WINDOW){
max = 7;
bit_len = 3;
@@ -832,11 +1023,25 @@
previous = book_vector[band];
if (writeFlag) {
- PutBit(bitStream,book_vector[band],4);
+ PutBit(bitStream,book_vector[band],sect_cb_bits);
}
- bit_count += 4;
+ bit_count += sect_cb_bits;
for (i=band+1;i<band+max_sfb;i++) {
+#ifdef DRM
+ /* sect_len is not transmitted in case the codebook for a */
+ /* section is 11 or in the range of 16 and 31 */
+ if ((previous == 11) ||
+ ((previous >= 16) && (previous <= 32)))
+ {
+ if (writeFlag)
+ PutBit(bitStream,book_vector[i],sect_cb_bits);
+ bit_count += sect_cb_bits;
+ previous = book_vector[i];
+ repeat_counter=1;
+
+ } else
+#endif
if( (book_vector[i] != previous)) {
if (writeFlag) {
PutBit(bitStream,repeat_counter,bit_len);
@@ -850,11 +1055,10 @@
}
if (writeFlag)
- PutBit(bitStream,book_vector[i],4);
- bit_count += 4;
+ PutBit(bitStream,book_vector[i],sect_cb_bits);
+ bit_count += sect_cb_bits;
previous = book_vector[i];
repeat_counter=1;
-
}
/* if the length of the section is longer than the amount of bits available in */
/* the bitsream, "max", then start up an escape sequence */
@@ -870,18 +1074,21 @@
}
}
- if (writeFlag)
- PutBit(bitStream,repeat_counter,bit_len);
- bit_count += bit_len;
-
- if (repeat_counter == max) { /* special case if the last section length is an */
- /* escape sequence */
+#ifdef DRM
+ if (!((previous == 11) || ((previous >= 16) && (previous <= 32))))
+#endif
+ {
if (writeFlag)
- PutBit(bitStream,0,bit_len);
+ PutBit(bitStream,repeat_counter,bit_len);
bit_count += bit_len;
- }
-
+ if (repeat_counter == max) { /* special case if the last section length is an */
+ /* escape sequence */
+ if (writeFlag)
+ PutBit(bitStream,0,bit_len);
+ bit_count += bit_len;
+ }
+ }
} /* Bottom of group iteration */
return bit_count;
--
⑨