[FFmpeg-devel] [PATCH] TwinVQ decoder

Vitor Sessak vitor1001
Wed Jul 22 09:16:50 CEST 2009


Vitor Sessak wrote:
> Michael Niedermayer wrote:
>> On Mon, Jun 08, 2009 at 10:01:40PM +0200, Vitor Sessak wrote:
>>> Michael Niedermayer wrote:
>>>> On Mon, May 18, 2009 at 06:32:55PM +0200, Vitor Sessak wrote:
>>>>> Michael Niedermayer wrote:
>>>>>> On Wed, May 06, 2009 at 05:09:50PM +0200, Vitor Sessak wrote:
>>>>>>> Vitor Sessak wrote:
>> [...]
>>>>> /**
>>>>>  * Evaluate a single LPC amplitude spectrum envelope coefficient 
>>>>> from the line
>>>>>  * spectrum pairs
>>>>>  *
>>>>>  * @param cos_lsp a vector of the cosinus of the LSP values
>>>>>  * @param cos_val cos(PI*i/N) where i is the index of the LPC 
>>>>> amplitude
>>>>>  * @return the LPC value
>>>>>  *
>>>>>  * @todo reuse code from vorbis_dec.c: vorbis_floor0_decode
>                                             ^^^^^^^^^^^^^^^^^^^^
> 
>>>>>  */
>>>>> static float eval_lpc_spectrum(const float *cos_lsp, float cos_val, 
>>>>> int size)
>>>>> {
>>>>>     int i;
>>>>>     float a = .5;
>>>>>     float b = .5;
>>>>>
>>>>>     for (i=0; i < size; i += 2) {
>>>>>         a *= 2*cos_val - cos_lsp[i  ];
>>>>>         b *= 2*cos_val - cos_lsp[i+1];
>>>>>     }
>>>>>
>>>>>     a *= a*(2+2*cos_val);
>>>>>     b *= b*(2-2*cos_val);
>>>>>
>>>>>     return .5/(a+b);
>>>>> }
>>>> if iam not too tired the .5 and 2 are useless
>>> It is, but it is like that to make it easier to see in what way it is 
>>> similar to vorbis_floor0_decode().
>>
>> add a comment that says that please
> 
> See above...
> 
> 
> [... Comments that where changes as suggestion ...]
> 
>>> /**
>>>  * Evaluates the LPC amplitude spectrum envelope from the line 
>>> spectrum pairs.
>>>  * Probably for speed reasons, the coefficients are evaluated like
>>>  * siiiibiiiiisiiiibiiiiisiiiibiiiiisiiiibiiiiis ...
>>>  * where s is an evaluated value, i is a value interpolated from the 
>>> others
>>>  * and b might be either calculated or interpolated, dependent on a
>>>  * unexplained condition.
>>>  *
>>>  * @param step the size of a block "siiiibiiii"
>>>  * @param in the cosinus of the LSP data
>>>  */
>>> static inline void eval_lpcenv_or_interp(float *out, const float *in,
>>>                                          int size, int step, int sub,
>>>                                          const ModeTab *mtab, int 
>>> forward)
>>> {
>>>     int i;
>>>     const float *cos_tab = ff_cos_tabs[av_log2(mtab->size)-1];
>>>
>>>     // Fill the 's'
>>>     for (i=0; i < size; i += step)
>>>         out[i] =
>>>             eval_lpc_spectrum(in,
>>>                               GET_COS(sub, i*4+2, forward,
>>>                                       cos_tab, 2*mtab->size - 
>>> sub*size*2),
>>>                               mtab->n_lsp);
>>>
>>>     // Fill the 'b'
>>>     for (i=step; i < size - step; i += step) {
>>>         if ((out[i + step] + out[i - step] > 1.95*out[i]) ||
>>>             (out[i - step]               <= out[i + step])) {
>>>             out[i - step/2] = (out[i] + out[i-step])*.5;
>>>         } else {
>>>             out[i - step/2] =
>>>                 eval_lpc_spectrum(in,
>>>                                   GET_COS(sub, 4*i-2*step+2, forward,
>>>                                           cos_tab,
>>>                                           2*mtab->size - sub*size*2),
>>>                                   mtab->n_lsp);
>>>         }
>>>     }
>>>
>>>     // Fill the 'i'
>>>     for (i=step; i < size - step; i += step/2)
>>>         interpolate(out + i-step  +1, out[i-step/2], out[i-step  ], 
>>> step/2);
>>>
>>>     interpolate(out+i-step+1, out[i], out[i-step], step);
>>
>> hmm, still ugly
>>
>> what about something like: (note its buggy but the idea should be clear)
>> {
>>     if(!(i&step) || (out[i + step]  + out[i - step] <= 1.95*out[i] &&
>>                      out[i + step] < out[i - step]                   )){
>>         eval_lpc_spectrum
>>         if(i)
>>             interpolate(i, last_point);
>>         last_point= i
>>     }
>> }
>>
>> the b really is just a longer interpolation AFAICS
> 
> The problem is that to know if the "b" will be evaluated or 
> interpolated, one needs to have the previous and the following "s" 
> already calculated. So doing in one pass is not really possible cleanly. 
> I've made it in two passes ("i"s, then "s" and "b");
> 
> [... more comments that have been taken care of ...]
> 
>>> static void extend_pitch(int a1, const float *pitch, float pit_gain,
>>>                          float *speech, TwinContext *tctx)
>>> {
>>>     const ModeTab *mtab = tctx->mtab;
>>>     int pos;
>>
>>>     int unk1;
>>>     int unk2;
>>
>> ehm
>>
>>
>>>     int fcmax_i, fcmin_i;
>>>     int i, j;
>>>     int basf_step = (1 << mtab->basf_bit) - 1;
>>>     int isampf = tctx->avctx->sample_rate/1000;
>>>     int ibps = tctx->avctx->bit_rate/(1000 * tctx->avctx->channels);
>>>
>>>     fcmin_i = (  40*2*mtab->size + isampf/2)/isampf;
>>>     fcmax_i = (6*40*2*mtab->size + isampf/2)/isampf;
>>>
>>>     unk1 = fcmin_i +  (a1*(fcmax_i - fcmin_i) + basf_step/2)/basf_step;
>>>
>>>     if ((isampf == 22) && (ibps == 32)) {
>>>         unk2 = ((unk1 + 800LL)* mtab->pitch_cst * mtab->pit_cb_len * 
>>> unk1 +
>>>                200LL * mtab->size*unk1)/
>>>             (400LL * mtab->size * unk1);
>>>     } else
>>>         unk2 = (mtab->pitch_cst * mtab->pit_cb_len * unk1)/(400 * 
>>> mtab->size);
>>>
>>>     for (i=0; i < unk2/2; i++)
>>>         speech[i] += pit_gain * pitch[i];
>>>
>>>     pos = unk2/2;
>>>
>>>     for (i=0; i < mtab->pit_cb_len; i++) {
>>>         int v38 = very_broken_op(unk1, i + 1);
>>
>> v38 ?
>>
>> also i should mention that a 1:1 convertion to C from disassembly 
>> might not
>> be legal, we need an independant implementation of things
>> variables with names that look like they are copied from a disassembler
>> raise a big red flag here and you will have to convince me that you 
>> really
>> wrote an independant implementation if you want to see this in svn
> 
> Rewritten all the functions that were not reimplemented from scratch.
> 
> New patch attached. Now tables were converted to int16_t, and now 
> stripped twinvq.o weights "only" 200kb.
> 
> To avoid the need for moderation the twinvq_data.c file was trimmed. One 
> can find the full version at http://vsessak.googlepages.com/twinvq_data.h .

New version attached. Changes:

- Use DSP functions
- Do not alloc big buffers on the stack
- Some random optimizations
- Diego's cosmetics suggestions

-Vitor
-------------- next part --------------
A non-text attachment was scrubbed...
Name: twinvq.c
Type: text/x-csrc
Size: 38308 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090722/60c1f5b5/attachment.c>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: twinvq_data.h
Type: text/x-chdr
Size: 13509 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090722/60c1f5b5/attachment.h>



More information about the ffmpeg-devel mailing list