celt.c 41.3 KB
Newer Older
Jean-Marc Valin's avatar
Jean-Marc Valin committed
1
2
3
4
/* Copyright (c) 2007-2008 CSIRO
   Copyright (c) 2007-2009 Xiph.Org Foundation
   Copyright (c) 2008 Gregory Maxwell 
   Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valin's avatar
Jean-Marc Valin committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
   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.
*/

34
35
36
37
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

38
39
#define CELT_C

Jean-Marc Valin's avatar
Jean-Marc Valin committed
40
#include "os_support.h"
41
42
#include "mdct.h"
#include <math.h>
43
#include "celt.h"
44
#include "pitch.h"
45
#include "kiss_fftr.h"
46
#include "bands.h"
47
#include "modes.h"
48
#include "entcode.h"
49
#include "quant_bands.h"
50
#include "psy.h"
Jean-Marc Valin's avatar
Jean-Marc Valin committed
51
#include "rate.h"
52
#include "stack_alloc.h"
53
#include "mathops.h"
54
#include "float_cast.h"
55
#include <stdarg.h>
56

57
58
static const celt_word16_t preemph = QCONST16(0.8f,15);

59
60
61
62
63
64
#ifdef FIXED_POINT
static const celt_word16_t transientWindow[16] = {
     279,  1106,  2454,  4276,  6510,  9081, 11900, 14872,
   17896, 20868, 23687, 26258, 28492, 30314, 31662, 32489};
#else
static const float transientWindow[16] = {
65
66
67
68
   0.0085135, 0.0337639, 0.0748914, 0.1304955, 
   0.1986827, 0.2771308, 0.3631685, 0.4538658,
   0.5461342, 0.6368315, 0.7228692, 0.8013173, 
   0.8695045, 0.9251086, 0.9662361, 0.9914865};
69
70
#endif

71
72
73
#define ENCODERVALID   0x4c434554
#define ENCODERPARTIAL 0x5445434c
#define ENCODERFREED   0x4c004500
74
   
Jean-Marc Valin's avatar
Jean-Marc Valin committed
75
76
77
/** Encoder state 
 @brief Encoder state
 */
78
struct CELTEncoder {
79
   celt_uint32 marker;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
80
   const CELTMode *mode;     /**< Mode used by the encoder */
Jean-Marc Valin's avatar
Jean-Marc Valin committed
81
82
   int frame_size;
   int block_size;
83
   int overlap;
84
85
   int channels;
   
86
87
88
89
   int pitch_enabled;       /* Complexity level is allowed to use pitch */
   int pitch_permitted;     /*  Use of the LTP is permitted by the user */
   int pitch_available;     /*  Amount of pitch buffer available */
   int force_intra;
90
   int delayedIntra;
91
92
   celt_word16_t tonal_average;
   int fold_decision;
93
   celt_word16_t gain_prod;
94

95
   int VBR_rate; /* Target number of 16th bits per frame */
96
   celt_word16_t * restrict preemph_memE; 
97
   celt_sig_t    * restrict preemph_memD;
98

99
100
   celt_sig_t *in_mem;
   celt_sig_t *out_mem;
101

102
   celt_word16_t *oldBandE;
103
104
105
106
#ifdef EXP_PSY
   celt_word16_t *psy_mem;
   struct PsyDecay psy;
#endif
Jean-Marc Valin's avatar
Jean-Marc Valin committed
107
108
};

109
static int check_encoder(const CELTEncoder *st) 
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
{
   if (st==NULL)
   {
      celt_warning("NULL passed as an encoder structure");  
      return CELT_INVALID_STATE;
   }
   if (st->marker == ENCODERVALID)
      return CELT_OK;
   if (st->marker == ENCODERFREED)
      celt_warning("Referencing an encoder that has already been freed");
   else
      celt_warning("This is not a valid CELT encoder structure");
   return CELT_INVALID_STATE;
}

125
CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
126
{
127
   int N, C;
128
   CELTEncoder *st;
129
130

   if (check_mode(mode) != CELT_OK)
131
132
133
   {
      if (error)
         *error = CELT_INVALID_MODE;
134
      return NULL;
135
   }
136
137
138
139
140
141
142
   if (channels < 0 || channels > 2)
   {
      celt_warning("Only mono and stereo supported");
      if (error)
         *error = CELT_BAD_ARG;
      return NULL;
   }
143

144
   N = mode->mdctSize;
145
   C = channels;
146
   st = celt_alloc(sizeof(CELTEncoder));
147
   
148
149
150
151
   if (st==NULL)
   {
      if (error)
         *error = CELT_ALLOC_FAIL;
152
      return NULL;
153
   }
154
   st->marker = ENCODERPARTIAL;
155
   st->mode = mode;
156
   st->frame_size = N;
157
   st->block_size = N;
158
   st->overlap = mode->overlap;
159
   st->channels = channels;
160

161
   st->VBR_rate = 0;
162
   st->pitch_enabled = 1;
163
   st->pitch_permitted = 1;
164
   st->pitch_available = 1;
165
   st->force_intra  = 0;
166
   st->delayedIntra = 1;
167
168
   st->tonal_average = QCONST16(1.,8);
   st->fold_decision = 1;
169

170
   st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
171
   st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
172

173
   st->oldBandE = (celt_word16_t*)celt_alloc(C*mode->nbEBands*sizeof(celt_word16_t));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
174

175
176
   st->preemph_memE = (celt_word16_t*)celt_alloc(C*sizeof(celt_word16_t));
   st->preemph_memD = (celt_sig_t*)celt_alloc(C*sizeof(celt_sig_t));
177

178
179
180
181
182
#ifdef EXP_PSY
   st->psy_mem = celt_alloc(MAX_PERIOD*sizeof(celt_word16_t));
   psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
#endif

183
184
185
186
187
188
   if ((st->in_mem!=NULL) && (st->out_mem!=NULL) && (st->oldBandE!=NULL) 
#ifdef EXP_PSY
       && (st->psy_mem!=NULL) 
#endif   
       && (st->preemph_memE!=NULL) && (st->preemph_memD!=NULL))
   {
189
190
      if (error)
         *error = CELT_OK;
191
192
193
194
195
      st->marker   = ENCODERVALID;
      return st;
   }
   /* If the setup fails for some reason deallocate it. */
   celt_encoder_destroy(st);  
196
197
   if (error)
      *error = CELT_ALLOC_FAIL;
198
   return NULL;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
199
200
}

201
void celt_encoder_destroy(CELTEncoder *st)
202
203
204
205
206
207
{
   if (st == NULL)
   {
      celt_warning("NULL passed to celt_encoder_destroy");
      return;
   }
208
209
210
211

   if (st->marker == ENCODERFREED)
   {
      celt_warning("Freeing an encoder which has already been freed"); 
212
      return;
213
   }
214

215
216
217
218
219
220
221
222
223
224
   if (st->marker != ENCODERVALID && st->marker != ENCODERPARTIAL)
   {
      celt_warning("This is not a valid CELT encoder structure");
      return;
   }
   /*Check_mode is non-fatal here because we can still free
    the encoder memory even if the mode is bad, although calling
    the free functions in this order is a violation of the API.*/
   check_mode(st->mode);
   
225
226
   celt_free(st->in_mem);
   celt_free(st->out_mem);
227
   
Jean-Marc Valin's avatar
Jean-Marc Valin committed
228
   celt_free(st->oldBandE);
229
230
231
232
   
   celt_free(st->preemph_memE);
   celt_free(st->preemph_memD);
   
233
234
235
236
#ifdef EXP_PSY
   celt_free (st->psy_mem);
   psydecay_clear(&st->psy);
#endif
237
   st->marker = ENCODERFREED;
238
   
239
240
241
   celt_free(st);
}

242
static inline celt_int16 FLOAT2INT16(float x)
243
{
244
   x = x*CELT_SIG_SCALE;
245
246
   x = MAX32(x, -32768);
   x = MIN32(x, 32767);
247
   return (celt_int16)float2int(x);
248
249
250
251
}

static inline celt_word16_t SIG2WORD16(celt_sig_t x)
{
252
#ifdef FIXED_POINT
253
254
255
   x = PSHR32(x, SIG_SHIFT);
   x = MAX32(x, -32768);
   x = MIN32(x, 32767);
256
257
   return EXTRACT16(x);
#else
258
   return (celt_word16_t)x;
259
260
261
#endif
}

262
static int transient_analysis(celt_word32_t *in, int len, int C, int *transient_time, int *transient_shift)
263
264
{
   int c, i, n;
265
266
267
268
   celt_word32_t ratio;
   VARDECL(celt_word32_t, begin);
   SAVE_STACK;
   ALLOC(begin, len, celt_word32_t);
269
   for (i=0;i<len;i++)
270
      begin[i] = ABS32(SHR32(in[C*i],SIG_SHIFT));
271
272
273
   for (c=1;c<C;c++)
   {
      for (i=0;i<len;i++)
274
         begin[i] = MAX32(begin[i], ABS32(SHR32(in[C*i+c],SIG_SHIFT)));
275
276
   }
   for (i=1;i<len;i++)
277
      begin[i] = MAX32(begin[i-1],begin[i]);
278
279
280
   n = -1;
   for (i=8;i<len-8;i++)
   {
281
282
      if (begin[i] < MULT16_32_Q15(QCONST16(.2f,15),begin[len-1]))
         n=i;
283
284
285
286
287
   }
   if (n<32)
   {
      n = -1;
      ratio = 0;
288
289
   } else {
      ratio = DIV32(begin[len-1],1+begin[n-16]);
290
   }
291
292
293
294
   if (ratio < 0)
      ratio = 0;
   if (ratio > 1000)
      ratio = 1000;
295
   ratio *= ratio;
296
297
   
   if (ratio > 2048)
298
      *transient_shift = 3;
299
300
301
   else
      *transient_shift = 0;
   
302
303
   *transient_time = n;
   
304
   RESTORE_STACK;
305
   return ratio > 20;
306
307
}

308
309
/** Apply window and compute the MDCT for all sub-frames and 
    all channels in a frame */
310
static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t * restrict in, celt_sig_t * restrict out, int _C)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
311
{
312
   const int C = CHANNELS(_C);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
313
   if (C==1 && !shortBlocks)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
314
   {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
315
316
317
      const mdct_lookup *lookup = MDCT(mode);
      const int overlap = OVERLAP(mode);
      mdct_forward(lookup, in, out, mode->window, overlap);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
318
   } else {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
319
320
      const mdct_lookup *lookup = MDCT(mode);
      const int overlap = OVERLAP(mode);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
321
322
323
      int N = FRAMESIZE(mode);
      int B = 1;
      int b, c;
324
325
326
      VARDECL(celt_word32_t, x);
      VARDECL(celt_word32_t, tmp);
      SAVE_STACK;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
327
      if (shortBlocks)
328
      {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
329
330
331
         lookup = &mode->shortMdct;
         N = mode->shortMdctSize;
         B = mode->nbShortMdcts;
332
      }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
333
334
335
336
337
338
339
340
341
342
343
344
      ALLOC(x, N+overlap, celt_word32_t);
      ALLOC(tmp, N, celt_word32_t);
      for (c=0;c<C;c++)
      {
         for (b=0;b<B;b++)
         {
            int j;
            for (j=0;j<N+overlap;j++)
               x[j] = in[C*(b*N+j)+c];
            mdct_forward(lookup, x, tmp, mode->window, overlap);
            /* Interleaving the sub-frames */
            for (j=0;j<N;j++)
345
               out[(j*B+b)+c*N*B] = tmp[j];
Jean-Marc Valin's avatar
Jean-Marc Valin committed
346
347
348
         }
      }
      RESTORE_STACK;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
349
350
351
   }
}

352
353
/** Compute the IMDCT and apply window for all sub-frames and 
    all channels in a frame */
354
static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem, int _C)
355
{
356
   int c, N4;
357
   const int C = CHANNELS(_C);
358
359
   const int N = FRAMESIZE(mode);
   const int overlap = OVERLAP(mode);
360
   N4 = (N-overlap)>>1;
361
   for (c=0;c<C;c++)
362
   {
363
      int j;
364
      if (transient_shift==0 && C==1 && !shortBlocks) {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
365
366
367
368
369
         const mdct_lookup *lookup = MDCT(mode);
         mdct_backward(lookup, X, out_mem+C*(MAX_PERIOD-N-N4), mode->window, overlap);
      } else {
         VARDECL(celt_word32_t, x);
         VARDECL(celt_word32_t, tmp);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
370
371
372
373
374
         int b;
         int N2 = N;
         int B = 1;
         int n4offset=0;
         const mdct_lookup *lookup = MDCT(mode);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
375
         SAVE_STACK;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
376
         
Jean-Marc Valin's avatar
Jean-Marc Valin committed
377
378
         ALLOC(x, 2*N, celt_word32_t);
         ALLOC(tmp, N, celt_word32_t);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
379
380
381
382
383
384
385
386

         if (shortBlocks)
         {
            lookup = &mode->shortMdct;
            N2 = mode->shortMdctSize;
            B = mode->nbShortMdcts;
            n4offset = N4;
         }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
387
         /* Prevents problems from the imdct doing the overlap-add */
388
         CELT_MEMSET(x+N4, 0, N2);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
389

Jean-Marc Valin's avatar
Jean-Marc Valin committed
390
391
392
393
         for (b=0;b<B;b++)
         {
            /* De-interleaving the sub-frames */
            for (j=0;j<N2;j++)
394
               tmp[j] = X[(j*B+b)+c*N2*B];
Jean-Marc Valin's avatar
Jean-Marc Valin committed
395
            mdct_backward(lookup, tmp, x+n4offset+N2*b, mode->window, overlap);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
396
         }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
397

398
         if (transient_shift > 0)
399
         {
400
401
402
403
404
405
#ifdef FIXED_POINT
            for (j=0;j<16;j++)
               x[N4+transient_time+j-16] = MULT16_32_Q15(SHR16(Q15_ONE-transientWindow[j],transient_shift)+transientWindow[j], SHL32(x[N4+transient_time+j-16],transient_shift));
            for (j=transient_time;j<N+overlap;j++)
               x[N4+j] = SHL32(x[N4+j], transient_shift);
#else
406
            for (j=0;j<16;j++)
407
               x[N4+transient_time+j-16] *= 1+transientWindow[j]*((1<<transient_shift)-1);
408
            for (j=transient_time;j<N+overlap;j++)
409
410
               x[N4+j] *= 1<<transient_shift;
#endif
411
         }
412
413
         /* The first and last part would need to be set to zero 
            if we actually wanted to use them. */
414
415
416
417
418
419
420
421
         for (j=0;j<overlap;j++)
            out_mem[C*(MAX_PERIOD-N)+C*j+c] += x[j+N4];
         for (j=0;j<overlap;j++)
            out_mem[C*(MAX_PERIOD)+C*(overlap-j-1)+c] = x[2*N-j-N4-1];
         for (j=0;j<2*N4;j++)
            out_mem[C*(MAX_PERIOD-N)+C*(j+overlap)+c] = x[j+N4+overlap];
         RESTORE_STACK;
      }
422
423
424
   }
}

425
#define FLAG_NONE        0
Jean-Marc Valin's avatar
Jean-Marc Valin committed
426
427
428
429
#define FLAG_INTRA       (1U<<13)
#define FLAG_PITCH       (1U<<12)
#define FLAG_SHORT       (1U<<11)
#define FLAG_FOLD        (1U<<10)
430
431
#define FLAG_MASK        (FLAG_INTRA|FLAG_PITCH|FLAG_SHORT|FLAG_FOLD)

432
static const int flaglist[8] = {
433
434
435
436
437
438
439
440
      0 /*00  */ | FLAG_FOLD,
      1 /*01  */ | FLAG_PITCH|FLAG_FOLD,
      8 /*1000*/ | FLAG_NONE,
      9 /*1001*/ | FLAG_SHORT|FLAG_FOLD,
     10 /*1010*/ | FLAG_PITCH,
     11 /*1011*/ | FLAG_INTRA,
      6 /*110 */ | FLAG_INTRA|FLAG_FOLD,
      7 /*111 */ | FLAG_INTRA|FLAG_SHORT|FLAG_FOLD
441
442
};

443
static void encode_flags(ec_enc *enc, int intra_ener, int has_pitch, int shortBlocks, int has_fold)
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
{
   int i;
   int flags=FLAG_NONE;
   int flag_bits;
   flags |= intra_ener   ? FLAG_INTRA : 0;
   flags |= has_pitch    ? FLAG_PITCH : 0;
   flags |= shortBlocks  ? FLAG_SHORT : 0;
   flags |= has_fold     ? FLAG_FOLD  : 0;
   for (i=0;i<8;i++)
      if (flags == (flaglist[i]&FLAG_MASK))
         break;
   celt_assert(i<8);
   flag_bits = flaglist[i]&0xf;
   /*printf ("enc %d: %d %d %d %d\n", flag_bits, intra_ener, has_pitch, shortBlocks, has_fold);*/
   if (i<2)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
459
      ec_enc_uint(enc, flag_bits, 4);
460
   else if (i<6)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
461
      ec_enc_uint(enc, flag_bits, 16);
462
   else
Jean-Marc Valin's avatar
Jean-Marc Valin committed
463
      ec_enc_uint(enc, flag_bits, 8);
464
465
}

466
static void decode_flags(ec_dec *dec, int *intra_ener, int *has_pitch, int *shortBlocks, int *has_fold)
467
468
469
{
   int i;
   int flag_bits;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
470
   flag_bits = ec_dec_uint(dec, 4);
471
472
   /*printf ("(%d) ", flag_bits);*/
   if (flag_bits==2)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
473
      flag_bits = (flag_bits<<2) | ec_dec_uint(dec, 4);
474
   else if (flag_bits==3)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
475
      flag_bits = (flag_bits<<1) | ec_dec_uint(dec, 2);
476
477
478
479
480
481
482
483
484
485
486
   for (i=0;i<8;i++)
      if (flag_bits == (flaglist[i]&0xf))
         break;
   celt_assert(i<8);
   *intra_ener  = (flaglist[i]&FLAG_INTRA) != 0;
   *has_pitch   = (flaglist[i]&FLAG_PITCH) != 0;
   *shortBlocks = (flaglist[i]&FLAG_SHORT) != 0;
   *has_fold    = (flaglist[i]&FLAG_FOLD ) != 0;
   /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
}

487
static void deemphasis(celt_sig_t *in, celt_word16_t *pcm, int N, int _C, celt_word16_t coef, celt_sig_t *mem)
488
{
489
   const int C = CHANNELS(_C);
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
   int c;
   for (c=0;c<C;c++)
   {
      int j;
      for (j=0;j<N;j++)
      {
         celt_sig_t tmp = MAC16_32_Q15(in[C*(MAX_PERIOD-N)+C*j+c],
                                       coef,mem[c]);
         mem[c] = tmp;
         pcm[C*j+c] = SCALEOUT(SIG2WORD16(tmp));
      }
   }

}

505
static void mdct_shape(const CELTMode *mode, celt_norm_t *X, int start, int end, int N, int nbShortMdcts, int mdct_weight_shift, int _C)
506
507
{
   int m, i, c;
508
   const int C = CHANNELS(_C);
509
510
511
512
513
514
515
516
   for (c=0;c<C;c++)
      for (m=start;m<end;m++)
         for (i=m+c*N;i<(c+1)*N;i+=nbShortMdcts)
#ifdef FIXED_POINT
            X[i] = SHR16(X[i], mdct_weight_shift);
#else
            X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
#endif
517
   renormalise_bands(mode, X, C);
518
519
520
}


521
#ifdef FIXED_POINT
522
int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
523
{
524
#else
525
int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_sig_t * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
526
527
{
#endif
528
   int i, c, N, NN, N4;
529
   int has_pitch;
530
   int pitch_index;
531
   int bits;
532
   int has_fold=1;
533
   unsigned coarse_needed;
534
535
   ec_byte_buffer buf;
   ec_enc         enc;
536
537
   VARDECL(celt_sig_t, in);
   VARDECL(celt_sig_t, freq);
538
   VARDECL(celt_sig_t, pitch_freq);
539
540
   VARDECL(celt_norm_t, X);
   VARDECL(celt_ener_t, bandE);
541
   VARDECL(celt_word16_t, bandLogE);
542
   VARDECL(int, fine_quant);
543
   VARDECL(celt_word16_t, error);
544
545
   VARDECL(int, pulses);
   VARDECL(int, offsets);
546
   VARDECL(int, fine_priority);
547
   int intra_ener = 0;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
548
   int shortBlocks=0;
549
   int transient_time;
550
   int transient_shift;
551
   const int C = CHANNELS(st->channels);
552
553
   int mdct_weight_shift = 0;
   int mdct_weight_pos=0;
554
   int gain_id=0;
555
   int norm_rate;
556
   SAVE_STACK;
557

558
559
560
   if (check_encoder(st) != CELT_OK)
      return CELT_INVALID_STATE;

561
562
563
   if (check_mode(st->mode) != CELT_OK)
      return CELT_INVALID_MODE;

564
   if (nbCompressedBytes<0 || pcm==NULL)
565
566
     return CELT_BAD_ARG; 

567
568
   /* The memset is important for now in case the encoder doesn't 
      fill up all the bytes */
569
570
571
572
   CELT_MEMSET(compressed, 0, nbCompressedBytes);
   ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
   ec_enc_init(&enc,&buf);

573
   N = st->block_size;
574
   N4 = (N-st->overlap)>>1;
575
   ALLOC(in, 2*C*N-2*C*N4, celt_sig_t);
576

577
   CELT_COPY(in, st->in_mem, C*st->overlap);
578
   for (c=0;c<C;c++)
579
   {
580
      const celt_word16_t * restrict pcmp = pcm+c;
581
      celt_sig_t * restrict inp = in+C*st->overlap+c;
582
      for (i=0;i<N;i++)
583
      {
584
         /* Apply pre-emphasis */
585
         celt_sig_t tmp = SCALEIN(SHL32(EXTEND32(*pcmp), SIG_SHIFT));
586
         *inp = SUB32(tmp, SHR32(MULT16_16(preemph,st->preemph_memE[c]),3));
587
         st->preemph_memE[c] = SCALEIN(*pcmp);
588
589
         inp += C;
         pcmp += C;
590
      }
591
   }
592
   CELT_COPY(st->in_mem, in+C*(2*N-2*N4-st->overlap), C*st->overlap);
593

594
   /* Transient handling */
595
596
597
598
599
   transient_time = -1;
   transient_shift = 0;
   shortBlocks = 0;

   if (st->mode->nbShortMdcts > 1 && transient_analysis(in, N+st->overlap, C, &transient_time, &transient_shift))
600
   {
601
#ifndef FIXED_POINT
602
      float gain_1;
603
#endif
604
605
606
      /* Apply the inverse shaping window */
      if (transient_shift)
      {
607
#ifdef FIXED_POINT
608
609
610
611
612
613
         for (c=0;c<C;c++)
            for (i=0;i<16;i++)
               in[C*(transient_time+i-16)+c] = MULT16_32_Q15(EXTRACT16(SHR32(celt_rcp(Q15ONE+MULT16_16(transientWindow[i],((1<<transient_shift)-1))),1)), in[C*(transient_time+i-16)+c]);
         for (c=0;c<C;c++)
            for (i=transient_time;i<N+st->overlap;i++)
               in[C*i+c] = SHR32(in[C*i+c], transient_shift);
614
#else
615
616
617
618
619
620
621
         for (c=0;c<C;c++)
            for (i=0;i<16;i++)
               in[C*(transient_time+i-16)+c] /= 1+transientWindow[i]*((1<<transient_shift)-1);
         gain_1 = 1./(1<<transient_shift);
         for (c=0;c<C;c++)
            for (i=transient_time;i<N+st->overlap;i++)
               in[C*i+c] *= gain_1;
622
#endif
623
      }
624
625
      shortBlocks = 1;
      has_fold = 1;
626
   }
627

628
629
   ALLOC(freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
   ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
630
   ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16_t);
631
   /* Compute MDCTs */
632
   compute_mdcts(st->mode, shortBlocks, in, freq, C);
633

634

635
   norm_rate = (nbCompressedBytes-5)*8*(celt_uint32)st->mode->Fs/(C*N)>>10;
636
   /* Pitch analysis: we do it early to save on the peak stack space */
637
638
   /* Don't use pitch if there isn't enough data available yet, 
      or if we're using shortBlocks */
639
   has_pitch = st->pitch_enabled && st->pitch_permitted && (N <= 512) 
640
641
            && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks)
            && norm_rate < 50;
642
   if (has_pitch)
643
   {
644
      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
645
   }
646

647
648
   /* Deferred allocation after find_spectral_pitch() to reduce 
      the peak memory usage */
649
   ALLOC(X, C*N, celt_norm_t);         /**< Interleaved normalised MDCTs */
650

651
   ALLOC(pitch_freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
652
653
   if (has_pitch)
   {
654
      
655
      compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
656
      has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C, &st->gain_prod);
657
658
659
   }
   
   if (has_pitch)
660
      apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
661

662
   compute_band_energies(st->mode, freq, bandE, C);
663
664
665
   for (i=0;i<st->mode->nbEBands*C;i++)
      bandLogE[i] = amp2Log(bandE[i]);
   
Jean-Marc Valin's avatar
Jean-Marc Valin committed
666
   /* Band normalisation */
667
668
   normalise_bands(st->mode, freq, X, bandE, C);
   if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C))
669
      has_fold = 0;
670

671
672
673
674
675
676
677
   /* Don't use intra energy when we're operating at low bit-rate */
   intra_ener = st->force_intra || (!has_pitch && st->delayedIntra && nbCompressedBytes > st->mode->nbEBands);
   if (shortBlocks || intra_decision(bandLogE, st->oldBandE, st->mode->nbEBands))
      st->delayedIntra = 1;
   else
      st->delayedIntra = 0;

678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
   NN = st->mode->eBands[st->mode->nbEBands];
   if (shortBlocks && !transient_shift) 
   {
      celt_word32_t sum[8]={1,1,1,1,1,1,1,1};
      int m;
      for (c=0;c<C;c++)
      {
         m=0;
         do {
            celt_word32_t tmp=0;
            for (i=m+c*N;i<c*N+NN;i+=st->mode->nbShortMdcts)
               tmp += ABS32(X[i]);
            sum[m++] += tmp;
         } while (m<st->mode->nbShortMdcts);
      }
      m=0;
#ifdef FIXED_POINT
      do {
         if (SHR32(sum[m+1],3) > sum[m])
         {
            mdct_weight_shift=2;
            mdct_weight_pos = m;
         } else if (SHR32(sum[m+1],1) > sum[m] && mdct_weight_shift < 2)
         {
            mdct_weight_shift=1;
            mdct_weight_pos = m;
         }
         m++;
      } while (m<st->mode->nbShortMdcts-1);
#else
      do {
         if (sum[m+1] > 8*sum[m])
         {
            mdct_weight_shift=2;
            mdct_weight_pos = m;
         } else if (sum[m+1] > 2*sum[m] && mdct_weight_shift < 2)
         {
            mdct_weight_shift=1;
            mdct_weight_pos = m;
         }
         m++;
      } while (m<st->mode->nbShortMdcts-1);
#endif
      if (mdct_weight_shift)
      {
723
724
         mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
         renormalise_bands(st->mode, X, C);
725
726
727
      }
   }

728

729
   encode_flags(&enc, intra_ener, has_pitch, shortBlocks, has_fold);
730
731
   if (has_pitch)
   {
732
      ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
733
      ec_enc_uint(&enc, gain_id, 16);
734
   }
735
736
737
   if (shortBlocks)
   {
      if (transient_shift)
738
      {
739
         ec_enc_uint(&enc, transient_shift, 4);
740
         ec_enc_uint(&enc, transient_time, N+st->overlap);
741
      } else {
742
         ec_enc_uint(&enc, mdct_weight_shift, 4);
743
744
745
         if (mdct_weight_shift && st->mode->nbShortMdcts!=2)
            ec_enc_uint(&enc, mdct_weight_pos, st->mode->nbShortMdcts-1);
      }
746
   }
747

748
   ALLOC(fine_quant, st->mode->nbEBands, int);
749
   ALLOC(pulses, st->mode->nbEBands, int);
750
751

   /* Bit allocation */
752
   ALLOC(error, C*st->mode->nbEBands, celt_word16_t);
753
   coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8/3, intra_ener, st->mode->prob, error, &enc, C);
754
755
756
757
758
759
760
   coarse_needed = ((coarse_needed*3-1)>>3)+1;

   /* Variable bitrate */
   if (st->VBR_rate>0)
   {
     /* The target rate in 16th bits per frame */
     int target=st->VBR_rate;
761
   
762
763
     /* Shortblocks get a large boost in bitrate, but since they 
        are uncommon long blocks are not greatly effected */
764
765
766
767
768
     if (shortBlocks)
       target*=2;
     else if (st->mode->nbShortMdcts > 1)
       target-=(target+14)/28;     

769
770
     /* The average energy is removed from the target and the actual 
        energy added*/
771
     target=target-588+ec_enc_tell(&enc, BITRES);
772
773
774
775

     /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
     target=IMAX(coarse_needed,(target+64)/128);
     nbCompressedBytes=IMIN(nbCompressedBytes,target);
776
     ec_byte_shrink(&buf, nbCompressedBytes);
777
778
   }

779
   ALLOC(offsets, st->mode->nbEBands, int);
780
   ALLOC(fine_priority, st->mode->nbEBands, int);
781

782
783
   for (i=0;i<st->mode->nbEBands;i++)
      offsets[i] = 0;
784
   bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
785
   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
786

787
   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
788

Jean-Marc Valin's avatar
Jean-Marc Valin committed
789
   /* Residual quantisation */
790
   if (C==1)
791
      quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
792
#ifndef DISABLE_STEREO
793
   else
794
      quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
795
#endif
796

797
   quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc, C);
798

799
   /* Re-synthesis of the coded audio if required */
800
   if (st->pitch_available>0 || optional_synthesis!=NULL)
801
   {
802
803
804
      if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
        st->pitch_available+=st->frame_size;

805
806
      if (mdct_weight_shift)
      {
807
         mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
808
      }
809
810

      /* Synthesis */
811
      denormalise_bands(st->mode, X, freq, bandE, C);
812
813
814

      CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));

815
      if (has_pitch)
816
         apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
817
      
818
      compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
819

820
821
      /* De-emphasis and put everything back at the right place 
         in the synthesis history */
822
      if (optional_synthesis != NULL) {
823
824
         deemphasis(st->out_mem, optional_synthesis, N, C, preemph, st->preemph_memD);

825
      }
826
   }
827

828
   ec_enc_done(&enc);
829
   
830
   RESTORE_STACK;
831
   return nbCompressedBytes;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
832
833
}

834
835
#ifdef FIXED_POINT
#ifndef DISABLE_FLOAT_API
836
int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
837
{
838
   int j, ret, C, N;
839
   VARDECL(celt_int16, in);
840
   SAVE_STACK;
841
842
843
844
845
846
847

   if (check_encoder(st) != CELT_OK)
      return CELT_INVALID_STATE;

   if (check_mode(st->mode) != CELT_OK)
      return CELT_INVALID_MODE;

848
849
850
   if (pcm==NULL)
      return CELT_BAD_ARG;

851
   C = CHANNELS(st->channels);
852
   N = st->block_size;
853
   ALLOC(in, C*N, celt_int16);
854
855
856
857

   for (j=0;j<C*N;j++)
     in[j] = FLOAT2INT16(pcm[j]);

858
859
   if (optional_synthesis != NULL) {
     ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
860
      for (j=0;j<C*N;j++)
861
862
863
864
         optional_synthesis[j]=in[j]*(1/32768.);
   } else {
     ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
   }
Wessel Lubberhuizen's avatar
Wessel Lubberhuizen committed
865
   RESTORE_STACK;
866
867
868
869
870
   return ret;

}
#endif /*DISABLE_FLOAT_API*/
#else
871
int celt_encode(CELTEncoder * restrict st, const celt_int16 * pcm, celt_int16 * optional_synthesis, unsigned char *compressed, int nbCompressedBytes)
872
{
873
   int j, ret, C, N;
874
   VARDECL(celt_sig_t, in);
875
   SAVE_STACK;
876
877
878
879
880
881
882

   if (check_encoder(st) != CELT_OK)
      return CELT_INVALID_STATE;

   if (check_mode(st->mode) != CELT_OK)
      return CELT_INVALID_MODE;

883
884
885
   if (pcm==NULL)
      return CELT_BAD_ARG;

886
   C=CHANNELS(st->channels);
887
   N=st->block_size;
888
889
890
891
892
   ALLOC(in, C*N, celt_sig_t);
   for (j=0;j<C*N;j++) {
     in[j] = SCALEOUT(pcm[j]);
   }