Пример #1
0
        public PcmData MonoToStereo()
        {
            System.Diagnostics.Debug.Assert(NumChannels == 1);

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            var newSampleArray = new WWUtil.LargeArray <byte>(mSampleLargeArray.LongLength * 2);

            {
                int bytesPerSample = BitsPerSample / 8;

                // sampleArrayのフレーム数はこれよりも少ないことがある。
                // 実際に存在するサンプル数sampleFramesだけ処理する。
                long sampleFrames = mSampleLargeArray.LongLength / bytesPerSample; // NumChannels==1なので。
                long fromPosBytes = 0;
                for (long frame = 0; frame < sampleFrames; ++frame)
                {
                    for (int offs = 0; offs < bytesPerSample; ++offs)
                    {
                        byte b = mSampleLargeArray.At(fromPosBytes + offs);
                        newSampleArray.Set(fromPosBytes * 2 + offs, b);
                        newSampleArray.Set(fromPosBytes * 2 + bytesPerSample + offs, b);
                    }
                    fromPosBytes += bytesPerSample;
                }
            }
            PcmData newPcmData = new PcmData();

            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(2, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleLargeArray(newSampleArray);

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

            WWMFReader.Metadata meta;
            int rv = WWMFReader.ReadHeader(path, out meta);

            if (0 <= rv)
            {
                pd.SetFormat(meta.numChannels, meta.bitsPerSample, meta.bitsPerSample, meta.sampleRate,
                             PcmData.ValueRepresentationType.SInt, meta.numApproxFrames);
                pd.SampleDataType = PcmDataLib.PcmData.DataType.PCM;
                pd.DisplayName    = meta.title;
                pd.AlbumTitle     = meta.album;
                pd.ArtistName     = meta.artist;
                pd.ComposerName   = meta.composer;
                if (null != meta.picture)
                {
                    pd.SetPicture(meta.picture.Length, meta.picture);
                }

                pd.BitRate           = meta.bitRate;
                pd.IsLossyCompressed = true;

                if (CheckAddPcmData(path, pd, true))
                {
                    result = true;
                }
            }
            else
            {
                LoadErrorMessageAdd(string.Format(CultureInfo.InvariantCulture, Properties.Resources.ReadFileFailed + " {1}: {2}{3}",
                                                  "MP3", rv, path, Environment.NewLine));
            }

            return(result);
        }
Пример #5
0
        public PcmData ConvertChannelCount(int newCh)
        {
            if (NumChannels == newCh)
            {
                // 既に希望のチャンネル数である。
                return(this);
            }

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            // 新しいサンプルサイズ
            // NumFramesは総フレーム数。sampleArrayのフレーム数はこれよりも少ないことがある。
            // 実際に存在するサンプル数sampleFramesだけ処理する。
            int  bytesPerSample = BitsPerSample / 8;
            long sampleFrames   = mSampleLargeArray.LongLength / (BitsPerFrame / 8);
            var  newSampleArray = new WWUtil.LargeArray <byte>((long)newCh * bytesPerSample * sampleFrames);

            for (long frame = 0; frame < sampleFrames; ++frame)
            {
                int copyBytes = NumChannels * bytesPerSample;
                if (newCh < NumChannels)
                {
                    // チャンネル数が減る場合。
                    copyBytes = newCh * bytesPerSample;
                }

                newSampleArray.CopyFrom(mSampleLargeArray, (long)NumChannels * bytesPerSample * frame,
                                        (long)newCh * bytesPerSample * frame, copyBytes);

                if (SampleDataType == DataType.DoP &&
                    NumChannels < newCh)
                {
                    // 追加したチャンネルにDSD無音をセットする。
                    switch (bytesPerSample)
                    {
                    case 3:
                        for (int ch = NumChannels; ch < newCh; ++ch)
                        {
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 0, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 1, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 2, (byte)((frame & 1) == 1 ? 0xfa : 0x05));
                        }
                        break;

                    case 4:
                        for (int ch = NumChannels; ch < newCh; ++ch)
                        {
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 1, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 2, 0x69);
                            newSampleArray.Set((frame * newCh + ch) * bytesPerSample + 3, (byte)((frame & 1) == 1 ? 0xfa : 0x05));
                        }
                        break;
                    }
                }
            }

            PcmData newPcmData = new PcmData();

            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(newCh, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleLargeArray(newSampleArray);

            return(newPcmData);
        }
        /// <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;
        }
Пример #7
0
        public PcmData MonoToStereo()
        {
            System.Diagnostics.Debug.Assert(NumChannels == 1);

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            byte [] newSampleArray = new byte[mSampleArray.LongLength * 2];

            {
                int bytesPerSample = BitsPerSample / 8;

                // NumFramesは総フレーム数。sampleArrayのフレーム数はこれよりも少ないことがある。
                // 実際に存在するサンプル数sampleFramesだけ処理する。
                long sampleFrames = mSampleArray.LongLength / bytesPerSample;
                long fromPosBytes = 0;
                for (long frame = 0; frame < sampleFrames; ++frame) {
                    for (int offs = 0; offs < bytesPerSample; ++offs) {
                        newSampleArray[fromPosBytes * 2 + offs] = mSampleArray[fromPosBytes + offs];
                        newSampleArray[fromPosBytes * 2 + bytesPerSample + offs] = mSampleArray[fromPosBytes + offs];
                    }
                    fromPosBytes += bytesPerSample;
                }
            }
            PcmData newPcmData = new PcmData();
            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(2, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleArray(newSampleArray);

            return newPcmData;
        }
Пример #8
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;
        }
Пример #9
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;
        }
Пример #10
0
        /// <summary>
        /// WAVファイルのヘッダ部分を読み込む。
        /// </summary>
        /// <returns>読めたらtrue</returns>
        private bool ReadWavFileHeader(string path)
        {
            bool result = false;
            var pd = new PcmDataLib.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 ("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;
                        }
                    }
                    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;
        }
Пример #11
0
        public PcmData ConvertChannelCount(int newCh)
        {
            if (NumChannels == newCh) {
                // 既に希望のチャンネル数である。
                return this;
            }

            // サンプルあたりビット数が8の倍数でないとこのアルゴリズムは使えない
            System.Diagnostics.Debug.Assert((BitsPerSample & 7) == 0);

            // 新しいサンプルサイズ
            // NumFramesは総フレーム数。sampleArrayのフレーム数はこれよりも少ないことがある。
            // 実際に存在するサンプル数sampleFramesだけ処理する。
            int bytesPerSample = BitsPerSample / 8;
            long sampleFrames = mSampleArray.LongLength / (BitsPerFrame / 8);
            var newSampleArray = new byte[newCh * bytesPerSample * sampleFrames];

            for (long frame = 0; frame < sampleFrames; ++frame) {
                int copyBytes = NumChannels * bytesPerSample;
                if (newCh < NumChannels) {
                    // チャンネル数が減る場合。
                    copyBytes = newCh * bytesPerSample;
                }

                Array.Copy(mSampleArray, NumChannels * bytesPerSample * frame,
                    newSampleArray, newCh * bytesPerSample * frame,
                    copyBytes);
                if (SampleDataType == DataType.DoP
                        && NumChannels < newCh) {
                    // 追加したチャンネルにDSD無音をセットする。
                    switch (bytesPerSample) {
                    case 3:
                        for (int ch = NumChannels; ch < newCh; ++ch) {
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 0] = 0x69;
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 1] = 0x69;
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 2] = (byte)((frame & 1) == 1 ? 0xfa : 0x05);
                        }
                        break;
                    case 4:
                        for (int ch = NumChannels; ch < newCh; ++ch) {
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 1] = 0x69;
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 2] = 0x69;
                            newSampleArray[(frame * newCh + ch) * bytesPerSample + 3] = (byte)((frame & 1) == 1 ? 0xfa : 0x05);
                        }
                        break;
                    }
                }
            }

            PcmData newPcmData = new PcmData();
            newPcmData.CopyHeaderInfoFrom(this);
            newPcmData.SetFormat(newCh, BitsPerSample, ValidBitsPerSample, SampleRate, SampleValueRepresentationType, NumFrames);
            newPcmData.SetSampleArray(newSampleArray);

            return newPcmData;
        }