#include "dsputil.h"
#include "common.h"
#include "bytestream.h"
+#include "random.h"
#include "cookdata.h"
int bits_per_subpacket;
int cookversion;
/* states */
- int random_state;
+ AVRandomState random_state;
/* transform data */
MDCTContext mdct_ctx;
}
}
-/**
- * Create the quant value table.
- *
- * @param q pointer to the COOKContext
- * @param quant_value_table pointer to the array
- */
-
-static void inline dequant_envelope(COOKContext *q, int* quant_index_table,
- float* quant_value_table){
-
- int i;
- for(i=0 ; i < q->total_subbands ; i++){
- quant_value_table[i] = q->rootpow2tab[quant_index_table[i]+63];
- }
-}
-
/**
* Calculate the category and category_index vector.
*
*
* @param q pointer to the COOKContext
* @param index index
- * @param band current subband
- * @param quant_value_table pointer to the array
+ * @param quant_index quantisation index
* @param subband_coef_index array of indexes to quant_centroid_tab
- * @param subband_coef_noise use random noise instead of predetermined value
- * @param mlt_buffer pointer to the mlt buffer
+ * @param subband_coef_sign signs of coefficients
+ * @param mlt_p pointer into the mlt buffer
*/
-
-static void scalar_dequant(COOKContext *q, int index, int band,
- float* quant_value_table, int* subband_coef_index,
- int* subband_coef_noise, float* mlt_buffer){
+static void scalar_dequant(COOKContext *q, int index, int quant_index,
+ int* subband_coef_index, int* subband_coef_sign,
+ float* mlt_p){
int i;
float f1;
for(i=0 ; i<SUBBAND_SIZE ; i++) {
if (subband_coef_index[i]) {
- if (subband_coef_noise[i]) {
- f1 = -quant_centroid_tab[index][subband_coef_index[i]];
- } else {
- f1 = quant_centroid_tab[index][subband_coef_index[i]];
- }
+ f1 = quant_centroid_tab[index][subband_coef_index[i]];
+ if (subband_coef_sign[i]) f1 = -f1;
} else {
- /* noise coding if subband_coef_noise[i] == 0 */
- q->random_state = q->random_state * 214013 + 2531011; //typical RNG numbers
- f1 = randsign[(q->random_state/0x1000000)&1] * dither_tab[index]; //>>31
+ /* noise coding if subband_coef_index[i] == 0 */
+ f1 = dither_tab[index];
+ if (av_random(&q->random_state) < 0x80000000) f1 = -f1;
}
- mlt_buffer[band*20+ i] = f1 * quant_value_table[band];
+ mlt_p[i] = f1 * q->rootpow2tab[quant_index+63];
}
}
/**
- * Unpack the subband_coef_index and subband_coef_noise vectors.
+ * Unpack the subband_coef_index and subband_coef_sign vectors.
*
* @param q pointer to the COOKContext
* @param category pointer to the category array
* @param subband_coef_index array of indexes to quant_centroid_tab
- * @param subband_coef_noise use random noise instead of predetermined value
+ * @param subband_coef_sign signs of coefficients
*/
static int unpack_SQVH(COOKContext *q, int category, int* subband_coef_index,
- int* subband_coef_noise) {
+ int* subband_coef_sign) {
int i,j;
int vlc, vd ,tmp, result;
int ub;
for(j=0 ; j<vd ; j++){
if (subband_coef_index[i*vd + j]) {
if(get_bits_count(&q->gb) < q->bits_per_subpacket){
- subband_coef_noise[i*vd+j] = get_bits1(&q->gb);
+ subband_coef_sign[i*vd+j] = get_bits1(&q->gb);
} else {
result=1;
- subband_coef_noise[i*vd+j]=0;
+ subband_coef_sign[i*vd+j]=0;
}
} else {
- subband_coef_noise[i*vd+j]=0;
+ subband_coef_sign[i*vd+j]=0;
}
}
}
*
* @param q pointer to the COOKContext
* @param category pointer to the category array
- * @param quant_value_table pointer to the array
+ * @param quant_index_table pointer to the array
* @param mlt_buffer pointer to mlt coefficients
*/
static void decode_vectors(COOKContext* q, int* category,
- float* quant_value_table, float* mlt_buffer){
+ int *quant_index_table, float* mlt_buffer){
/* A zero in this table means that the subband coefficient is
random noise coded. */
- int subband_coef_noise[SUBBAND_SIZE];
+ int subband_coef_index[SUBBAND_SIZE];
/* A zero in this table means that the subband coefficient is a
positive multiplicator. */
- int subband_coef_index[SUBBAND_SIZE];
+ int subband_coef_sign[SUBBAND_SIZE];
int band, j;
int index=0;
for(band=0 ; band<q->total_subbands ; band++){
index = category[band];
if(category[band] < 7){
- if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_noise)){
+ if(unpack_SQVH(q, category[band], subband_coef_index, subband_coef_sign)){
index=7;
for(j=0 ; j<q->total_subbands ; j++) category[band+j]=7;
}
}
if(index==7) {
memset(subband_coef_index, 0, sizeof(subband_coef_index));
- memset(subband_coef_noise, 0, sizeof(subband_coef_noise));
+ memset(subband_coef_sign, 0, sizeof(subband_coef_sign));
}
- scalar_dequant(q, index, band, quant_value_table, subband_coef_index,
- subband_coef_noise, mlt_buffer);
+ scalar_dequant(q, index, quant_index_table[band],
+ subband_coef_index, subband_coef_sign,
+ &mlt_buffer[band * 20]);
}
if(q->total_subbands*SUBBAND_SIZE >= q->samples_per_channel){
return;
- }
+ } /* FIXME: should this be removed, or moved into loop above? */
}
static void mono_decode(COOKContext *q, float* mlt_buffer) {
int category_index[128];
- float quant_value_table[102];
int quant_index_table[102];
int category[128];
memset(&category, 0, 128*sizeof(int));
- memset(&quant_value_table, 0, 102*sizeof(int));
memset(&category_index, 0, 128*sizeof(int));
decode_envelope(q, quant_index_table);
q->num_vectors = get_bits(&q->gb,q->log2_numvector_size);
- dequant_envelope(q, quant_index_table, quant_value_table);
categorize(q, quant_index_table, category, category_index);
expand_category(q, category, category_index);
- decode_vectors(q, category, quant_value_table, mlt_buffer);
-}
-
-
-/**
- * The modulated lapped transform, this takes transform coefficients
- * and transforms them into timedomain samples. This is done through
- * an FFT-based algorithm with pre- and postrotation steps.
- * A window and reorder step is also included.
- *
- * @param q pointer to the COOKContext
- * @param inbuffer pointer to the mltcoefficients
- * @param outbuffer pointer to the timedomain buffer
- * @param mlt_tmp pointer to temporary storage space
- */
-
-static void cook_imlt(COOKContext *q, float* inbuffer, float* outbuffer)
-{
- int i;
-
- q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, outbuffer, inbuffer, q->mdct_tmp);
-
- for(i = 0; i < q->samples_per_channel; i++){
- float tmp = outbuffer[i];
-
- outbuffer[i] = q->mlt_window[i] * outbuffer[q->samples_per_channel + i];
- outbuffer[q->samples_per_channel + i] = q->mlt_window[q->samples_per_channel - 1 - i] * -tmp;
- }
+ decode_vectors(q, category, quant_index_table, mlt_buffer);
}
/**
- * mlt overlapping and buffer management
+ * The modulated lapped transform, this takes transform coefficients
+ * and transforms them into timedomain samples.
+ * Apply transform window, overlap buffers, apply gain profile
+ * and buffer management.
*
* @param q pointer to the COOKContext
+ * @param inbuffer pointer to the mltcoefficients
* @param gains_ptr current and previous gains
* @param previous_buffer pointer to the previous buffer to be used for overlapping
*/
-static void gain_compensate(COOKContext *q, cook_gains *gains_ptr,
- float* previous_buffer)
+static void imlt_gain(COOKContext *q, float *inbuffer,
+ cook_gains *gains_ptr, float* previous_buffer)
{
const float fc = q->pow2tab[gains_ptr->previous[0] + 63];
- float *buffer = q->mono_mdct_output;
+ float *buffer0 = q->mono_mdct_output;
+ float *buffer1 = q->mono_mdct_output + q->samples_per_channel;
int i;
- /* Overlap with the previous block. */
- for(i=0 ; i<q->samples_per_channel ; i++) {
- buffer[i] *= fc;
- buffer[i] += previous_buffer[i];
+ /* Inverse modified discrete cosine transform */
+ q->mdct_ctx.fft.imdct_calc(&q->mdct_ctx, q->mono_mdct_output,
+ inbuffer, q->mdct_tmp);
+
+ /* The weird thing here, is that the two halves of the time domain
+ * buffer are swapped. Also, the newest data, that we save away for
+ * next frame, has the wrong sign. Hence the subtraction below.
+ * Almost sounds like a complex conjugate/reverse data/FFT effect.
+ */
+
+ /* Apply window and overlap */
+ for(i = 0; i < q->samples_per_channel; i++){
+ buffer1[i] = buffer1[i] * fc * q->mlt_window[i] -
+ previous_buffer[i] * q->mlt_window[q->samples_per_channel - 1 - i];
}
/* Apply gain profile */
for (i = 0; i < 8; i++) {
if (gains_ptr->now[i] || gains_ptr->now[i + 1])
- interpolate(q, &buffer[q->gain_size_factor * i],
+ interpolate(q, &buffer1[q->gain_size_factor * i],
gains_ptr->now[i], gains_ptr->now[i + 1]);
}
/* Save away the current to be previous block. */
- memcpy(previous_buffer, buffer+q->samples_per_channel,
- sizeof(float)*q->samples_per_channel);
+ memcpy(previous_buffer, buffer0, sizeof(float)*q->samples_per_channel);
}
cook_gains *gains, float *previous_buffer,
int16_t *out, int chan)
{
+ float *output = q->mono_mdct_output + q->samples_per_channel;
int j;
- cook_imlt(q, decode_buffer, q->mono_mdct_output);
- gain_compensate(q, gains, previous_buffer);
+ imlt_gain(q, decode_buffer, gains, previous_buffer);
/* Clip and convert floats to 16 bits.
*/
for (j = 0; j < q->samples_per_channel; j++) {
out[chan + q->nb_channels * j] =
- av_clip(lrintf(q->mono_mdct_output[j]), -32768, 32767);
+ av_clip(lrintf(output[j]), -32768, 32767);
}
}
q->nb_channels = avctx->channels;
q->bit_rate = avctx->bit_rate;
- /* Initialize state. */
- q->random_state = 1;
+ /* Initialize RNG. */
+ av_init_random(1, &q->random_state);
/* Initialize extradata related variables. */
q->samples_per_channel = q->samples_per_frame / q->nb_channels;