-/* (C) 2007 Jean-Marc Valin, CSIRO
+/* (C) 2007-2008 Jean-Marc Valin, CSIRO
*/
/*
Redistribution and use in source and binary forms, with or without
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "modes.h"
-
-#define NBANDS 18
-#define PBANDS 8
-#define PITCH_END 74
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
-#define NBANDS128 15
-#define PBANDS128 8
-#define PITCH_END128 45
+#include "celt.h"
+#include "modes.h"
+#include "rate.h"
+#include "os_support.h"
+#include "stack_alloc.h"
+#include "quant_bands.h"
-static const float means[15] = {
- 14.8621, 12.6918, 10.2978, 9.5862, 10.3784,
- 10.4555, 9.1594, 9.0280, 8.3291, 8.3410,
- 8.5737, 8.5614, 9.0107, 7.6809, 7.0665};
+#ifdef STATIC_MODES
+#include "static_modes.c"
+#endif
-static const float means18[18] = {
- 9.9067, 8.4524, 6.8577, 6.3804, 6.1786, 5.9815,
- 6.2068, 6.1076, 5.7711, 5.7734, 5.7935, 5.3981,
- 5.1992, 5.7214, 5.9656, 5.7548, 5.0802, 4.2626};
+#define MODEVALID 0xa110ca7e
+#define MODEFREED 0xb10cf8ee
-static const int decay[15] = {
- 14800, 13800, 12600, 12000, 11000, 10000, 9800, 8400, 8000, 7500, 7000, 7000, 7000, 6000, 6000
-};
+#ifndef M_PI
+#define M_PI 3.141592653
+#endif
-static const int decay18[18] = {
- 14800, 13800, 12600, 12000, 11000, 11000, 10000, 10000, 9800, 8400, 8400, 8000, 7500, 7000, 7000, 7000, 6000, 6000
-};
-const int qbank0[NBANDS +2] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 38, 44, 52, 62, 74, 90,112,142,182, 232,256};
-const int pbank0[PBANDS +2] = {0, 4, 8, 12, 16, 24, 38, 62, PITCH_END, 256};
-//const int pbank0[PBANDS +2] = {0, 4, 8, 12, 19, PITCH_END, 128};
-const int qpulses0[NBANDS ] = {7, 6, 6, 5, 5, 5, 5, 4, 3, 3, 3, 3, 3, 3, -3, -2, 0, 0};
-//const int qpulses0[NBANDS ] = {7, 5, 5, 5, 4, 4, 3, 3, 3, 3, 4, 3, 3, -2, 0, 0, 0, 0};
+int EXPORT celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
+{
+ switch (request)
+ {
+ case CELT_GET_FRAME_SIZE:
+ *value = mode->mdctSize;
+ break;
+ case CELT_GET_LOOKAHEAD:
+ *value = mode->overlap;
+ break;
+ 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
-const int qbank1[NBANDS128+2] = {0, 2, 4, 6, 8, 12, 16, 20, 24, 28, 36, 44, 52, 68, 84, 116, 128};
+#define PBANDS 8
-const int qpulses1[NBANDS128] = {7, 5, 5, 5, 4, 5, 4, 5, 5, 4, 2, 0, 0, 0, 0};
-const int qpulses2[NBANDS] = {28,25,23,20,18,15, 13, 11, 10, 8,8, 7, 7, -6, -5, -4, -1, -1};
-//const int qpulses2[NBANDS128] = {28,24,20,16,24,20, 18, 12, 10, 10,-7, -4, 1, 1, 1, 1, 1, 1};
-const int qpulses2s[NBANDS128] ={38,30,24,20,24,20, 18, 16, 14, 20,-20,-14, -8, -8, -5};
+#ifdef STDIN_TUNING
+int MIN_BINS;
+#else
+#define MIN_BINS 3
+#endif
-const int qpulses4s[NBANDS] ={38,31,25,21,18,16, 14, 12, 14, 12,14,15, 14, 15, 16, 12, 10, 6};
+/* 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
+static const celt_int16_t bark_freq[BARK_BANDS+1] = {
+ 0, 100, 200, 300, 400,
+ 510, 630, 770, 920, 1080,
+ 1270, 1480, 1720, 2000, 2320,
+ 2700, 3150, 3700, 4400, 5300,
+ 6400, 7700, 9500, 12000, 15500,
+ 20000};
-//const int qpulses4s[NBANDS128] ={38,35,30,27,24,22, 21, 20, 22, 20,20,20, 20, 20, 14, 12, 12, 12};
+static const celt_int16_t pitch_freq[PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374};
-const int pbank1[PBANDS128+2] = {0, 2, 4, 6, 8, 12, 20, 28, PITCH_END128, 128};
-//const int pbank1[PBANDS128+2] = {0, 4, 8, 12, 20, PITCH_END128, 128};
+/* 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 */
-#define NALLOCS 7
-int bitalloc0[NBANDS*NALLOCS] =
- { 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
- 8, 7, 7, 6, 6, 6, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 17, 15, 6, 7,
- 16, 15, 14, 14, 14, 13, 13, 13, 13, 13, 15, 16, 17, 18, 20, 18, 11, 12,
- 26, 25, 24, 22, 20, 18, 19, 19, 25, 22, 25, 30, 30, 35, 35, 35, 35, 25,
- 32, 30, 28, 27, 25, 24, 23, 21, 29, 27, 35, 40, 42, 50, 59, 54, 51, 36,
- 42, 40, 38, 37, 35, 34, 33, 31, 39, 37, 45, 50, 52, 60, 60, 60, 60, 46,
+#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, 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 celt_int16_t *compute_ebands(celt_int32_t Fs, int frame_size, int *nbEBands)
+{
+ celt_int16_t *eBands;
+ int i, res, min_width, lin, low, high;
+ res = (Fs+frame_size)/(2*frame_size);
+ min_width = MIN_BINS*res;
+ /*printf ("min_width = %d\n", min_width);*/
-#define NBANDS256 15
-#define PBANDS256 8
-#define PITCH_END256 88
-const int qbank3[NBANDS256+2] = {0, 4, 8, 12, 16, 24, 32, 40, 48, 56, 72, 88, 104, 136, 168, 232, 256};
-//const int pbank3[PBANDS256+2] = {0, 8, 16, 24, 40, PITCH_END256, 256};
-const int pbank3[PBANDS256+2] = {0, 4, 8, 12, 16, 24, 40, 56, PITCH_END256, 256};
-
-static const CELTMode mono_mode = {
- 128, /**< overlap */
- 256, /**< mdctSize */
- 1, /**< nbMdctBlocks */
- 1, /**< channels */
+ /* Find where the linear part ends (i.e. where the spacing is more than min_width */
+ for (lin=0;lin<BARK_BANDS;lin++)
+ if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
+ break;
- NBANDS, /**< nbEBands */
- PBANDS, /**< nbPBands */
- PITCH_END, /**< pitchEnd */
+ /*printf ("lin = %d (%d Hz)\n", lin, bark_freq[lin]);*/
+ low = ((bark_freq[lin]/res)+(MIN_BINS-1))/MIN_BINS;
+ high = BARK_BANDS-lin;
+ *nbEBands = low+high;
+ eBands = celt_alloc(sizeof(celt_int16_t)*(*nbEBands+2));
- qbank0, /**< eBands */
- pbank0, /**< pBands*/
- qpulses0, /**< nbPulses */
+ /* Linear spacing (min_width) */
+ for (i=0;i<low;i++)
+ eBands[i] = MIN_BINS*i;
+ /* Spacing follows critical bands */
+ for (i=0;i<high;i++)
+ eBands[i+low] = (bark_freq[lin+i]+res/2)/res;
+ /* Enforce the minimum spacing at the boundary */
+ for (i=0;i<*nbEBands;i++)
+ if (eBands[i] < MIN_BINS*i)
+ eBands[i] = MIN_BINS*i;
+ eBands[*nbEBands] = (bark_freq[BARK_BANDS]+res/2)/res;
+ eBands[*nbEBands+1] = frame_size;
+ if (eBands[*nbEBands] > eBands[*nbEBands+1])
+ eBands[*nbEBands] = eBands[*nbEBands+1];
- 0.8, /**< ePredCoef */
- means18, /**< eMeans */
- decay18, /**< eDecay */
+ /* FIXME: Remove last band if too small */
+ /*for (i=0;i<*nbEBands+2;i++)
+ printf("%d ", eBands[i]);
+ printf ("\n");*/
+ return eBands;
+}
+
+static void compute_pbands(CELTMode *mode, int res)
+{
+ int i;
+ celt_int16_t *pBands;
+ pBands=celt_alloc(sizeof(celt_int16_t)*(PBANDS+2));
+ mode->nbPBands = PBANDS;
+ for (i=0;i<PBANDS+1;i++)
+ {
+ pBands[i] = (pitch_freq[i]+res/2)/res;
+ if (pBands[i] < mode->eBands[i])
+ pBands[i] = mode->eBands[i];
+ }
+ pBands[PBANDS+1] = mode->eBands[mode->nbEBands+1];
+ for (i=1;i<mode->nbPBands+1;i++)
+ {
+ int j;
+ for (j=0;j<mode->nbEBands;j++)
+ if (mode->eBands[j] <= pBands[i] && mode->eBands[j+1] > pBands[i])
+ break;
+ /*printf ("%d %d\n", i, j);*/
+ if (mode->eBands[j] != pBands[i])
+ {
+ if (pBands[i]-mode->eBands[j] < mode->eBands[j+1]-pBands[i] &&
+ mode->eBands[j] != pBands[i-1])
+ pBands[i] = mode->eBands[j];
+ else
+ pBands[i] = mode->eBands[j+1];
+ }
+ }
+ /*for (i=0;i<mode->nbPBands+2;i++)
+ printf("%d ", pBands[i]);
+ printf ("\n");*/
+ mode->pBands = pBands;
+ mode->pitchEnd = pBands[PBANDS];
+}
+
+static void compute_allocation_table(CELTMode *mode, int res)
+{
+ int i, j, eband;
+ celt_int16_t *allocVectors;
- NALLOCS, /**< nbAllocVectors */
- bitalloc0, /**< allocVectors */
-};
+ mode->nbAllocVectors = BITALLOC_SIZE;
+ allocVectors = celt_alloc(sizeof(celt_int16_t)*(BITALLOC_SIZE*mode->nbEBands));
+ for (i=0;i<BITALLOC_SIZE;i++)
+ {
+ eband = 0;
+ for (j=0;j<BARK_BANDS;j++)
+ {
+ int edge, low;
+ edge = mode->eBands[eband+1]*res;
+ if (edge < bark_freq[j+1])
+ {
+ int num, den;
+ num = band_allocation[i*BARK_BANDS+j] * (edge-bark_freq[j]);
+ den = bark_freq[j+1]-bark_freq[j];
+ low = (num+den/2)/den;
+ allocVectors[i*mode->nbEBands+eband] += low;
+ eband++;
+ allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j]-low;
+ } else {
+ allocVectors[i*mode->nbEBands+eband] += band_allocation[i*BARK_BANDS+j];
+ }
+ }
+ }
+ /*for (i=0;i<BITALLOC_SIZE;i++)
+ {
+ for (j=0;j<mode->nbEBands;j++)
+ printf ("%2d ", allocVectors[i*mode->nbEBands+j]);
+ printf ("\n");
+ }*/
+ mode->allocVectors = allocVectors;
+}
+#endif /* STATIC_MODES */
-/* Stereo mode around 120 kbps */
-static const CELTMode stereo_mode = {
- 128, /**< overlap */
- 256, /**< mdctSize */
- 1, /**< nbMdctBlocks */
- 2, /**< channels */
+static void compute_energy_allocation_table(CELTMode *mode)
+{
+ int i, j;
+ celt_int16_t *alloc;
- NBANDS, /**< nbEBands */
- PBANDS, /**< nbPBands */
- PITCH_END, /**< pitchEnd */
+ 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 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;
+ CELTMode *mode;
+ celt_word16_t *window;
+ ALLOC_STACK;
+
+ /* The good thing here is that permutation of the arguments will automatically be invalid */
- qbank0, /**< eBands */
- pbank0, /**< pBands*/
- qpulses4s, /**< nbPulses */
+ if (Fs < 32000 || Fs > 64000)
+ {
+ celt_warning("Sampling rate must be between 32 kHz and 64 kHz");
+ if (error)
+ *error = CELT_BAD_ARG;
+ return NULL;
+ }
+ if (channels < 0 || channels > 2)
+ {
+ celt_warning("Only mono and stereo supported");
+ if (error)
+ *error = CELT_BAD_ARG;
+ return NULL;
+ }
+ if (frame_size < 64 || frame_size > 256 || frame_size%2!=0)
+ {
+ celt_warning("Only even frame sizes between 64 and 256 are supported");
+ if (error)
+ *error = CELT_BAD_ARG;
+ return NULL;
+ }
+ if (lookahead < 32 || lookahead > frame_size)
+ {
+ celt_warning("The overlap must be between 32 and the frame size");
+ if (error)
+ *error = CELT_BAD_ARG;
+ return NULL;
+ }
+ res = (Fs+frame_size)/(2*frame_size);
- 0.8, /**< ePredCoef */
- means18, /**< eMeans */
- decay18, /**< eDecay */
+ mode = celt_alloc(sizeof(CELTMode));
+ mode->Fs = Fs;
+ mode->overlap = lookahead;
+ mode->mdctSize = frame_size;
+ mode->nbChannels = channels;
+ mode->eBands = compute_ebands(Fs, frame_size, &mode->nbEBands);
+ compute_pbands(mode, res);
+ mode->ePredCoef = QCONST16(.8f,15);
- NALLOCS, /**< nbAllocVectors */
- bitalloc0, /**< allocVectors */
-};
+ compute_allocation_table(mode, res);
+ /*printf ("%d bands\n", mode->nbEBands);*/
+
+ window = (celt_word16_t*)celt_alloc(mode->overlap*sizeof(celt_word16_t));
-const CELTMode const *celt_mono = &mono_mode;
-const CELTMode const *celt_stereo = &stereo_mode;
-
-
-#define NBANDS51 17
-#define PBANDS51 8
-#define PITCH_END51 64
-const int qbank51[NBANDS51 +2] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 38, 44, 52, 64, 78, 96,122,156,204, 256};
-const int qbank51b[NBANDS +2] = {0, 3, 6, 9, 12, 16, 20, 24, 28, 32, 38, 44, 52, 64, 78, 96,122,156,204, 256};
-
-const int pbank51[PBANDS51 +2] = {0, 4, 8, 12, 16, 24, 32, 44, PITCH_END51, 256};
-const int pbank51b[PBANDS +2] = {0, 3, 6, 9, 12, 20, 38, 52, PITCH_END51, 256};
-#define NALLOCS51 10
-int bitalloc51[NBANDS51*NALLOCS51] =
- { 6, 5, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0,
- 8, 7, 6, 5, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0,
- 9, 8, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0,
- 10, 9, 8, 8, 7, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0,
- 10, 9, 9, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 10, 10, 5, 5,
- 16, 15, 14, 14, 14, 13, 13, 13, 13, 13, 15, 16, 17, 18, 20, 18, 11,
- 26, 25, 24, 22, 20, 18, 19, 19, 25, 22, 25, 30, 30, 35, 35, 35, 35,
- 32, 30, 28, 27, 25, 24, 23, 21, 29, 27, 35, 40, 42, 50, 59, 54, 51,
- 42, 40, 38, 37, 35, 34, 33, 31, 39, 37, 45, 50, 52, 60, 60, 60, 60,
- };
-
-static const CELTMode ld51 = {
- 128, /**< overlap */
- 256, /**< mdctSize */
- 1, /**< nbMdctBlocks */
- 1, /**< channels */
-
- NBANDS51, /**< nbEBands */
- PBANDS51, /**< nbPBands */
- PITCH_END51, /**< pitchEnd */
-
- qbank51, /**< eBands */
- pbank51, /**< pBands*/
- 0, /**< nbPulses */
-
- 0.8, /**< ePredCoef */
- means18, /**< eMeans */
- decay18, /**< eDecay */
-
- NALLOCS51, /**< nbAllocVectors */
- bitalloc51, /**< allocVectors */
-};
-const CELTMode const *celt_ld51 = &ld51;
+#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++)
+ 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);
-int celt_mode_info(const CELTMode *mode, int request, celt_int32_t *value)
+#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 EXPORT celt_mode_destroy(CELTMode *mode)
{
- switch (request)
+#ifndef STATIC_MODES
+ int i;
+ const celt_int16_t *prevPtr = NULL;
+ for (i=0;i<mode->nbEBands;i++)
{
- case CELT_GET_FRAME_SIZE:
- *value = mode->mdctSize;
- break;
- case CELT_GET_LOOKAHEAD:
- *value = mode->overlap;
- break;
- case CELT_GET_NB_CHANNELS:
- *value = mode->nbChannels;
- break;
- default:
- return CELT_BAD_ARG;
+ if (mode->bits[i] != prevPtr)
+ {
+ prevPtr = mode->bits[i];
+ celt_free((int*)mode->bits[i]);
+ }
}
- return CELT_OK;
+ celt_free((int**)mode->bits);
+ 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)
+{
+ if (mode->marker_start == MODEVALID && mode->marker_end == MODEVALID)
+ return CELT_OK;
+ if (mode->marker_start == MODEFREED || mode->marker_end == MODEFREED)
+ celt_warning("Using a mode that has already been freed");
+ else
+ celt_warning("This is not a valid CELT mode");
+ return CELT_INVALID_MODE;
+}