/// <summary> /// Frees resources associated with this ACM Stream /// </summary> protected virtual void Dispose(bool disposing) { if (disposing) { // Free other state (managed objects). if (streamHeader != null) { streamHeader.Dispose(); streamHeader = null; } } // Free your own state (unmanaged objects). if (streamHandle != IntPtr.Zero) { MmResult result = AcmInterop.acmStreamClose(streamHandle, 0); streamHandle = IntPtr.Zero; if (result != MmResult.NoError) { throw new MmException(result, "acmStreamClose"); } } // Set large fields to null. if (driverHandle != IntPtr.Zero) { AcmInterop.acmDriverClose(driverHandle, 0); driverHandle = IntPtr.Zero; } }
/// <summary> /// Creates a new ACM stream to convert one format to another. Note that /// not all conversions can be done in one step /// </summary> /// <param name="sourceFormat">The source audio format</param> /// <param name="destFormat">The destination audio format</param> public AcmStream(WaveFormat sourceFormat, WaveFormat destFormat) { try { streamHandle = IntPtr.Zero; this.sourceFormat = sourceFormat; int sourceBufferSize = Math.Max(65536, sourceFormat.AverageBytesPerSecond); sourceBufferSize -= (sourceBufferSize % sourceFormat.BlockAlign); IntPtr sourceFormatPointer = WaveFormat.MarshalToPtr(sourceFormat); IntPtr destFormatPointer = WaveFormat.MarshalToPtr(destFormat); try { MmException.Try(AcmInterop.acmStreamOpen2(out streamHandle, IntPtr.Zero, sourceFormatPointer, destFormatPointer, null, IntPtr.Zero, IntPtr.Zero, AcmStreamOpenFlags.NonRealTime), "acmStreamOpen"); } finally { Marshal.FreeHGlobal(sourceFormatPointer); Marshal.FreeHGlobal(destFormatPointer); } int destBufferSize = SourceToDest(sourceBufferSize); streamHeader = new AcmStreamHeader(streamHandle, sourceBufferSize, destBufferSize); driverHandle = IntPtr.Zero; } catch { // suppress the finalise and clean up resources Dispose(); throw; } }
private void Prepare() { streamHeader.cbStruct = Marshal.SizeOf(streamHeader); streamHeader.sourceBufferLength = SourceBuffer.Length; streamHeader.sourceBufferPointer = hSourceBuffer.AddrOfPinnedObject(); streamHeader.destBufferLength = DestBuffer.Length; streamHeader.destBufferPointer = hDestBuffer.AddrOfPinnedObject(); MmException.Try(AcmInterop.acmStreamPrepareHeader(streamHandle, streamHeader, 0), "acmStreamPrepareHeader"); }
/// <summary> /// Returns the number of source bytes for a given number of destination bytes /// </summary> /// <param name="dest">Number of destination bytes</param> /// <returns>Number of source bytes</returns> public int DestToSource(int dest) { if (dest == 0) // zero is an invalid parameter to acmStreamSize { return(0); } int convertedBytes; MmException.Try(AcmInterop.acmStreamSize(streamHandle, dest, out convertedBytes, AcmStreamSizeFlags.Destination), "acmStreamSize"); return(convertedBytes); }
/// <summary> /// Returns the number of output bytes for a given number of input bytes /// </summary> /// <param name="source">Number of input bytes</param> /// <returns>Number of output bytes</returns> public int SourceToDest(int source) { if (source == 0) // zero is an invalid parameter to acmStreamSize { return(0); } int convertedBytes; var mmResult = AcmInterop.acmStreamSize(streamHandle, source, out convertedBytes, AcmStreamSizeFlags.Source); MmException.Try(mmResult, "acmStreamSize"); return(convertedBytes); }
private void Unprepare() { streamHeader.sourceBufferLength = SourceBuffer.Length; streamHeader.sourceBufferPointer = hSourceBuffer.AddrOfPinnedObject(); streamHeader.destBufferLength = DestBuffer.Length; streamHeader.destBufferPointer = hDestBuffer.AddrOfPinnedObject(); MmResult result = AcmInterop.acmStreamUnprepareHeader(streamHandle, streamHeader, 0); if (result != MmResult.NoError) { //if (result == MmResult.AcmHeaderUnprepared) throw new MmException(result, "acmStreamUnprepareHeader"); } }
public int Convert(int bytesToConvert, out int sourceBytesConverted) { Prepare(); try { streamHeader.sourceBufferLength = bytesToConvert; streamHeader.sourceBufferLengthUsed = bytesToConvert; AcmStreamConvertFlags flags = firstTime ? (AcmStreamConvertFlags.Start | AcmStreamConvertFlags.BlockAlign) : AcmStreamConvertFlags.BlockAlign; MmException.Try(AcmInterop.acmStreamConvert(streamHandle, streamHeader, flags), "acmStreamConvert"); firstTime = false; System.Diagnostics.Debug.Assert(streamHeader.destBufferLength == DestBuffer.Length, "Codecs should not change dest buffer length"); sourceBytesConverted = streamHeader.sourceBufferLengthUsed; } finally { Unprepare(); } return(streamHeader.destBufferLengthUsed); }
/// <summary> /// Creates a new ACM stream to convert one format to another, using a /// specified driver identifier and wave filter /// </summary> /// <param name="driverId">the driver identifier</param> /// <param name="sourceFormat">the source format</param> /// <param name="waveFilter">the wave filter</param> public AcmStream(IntPtr driverId, WaveFormat sourceFormat, WaveFilter waveFilter) { int sourceBufferSize = Math.Max(16384, sourceFormat.AverageBytesPerSecond); this.sourceFormat = sourceFormat; sourceBufferSize -= (sourceBufferSize % sourceFormat.BlockAlign); MmException.Try(AcmInterop.acmDriverOpen(out driverHandle, driverId, 0), "acmDriverOpen"); IntPtr sourceFormatPointer = WaveFormat.MarshalToPtr(sourceFormat); try { MmException.Try(AcmInterop.acmStreamOpen2(out streamHandle, driverHandle, sourceFormatPointer, sourceFormatPointer, waveFilter, IntPtr.Zero, IntPtr.Zero, AcmStreamOpenFlags.NonRealTime), "acmStreamOpen"); } finally { Marshal.FreeHGlobal(sourceFormatPointer); } streamHeader = new AcmStreamHeader(streamHandle, sourceBufferSize, SourceToDest(sourceBufferSize)); }
/// <summary> /// Suggests an appropriate PCM format that the compressed format can be converted /// to in one step /// </summary> /// <param name="compressedFormat">The compressed format</param> /// <returns>The PCM format</returns> public static WaveFormat SuggestPcmFormat(WaveFormat compressedFormat) { // create a PCM format WaveFormat suggestedFormat = new WaveFormat(compressedFormat.SampleRate, 16, compressedFormat.Channels); //MmException.Try(AcmInterop.acmFormatSuggest(IntPtr.Zero, compressedFormat, suggestedFormat, Marshal.SizeOf(suggestedFormat), AcmFormatSuggestFlags.FormatTag), "acmFormatSuggest"); IntPtr suggestedFormatPointer = WaveFormat.MarshalToPtr(suggestedFormat); IntPtr compressedFormatPointer = WaveFormat.MarshalToPtr(compressedFormat); try { MmResult result = AcmInterop.acmFormatSuggest2(IntPtr.Zero, compressedFormatPointer, suggestedFormatPointer, Marshal.SizeOf(suggestedFormat), AcmFormatSuggestFlags.FormatTag); suggestedFormat = WaveFormat.MarshalFromPtr(suggestedFormatPointer); MmException.Try(result, "acmFormatSuggest"); } finally { Marshal.FreeHGlobal(suggestedFormatPointer); Marshal.FreeHGlobal(compressedFormatPointer); } return(suggestedFormat); }