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); }
/// <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); }
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; }
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); }
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; }
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; }
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; }
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; }
/// <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; }
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; }