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.SetSampleLargeArray(reader.GetSampleLargeArray()); 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); }