2013-02-13 17:41:24 +01:00
|
|
|
/* (C) 2007-2009 Jean-Marc Valin, CSIRO
|
|
|
|
(C) 2008 Gregory Maxwell */
|
|
|
|
/*
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions
|
|
|
|
are met:
|
|
|
|
|
|
|
|
- Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
- Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
- Neither the name of the Xiph.org Foundation nor the names of its
|
|
|
|
contributors may be used to endorse or promote products derived from
|
|
|
|
this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
|
|
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "cc6_celt.h"
|
2013-02-13 19:51:13 +01:00
|
|
|
#include "cc6_modes.h"
|
|
|
|
#include "cc6_rate.h"
|
|
|
|
#include "cc6_os_support.h"
|
|
|
|
#include "cc6_stack_alloc.h"
|
|
|
|
#include "cc6_quant_bands.h"
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
#ifdef STATIC_MODES
|
|
|
|
#include "static_modes.c"
|
|
|
|
#endif
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
#define cc6_MODEVALID 0xa110ca7e
|
|
|
|
#define cc6_MODEPARTIAL 0x7eca10a1
|
|
|
|
#define cc6_MODEFREED 0xb10cf8ee
|
2013-02-13 17:41:24 +01:00
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
#ifndef cc6_M_PI
|
|
|
|
#define cc6_M_PI 3.141592653
|
2013-02-13 17:41:24 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
int cc6_celt_mode_info(const cc6_CELTMode *mode, int request, cc6_celt_int32_t *value)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
if (cc6_check_mode(mode) != cc6_CELT_OK)
|
|
|
|
return cc6_CELT_INVALID_MODE;
|
2013-02-13 17:41:24 +01:00
|
|
|
switch (request)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
case cc6_CELT_GET_FRAME_SIZE:
|
2013-02-13 17:41:24 +01:00
|
|
|
*value = mode->mdctSize;
|
|
|
|
break;
|
2013-02-15 21:04:02 +01:00
|
|
|
case cc6_CELT_GET_LOOKAHEAD:
|
2013-02-13 17:41:24 +01:00
|
|
|
*value = mode->overlap;
|
|
|
|
break;
|
2013-02-15 21:04:02 +01:00
|
|
|
case cc6_CELT_GET_NB_CHANNELS:
|
2013-02-13 17:41:24 +01:00
|
|
|
*value = mode->nbChannels;
|
|
|
|
break;
|
2013-02-15 21:04:02 +01:00
|
|
|
case cc6_CELT_GET_BITSTREAM_VERSION:
|
|
|
|
*value = cc6_CELT_BITSTREAM_VERSION;
|
2013-02-13 17:41:24 +01:00
|
|
|
break;
|
2013-02-15 21:04:02 +01:00
|
|
|
case cc6_CELT_GET_SAMPLE_RATE:
|
2013-02-13 17:41:24 +01:00
|
|
|
*value = mode->Fs;
|
|
|
|
break;
|
|
|
|
default:
|
2013-02-15 21:04:02 +01:00
|
|
|
return cc6_CELT_UNIMPLEMENTED;
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
return cc6_CELT_OK;
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef STATIC_MODES
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
#define cc6_PBANDS 8
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
#ifdef STDIN_TUNING
|
2013-02-15 21:04:02 +01:00
|
|
|
int cc6_MIN_BINS;
|
2013-02-13 17:41:24 +01:00
|
|
|
#else
|
2013-02-15 21:04:02 +01:00
|
|
|
#define cc6_MIN_BINS 3
|
2013-02-13 17:41:24 +01:00
|
|
|
#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 */
|
2013-02-15 21:04:02 +01:00
|
|
|
#define cc6_BARK_BANDS 25
|
|
|
|
static const cc6_celt_int16_t bark_freq[cc6_BARK_BANDS+1] = {
|
2013-02-13 17:41:24 +01:00
|
|
|
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};
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
static const cc6_celt_int16_t pitch_freq[cc6_PBANDS+1] ={0, 345, 689, 1034, 1378, 2067, 3273, 5340, 6374};
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
/* 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
|
2013-02-15 21:04:02 +01:00
|
|
|
int cc6_BITALLOC_SIZE;
|
|
|
|
int *cc6_band_allocation;
|
2013-02-13 17:41:24 +01:00
|
|
|
#else
|
2013-02-15 21:04:02 +01:00
|
|
|
#define cc6_BITALLOC_SIZE 12
|
|
|
|
static const int cc6_band_allocation[cc6_BARK_BANDS*cc6_BITALLOC_SIZE] =
|
2013-02-13 17:41:24 +01:00
|
|
|
/* 0 100 200 300 400 510 630 770 920 1k 1.2 1.5 1.7 2k 2.3 2.7 3.1 3.7 4.4 5.3 6.4 7.7 9.5 12k 15k */
|
|
|
|
{ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0*/
|
|
|
|
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, /*1*/
|
|
|
|
2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 4, 5, 7, 7, 7, 5, 4, 0, 0, 0, 0, 0, 0, /*2*/
|
|
|
|
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 6, 8, 8, 8, 6, 5, 4, 0, 0, 0, 0, 0, /*3*/
|
|
|
|
3, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 6, 7, 9, 9, 9, 7, 6, 5, 5, 5, 0, 0, 0, /*4*/
|
|
|
|
3, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 9, 10, 10, 10, 9, 6, 5, 5, 5, 5, 1, 0, /*5*/
|
|
|
|
4, 3, 3, 4, 6, 7, 7, 7, 7, 7, 8, 9, 9, 9, 11, 10, 10, 9, 9, 8, 11, 10, 10, 1, 0, /*6*/
|
|
|
|
5, 5, 5, 6, 7, 7, 7, 7, 8, 8, 9, 10, 10, 12, 12, 11, 11, 17, 12, 15, 15, 20, 18, 10, 1, /*7*/
|
|
|
|
6, 7, 7, 7, 8, 8, 8, 8, 9, 10, 11, 12, 14, 17, 18, 21, 22, 27, 29, 39, 37, 38, 40, 35, 1, /*8*/
|
|
|
|
7, 7, 7, 8, 8, 8, 10, 10, 10, 13, 14, 18, 20, 24, 28, 32, 32, 35, 38, 38, 42, 50, 59, 54, 31, /*9*/
|
|
|
|
8, 8, 8, 8, 8, 9, 10, 12, 14, 20, 22, 25, 28, 30, 35, 42, 46, 50, 55, 60, 62, 62, 72, 82, 62, /*10*/
|
|
|
|
9, 9, 9, 10, 12, 13, 15, 18, 22, 30, 32, 35, 40, 45, 55, 62, 66, 70, 85, 90, 92, 92, 92,102, 92, /*11*/
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
static cc6_celt_int16_t *cc6_compute_ebands(cc6_celt_int32_t Fs, int frame_size, int *nbEBands)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_int16_t *eBands;
|
2013-02-13 17:41:24 +01:00
|
|
|
int i, res, min_width, lin, low, high, nBark;
|
|
|
|
res = (Fs+frame_size)/(2*frame_size);
|
2013-02-15 21:04:02 +01:00
|
|
|
min_width = cc6_MIN_BINS*res;
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
/* Find the number of critical bands supported by our sampling rate */
|
2013-02-15 21:04:02 +01:00
|
|
|
for (nBark=1;nBark<cc6_BARK_BANDS;nBark++)
|
2013-02-13 17:41:24 +01:00
|
|
|
if (bark_freq[nBark+1]*2 >= Fs)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Find where the linear part ends (i.e. where the spacing is more than min_width */
|
|
|
|
for (lin=0;lin<nBark;lin++)
|
|
|
|
if (bark_freq[lin+1]-bark_freq[lin] >= min_width)
|
|
|
|
break;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
low = ((bark_freq[lin]/res)+(cc6_MIN_BINS-1))/cc6_MIN_BINS;
|
2013-02-13 17:41:24 +01:00
|
|
|
high = nBark-lin;
|
|
|
|
*nbEBands = low+high;
|
2013-02-15 21:04:02 +01:00
|
|
|
eBands = cc6_celt_alloc(sizeof(cc6_celt_int16_t)*(*nbEBands+2));
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
if (eBands==NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Linear spacing (min_width) */
|
|
|
|
for (i=0;i<low;i++)
|
2013-02-15 21:04:02 +01:00
|
|
|
eBands[i] = cc6_MIN_BINS*i;
|
2013-02-13 17:41:24 +01:00
|
|
|
/* 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++)
|
2013-02-15 21:04:02 +01:00
|
|
|
if (eBands[i] < cc6_MIN_BINS*i)
|
|
|
|
eBands[i] = cc6_MIN_BINS*i;
|
2013-02-13 17:41:24 +01:00
|
|
|
eBands[*nbEBands] = (bark_freq[nBark]+res/2)/res;
|
|
|
|
eBands[*nbEBands+1] = frame_size;
|
|
|
|
if (eBands[*nbEBands] > eBands[*nbEBands+1])
|
|
|
|
eBands[*nbEBands] = eBands[*nbEBands+1];
|
|
|
|
|
|
|
|
/* FIXME: Remove last band if too small */
|
|
|
|
return eBands;
|
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
static void cc6_compute_pbands(cc6_CELTMode *mode, int res)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
int i;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_int16_t *pBands;
|
|
|
|
pBands=cc6_celt_alloc(sizeof(cc6_celt_int16_t)*(cc6_PBANDS+2));
|
2013-02-13 17:41:24 +01:00
|
|
|
mode->pBands = pBands;
|
|
|
|
if (pBands==NULL)
|
|
|
|
return;
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->nbPBands = cc6_PBANDS;
|
|
|
|
for (i=0;i<cc6_PBANDS+1;i++)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
pBands[i] = (pitch_freq[i]+res/2)/res;
|
|
|
|
if (pBands[i] < mode->eBands[i])
|
|
|
|
pBands[i] = mode->eBands[i];
|
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
pBands[cc6_PBANDS+1] = mode->eBands[mode->nbEBands+1];
|
2013-02-13 17:41:24 +01:00
|
|
|
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;
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->pitchEnd = pBands[cc6_PBANDS];
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
static void cc6_compute_allocation_table(cc6_CELTMode *mode, int res)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
int i, j, nBark;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_int16_t *allocVectors;
|
|
|
|
const int C = cc6_CHANNELS(mode);
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
/* Find the number of critical bands supported by our sampling rate */
|
2013-02-15 21:04:02 +01:00
|
|
|
for (nBark=1;nBark<cc6_BARK_BANDS;nBark++)
|
2013-02-13 17:41:24 +01:00
|
|
|
if (bark_freq[nBark+1]*2 >= mode->Fs)
|
|
|
|
break;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->nbAllocVectors = cc6_BITALLOC_SIZE;
|
|
|
|
allocVectors = cc6_celt_alloc(sizeof(cc6_celt_int16_t)*(cc6_BITALLOC_SIZE*mode->nbEBands));
|
2013-02-13 17:41:24 +01:00
|
|
|
if (allocVectors==NULL)
|
|
|
|
return;
|
|
|
|
/* Compute per-codec-band allocation from per-critical-band matrix */
|
2013-02-15 21:04:02 +01:00
|
|
|
for (i=0;i<cc6_BITALLOC_SIZE;i++)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_int32_t current = 0;
|
2013-02-13 17:41:24 +01:00
|
|
|
int eband = 0;
|
|
|
|
for (j=0;j<nBark;j++)
|
|
|
|
{
|
|
|
|
int edge, low;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_int32_t alloc;
|
2013-02-13 17:41:24 +01:00
|
|
|
edge = mode->eBands[eband+1]*res;
|
2013-02-15 21:04:02 +01:00
|
|
|
alloc = cc6_band_allocation[i*cc6_BARK_BANDS+j];
|
2013-02-13 17:41:24 +01:00
|
|
|
alloc = alloc*C*mode->mdctSize;
|
|
|
|
if (edge < bark_freq[j+1])
|
|
|
|
{
|
|
|
|
int num, den;
|
|
|
|
num = alloc * (edge-bark_freq[j]);
|
|
|
|
den = bark_freq[j+1]-bark_freq[j];
|
|
|
|
low = (num+den/2)/den;
|
|
|
|
allocVectors[i*mode->nbEBands+eband] = (current+low+128)/256;
|
|
|
|
current=0;
|
|
|
|
eband++;
|
|
|
|
current += alloc-low;
|
|
|
|
} else {
|
|
|
|
current += alloc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allocVectors[i*mode->nbEBands+eband] = (current+128)/256;
|
|
|
|
}
|
|
|
|
mode->allocVectors = allocVectors;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* STATIC_MODES */
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_CELTMode *cc6_celt_mode_create(cc6_celt_int32_t Fs, int channels, int frame_size, int *error)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
#ifdef STDIN_TUNING
|
2013-02-15 21:04:02 +01:00
|
|
|
scanf("%d ", &cc6_MIN_BINS);
|
|
|
|
scanf("%d ", &cc6_BITALLOC_SIZE);
|
|
|
|
cc6_band_allocation = cc6_celt_alloc(sizeof(int)*cc6_BARK_BANDS*cc6_BITALLOC_SIZE);
|
|
|
|
for (i=0;i<cc6_BARK_BANDS*cc6_BITALLOC_SIZE;i++)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
scanf("%d ", cc6_band_allocation+i);
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef STATIC_MODES
|
2013-02-15 21:04:02 +01:00
|
|
|
const cc6_CELTMode *m = NULL;
|
|
|
|
cc6_CELTMode *mode=NULL;
|
|
|
|
cc6_ALLOC_STACK;
|
2013-02-13 17:41:24 +01:00
|
|
|
#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
|
2013-02-15 21:04:02 +01:00
|
|
|
if (cc6_global_stack==NULL)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_free(cc6_global_stack);
|
2013-02-13 17:41:24 +01:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
m = static_mode_list[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m == NULL)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Mode not included as part of the static modes");
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_BAD_ARG;
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
mode = (cc6_CELTMode*)cc6_celt_alloc(sizeof(cc6_CELTMode));
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode==NULL)
|
|
|
|
goto failure;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_CELT_COPY(mode, m, 1);
|
|
|
|
mode->marker_start = cc6_MODEPARTIAL;
|
2013-02-13 17:41:24 +01:00
|
|
|
#else
|
|
|
|
int res;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_CELTMode *mode=NULL;
|
|
|
|
cc6_celt_word16_t *window;
|
|
|
|
cc6_ALLOC_STACK;
|
2013-02-13 17:41:24 +01:00
|
|
|
#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
|
2013-02-15 21:04:02 +01:00
|
|
|
if (cc6_global_stack==NULL)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_free(cc6_global_stack);
|
2013-02-13 17:41:24 +01:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* The good thing here is that permutation of the arguments will automatically be invalid */
|
|
|
|
|
|
|
|
if (Fs < 32000 || Fs > 96000)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Sampling rate must be between 32 kHz and 96 kHz");
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_BAD_ARG;
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (channels < 0 || channels > 2)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Only mono and stereo supported");
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_BAD_ARG;
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (frame_size < 64 || frame_size > 1024 || frame_size%2!=0)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Only even frame sizes from 64 to 1024 are supported");
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_BAD_ARG;
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
res = (Fs+frame_size)/(2*frame_size);
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
mode = cc6_celt_alloc(sizeof(cc6_CELTMode));
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode==NULL)
|
|
|
|
goto failure;
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->marker_start = cc6_MODEPARTIAL;
|
2013-02-13 17:41:24 +01:00
|
|
|
mode->Fs = Fs;
|
|
|
|
mode->mdctSize = frame_size;
|
|
|
|
mode->nbChannels = channels;
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->eBands = cc6_compute_ebands(Fs, frame_size, &mode->nbEBands);
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode->eBands==NULL)
|
|
|
|
goto failure;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_compute_pbands(mode, res);
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode->pBands==NULL)
|
|
|
|
goto failure;
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->ePredCoef = cc6_QCONST16(.8f,15);
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
if (frame_size > 640 && (frame_size%16)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 8;
|
|
|
|
} else if (frame_size > 384 && (frame_size%8)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 4;
|
|
|
|
} else if (frame_size > 384 && (frame_size%10)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 5;
|
|
|
|
} else if (frame_size > 256 && (frame_size%6)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 3;
|
|
|
|
} else if (frame_size > 256 && (frame_size%8)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 4;
|
|
|
|
} else if (frame_size > 64 && (frame_size%4)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 2;
|
|
|
|
} else if (frame_size > 128 && (frame_size%6)==0)
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 3;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
mode->nbShortMdcts = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Overlap must be divisible by 4 */
|
|
|
|
if (mode->nbShortMdcts > 1)
|
|
|
|
mode->overlap = ((frame_size/mode->nbShortMdcts)>>2)<<2;
|
|
|
|
else
|
|
|
|
mode->overlap = (frame_size>>3)<<2;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_compute_allocation_table(mode, res);
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode->allocVectors==NULL)
|
|
|
|
goto failure;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
window = (cc6_celt_word16_t*)cc6_celt_alloc(mode->overlap*sizeof(cc6_celt_word16_t));
|
2013-02-13 17:41:24 +01:00
|
|
|
if (window==NULL)
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
#ifndef FIXED_POINT
|
|
|
|
for (i=0;i<mode->overlap;i++)
|
2013-02-15 21:04:02 +01:00
|
|
|
window[i] = cc6_Q15ONE*sin(.5*cc6_M_PI* sin(.5*cc6_M_PI*(i+.5)/mode->overlap) * sin(.5*cc6_M_PI*(i+.5)/mode->overlap));
|
2013-02-13 17:41:24 +01:00
|
|
|
#else
|
|
|
|
for (i=0;i<mode->overlap;i++)
|
2013-02-15 21:04:02 +01:00
|
|
|
window[i] = cc6_MIN32(32767,32768.*sin(.5*cc6_M_PI* sin(.5*cc6_M_PI*(i+.5)/mode->overlap) * sin(.5*cc6_M_PI*(i+.5)/mode->overlap)));
|
2013-02-13 17:41:24 +01:00
|
|
|
#endif
|
|
|
|
mode->window = window;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->bits = (const cc6_celt_int16_t **)cc6_compute_alloc_cache(mode, 1);
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode->bits==NULL)
|
|
|
|
goto failure;
|
|
|
|
|
|
|
|
#ifndef SHORTCUTS
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_psydecay_init(&mode->psy, cc6_MAX_PERIOD/2, mode->Fs);
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode->psy.decayR==NULL)
|
|
|
|
goto failure;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* !STATIC_MODES */
|
|
|
|
|
|
|
|
#ifdef DISABLE_STEREO
|
|
|
|
if (channels > 1)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Stereo support was disable from this build");
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_BAD_ARG;
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_mdct_init(&mode->mdct, 2*mode->mdctSize);
|
|
|
|
mode->fft = cc6_pitch_state_alloc(cc6_MAX_PERIOD);
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
mode->shortMdctSize = mode->mdctSize/mode->nbShortMdcts;
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_mdct_init(&mode->shortMdct, 2*mode->shortMdctSize);
|
2013-02-13 17:41:24 +01:00
|
|
|
mode->shortWindow = mode->window;
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->prob = cc6_quant_prob_alloc(mode);
|
2013-02-13 17:41:24 +01:00
|
|
|
if ((mode->mdct.trig==NULL) || (mode->mdct.kfft==NULL) || (mode->fft==NULL) ||
|
|
|
|
(mode->shortMdct.trig==NULL) || (mode->shortMdct.kfft==NULL) || (mode->prob==NULL))
|
|
|
|
goto failure;
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->marker_start = cc6_MODEVALID;
|
|
|
|
mode->marker_end = cc6_MODEVALID;
|
2013-02-13 17:41:24 +01:00
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_OK;
|
2013-02-13 17:41:24 +01:00
|
|
|
return mode;
|
|
|
|
failure:
|
|
|
|
if (error)
|
2013-02-15 21:04:02 +01:00
|
|
|
*error = cc6_CELT_INVALID_MODE;
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode!=NULL)
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_mode_destroy(mode);
|
2013-02-13 17:41:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
void cc6_celt_mode_destroy(cc6_CELTMode *mode)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
int i;
|
2013-02-15 21:04:02 +01:00
|
|
|
const cc6_celt_int16_t *prevPtr = NULL;
|
2013-02-13 17:41:24 +01:00
|
|
|
if (mode == NULL)
|
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("NULL passed to cc6_celt_mode_destroy");
|
2013-02-13 17:41:24 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
if (mode->marker_start == cc6_MODEFREED || mode->marker_end == cc6_MODEFREED)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("Freeing a mode which has already been freed");
|
2013-02-13 17:41:24 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
if (mode->marker_start != cc6_MODEVALID && mode->marker_start != cc6_MODEPARTIAL)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("This is not a valid CELT mode structure");
|
2013-02-13 17:41:24 +01:00
|
|
|
return;
|
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
mode->marker_start = cc6_MODEFREED;
|
2013-02-13 17:41:24 +01:00
|
|
|
#ifndef STATIC_MODES
|
|
|
|
if (mode->bits!=NULL)
|
|
|
|
{
|
|
|
|
for (i=0;i<mode->nbEBands;i++)
|
|
|
|
{
|
|
|
|
if (mode->bits[i] != prevPtr)
|
|
|
|
{
|
|
|
|
prevPtr = mode->bits[i];
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_free((int*)mode->bits[i]);
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_free((int**)mode->bits);
|
|
|
|
cc6_celt_free((int*)mode->eBands);
|
|
|
|
cc6_celt_free((int*)mode->pBands);
|
|
|
|
cc6_celt_free((int*)mode->allocVectors);
|
2013-02-13 17:41:24 +01:00
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_free((cc6_celt_word16_t*)mode->window);
|
2013-02-13 17:41:24 +01:00
|
|
|
|
|
|
|
#ifndef SHORTCUTS
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_psydecay_clear(&mode->psy);
|
2013-02-13 17:41:24 +01:00
|
|
|
#endif
|
|
|
|
#endif
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_mdct_clear(&mode->mdct);
|
|
|
|
cc6_mdct_clear(&mode->shortMdct);
|
|
|
|
cc6_pitch_state_free(mode->fft);
|
|
|
|
cc6_quant_prob_free(mode->prob);
|
|
|
|
mode->marker_end = cc6_MODEFREED;
|
|
|
|
cc6_celt_free((cc6_CELTMode *)mode);
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|
|
|
|
|
2013-02-15 21:04:02 +01:00
|
|
|
int cc6_check_mode(const cc6_CELTMode *mode)
|
2013-02-13 17:41:24 +01:00
|
|
|
{
|
|
|
|
if (mode==NULL)
|
2013-02-15 21:04:02 +01:00
|
|
|
return cc6_CELT_INVALID_MODE;
|
|
|
|
if (mode->marker_start == cc6_MODEVALID && mode->marker_end == cc6_MODEVALID)
|
|
|
|
return cc6_CELT_OK;
|
|
|
|
if (mode->marker_start == cc6_MODEFREED || mode->marker_end == cc6_MODEFREED)
|
|
|
|
cc6_celt_warning("Using a mode that has already been freed");
|
2013-02-13 17:41:24 +01:00
|
|
|
else
|
2013-02-15 21:04:02 +01:00
|
|
|
cc6_celt_warning("This is not a valid CELT mode");
|
|
|
|
return cc6_CELT_INVALID_MODE;
|
2013-02-13 17:41:24 +01:00
|
|
|
}
|