[FFmpeg-devel] [PATCH] atrac decoder

Benjamin Larsson banan
Wed Aug 12 09:16:09 CEST 2009


Michael Niedermayer wrote:
> On Tue, Aug 11, 2009 at 10:01:49PM +0200, Benjamin Larsson wrote:
>   
>> Michael Niedermayer wrote:
>>     
>>> On Tue, Aug 11, 2009 at 07:32:30PM +0200, Benjamin Larsson wrote:
>>>       
>>>> Michael Niedermayer wrote:
>>>>         
>>>>> On Mon, Aug 10, 2009 at 11:10:40PM +0200, Benjamin Larsson wrote:
>>>>>           
>>>>>> Michael Niedermayer wrote:
>>>>>>             
>>>>>>> On Mon, Jun 08, 2009 at 09:40:18PM +0200, Benjamin Larsson wrote:
>>>>>>>               
>>>>> [...]
>>>>>           
>>>>>>> [...]
>>>>>>>               
>>>>>>>> +static void at1_imdct_transform(ATRAC1Context *q, float *spec, float *out, int nbits, int reverse_spectrum)
>>>>>>>> +{
>>>>>>>> +    float* window;
>>>>>>>> +    MDCTContext* mdct_context;
>>>>>>>> +    int transf_size = 1 << nbits;
>>>>>>>> +
>>>>>>>> +    switch(nbits) {
>>>>>>>> +        case 5:
>>>>>>>> +            window = short_window;
>>>>>>>> +            mdct_context = &q->mdct_ctx[0];
>>>>>>>> +            break;
>>>>>>>> +        case 7:
>>>>>>>> +            window = mid_window;
>>>>>>>> +            mdct_context = &q->mdct_ctx[1];
>>>>>>>> +            break;
>>>>>>>> +        case 8:
>>>>>>>> +        default:
>>>>>>>> +            window = long_window;
>>>>>>>> +            mdct_context = &q->mdct_ctx[2];
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    if (reverse_spectrum) {
>>>>>>>> +        int i;
>>>>>>>> +        for (i=0; i<transf_size/2; i++)
>>>>>>>> +            FFSWAP(float, spec[i], spec[transf_size-1-i]);
>>>>>>>> +    }
>>>>>>>>                 
>>>>>>> i think that can be avoided by decong in reverse order ...
>>>>>>>
>>>>>>>               
>>>>>> Would be possible if there where no short blocks. The logic to untangle
>>>>>> those are not worth it.
>>>>>>             
>>>>> elabrate please
>>>>>           
>>>> A subband that is reversed can use short or long mdct sizes. If it is
>>>> long then decoding in reverse order would work.
>>>>
>>>> 12,11,10,9,8,7,6,5,4,3,2,1
>>>>
>>>> But when the short order is used (to code transients), the blocks are
>>>> reversed in groups.
>>>>
>>>> 3,2,1,6,5,4,9,8,7,12,11,10
>>>>         
>>> these groups dont coincide with some for loop ?
>>> and they arent powers of 2 ? 4321 8765 ...
>>>       
>> They are, the numbers where just an illustration of how the bitstream is
>> formated in different modes.
>>
>> Following is the code logic.
>>
>> bsm is parsed from the bitstream.
>>
>> num_blocks = 1 << bsm;
>> for (; num_blocks != 0; num_blocks--) {
>>     at1_imdct_transform(q, &q->spec[pos], q->short_buf, 5, band_num);
>>     pos += 32;
>> }
>>
>> 32 samples.
>>
>> at1_imdct_transform is the function that reverses the &q->spec[pos]
>> buffer. So to properly reverse the buffer during bitstream parsing you
>> need to decode the spectrum in 32 sample blocks. The following logic
>> (simplified) is used to requant short blocks.
>>
>> num_specs = specs_per_bfu[bfu_num];
>> pos = bfu_start_short[bfu_num];
>>
>> for (i=0 ; i<num_specs ; i++)
>> 	spec[pos + i] = get_sbits(gb, word_len)
>>
>> So for long blocks, just count backwards from 512 and everything is
>> fine. For short blocks now we would need to calculate every index if it
>> in the right position or try to count backwards and adjust the index in
>> some nice way. The second suggestion doesn't work to well as num_specs
>> can be odd. Thus the first suggestion has to be used, and as this code
>> is used for long blocks also it would slow them down if the index
>> recalculation is added or it would lead to code duplication. All in all
>> lots of complication and work for something that could be solved by
>> reverse reading in the mdct. But as I'm one of the few people who care
>> about atrac I see no need to add that. Just swapping the buffer would be
>> my prefered solution.
>>     
>
> if the groups are a power of 2 you can do
> 0123456789ABCDEF
> ^3
> 32107654...
>
> thats just a ^C in the index and can be omited when filling whole
> blocks of size C with zeros
>
>   

Ok, that seem to work. I'll implement it.

>   
>>>
>>>       
>>>>>>>> +
>>>>>>>> +    ff_imdct_calc(mdct_context,out,spec);
>>>>>>>>                 
>>>>>>> cant imdct_half be used?
>>>>>>>
>>>>>>>               
>>>>>> Changed to
>>>>>>
>>>>>> memset
>>>>>> fmul
>>>>>> fmul_rev
>>>>>> memset
>>>>>>
>>>>>> It was slightly faster and uses less memory.
>>>>>>             
>>>>> you still use the full imdct
>>>>>           
>>>> Yes, that has to do with windowing. As I shouldn't multiply with 0 and 1
>>>> I have to do it this way. To use imdct_half I need to build the complete
>>>> windows again (Use more memory etc).
>>>>         
>>> iam not convinced but i didnt verify it can be done ...
>>>
>>>       
>> Well as vector_fmul_window is defined now you need to use the complete
>> windows.
>>     
>
> and when window is 0 or 1 some other function could be used, besides
> is vector_fmul_window + half_imdct slower than the cutrrent code?
>

The window is not only 0's and 1's. I'll benchmark vector_fmul_window + 
half_imdct against the current solution later this week.

MvH
Benjamin Larsson





More information about the ffmpeg-devel mailing list