public void Close() { int mmr; if (this.opened) { AcmInterop.acmStreamUnprepareHeader(this.pStream, ref this.header, 0); } if (headerGCHandle.IsAllocated) { headerGCHandle.Free(); } if (this.header.pbDst != IntPtr.Zero) { Marshal.FreeHGlobal(this.header.pbDst); this.header.pbDst = IntPtr.Zero; } if (this.header.pbSrc != IntPtr.Zero) { Marshal.FreeHGlobal(this.header.pbSrc); this.header.pbSrc = IntPtr.Zero; } if (this.pStream != IntPtr.Zero) { mmr = AcmInterop.acmStreamClose(this.pStream, 0); this.pStream = IntPtr.Zero; } this.opened = false; }
public void Open() { if (this.opened) { throw new InvalidOperationException(); } if (this.inputFormat == null) { throw new InvalidOperationException("Input format is not specified."); } if (this.outputFormat == null) { throw new InvalidOperationException("Output format is not specified."); } this.pwfxSource = this.inputFormat.ToPtr(); this.pwfxDest = this.outputFormat.ToPtr(); this.outputFormat = new SoundFormat(this.pwfxDest); int mmr = AcmInterop.acmStreamOpen(out this.pStream, IntPtr.Zero, this.pwfxSource, this.pwfxDest, IntPtr.Zero, IntPtr.Zero, UIntPtr.Zero, 0); if (mmr != 0) { throw new SoundException("acmStreamOpen", mmr); } int cbSrcLength = (int)((this.bufferLength / 1000.0) * this.inputFormat.AverageBytesPerSecond); this.header = new AcmInterop.ACMSTREAMHEADER(); this.header.cbStruct = Marshal.SizeOf(this.header); this.header.cbSrcLength = cbSrcLength; int suggestedDstLength; mmr = AcmInterop.acmStreamSize(this.pStream, cbSrcLength, out suggestedDstLength, AcmInterop.ACM_STREAMSIZEF_SOURCE); try { this.header.cbDstLength = suggestedDstLength; this.header.pbDst = Marshal.AllocHGlobal(suggestedDstLength); this.header.pbSrc = Marshal.AllocHGlobal(cbSrcLength); this.headerGCHandle = GCHandle.Alloc(this.header, GCHandleType.Pinned); mmr = AcmInterop.acmStreamPrepareHeader(this.pStream, ref this.header, 0); if (mmr != 0) { throw new SoundException("acmStreamPrepareHeader", mmr); } this.isStart = true; this.opened = true; } finally { if (!this.opened) { this.Close(); } } }
public static int GetMaxFormatSize() { if (maxFormatSize > 0) { return(maxFormatSize); } // Get maximum size of WAVEFORMATEX int mmr = AcmInterop.acmMetrics(IntPtr.Zero, AcmInterop.ACM_METRIC_MAX_SIZE_FORMAT, out maxFormatSize); if (mmr != 0) { throw new SoundException("acmMetrics", mmr); } return(maxFormatSize); }
public static int[] GetDriverIds() { if (driverIds != null) { return(driverIds); } callbackDriverIdList = new List <int>(); int mmr = AcmInterop.acmDriverEnum(DriverCallback, 0, 0); if (mmr != 0) { throw new SoundException("acmDriverEnum", mmr); } driverIds = callbackDriverIdList.ToArray(); return(driverIds); }
public byte[] Convert(byte[] source, int offset, int length, bool isEnd) { if (!this.opened) { throw new InvalidOperationException(); } // Copy data to source pointer this.header.cbSrcLength = length; this.header.cbSrcLengthUsed = 0; this.header.cbDstLengthUsed = 0; Marshal.Copy(source, offset, this.header.pbSrc, length); // Convert source AcmConvertFlags flags = AcmConvertFlags.None; if (!isStart && !isEnd) { flags = AcmConvertFlags.BlockAlign; } if (this.isStart) { flags |= AcmConvertFlags.Start; this.isStart = false; } if (isEnd) { flags |= AcmConvertFlags.End; } int mmr = AcmInterop.acmStreamConvert(this.pStream, ref this.header, (int)flags); if (mmr != 0) { throw new SoundException("acmStreamConvert", mmr); } // Copy data from source pointer to byte array int destLength = this.header.cbDstLengthUsed; byte[] dest = new byte[destLength]; Marshal.Copy(this.header.pbDst, dest, 0, destLength); return(dest); }
public static AcmConvertionMap GetConvertionMap(SoundFormat[] inputFormats, SoundFormatTag tagFilter) { // First, we enumerate convertion formats AcmConvertionMap initConvertionMap = new AcmConvertionMap(); int maxFormatSize = GetMaxFormatSize(); // Enumerate acm drivers foreach (int driverId in GetDriverIds()) { // Open driver IntPtr phDriver; int mmr = AcmInterop.acmDriverOpen(out phDriver, driverId, 0); if (mmr != 0) { continue; } // For each input format, we do enumeration foreach (SoundFormat inputFormat in inputFormats) { // Fill format details struct AcmInterop.ACMFORMATDETAILS fmtDetails = new AcmInterop.ACMFORMATDETAILS(); IntPtr pwfxFormat = inputFormat.ToPtr(maxFormatSize); fmtDetails.cbStruct = Marshal.SizeOf(fmtDetails); fmtDetails.pwfx = pwfxFormat; fmtDetails.cbwfx = maxFormatSize; // Enumerate convertion formats callbackFormats = new List <SoundFormat>(); IntPtr pwfxInput = inputFormat.ToPtr(); mmr = AcmInterop.acmFormatEnum(phDriver, ref fmtDetails, FormatEnumCallback, IntPtr.Zero, AcmInterop.ACM_FORMATENUMF_CONVERT); Marshal.FreeHGlobal(pwfxInput); // Add formats to the map (if succeed) if (mmr == 0) { initConvertionMap.Add(inputFormat, callbackFormats); } callbackFormats = null; } // Close driver mmr = AcmInterop.acmDriverClose(phDriver, 0); } // Now we query ACM to make sure each convertion is supported AcmConvertionMap finalConvertionMap = new AcmConvertionMap(); SoundFormat[] inputs = initConvertionMap.GetInputs(); foreach (SoundFormat inputFormat in inputs) { IntPtr pwfxSrc = inputFormat.ToPtr(); foreach (SoundFormat outputFormat in initConvertionMap.GetOutputs(inputFormat)) { // Filter tags if (tagFilter != SoundFormatTag.UNKNOWN && outputFormat.Tag != tagFilter) { continue; } IntPtr phs; IntPtr pwfxDst = outputFormat.ToPtr(); // Open acm stream using the query flag int mmr = AcmInterop.acmStreamOpen(out phs, IntPtr.Zero, pwfxSrc, pwfxDst, IntPtr.Zero, IntPtr.Zero, UIntPtr.Zero, AcmInterop.ACM_STREAMOPENF_QUERY); Marshal.FreeHGlobal(pwfxDst); // Add format to the final map if succeed if (mmr == 0) { finalConvertionMap.Add(inputFormat, outputFormat); } } Marshal.FreeHGlobal(pwfxSrc); } return(finalConvertionMap); }
private static bool FormatEnumCallback(IntPtr had, ref AcmInterop.ACMFORMATDETAILS pafd, UIntPtr dwInstance, int fdwSupport) { if (pafd.cbwfx >= Marshal.SizeOf(typeof(MMInterop.WAVEFORMATEX))) { SoundFormat soundFormat = new SoundFormat(pafd.pwfx); callbackFormats.Add(soundFormat); } return true; }