예제 #1
0
        public WWFilterCpp CreateIIRFilterCpp(int osr, int decimation)
        {
            var fg = mIIRFilterDesign.CreateIIRFilterGraph();

            var fgSerial   = fg as IIRFilterSerial;
            var fgParallel = fg as IIRFilterParallel;

            var r = new WWFilterCpp();

            if (fgSerial != null)
            {
                r.BuildIIRSerial(fg.BlockCount());
            }
            else
            {
                r.BuildIIRParallel(fg.BlockCount());
            }

            for (int i = 0; i < fg.BlockCount(); ++i)
            {
                var block = fg.GetNthBlock(i);
                var a     = block.A();
                var b     = block.B();
                r.AddIIRBlock(a.Length, a, b.Length, b);
            }

            r.SetParam(osr, decimation);

            return(r);
        }
예제 #2
0
        /// <summary>
        /// mLoopFiltersを設計する。
        /// </summary>
        /// <param name="order">フィルターの次数(3,5,7)。</param>
        /// <param name="numChannels">音声のチャンネル数。</param>
        public void Design(int order, int numChannels)
        {
            mCh = numChannels;
            var ntfHz = new NTFHzcoeffs(order);

            // フィードバック係数g。Hzの分子の零(単位円上)のz=1からの角度 ω → g = 2 - 2cos(ω)
            var g = new double[order / 2];

            for (int i = 0; i < g.Length; ++i)
            {
                // Hzの分子の零の位置r。
                var r    = ntfHz.ZeroNth(i);
                var cosω = r.real;
                g[i] = 2.0 - 2.0 * cosω;
            }

            var d = new double[order + 1];

            for (int i = 0; i < d.Length; ++i)
            {
                d[i] = ntfHz.D(i);
            }

            // CRFB構造のノイズシェイピングフィルターの係数a[]。
            // R. Schreier and G. Temes, ΔΣ型アナログ/デジタル変換器入門,丸善,2007, pp.95,96
            var a = new double[order];

            switch (order)
            {
            case 2:
                a[0] = d[0] + d[1] - g[0] + 1;
                a[1] = 1 - d[0];
                break;

            case 3:
                a[0] = 1 + d[0] + d[1] + d[2];
                a[1] = 2 - d[0] + d[2] - g[0];
                a[2] = 1 + d[0];
                break;

            case 4:
                a[0] = 1 + d[0] + d[1] + d[2] + d[3] - 3 * g[0] - d[0] * g[0] - d[3] * g[0] + g[0] * g[0];
                a[1] = 2 - 2 * d[0] - d[1] + d[3] - g[0] + d[0] * g[0];
                a[2] = 3 + d[0] + d[3] - g[0] - g[1];
                a[3] = 1 - d[0];
                break;

            case 5:
                a[0] = 1 + d[0] + d[1] + d[2] + d[3] + d[4];
                a[1] = 3 - 2 * d[0] - d[1] + d[3] + 2 * d[4] - 4 * g[0] + d[0] * g[0] - d[4] * g[0] + g[0] * g[0];
                a[2] = 3 + 3 * d[0] + d[1] + d[4] - g[0] - d[0] * g[0];
                a[3] = 4 - d[0] + d[4] - g[0] - g[1];
                a[4] = 1 + d[0];
                break;

            case 6:
                a[0] = 1 + d[0] + d[1] + d[2] + d[3] + d[4] + d[5] - 6 * g[0] - 3 * d[0] * g[0] - d[1] * g[0] - d[4] * g[0] - 3 * d[5] * g[0] + 5 * g[0] * g[0] + d[0] * g[0] * g[0] + d[5] * g[0] * g[0] - g[0] * g[0] * g[0];
                a[1] = 3 - 3 * d[0] - 2 * d[1] - d[2] + d[4] + 2 * d[5] - 4 * g[0] + 4 * d[0] * g[0] + d[1] * g[0] - d[5] * g[0] + g[0] * g[0] - d[0] * g[0] * g[0];
                a[2] = 6 + 3 * d[0] + d[1] + d[4] + 3 * d[5] - 5 * g[0] - d[0] * g[0] - d[5] * g[0] + g[0] * g[0] - 5 * g[1] - d[0] * g[1] - d[5] * g[1] + g[0] * g[1] + g[1] * g[1];
                a[3] = 4 - 4 * d[0] - d[1] + d[5] - g[0] + d[0] * g[0] - g[1] + d[0] * g[1];
                a[4] = 5 + d[0] + d[5] - g[0] - g[1] - g[2];
                a[5] = 1 - d[0];
                break;

            case 7:
                a[0] = 1 + d[0] + d[1] + d[2] + d[3] + d[4] + d[5] + d[6];
                a[1] = 4 - 3 * d[0] - 2 * d[1] - d[2] + d[4] + 2 * d[5] + 3 * d[6] - 10 * g[0] + 4 * d[0] * g[0] + d[1] * g[0] - d[5] * g[0] - 4 * d[6] * g[0] + 6 * g[0] * g[0] - d[0] * g[0] * g[0] + d[6] * g[0] * g[0] - g[0] * g[0] * g[0];
                a[2] = 6 + 6 * d[0] + 3 * d[1] + d[2] + d[5] + 3 * d[6] - 5 * g[0] - 5 * d[0] * g[0] - d[1] * g[0] - d[6] * g[0] + g[0] * g[0] + d[0] * g[0] * g[0];
                a[3] = 10 - 4 * d[0] - d[1] + d[5] + 4 * d[6] - 6 * g[0] + d[0] * g[0] - d[6] * g[0] + g[0] * g[0] - 6 * g[1] + d[0] * g[1] - d[6] * g[1] + g[0] * g[1] + g[1] * g[1];
                a[4] = 5 + 5 * d[0] + d[1] + d[6] - g[0] - d[0] * g[0] - g[1] - d[0] * g[1];
                a[5] = 6 - d[0] + d[6] - g[0] - g[1] - g[2];
                a[6] = 1 + d[0];
                break;

            default:
                throw new NotImplementedException();
            }

            // CRFBでSTF==1になるようなb[]の係数。
            var b = new double[order + 1];

            for (int i = 0; i < order; ++i)
            {
                b[i] = a[i];
            }
            b[order] = 1.0;

            /*
             * Console.Write("double [] g = {");
             * for (int i = 0; i < g.Length; ++i) {
             *  Console.Write("{0:R}, ", g[i]);
             * }
             * Console.WriteLine("};");
             *
             * Console.Write("double [] a = {");
             * for (int i = 0; i < a.Length; ++i) {
             *  Console.Write("{0:R}, ", a[i]);
             * }
             * Console.WriteLine("};");
             *
             * Console.Write("double [] b = {");
             * for (int i = 0; i < b.Length; ++i) {
             *  Console.Write("{0:R}, ", b[i]);
             * }
             * Console.WriteLine("};");
             *
             * Console.Write("double [] n = {");
             * for (int i = 0; i < order+1; ++i) {
             *  Console.Write("{0:R}, ", ntfHz.N(i));
             * }
             * Console.WriteLine("};");
             *
             * Console.Write("double [] d = {");
             * for (int i = 0; i < d.Length; ++i) {
             *  Console.Write("{0:R}, ", d[i]);
             * }
             * Console.WriteLine("};");
             */

#if USE_CPP
            mLoopFiltersCpp = new WWFilterCpp[numChannels];
            for (int ch = 0; ch < numChannels; ++ch)
            {
                var p = new WWFilterCpp();
                p.BuildCrfb(order, a, b, g, 0.5);
                mLoopFiltersCpp[ch] = p;
            }
#else
            mLoopFilters = new LoopFilterCRFB[numChannels];
            for (int ch = 0; ch < numChannels; ++ch)
            {
                mLoopFilters[ch] = new LoopFilterCRFB(a, b, g);
            }
#endif
        }
예제 #3
0
        public BWCompletedParam DoWork(BWStartParams param, ProgressReportDelegate ReportProgress)
        {
            int rv = 0;

            var flacR = new WWFlacRWCS.FlacRW();

            do
            {
                // FLACファイルからメタデータ、画像、音声を取り出す。
                WWFlacRWCS.Metadata metaR;
                rv = flacR.DecodeAll(param.inputFile);
                if (rv < 0)
                {
                    // do-whileを抜けたところでflacR.DecodeEndする。
                    break;
                }

                flacR.GetDecodedMetadata(out metaR);

                byte[] picture = null;
                if (0 < metaR.pictureBytes)
                {
                    rv = flacR.GetDecodedPicture(out picture, metaR.pictureBytes);
                    if (rv < 0)
                    {
                        // do-whileを抜けたところでflacR.DecodeEndする。
                        break;
                    }
                }

                // flacRはまだ使用するのでここではDecodeEndしない。

                long lcm             = WWMath.Functions.LCM(metaR.sampleRate, param.targetSampleRate);
                int  upsampleScale   = (int)(lcm / metaR.sampleRate);
                int  downsampleScale = (int)(lcm / param.targetSampleRate);

                // IIRフィルターを設計。

                // ストップバンド最小周波数fs。
                double fs = metaR.sampleRate / 2 * STOPBAND_FREQ_RATIO;
                if (param.targetSampleRate / 2 * STOPBAND_FREQ_RATIO < fs)
                {
                    fs = param.targetSampleRate / 2 * STOPBAND_FREQ_RATIO;
                }

                // カットオフ周波数fc。
                double fc = CUTOFF_STOPBAND_RATIO * fs;

                mIIRFilterDesign = new IIRFilterDesign();
                mIIRFilterDesign.Design(fc, fs, lcm, param.method);

                ReportProgress(CONVERT_START_PERCENT, new BWProgressParam(State.FilterDesigned,
                                                                          string.Format("Read FLAC completed.\nSource sample rate = {0}kHz.\nTarget sample rate = {1}kHz. ratio={2}/{3}\n",
                                                                                        metaR.sampleRate / 1000.0, param.targetSampleRate / 1000.0,
                                                                                        lcm / metaR.sampleRate, lcm / param.targetSampleRate)));

                double RESAMPLE_RATIO = param.targetSampleRate / metaR.sampleRate;

                mSw.Restart();

                // 書き込み準備。
                WWFlacRWCS.Metadata metaW = new WWFlacRWCS.Metadata(metaR);
                metaW.sampleRate    = param.targetSampleRate;
                metaW.pictureBytes  = metaR.pictureBytes;
                metaW.bitsPerSample = 24;
                metaW.totalSamples  = metaR.totalSamples * upsampleScale / downsampleScale;

                if (param.isTargetPcm)
                {
                    mFlacWrite = new FlacWrite();
                    mFlacWrite.Setup(metaW, picture);
                }
                else
                {
                    mDsfWrite = new DsfWrite();
                    mDsfWrite.Setup(metaW, picture);
                }

                var  stat = new SampleValueStatistics();
                long totalSamplesOfAllChannels = metaR.totalSamples * metaR.channels;
                long processedSamples          = 0;

                // Mathematica用の設定。
                WWComplex.imaginaryUnit = "I";

                // 変換する
                for (int ch = 0; ch < metaR.channels; ++ch)
                {
                    //Parallel.For(0, metaR.channels, (int ch) => {
                    var pcmW = new WWUtil.LargeArray <byte>(metaW.totalSamples * metaW.BytesPerSample);

#if USE_ZOH_UPSAMPLE
                    // 零次ホールドのハイ落ち補償フィルター。
# if USE_CPP
                    var zohCompensation = new WWFilterCpp();
                    zohCompensation.BuildZohCompensation();
# else
                    var zohCompensation = new WWIIRFilterDesign.ZohNosdacCompensation(33);
# endif