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