[FFmpeg-devel] Review request - ra288.{c,h} ra144.{c,h}
Vitor Sessak
vitor1001
Sun Sep 14 20:17:18 CEST 2008
Michael Niedermayer wrote:
> On Sun, Sep 14, 2008 at 05:55:16PM +0200, Vitor Sessak wrote:
>> Michael Niedermayer wrote:
>>> On Sat, Sep 13, 2008 at 09:48:46PM +0200, Vitor Sessak wrote:
>>>> Michael Niedermayer wrote:
>>>>> On Sat, Sep 13, 2008 at 07:07:26PM +0200, Vitor Sessak wrote:
>>>>>> Michael Niedermayer wrote:
>>>>>>> On Fri, Sep 05, 2008 at 12:23:58AM +0200, Vitor Sessak wrote:
>>>>>>>> Vitor Sessak wrote:
>>>>> [...]
>>>>>>> [...]
>>>>>>>> static void colmult(float *tgt, const float *m1, const float *m2, int n)
>>>>>>>> {
>>>>>>>> while (n--)
>>>>>>>> *tgt++ = *m1++ * *m2++;
>>>>>>>> }
>>>>>>> such function is commonly called apply_window() in other codecs
>>>>>>>> static void decode(RA288Context *ractx, float gain, int cb_coef)
>>>>>>>> {
>>>>>>>> int i, j;
>>>>>>>> double sumsum;
>>>>>>>> float sum, buffer[5];
>>>>>>>> float *block = ractx->sp_block + 36; // Current block
>>>>>>>>
>>>>>>>> memmove(ractx->sp_block, ractx->sp_block + 5,
>>>>>>>> 36*sizeof(*ractx->sp_block));
>>>>>>>>
>>>>>>>> for (i=0; i < 5; i++) {
>>>>>>>> block[i] = 0.;
>>>>>>>> for (j=0; j < 36; j++)
>>>>>>>> block[i] -= block[i-1-j]*ractx->sp_lpc[j];
>>>>>>>> }
>>>>>>>>
>>>>>>>> /* block 46 of G.728 spec */
>>>>>>>> sum = 32.;
>>>>>>>> for (i=0; i < 10; i++)
>>>>>>>> sum -= ractx->gain_block[9-i] * ractx->gain_lpc[i];
>>>>>>>>
>>>>>>>> /* block 47 of G.728 spec */
>>>>>>>> sum = av_clipf(sum, 0, 60);
>>>>>>>>
>>>>>>>> /* block 48 of G.728 spec */
>>>>>>>> sumsum = exp(sum * 0.1151292546497) * gain; /* pow(10.0,sum/20)*gain
>>>>>>>> */
>>>>>>>>
>>>>>>>> for (i=0; i < 5; i++)
>>>>>>>> buffer[i] = codetable[cb_coef][i] * sumsum;
>>>>>>>>
>>>>>>>> sum = scalar_product_float(buffer, buffer, 5) / 5;
>>>>>>>>
>>>>>>>> sum = FFMAX(sum, 1);
>>>>>>>>
>>>>>>>> /* shift and store */
>>>>>>>> memmove(ractx->gain_block, ractx->gain_block + 1,
>>>>>>>> 9 * sizeof(*ractx->gain_block));
>>>>>>>>
>>>>>>>> ractx->gain_block[9] = 10 * log10(sum) - 32;
>>>>>>>>
>>>>>>>> for (i=1; i < 5; i++)
>>>>>>>> for (j=i-1; j >= 0; j--)
>>>>>>>> buffer[i] -= ractx->sp_lpc[i-j-1] * buffer[j];
>>>>>>>>
>>>>>>>> /* output */
>>>>>>>> for (i=0; i < 5; i++)
>>>>>>>> block[i] = av_clipf(block[i] + buffer[i], -4095, 4095);
>>>>>>> can the buffer values be stored in block and sp_lpc applied over both
>>>>>>> in one pass instead of this 2 pass and add-clip thing?
>>>>>> I can't apply sp_lpc to buffer+block, so I need two buffers...
>>>>> What i was thinking about was:
>>>>>
>>>>> /* block 46 of G.728 spec */
>>>>> sum = 32.;
>>>>> for (i=0; i < 10; i++)
>>>>> sum -= gain_block[9-i] * ractx->gain_lpc[i];
>>>>>
>>>>> /* block 47 of G.728 spec */
>>>>> sum = av_clipf(sum, 0, 60);
>>>>>
>>>>> /* block 48 of G.728 spec */
>>>>> sumsum = exp(sum * 0.1151292546497) * gain; /* pow(10.0,sum/20)*gain */
>>>>>
>>>>> for (i=0; i < 5; i++)
>>>>> buffer[i] = codetable[cb_coef][i] * sumsum * (1./2048.);
>>>>>
>>>>> sum = scalar_product_float(buffer, buffer, 5) / 5;
>>>>>
>>>>> sum = FFMAX(sum, 1);
>>>>>
>>>>> /* shift and store */
>>>>> memmove(gain_block, gain_block + 1, 9 * sizeof(*gain_block));
>>>>>
>>>>> gain_block[9] = 10 * log10(sum) - 32;
>>>>>
>>>>> for (i=0; i < 5; i++) {
>>>>> block[i] = buffer[i];
>>>> Here you are overwriting the value of block[i] (while previous code used
>>>> this value).
>>> previous code did:
>>> for (i=0; i < 5; i++) {
>>> block[i] = 0.;
>>>
>>> so that certainly was not useing it
>> Ok, the problem is the following. Now we have (moving down a few loops):
>>
>> for (i=1; i < 5; i++)
>> for (j=i-1; j >= 0; j--)
>> buffer[i] -= ractx->sp_lpc[i-j-1] * buffer[j];
>>
>> for (i=0; i < 5; i++) {
>> block[i] = 0.;
>> for (j=0; j < 36; j++)
>> block[i] -= block[i-1-j]*ractx->sp_lpc[j];
>> }
>>
>> /* output */
>> for (i=0; i < 5; i++)
>> block[i] = av_clipf(block[i] + buffer[i], -4095, 4095);
>>
>> And I cannot change block[i] = 0. to block[i] = buffer[i] because
>> block[0] will be read for evaluating block[1] in the second loop.
>
> no and yes
>
> the second loop applies a LPC filter to block assuming the future samples
> are 0
> the first loop applies the same LPC filter to buffer assuming the previous
> samples are 0
> the third loop combines them so that they match as if a LPC filter had
> been applied to their sum i think.
>
>
>
>>>>>>> [...]
>>>>>>>> static int ra288_decode_frame(AVCodecContext * avctx, void *data,
>>>>>>>> int *data_size, const uint8_t * buf,
>>>>>>>> int buf_size)
>>>>>>>> {
>>>>>>>> int16_t *out = data;
>>>>>>>> int i, j;
>>>>>>>> RA288Context *ractx = avctx->priv_data;
>>>>>>>> GetBitContext gb;
>>>>>>>>
>>>>>>>> if (buf_size < avctx->block_align) {
>>>>>>>> av_log(avctx, AV_LOG_ERROR,
>>>>>>>> "Error! Input buffer is too small [%d<%d]\n",
>>>>>>>> buf_size, avctx->block_align);
>>>>>>>> return 0;
>>>>>>>> }
>>>>>>>>
>>>>>>>> if (*data_size < 32*5*2)
>>>>>>>> return -1;
>>>>>>>>
>>>>>>>> init_get_bits(&gb, buf, avctx->block_align * 8);
>>>>>>>>
>>>>>>>> for (i=0; i < 32; i++) {
>>>>>>>> float gain = amptable[get_bits(&gb, 3)];
>>>>>>>> int cb_coef = get_bits(&gb, 6 + (i&1));
>>>>>>>>
>>>>>>>> decode(ractx, gain, cb_coef);
>>>>>>>>
>>>>>>>> for (j=0; j < 5; j++)
>>>>>>>> *(out++) = 8 * ractx->sp_block[36 + j];
>>>>>>> if float output works already, then this could output floats, if not then
>>>>>>> this could use lrintf()
>>>>>> I've tried the float output (with the attached patch) and it didn't work.
>>>>> ok
>>>>>
>>>>>
>>>>>> Using lrint() changes slightly the output (PSNR about 99), is it expected?
>>>>> yes, it does round differently (=more correctly)
>>>> Too correct maybe. PSNR to binary decoder with SVN:
>>>>
>>>> stddev: 0.15 PSNR:112.70 bytes: 990720/ 1013760
>>>> stddev: 0.04 PSNR:122.74 bytes: 368640/ 368640
>>>> stddev: 0.07 PSNR:118.84 bytes: 460800/ 458752
>>>> stddev: 0.31 PSNR:106.24 bytes: 6451200/ 6451200
>>>>
>>>> Using lrint()
>>>>
>>>> stddev: 0.70 PSNR: 99.33 bytes: 990720/ 1013760
>>>> stddev: 0.70 PSNR: 99.35 bytes: 368640/ 368640
>>>> stddev: 0.70 PSNR: 99.35 bytes: 460800/ 458752
>>>> stddev: 0.75 PSNR: 98.76 bytes: 6451200/ 6451200
>>> yes, the rounding is more accurate, and differs by +-1 50% of the time from
>>> the binary decoder, sqrt(0.5) ~ 0.7
>>>
>>> If you want a proof that it is better, you should compare the original
>>> pcm that is
>>>
>>> X -> encoder -> binary decoder -> Y
>>> -> FF decoder ->Z
>>>
>>> and look at how the X-Y and X-Z change relative to each other.
>>>
>>> Also you would see a similar PSNR change relative to the binary decoder if
>>> you would output floats.
>> I've already tried comparing PSNR to the original input when I was
>> looking for a way to test float codecs in FATE.
>>
>> vitor at vitor$ ffmpeg -i luckynightmono2.ra -ac 1 -ar 8000 test.wav
>> vitor at vitor$ ffmpeg -i luckynight.wav -ac 1 -ar 8000 test2.wav
>> vitor at vitor$ tiny_psnr test.wav test2.wav 2 0 44
>> stddev: 5981.39 PSNR: 20.78 bytes: 990720/ 967662
>> vitor at vitor$ tiny_psnr test.wav test2.wav 2 2 44
>> stddev: 5982.77 PSNR: 20.78 bytes: 990718/ 967662
>> vitor at vitor$ tiny_psnr test.wav test2.wav 2 100 44
>> stddev: 6012.76 PSNR: 20.74 bytes: 990620/ 967662
>>
>> And by looking at results, if I change the "skip bytes" parameter I
>> don't get much change in PSNR. For me, this is a signal that the value I
>> got is meaningless (since it don't change a lot if I compare it with
>> different data). I asked about it in IRC and people told me that PSNR
>> didn't worked very well to LPC vocoders. Sample in
>> http://samples.mplayerhq.hu/real/AC-28_8/ .
>
> considering that the claimed encoder input has
> 10668716 bytes of 44.1khz at stereo
> and that /2/44100*8000 is ~967684
> and the ra288 decoder output has 990764 bytes i cant help but wonder
> why, but of course this is incompareable. PSNR or otherwise
Yes, the files have different sizes. That's why I started poking with
"skip bytes" and tried to cut the files. But I didn't succeeded in
making they match whatever I did.
-Vitor
More information about the ffmpeg-devel
mailing list