#include "modes.h"
#include "rate.h"
#include "os_support.h"
+#include "stack_alloc.h"
+#include "quant_bands.h"
+
+#ifdef STATIC_MODES
+#include "static_modes.c"
+#endif
#define MODEVALID 0xa110ca7e
#define MODEFREED 0xb10cf8ee
#endif
-int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
+int EXPORT celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
{
switch (request)
{
case CELT_GET_NB_CHANNELS:
*value = mode->nbChannels;
break;
+ case CELT_GET_BITSTREAM_VERSION:
+ *value = CELT_BITSTREAM_VERSION;
+ break;
default:
return CELT_BAD_ARG;
}
return CELT_OK;
}
+#ifndef STATIC_MODES
+
#define PBANDS 8
-#define MIN_BINS 4
+
+#ifdef STDIN_TUNING
+int MIN_BINS;
+#else
+#define MIN_BINS 3
+#endif
+
/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
#define BARK_BANDS 25
/* This allocation table is per critical band. When creating a mode, the bits get added together
into the codec bands, which are sometimes larger than one critical band at low frequency */
+
+#ifdef STDIN_TUNING
+int BITALLOC_SIZE;
+int *band_allocation;
+#else
#define BITALLOC_SIZE 10
static const int band_allocation[BARK_BANDS*BITALLOC_SIZE] =
{ 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 5, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 6, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0,
- 3, 2, 2, 2, 3, 3, 2, 3, 2, 2, 4, 3, 7, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0,
- 3, 3, 2, 2, 3, 3, 3, 3, 3, 2, 4, 4, 9, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 0, 0,
- 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 10, 10, 12, 12, 12, 10, 10, 10, 11, 10, 10, 5, 5,
- 4, 4, 4, 4, 5, 5, 5, 5, 5, 4, 7, 7, 14, 13, 13, 13, 13, 13, 15, 16, 17, 18, 20, 18, 11,
- 7, 7, 6, 6, 9, 8, 8, 8, 8, 8, 11, 11, 20, 18, 19, 19, 25, 22, 25, 30, 30, 35, 35, 35, 35,
- 8, 8, 8, 8, 10, 10, 10, 10, 9, 9, 19, 18, 25, 24, 23, 21, 29, 27, 35, 40, 42, 50, 59, 54, 51,
- 11, 11, 10, 10, 14, 13, 13, 13, 13, 12, 19, 18, 35, 34, 33, 31, 39, 37, 45, 50, 52, 60, 60, 60, 60,
- };
-
+ 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 4, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 3, 5, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0,
+ 3, 2, 2, 2, 3, 3, 2, 3, 2, 3, 4, 4, 6, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0,
+ 3, 3, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 7, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 1, 0,
+ 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 6, 7, 7, 9, 11, 10, 10, 9, 9, 8, 11, 10, 10, 1, 1,
+ 5, 5, 4, 4, 5, 5, 5, 5, 6, 6, 8, 8, 10, 12, 15, 15, 13, 12, 12, 12, 18, 18, 16, 10, 1,
+ 6, 6, 6, 6, 6, 6, 7, 7, 9, 9, 11, 12, 13, 18, 22, 23, 24, 25, 28, 30, 35, 35, 35, 35, 15,
+ 7, 7, 7, 7, 7, 7, 10, 10, 10, 13, 14, 18, 20, 24, 28, 32, 32, 35, 38, 38, 42, 50, 59, 54, 31,
+ 8, 8, 8, 8, 8, 9, 10, 12, 14, 20, 22, 25, 28, 30, 35, 42, 46, 50, 55, 60, 62, 62, 62, 62, 62,
+};
+#endif
-static int *compute_ebands(int Fs, int frame_size, int *nbEBands)
+static celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
{
- int *eBands;
+ celt_int16_t *eBands;
int i, res, min_width, lin, low, high;
res = (Fs+frame_size)/(2*frame_size);
min_width = MIN_BINS*res;
low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
high = BARK_BANDS-lin;
*nbEBands = low+high;
- eBands = celt_alloc(sizeof(int)*(*nbEBands+2));
+ eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
/* Linear spacing (min_width) */
for (i=0;i<low;i++)
static void compute_pbands(CELTMode *mode, int res)
{
int i;
- int *pBands;
- pBands=celt_alloc(sizeof(int)*(PBANDS+2));
+ celt_int16_t *pBands;
+ pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
mode->nbPBands = PBANDS;
for (i=0;i<PBANDS+1;i++)
{
static void compute_allocation_table(CELTMode *mode, int res)
{
int i, j, eband;
- int *allocVectors;
+ celt_int16_t *allocVectors;
mode->nbAllocVectors = BITALLOC_SIZE;
- allocVectors = celt_alloc(sizeof(int)*(BITALLOC_SIZE*mode->nbEBands));
+ allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
for (i=0;i<BITALLOC_SIZE;i++)
{
eband = 0;
mode->allocVectors = allocVectors;
}
+#endif /* STATIC_MODES */
+static void compute_energy_allocation_table(CELTMode *mode)
+{
+ int i, j;
+ celt_int16_t *alloc;
+
+ alloc = celt_alloc(sizeof(celt_int16_t)*(mode->nbAllocVectors*(mode->nbEBands+1)));
+ for (i=0;i<mode->nbAllocVectors;i++)
+ {
+ int sum = 0;
+ int min_bits = 1;
+ if (mode->allocVectors[i*mode->nbEBands]>12)
+ min_bits = 2;
+ if (mode->allocVectors[i*mode->nbEBands]>24)
+ min_bits = 3;
+ for (j=0;j<mode->nbEBands;j++)
+ {
+ alloc[i*(mode->nbEBands+1)+j] = mode->allocVectors[i*mode->nbEBands+j]
+ / (mode->eBands[j+1]-mode->eBands[j]-1);
+ if (alloc[i*(mode->nbEBands+1)+j]<min_bits)
+ alloc[i*(mode->nbEBands+1)+j] = min_bits;
+ if (alloc[i*(mode->nbEBands+1)+j]>7)
+ alloc[i*(mode->nbEBands+1)+j] = 7;
+ sum += alloc[i*(mode->nbEBands+1)+j];
+ /*printf ("%d ", alloc[i*(mode->nbEBands+1)+j]);*/
+ /*printf ("%f ", mode->allocVectors[i*mode->nbEBands+j]*1.f/(mode->eBands[j+1]-mode->eBands[j]-1));*/
+ }
+ alloc[i*(mode->nbEBands+1)+mode->nbEBands] = sum;
+ /*printf ("\n");*/
+ }
+ mode->energy_alloc = alloc;
+}
-CELTMode *celt_mode_create(int Fs, int channels, int frame_size, int lookahead, int *error)
+CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int lookahead, int *error)
{
+ int i;
+#ifdef STDIN_TUNING
+ scanf("%d ", &MIN_BINS);
+ scanf("%d ", &BITALLOC_SIZE);
+ band_allocation = celt_alloc(sizeof(int)*BARK_BANDS*BITALLOC_SIZE);
+ for (i=0;i<BARK_BANDS*BITALLOC_SIZE;i++)
+ {
+ scanf("%d ", band_allocation+i);
+ }
+#endif
+#ifdef STATIC_MODES
+ const CELTMode *m = NULL;
+ CELTMode *mode=NULL;
+ ALLOC_STACK;
+ for (i=0;i<TOTAL_MODES;i++)
+ {
+ if (Fs == static_mode_list[i]->Fs &&
+ channels == static_mode_list[i]->nbChannels &&
+ frame_size == static_mode_list[i]->mdctSize &&
+ lookahead == static_mode_list[i]->overlap)
+ {
+ m = static_mode_list[i];
+ break;
+ }
+ }
+ if (m == NULL)
+ {
+ celt_warning("Mode not included as part of the static modes");
+ if (error)
+ *error = CELT_BAD_ARG;
+ return NULL;
+ }
+ mode = (CELTMode*)celt_alloc(sizeof(CELTMode));
+ CELT_COPY(mode, m, 1);
+#else
int res;
- int N, N2, N4, i;
CELTMode *mode;
-
+ celt_word16_t *window;
+ ALLOC_STACK;
+
/* The good thing here is that permutation of the arguments will automatically be invalid */
if (Fs < 32000 || Fs > 64000)
mode->Fs = Fs;
mode->overlap = lookahead;
mode->mdctSize = frame_size;
- mode->nbMdctBlocks = 1;
mode->nbChannels = channels;
mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
compute_pbands(mode, res);
mode->ePredCoef = QCONST16(.8f,15);
compute_allocation_table(mode, res);
- compute_alloc_cache(mode);
/*printf ("%d bands\n", mode->nbEBands);*/
- N = mode->mdctSize;
- N2 = N/2;
- N4 = N/4;
- mdct_init(&mode->mdct, 2*N);
+ window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
- mode->window = (celt_word16_t*)celt_alloc(2*N*sizeof(celt_word16_t));
-
- for (i=0;i<2*N;i++)
- mode->window[i] = 0;
+#ifndef FIXED_POINT
+ for (i=0;i<mode->overlap;i++)
+ window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
+#else
for (i=0;i<mode->overlap;i++)
- mode->window[N4+i] = mode->window[2*N-N4-i-1]
- = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
- for (i=0;i<N2;i++)
- mode->window[N-N4+i] = Q15ONE;
+ window[i] = MIN32(32767,32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap)));
+#endif
+ mode->window = window;
+
+ mode->bits = (const celt_int16_t **)compute_alloc_cache(mode, mode->nbChannels);
+#ifndef SHORTCUTS
+ psydecay_init(&mode->psy, MAX_PERIOD/2, mode->Fs);
+#endif
+
mode->marker_start = MODEVALID;
mode->marker_end = MODEVALID;
+#endif /* !STATIC_MODES */
+ mdct_init(&mode->mdct, 2*mode->mdctSize);
+ mode->fft = pitch_state_alloc(MAX_PERIOD);
+
+ mode->prob = quant_prob_alloc(mode);
+ compute_energy_allocation_table(mode);
+
+ if (error)
+ *error = CELT_OK;
return mode;
}
-void celt_mode_destroy(CELTMode *mode)
+void EXPORT celt_mode_destroy(CELTMode *mode)
{
+#ifndef STATIC_MODES
int i;
- const int *prevPtr = NULL;
- if (check_mode(mode) != CELT_OK)
- return;
- celt_free((int*)mode->eBands);
- celt_free((int*)mode->pBands);
- celt_free((int*)mode->allocVectors);
-
+ const celt_int16_t *prevPtr = NULL;
for (i=0;i<mode->nbEBands;i++)
{
if (mode->bits[i] != prevPtr)
}
}
celt_free((int**)mode->bits);
- mdct_clear(&mode->mdct);
- celt_free(mode->window);
+ if (check_mode(mode) != CELT_OK)
+ return;
+ celt_free((int*)mode->eBands);
+ celt_free((int*)mode->pBands);
+ celt_free((int*)mode->allocVectors);
+
+ celt_free((celt_word16_t*)mode->window);
mode->marker_start = MODEFREED;
mode->marker_end = MODEFREED;
+#ifndef SHORTCUTS
+ psydecay_clear(&mode->psy);
+#endif
+#endif
+ mdct_clear(&mode->mdct);
+ pitch_state_free(mode->fft);
+ quant_prob_free(mode->prob);
+ celt_free((celt_int16_t *)mode->energy_alloc);
celt_free((CELTMode *)mode);
-
}
int check_mode(const CELTMode *mode)