From f02ba11950b3cf54dea27d4004afae3f0c89b3be Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jean-marc.valin@usherbrooke.ca> Date: Fri, 30 Nov 2007 01:10:42 +1100 Subject: [PATCH] MDCT analysis-synthesis (untested) --- celt.kdevelop | 103 ++++++++++++++++++++++++++++++++++++++++++- libcelt/celt.c | 66 ++++++++++++++++++++++++--- libcelt/mdct.c | 12 ++--- libcelt/mdct.h | 2 +- libcelt/os_support.h | 68 ++++++++++++++-------------- 5 files changed, 202 insertions(+), 49 deletions(-) diff --git a/celt.kdevelop b/celt.kdevelop index ab27c560c..c4e915317 100644 --- a/celt.kdevelop +++ b/celt.kdevelop @@ -8,12 +8,27 @@ <primarylanguage>C</primarylanguage> <ignoreparts/> <projectname>celt</projectname> + <projectdirectory>.</projectdirectory> + <absoluteprojectpath>false</absoluteprojectpath> + <description/> + <defaultencoding/> </general> <kdevautoproject> <general> - <useconfiguration>debug</useconfiguration> + <useconfiguration>default</useconfiguration> </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> <optimized> <builddir>optimized</builddir> @@ -31,11 +46,30 @@ <cflags>-O0 -g3</cflags> </debug> </configurations> + <make> + <envvars> + <envvar value="1" name="WANT_AUTOCONF_2_5" /> + <envvar value="1" name="WANT_AUTOMAKE_1_6" /> + </envvars> + </make> </kdevautoproject> <kdevdebugger> <general> <dbgshell>libtool</dbgshell> + <gdbpath/> + <configGdbScript/> + <runShellScript/> + <runGdbScript/> + <breakonloadinglibs>true</breakonloadinglibs> + <separatetty>false</separatetty> + <floatingtoolbar>false</floatingtoolbar> + <raiseGDBOnStart>false</raiseGDBOnStart> </general> + <display> + <staticmembers>false</staticmembers> + <demanglenames>true</demanglenames> + <outputradix>10</outputradix> + </display> </kdevdebugger> <kdevdoctreeview> <ignoretocs> @@ -92,4 +126,69 @@ <type ext="h" /> </useglobaltypes> </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> diff --git a/libcelt/celt.c b/libcelt/celt.c index 4ba388780..20c6e1705 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -30,6 +30,10 @@ */ #include "os_support.h" +#include "mdct.h" +#include <math.h> + +#define MAX_PERIOD 2048 struct CELTState_ { int frame_size; @@ -39,6 +43,8 @@ struct CELTState_ { float preemph; float preemph_mem; + mdct_lookup mdct_lookup; + float *window; float *in_mem; float *mdct_overlap; @@ -49,24 +55,53 @@ typedef struct CELTState_ CELTState; 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) { - int i; - int N = st->block_size; - float in[(st->nb_blocks+1)*N]; - float X[st->nb_blocks*N]; + int i, N, B; + N = st->block_size; + B = st->nb_blocks; + float in[(B+1)*N]; + float X[B*N]; /* FIXME: Add preemphasis */ for (i=0;i<N;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]; - /* 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 */ /* Band normalisation */ @@ -76,5 +111,24 @@ void celt_encode(CELTState *st, short *pcm) /* Residual quantisation */ /* 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]; + } + } diff --git a/libcelt/mdct.c b/libcelt/mdct.c index ae83ed438..12e9a0fab 100644 --- a/libcelt/mdct.c +++ b/libcelt/mdct.c @@ -41,9 +41,9 @@ #include <stdlib.h> #include <string.h> #include <math.h> -#include "vorbis/codec.h" +/*#include "vorbis/codec.h"*/ #include "mdct.h" -/*#include "os.h"*/ +#include "os_support.h" /*#include "misc.h"*/ #define STIN static inline @@ -52,8 +52,8 @@ some window function algebra. */ void mdct_init(mdct_lookup *lookup,int n){ - int *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4)); - DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4)); + int *bitrev=celt_alloc(sizeof(*bitrev)*(n/4)); + DATA_TYPE *T=celt_alloc(sizeof(*T)*(n+n/4)); int i; int n2=n>>1; @@ -340,8 +340,8 @@ STIN void mdct_butterflies(mdct_lookup *init, void mdct_clear(mdct_lookup *l){ if(l){ - if(l->trig)_ogg_free(l->trig); - if(l->bitrev)_ogg_free(l->bitrev); + if(l->trig)celt_free(l->trig); + if(l->bitrev)celt_free(l->bitrev); memset(l,0,sizeof(*l)); } } diff --git a/libcelt/mdct.h b/libcelt/mdct.h index 176daad85..b91dc4371 100644 --- a/libcelt/mdct.h +++ b/libcelt/mdct.h @@ -18,7 +18,7 @@ #ifndef _OGG_mdct_H_ #define _OGG_mdct_H_ -#include "vorbis/codec.h" +/*#include "vorbis/codec.h"*/ diff --git a/libcelt/os_support.h b/libcelt/os_support.h index d2f9eb843..ad06b95b3 100644 --- a/libcelt/os_support.h +++ b/libcelt/os_support.h @@ -38,10 +38,10 @@ #include <stdio.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 - NOTE: speex_alloc needs to CLEAR THE MEMORY */ -#ifndef OVERRIDE_SPEEX_ALLOC -static inline void *speex_alloc (int size) +/** 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: celt_alloc needs to CLEAR THE MEMORY */ +#ifndef OVERRIDE_CELT_ALLOC +static inline void *celt_alloc (int size) { /* 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 @@ -50,66 +50,66 @@ static inline void *speex_alloc (int size) } #endif -/** Same as speex_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ -#ifndef OVERRIDE_SPEEX_ALLOC_SCRATCH -static inline void *speex_alloc_scratch (int size) +/** Same as celt_alloc, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ +#ifndef OVERRIDE_CELT_ALLOC_SCRATCH +static inline void *celt_alloc_scratch (int size) { /* Scratch space doesn't need to be cleared */ return calloc(size,1); } #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 */ -#ifndef OVERRIDE_SPEEX_REALLOC -static inline void *speex_realloc (void *ptr, int size) +/** 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_CELT_REALLOC +static inline void *celt_realloc (void *ptr, int size) { return realloc(ptr, size); } #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 */ -#ifndef OVERRIDE_SPEEX_FREE -static inline void speex_free (void *ptr) +/** 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_CELT_FREE +static inline void celt_free (void *ptr) { free(ptr); } #endif -/** Same as speex_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ -#ifndef OVERRIDE_SPEEX_FREE_SCRATCH -static inline void speex_free_scratch (void *ptr) +/** Same as celt_free, except that the area is only needed inside a Speex call (might cause problem with wideband though) */ +#ifndef OVERRIDE_CELT_FREE_SCRATCH +static inline void celt_free_scratch (void *ptr) { free(ptr); } #endif /** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */ -#ifndef OVERRIDE_SPEEX_COPY -#define SPEEX_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#ifndef OVERRIDE_CELT_COPY +#define CELT_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #endif /** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term provides compile-time type checking */ -#ifndef OVERRIDE_SPEEX_MOVE -#define SPEEX_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) +#ifndef OVERRIDE_CELT_MOVE +#define CELT_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #endif /** Set n bytes of memory to value of c, starting at address s */ -#ifndef OVERRIDE_SPEEX_MEMSET -#define SPEEX_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) +#ifndef OVERRIDE_CELT_MEMSET +#define CELT_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst)))) #endif -#ifndef OVERRIDE_SPEEX_FATAL -static inline void _speex_fatal(const char *str, const char *file, int line) +#ifndef OVERRIDE_CELT_FATAL +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); exit(1); } #endif -#ifndef OVERRIDE_SPEEX_WARNING -static inline void speex_warning(const char *str) +#ifndef OVERRIDE_CELT_WARNING +static inline void celt_warning(const char *str) { #ifndef DISABLE_WARNINGS fprintf (stderr, "warning: %s\n", str); @@ -117,8 +117,8 @@ static inline void speex_warning(const char *str) } #endif -#ifndef OVERRIDE_SPEEX_WARNING_INT -static inline void speex_warning_int(const char *str, int val) +#ifndef OVERRIDE_CELT_WARNING_INT +static inline void celt_warning_int(const char *str, int val) { #ifndef DISABLE_WARNINGS fprintf (stderr, "warning: %s %d\n", str, val); @@ -126,8 +126,8 @@ static inline void speex_warning_int(const char *str, int val) } #endif -#ifndef OVERRIDE_SPEEX_NOTIFY -static inline void speex_notify(const char *str) +#ifndef OVERRIDE_CELT_NOTIFY +static inline void celt_notify(const char *str) { #ifndef DISABLE_NOTIFICATIONS fprintf (stderr, "notification: %s\n", str); @@ -135,17 +135,17 @@ static inline void speex_notify(const char *str) } #endif -#ifndef OVERRIDE_SPEEX_PUTC +#ifndef OVERRIDE_CELT_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; fprintf(f, "%c", ch); } #endif -#define speex_fatal(str) _speex_fatal(str, __FILE__, __LINE__); -#define speex_assert(cond) {if (!(cond)) {speex_fatal("assertion failed: " #cond);}} +#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); +#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}} #ifndef RELEASE static inline void print_vec(float *vec, int len, char *name) -- GitLab