CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/ext/at3_standalone/atrac.cpp
Views: 1401
/*1* common functions for the ATRAC family of decoders2*3* Copyright (c) 2006-2013 Maxim Poliakovski4* Copyright (c) 2006-2008 Benjamin Larsson5*6* This file is part of FFmpeg.7*8* FFmpeg is free software; you can redistribute it and/or9* modify it under the terms of the GNU Lesser General Public10* License as published by the Free Software Foundation; either11* version 2.1 of the License, or (at your option) any later version.12*13* FFmpeg is distributed in the hope that it will be useful,14* but WITHOUT ANY WARRANTY; without even the implied warranty of15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16* Lesser General Public License for more details.17*18* You should have received a copy of the GNU Lesser General Public19* License along with FFmpeg; if not, write to the Free Software20* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA21*/2223/**24* @file25*/2627#include <math.h>28#include <stddef.h>29#include <stdio.h>30#include <string.h>3132#include "atrac.h"3334float av_atrac_sf_table[64];35static float qmf_window[48];3637static const float qmf_48tap_half[24] = {38-0.00001461907, -0.00009205479,-0.000056157569,0.00030117269,390.0002422519, -0.00085293897,-0.0005205574, 0.0020340169,400.00078333891, -0.0042153862, -0.00075614988, 0.0078402944,41-0.000061169922,-0.01344162, 0.0024626821, 0.021736089,42-0.007801671, -0.034090221, 0.01880949, 0.054326009,43-0.043596379, -0.099384367, 0.13207909, 0.4642415944};4546void ff_atrac_generate_tables(void)47{48int i;49float s;5051/* Generate scale factors */52if (!av_atrac_sf_table[63])53for (i=0 ; i<64 ; i++)54av_atrac_sf_table[i] = pow(2.0, (i - 15) / 3.0);5556/* Generate the QMF window. */57if (!qmf_window[47])58for (i=0 ; i<24; i++) {59s = qmf_48tap_half[i] * 2.0;60qmf_window[i] = qmf_window[47 - i] = s;61}62}6364void ff_atrac_init_gain_compensation(AtracGCContext *gctx, int id2exp_offset,65int loc_scale)66{67int i;6869gctx->loc_scale = loc_scale;70gctx->loc_size = 1 << loc_scale;71gctx->id2exp_offset = id2exp_offset;7273/* Generate gain level table. */74for (i = 0; i < 16; i++)75gctx->gain_tab1[i] = powf(2.0, id2exp_offset - i);7677/* Generate gain interpolation table. */78for (i = -15; i < 16; i++)79gctx->gain_tab2[i + 15] = powf(2.0, -1.0f / gctx->loc_size * i);80}8182void ff_atrac_gain_compensation(AtracGCContext *gctx, float *in, float *prev,83AtracGainInfo *gc_now, AtracGainInfo *gc_next,84int num_samples, float *out)85{86float lev, gc_scale, gain_inc;87int i, pos, lastpos;8889gc_scale = gc_next->num_points ? gctx->gain_tab1[gc_next->lev_code[0]]90: 1.0f;9192if (!gc_now->num_points) {93for (pos = 0; pos < num_samples; pos++)94out[pos] = in[pos] * gc_scale + prev[pos];95} else {96pos = 0;9798for (i = 0; i < gc_now->num_points; i++) {99lastpos = gc_now->loc_code[i] << gctx->loc_scale;100101lev = gctx->gain_tab1[gc_now->lev_code[i]];102gain_inc = gctx->gain_tab2[(i + 1 < gc_now->num_points ? gc_now->lev_code[i + 1]103: gctx->id2exp_offset) -104gc_now->lev_code[i] + 15];105106/* apply constant gain level and overlap */107for (; pos < lastpos; pos++)108out[pos] = (in[pos] * gc_scale + prev[pos]) * lev;109110/* interpolate between two different gain levels */111for (; pos < lastpos + gctx->loc_size; pos++) {112out[pos] = (in[pos] * gc_scale + prev[pos]) * lev;113lev *= gain_inc;114}115}116117for (; pos < num_samples; pos++)118out[pos] = in[pos] * gc_scale + prev[pos];119}120121/* copy the overlapping part into the delay buffer */122memcpy(prev, &in[num_samples], num_samples * sizeof(float));123}124125void ff_atrac_iqmf(float *inlo, float *inhi, unsigned int nIn, float *pOut,126float *delayBuf, float *temp)127{128int i, j;129float *p1, *p3;130131memcpy(temp, delayBuf, 46*sizeof(float));132133p3 = temp + 46;134135/* loop1 */136for(i=0; i<(int)nIn; i+=2){137p3[2*i+0] = inlo[i ] + inhi[i ];138p3[2*i+1] = inlo[i ] - inhi[i ];139p3[2*i+2] = inlo[i+1] + inhi[i+1];140p3[2*i+3] = inlo[i+1] - inhi[i+1];141}142143/* loop2 */144p1 = temp;145for (j = (int)nIn; j != 0; j--) {146float s1 = 0.0;147float s2 = 0.0;148149for (i = 0; i < 48; i += 2) {150s1 += p1[i] * qmf_window[i];151s2 += p1[i+1] * qmf_window[i+1];152}153154pOut[0] = s2;155pOut[1] = s1;156157p1 += 2;158pOut += 2;159}160161/* Update the delay buffer. */162memcpy(delayBuf, temp + nIn*2, 46*sizeof(float));163}164165166