Esempio n. 1
0
        public virtual 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;
                }
            }
        }
Esempio n. 2
0
 public virtual void copy(AtracGainInfo from)
 {
     this.numPoints = from.numPoints;
     Array.Copy(from.levCode, 0, this.levCode, 0, levCode.Length);
     Array.Copy(from.locCode, 0, this.locCode, 0, locCode.Length);
 }
Esempio n. 3
0
        public virtual void gainCompensation(float[] @in, int inOffset, float[] prev, int prevOffset, AtracGainInfo gcNow, AtracGainInfo gcNext, int numSamples, float[] @out, int outOffset)
        {
            float gcScale = (gcNext.numPoints != 0 ? gainTab1[gcNext.levCode[0]] : 1f);

            if (gcNow.numPoints == 0)
            {
                for (int pos = 0; pos < numSamples; pos++)
                {
                    @out[outOffset + pos] = @in[inOffset + pos] * gcScale + prev[prevOffset + pos];
                }
            }
            else
            {
                int pos = 0;

                for (int i = 0; i < gcNow.numPoints; i++)
                {
                    int lastpos = gcNow.locCode[i] << locScale;

                    float lev     = gainTab1[gcNow.levCode[i]];
                    float gainInc = gainTab2[(i + 1 < gcNow.numPoints ? gcNow.levCode[i + 1] : id2expOffset) - gcNow.levCode[i] + 15];

                    // apply constant gain level and overlap
                    for (; pos < lastpos; pos++)
                    {
                        @out[outOffset + pos] = (@in[inOffset + pos] * gcScale + prev[prevOffset + pos]) * lev;
                    }

                    // interpolate between two different gain levels
                    for (; pos < lastpos + locSize; pos++)
                    {
                        @out[outOffset + pos] = (@in[inOffset + pos] * gcScale + prev[prevOffset + pos]) * lev;
                        lev *= gainInc;
                    }
                }

                for (; pos < numSamples; pos++)
                {
                    @out[outOffset + pos] = @in[inOffset + pos] * gcScale + prev[prevOffset + pos];
                }
            }

            // copy the overlapping part into the delay buffer
            Array.Copy(@in, inOffset + numSamples, prev, prevOffset, numSamples);
        }