Skip to content

Commit

Permalink
Move floating point IDCT coeffs into per-context data.
Browse files Browse the repository at this point in the history
Makes the decoder library thread safe with no global modifiable
variables.
  • Loading branch information
foo86 committed Mar 26, 2015
1 parent 79cfae4 commit 5a9239f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 50 deletions.
6 changes: 5 additions & 1 deletion libdcadec/core_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,11 +918,15 @@ int core_filter(struct core_decoder *core, int flags)

core->filter_flags = flags;

if (!core->subband_dsp_data)
if (!(core->subband_dsp_data = interpolator_init(core)))
return -DCADEC_ENOMEM;

// Filter primary channels
for (int ch = 0; ch < core->nchannels; ch++) {
// Allocate subband DSP
if (!core->subband_dsp[ch])
if (!(core->subband_dsp[ch] = interpolator_create(core, flags)))
if (!(core->subband_dsp[ch] = interpolator_create(core->subband_dsp_data, flags)))
return -DCADEC_ENOMEM;

// Map this primary channel to speaker
Expand Down
1 change: 1 addition & 0 deletions libdcadec/core_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct core_decoder {
int *subband_buffer;
int *subband_samples[MAX_CHANNELS][MAX_SUBBANDS];
struct interpolator *subband_dsp[MAX_CHANNELS];
struct interpolator_data *subband_dsp_data;

int *lfe_samples;

Expand Down
32 changes: 23 additions & 9 deletions libdcadec/interpolator.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,30 @@
#include "common.h"
#include "interpolator.h"

struct interpolator *interpolator_create(struct core_decoder *parent, int flags)
struct interpolator_data *interpolator_init(struct core_decoder *parent)
{
struct interpolator_data *data = ta_new(parent, struct interpolator_data);
if (!data)
return NULL;

for (int i = 0, k = 0; i < 32; i++)
for (int j = 0; j < 32; j++)
data->cos_mod_32[k++] = 0.250 * cos((2 * i + 1) * (2 * j + 1) * M_PI / 128);

for (int i = 0, k = 0; i < 64; i++)
for (int j = 0; j < 64; j++)
data->cos_mod_64[k++] = 0.125 * cos((2 * i + 1) * (2 * j + 1) * M_PI / 256);

return data;
}

struct interpolator *interpolator_create(struct interpolator_data *parent, int flags)
{
struct interpolator *dsp = ta_new(parent, struct interpolator);
if (!dsp)
return NULL;

dsp->data = parent;
dsp->history = ta_znew_array_size(dsp,
(flags & DCADEC_FLAG_CORE_BIT_EXACT) ? sizeof(int) : sizeof(double),
(flags & DCADEC_FLAG_CORE_SYNTH_X96) ? 1024 : 512);
Expand All @@ -34,19 +52,15 @@ struct interpolator *interpolator_create(struct core_decoder *parent, int flags)
}

if (flags & DCADEC_FLAG_CORE_BIT_EXACT) {
if (flags & DCADEC_FLAG_CORE_SYNTH_X96) {
if (flags & DCADEC_FLAG_CORE_SYNTH_X96)
dsp->interpolate = interpolate_sub64_fixed;
} else {
else
dsp->interpolate = interpolate_sub32_fixed;
}
} else {
if (flags & DCADEC_FLAG_CORE_SYNTH_X96) {
interpolate_sub64_float_init();
if (flags & DCADEC_FLAG_CORE_SYNTH_X96)
dsp->interpolate = interpolate_sub64_float;
} else {
interpolate_sub32_float_init();
else
dsp->interpolate = interpolate_sub32_float;
}
}

return dsp;
Expand Down
12 changes: 8 additions & 4 deletions libdcadec/interpolator.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@ typedef void (*interpolate_sub_t)(struct interpolator *dsp, int *pcm_samples,
int **subband_samples_hi,
int nsamples, bool perfect);

struct interpolator_data {
double cos_mod_32[32 * 32];
double cos_mod_64[64 * 64];
};

struct interpolator {
struct interpolator_data *data;
void *history;
interpolate_sub_t interpolate;
};

struct interpolator *interpolator_create(struct core_decoder *parent, int flags);
struct interpolator_data *interpolator_init(struct core_decoder *parent);
struct interpolator *interpolator_create(struct interpolator_data *parent, int flags);
void interpolator_clear(struct interpolator *dsp);

#define INTERPOLATE_LFE(x) \
Expand All @@ -57,9 +64,6 @@ INTERPOLATE_LFE(lfe_float_iir);
INTERPOLATE_SUB(sub32_float);
INTERPOLATE_SUB(sub64_float);

void interpolate_sub32_float_init(void);
void interpolate_sub64_float_init(void);

INTERPOLATE_LFE(lfe_fixed_fir);
INTERPOLATE_SUB(sub32_fixed);
INTERPOLATE_SUB(sub64_fixed);
Expand Down
46 changes: 10 additions & 36 deletions libdcadec/interpolator_float.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ static const double lfe_iir[12] = {
1.9922787089263100, 1.0000000000000000, -1.9974180593495760
};

static double cos_mod_32[32][32];

static double cos_mod_64[64][64];

static inline int convert(double a)
{
if (a > 0x7fffff)
Expand Down Expand Up @@ -118,6 +114,9 @@ INTERPOLATE_SUB(sub32_float)
// Get history pointer
double *history = dsp->history;

// Get IDCT coefficients
const double *cos_mod = dsp->data->cos_mod_32;

// Select filter
const double *filter_coeff = perfect ? band_fir_perfect : band_fir_nonperfect;

Expand All @@ -132,10 +131,10 @@ INTERPOLATE_SUB(sub32_float)

// Inverse DCT
double output[32];
for (i = 0; i < 32; i++) {
for (i = 0, k = 0; i < 32; i++) {
double res = 0.0;
for (j = 0; j < 32; j++)
res += input[j] * cos_mod_32[i][j];
res += input[j] * cos_mod[k++];
output[i] = res;
}

Expand Down Expand Up @@ -187,6 +186,9 @@ INTERPOLATE_SUB(sub64_float)
// Get history pointer
double *history = dsp->history;

// Get IDCT coefficients
const double *cos_mod = dsp->data->cos_mod_64;

// Interpolation begins
for (int sample = 0; sample < nsamples; sample++) {
int i, j, k;
Expand All @@ -209,10 +211,10 @@ INTERPOLATE_SUB(sub64_float)

// Inverse DCT
double output[64];
for (i = 0; i < 64; i++) {
for (i = 0, k = 0; i < 64; i++) {
double res = 0.0;
for (j = 0; j < 64; j++)
res += input[j] * cos_mod_64[i][j];
res += input[j] * cos_mod[k++];
output[i] = res;
}

Expand Down Expand Up @@ -256,31 +258,3 @@ INTERPOLATE_SUB(sub64_float)
history[i] = history[i - 64];
}
}

void interpolate_sub32_float_init(void)
{
static bool initialized;

if (initialized)
return;

for (int i = 0; i < 32; i++)
for (int j = 0; j < 32; j++)
cos_mod_32[i][j] = 0.25 * cos((2 * i + 1) * (2 * j + 1) * M_PI / 128);

initialized = true;
}

void interpolate_sub64_float_init(void)
{
static bool initialized;

if (initialized)
return;

for (int i = 0; i < 64; i++)
for (int j = 0; j < 64; j++)
cos_mod_64[i][j] = 0.125 * cos((2 * i + 1) * (2 * j + 1) * M_PI / 256);

initialized = true;
}

0 comments on commit 5a9239f

Please sign in to comment.