MDCT analysis-synthesis (untested)

This commit is contained in:
Jean-Marc Valin 2007-11-30 01:10:42 +11:00
parent 8ebd345430
commit f02ba11950
5 changed files with 202 additions and 49 deletions

View file

@ -8,12 +8,27 @@
<primarylanguage>C</primarylanguage> <primarylanguage>C</primarylanguage>
<ignoreparts/> <ignoreparts/>
<projectname>celt</projectname> <projectname>celt</projectname>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
<defaultencoding/>
</general> </general>
<kdevautoproject> <kdevautoproject>
<general> <general>
<useconfiguration>debug</useconfiguration> <useconfiguration>default</useconfiguration>
</general> </general>
<run/> <run>
<mainprogram/>
<programargs/>
<globaldebugarguments/>
<globalcwd/>
<useglobalprogram>true</useglobalprogram>
<terminal>false</terminal>
<autocompile>false</autocompile>
<autoinstall>false</autoinstall>
<autokdesu>false</autokdesu>
<envvars/>
</run>
<configurations> <configurations>
<optimized> <optimized>
<builddir>optimized</builddir> <builddir>optimized</builddir>
@ -31,11 +46,30 @@
<cflags>-O0 -g3</cflags> <cflags>-O0 -g3</cflags>
</debug> </debug>
</configurations> </configurations>
<make>
<envvars>
<envvar value="1" name="WANT_AUTOCONF_2_5" />
<envvar value="1" name="WANT_AUTOMAKE_1_6" />
</envvars>
</make>
</kdevautoproject> </kdevautoproject>
<kdevdebugger> <kdevdebugger>
<general> <general>
<dbgshell>libtool</dbgshell> <dbgshell>libtool</dbgshell>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
<raiseGDBOnStart>false</raiseGDBOnStart>
</general> </general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger> </kdevdebugger>
<kdevdoctreeview> <kdevdoctreeview>
<ignoretocs> <ignoretocs>
@ -92,4 +126,69 @@
<type ext="h" /> <type ext="h" />
</useglobaltypes> </useglobaltypes>
</kdevfilecreate> </kdevfilecreate>
<kdevcppsupport>
<qt>
<used>false</used>
<version>3</version>
<includestyle>3</includestyle>
<root></root>
<designerintegration>EmbeddedKDevDesigner</designerintegration>
<qmake></qmake>
<designer></designer>
<designerpluginpaths/>
</qt>
<codecompletion>
<automaticCodeCompletion>false</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
<completionBoxItemOrder>0</completionBoxItemOrder>
<howEvaluationContextMenu>true</howEvaluationContextMenu>
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
<processPrimaryTypes>true</processPrimaryTypes>
<processFunctionArguments>false</processFunctionArguments>
<preProcessAllHeaders>false</preProcessAllHeaders>
<parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
<alwaysParseInBackground>true</alwaysParseInBackground>
<usePermanentCaching>true</usePermanentCaching>
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
<includePaths>.;</includePaths>
</codecompletion>
<creategettersetter>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
<splitheadersource>
<enabled>false</enabled>
<synchronize>true</synchronize>
<orientation>Vertical</orientation>
</splitheadersource>
<references/>
</kdevcppsupport>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
<kdevfileview>
<groups>
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
</kdevelop> </kdevelop>

View file

@ -30,6 +30,10 @@
*/ */
#include "os_support.h" #include "os_support.h"
#include "mdct.h"
#include <math.h>
#define MAX_PERIOD 2048
struct CELTState_ { struct CELTState_ {
int frame_size; int frame_size;
@ -39,6 +43,8 @@ struct CELTState_ {
float preemph; float preemph;
float preemph_mem; float preemph_mem;
mdct_lookup mdct_lookup;
float *window; float *window;
float *in_mem; float *in_mem;
float *mdct_overlap; float *mdct_overlap;
@ -49,24 +55,53 @@ typedef struct CELTState_ CELTState;
CELTState *celt_init(int blockSize, int blocksPerFrame) CELTState *celt_init(int blockSize, int blocksPerFrame)
{ {
int i, N;
N = blockSize;
CELTState *st = celt_alloc(sizeof(CELTState));
st->frame_size = blockSize * blocksPerFrame;
st->block_size = blockSize;
st->nb_blocks = blocksPerFrame;
mdct_init(&st->mdct_lookup, 2*N);
st->window = celt_alloc(2*N*sizeof(float));
st->in_mem = celt_alloc(N*sizeof(float));
st->mdct_overlap = celt_alloc(N*sizeof(float));
st->out_mem = celt_alloc(MAX_PERIOD*sizeof(float));
for (i=0;i<N;i++)
st->window[i] = st->window[2*N-i-1] = sin(.5*M_PI* sin(.5*M_PI*(i+.5)/N) * sin(.5*M_PI*(i+.5)/N));
return st;
} }
void celt_encode(CELTState *st, short *pcm) void celt_encode(CELTState *st, short *pcm)
{ {
int i; int i, N, B;
int N = st->block_size; N = st->block_size;
float in[(st->nb_blocks+1)*N]; B = st->nb_blocks;
float X[st->nb_blocks*N]; float in[(B+1)*N];
float X[B*N];
/* FIXME: Add preemphasis */ /* FIXME: Add preemphasis */
for (i=0;i<N;i++) for (i=0;i<N;i++)
in[i] = st->in_mem[i]; in[i] = st->in_mem[i];
for (;i<st->nb_blocks*N;i++) for (;i<(B+1)*N;i++)
in[i] = pcm[i-N]; in[i] = pcm[i-N];
/* Compute MDCTs */ for (i=0;i<N;i++)
st->in_mem[i] = pcm[(B-1)*N+i];
/* Compute MDCTs */
for (i=0;i<B;i++)
{
int j;
float x[2*N];
for (j=0;j<2*N;j++)
x[j] = st->window[j]*in[i*N+j];
mdct_forward(&st->mdct_lookup, x, X+N*i);
}
/* Pitch analysis */ /* Pitch analysis */
/* Band normalisation */ /* Band normalisation */
@ -76,5 +111,24 @@ void celt_encode(CELTState *st, short *pcm)
/* Residual quantisation */ /* Residual quantisation */
/* Synthesis */ /* Synthesis */
CELT_MOVE(st->out_mem, st->out_mem+B*N, MAX_PERIOD-B*N);
/* Compute inverse MDCTs */
for (i=0;i<B;i++)
{
int j;
float x[2*N];
mdct_backward(&st->mdct_lookup, X+N*i, x);
for (j=0;j<2*N;j++)
x[j] = st->window[j]*x[j];
for (j=0;j<N;j++)
st->out_mem[MAX_PERIOD+(i-B)*N+j] = x[j]+st->mdct_overlap[j];
for (j=0;j<N;j++)
st->mdct_overlap[j] = x[N+j];
for (j=0;j<N;j++)
pcm[i*N+j] = st->out_mem[MAX_PERIOD+(i-B)*N+j];
}
} }

View file

@ -41,9 +41,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "vorbis/codec.h" /*#include "vorbis/codec.h"*/
#include "mdct.h" #include "mdct.h"
/*#include "os.h"*/ #include "os_support.h"
/*#include "misc.h"*/ /*#include "misc.h"*/
#define STIN static inline #define STIN static inline
@ -52,8 +52,8 @@
some window function algebra. */ some window function algebra. */
void mdct_init(mdct_lookup *lookup,int n){ void mdct_init(mdct_lookup *lookup,int n){
int *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4)); int *bitrev=celt_alloc(sizeof(*bitrev)*(n/4));
DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4)); DATA_TYPE *T=celt_alloc(sizeof(*T)*(n+n/4));
int i; int i;
int n2=n>>1; int n2=n>>1;
@ -340,8 +340,8 @@ STIN void mdct_butterflies(mdct_lookup *init,
void mdct_clear(mdct_lookup *l){ void mdct_clear(mdct_lookup *l){
if(l){ if(l){
if(l->trig)_ogg_free(l->trig); if(l->trig)celt_free(l->trig);
if(l->bitrev)_ogg_free(l->bitrev); if(l->bitrev)celt_free(l->bitrev);
memset(l,0,sizeof(*l)); memset(l,0,sizeof(*l));
} }
} }

View file

@ -18,7 +18,7 @@
#ifndef _OGG_mdct_H_ #ifndef _OGG_mdct_H_
#define _OGG_mdct_H_ #define _OGG_mdct_H_
#include "vorbis/codec.h" /*#include "vorbis/codec.h"*/

View file

@ -38,10 +38,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_free /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, celt_realloc and celt_free
NOTE: speex_alloc needs to CLEAR THE MEMORY */ NOTE: celt_alloc needs to CLEAR THE MEMORY */
#ifndef OVERRIDE_SPEEX_ALLOC #ifndef OVERRIDE_CELT_ALLOC
static inline void *speex_alloc (int size) static inline void *celt_alloc (int size)
{ {
/* WARNING: this is not equivalent to malloc(). If you want to use malloc() /* WARNING: this is not equivalent to malloc(). If you want to use malloc()
or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
@ -50,66 +50,66 @@ static inline void *speex_alloc (int size)
} }
#endif #endif
/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ /** Same as celt_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH #ifndef OVERRIDE_CELT_ALLOC_SCRATCH
static inline void *speex_alloc_scratch (int size) static inline void *celt_alloc_scratch (int size)
{ {
/* Scratch space doesn't need to be cleared */ /* Scratch space doesn't need to be cleared */
return calloc(size,1); return calloc(size,1);
} }
#endif #endif
/** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, speex_alloc and speex_free */ /** Speex wrapper for realloc. To do your own dynamic allocation, all you need to do is replace this function, celt_alloc and celt_free */
#ifndef OVERRIDE_SPEEX_REALLOC #ifndef OVERRIDE_CELT_REALLOC
static inline void *speex_realloc (void *ptr, int size) static inline void *celt_realloc (void *ptr, int size)
{ {
return realloc(ptr, size); return realloc(ptr, size);
} }
#endif #endif
/** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, speex_realloc and speex_alloc */ /** Speex wrapper for calloc. To do your own dynamic allocation, all you need to do is replace this function, celt_realloc and celt_alloc */
#ifndef OVERRIDE_SPEEX_FREE #ifndef OVERRIDE_CELT_FREE
static inline void speex_free (void *ptr) static inline void celt_free (void *ptr)
{ {
free(ptr); free(ptr);
} }
#endif #endif
/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ /** Same as celt_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */
#ifndef OVERRIDE_SPEEX_FREE_SCRATCH #ifndef OVERRIDE_CELT_FREE_SCRATCH
static inline void speex_free_scratch (void *ptr) static inline void celt_free_scratch (void *ptr)
{ {
free(ptr); free(ptr);
} }
#endif #endif
/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */ /** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_SPEEX_COPY #ifndef OVERRIDE_CELT_COPY
#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #define CELT_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif #endif
/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term /** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term
provides compile-time type checking */ provides compile-time type checking */
#ifndef OVERRIDE_SPEEX_MOVE #ifndef OVERRIDE_CELT_MOVE
#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #define CELT_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif #endif
/** Set n bytes of memory to value of c, starting at address s */ /** Set n bytes of memory to value of c, starting at address s */
#ifndef OVERRIDE_SPEEX_MEMSET #ifndef OVERRIDE_CELT_MEMSET
#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) #define CELT_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst))))
#endif #endif
#ifndef OVERRIDE_SPEEX_FATAL #ifndef OVERRIDE_CELT_FATAL
static inline void _speex_fatal(const char *str, const char *file, int line) static inline void _celt_fatal(const char *str, const char *file, int line)
{ {
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str); fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
exit(1); exit(1);
} }
#endif #endif
#ifndef OVERRIDE_SPEEX_WARNING #ifndef OVERRIDE_CELT_WARNING
static inline void speex_warning(const char *str) static inline void celt_warning(const char *str)
{ {
#ifndef DISABLE_WARNINGS #ifndef DISABLE_WARNINGS
fprintf (stderr, "warning: %s\n", str); fprintf (stderr, "warning: %s\n", str);
@ -117,8 +117,8 @@ static inline void speex_warning(const char *str)
} }
#endif #endif
#ifndef OVERRIDE_SPEEX_WARNING_INT #ifndef OVERRIDE_CELT_WARNING_INT
static inline void speex_warning_int(const char *str, int val) static inline void celt_warning_int(const char *str, int val)
{ {
#ifndef DISABLE_WARNINGS #ifndef DISABLE_WARNINGS
fprintf (stderr, "warning: %s %d\n", str, val); fprintf (stderr, "warning: %s %d\n", str, val);
@ -126,8 +126,8 @@ static inline void speex_warning_int(const char *str, int val)
} }
#endif #endif
#ifndef OVERRIDE_SPEEX_NOTIFY #ifndef OVERRIDE_CELT_NOTIFY
static inline void speex_notify(const char *str) static inline void celt_notify(const char *str)
{ {
#ifndef DISABLE_NOTIFICATIONS #ifndef DISABLE_NOTIFICATIONS
fprintf (stderr, "notification: %s\n", str); fprintf (stderr, "notification: %s\n", str);
@ -135,17 +135,17 @@ static inline void speex_notify(const char *str)
} }
#endif #endif
#ifndef OVERRIDE_SPEEX_PUTC #ifndef OVERRIDE_CELT_PUTC
/** Speex wrapper for putc */ /** Speex wrapper for putc */
static inline void _speex_putc(int ch, void *file) static inline void _celt_putc(int ch, void *file)
{ {
FILE *f = (FILE *)file; FILE *f = (FILE *)file;
fprintf(f, "%c", ch); fprintf(f, "%c", ch);
} }
#endif #endif
#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__); #define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}} #define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}}
#ifndef RELEASE #ifndef RELEASE
static inline void print_vec(float *vec, int len, char *name) static inline void print_vec(float *vec, int len, char *name)