[FFmpeg-devel] Nellymoser encoder

Bartlomiej Wolowiec bartek.wolowiec
Sun Aug 31 22:07:22 CEST 2008


Sunday 31 August 2008 15:53:23 Michael Niedermayer napisa?(a):
> On Sun, Aug 31, 2008 at 01:07:15PM +0200, Bartlomiej Wolowiec wrote:
> > Saturday 30 August 2008 18:10:41 Michael Niedermayer napisa?(a):
> > > On Sat, Aug 30, 2008 at 03:42:37PM +0200, Bartlomiej Wolowiec wrote:
> > > > Friday 29 August 2008 22:36:10 Michael Niedermayer napisa?(a):
> > > > > > > > > > +
> > > > > > > > > > +void apply_mdct(NellyMoserEncodeContext *s, float *in,
> > > > > > > > > > float *coefs) +{
> > > > > > > > > > +    DECLARE_ALIGNED_16(float, in_buff[NELLY_SAMPLES]);
> > > > > > > > > > +
> > > > > > > > > > +    memcpy(&in_buff[0], &in[0], NELLY_SAMPLES *
> > > > > > > > > > sizeof(float)); +    s->dsp.vector_fmul(in_buff,
> > > > > > > > > > ff_sine_128, NELLY_BUF_LEN); +   
> > > > > > > > > > s->dsp.vector_fmul_reverse(in_buff + NELLY_BUF_LEN,
> > > > > > > > > > in_buff + NELLY_BUF_LEN, ff_sine_128, NELLY_BUF_LEN); +
> > > > > > > > > > ff_mdct_calc(&s->mdct_ctx, coefs, in_buff);
> > > > > > > > > > +}
> > > > > > > > >
> > > > > > > > > The data is copied once in encode_frame and twice here
> > > > > > > > > There is no need to copy the data 3 times.
> > > > > > > > > vector_fmul can be used with a singl memcpy to get the data
> > > > > > > > > into any destination, and vector_fmul_reverse doesnt even
> > > > > > > > > need 1 memcpy, so overall a single memcpy is enough
> > > > > > > >
> > > > > > > > Hope that you meant something similar to my solution.
> > > > > > >
> > > > > > > no, you still do 2 memcpy() but now the code is really messy as
> > > > > > > well.
> > > > > > >
> > > > > > > what you should do is, for each block of samples you get from
> > > > > > > the user 1. apply one half of the window onto it with
> > > > > > > vector_fmul_reverse and destination of some internal buffer
> > > > > > > 2. memcpy into the 2nd destination and apply the other half of
> > > > > > > the window onto it with vector_fmul
> > > > > > > 3. run the mdct as appropriate on the internal buffers.
> > > > > >
> > > > > > Hmm, I considered it, but I don't understand exactly what should
> > > > > > I change... In the code I copy data two times:
> > > > > > a) in encode_frame - I convert int16_t to float and copy data to
> > > > > > s->buf - I need to do it somewhere because vector_mul requires
> > > > > > float *. Additionally, part of the data is needed to the next
> > > > > > call of encode_frame b) in apply_mdct - here I think that some
> > > > > > additional part of buffer is needed. If I understood correctly I
> > > > > > have to get rid of a), but how to get access to old data when the
> > > > > > next call of encode_frame is performed and how call vector_fmul
> > > > > > on int16_t?
> > > > >
> > > > > have you tried setting AVCodec.sample_fmts to SAMPLE_FMT_FLT ?
> > > > > I think ffmpeg should support this already. If it does not work
> > > > > then we can keep int16 for now which would implicate more copying
> > > >
> > > > Hmm... I tried to use SAMPLE_FMT_FLT, but something doesn't work. I
> > > > made only that changes:
> > > >
> > > > float *samples = data;
> > > > ...
> > > > for (i = 0; i < avctx->frame_size; i++) {
> > > >     s->buf[s->bufsel][i] = samples[i]*(1<<15);
> > > > }
> > > > ...
> > > > .sample_fmts = (enum SampleFormat[]){SAMPLE_FMT_FLT,SAMPLE_FMT_NONE},
> > >
> > > hmm
> >
> > Any idea? or should I leave it as it is?
>
> does PCM float work for you? if so what is the difference to your encoder?

pcm_f32le doesn't work - because it isn't hacked in ffmpeg.c. Nellymoser 
probably for the same reason...

[...]
> > +/**
> > + * Encodes NELLY_SAMPLES samples. It assumes, that samples contains 3 *
> > NELLY_BUF_LEN values + *  @param s               encoder context
> > + *  @param output          output buffer
> > + *  @param output_size     size of output buffer
> > + */
> > +static void encode_block(NellyMoserEncodeContext *s, unsigned char
> > *output, int output_size) +{
> > +    PutBitContext pb;
> > +    int i, j, band, block, best_idx, power_idx = 0;
> > +    float power_val, coeff, coeff_sum;
> > +    float pows[NELLY_FILL_LEN];
> > +    int bits[NELLY_BUF_LEN], idx_table[NELLY_BANDS];
> > +    float cand[NELLY_BANDS];
> > +
> >
> > +    const float C = 1.0;
> > +    const float D = 3.0;
>
> any reason why you changed these? Do these sound better?

No, I tested other settings with get_exponent_dynamic and I forgot to change 
it - in my opinion such change doesn't give greater effect.

> > +
> > +    apply_mdct(s);
> > +
> >
> > +    init_put_bits(&pb, output, output_size * 8);
> > +
> > +    i = 0;
> > +    for (band = 0; band < NELLY_BANDS; band++) {
> > +        coeff_sum = 0;
> > +        for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) {
> > +            //coeff_sum += s->mdct_out[i                ] *
> > s->mdct_out[i                ] +            //           + s->mdct_out[i
> > + NELLY_BUF_LEN] * s->mdct_out[i + NELLY_BUF_LEN]; +            coeff_sum
> > += pow(fabs(s->mdct_out[i]), D) + pow(fabs(s->mdct_out[i +
> > NELLY_BUF_LEN]), D); +        }
> > +        cand[band] =
> > +            //log(FFMAX(1.0, coeff_sum /
> > (ff_nelly_band_sizes_table[band] << 7))) * 1024.0 / M_LN2; +            C
> > * log(FFMAX(1.0, coeff_sum / (ff_nelly_band_sizes_table[band] << 7))) *
> > 1024.0 / log(D);
>
> the MAX should maybe be done after the correction for D

I don't know what exactly do you mean...

-- 
Bartlomiej Wolowiec
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nellymoser6.patch
Type: text/x-diff
Size: 8978 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080831/529c0985/attachment.patch>



More information about the ffmpeg-devel mailing list