Ejemplo n.º 1
0
    private static void AthSetup(CodecSetup codecSetup, int block)
    {
        var psyParam = codecSetup.PsyParams[block];

        psyParam.AthAdjAtt = (float)codecSetup.EncodeSetup.AthFloatingDecibel;
        psyParam.AthMaxAtt = (float)codecSetup.EncodeSetup.AthAbsoluteDecibel;
    }
Ejemplo n.º 2
0
 private static void PackModes(EncodeBuffer buffer, CodecSetup codecSetup, int i)
 {
     buffer.Write((uint)codecSetup.ModeParams[i].BlockFlag, 1);
     buffer.Write((uint)codecSetup.ModeParams[i].WindowType, 16);
     buffer.Write((uint)codecSetup.ModeParams[i].TransformType, 16);
     buffer.Write((uint)codecSetup.ModeParams[i].Mapping, 8);
 }
Ejemplo n.º 3
0
    private static void MapAndResSetup(
        CodecSetup codecSetup,
        int sampleRate,
        int channels,
        IMappingTemplate[] templateMaps)
    {
        var encodeSetupBaseSetting = (int)codecSetup.EncodeSetup.BaseSetting;
        var map = templateMaps[encodeSetupBaseSetting].Mapping;
        var res = templateMaps[encodeSetupBaseSetting].ResidueTemplate;

        var modes = 2;

        if (codecSetup.BlockSizes[0] == codecSetup.BlockSizes[1])
        {
            modes = 1;
        }

        for (var i = 0; i < modes; i++)
        {
            codecSetup.ModeParams.Add(ModeTemplate[i]);
            codecSetup.MapParams.Add(map[i].Clone());

            for (var j = 0; j < map[i].SubMaps; j++)
            {
                ResidueSetup(
                    codecSetup,
                    sampleRate,
                    channels,
                    map[i].ResidueSubMap[j],
                    i,
                    res[map[i].ResidueSubMap[j]]);
            }
        }
    }
Ejemplo n.º 4
0
    private static void CompandSetup(
        CodecSetup codecSetup,
        double noiseCompandSetting,
        int block,
        CompandBlock[] templatePsyNoiseCompand,
        double[] templatePsyNoiseCompandShortMapping)
    {
        var setting = (int)noiseCompandSetting;
        var ds      = noiseCompandSetting - setting;
        var p       = codecSetup.PsyParams[block];

        ds = templatePsyNoiseCompandShortMapping[setting] * (1 - ds)
             + templatePsyNoiseCompandShortMapping[setting + 1] * ds;

        setting = (int)ds;
        ds     -= setting;
        if ((ds <= 0) && (setting > 0))
        {
            setting--;
            ds = 1;
        }

        // interpolate the compander settings
        for (var i = 0; i < p.NoiseCompand.Length; i++)
        {
            p.NoiseCompand[i] = (float)(templatePsyNoiseCompand[setting].Data[i] * (1 - ds)
                                        + templatePsyNoiseCompand[setting + 1].Data[i] * ds);
        }
    }
Ejemplo n.º 5
0
 private VorbisInfo(
     CodecSetup codecSetup,
     int channels,
     int sampleRate,
     int bitRateNominal)
 {
     CodecSetup     = codecSetup;
     Channels       = channels;
     SampleRate     = sampleRate;
     BitRateNominal = bitRateNominal;
 }
Ejemplo n.º 6
0
    private static void BlockSizeSetup(
        CodecSetup codecSetup,
        int index,
        int[] templateBlockSizeShort,
        int[] templateBlockSizeLong)
    {
        var blockshort = templateBlockSizeShort[index];
        var blocklong  = templateBlockSizeLong[index];

        codecSetup.BlockSizes[0] = blockshort;
        codecSetup.BlockSizes[1] = blocklong;
    }
Ejemplo n.º 7
0
    private static void FloorSetup(
        CodecSetup codecSetup,
        int encodeSetupBaseSetting,
        IStaticCodeBook[][] templateFloorBooks,
        Floor[] templateFloorParams,
        int[] templateFloorMappings)
    {
        var sourceIndex = templateFloorMappings[encodeSetupBaseSetting];
        var clonedFloor = templateFloorParams[sourceIndex].Clone();

        // books
        int maxClass = -1, maxBook = -1;

        foreach (var partitionClass in clonedFloor.PartitionClass)
        {
            if (partitionClass > maxClass)
            {
                maxClass = partitionClass;
            }
        }

        for (var i = 0; i <= maxClass; i++)
        {
            if (clonedFloor.ClassBook[i] > maxBook)
            {
                maxBook = clonedFloor.ClassBook[i];
            }

            clonedFloor.ClassBook[i] += codecSetup.BookParams.Count;

            for (var k = 0; k < 1 << clonedFloor.ClassSubs[i]; k++)
            {
                if (clonedFloor.ClassSubBook[i][k] > maxBook)
                {
                    maxBook = clonedFloor.ClassSubBook[i][k];
                }

                if (clonedFloor.ClassSubBook[i][k] >= 0)
                {
                    clonedFloor.ClassSubBook[i][k] += codecSetup.BookParams.Count;
                }
            }
        }

        for (var i = 0; i <= maxBook; i++)
        {
            var bookParam = templateFloorBooks[sourceIndex][i];
            codecSetup.BookParams.Add(bookParam);
        }

        codecSetup.FloorParams.Add(clonedFloor);
    }
Ejemplo n.º 8
0
    private static void PeakSetup(
        CodecSetup codecSetup,
        double tonePeakLimitSetting,
        int block,
        int[] templatePsyToneDecibelSuppress)
    {
        var setting = (int)tonePeakLimitSetting;
        var ds      = tonePeakLimitSetting - setting;
        var p       = codecSetup.PsyParams[block];

        p.ToneAbsLimit = (float)(templatePsyToneDecibelSuppress[setting] * (1 - ds)
                                 + templatePsyToneDecibelSuppress[setting + 1] * ds);
    }
Ejemplo n.º 9
0
    private static int GetOrAddBook(CodecSetup codecSetup, IStaticCodeBook codeBook)
    {
        int i;

        for (i = 0; i < codecSetup.BookParams.Count; i++)
        {
            if (codecSetup.BookParams[i] == codeBook)
            {
                return(i);
            }
        }

        codecSetup.BookParams.Add(codeBook);
        return(codecSetup.BookParams.Count - 1);
    }
Ejemplo n.º 10
0
    private static void GlobalStereo(
        CodecSetup codecSetup,
        int sampleRate,
        AdjStereo[] templateStereoModes)
    {
        var setting     = (int)codecSetup.EncodeSetup.BaseSetting;
        var ds          = codecSetup.EncodeSetup.BaseSetting - setting;
        var psyGlobal   = codecSetup.PsyGlobalParam;
        var packetBlobs = PsyGlobal.PacketBlobs;

        if (templateStereoModes != null)
        {
            psyGlobal.CouplingPrePointAmp  = templateStereoModes[setting].Pre.ToArray();
            psyGlobal.CouplingPostPointAmp = templateStereoModes[setting].Post.ToArray();

            var kHz = templateStereoModes[setting].Kilohertz[packetBlobs / 2] * (1 - ds)
                      + templateStereoModes[setting + 1].Kilohertz[packetBlobs / 2] * ds;

            for (var i = 0; i < packetBlobs; i++)
            {
                psyGlobal.CouplingPointLimit[0][i] =
                    (int)(kHz * 1000 / sampleRate * codecSetup.BlockSizes[0]);
                psyGlobal.CouplingPointLimit[1][i] =
                    (int)(kHz * 1000 / sampleRate * codecSetup.BlockSizes[1]);
                psyGlobal.CouplingPerKilohertz[i] = (int)kHz;
            }

            kHz = templateStereoModes[setting].LowPassKilohertz[packetBlobs / 2] * (1 - ds)
                  + templateStereoModes[setting + 1].LowPassKilohertz[packetBlobs / 2] * ds;

            for (var i = 0; i < packetBlobs; i++)
            {
                psyGlobal.SlidingLowPass[0][i] = (int)(kHz * 1000 / sampleRate * codecSetup.BlockSizes[0]);
                psyGlobal.SlidingLowPass[1][i] = (int)(kHz * 1000 / sampleRate * codecSetup.BlockSizes[1]);
            }
        }
        else
        {
            for (var i = 0; i < packetBlobs; i++)
            {
                psyGlobal.SlidingLowPass[0][i] = codecSetup.BlockSizes[0];
                psyGlobal.SlidingLowPass[1][i] = codecSetup.BlockSizes[1];
            }
        }
    }
Ejemplo n.º 11
0
    private static void PsyParamSetup(
        CodecSetup codecSetup,
        int encodeSetupBaseSetting,
        int[] noiseNormalStart,
        int[] noiseNormalPartition,
        double[] noiseNormalThreshold,
        int block)
    {
        var psyParam = Psy.PsyInfoTemplate.Clone();

        codecSetup.PsyParams.Add(psyParam);
        psyParam.BlockFlag = block >> 1;

        psyParam.Normalize       = true;
        psyParam.NormalStart     = noiseNormalStart[encodeSetupBaseSetting];
        psyParam.NormalPartition = noiseNormalPartition[encodeSetupBaseSetting];
        psyParam.NormalThreshold = noiseNormalThreshold[encodeSetupBaseSetting];
    }
Ejemplo n.º 12
0
    private static void NoiseBiasSetup(
        CodecSetup codecSetup,
        double noiseBiasSetting,
        int block,
        int[] templatePsyNoiseDecibelSuppress,
        Noise3[] templatePsyNoiseBiasLong,
        NoiseGuard[] templatePsyNoiseGuards)
    {
        var setting  = (int)noiseBiasSetting;
        var ds       = noiseBiasSetting - setting;
        var psyParam = codecSetup.PsyParams[block];

        psyParam.NoiseMaxSuppress = (float)(templatePsyNoiseDecibelSuppress[setting] * (1 - ds)
                                            + templatePsyNoiseDecibelSuppress[setting + 1] * ds);

        psyParam.NoiseWindowLowMin  = templatePsyNoiseGuards[block].Low;
        psyParam.NoiseWindowHighMin = templatePsyNoiseGuards[block].High;
        psyParam.NoiseWindowFixed   = templatePsyNoiseGuards[block].Fixed;

        for (var j = 0; j < psyParam.NoiseOffset.Length; j++)
        {
            for (var i = 0; i < psyParam.NoiseOffset[j].Length; i++)
            {
                psyParam.NoiseOffset[j][i] = (float)(templatePsyNoiseBiasLong[setting].Data[j][i] * (1 - ds)
                                                     + templatePsyNoiseBiasLong[setting + 1].Data[j][i] * ds);
            }
        }

        // impulse blocks may take a user specified bias to boost the nominal/high noise encoding depth
        foreach (var noiseOffset in psyParam.NoiseOffset)
        {
            var min = noiseOffset[0] + 6;
            for (var i = 0; i < noiseOffset.Length; i++)
            {
                if (noiseOffset[i] < min)
                {
                    noiseOffset[i] = min;
                }
            }
        }
    }
Ejemplo n.º 13
0
    private static void FillBooks(
        CodecSetup codecSetup,
        ResidueEntry r,
        IStaticCodeBook bookAux,
        IStaticBookBlock bookBlock)
    {
        for (var i = 0; i < r.Partitions; i++)
        {
            for (var k = 0; k < 4; k++)
            {
                if ((i < bookBlock.Books.Length) &&
                    (k < bookBlock.Books[i].Length) &&
                    (bookBlock.Books[i][k] != null))
                {
                    r.SecondStages[i] |= 1 << k;
                }
            }
        }

        r.GroupBook = GetOrAddBook(codecSetup, bookAux);

        var booklist = 0;

        for (var i = 0; i < r.Partitions; i++)
        {
            for (var k = 0; k < 4; k++)
            {
                if ((i < bookBlock.Books.Length) &&
                    (k < bookBlock.Books[i].Length))
                {
                    var sourceBook = bookBlock.Books[i][k];
                    if (sourceBook != null)
                    {
                        var bookid = GetOrAddBook(codecSetup, sourceBook);
                        r.BookList[booklist++] = bookid;
                    }
                }
            }
        }
    }
Ejemplo n.º 14
0
    private static void ToneMaskSetup(
        CodecSetup codecSetup,
        double toneMaskSetting,
        int block,
        Att3[] templatePsyToneMasterAtt,
        int[] templatePsyTone0Decibel,
        AdjBlock[] templatePsyToneAdjLong)
    {
        var setting = (int)toneMaskSetting;
        var ds      = toneMaskSetting - setting;

        var psyParam = codecSetup.PsyParams[block];

        // 0 and 2 are only used by bitmanagement, but there's no harm to always filling the values in here
        psyParam.ToneMasterAtt[0] = (float)(templatePsyToneMasterAtt[setting].Att[0] * (1 - ds)
                                            + templatePsyToneMasterAtt[setting + 1].Att[0] * ds);

        psyParam.ToneMasterAtt[1] = (float)(templatePsyToneMasterAtt[setting].Att[1] * (1 - ds)
                                            + templatePsyToneMasterAtt[setting + 1].Att[1] * ds);

        psyParam.ToneMasterAtt[2] = (float)(templatePsyToneMasterAtt[setting].Att[2] * (1 - ds)
                                            + templatePsyToneMasterAtt[setting + 1].Att[2] * ds);

        psyParam.ToneCenterBoost = (float)(templatePsyToneMasterAtt[setting].Boost * (1 - ds)
                                           + templatePsyToneMasterAtt[setting + 1].Boost * ds);

        psyParam.ToneDecay = (float)(templatePsyToneMasterAtt[setting].Decay * (1 - ds)
                                     + templatePsyToneMasterAtt[setting + 1].Decay * ds);

        psyParam.MaxCurveDecibel = (float)(templatePsyTone0Decibel[setting] * (1 - ds)
                                           + templatePsyTone0Decibel[setting + 1] * ds);

        for (var i = 0; i < PsyInfo.Bands; i++)
        {
            psyParam.ToneAtt[i] = (float)(templatePsyToneAdjLong[setting].Block[i] * (1 - ds)
                                          + templatePsyToneAdjLong[setting + 1].Block[i] * ds);
        }
    }
Ejemplo n.º 15
0
    private static void GlobalPsychSetup(
        CodecSetup codecSetup,
        double encodeSetupTriggerSetting,
        PsyGlobal[] templateGlobalParams,
        double[] templateGlobalMapping)
    {
        var setting = (int)encodeSetupTriggerSetting;
        var ds      = encodeSetupTriggerSetting - setting;

        var sourceIndex = (int)templateGlobalMapping[setting];
        var globalParam = codecSetup.PsyGlobalParam = templateGlobalParams[sourceIndex].Clone();

        ds = templateGlobalMapping[setting]
             * (1 - ds) + templateGlobalMapping[setting + 1]
             * ds;

        setting = (int)ds;
        ds     -= setting;
        if ((ds <= 0) && (setting > 0))
        {
            setting--;
            ds = 1;
        }

        // interpolate the trigger threshholds
        for (var i = 0; i < 4; i++)
        {
            globalParam.PreEchoThreshold[i] = (float)
                                              (templateGlobalParams[setting].PreEchoThreshold[i] * (1 - ds)
                                               + templateGlobalParams[setting + 1].PreEchoThreshold[i] * ds);

            globalParam.PostEchoThreshold[i] = (float)
                                               (templateGlobalParams[setting].PostEchoThreshold[i] * (1 - ds)
                                                + templateGlobalParams[setting + 1].PostEchoThreshold[i] * ds);
        }

        globalParam.AmpMaxAttPerSec = (float)codecSetup.EncodeSetup.AmplitudeTrackDbPerSec;
    }
Ejemplo n.º 16
0
    public static void WriteFile(Unity_Studio.EndianStream stream, string file, int offset, int size, Ogg ogg)
    {
        // Write to disk
        using (BinaryWriter writer = new BinaryWriter(File.Open(file, FileMode.Create)))
        {
            // Only support header CRC 3605052372 for now
            OggVorbisHeader head = new OggVorbisHeader();

            HeaderPacketBuilder hpb    = new HeaderPacketBuilder();
            CodecSetup          cSetup = new CodecSetup(null);
            cSetup.BlockSizes[0] = 256;
            cSetup.BlockSizes[1] = 2048;

            VorbisInfo info = new VorbisInfo(cSetup, (int)ogg.channels, (int)ogg.frequency, 0);

            OggPacket headerInfo = hpb.BuildInfoPacket(info);

            Comments comments = new Comments();
            if (ogg.loopStart > 0 && ogg.loopEnd > 0)
            {
                comments.AddTag("LOOP_START", ogg.loopStart.ToString());
                comments.AddTag("LOOP_END", ogg.loopEnd.ToString());
            }
            OggPacket headerComment = hpb.BuildCommentsPacket(comments);
            OggPacket headerSetup   = new OggPacket(OggVorbisHeader.GetHeader(ogg.crc32), false, 0, 2);

            OggStream output = new OggStream(1);
            output.PacketIn(headerInfo);
            output.PacketIn(headerComment);
            output.PacketIn(headerSetup);

            stream.Position = offset;

            UInt16 packetSize     = stream.ReadUInt16();
            int    prevPacketNo   = 2;
            int    prevGranulePos = 0;

            while (packetSize > 0)
            {
                OggPacket packet = new OggPacket(stream.ReadBytes(packetSize), false, 0, prevPacketNo + 1);

                byte firstByte = packet.PacketData[0];

                // OK for stereo
                int granuleSize = 128;
                if ((firstByte & 2) != 0)
                {
                    granuleSize = 1024;
                }

                if (ogg.channels == 1)
                {
                    granuleSize /= 4;
                }
                packet.GranulePosition = prevGranulePos + granuleSize;

                if (stream.Position + 2 < offset + size)
                {
                    packetSize = stream.ReadUInt16();
                }
                else
                {
                    packetSize = 0;
                }
                packet.EndOfStream = packetSize == 0;
                prevGranulePos     = packet.GranulePosition;
                prevPacketNo       = packet.PacketNumber;

                output.PacketIn(packet);
                OggPage page = null;
                if (output.PageOut(out page, true))
                {
                    writer.Write(page.Header);
                    writer.Write(page.Body);
                }
            }

            //float vorbis_quality = ((ogg.quality - 1) + (ogg.quality - 100) * 0.1f) / 99.0f;
            //VorbisInfo.InitVariableBitRate(ogg.channels, ogg.frequency, ogg.)
            //writer.Write();
            writer.Close();
        }
    }
Ejemplo n.º 17
0
    private static void ResidueSetup(
        CodecSetup codecSetup,
        int sampleRate,
        int channels,
        int number,
        int block,
        IResidueTemplate residueTemplate)
    {
        var residue = residueTemplate.Residue.Clone(
            residueTemplate.ResidueType,
            residueTemplate.Grouping);

        codecSetup.ResidueParams.Add(residue);

        // fill in all the books
        FillBooks(codecSetup, residue, residueTemplate.BookAux, residueTemplate.BooksBase);

        // lowpass setup/pointlimit
        var freq      = codecSetup.EncodeSetup.LowPassKilohertz * 1000;
        var f         = codecSetup.FloorParams[block]; // by convention
        var nyq       = sampleRate / 2.0;
        var blocksize = codecSetup.BlockSizes[block] >> 1;

        // lowpass needs to be set in the floor and the residue.
        if (freq > nyq)
        {
            freq = nyq;
        }

        // in the floor, the granularity can be very fine; it doesn't alter
        // the encoding structure, only the samples used to fit the floor approximation
        f.N = (int)(freq / nyq * blocksize);

        // this res may by limited by the maximum pointlimit of the mode,
        // not the lowpass. the floor is always lowpass limited.
        switch (residueTemplate.LimitType)
        {
        case ResidueLimitType.PointStereo:
            freq = codecSetup.PsyGlobalParam.CouplingPerKilohertz[PsyGlobal.PacketBlobs / 2] * 1000;

            if (freq > nyq)
            {
                freq = nyq;
            }

            break;

        case ResidueLimitType.LowFrequencyEffects:
            freq = 250;
            break;
        }

        // in the residue, we're constrained, physically, by partition
        // boundaries.  We still lowpass 'wherever', but we have to round up
        // here to next boundary, or the vorbis spec will round it *down* to
        // previous boundary in encode/decode
        if (residue.ResidueType == ResidueType.Two)
        {
            // Residue 2 bundles together multiple channels; used by stereo
            // and surround.  Count the channels in use
            // Multiple maps/submaps can point to the same residue.  In the case
            // of residue 2, they all better have the same number of channels/samples.
            var ch = 0;
            for (var i = 0; (i < codecSetup.MapParams.Count) && (ch == 0); i++)
            {
                var mapping = codecSetup.MapParams[i];
                for (var j = 0; (j < mapping.SubMaps) && (ch == 0); j++)
                {
                    if (mapping.ResidueSubMap[j] == number) // we found a submap referencing this residue backend
                    {
                        for (var k = 0; k < channels; k++)
                        {
                            if (mapping.ChannelMuxList[k] == j) // this channel belongs to the submap
                            {
                                ch++;
                            }
                        }
                    }
                }
            }

            // round up only if we're well past
            residue.End = (int)(freq / nyq * blocksize * ch / residue.Grouping + .9) * residue.Grouping;

            // the blocksize and grouping may disagree at the end
            if (residue.End > blocksize * ch)
            {
                residue.End = blocksize * ch / residue.Grouping * residue.Grouping;
            }
        }
        else
        {
            // round up only if we're well past
            residue.End = (int)(freq / nyq * blocksize / residue.Grouping + .9) * residue.Grouping;

            // the blocksize and grouping may disagree at the end
            if (residue.End > blocksize)
            {
                residue.End = blocksize / residue.Grouping * residue.Grouping;
            }
        }

        if (residue.End == 0)
        {
            residue.End = residue.Grouping; // LFE channel
        }
    }
Ejemplo n.º 18
0
    public static VorbisInfo InitVariableBitRate(int channels, int sampleRate, float baseQuality)
    {
        var encodeSetup = GetEncodeSetup(channels, sampleRate, baseQuality);
        var codecSetup  = new CodecSetup(encodeSetup);
        var template    = encodeSetup.Template;

        // choose Block sizes from configured sizes as well as paying
        // attention to long_Block_p and short_Block_p.  If the configured
        // short and long Blocks are the same length, we set long_Block_p
        // and unset short_Block_p
        BlockSizeSetup(
            codecSetup,
            (int)encodeSetup.BaseSetting,
            template.BlockSizeShort,
            template.BlockSizeLong);

        var singleBlock = codecSetup.BlockSizes[0]
                          == codecSetup.BlockSizes[1];

        // floor setup; choose proper floor params.  Allocated on the floor
        // stack in order; if we alloc only long floor, it's 0
        foreach (var floorMappings in template.FloorMappings)
        {
            FloorSetup(
                codecSetup,
                (int)encodeSetup.BaseSetting,
                template.FloorBooks,
                template.FloorParams,
                floorMappings);
        }

        // setup of [mostly] short Block detection and stereo
        GlobalPsychSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            template.GlobalParams,
            template.GlobalMapping);

        GlobalStereo(
            codecSetup,
            sampleRate,
            template.StereoModes);

        // basic psych setup and noise normalization
        PsyParamSetup(
            codecSetup,
            (int)encodeSetup.BaseSetting,
            template.PsyNoiseNormalStart[0],
            template.PsyNoiseNormalPartition[0],
            template.PsyNoiseNormalThreshold,
            0);

        PsyParamSetup(
            codecSetup,
            (int)encodeSetup.BaseSetting,
            template.PsyNoiseNormalStart[0],
            template.PsyNoiseNormalPartition[0],
            template.PsyNoiseNormalThreshold,
            1);

        if (!singleBlock)
        {
            PsyParamSetup(
                codecSetup,
                (int)encodeSetup.BaseSetting,
                template.PsyNoiseNormalStart[1],
                template.PsyNoiseNormalPartition[1],
                template.PsyNoiseNormalThreshold,
                2);

            PsyParamSetup(
                codecSetup,
                (int)encodeSetup.BaseSetting,
                template.PsyNoiseNormalStart[1],
                template.PsyNoiseNormalPartition[1],
                template.PsyNoiseNormalThreshold,
                3);
        }

        // tone masking setup
        ToneMaskSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            0,
            template.PsyToneMasterAtt,
            template.PsyTone0Decibel,
            template.PsyToneAdjImpulse);

        ToneMaskSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            1,
            template.PsyToneMasterAtt,
            template.PsyTone0Decibel,
            template.PsyToneAdjOther);

        if (!singleBlock)
        {
            ToneMaskSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                2,
                template.PsyToneMasterAtt,
                template.PsyTone0Decibel,
                template.PsyToneAdjOther);

            ToneMaskSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                3,
                template.PsyToneMasterAtt,
                template.PsyTone0Decibel,
                template.PsyToneAdjLong);
        }

        // noise compand setup
        CompandSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            0,
            template.PsyNoiseCompand,
            template.PsyNoiseCompandShortMapping);

        CompandSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            1,
            template.PsyNoiseCompand,
            template.PsyNoiseCompandShortMapping);

        if (!singleBlock)
        {
            CompandSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                2,
                template.PsyNoiseCompand,
                template.PsyNoiseCompandLongMapping);

            CompandSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                3,
                template.PsyNoiseCompand,
                template.PsyNoiseCompandLongMapping);
        }

        // peak guarding setup
        PeakSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            0,
            template.PsyToneDecibelSuppress);

        PeakSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            1,
            template.PsyToneDecibelSuppress);

        if (!singleBlock)
        {
            PeakSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                2,
                template.PsyToneDecibelSuppress);

            PeakSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                3,
                template.PsyToneDecibelSuppress);
        }

        // noise bias setup
        NoiseBiasSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            0,
            template.PsyNoiseDecibelSuppress,
            template.PsyNoiseBiasImpulse,
            template.PsyNoiseGuards);

        NoiseBiasSetup(
            codecSetup,
            encodeSetup.BaseSetting,
            1,
            template.PsyNoiseDecibelSuppress,
            template.PsyNoiseBiasPadding,
            template.PsyNoiseGuards);

        if (!singleBlock)
        {
            NoiseBiasSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                2,
                template.PsyNoiseDecibelSuppress,
                template.PsyNoiseBiasTrans,
                template.PsyNoiseGuards);

            NoiseBiasSetup(
                codecSetup,
                encodeSetup.BaseSetting,
                3,
                template.PsyNoiseDecibelSuppress,
                template.PsyNoiseBiasLong,
                template.PsyNoiseGuards);
        }

        AthSetup(codecSetup, 0);
        AthSetup(codecSetup, 1);

        if (!singleBlock)
        {
            AthSetup(codecSetup, 2);
            AthSetup(codecSetup, 3);
        }

        MapAndResSetup(
            codecSetup,
            sampleRate,
            channels,
            template.Maps);

        var bitRateNominal = GetApproxBitRate(encodeSetup, channels);

        return(new VorbisInfo(
                   codecSetup,
                   channels,
                   sampleRate,
                   bitRateNominal));
    }