/// <summary> /// writes PCM data onto WAV file /// </summary> public bool Write(BinaryWriter bw, int numChannels, int bitsPerSample, int validBitsPerSample, int sampleRate, PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation, long numFrames, byte[] sampleArray) { if (0xffffffffL < sampleArray.LongLength + 36) { System.Diagnostics.Debug.Assert(false); return(false); } int dwChannelMask = 0; if (numChannels == 2) { dwChannelMask = 3; } mLL.RiffChunkWrite(bw, (int)(36 + sampleArray.LongLength)); mLL.FmtChunkWriteExtensible(bw, (short)numChannels, (int)sampleRate, (short)bitsPerSample, (short)validBitsPerSample, sampleValueRepresentation, dwChannelMask); mLL.DataChunkWrite(bw, false, sampleArray); return(true); }
public void FmtChunkWriteExtensible(BinaryWriter bw, short numChannels, int sampleRate, short bitsPerSample, short validBitsPerSample, PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation, int dwChannelMask) { FmtChunkWriteInternal(bw, numChannels, sampleRate, bitsPerSample, 40, WAVE_FORMAT_EXTENSIBLE); ushort cbSize = 22; bw.Write(cbSize); bw.Write(validBitsPerSample); bw.Write(dwChannelMask); byte[] guidByteArray = null; if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SInt) { var pcmGuid = Guid.Parse("00000001-0000-0010-8000-00aa00389b71"); guidByteArray = pcmGuid.ToByteArray(); } else if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SFloat) { var floatGuid = Guid.Parse("00000003-0000-0010-8000-00aa00389b71"); guidByteArray = floatGuid.ToByteArray(); } else { throw new ArgumentException("sampleValueRepresentation"); } bw.Write(guidByteArray); }
/// <summary> /// フォーマット設定から、 /// Setup()に設定されうるビットフォーマットの候補の数を数えて戻す。 /// </summary> /// <returns>Setup()に設定されうるビットフォーマットの候補の数</returns> static public int GetSetupSampleFormatCandidateNum( WasapiSharedOrExclusiveType sharedOrExclusive, BitsPerSampleFixType bitsPerSampleFixType, int validBitsPerSample, PcmDataLib.PcmData.ValueRepresentationType vrt) { if (bitsPerSampleFixType != BitsPerSampleFixType.AutoSelect || sharedOrExclusive == WasapiSharedOrExclusiveType.Shared) { // 共有モードの場合 1通り // 排他モードで自動選択以外の選択肢の場合 1通り return(1); } // 排他モードのAutoSelect switch (validBitsPerSample) { case 16: return(mTryFormat16.Length); case 24: default: return(mTryFormat24.Length); case 32: return(mTryFormat32.Length); } }
public bool Set( int numChannels, int bitsPerSample, int validBitsPerSample, int sampleRate, PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation, long numFrames, byte[] sampleArray) { mRcd = new RiffChunkDescriptor(); if (0xffffffffL < sampleArray.LongLength + 36) { System.Diagnostics.Debug.Assert(false); return(false); } mRcd.Create((uint)(36 + sampleArray.LongLength)); mFsc = new FmtSubChunk(); mFsc.Create(numChannels, sampleRate, bitsPerSample, validBitsPerSample, sampleValueRepresentation); var dsc = new WavDataSubChunk(); dsc.Create(numFrames, sampleArray); mDscList.Clear(); mDscList.Add(dsc); return(true); }
private static int ValueRepresentationToAudioFormat(PcmDataLib.PcmData.ValueRepresentationType vr) { switch (vr) { case PcmDataLib.PcmData.ValueRepresentationType.SInt: return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_PCM); case PcmDataLib.PcmData.ValueRepresentationType.SFloat: return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_IEEE_FLOAT); default: System.Diagnostics.Debug.Assert(false); return(WavRWLib2.WavWriterLowLevel.WAVE_FORMAT_PCM); } }
public bool Create( int numChannels, int sampleRate, int bitsPerSample, int validBitsPerSample, PcmDataLib.PcmData.ValueRepresentationType sampleValueRepresentation) { m_subChunk1Id = new byte[4]; m_subChunk1Id[0] = (byte)'f'; m_subChunk1Id[1] = (byte)'m'; m_subChunk1Id[2] = (byte)'t'; m_subChunk1Id[3] = (byte)' '; m_subChunk1Size = 16; m_audioFormat = 1; System.Diagnostics.Debug.Assert(0 < numChannels); NumChannels = (ushort)numChannels; SampleRate = (uint)sampleRate; m_byteRate = (uint)(sampleRate * numChannels * bitsPerSample / 8); m_blockAlign = (ushort)(numChannels * bitsPerSample / 8); BitsPerSample = (ushort)bitsPerSample; ValidBitsPerSample = (ushort)validBitsPerSample; ChannelMask = 0; SampleValueRepresentationType = sampleValueRepresentation; if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SInt) { m_audioFormat = 1; } else if (sampleValueRepresentation == PcmDataLib.PcmData.ValueRepresentationType.SFloat) { m_audioFormat = 3; } else { System.Diagnostics.Debug.Assert(false); } return(true); }
private int WasapiSetup( int deviceId, bool isExclusive, bool isEventDriven, int sampleRate, int pcmDataBitsPerSample, int pcmDataValidBitsPerSample, PcmDataLib.PcmData.ValueRepresentationType vrt, int latencyMillisec) { int num = SampleFormatInfo.GetSetupSampleFormatCandidateNum( isExclusive ? WasapiSharedOrExclusiveType.Exclusive : WasapiSharedOrExclusiveType.Shared, BitsPerSampleFixType.AutoSelect, pcmDataValidBitsPerSample, vrt); int hr = -1; for (int i = 0; i < num; ++i) { SampleFormatInfo sf = SampleFormatInfo.CreateSetupSampleFormat( isExclusive ? WasapiSharedOrExclusiveType.Exclusive : WasapiSharedOrExclusiveType.Shared, BitsPerSampleFixType.AutoSelect, pcmDataBitsPerSample, pcmDataValidBitsPerSample, vrt, i); hr = wasapi.Setup(deviceId, WasapiCS.DeviceType.Play, WasapiCS.StreamType.PCM, sampleRate, sf.GetSampleFormatType(), 2, WasapiCS.MMCSSCallType.Enable, WasapiCS.MMThreadPriorityType.None, WasapiCS.SchedulerTaskType.ProAudio, WasapiCS.ShareMode.Exclusive, isEventDriven ? WasapiCS.DataFeedMode.EventDriven : WasapiCS.DataFeedMode.TimerDriven, latencyMillisec, 500, 10000); if (0 <= hr) { m_sampleFormat = sf; return(hr); } } wasapi.Unsetup(); return(hr); }
/// <summary> /// PcmDataの形式と、(共有・排他)、フォーマット固定設定から、 /// デバイスに設定されるビットフォーマットを取得。 /// /// これは、内容的にテーブルなので、テーブルにまとめたほうが良い。 /// </summary> /// <returns>デバイスに設定されるビットフォーマット</returns> static public SampleFormatInfo CreateSetupSampleFormat( WasapiSharedOrExclusiveType sharedOrExclusive, BitsPerSampleFixType bitsPerSampleFixType, int bitsPerSample, int validBitsPerSample, PcmDataLib.PcmData.ValueRepresentationType vrt, int candidateId) { SampleFormatInfo sf = new SampleFormatInfo(); if (sharedOrExclusive == WasapiSharedOrExclusiveType.Shared) { // 共有モード sf.bitsPerSample = bitsPerSample; sf.validBitsPerSample = validBitsPerSample; sf.bitFormatType = SampleFormatInfo.VrtToBft(vrt); return(sf); } // 排他モード switch (bitsPerSampleFixType) { case BitsPerSampleFixType.Sint16: sf.bitFormatType = WasapiCS.BitFormatType.SInt; sf.bitsPerSample = 16; sf.validBitsPerSample = 16; break; case BitsPerSampleFixType.Sint24: sf.bitFormatType = WasapiCS.BitFormatType.SInt; sf.bitsPerSample = 24; sf.validBitsPerSample = 24; break; case BitsPerSampleFixType.Sint32: sf.bitFormatType = WasapiCS.BitFormatType.SInt; sf.bitsPerSample = 32; sf.validBitsPerSample = 32; break; case BitsPerSampleFixType.Sint32V24: sf.bitFormatType = WasapiCS.BitFormatType.SInt; sf.bitsPerSample = 32; sf.validBitsPerSample = 24; break; case BitsPerSampleFixType.Sfloat32: sf.bitFormatType = WasapiCS.BitFormatType.SFloat; sf.bitsPerSample = 32; sf.validBitsPerSample = 32; break; case BitsPerSampleFixType.AutoSelect: WasapiCS.SampleFormatType sampleFormat = WasapiCS.SampleFormatType.Sint16; switch (validBitsPerSample) { case 16: sampleFormat = mTryFormat16[candidateId]; break; case 24: default: /* ? */ sampleFormat = mTryFormat24[candidateId]; break; case 32: sampleFormat = mTryFormat32[candidateId]; break; } sf.bitFormatType = WasapiCS.BitFormatType.SInt; sf.bitsPerSample = WasapiCS.SampleFormatTypeToUseBitsPerSample(sampleFormat); sf.validBitsPerSample = WasapiCS.SampleFormatTypeToValidBitsPerSample(sampleFormat); break; default: System.Diagnostics.Debug.Assert(false); break; } return(sf); }