libavcodec/mlpdsp.c
bf4f19dc
 /*
  * Copyright (c) 2007-2008 Ian Caulfield
  *               2009 Ramiro Polla
  *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
  * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
2d6caade
 #include "config.h"
6fee1b90
 #include "libavutil/attributes.h"
2d6caade
 #include "mlpdsp.h"
dc25d79f
 #include "mlp.h"
bf4f19dc
 
088f38a4
 static void mlp_filter_channel(int32_t *state, const int32_t *coeff,
                                int firorder, int iirorder,
                                unsigned int filter_shift, int32_t mask,
                                int blocksize, int32_t *sample_buffer)
bf4f19dc
 {
13bd2044
     int32_t *firbuf = state;
     int32_t *iirbuf = state + MAX_BLOCKSIZE + MAX_FIR_ORDER;
     const int32_t *fircoeff = coeff;
     const int32_t *iircoeff = coeff + MAX_FIR_ORDER;
bf4f19dc
     int i;
 
     for (i = 0; i < blocksize; i++) {
         int32_t residual = *sample_buffer;
         unsigned int order;
         int64_t accum = 0;
         int32_t result;
 
         for (order = 0; order < firorder; order++)
             accum += (int64_t) firbuf[order] * fircoeff[order];
         for (order = 0; order < iirorder; order++)
             accum += (int64_t) iirbuf[order] * iircoeff[order];
 
         accum  = accum >> filter_shift;
         result = (accum + residual) & mask;
 
         *--firbuf = result;
         *--iirbuf = result - accum;
 
         *sample_buffer = result;
42e64bf8
         sample_buffer += MAX_CHANNELS;
bf4f19dc
     }
 }
 
3f4e73af
 void ff_mlp_rematrix_channel(int32_t *samples,
                              const int32_t *coeffs,
                              const uint8_t *bypassed_lsbs,
                              const int8_t *noise_buffer,
                              int index,
                              unsigned int dest_ch,
                              uint16_t blockpos,
                              unsigned int maxchan,
                              int matrix_noise_shift,
                              int access_unit_size_pow2,
                              int32_t mask)
 {
     unsigned int src_ch, i;
     int index2 = 2 * index + 1;
     for (i = 0; i < blockpos; i++) {
         int64_t accum = 0;
 
         for (src_ch = 0; src_ch <= maxchan; src_ch++)
             accum += (int64_t) samples[src_ch] * coeffs[src_ch];
 
         if (matrix_noise_shift) {
             index &= access_unit_size_pow2 - 1;
             accum += noise_buffer[index] << (matrix_noise_shift + 7);
             index += index2;
         }
 
         samples[dest_ch] = ((accum >> 14) & mask) + *bypassed_lsbs;
         bypassed_lsbs += MAX_CHANNELS;
         samples += MAX_CHANNELS;
     }
 }
 
b01a2562
 static int32_t (*mlp_select_pack_output(uint8_t *ch_assign,
                                         int8_t *output_shift,
                                         uint8_t max_matrix_channel,
                                         int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int)
 {
     return ff_mlp_pack_output;
 }
 
 int32_t ff_mlp_pack_output(int32_t lossless_check_data,
                            uint16_t blockpos,
                            int32_t (*sample_buffer)[MAX_CHANNELS],
                            void *data,
                            uint8_t *ch_assign,
                            int8_t *output_shift,
                            uint8_t max_matrix_channel,
                            int is32)
 {
     unsigned int i, out_ch = 0;
     int32_t *data_32 = data;
     int16_t *data_16 = data;
 
     for (i = 0; i < blockpos; i++) {
         for (out_ch = 0; out_ch <= max_matrix_channel; out_ch++) {
             int mat_ch = ch_assign[out_ch];
             int32_t sample = sample_buffer[i][mat_ch]
                           << output_shift[mat_ch];
             lossless_check_data ^= (sample & 0xffffff) << mat_ch;
             if (is32)
                 *data_32++ = sample << 8;
             else
                 *data_16++ = sample >> 8;
         }
     }
     return lossless_check_data;
 }
 
6fee1b90
 av_cold void ff_mlpdsp_init(MLPDSPContext *c)
bf4f19dc
 {
088f38a4
     c->mlp_filter_channel = mlp_filter_channel;
3f4e73af
     c->mlp_rematrix_channel = ff_mlp_rematrix_channel;
b01a2562
     c->mlp_select_pack_output = mlp_select_pack_output;
     c->mlp_pack_output = ff_mlp_pack_output;
87b128d5
     if (ARCH_ARM)
         ff_mlpdsp_init_arm(c);
cbd7836e
     if (ARCH_X86)
2d6caade
         ff_mlpdsp_init_x86(c);
bf4f19dc
 }