/// <summary>
        /// Converts sample format to toFormat and returns new instance of PcmData.
        /// pcmFrom is not changed.
        /// </summary>
        /// <param name="toFormat">sample format to convert</param>
        /// <returns>Newly instanciated PcmData</returns>
        public PcmData Convert(PcmData pcmFrom, WasapiCS.SampleFormatType toFormat, BitsPerSampleConvArgs args)
        {
            if (args == null)
            {
                args = new BitsPerSampleConvArgs(NoiseShapingType.None);
            }

            var fromFormat = WasapiCS.BitAndFormatToSampleFormatType(pcmFrom.BitsPerSample, pcmFrom.ValidBitsPerSample,
                                                                     SampleFormatInfo.VrtToBft(pcmFrom.SampleValueRepresentationType));

            if (fromFormat == WasapiCS.SampleFormatType.Unknown ||
                toFormat == WasapiCS.SampleFormatType.Unknown)
            {
                return(null);
            }

            var newSampleArray = mConvert[(int)fromFormat][(int)toFormat](pcmFrom, toFormat, args);

            PcmData newPcmData = new PcmData();

            newPcmData.CopyHeaderInfoFrom(pcmFrom);
            newPcmData.SetFormat(pcmFrom.NumChannels,
                                 WasapiCS.SampleFormatTypeToUseBitsPerSample(toFormat),
                                 WasapiCS.SampleFormatTypeToValidBitsPerSample(toFormat), pcmFrom.SampleRate,
                                 SampleFormatInfo.BftToVrt(WasapiCS.SampleFormatTypeToBitFormatType(toFormat)), pcmFrom.NumFrames);
            newPcmData.SetSampleArray(newSampleArray);

            return(newPcmData);
        }
Пример #2
0
        /// <summary>
        /// WAVファイルのヘッダ部分を読み込む。
        /// </summary>
        /// <returns>読めたらtrue</returns>
        private bool ReadWavFileHeader(string path)
        {
            bool result = false;
            var  pd     = new PcmData();

            var wavR = new WavReader();

            using (BinaryReader br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                if (wavR.ReadHeader(br))
                {
                    // WAVヘッダ読み込み成功。PcmDataを作って再生リストに足す。

                    pd.SetFormat(wavR.NumChannels, wavR.BitsPerSample, wavR.ValidBitsPerSample,
                                 (int)wavR.SampleRate, wavR.SampleValueRepresentationType, wavR.NumFrames);

                    if (wavR.SampleDataType == WavReader.DataType.DoP)
                    {
                        pd.SampleDataType = PcmData.DataType.DoP;
                    }

                    if ("RIFFINFO_INAM".Equals(wavR.Title) &&
                        "RIFFINFO_IART".Equals(wavR.ArtistName))
                    {
                        // Issue 79 workaround
                    }
                    else
                    {
                        if (wavR.Title != null)
                        {
                            pd.DisplayName = wavR.Title;
                        }
                        if (wavR.AlbumName != null)
                        {
                            pd.AlbumTitle = wavR.AlbumName;
                        }
                        if (wavR.ArtistName != null)
                        {
                            pd.ArtistName = wavR.ArtistName;
                        }
                        if (wavR.ComposerName != null)
                        {
                            pd.ComposerName = wavR.ComposerName;
                        }
                    }
                    pd.SetPicture(wavR.PictureBytes, wavR.PictureData);
                    result = CheckAddPcmData(path, pd, true);
                }
                else
                {
                    LoadErrorMessageAdd(string.Format(CultureInfo.InvariantCulture, Properties.Resources.ReadFileFailed + ": {1} : {2}{3}",
                                                      "WAV", path, wavR.ErrorReason, Environment.NewLine));
                }
            }

            return(result);
        }
Пример #3
0
        private PcmData ReadWavFile(string path)
        {
            PcmData pcmData = new PcmData();

            using (BinaryReader br = new BinaryReader(
                       File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) {
                var  wavR        = new WavReader();
                bool readSuccess = wavR.ReadHeaderAndSamples(br, 0, -1);
                if (!readSuccess)
                {
                    return(null);
                }
                pcmData.SetFormat(wavR.NumChannels, wavR.BitsPerSample, wavR.BitsPerSample,
                                  wavR.SampleRate, wavR.SampleValueRepresentationType, wavR.NumFrames);
                pcmData.SetSampleArray(wavR.GetSampleArray());
            }

            return(pcmData);
        }
Пример #4
0
        public static PcmData ReadWav(BinaryReader br)
        {
            var reader = new WavReader();

            if (!reader.ReadHeaderAndSamples(br, 0, -1))
            {
                return(null);
            }

            var pcm = new PcmData();

            pcm.AlbumTitle  = reader.AlbumName;
            pcm.ArtistName  = reader.ArtistName;
            pcm.DisplayName = reader.Title;

            pcm.SetFormat(reader.NumChannels, reader.BitsPerSample,
                          reader.ValidBitsPerSample, reader.SampleRate,
                          reader.SampleValueRepresentationType, reader.NumFrames);

            pcm.SetSampleArray(reader.GetSampleArray());

            return(pcm);
        }
Пример #5
0
        private int Convert1(ConvertArgs ca)
        {
            int hr = 0;

            CallEvent(EventCallbackTypes.Started, PROGRESS_STARTED, hr);

            hr = mResampleGpu.ChooseAdapter(ca.mGpuId);
            if (hr < 0)
            {
                CallEvent(EventCallbackTypes.InitGpuAdapterFailed, 0, hr);
                return(hr);
            }

            var flacR = new FlacRW();

            hr = flacR.DecodeAll(ca.mInPath);
            if (hr < 0)
            {
                CallEvent(EventCallbackTypes.ReadFailed, 0, hr);
                return(hr);
            }
            else
            {
                CallEvent(EventCallbackTypes.ReadCompleted, PROGRESS_READ_END, hr);
            }

            Metadata metaR;

            flacR.GetDecodedMetadata(out metaR);

            var inPcmOfCh = new List <float[]>();

            for (int ch = 0; ch < metaR.channels; ++ch)
            {
                var pcm = new LargeArray <byte>(metaR.BytesPerSample * metaR.totalSamples);

                int fragmentSamples = 1024 * 1024;
                for (long posSamples = 0; posSamples < metaR.totalSamples; posSamples += fragmentSamples)
                {
                    int copySamples = fragmentSamples;
                    if ((metaR.totalSamples - posSamples) < copySamples)
                    {
                        copySamples = (int)(metaR.totalSamples - posSamples);
                    }
                    var b = new byte[metaR.BytesPerSample * copySamples];
                    flacR.GetPcmOfChannel(ch, posSamples, ref b, copySamples);
                    pcm.CopyFrom(b, 0,
                                 metaR.BytesPerSample * posSamples, metaR.BytesPerSample * copySamples);
                }

                var pcmData = new PcmData();
                pcmData.SetFormat(1, metaR.bitsPerSample, metaR.bitsPerSample,
                                  metaR.sampleRate, PcmData.ValueRepresentationType.SInt,
                                  metaR.totalSamples);
                pcmData.SetSampleLargeArray(pcm);

                var fb = new float[metaR.totalSamples];
                for (long i = 0; i < metaR.totalSamples; ++i)
                {
                    fb[i] = pcmData.GetSampleValueInFloat(0, i);
                }
                pcmData = null;
                pcm     = null;

                inPcmOfCh.Add(fb);
            }

            {
                CallEvent(EventCallbackTypes.PrepareDataCompleted, PROGRESS_PREPARE_END, hr);
            }


            System.Diagnostics.Debug.Assert(0.5 <= ca.mSampleRateScale & ca.mSampleRateScale <= 2.0);
            int sampleRateTo  = (int)(ca.mSampleRateScale * metaR.sampleRate);
            int sampleTotalTo = (int)(ca.mSampleRateScale * metaR.totalSamples);

            // metaW: 出力フォーマット。
            var metaW = new Metadata(metaR);

            if (ca.mSampleRateScale < 1.0)
            {
                // 曲の長さを縮めると、エイリアシング雑音が出るのでローパスフィルターが必要になる。
                // 出力サンプルレートを倍にしてローパスフィルターを省略。
                sampleRateTo  = (int)(2.0 * ca.mSampleRateScale * metaR.sampleRate);
                sampleTotalTo = (int)(2.0 * ca.mSampleRateScale * metaR.totalSamples);

                metaW.sampleRate *= 2;
            }

            metaW.bitsPerSample = 24;
            metaW.totalSamples  = sampleTotalTo;

            // ローパスフィルターが不要になる条件。
            System.Diagnostics.Debug.Assert(metaR.sampleRate <= metaW.sampleRate);

            var outPcmOfCh = new List <float[]>();

            for (int ch = 0; ch < metaR.channels; ++ch)
            {
                var inPcm = inPcmOfCh[ch];
                mResampleGpu.Setup(SINC_CONVOLUTION_N, inPcm,
                                   (int)metaR.totalSamples, metaR.sampleRate, sampleRateTo, sampleTotalTo);
                for (int i = 0; i < sampleTotalTo; i += GPU_WORK_COUNT)
                {
                    // 出力サンプル数countの調整。
                    int count = GPU_WORK_COUNT;
                    if (sampleTotalTo < i + count)
                    {
                        count = sampleTotalTo - i;
                    }

                    hr = mResampleGpu.Dispatch(i, count);
                    if (hr < 0)
                    {
                        CallEvent(EventCallbackTypes.ConvertFailed, 0, hr);
                        return(hr);
                    }
                    else
                    {
                        float progress0to1 = ((float)ch / metaR.channels)
                                             + (1.0f / metaR.channels) * ((float)i / sampleTotalTo);
                        int percent = (int)(PROGRESS_CONV_START +
                                            progress0to1 * (PROGRESS_CONV_END - PROGRESS_CONV_START));
                        CallEvent(EventCallbackTypes.ConvProgress, percent, hr);
                    }
                }

                var outPcm = new float[sampleTotalTo];
                mResampleGpu.ResultGetFromGpuMemory(outPcm);
                outPcmOfCh.Add(outPcm);

                mResampleGpu.Unsetup();
            }

            CallEvent(EventCallbackTypes.WriteStarted, PROGRESS_CONV_END, hr);

            var flacW = new FlacRW();

            hr = flacW.EncodeInit(metaW);
            if (hr < 0)
            {
                CallEvent(EventCallbackTypes.WriteFailed, 0, hr);
                return(hr);
            }

            if (0 < metaR.pictureBytes)
            {
                // 画像。
                byte[] metaPicture = null;
                flacR.GetDecodedPicture(out metaPicture, metaR.pictureBytes);
                hr = flacW.EncodeSetPicture(metaPicture);
                if (hr < 0)
                {
                    CallEvent(EventCallbackTypes.WriteFailed, 0, hr);
                    return(hr);
                }
            }


            for (int ch = 0; ch < metaW.channels; ++ch)
            {
                // 24bitのbyteAry作成。
                var floatAry = outPcmOfCh[ch];
                var byteAry  = new LargeArray <byte>(3 * metaW.totalSamples); //< 24bitなので1サンプルあたり3バイト。
                for (long i = 0; i < metaW.totalSamples; ++i)
                {
                    var b = PcmDataUtil.ConvertTo24bitLE(floatAry[i]);
                    byteAry.CopyFrom(b, 0, i * 3, 3);
                }

                flacW.EncodeAddPcm(ch, byteAry);
            }

            hr = flacW.EncodeRun(ca.mOutPath);
            if (hr < 0)
            {
                CallEvent(EventCallbackTypes.WriteFailed, 0, hr);
                return(hr);
            }

            flacW.EncodeEnd();
            flacR.DecodeEnd();

            return(hr);
        }
Пример #6
0
        public string ReadHeader(BinaryReader br, out PcmData pcmData)
        {
            pcmData = new PcmData();

            ResultType result = ReadFormChunkHeader(br);

            if (result != ResultType.Success)
            {
                mSB.Append(string.Format("Error: Form Chunkチャンクの読み込み失敗。{0}\r\n", result));
                return(mSB.ToString());
            }

            if (mIsAIFC)
            {
                // AIFCの場合、FVERチャンクが来る(required)
                result = ReadFverChunk(br);
                if (ResultType.Success != result)
                {
                    mSB.Append(string.Format("Error: AIFC FVERチャンクのエラー。{0}\r\n", result));
                    return(mSB.ToString());
                }
            }

            result = ReadCommonChunk(br);
            if (ResultType.Success != result)
            {
                mSB.Append(string.Format("Error: COMMチャンクのエラー。{0}\r\n", result));
                return(mSB.ToString());
            }

            result = ReadSoundDataChunk(br);
            if (ResultType.Success != result)
            {
                mSB.Append(string.Format("Error: SSNDチャンクのエラー。{0}\r\n", result));
                return(mSB.ToString());
            }

            if (16 != BitsPerSample &&
                24 != BitsPerSample)
            {
                mSB.Append(string.Format("Info: 量子化ビット数がエキゾチックです。{0} bit\r\n", BitsPerSample));
                return(mSB.ToString());
            }

            pcmData.SetFormat(
                NumChannels,
                BitsPerSample,
                BitsPerSample,
                SampleRate,
                PcmData.ValueRepresentationType.SInt,
                NumFrames);

            result = ReadID3Chunk(br);
            switch (result)
            {
            case ResultType.NotFoundID3Header:
                // ID3ヘッダーが無い。
                break;

            case ResultType.Success:
                // ID3読み込み成功
                pcmData.DisplayName  = TitleName;
                pcmData.AlbumTitle   = AlbumName;
                pcmData.ArtistName   = ArtistName;
                pcmData.ComposerName = Composer;
                if (0 < PictureBytes)
                {
                    pcmData.SetPicture(PictureBytes, PictureData);
                }
                mSB.Append(string.Format("    TitleName={0}\r\n", TitleName));
                mSB.Append(string.Format("    AlbumName={0}\r\n", AlbumName));
                mSB.Append(string.Format("    ArtistName={0}\r\n", ArtistName));
                mSB.Append(string.Format("    Composer={0}\r\n", Composer));
                mSB.Append(string.Format("    ID3チャンク読み込み終了。\r\n"));
                break;

            default:
                mSB.Append(string.Format("Error: ID3チャンクのエラー。{0}\r\n", result));
                return(mSB.ToString());
            }

            mSB.Append("正常終了。\r\n");

            return(mSB.ToString());
        }
Пример #7
0
        private bool ItUpsampleDo(FirWorkerArgs args, PcmData pcmDataIn, out PcmData pcmDataOut)
        {
            pcmDataOut = new PcmData();
            pcmDataOut.SetFormat(pcmDataIn.NumChannels, 64, 64,
                                 pcmDataIn.SampleRate * mFreqMagnitude,
                                 PcmData.ValueRepresentationType.SFloat, pcmDataIn.NumFrames * mFreqMagnitude);
            pcmDataOut.SetSampleArray(new byte[pcmDataOut.NumFrames * pcmDataOut.BitsPerFrame / 8]);

            var pcm = pcmDataOut;

            switch (mItUpsampleType)
            {
            case ItUpsampleType.ImpulseTrain:
                Parallel.For(0, pcmDataIn.NumFrames, (pos) => {
                    for (int ch = 0; ch < pcmDataIn.NumChannels; ++ch)
                    {
                        var v = pcmDataIn.GetSampleValueInDouble(ch, pos);
                        pcm.SetSampleValueInDouble(ch, pos * mFreqMagnitude, v);
                    }
                });
                break;

            case ItUpsampleType.SampleHold:
                Parallel.For(0, pcmDataIn.NumFrames, (pos) => {
                    for (int ch = 0; ch < pcmDataIn.NumChannels; ++ch)
                    {
                        var v = pcmDataIn.GetSampleValueInDouble(ch, pos);
                        for (int i = 0; i < mFreqMagnitude; ++i)
                        {
                            pcm.SetSampleValueInDouble(ch, pos * mFreqMagnitude + i, v);
                        }
                    }
                });
                break;

            case ItUpsampleType.Linear:
                Parallel.For(0, pcmDataIn.NumFrames - 1, (pos) => {
                    // 0 <= pos <= NumFrames-2まで実行する
                    for (int ch = 0; ch < pcmDataIn.NumChannels; ++ch)
                    {
                        var v0 = pcmDataIn.GetSampleValueInDouble(ch, pos);
                        var v1 = pcmDataIn.GetSampleValueInDouble(ch, pos + 1);
                        for (int i = 0; i < mFreqMagnitude; ++i)
                        {
                            var ratio = (double)i / mFreqMagnitude;
                            var v     = v0 * (1 - ratio) + v1 * ratio;
                            pcm.SetSampleValueInDouble(ch, pos * mFreqMagnitude + i, v);
                        }
                    }
                });

                // 最後の1区間は0に向かう
                for (int ch = 0; ch < pcmDataIn.NumChannels; ++ch)
                {
                    var pos = pcmDataIn.NumFrames - 1;
                    var v   = pcmDataIn.GetSampleValueInDouble(ch, pos);
                    for (int i = 0; i < mFreqMagnitude; ++i)
                    {
                        pcm.SetSampleValueInDouble(ch, pos * mFreqMagnitude + i, v * (mFreqMagnitude - i - 1) / mFreqMagnitude);
                    }
                }
                break;

            case ItUpsampleType.Cubic: {
                var    h = new double[4 * mFreqMagnitude];
                double a = -0.5;
                for (int i = 0; i < mFreqMagnitude; ++i)
                {
                    double t = (double)i / mFreqMagnitude;
                    h[mFreqMagnitude * 2 + i] = (a + 2) * t * t * t - (a + 3) * t * t + 1;
                    h[mFreqMagnitude * 2 - i] = h[mFreqMagnitude * 2 + i];
                }
                for (int i = mFreqMagnitude; i < mFreqMagnitude * 2; ++i)
                {
                    double t = (double)i / mFreqMagnitude;
                    h[mFreqMagnitude * 2 + i] = a * t * t * t - 5 * a * t * t + 8 * a * t - 4 * a;
                    h[mFreqMagnitude * 2 - i] = h[mFreqMagnitude * 2 + i];
                }
                Parallel.For(0, pcmDataOut.NumFrames, (pos) => {
                        for (int ch = 0; ch < pcmDataIn.NumChannels; ++ch)
                        {
                            var x = new double[4 * mFreqMagnitude];
                            for (int i = 0; i < 4 * mFreqMagnitude; ++i)
                            {
                                if (0 == (pos + i) % mFreqMagnitude)
                                {
                                    x[i] = pcmDataIn.GetSampleValueInDouble(ch, (pos + i) / mFreqMagnitude);
                                }
                            }
                            double v = 0;
                            for (int i = 0; i < 4 * mFreqMagnitude; ++i)
                            {
                                v += h[i] * x[i];
                            }
                            pcm.SetSampleValueInDouble(ch, pos, v);
                        }
                    });
            }
            break;

            default:
                System.Diagnostics.Debug.Assert(false);
                break;
            }

            return(true);
        }