/// <summary> /// Helper function to retrieve a WaveFormat structure from a pointer /// </summary> /// <param name="pointer">WaveFormat structure</param> /// <returns></returns> public static WaveFormatProvider MarshalFromPtr(IntPtr pointer) { WaveFormatProvider waveFormat = (WaveFormatProvider)Marshal.PtrToStructure(pointer, typeof(WaveFormatProvider)); switch (waveFormat.Encoding) { case WaveFormatEncoding.Pcm: // can't rely on extra size even being there for PCM so blank it to avoid reading // corrupt data waveFormat.extraSize = 0; break; case WaveFormatEncoding.Extensible: waveFormat = (WaveFormatExtensible)Marshal.PtrToStructure(pointer, typeof(WaveFormatExtensible)); break; case WaveFormatEncoding.Adpcm: waveFormat = (AdpcmWaveFormat)Marshal.PtrToStructure(pointer, typeof(AdpcmWaveFormat)); break; case WaveFormatEncoding.Gsm610: waveFormat = (Gsm610WaveFormat)Marshal.PtrToStructure(pointer, typeof(Gsm610WaveFormat)); break; default: if (waveFormat.ExtraSize > 0) { waveFormat = (WaveFormatExtraData)Marshal.PtrToStructure(pointer, typeof(WaveFormatExtraData)); } break; } return(waveFormat); }
/// <summary> /// Helper function to marshal WaveFormat to an IntPtr /// </summary> /// <param name="format">WaveFormat</param> /// <returns>IntPtr to WaveFormat structure (needs to be freed by callee)</returns> public static IntPtr MarshalToPtr(WaveFormatProvider format) { int formatSize = Marshal.SizeOf(format); IntPtr formatPointer = Marshal.AllocHGlobal(formatSize); Marshal.StructureToPtr(format, formatPointer, false); return(formatPointer); }
/// <summary> /// Initializes a new instance of the <see cref="WasapiCapture"/> class. /// </summary> /// <param name="captureDevice">The capture device.</param> /// <param name="useEventSync">true if sync is done with event. false use sleep.</param> public WasapiCapture(MMDevice captureDevice, bool useEventSync) { syncContext = SynchronizationContext.Current; audioClient = captureDevice.AudioClient; ShareMode = AudioClientShareMode.Shared; isUsingEventSync = useEventSync; waveFormat = audioClient.MixFormat; }
/// <summary> /// Creates a Wave File Reader based on an input stream /// </summary> /// <param name="inputStream">The input stream containing a WAV file including header</param> public WaveFileReader(Stream inputStream) { this.waveStream = inputStream; var chunkReader = new WaveFileChunkReader(); chunkReader.ReadWaveHeader(inputStream); this.waveFormat = chunkReader.WaveFormat; this.dataPosition = chunkReader.DataChunkPosition; this.dataChunkLength = chunkReader.DataChunkLength; this.chunks = chunkReader.RiffChunks; Position = 0; }
/// <summary> /// Creates a WaveFormat with custom members /// </summary> /// <param name="tag">The encoding</param> /// <param name="sampleRate">Sample Rate</param> /// <param name="channels">Number of channels</param> /// <param name="averageBytesPerSecond">Average Bytes Per Second</param> /// <param name="blockAlign">Block Align</param> /// <param name="bitsPerSample">Bits Per Sample</param> /// <returns></returns> public static WaveFormatProvider CreateCustomFormat(WaveFormatEncoding tag, int sampleRate, int channels, int averageBytesPerSecond, int blockAlign, int bitsPerSample) { WaveFormatProvider waveFormat = new WaveFormatProvider(); waveFormat.waveFormatTag = tag; waveFormat.channels = (short)channels; waveFormat.sampleRate = sampleRate; waveFormat.averageBytesPerSecond = averageBytesPerSecond; waveFormat.blockAlign = (short)blockAlign; waveFormat.bitsPerSample = (short)bitsPerSample; waveFormat.extraSize = 0; return(waveFormat); }
/// <summary> /// Creates a new 32 bit IEEE floating point wave format /// </summary> /// <param name="sampleRate">sample rate</param> /// <param name="channels">number of channels</param> public static WaveFormatProvider CreateIeeeFloatWaveFormat(int sampleRate, int channels) { WaveFormatProvider wf = new WaveFormatProvider(); wf.waveFormatTag = WaveFormatEncoding.IeeeFloat; wf.channels = (short)channels; wf.bitsPerSample = 32; wf.sampleRate = sampleRate; wf.blockAlign = (short)(4 * channels); wf.averageBytesPerSecond = sampleRate * wf.blockAlign; wf.extraSize = 0; return(wf); }
internal MmResult WaveOutOpen(out IntPtr waveOutHandle, int deviceNumber, WaveFormatProvider waveFormat, WaveInterop.WaveCallback callback) { MmResult result; if (Strategy == WaveCallbackStrategy.FunctionCallback) { result = WaveInterop.waveOutOpen(out waveOutHandle, (IntPtr)deviceNumber, waveFormat, callback, IntPtr.Zero, WaveInOutOpenFlags.CallbackFunction); } else { result = WaveInterop.waveOutOpenWindow(out waveOutHandle, (IntPtr)deviceNumber, waveFormat, this.Handle, IntPtr.Zero, WaveInOutOpenFlags.CallbackWindow); } return(result); }
/// <summary> /// Compares with another WaveFormat object /// </summary> /// <param name="obj">Object to compare to</param> /// <returns>True if the objects are the same</returns> public override bool Equals(object obj) { WaveFormatProvider other = obj as WaveFormatProvider; if (other != null) { return(waveFormatTag == other.waveFormatTag && channels == other.channels && sampleRate == other.sampleRate && averageBytesPerSecond == other.averageBytesPerSecond && blockAlign == other.blockAlign && bitsPerSample == other.bitsPerSample); } return(false); }
/// <summary> /// WaveFileWriter that actually writes to a stream /// </summary> /// <param name="outStream">Stream to be written to</param> /// <param name="format">Wave format to use</param> public WaveFileWriter(System.IO.Stream outStream, WaveFormatProvider format) { this.outStream = outStream; this.format = format; this.writer = new BinaryWriter(outStream, System.Text.Encoding.UTF8); this.writer.Write(System.Text.Encoding.UTF8.GetBytes("RIFF")); this.writer.Write((int)0); // placeholder this.writer.Write(System.Text.Encoding.UTF8.GetBytes("WAVE")); this.writer.Write(System.Text.Encoding.UTF8.GetBytes("fmt ")); format.Serialize(this.writer); CreateFactChunk(); WriteDataChunkHeader(); }
/// <summary> /// Prepares a Wave input device for recording /// </summary> public WaveIn(WaveCallbackInfo callbackInfo) { syncContext = SynchronizationContext.Current; if ((callbackInfo.Strategy == WaveCallbackStrategy.NewWindow || callbackInfo.Strategy == WaveCallbackStrategy.ExistingWindow) && syncContext == null) { throw new InvalidOperationException("Use WaveInEvent to record on a background thread"); } DeviceNumber = 0; WaveFormat = new WaveFormatProvider(8000, 16, 1); BufferMilliseconds = 100; NumberOfBuffers = 3; callback = Callback; this.callbackInfo = callbackInfo; callbackInfo.Connect(callback); }
/// <summary> /// Creates a new MediaFoundationReader based on the supplied file /// </summary> /// <param name="inputStream">The input stream containing a WAV.</param> /// <param name="settings">Advanced settings</param> public MediaFoundationReader(System.IO.Stream inputStream, MediaFoundationReaderSettings settings) { MediaFoundationApi.Startup(); this.settings = settings; _inputStream = inputStream; var reader = CreateReader(settings); waveFormat = GetCurrentWaveFormat(reader); reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true); length = GetLength(reader); if (settings.SingleReaderObject) { pReader = reader; } }
private WaveFormatProvider GetCurrentWaveFormat(IMFSourceReader reader) { IMFMediaType uncompressedMediaType; reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out uncompressedMediaType); // Two ways to query it, first is to ask for properties (second is to convert into WaveFormatEx using MFCreateWaveFormatExFromMFMediaType) var outputMediaType = new MediaType(uncompressedMediaType); Guid actualMajorType = outputMediaType.MajorType; Guid audioSubType = outputMediaType.SubType; int channels = outputMediaType.ChannelCount; int bits = outputMediaType.BitsPerSample; int sampleRate = outputMediaType.SampleRate; return(audioSubType == AudioSubtypes.MFAudioFormat_PCM ? new WaveFormatProvider(sampleRate, bits, channels) : WaveFormatProvider.CreateIeeeFloatWaveFormat(sampleRate, channels)); }
/// <summary> /// Creates a stream that can convert to PCM /// </summary> /// <param name="sourceStream">The source stream</param> /// <returns>A PCM stream</returns> public static WaveStream CreatePcmStream(WaveStream sourceStream) { if (sourceStream.WaveFormat.Encoding == WaveFormatEncoding.Pcm) { return(sourceStream); } WaveFormatProvider pcmFormat = AcmStream.SuggestPcmFormat(sourceStream.WaveFormat); if (pcmFormat.SampleRate < 8000) { if (sourceStream.WaveFormat.Encoding == WaveFormatEncoding.G723) { pcmFormat = new WaveFormatProvider(8000, 16, 1); } else { throw new InvalidOperationException("Invalid suggested output format, please explicitly provide a target format"); } } return(new WaveFormatConversionStream(pcmFormat, sourceStream)); }
/// <summary> /// Create a new WaveFormat conversion stream /// </summary> /// <param name="targetFormat">Desired output format</param> /// <param name="sourceStream">Source stream</param> public WaveFormatConversionStream(WaveFormatProvider targetFormat, WaveStream sourceStream) { this.sourceStream = sourceStream; this.targetFormat = targetFormat; conversionStream = new AcmStream(sourceStream.WaveFormat, targetFormat); /*try * { * // work out how many bytes the entire input stream will convert to * length = conversionStream.SourceToDest((int)sourceStream.Length); * } * catch * { * Dispose(); * throw; * }*/ length = EstimateSourceToDest((int)sourceStream.Length); position = 0; preferredSourceReadSize = System.Math.Min(sourceStream.WaveFormat.AverageBytesPerSecond, conversionStream.SourceBuffer.Length); preferredSourceReadSize -= (preferredSourceReadSize % sourceStream.WaveFormat.BlockAlign); }
public static extern MmResult waveInOpen(out IntPtr hWaveIn, IntPtr uDeviceID, WaveFormatProvider lpFormat, WaveCallback dwCallback, IntPtr dwInstance, WaveInOutOpenFlags dwFlags);
/// <summary> /// Creates a new WaveFileWriter /// </summary> /// <param name="filename">The filename to write to</param> /// <param name="format">The Wave Format of the output data</param> public WaveFileWriter(string filename, WaveFormatProvider format) : this(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read), format) { this.filename = filename; }
/// <summary> /// Reads from this wave stream /// </summary> /// <param name="buffer">Buffer to read into</param> /// <param name="offset">Offset in buffer</param> /// <param name="count">Bytes required</param> /// <returns>Number of bytes read; 0 indicates end of stream</returns> public override int Read(byte[] buffer, int offset, int count) { if (pReader == null) { pReader = CreateReader(settings); } if (repositionTo != -1) { Reposition(repositionTo); } int bytesWritten = 0; // read in any leftovers from last time if (decoderOutputCount > 0) { bytesWritten += ReadFromDecoderBuffer(buffer, offset, count - bytesWritten); } while (bytesWritten < count) { IMFSample pSample; MF_SOURCE_READER_FLAG dwFlags; ulong timestamp; int actualStreamIndex; pReader.ReadSample(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, out actualStreamIndex, out dwFlags, out timestamp, out pSample); if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_ENDOFSTREAM) != 0) { // reached the end of the stream break; } else if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) != 0) { waveFormat = GetCurrentWaveFormat(pReader); OnWaveFormatChanged(); // carry on, but user must handle the change of format } else if (dwFlags != 0) { throw new InvalidOperationException(String.Format("MediaFoundationReadError {0}", dwFlags)); } IMFMediaBuffer pBuffer; pSample.ConvertToContiguousBuffer(out pBuffer); IntPtr pAudioData; int cbBuffer; int pcbMaxLength; pBuffer.Lock(out pAudioData, out pcbMaxLength, out cbBuffer); EnsureBuffer(cbBuffer); Marshal.Copy(pAudioData, decoderOutputBuffer, 0, cbBuffer); decoderOutputOffset = 0; decoderOutputCount = cbBuffer; bytesWritten += ReadFromDecoderBuffer(buffer, offset + bytesWritten, count - bytesWritten); pBuffer.Unlock(); Marshal.ReleaseComObject(pBuffer); Marshal.ReleaseComObject(pSample); } position += bytesWritten; return(bytesWritten); }
public static extern MmResult waveInOpenWindow(out IntPtr hWaveIn, IntPtr uDeviceID, WaveFormatProvider lpFormat, IntPtr callbackWindowHandle, IntPtr dwInstance, WaveInOutOpenFlags dwFlags);