/// <summary> /// double型のLargeArrayを入力するバージョン。 /// </summary> public void SetPcmInDouble(WWUtil.LargeArray <double> pcm, long toPos) { long fromPos = 0; long copyCount = pcm.LongLength; if (mTotalSamples < toPos + pcm.LongLength) { copyCount = mTotalSamples - toPos; } for (long remain = copyCount; 0 < remain;) { int fragmentCount = WWUtil.LargeArray <byte> .ARRAY_FRAGMENT_LENGTH_NUM; if (remain < fragmentCount) { fragmentCount = (int)(remain); } var fragment = new double[fragmentCount]; pcm.CopyTo(fromPos, ref fragment, 0, fragmentCount); SetPcmInDouble(fragment, toPos); fragment = null; fromPos += fragmentCount; toPos += fragmentCount; remain -= fragmentCount; } }
public double[] GetPcmInDoubleSdm1bit(int count) { // サンプル数 / 8 == バイト数。 System.Diagnostics.Debug.Assert(count % 8 == 0); System.Diagnostics.Debug.Assert(count <= WWUtil.LargeArray <byte> .ARRAY_FRAGMENT_LENGTH_NUM); var result = new double[count]; int writePos = 0; if (mTotalSamples / 8 <= mOffsBytes || count == 0) { // 完全に範囲外の時。 } else { int copySamples = count; if (mTotalSamples < mOffsBytes * 8 + copySamples) { copySamples = (int)(mTotalSamples - mOffsBytes * 8); } var bitBuff = new byte[copySamples / 8]; mData.CopyTo(mOffsBytes, ref bitBuff, 0, copySamples / 8); for (long i = 0; i < copySamples / 8; ++i) { byte b = bitBuff[i]; // 1バイト内のビットの並びはMSBから古い順にデータが詰まっている。 for (int bit = 7; 0 <= bit; --bit) { result[writePos++] = ((b >> bit) & 1) == 1 ? 1.0 : -1.0; } } mOffsBytes += copySamples / 8; } while (writePos < count) { byte b = 0x69; // DSD silence // 1バイト内のビットの並びはMSBから古い順にデータが詰まっている。 for (int bit = 7; 0 <= bit; --bit) { result[writePos++] = ((b >> bit) & 1) == 1 ? 1.0 : -1.0; } } return(result); }
/// <summary> /// data chunk : total size 8 bytes + payload size /// </summary> public void DataChunkWrite(BinaryWriter bw, bool isDs64, WWUtil.LargeArray <byte> rawData) { var chunkId = new byte[4]; chunkId[0] = (byte)'d'; chunkId[1] = (byte)'a'; chunkId[2] = (byte)'t'; chunkId[3] = (byte)'a'; bw.Write(chunkId); if (UInt32.MaxValue < rawData.LongLength && !isDs64) { throw new ArgumentException("large rawData. needs DS64"); // RF64形式。別途ds64チャンクを用意して、そこにdata chunkのバイト数を入れる。 // ChunkSize = UInt32.MaxValue; } uint chunkSize; if (isDs64) { chunkSize = UInt32.MaxValue; } else { chunkSize = (uint)rawData.LongLength; } bw.Write(chunkSize); int fragmentLength = 1048576; for (long pos = 0; pos < rawData.LongLength; pos += fragmentLength) { int count = fragmentLength; if (rawData.LongLength - pos < count) { count = (int)(rawData.LongLength - pos); } var buff = new byte[count]; rawData.CopyTo(pos, ref buff, 0, count); bw.Write(buff); } AddPadIfNecessary(bw, rawData.LongLength); }
/// <summary> /// サンプル値取得。フォーマットがなんであっても使用可能。 /// </summary> /// <param name="ch">チャンネル番号</param> /// <param name="pos">サンプル番号</param> /// <returns>サンプル値。-1.0~+1.0位</returns> public double GetSampleValueInDouble(int ch, long pos) { Debug.Assert(0 <= ch && ch < NumChannels); if (pos < 0 || NumFrames <= pos) { return(0.0); } long offset = pos * BitsPerFrame / 8 + ch * BitsPerSample / 8; var data = new byte[BitsPerSample / 8]; mSampleLargeArray.CopyTo(offset, ref data, 0, BitsPerSample / 8); switch (BitsPerSample) { case 16: data = ConvI16toF64(data); break; case 24: data = ConvI24toF64(data); break; case 32: switch (SampleValueRepresentationType) { case ValueRepresentationType.SInt: data = ConvI32toF64(data); break; case ValueRepresentationType.SFloat: data = ConvF32toF64(data); break; default: System.Diagnostics.Debug.Assert(false); break; } break; case 64: switch (SampleValueRepresentationType) { case ValueRepresentationType.SInt: data = ConvI64toF64(data); break; case ValueRepresentationType.SFloat: data = ConvF64toF64(data); break; default: System.Diagnostics.Debug.Assert(false); break; } break; default: System.Diagnostics.Debug.Assert(false); break; } return(BitConverter.ToDouble(data, 0)); }