public int DecodeStreamStart(string path) { mDecodedMetadata = null; mPcmAllBuffer = null; mId = NativeMethods.WWFlacRW_Decode(NativeMethods.WWFLAC_FRDT_STREAM_ONE, path); return(mId); }
public LargeArray <WWComplex> InverseFft(LargeArray <WWComplex> aFrom, double?compensation = null) { for (int i = 0; i < aFrom.LongLength; ++i) { var t = new WWComplex(aFrom.At(i).real, -aFrom.At(i).imaginary); aFrom.Set(i, t); } var aTo = ForwardFft(aFrom); double c = 1.0 / mNumPoints; if (compensation != null) { c = (double)compensation; } for (int i = 0; i < aTo.LongLength; ++i) { var t = new WWComplex(aTo.At(i).real *c, -aTo.At(i).imaginary *c); aTo.Set(i, t); } return(aTo); }
/// <summary> /// ヘッダと全PCMデータを抽出する。 /// この関数呼び出し後 /// ・GetDecodedMetadata()でメタデータを取り出す。 /// ・GetDecodedCuesheet()でキューシートを取り出す。 /// ・GetDecodedPicture()でアルバムカバー画像を取り出す。 /// ・GetDecodedPcmBytes()でPCMデータを取り出す。 /// ・DecodeEnd()で後片付けする。 /// /// DecodeAll()が中で呼んでいる関数を個別に呼び出しても良い。 /// </summary> /// <param name="path">FLACのファイル名</param> /// <returns>0以上のとき成功。負のときFlacErrorCode</returns> public int DecodeAll(string path) { int rv = 0; rv = DecodeStreamStart(path); if (rv < 0) { return(rv); } rv = GetDecodedMetadata(out mDecodedMetadata); if (rv < 0) { return(rv); } mPcmAllBuffer = new LargeArray <byte>(mDecodedMetadata.PcmBytes); long pos = 0; while (pos < mDecodedMetadata.PcmBytes) { byte[] fragment; rv = DecodeStreamOne(out fragment); if (rv < 0) { return(rv); } mPcmAllBuffer.CopyFrom(fragment, 0, pos, fragment.Length); pos += fragment.Length; } // mPcmAllBufferから取り出す。 return(0); }
/// <summary> /// FLACファイルのヘッダー部分を読み込んでメタデータを取り出す。 /// この関数呼び出し後 /// ・GetDecodedMetadata()でメタデータを取り出す。 /// ・GetDecodedCuesheet()でキューシートを取り出す。 /// ・GetDecodedPicture()でアルバムカバー画像を取り出す。 /// </summary> /// <param name="path">FLACファイルのパス</param> /// <returns>0以上のとき成功。負のときFlacErrorCode</returns> public int DecodeHeader(string path) { mDecodedMetadata = null; mPcmAllBuffer = null; mId = NativeMethods.WWFlacRW_Decode(NativeMethods.WWFLAC_FRDT_HEADER, path); return(mId); }
public WWRadix2FftLargeArray(long numPoints) { if (!Functions.IsPowerOfTwo(numPoints) || numPoints < 2) { throw new ArgumentException("numPoints must be power of two integer and larger than 2"); } mNumPoints = numPoints; mWn = new LargeArray <WWComplex>(mNumPoints); for (long i = 0; i < mNumPoints; ++i) { double angle = -2.0 * Math.PI * i / mNumPoints; mWn.Set(i, new WWComplex(Math.Cos(angle), Math.Sin(angle))); } // mNumStage == log_2(mNumPoints) long t = mNumPoints; for (int i = 0; 0 < t; ++i) { t >>= 1; mNumStage = i; } mBitReversalTable = new LargeArray <ulong>(mNumPoints); for (long i = 0; i < mNumPoints; ++i) { mBitReversalTable.Set(i, BitReversal(mNumStage, (ulong)i)); } }
public LargeArray <WWComplex> ForwardFft(LargeArray <WWComplex> aFrom) { if (aFrom == null || aFrom.LongLength != mNumPoints) { throw new ArgumentOutOfRangeException("aFrom"); } var aTo = new LargeArray <WWComplex>(aFrom.LongLength); var aTmp0 = new LargeArray <WWComplex>(mNumPoints); for (int i = 0; i < aTmp0.LongLength; ++i) { aTmp0.Set(i, aFrom.At((long)mBitReversalTable.At(i))); } var aTmp1 = new LargeArray <WWComplex>(mNumPoints); for (int i = 0; i < aTmp1.LongLength; ++i) { aTmp1.Set(i, WWComplex.Zero()); } var aTmps = new LargeArray <WWComplex> [2]; aTmps[0] = aTmp0; aTmps[1] = aTmp1; for (int i = 0; i < mNumStage - 1; ++i) { FftStageN(i, aTmps[((i & 1) == 1) ? 1 : 0], aTmps[((i & 1) == 0) ? 1 : 0]); } FftStageN(mNumStage - 1, aTmps[(((mNumStage - 1) & 1) == 1) ? 1 : 0], aTo); return(aTo); }
public void Chunks() { var source = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; var actuals = LargeArray.Chunk(source, 4).ToList(); Assert.Equal(4, actuals.Count); Assert.Equal(4, actuals[0].Length); Assert.Equal(4, actuals[1].Length); Assert.Equal(4, actuals[2].Length); Assert.Equal(2, actuals[3].Length); Assert.Equal(1, actuals[0][0]); Assert.Equal(2, actuals[0][1]); Assert.Equal(3, actuals[0][2]); Assert.Equal(4, actuals[0][3]); Assert.Equal(5, actuals[1][0]); Assert.Equal(6, actuals[1][1]); Assert.Equal(7, actuals[1][2]); Assert.Equal(8, actuals[1][3]); Assert.Equal(9, actuals[2][0]); Assert.Equal(10, actuals[2][1]); Assert.Equal(11, actuals[2][2]); Assert.Equal(12, actuals[2][3]); Assert.Equal(13, actuals[3][0]); Assert.Equal(14, actuals[3][1]); }
public int AddPcm(int ch, LargeArray <byte> pcmW) { int rv; rv = mFlacW.EncodeAddPcm(ch, pcmW); return(rv); }
/// <summary> /// dataにcoeffsを畳み込む。 /// </summary> public LargeArray <float> Convolution(LargeArray <float> data, float[] coeffs) { mMaxMagnitude = 0; var r = new LargeArray <float>(data.LongLength); // rIdx: 出力サンプル列rの書き込みidx。1づつ増える。 for (long rIdx = 0; rIdx < data.LongLength; ++rIdx) { // v: 畳み込み結果。 float v = 0; // dIdx: dataの読み出し要素番号。 long dIdx = rIdx - coeffs.Length / 2; // cIdx: coeffsの読み出し要素番号。1づつ減る。 for (int cIdx = coeffs.Length - 1; 0 <= cIdx; --cIdx) { // dataの範囲外を読まないようにする。 if (0 <= dIdx && dIdx < data.LongLength) { v += data.At(dIdx++) * coeffs[cIdx]; } } if (mMaxMagnitude < Math.Abs(v)) { mMaxMagnitude = v; } r.Set(rIdx, v); } return(r); }
public static int ReadHeaderAndData( string sourceFile, out Metadata meta_return, out LargeArray <byte> data) { int hr = 0; data = new LargeArray <byte>(0); hr = ReadHeader(sourceFile, out meta_return); if (hr < 0) { return(hr); } // データのバイト数はこの時点で不明。 // 全て読んでから数える。 hr = NativeMethods.WWMFReaderIFReadDataStart(sourceFile); if (hr < 0) { return(hr); } int instanceId = hr; long bufTotalBytes = 0; var buf = new byte[1024 * 1024]; var bufList = new List <byte[]>(); while (true) { long bufBytes = buf.Length; hr = NativeMethods.WWMFReaderIFReadDataFragment(instanceId, buf, ref bufBytes); if (hr < 0) { break; } if (bufBytes == 0) { break; } var bufTrim = new byte[bufBytes]; Array.Copy(buf, 0, bufTrim, 0, bufBytes); bufList.Add(bufTrim); bufTotalBytes += bufBytes; } NativeMethods.WWMFReaderIFReadDataEnd(instanceId); // データのバイト数が確定。 data = WWUtil.ListUtils <byte> .GetLargeArrayFragment(bufList, 0, bufTotalBytes); meta_return.numExactFrames = data.LongLength / (meta_return.numChannels * meta_return.bitsPerSample / 8); return(hr); }
/// <summary> /// 指定チャンネルのPCMデータを取得。 /// </summary> /// <param name="ch">チャンネル番号 0から始まる。</param> /// <param name="posSamples">取得開始サンプル番号。</param> /// <param name="copySamples">取得するサンプル数。</param> /// <returns>float型のPCMデータ。-1 ≦ v < +1</returns> public LargeArray <float> GetFloatPcmOfChannel(int ch, long posSamples, long copySamples) { System.Diagnostics.Debug.Assert(mDecodedMetadata != null); System.Diagnostics.Debug.Assert(mPcmAllBuffer != null); System.Diagnostics.Debug.Assert(0 <= ch && ch < mDecodedMetadata.channels); int bpf = mDecodedMetadata.BytesPerFrame; int bps = mDecodedMetadata.BytesPerSample; // copySamplesを決定します。 long totalSamples = mPcmAllBuffer.LongLength / bpf; if (totalSamples < posSamples + copySamples) { copySamples = (int)(totalSamples - posSamples); } if (copySamples < 0) { copySamples = 0; } var samples = new LargeArray <float>(copySamples); long toIdx = 0; switch (bps) { case 2: for (long pos = posSamples; pos < posSamples + copySamples; ++pos) { long idx = bpf * pos + ch * bps; short vS = (short)(mPcmAllBuffer.At(idx) + (mPcmAllBuffer.At(idx + 1) << 8)); float vF = vS / 32768.0f; samples.Set(toIdx++, vF); //Console.WriteLine("{0:+00000;-00000}", vS); } break; case 3: for (long pos = posSamples; pos < posSamples + copySamples; ++pos) { long idx = bpf * pos + ch * bps; int vI = (int)((mPcmAllBuffer.At(idx + 0) << 8) + (mPcmAllBuffer.At(idx + 1) << 16) + (mPcmAllBuffer.At(idx + 2) << 24)); //Console.WriteLine("{0:+00000000;-00000000}", vI); float vF = vI / 2147483648.0f; samples.Set(toIdx++, vF); } break; default: throw new ArgumentException(string.Format("Unexpected BytesPerSample {0}", bps)); } return(samples); }
public void DecodeEnd() { NativeMethods.WWFlacRW_DecodeEnd(mId); mDecodedMetadata = null; mPcmAllBuffer = null; mId = (int)FlacErrorCode.IdNotFound; }
/// <summary> /// PCMデータを無加工で読み出す。 /// </summary> /// <param name="startFrame">0を指定すると最初から。</param> /// <param name="endFrame">負の値を指定するとファイルの最後まで。</param> /// <returns>false: ファイルの読み込みエラーなど</returns> public bool ReadDataChunkData(BinaryReader br, int numChannels, int bitsPerSample, long startFrame, long endFrame) { br.BaseStream.Seek(Offset, SeekOrigin.Begin); // endBytesがファイルの終わり指定(負の値)の場合の具体的位置を設定する。 // startBytesとendBytesがファイルの終わり以降を指していたら修正する。 // ・endBytesがファイルの終わり以降…ファイルの終わりを指す。 // ・startBytesがファイルの終わり以降…サイズ0バイトのWAVファイルにする。 int frameBytes = bitsPerSample / 8 * numChannels; long startBytes = startFrame * frameBytes; long endBytes = endFrame * frameBytes; System.Diagnostics.Debug.Assert(0 <= startBytes); if (endBytes < 0 || (NumFrames * frameBytes) < endBytes) { // 終了位置はファイルの終わり。 endBytes = NumFrames * frameBytes; } long newNumFrames = (endBytes - startBytes) / frameBytes; if (newNumFrames <= 0 || NumFrames * frameBytes <= startBytes || endBytes <= startBytes) { // サイズが0バイトのWAV。 mRawData = null; NumFrames = 0; return(true); } if (0 < startBytes) { PcmDataLib.PcmDataUtil.BinaryReaderSkip(br, startBytes); } mRawData = new LargeArray <byte>(newNumFrames * frameBytes); int fragmentBytes = 1048576; for (long pos = 0; pos < mRawData.LongLength; pos += fragmentBytes) { int bytes = fragmentBytes; if (mRawData.LongLength - pos < bytes) { bytes = (int)(mRawData.LongLength - pos); } var buff = br.ReadBytes(bytes); mRawData.CopyFrom(buff, 0, pos, bytes); } NumFrames = newNumFrames; return(true); }
public SampleData1ch(long size) { sdmData = new LargeArray <byte>(size); pos = 0; // 念のため無音をセットする。 for (long i = 0; i < size; ++i) { sdmData.Set(i, 0x69); } }
private float[] PrepareSampleDataForFFT(LargeArray <float> from, long fromPos, float[] w) { var r = new float[w.Length]; for (int i = 0; i < r.Length; ++i) { float v = from.At(fromPos + i); r[i] = v * w[i]; } return(r); }
private static void Main(string[] args) { //var summary = BenchmarkRunner.Run<PEFileMagic>(); #if RELEASE var summary = BenchmarkRunner.Run <LargeArray>(); #else var la = new LargeArray { size = 1 }; la.TraditionalTest(); #endif }
public bool AllocateCaptureMemory(long bytes) { try { mCapturedPcmData = null; mCapturedPcmData = new LargeArray <byte>(bytes); } catch (Exception ex) { Console.WriteLine(ex); return(false); } mNextWritePos = 0; return(true); }
public void Combines() { var source = new[] { new byte[] { 1, 2, 3, 4 }, new byte[] { 5, 6, 7, 8 }, new byte[] { 9, 10 }, }; var expected = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var actual = LargeArray.Combine(source); Assert.Equal(expected, actual); }
private LargeArray <float> StereoToMono(LargeArray <byte> v) { var m = new LargeArray <float>(v.LongLength / 4); for (long i = 0; i < v.LongLength / 4; ++i) { short l = (short)((int)v.At(i * 4 + 0) + 256 * v.At(i * 4 + 1)); short r = (short)((int)v.At(i * 4 + 2) + 256 * v.At(i * 4 + 3)); short mix = (short)((l + r) / 2); m.Set(i, mix / 32768.0f); } return(m); }
//[Test] //public unsafe void TestLargeUnmanagedArray() //{ // Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0); // using (LargeUnmanagedArray<int> array = new LargeUnmanagedArray<int>(4, Globals.MemoryPool, ptr => *(int*)ptr, (ptr, v) => *(int*)ptr = v)) // { // TestArray(array); // } // Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0); //} public void TestArray(LargeArray <int> array) { for (int x = 0; x < 250000; x++) { if (x >= array.Capacity) { HelperFunctions.ExpectError(() => array[x] = x); array.SetCapacity(array.Capacity + 1); } array[x] = x; } for (int x = 0; x < 250000; x++) { Assert.AreEqual(array[x], x); } }
//[Test] //public unsafe void TestLargeUnmanagedArray() //{ // Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0); // using (LargeUnmanagedArray<int> array = new LargeUnmanagedArray<int>(4, Globals.MemoryPool, ptr => *(int*)ptr, (ptr, v) => *(int*)ptr = v)) // { // TestArray(array); // } // Assert.AreEqual(Globals.MemoryPool.AllocatedBytes, 0); //} public void TestArray(LargeArray<int> array) { for (int x = 0; x < 250000; x++) { if (x >= array.Capacity) { HelperFunctions.ExpectError(() => array[x] = x); array.SetCapacity(array.Capacity + 1); } array[x] = x; } for (int x = 0; x < 250000; x++) { Assert.AreEqual(array[x], x); } }
private LargeArray <byte> CreatePcmSamples(double[] mls, WasapiCS.SampleFormatType sft, int numCh, int playCh) { int sampleBytes = (WasapiCS.SampleFormatTypeToUseBitsPerSample(sft) / 8); int frameBytes = sampleBytes * numCh; long bytes = (long)mls.Length * frameBytes; var r = new LargeArray <byte>(bytes); long writePos = 0; for (long i = 0; i < mls.Length; ++i) { for (int ch = 0; ch < numCh; ++ch) { if (ch != playCh) { for (int c = 0; c < sampleBytes; ++c) { r.Set(writePos++, 0); } } else { int v = 0x7fffffff; // -6dBする。 v /= 2; if (mls[i] < 0) { v = -v; } uint uV = (uint)v; for (int c = 0; c < sampleBytes; ++c) { byte b = (byte)(uV >> (8 * (4 - sampleBytes + c))); r.Set(writePos++, b); } } } } return(r); }
/// <summary> /// dataチャンクのヘッダ部分だけを読む。 /// 4バイトしか進まない。 /// </summary> public long ReadDataChunkHeader(BinaryReader br, long offset, byte[] fourcc, int numChannels, int bitsPerSample) { if (!PcmDataLib.PcmDataUtil.FourCCHeaderIs(fourcc, 0, "data")) { System.Diagnostics.Debug.Assert(false); return(0); } ChunkSize = br.ReadUInt32(); Offset = offset + 4; int frameBytes = bitsPerSample / 8 * numChannels; NumFrames = ChunkSize / frameBytes; mRawData = null; return(4); }
public static LargeArray <double> BlackmanWindow(long length) { // nは奇数 System.Diagnostics.Debug.Assert((length & 1) == 1); var window = new LargeArray <double>(length); // 教科書通りに計算すると両端の値が0.0になって // せっかくのデータが0にされて勿体無いので両端(pos==0とpos==length-1)の値はカットし、両端を1ずつ広げる long m = length + 1; for (long i = 0; i < length; ++i) { long pos = i + 1; double v = 0.42 - 0.5 * Math.Cos(2.0 * Math.PI * pos / m) + 0.08 * Math.Cos(4.0 * Math.PI * pos / m); window.Set(i, v); } return(window); }
private void PreparePcmData(StartTestingArgs args) { mMLSDecon = new MLSDeconvolution(args.order); var seq = mMLSDecon.MLSSequence(); var sampleData = CreatePcmSamples(seq, mPref.PlaySampleFormat, args.numChannels, args.testChannel); // mPcmPlay : テストデータ。このPCMデータを再生し、インパルス応答特性を調べる。 mPcmPlay = new PcmDataLib.PcmData(); mPcmPlay.SetFormat(args.numChannels, WasapiCS.SampleFormatTypeToUseBitsPerSample(mPref.PlaySampleFormat), WasapiCS.SampleFormatTypeToValidBitsPerSample(mPref.PlaySampleFormat), mPref.SampleRate, PcmDataLib.PcmData.ValueRepresentationType.SInt, seq.Length); mPcmPlay.SetSampleLargeArray(sampleData); // 録音データ置き場。Maximum Length Seqneuceのサイズよりも1サンプル多くしておく。 int recBytesPerSample = WasapiCS.SampleFormatTypeToUseBitsPerSample(mPref.RecSampleFormat) / 8; mCapturedPcmData = new LargeArray <byte>((long)recBytesPerSample * args.numChannels * (seq.Length + 1)); }
private void LoadPcm_DoWork(object sender, DoWorkEventArgs e) { string path = (string)e.Argument; var r = new LoadPcmResult(); r.path = path; r.result = false; r.pcmData = null; mPlayPcmData = null; try { using (var br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))) { var reader = new WavRWLib2.WavReader(); if (reader.ReadHeaderAndSamples(br, 0, -1) && reader.NumChannels == NUM_CHANNELS) { var b = reader.GetSampleLargeArray(); r.pcmData = new PcmDataLib.PcmData(); r.pcmData.SetFormat(NUM_CHANNELS, reader.BitsPerSample, reader.ValidBitsPerSample, reader.SampleRate, reader.SampleValueRepresentationType, reader.NumFrames); r.pcmData.SetSampleLargeArray(b); } } } catch (Exception ex) { Console.WriteLine(ex); r.pcmData = null; } if (r.pcmData == null) { try { var flacRW = new WWFlacRWCS.FlacRW(); int rv = flacRW.DecodeAll(r.path); if (0 <= rv) { WWFlacRWCS.Metadata metaData; flacRW.GetDecodedMetadata(out metaData); if (metaData.channels == NUM_CHANNELS) { var pcmBytes = new LargeArray <byte>(metaData.PcmBytes); int bytesPerSample = metaData.bitsPerSample / 8; var fragment = new byte[bytesPerSample]; for (long pos = 0; pos < metaData.totalSamples; ++pos) { for (int ch = 0; ch < NUM_CHANNELS; ++ch) { flacRW.GetDecodedPcmBytes(ch, pos * bytesPerSample, out fragment, bytesPerSample); pcmBytes.CopyFrom(fragment, 0, (long)bytesPerSample * (NUM_CHANNELS * pos + ch), bytesPerSample); } } r.pcmData = new PcmDataLib.PcmData(); r.pcmData.SetFormat(NUM_CHANNELS, metaData.bitsPerSample, metaData.bitsPerSample, metaData.sampleRate, PcmDataLib.PcmData.ValueRepresentationType.SInt, metaData.totalSamples); r.pcmData.SetSampleLargeArray(pcmBytes); } } flacRW.DecodeEnd(); } catch (Exception ex) { Console.WriteLine(ex); r.pcmData = null; } } if (r.pcmData != null) { r.result = true; } else { r.result = false; } e.Result = r; }
private void FftStageN(int stageNr, LargeArray <WWComplex> x, LargeArray <WWComplex> y) { /* * stage0: 2つの入力データにバタフライ演算 (length=8の時) 4回 (nRepeat=4, nSubRepeat=2) * y[0] = x[0] + w_n^(0*4) * x[1] * y[1] = x[0] + w_n^(1*4) * x[1] * * y[2] = x[2] + w_n^(0*4) * x[3] * y[3] = x[2] + w_n^(1*4) * x[3] * * y[4] = x[4] + w_n^(0*4) * x[5] * y[5] = x[4] + w_n^(1*4) * x[5] * * y[6] = x[6] + w_n^(0*4) * x[7] * y[7] = x[6] + w_n^(1*4) * x[7] */ /* * stage1: 4つの入力データにバタフライ演算 (length=8の時) 2回 (nRepeat=2, nSubRepeat=4) * y[0] = x[0] + w_n^(0*2) * x[2] * y[1] = x[1] + w_n^(1*2) * x[3] * y[2] = x[0] + w_n^(2*2) * x[2] * y[3] = x[1] + w_n^(3*2) * x[3] * * y[4] = x[4] + w_n^(0*2) * x[6] * y[5] = x[5] + w_n^(1*2) * x[7] * y[6] = x[4] + w_n^(2*2) * x[6] * y[7] = x[5] + w_n^(3*2) * x[7] */ /* * stage2: 8つの入力データにバタフライ演算 (length=8の時) 1回 (nRepeat=1, nSubRepeat=8) * y[0] = x[0] + w_n^(0*1) * x[4] * y[1] = x[1] + w_n^(1*1) * x[5] * y[2] = x[2] + w_n^(2*1) * x[6] * y[3] = x[3] + w_n^(3*1) * x[7] * y[4] = x[0] + w_n^(4*1) * x[4] * y[5] = x[1] + w_n^(5*1) * x[5] * y[6] = x[2] + w_n^(6*1) * x[6] * y[7] = x[3] + w_n^(7*1) * x[7] */ /* * stageN: */ long nRepeat = Pow2(mNumStage - stageNr - 1); long nSubRepeat = mNumPoints / nRepeat; for (long i = 0; i < nRepeat; ++i) { long offsBase = i * nSubRepeat; bool allZero = true; for (long j = 0; j < nSubRepeat / 2; ++j) { long offs = offsBase + (j % (nSubRepeat / 2)); if (Double.Epsilon < x.At(offs).Magnitude()) { allZero = false; break; } if (Double.Epsilon < x.At(offs + nSubRepeat / 2).Magnitude()) { allZero = false; break; } } if (allZero) { for (long j = 0; j < nSubRepeat; ++j) { y.Set(j + offsBase, WWComplex.Zero()); } } else { for (long j = 0; j < nSubRepeat; ++j) { long offs = offsBase + (j % (nSubRepeat / 2)); var t = x.At(offs); var t2 = WWComplex.Mul(mWn.At(j * nRepeat), x.At(offs + nSubRepeat / 2)); var t3 = WWComplex.Add(t, t2); y.Set(j + offsBase, t3); } } } }
private void PreparePcmData() { // mPcmSync : 長さ2秒、同期をするために頭に1回小さいクリック音を入れる。これを連続再生する。 // mPcmReady : 長さ2秒、頭に小さいクリック音がある。このPCMの直後にテストデータを再生する。 const int SYNC_PCM_SECONDS = 1; { mPcmSync = new PcmDataLib.PcmData(); mPcmSync.SetFormat(NUM_CHANNELS, WasapiCS.SampleFormatTypeToUseBitsPerSample(mPlaySampleFormat), WasapiCS.SampleFormatTypeToValidBitsPerSample(mPlaySampleFormat), mSampleRate, PcmDataLib.PcmData.ValueRepresentationType.SInt, SYNC_PCM_SECONDS * mSampleRate); var syncData = new LargeArray <byte>((WasapiCS.SampleFormatTypeToUseBitsPerSample(mPlaySampleFormat) / 8) * NUM_CHANNELS * mPcmSync.NumFrames); mPcmSync.SetSampleLargeArray(syncData); } { mPcmReady = new PcmDataLib.PcmData(); mPcmReady.CopyFrom(mPcmSync); var readyData = new LargeArray <byte>((WasapiCS.SampleFormatTypeToUseBitsPerSample(mPlaySampleFormat) / 8) * NUM_CHANNELS * mPcmSync.NumFrames); mPcmReady.SetSampleLargeArray(readyData); } switch (mPlaySampleFormat) { case WasapiCS.SampleFormatType.Sint16: mPcmSync.SetSampleValueInInt32(0, 0, 0x00040000); mPcmReady.SetSampleValueInInt32(0, 0, 0x00030000); break; case WasapiCS.SampleFormatType.Sint24: case WasapiCS.SampleFormatType.Sint32V24: mPcmSync.SetSampleValueInInt32(0, 0, 0x00000400); mPcmReady.SetSampleValueInInt32(0, 0, 0x00000300); break; default: System.Diagnostics.Debug.Assert(false); break; } // mPcmTest : テストデータ。このPCMデータを再生し、再生データと録音データが一致するかどうかを調べる。 if (mUseFile) { var conv = new WasapiPcmUtil.PcmFormatConverter(NUM_CHANNELS); mPcmTest = conv.Convert(mPlayPcmData, mPlaySampleFormat, new WasapiPcmUtil.PcmFormatConverter.BitsPerSampleConvArgs(WasapiPcmUtil.NoiseShapingType.None)); mNumTestFrames = mPcmTest.NumFrames; } else { mPcmTest = new PcmDataLib.PcmData(); mPcmTest.CopyHeaderInfoFrom(mPcmSync); var randData = new LargeArray <byte>((long)(WasapiCS.SampleFormatTypeToUseBitsPerSample(mPlaySampleFormat) / 8) * NUM_CHANNELS * mNumTestFrames); var fragment = new byte[4096]; for (long i = 0; i < randData.LongLength; i += fragment.Length) { long count = fragment.Length; if (randData.LongLength < i + count) { count = randData.LongLength - i; } mRand.NextBytes(fragment); randData.CopyFrom(fragment, 0, i, (int)count); } mPcmTest.SetSampleLargeArray(mNumTestFrames, randData); } // 録音データ置き場。 mCapturedPcmData = new LargeArray <byte>((long)(WasapiCS.SampleFormatTypeToUseBitsPerSample(mRecSampleFormat) / 8) * NUM_CHANNELS * (mNumTestFrames + (4 * SYNC_PCM_SECONDS) * mSampleRate)); }
/// <summary> /// float配列のPCMデータを指定ビットデプスのbyte配列PCMデータにする。 /// </summary> public static LargeArray <byte> ConvertToByteArrayPCM(LargeArray <float> from, int bytesPerSample) { var w = new LargeArray <byte>(from.LongLength * bytesPerSample); long wIdx = 0; switch (bytesPerSample) { case 2: for (long pos = 0; pos < from.LongLength; ++pos) { // 値vを取得。 float vF = from.At(pos); if (vF < -1.0f) { vF = -1.0f; } if (32767.0f / 32768.0f < vF) { vF = 32767.0f / 32768.0f; } // 型変換。 short vS = (short)(vF * 32768.0f); //Console.WriteLine("{0:+00000;-00000}", vS); // 書き込み。 w.Set(wIdx++, (byte)(vS & 0xff)); w.Set(wIdx++, (byte)((vS >> 8) & 0xff)); } break; case 3: for (long pos = 0; pos < from.LongLength; ++pos) { // 値vを取得。 float vF = from.At(pos); if (vF < -1.0f) { vF = -1.0f; } if (8388607.0f / 8388608.0f < vF) { vF = 8388607.0f / 8388608.0f; } // 型変換。 int vI = (int)(vF * 2147483648.0f); // 書き込み。 w.Set(wIdx++, (byte)((vI >> 8) & 0xff)); w.Set(wIdx++, (byte)((vI >> 16) & 0xff)); w.Set(wIdx++, (byte)((vI >> 24) & 0xff)); } break; default: throw new ArgumentException(string.Format("Unexpected BytesPerSample {0}", bytesPerSample)); } return(w); }
public static LargeArray <byte> ConvertTo32bitInt( int bitsPerSample, long numSamples, PcmData.ValueRepresentationType valueType, LargeArray <byte> data) { if (bitsPerSample == 32 && valueType == PcmData.ValueRepresentationType.SInt) { // すでに所望の形式。 return(data); } var data32 = new LargeArray <byte>(numSamples * 4); switch (valueType) { case PcmData.ValueRepresentationType.SInt: switch (bitsPerSample) { case 16: for (long i = 0; i < numSamples; ++i) { short v16 = (short)( (uint)data.At(i * 2) + ((uint)data.At(i * 2 + 1) << 8)); int v32 = v16; v32 *= 65536; data32.Set(i * 4 + 0, 0); data32.Set(i * 4 + 1, 0); data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16)); data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24)); } return(data32); case 24: for (long i = 0; i < numSamples; ++i) { int v32 = (int)( ((uint)data.At(i * 3 + 0) << 8) + ((uint)data.At(i * 3 + 1) << 16) + ((uint)data.At(i * 3 + 2) << 24)); data32.Set(i * 4 + 0, 0); data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8)); data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16)); data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24)); } return(data32); case 32: // 所望の形式。 System.Diagnostics.Debug.Assert(false); return(null); case 64: for (long i = 0; i < numSamples; ++i) { // 16.48 fixed point int v32 = (int)( ((uint)data.At(i * 8 + 2) << 0) + ((uint)data.At(i * 8 + 3) << 8) + ((uint)data.At(i * 8 + 4) << 16) + ((uint)data.At(i * 8 + 5) << 24)); data32.Set(i * 4 + 0, (byte)((v32 & 0x000000ff) >> 0)); data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8)); data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16)); data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24)); } return(data32); default: System.Diagnostics.Debug.Assert(false); return(null); } case PcmData.ValueRepresentationType.SFloat: for (long i = 0; i < numSamples; ++i) { double v; switch (bitsPerSample) { case 32: { var b4 = new byte[4]; data.CopyTo(i * 4, ref b4, 0, 4); v = BitConverter.ToSingle(b4, 0); } break; case 64: { var b8 = new byte[8]; data.CopyTo(i * 8, ref b8, 0, 8); v = BitConverter.ToDouble(b8, 0); } break; default: System.Diagnostics.Debug.Assert(false); return(null); } int v32 = 0; if (1.0f <= v) { v32 = Int32.MaxValue; } else if (v < -1.0f) { v32 = Int32.MinValue; } else { long vMax = -((long)Int32.MinValue); long v64 = (long)(v * vMax); if (Int32.MaxValue < v64) { v64 = Int32.MaxValue; } v32 = (int)v64; } data32.Set(i * 4 + 0, (byte)((v32 & 0x000000ff) >> 0)); data32.Set(i * 4 + 1, (byte)((v32 & 0x0000ff00) >> 8)); data32.Set(i * 4 + 2, (byte)((v32 & 0x00ff0000) >> 16)); data32.Set(i * 4 + 3, (byte)((v32 & 0xff000000) >> 24)); } return(data32); default: System.Diagnostics.Debug.Assert(false); return(null); } }
public void ReleaseCaptureMemory() { mCapturedPcmData = null; mNextWritePos = 0; }