/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.media.codec.atrac3plus;
import static java.lang.Math.cos;
import static java.lang.Math.max;
import static java.lang.Math.pow;
import static java.lang.Math.sin;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.ATRAC3P_FRAME_SAMPLES;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.ATRAC3P_POWER_COMP_OFF;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.ATRAC3P_PQF_FIR_LEN;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.ATRAC3P_SUBBANDS;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.ATRAC3P_SUBBAND_SAMPLES;
import static jpcsp.media.codec.atrac3plus.Atrac3plusDecoder.CH_UNIT_STEREO;
import static jpcsp.media.codec.util.FloatDSP.vectorFmul;
import static jpcsp.media.codec.util.FloatDSP.vectorFmulReverse;
import static jpcsp.media.codec.util.SineWin.ff_sine_128;
import static jpcsp.media.codec.util.SineWin.ff_sine_64;
import java.util.Arrays;
import jpcsp.media.codec.atrac3plus.ChannelUnitContext.IPQFChannelContext;
import jpcsp.media.codec.util.FFT;
import jpcsp.media.codec.util.SineWin;
/*
* Based on the FFmpeg version from Maxim Poliakovski.
* All credits go to him.
*/
public class Atrac3plusDsp {
private static final int ATRAC3P_MDCT_SIZE = ATRAC3P_SUBBAND_SAMPLES * 2;
private static final float[] sine_table = new float[2048]; ///< wave table
private static final float[] hann_window = new float[256]; ///< Hann windowing function
private static final float[] amp_sf_tab = new float[64]; ///< scalefactors for quantized amplitudes
private static final double TWOPI = 2 * Math.PI;
/**
* Map quant unit number to its position in the spectrum.
* To get the number of spectral lines in each quant unit do the following:
* num_specs = qu_to_spec_pos[i+1] - qu_to_spec_pos[i]
*/
static final public int ff_atrac3p_qu_to_spec_pos[] = new int[] {
0, 16, 32, 48, 64, 80, 96, 112,
128, 160, 192, 224, 256, 288, 320, 352,
384, 448, 512, 576, 640, 704, 768, 896,
1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920,
2048
};
/* Scalefactors table. */
/* Approx. Equ: pow(2.0, (i - 16.0 + 0.501783948) / 3.0) */
static final public float ff_atrac3p_sf_tab[] = new float[] {
0.027852058f, 0.0350914f, 0.044212341f, 0.055704117f, 0.0701828f,
0.088424683f, 0.11140823f, 0.1403656f, 0.17684937f, 0.22281647f, 0.2807312f, 0.35369873f,
0.44563293f, 0.5614624f, 0.70739746f, 0.89126587f, 1.1229248f, 1.4147949f, 1.7825317f,
2.2458496f, 2.8295898f, 3.5650635f, 4.4916992f, 5.6591797f, 7.130127f, 8.9833984f,
11.318359f, 14.260254f, 17.966797f, 22.636719f, 28.520508f, 35.933594f, 45.273438f,
57.041016f, 71.867188f, 90.546875f, 114.08203f, 143.73438f, 181.09375f, 228.16406f,
287.46875f, 362.1875f, 456.32812f, 574.9375f, 724.375f, 912.65625f, 1149.875f,
1448.75f, 1825.3125f, 2299.75f, 2897.5f, 3650.625f, 4599.5f, 5795.0f,
7301.25f, 9199.0f, 11590.0f, 14602.5f, 18398.0f, 23180.0f, 29205.0f,
36796.0f, 46360.0f, 58410.0f
};
/* Mantissa table. */
/* pow(10, x * log10(2) + 0.05) / 2 / ([1,2,3,5,7,15,31] + 0.5) */
static final public float ff_atrac3p_mant_tab[] = new float[] {
0.0f,
0.74801636f,
0.44882202f,
0.32058716f,
0.20400238f,
0.1496048f,
0.07239151f,
0.035619736f
};
static final private int subband_to_powgrp[] = new int[] {
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4
};
/* noise table for power compensation */
static final private float noise_tab[] = new float[] {
-0.01358032f, -0.05593872f, 0.01696777f, -0.14871216f, -0.26412964f, -0.09893799f, 0.25723267f,
0.02008057f, -0.72235107f, -0.44351196f, -0.22985840f, 0.16833496f, 0.46902466f, 0.05917358f,
-0.15179443f, 0.41299438f, -0.01287842f, 0.13360596f, 0.43557739f, -0.09530640f, -0.58422852f,
0.39266968f, -0.08343506f, -0.25604248f, 0.22848511f, 0.26013184f, -0.65588379f, 0.17288208f,
-0.08673096f, -0.05203247f, 0.07299805f, -0.28665161f, -0.35806274f, 0.06552124f, -0.09387207f,
0.21099854f, -0.28347778f, -0.72402954f, 0.05050659f, -0.10635376f, -0.18853760f, 0.29724121f,
0.20703125f, -0.29791260f, -0.37634277f, 0.47970581f, -0.09976196f, 0.32641602f, -0.29248047f,
-0.28237915f, 0.26028442f, -0.36157227f, 0.22042847f, -0.03222656f, -0.37268066f, -0.03759766f,
0.09909058f, 0.23284912f, 0.19320679f, 0.14453125f, -0.02139282f, -0.19702148f, 0.31533813f,
-0.16741943f, 0.35031128f, -0.35656738f, -0.66128540f, -0.00701904f, 0.20898438f, 0.26837158f,
-0.33706665f, -0.04568481f, 0.12600708f, 0.10284424f, 0.07321167f, -0.18280029f, 0.38101196f,
0.21301270f, 0.04541016f, 0.01156616f, -0.26391602f, -0.02346802f, -0.22125244f, 0.29760742f,
-0.36233521f, -0.31314087f, -0.13967896f, -0.11276245f, -0.19433594f, 0.34490967f, 0.02343750f,
0.21963501f, -0.02777100f, -0.67678833f, -0.08999634f, 0.14233398f, -0.27697754f, 0.51422119f,
-0.05047607f, 0.48327637f, 0.37167358f, -0.60806274f, 0.18728638f, -0.15191650f, 0.00637817f,
0.02832031f, -0.15618896f, 0.60644531f, 0.21826172f, 0.06384277f, -0.31863403f, 0.08816528f,
0.15447998f, -0.07015991f, -0.08154297f, -0.40966797f, -0.39785767f, -0.11709595f, 0.22052002f,
0.18466187f, -0.17257690f, 0.03759766f, -0.06195068f, 0.00433350f, 0.12176514f, 0.34011841f,
0.25610352f, -0.05294800f, 0.41033936f, 0.16854858f, -0.76187134f, 0.13845825f, -0.19418335f,
-0.21524048f, -0.44412231f, -0.08160400f, -0.28195190f, -0.01873779f, 0.15524292f, -0.37438965f,
-0.44860840f, 0.43096924f, -0.24746704f, 0.49856567f, 0.14859009f, 0.38159180f, 0.20541382f,
-0.39175415f, -0.65850830f, -0.43716431f, 0.13037109f, -0.05111694f, 0.39956665f, 0.21447754f,
-0.04861450f, 0.33654785f, 0.10589600f, -0.88085938f, -0.30822754f, 0.38577271f, 0.30047607f,
0.38836670f, 0.09118652f, -0.36477661f, -0.01641846f, -0.23031616f, 0.26058960f, 0.18859863f,
-0.21868896f, -0.17861938f, -0.29754639f, 0.09777832f, 0.10806274f, -0.51605225f, 0.00076294f,
0.13259888f, 0.11090088f, -0.24084473f, 0.24957275f, 0.01379395f, -0.04141235f, -0.04937744f,
0.57394409f, 0.27410889f, 0.27587891f, 0.45013428f, -0.32592773f, 0.11160278f, -0.00970459f,
0.29092407f, 0.03356934f, -0.70925903f, 0.04882812f, 0.43499756f, 0.07720947f, -0.27554321f,
-0.01742554f, -0.08413696f, -0.04028320f, -0.52850342f, -0.07330322f, 0.05181885f, 0.21362305f,
-0.18765259f, 0.07058716f, -0.03009033f, 0.32662964f, 0.27023315f, -0.28002930f, 0.17568970f,
0.03338623f, 0.30242920f, -0.03921509f, 0.32174683f, -0.23733521f, 0.08575439f, -0.38269043f,
0.09194946f, -0.07238770f, 0.17941284f, -0.51278687f, -0.25146484f, 0.19790649f, -0.19195557f,
0.16549683f, 0.42456055f, 0.39129639f, -0.02868652f, 0.17980957f, 0.24902344f, -0.76583862f,
-0.20959473f, 0.61013794f, 0.37011719f, 0.36859131f, -0.04486084f, 0.10678101f, -0.15994263f,
-0.05328369f, 0.28463745f, -0.06420898f, -0.36987305f, -0.28009033f, -0.11764526f, 0.04312134f,
-0.08038330f, 0.04885864f, -0.03067017f, -0.00042725f, 0.34289551f, -0.00988770f, 0.34838867f,
0.32516479f, -0.16271973f, 0.38269043f, 0.03240967f, 0.12417603f, -0.14331055f, -0.34902954f,
-0.18325806f, 0.29421997f, 0.44284058f, 0.75170898f, -0.67245483f, -0.12176514f, 0.27914429f,
-0.29806519f, 0.19863892f, 0.30087280f, 0.22680664f, -0.36633301f, -0.32534790f, -0.57553101f,
-0.16641235f, 0.43811035f, 0.08331299f, 0.15942383f, 0.26516724f, -0.24240112f, -0.11761475f,
-0.16827393f, -0.14260864f, 0.46343994f, 0.11804199f, -0.55514526f, -0.02520752f, -0.14309692f,
0.00448608f, 0.02749634f, -0.30545044f, 0.70965576f, 0.45108032f, 0.66439819f, -0.68255615f,
-0.12496948f, 0.09146118f, -0.21109009f, -0.23791504f, 0.79943848f, -0.35205078f, -0.24963379f,
0.18719482f, -0.19079590f, 0.07458496f, 0.07623291f, -0.28781128f, -0.37121582f, -0.19580078f,
-0.01773071f, -0.16717529f, 0.13040161f, 0.14672852f, 0.42379761f, 0.03582764f, 0.11431885f,
0.05145264f, 0.44702148f, 0.08963013f, 0.01367188f, -0.54519653f, -0.12692261f, 0.21176147f,
0.04925537f, 0.30670166f, -0.11029053f, 0.19555664f, -0.27740479f, 0.23043823f, 0.15554810f,
-0.19299316f, -0.25729370f, 0.17800903f, -0.03579712f, -0.05065918f, -0.06933594f, -0.09500122f,
-0.07821655f, 0.23889160f, -0.31900024f, 0.03073120f, -0.00415039f, 0.61315918f, 0.37176514f,
-0.13442993f, -0.15536499f, -0.19216919f, -0.37899780f, 0.19992065f, 0.02630615f, -0.12573242f,
0.25927734f, -0.02447510f, 0.29629517f, -0.40731812f, -0.17333984f, 0.24310303f, -0.10607910f,
0.14828491f, 0.08792114f, -0.18743896f, -0.05572510f, -0.04833984f, 0.10473633f, -0.29028320f,
-0.67687988f, -0.28170776f, -0.41687012f, 0.05413818f, -0.23284912f, 0.09555054f, -0.08969116f,
-0.15112305f, 0.12738037f, 0.35986328f, 0.28948975f, 0.30691528f, 0.23956299f, 0.06973267f,
-0.31198120f, -0.18450928f, 0.22280884f, -0.21600342f, 0.23522949f, -0.61840820f, -0.13012695f,
0.26412964f, 0.47320557f, -0.26440430f, 0.38757324f, 0.17352295f, -0.26104736f, -0.25866699f,
-0.12274170f, -0.29733276f, 0.07687378f, 0.18588257f, -0.08880615f, 0.31185913f, 0.05313110f,
-0.10885620f, -0.14901733f, -0.22323608f, -0.08538818f, 0.19812012f, 0.19732666f, -0.18927002f,
0.29058838f, 0.25555420f, -0.48599243f, 0.18768311f, 0.01345825f, 0.34887695f, 0.21530151f,
0.19857788f, 0.18661499f, -0.01394653f, -0.09063721f, -0.38781738f, 0.27160645f, -0.20379639f,
-0.32119751f, -0.23889160f, 0.27096558f, 0.24951172f, 0.07922363f, 0.07479858f, -0.50946045f,
0.10220337f, 0.58364868f, -0.19503784f, -0.18560791f, -0.01165771f, 0.47195435f, 0.22430420f,
-0.38635254f, -0.03732300f, -0.09179688f, 0.06991577f, 0.15106201f, 0.20605469f, -0.05969238f,
-0.41821289f, 0.12231445f, -0.04672241f, -0.05117798f, -0.11523438f, -0.51849365f, -0.04077148f,
0.44284058f, -0.64086914f, 0.17019653f, 0.02236938f, 0.22848511f, -0.23214722f, -0.32354736f,
-0.14068604f, -0.29690552f, -0.19891357f, 0.02774048f, -0.20965576f, -0.52191162f, -0.19299316f,
-0.07290649f, 0.49053955f, -0.22302246f, 0.05642700f, 0.13122559f, -0.20819092f, -0.83590698f,
-0.08181763f, 0.26797485f, -0.00091553f, -0.09457397f, 0.17089844f, -0.27020264f, 0.30270386f,
0.05496216f, 0.09564209f, -0.08590698f, 0.02130127f, 0.35931396f, 0.21728516f, -0.15396118f,
-0.05053711f, 0.02719116f, 0.16302490f, 0.43212891f, 0.10229492f, -0.40820312f, 0.21646118f,
0.08435059f, -0.11145020f, -0.39962769f, -0.05618286f, -0.10223389f, -0.60839844f, 0.33724976f,
-0.06341553f, -0.47369385f, -0.32852173f, 0.05242920f, 0.19635010f, -0.19137573f, -0.67901611f,
0.16180420f, 0.05133057f, -0.22283936f, 0.09646606f, 0.24288940f, -0.45007324f, 0.08804321f,
0.14053345f, 0.22619629f, -0.01000977f, 0.36355591f, -0.19863892f, -0.30364990f, -0.24118042f,
-0.57461548f, 0.26498413f, 0.04345703f, -0.09796143f, -0.47714233f, -0.23739624f, 0.18737793f,
0.08926392f, -0.02795410f, 0.00305176f, -0.08700562f, -0.38711548f, 0.03222656f, 0.10940552f,
-0.41906738f, -0.01620483f, -0.47061157f, 0.37985229f, -0.21624756f, 0.47976685f, -0.20046997f,
-0.62533569f, -0.26907349f, -0.02877808f, 0.00671387f, -0.29071045f, -0.24685669f, -0.15722656f,
-0.26055908f, 0.29968262f, 0.28225708f, -0.08990479f, -0.16748047f, -0.46759033f, -0.25067139f,
-0.25183105f, -0.45932007f, 0.05828857f, 0.29006958f, 0.23840332f, -0.17974854f, 0.26931763f,
0.10696411f, -0.06848145f, -0.17126465f, -0.10522461f, -0.55386353f, -0.42306519f, -0.07608032f,
0.24380493f, 0.38586426f, 0.16882324f, 0.26751709f, 0.17303467f, 0.35809326f, -0.22094727f,
-0.30703735f, -0.28497314f, -0.04321289f, 0.15219116f, -0.17071533f, -0.39334106f, 0.03439331f,
-0.10809326f, -0.30590820f, 0.26449585f, -0.07412720f, 0.13638306f, -0.01062012f, 0.27996826f,
0.04397583f, -0.05557251f, -0.56933594f, 0.03363037f, -0.00949097f, 0.52642822f, -0.44329834f,
0.28308105f, -0.05499268f, -0.23312378f, -0.29870605f, -0.05123901f, 0.26831055f, -0.35238647f,
-0.30993652f, 0.34646606f, -0.19775391f, 0.44595337f, 0.13769531f, 0.45358276f, 0.19961548f,
0.42681885f, 0.15722656f, 0.00128174f, 0.23757935f, 0.40988159f, 0.25164795f, -0.00732422f,
-0.12405396f, -0.43420410f, -0.00402832f, 0.34243774f, 0.36264038f, 0.18807983f, -0.09301758f,
-0.10296631f, 0.05532837f, -0.31652832f, 0.14337158f, 0.35040283f, 0.32540894f, 0.05728149f,
-0.12030029f, -0.25942993f, -0.20312500f, -0.16491699f, -0.46051025f, -0.08004761f, 0.50772095f,
0.16168213f, 0.28439331f, 0.08105469f, -0.19104004f, 0.38589478f, -0.16400146f, -0.25454712f,
0.20281982f, -0.20730591f, -0.06311035f, 0.32937622f, 0.15032959f, -0.05340576f, 0.30487061f,
-0.11648560f, 0.38009644f, -0.20062256f, 0.43466187f, 0.01150513f, 0.35754395f, -0.13146973f,
0.67489624f, 0.05212402f, 0.27914429f, -0.39431763f, 0.75308228f, -0.13366699f, 0.24453735f,
0.42248535f, -0.65905762f, -0.00546265f, -0.03491211f, -0.13659668f, -0.08294678f, -0.45666504f,
0.27188110f, 0.12731934f, 0.61148071f, 0.10449219f, -0.28836060f, 0.00091553f, 0.24618530f,
0.13119507f, 0.05685425f, 0.17355347f, 0.42034912f, 0.08514404f, 0.24536133f, 0.18951416f,
-0.19107056f, -0.15036011f, 0.02334595f, 0.54986572f, 0.32321167f, -0.16104126f, -0.03054810f,
0.43594360f, 0.17309570f, 0.61053467f, 0.24731445f, 0.33334351f, 0.15240479f, 0.15588379f,
0.36425781f, -0.30407715f, -0.13302612f, 0.00427246f, 0.04171753f, -0.33178711f, 0.34216309f,
-0.12463379f, -0.02764893f, 0.05905151f, -0.31436157f, 0.16531372f, 0.34542847f, -0.03292847f,
0.12527466f, -0.12313843f, -0.13171387f, 0.04757690f, -0.45095825f, -0.19085693f, 0.35342407f,
-0.23239136f, -0.34387207f, 0.11264038f, -0.15740967f, 0.05273438f, 0.74942017f, 0.21505737f,
0.08514404f, -0.42391968f, -0.19531250f, 0.35293579f, 0.25305176f, 0.15731812f, -0.70324707f,
-0.21591187f, 0.35604858f, 0.14132690f, 0.11724854f, 0.15853882f, -0.24597168f, 0.07019043f,
0.02127075f, 0.12658691f, 0.06390381f, -0.12292480f, 0.15441895f, -0.47640991f, 0.06195068f,
0.58981323f, -0.15151978f, -0.03604126f, -0.45059204f, -0.01672363f, -0.46997070f, 0.25750732f,
0.18084717f, 0.06661987f, 0.13253784f, 0.67828369f, 0.11370850f, 0.11325073f, -0.04611206f,
-0.07791138f, -0.36544800f, -0.06747437f, -0.31594849f, 0.16131592f, 0.41983032f, 0.11071777f,
-0.36889648f, 0.30963135f, -0.37875366f, 0.58508301f, 0.00393677f, 0.12338257f, 0.03424072f,
-0.21728516f, -0.12838745f, -0.46981812f, 0.05868530f, -0.25015259f, 0.27407837f, 0.65240479f,
-0.34429932f, -0.15179443f, 0.14056396f, 0.33505249f, 0.28826904f, 0.09921265f, 0.34390259f,
0.13656616f, -0.23608398f, 0.00863647f, 0.02627563f, -0.19119263f, 0.19775391f, -0.07214355f,
0.07809448f, 0.03454590f, -0.03417969f, 0.00033569f, -0.23095703f, 0.18673706f, 0.05798340f,
0.03814697f, -0.04318237f, 0.05487061f, 0.08633423f, 0.55950928f, -0.06347656f, 0.10333252f,
0.25305176f, 0.05853271f, 0.12246704f, -0.25543213f, -0.34262085f, -0.36437988f, -0.21304321f,
-0.05093384f, 0.02777100f, 0.07620239f, -0.21215820f, -0.09326172f, 0.19021606f, -0.40579224f,
-0.01193237f, 0.19845581f, -0.35336304f, -0.07397461f, 0.20104980f, 0.08615112f, -0.44375610f,
0.11419678f, 0.24453735f, -0.16555786f, -0.05081177f, -0.01406860f, 0.27893066f, -0.18692017f,
0.07473755f, 0.03451538f, -0.39733887f, 0.21548462f, -0.22534180f, -0.39651489f, -0.04989624f,
-0.57662964f, 0.06390381f, 0.62020874f, -0.13470459f, 0.04345703f, -0.21862793f, -0.02789307f,
0.51696777f, -0.27587891f, 0.39004517f, 0.09857178f, -0.00738525f, 0.31317139f, 0.00048828f,
-0.46572876f, 0.29531860f, -0.10009766f, -0.27856445f, 0.03594971f, 0.25048828f, -0.74584961f,
-0.25350952f, -0.03302002f, 0.31188965f, 0.01571655f, 0.46710205f, 0.21591187f, 0.07260132f,
-0.42132568f, -0.53900146f, -0.13674927f, -0.16571045f, -0.34454346f, 0.12359619f, -0.11184692f,
0.00967407f, 0.34576416f, -0.05761719f, 0.34848022f, 0.17645264f, -0.39395142f, 0.10339355f,
0.18215942f, 0.20697021f, 0.59109497f, -0.11560059f, -0.07385254f, 0.10397339f, 0.35437012f,
-0.22863770f, 0.01794434f, 0.17559814f, -0.17495728f, 0.12142944f, 0.10928345f, -1.00000000f,
-0.01379395f, 0.21237183f, -0.27035522f, 0.27319336f, -0.37066650f, 0.41354370f, -0.40054321f,
0.00689697f, 0.26321411f, 0.39266968f, 0.65298462f, 0.41625977f, -0.13909912f, 0.78375244f,
-0.30941772f, 0.20169067f, -0.39367676f, 0.94021606f, -0.24066162f, 0.05557251f, -0.24533081f,
-0.05444336f, -0.76754761f, -0.19375610f, -0.11041260f, -0.17532349f, 0.16006470f, 0.02188110f,
0.17465210f, -0.04342651f, -0.56777954f, -0.40988159f, 0.26687622f, 0.11700439f, -0.00344849f,
-0.05395508f, 0.37426758f, -0.40719604f, -0.15032959f, -0.01660156f, 0.04196167f, -0.04559326f,
-0.12969971f, 0.12011719f, 0.08419800f, -0.11199951f, 0.35174561f, 0.10275269f, -0.25686646f,
0.48446655f, 0.03225708f, 0.28408813f, -0.18701172f, 0.36282349f, -0.03280640f, 0.32302856f,
0.17233276f, 0.48269653f, 0.31112671f, -0.04946899f, 0.12774658f, 0.52685547f, 0.10211182f,
0.05953979f, 0.05999756f, 0.20144653f, 0.00744629f, 0.27316284f, 0.24377441f, 0.39672852f,
0.01702881f, -0.35513306f, 0.11364746f, -0.13555908f, 0.48880005f, -0.15417480f, -0.09149170f,
-0.02615356f, 0.46246338f, -0.72250366f, 0.22332764f, 0.23849487f, -0.25686646f, -0.08514404f,
-0.02062988f, -0.34494019f, -0.02297974f, -0.80386353f, -0.08074951f, -0.12689209f, -0.06896973f,
0.24099731f, -0.35650635f, -0.09558105f, 0.29254150f, 0.23132324f, -0.16726685f, 0.00000000f,
-0.24237061f, 0.30899048f, 0.29504395f, -0.20898438f, 0.17059326f, -0.07672119f, -0.14395142f,
0.05572510f, 0.20602417f, -0.51550293f, -0.03167725f, -0.48840332f, -0.20425415f, 0.14144897f,
0.07275391f, -0.76669312f, -0.22488403f, 0.20651245f, 0.03259277f, 0.00085449f, 0.03039551f,
0.47555542f, 0.38351440f
};
/** Noise level table for power compensation.
* Equ: pow(2.0f, (double)(6 - i) / 3.0f) where i = 0...15 */
static final private float pwc_levs[] = new float[] {
3.96875f, 3.15625f, 2.5f, 2.0f, 1.59375f, 1.25f, 1.0f, 0.78125f,
0.625f, 0.5f, 0.40625f, 0.3125f, 0.25f, 0.1875f, 0.15625f, 0.0f
};
/** Map subband number to quant unit number. */
static final private int subband_to_qu[] = new int[] {
0, 8, 12, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
};
/* lookup table for fast modulo 23 op required for cyclic buffers of the IPQF */
static final int mod23_lut[] = new int[] {
23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0
};
// First half of the 384-tap IPQF filtering coefficients.
static final float ipqf_coeffs1[][] = new float[][] {
{ -5.8336207e-7f, -8.0604229e-7f, -4.2005411e-7f, -4.4400572e-8f,
3.226247e-8f, 3.530856e-8f, 1.2660377e-8f, 0.000010516783f,
-0.000011838618f, 6.005389e-7f, 0.0000014333754f, 0.0000023108685f,
0.0000032569742f, 0.0000046192422f, 0.0000063894258f, 0.0000070302972f },
{ -0.0000091622824f, -0.000010502935f, -0.0000079212787f, -0.0000041712024f,
-0.0000026336629f, -0.0000015432918f, -5.7168614e-7f, 0.0000018111954f,
0.000023530851f, 0.00002780562f, 0.000032302323f, 0.000036968919f,
0.000041575615f, 0.000045337845f, 0.000046043948f, 0.000048585582f },
{ -0.000064464548f, -0.000068306952f, -0.000073081472f, -0.00007612785f,
-0.000074850752f, -0.000070208509f, -0.000062285151f, -0.000058270442f,
-0.000056296329f, -0.000049888811f, -0.000035615325f, -0.000018532943f,
0.0000016657353f, 0.00002610587f, 0.000053397067f, 0.00008079566f },
{ -0.00054488552f, -0.00052537228f, -0.00049731287f, -0.00045778f,
-0.00040612387f, -0.00034301577f, -0.00026866337f, -0.00018248901f,
-0.000084307925f, 0.000025081157f, 0.00014135583f, 0.00026649953f,
0.00039945057f, 0.00053928449f, 0.00068422867f, 0.00083093712f },
{ -0.0014771431f, -0.001283227f, -0.0010566821f, -0.00079780724f,
-0.00050782406f, -0.00018855913f, 0.00015771533f, 0.00052769453f,
0.00091862219f, 0.001326357f, 0.0017469483f, 0.0021754825f,
0.0026067684f, 0.0030352892f, 0.0034549395f, 0.0038591374f },
{ -0.0022995141f, -0.001443546f, -0.00049266568f, 0.00055068987f,
0.001682895f, 0.0028992873f, 0.0041943151f, 0.0055614738f,
0.0069935122f, 0.0084823566f, 0.010018963f, 0.011593862f,
0.013196872f, 0.014817309f, 0.016444042f, 0.018065533f },
{ -0.034426283f, -0.034281436f, -0.033992987f, -0.033563249f,
-0.032995768f, -0.032295227f, -0.031467363f, -0.030518902f,
-0.02945766f, -0.028291954f, -0.027031265f, -0.025685543f,
-0.024265358f, -0.022781773f, -0.021246184f, -0.019670162f },
{ -0.0030586775f, -0.0037203205f, -0.0042847847f, -0.0047529764f,
-0.0051268316f, -0.0054091476f, -0.0056034233f, -0.005714261f,
-0.0057445862f, -0.0057025906f, -0.0055920109f, -0.0054194843f,
-0.0051914565f, -0.0049146507f, -0.0045959447f, -0.0042418269f },
{ -0.0016376863f, -0.0017651899f, -0.0018608454f, -0.0019252141f,
-0.0019593791f, -0.0019653172f, -0.0019450618f, -0.0018990048f,
-0.00183808f, -0.0017501717f, -0.0016481078f, -0.0015320742f,
-0.0014046903f, -0.0012685474f, -0.001125814f, -0.00097943726f },
{ -0.00055432378f, -0.00055472925f, -0.00054783461f, -0.00053276919f,
-0.00051135791f, -0.00048466062f, -0.00045358928f, -0.00042499689f,
-0.00036942671f, -0.0003392619f, -0.00030001783f, -0.00025986304f,
-0.0002197204f, -0.00018116167f, -0.00014691355f, -0.00011279432f },
{ -0.000064147389f, -0.00006174868f, -0.000054267788f, -0.000047133824f,
-0.000042927582f, -0.000039477309f, -0.000036340745f, -0.000029687517f,
-0.000049787737f, -0.000041577889f, -0.000033864744f, -0.000026534748f,
-0.000019841305f, -0.000014789486f, -0.000013131184f, -0.0000099198869f },
{ -0.0000062990207f, -0.0000072701259f, -0.000011984052f, -0.000017348082f,
-0.000019907106f, -0.000021348773f, -0.000021961965f, -0.000012203576f,
-0.000010840992f, 4.6299544e-7f, 5.2588763e-7f, 2.7792686e-7f,
-2.3649704e-7f, -0.0000010897784f, -9.171448e-7f, -5.22682e-7f }
};
// Second half of the 384-tap IPQF filtering coefficients.
static final float ipqf_coeffs2[][] = new float[][] {
{ 5.22682e-7f, 9.171448e-7f, 0.0000010897784f, 2.3649704e-7f,
-2.7792686e-7f, -5.2588763e-7f, -4.6299544e-7f, 0.000010840992f,
-0.000012203576f, -0.000021961965f, -0.000021348773f, -0.000019907106f,
-0.000017348082f, -0.000011984052f, -0.0000072701259f, -0.0000062990207f },
{ 0.0000099198869f, 0.000013131184f, 0.000014789486f, 0.000019841305f,
0.000026534748f, 0.000033864744f, 0.000041577889f, 0.000049787737f,
-0.000029687517f, -0.000036340745f, -0.000039477309f, -0.000042927582f,
-0.000047133824f, -0.000054267788f, -0.00006174868f, -0.000064147389f },
{ 0.00011279432f, 0.00014691355f, 0.00018116167f, 0.0002197204f,
0.00025986304f, 0.00030001783f, 0.0003392619f, 0.00036942671f,
-0.00042499689f, -0.00045358928f, -0.00048466062f, -0.00051135791f,
-0.00053276919f, -0.00054783461f, -0.00055472925f, -0.00055432378f },
{ 0.00097943726f, 0.001125814f, 0.0012685474f, 0.0014046903f,
0.0015320742f, 0.0016481078f, 0.0017501717f, 0.00183808f,
-0.0018990048f, -0.0019450618f, -0.0019653172f, -0.0019593791f,
-0.0019252141f, -0.0018608454f, -0.0017651899f, -0.0016376863f },
{ 0.0042418269f, 0.0045959447f, 0.0049146507f, 0.0051914565f,
0.0054194843f, 0.0055920109f, 0.0057025906f, 0.0057445862f,
-0.005714261f, -0.0056034233f, -0.0054091476f, -0.0051268316f,
-0.0047529764f, -0.0042847847f, -0.0037203205f, -0.0030586775f },
{ 0.019670162f, 0.021246184f, 0.022781773f, 0.024265358f,
0.025685543f, 0.027031265f, 0.028291954f, 0.02945766f,
-0.030518902f, -0.031467363f, -0.032295227f, -0.032995768f,
-0.033563249f, -0.033992987f, -0.034281436f, -0.034426283f },
{ -0.018065533f, -0.016444042f, -0.014817309f, -0.013196872f,
-0.011593862f, -0.010018963f, -0.0084823566f, -0.0069935122f,
0.0055614738f, 0.0041943151f, 0.0028992873f, 0.001682895f,
0.00055068987f, -0.00049266568f, -0.001443546f, -0.0022995141f },
{ -0.0038591374f, -0.0034549395f, -0.0030352892f, -0.0026067684f,
-0.0021754825f, -0.0017469483f, -0.001326357f, -0.00091862219f,
0.00052769453f, 0.00015771533f, -0.00018855913f, -0.00050782406f,
-0.00079780724f, -0.0010566821f, -0.001283227f, -0.0014771431f },
{ -0.00083093712f, -0.00068422867f, -0.00053928449f, -0.00039945057f,
-0.00026649953f, -0.00014135583f, -0.000025081157f, 0.000084307925f,
-0.00018248901f, -0.00026866337f, -0.00034301577f, -0.00040612387f,
-0.00045778f, -0.00049731287f, -0.00052537228f, -0.00054488552f },
{ -0.00008079566f, -0.000053397067f, -0.00002610587f, -0.0000016657353f,
0.000018532943f, 0.000035615325f, 0.000049888811f, 0.000056296329f,
-0.000058270442f, -0.000062285151f, -0.000070208509f, -0.000074850752f,
-0.00007612785f, -0.000073081472f, -0.000068306952f, -0.000064464548f },
{ -0.000048585582f, -0.000046043948f, -0.000045337845f, -0.000041575615f,
-0.000036968919f, -0.000032302323f, -0.00002780562f, -0.000023530851f,
0.0000018111954f, -5.7168614e-7f, -0.0000015432918f, -0.0000026336629f,
-0.0000041712024f, -0.0000079212787f, -0.000010502935f, -0.0000091622824f },
{ -0.0000070302972f, -0.0000063894258f, -0.0000046192422f, -0.0000032569742f,
-0.0000023108685f, -0.0000014333754f, -6.005389e-7f, 0.000011838618f,
0.000010516783f, 1.2660377e-8f, 3.530856e-8f, 3.226247e-8f,
-4.4400572e-8f, -4.2005411e-7f, -8.0604229e-7f, -5.8336207e-7f }
};
private static int DEQUANT_PHASE(int ph) {
return (ph & 0x1F) << 6;
}
public void initImdct(FFT mdctCtx) {
SineWin.initFfSineWindows();
// Initialize the MDCT transform
mdctCtx.mdctInit(8, true, -1.0);
}
public static void initWaveSynth() {
// generate sine wave table
for (int i = 0; i < 2048; i++) {
sine_table[i] = (float) sin(TWOPI * i / 2048);
}
// generate Hann window
for (int i = 0; i < 256; i++) {
hann_window[i] = (float) ((1.0 - cos(TWOPI * i / 256)) * 0.5);
}
// generate amplitude scalefactors table
for (int i = 0; i < 64; i++) {
amp_sf_tab[i] = (float) pow(2.0, ((double) (i - 3)) / 4.0);
}
}
public void powerCompensation(ChannelUnitContext ctx, int chIndex, float[] sp, int rngIndex, int sb) {
float pwcsp[] = new float[ATRAC3P_SUBBAND_SAMPLES];
int gcv = 0;
int swapCh = (ctx.unitType == CH_UNIT_STEREO && ctx.swapChannels[sb] ? 1 : 0);
if (ctx.channels[chIndex ^ swapCh].powerLevs[subband_to_powgrp[sb]] == ATRAC3P_POWER_COMP_OFF) {
return;
}
// generate initial noise spectrum
for (int i = 0; i < ATRAC3P_SUBBAND_SAMPLES; i++, rngIndex++) {
pwcsp[i] = noise_tab[rngIndex & 0x3FF];
}
// check gain control information
AtracGainInfo g1 = ctx.channels[chIndex ^ swapCh].gainData[sb];
AtracGainInfo g2 = ctx.channels[chIndex ^ swapCh].gainDataPrev[sb];
int gainLev = (g1.numPoints > 0 ? (6 - g1.levCode[0]) : 0);
for (int i = 0; i < g2.numPoints; i++) {
gcv = max(gcv, gainLev - (g2.levCode[i] - 6));
}
for (int i = 0; i < g1.numPoints; i++) {
gcv = max(gcv, 6 - g1.levCode[i]);
}
float grpLev = pwc_levs[ctx.channels[chIndex ^ swapCh].powerLevs[subband_to_powgrp[sb]]] / (1 << gcv);
// skip the lowest two quant units (frequencies 0...351 Hz) for subband 0
for (int qu = subband_to_qu[sb] + (sb == 0 ? 2 : 0); qu < subband_to_qu[sb + 1]; qu++) {
if (ctx.channels[chIndex].quWordlen[qu] <= 0) {
continue;
}
float quLev = ff_atrac3p_sf_tab[ctx.channels[chIndex].quSfIdx[qu]] * ff_atrac3p_mant_tab[ctx.channels[chIndex].quWordlen[qu]] / (1 << ctx.channels[chIndex].quWordlen[qu]) * grpLev;
int dst = ff_atrac3p_qu_to_spec_pos[qu];
int nsp = ff_atrac3p_qu_to_spec_pos[qu + 1] - ff_atrac3p_qu_to_spec_pos[qu];
for (int i = 0; i < nsp; i++) {
sp[dst + i] += pwcsp[i] * quLev;
}
}
}
public void imdct(FFT mdctCtx, float in[], int inOffset, float out[], int outOffset, int windId, int sb) {
if ((sb & 1) != 0) {
for (int i = 0; i < ATRAC3P_SUBBAND_SAMPLES / 2; i++) {
float tmp = in[inOffset + i];
in[inOffset + i] = in[inOffset + ATRAC3P_SUBBAND_SAMPLES - 1 - i];
in[inOffset + ATRAC3P_SUBBAND_SAMPLES - 1 - i] = tmp;
}
}
mdctCtx.imdctCalc(out, outOffset, in, inOffset);
/* Perform windowing on the output.
* ATRAC3+ uses two different MDCT windows:
* - The first one is just the plain sine window of size 256
* - The 2nd one is the plain sine window of size 128
* wrapped into zero (at the start) and one (at the end) regions.
* Both regions are 32 samples long. */
if ((windId & 2) != 0) { // 1st half: steep window
Arrays.fill(out, outOffset, outOffset + 32, 0f);
vectorFmul(out, outOffset + 32, out, outOffset + 32, ff_sine_64, 0, 64);
} else { // 1st halt: simple sine window
vectorFmul(out, outOffset, out, outOffset, ff_sine_128, 0, ATRAC3P_MDCT_SIZE / 2);
}
if ((windId & 1) != 0) { // 2nd half: steep window
vectorFmulReverse(out, outOffset + 160, out, outOffset + 160, ff_sine_64, 0, 64);
Arrays.fill(out, outOffset + 224, outOffset + 224 + 32, 0f);
} else { // 2nd half: simple sine window
vectorFmulReverse(out, outOffset + 128, out, outOffset + 128, ff_sine_128, 0, ATRAC3P_MDCT_SIZE / 2);
}
}
/**
* Synthesize sine waves according to given parameters.
*
* @param[in] synthParam common synthesis parameters
* @param[in] wavesInfo parameters for each sine wave
* @param[in] envelope envelope data for all waves in a group
* @param[in] phaseShift flag indicates 180 degrees phase shift
* @param[in] regOffset region offset for trimming envelope data
* @param[out] out receives synthesized data
*/
private void wavesSynth(WaveSynthParams synthParams, WavesData wavesInfo, WaveEnvelope envelope, boolean phaseShift, int regOffset, float[] out) {
int waveParam = wavesInfo.startIndex;
for (int wn = 0; wn < wavesInfo.numWavs; wn++, waveParam++) {
// amplitude dequantization
double amp = amp_sf_tab[synthParams.waves[waveParam].ampSf] * (synthParams.amplitudeMode == 0 ? (synthParams.waves[waveParam].ampIndex + 1) / 15.13f : 1.0f);
int inc = synthParams.waves[waveParam].freqIndex;
int pos = DEQUANT_PHASE(synthParams.waves[waveParam].phaseIndex) - (regOffset ^ 128) * inc & 2047;
// waveform generation
for (int i = 0; i < 128; i++) {
out[i] += sine_table[pos] * amp;
pos = (pos + inc) & 2047;
}
}
if (phaseShift) {
// 180 degrees phase shift
for (int i = 0; i < 128; i++) {
out[i] = -out[i];
}
}
// fade in with steep Hann window if requested
if (envelope.hasStartPoint) {
int pos = (envelope.startPos << 2) - regOffset;
if (pos > 0 && pos <= 128) {
Arrays.fill(out, 0, pos, 0f);
if (!envelope.hasStopPoint || envelope.startPos != envelope.stopPos) {
out[pos + 0] *= hann_window[ 0];
out[pos + 1] *= hann_window[32];
out[pos + 2] *= hann_window[64];
out[pos + 3] *= hann_window[96];
}
}
}
// fade out with steep Hann window if requested
if (envelope.hasStopPoint) {
int pos = (envelope.stopPos + 1 << 2) - regOffset;
if (pos > 0 && pos <= 128) {
out[pos - 4] *= hann_window[96];
out[pos - 3] *= hann_window[64];
out[pos - 2] *= hann_window[32];
out[pos - 1] *= hann_window[ 0];
Arrays.fill(out, pos, 128, 0f);
}
}
}
public void generateTones(ChannelUnitContext ctx, int chNum, int sb, float out[], int outOffset) {
float[] wavreg1 = new float[128];
float[] wavreg2 = new float[128];
WavesData tonesNow = ctx.channels[chNum].tonesInfoPrev[sb];
WavesData tonesNext = ctx.channels[chNum].tonesInfo[sb];
// reconstruct full envelopes for both overlapping regions
// from truncated bitstream data
if (tonesNext.pendEnv.hasStartPoint && tonesNext.pendEnv.startPos < tonesNext.pendEnv.stopPos) {
tonesNext.currEnv.hasStartPoint = true;
tonesNext.currEnv.startPos = tonesNext.pendEnv.startPos + 32;
} else if (tonesNow.pendEnv.hasStartPoint) {
tonesNext.currEnv.hasStartPoint = true;
tonesNext.currEnv.startPos = tonesNow.pendEnv.startPos;
} else {
tonesNext.currEnv.hasStartPoint = false;
tonesNext.currEnv.startPos = 0;
}
if (tonesNow.pendEnv.hasStopPoint && tonesNow.pendEnv.stopPos >= tonesNext.currEnv.startPos) {
tonesNext.currEnv.hasStopPoint = true;
tonesNext.currEnv.stopPos = tonesNow.pendEnv.stopPos;
} else if (tonesNext.pendEnv.hasStopPoint) {
tonesNext.currEnv.hasStopPoint = true;
tonesNext.currEnv.stopPos = tonesNext.pendEnv.stopPos + 32;
} else {
tonesNext.currEnv.hasStopPoint = false;
tonesNext.currEnv.stopPos = 64;
}
// is the visible part of the envelope non-zero?
boolean reg1EnvNonzero = (tonesNow.currEnv.stopPos < 32 ? false : true);
boolean reg2EnvNonzero = (tonesNext.currEnv.startPos >= 32 ? false : true);
// synthesize waves for both overlapping regions
if (tonesNow.numWavs > 0 && reg1EnvNonzero) {
wavesSynth(ctx.wavesInfoPrev, tonesNow, tonesNow.currEnv, ctx.wavesInfoPrev.phaseShift[sb] && (chNum > 0), 128, wavreg1);
}
if (tonesNext.numWavs > 0 && reg2EnvNonzero) {
wavesSynth(ctx.wavesInfo, tonesNext, tonesNext.currEnv, ctx.wavesInfo.phaseShift[sb] && (chNum > 0), 0, wavreg2);
}
// Hann windowing for non-faded wave signals
if (tonesNow.numWavs > 0 && tonesNext.numWavs > 0 && reg1EnvNonzero && reg2EnvNonzero) {
vectorFmul(wavreg1, 0, wavreg1, 0, hann_window, 128, 128);
vectorFmul(wavreg2, 0, wavreg2, 0, hann_window, 0, 128);
} else {
if (tonesNow.numWavs > 0 && !tonesNow.currEnv.hasStopPoint) {
vectorFmul(wavreg1, 0, wavreg1, 0, hann_window, 128, 128);
}
if (tonesNext.numWavs > 0 && !tonesNext.currEnv.hasStartPoint) {
vectorFmul(wavreg2, 0, wavreg2, 0, hann_window, 0, 128);
}
}
// Overlap and add to residual
for (int i = 0; i < 128; i++) {
out[outOffset + i] += wavreg1[i] + wavreg2[i];
}
}
public void ipqf(FFT dctCtx, IPQFChannelContext hist, float[] in, float[] out) {
float[] idctIn = new float[ATRAC3P_SUBBANDS];
float[] idctOut = new float[ATRAC3P_SUBBANDS];
Arrays.fill(out, 0, ATRAC3P_FRAME_SAMPLES, 0f);
for (int s = 0; s < ATRAC3P_SUBBAND_SAMPLES; s++) {
// pack up one sample from each subband
for (int sb = 0; sb < ATRAC3P_SUBBANDS; sb++) {
idctIn[sb] = in[sb * ATRAC3P_SUBBAND_SAMPLES + s];
}
// Calculate the sine and cosine part of the PQF using IDCT-IV
dctCtx.imdctHalf(idctOut, 0, idctIn, 0);
// append the result to the history
for (int i = 0; i < 8; i++) {
hist.buf1[hist.pos][i] = idctOut[i + 8];
hist.buf2[hist.pos][i] = idctOut[7 - i];
}
int posNow = hist.pos;
int posNext = mod23_lut[posNow + 2]; // posNext = (posNow + 1) % 23
for (int t = 0; t < ATRAC3P_PQF_FIR_LEN; t++) {
for (int i = 0; i < 8; i++) {
out[s * 16 + i + 0] += hist.buf1[posNow][i] * ipqf_coeffs1[t][i] + hist.buf2[posNext][i] * ipqf_coeffs2[t][i];
out[s * 16 + i + 8] += hist.buf1[posNow][7 - i] * ipqf_coeffs1[t][i + 8] + hist.buf2[posNext][7 - i] * ipqf_coeffs2[t][i + 8];
}
posNow = mod23_lut[posNext + 2]; // posNow = (posNow + 2) % 23;
posNext = mod23_lut[posNow + 2]; // posNext = (posNext + 2) % 23;
}
hist.pos = mod23_lut[hist.pos]; // hist.pos = (hist.pos - 1) % 23;
}
}
}