mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
2.0.7
This commit is contained in:
91
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioCaptureClient.cs
Normal file
91
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioCaptureClient.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Capture Client
|
||||
/// </summary>
|
||||
public class AudioCaptureClient : IDisposable
|
||||
{
|
||||
IAudioCaptureClient audioCaptureClientInterface;
|
||||
|
||||
internal AudioCaptureClient(IAudioCaptureClient audioCaptureClientInterface)
|
||||
{
|
||||
this.audioCaptureClientInterface = audioCaptureClientInterface;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the buffer
|
||||
/// </summary>
|
||||
/// <returns>Pointer to the buffer</returns>
|
||||
public IntPtr GetBuffer(
|
||||
out int numFramesToRead,
|
||||
out AudioClientBufferFlags bufferFlags,
|
||||
out long devicePosition,
|
||||
out long qpcPosition)
|
||||
{
|
||||
IntPtr bufferPointer;
|
||||
Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetBuffer(out bufferPointer, out numFramesToRead, out bufferFlags, out devicePosition, out qpcPosition));
|
||||
return bufferPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the buffer
|
||||
/// </summary>
|
||||
/// <param name="numFramesToRead">Number of frames to read</param>
|
||||
/// <param name="bufferFlags">Buffer flags</param>
|
||||
/// <returns>Pointer to the buffer</returns>
|
||||
public IntPtr GetBuffer(
|
||||
out int numFramesToRead,
|
||||
out AudioClientBufferFlags bufferFlags)
|
||||
{
|
||||
IntPtr bufferPointer;
|
||||
long devicePosition;
|
||||
long qpcPosition;
|
||||
Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetBuffer(out bufferPointer, out numFramesToRead, out bufferFlags, out devicePosition, out qpcPosition));
|
||||
return bufferPointer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the next packet
|
||||
/// </summary>
|
||||
public int GetNextPacketSize()
|
||||
{
|
||||
int numFramesInNextPacket;
|
||||
Marshal.ThrowExceptionForHR(audioCaptureClientInterface.GetNextPacketSize(out numFramesInNextPacket));
|
||||
return numFramesInNextPacket;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release buffer
|
||||
/// </summary>
|
||||
/// <param name="numFramesWritten">Number of frames written</param>
|
||||
public void ReleaseBuffer(int numFramesWritten)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(audioCaptureClientInterface.ReleaseBuffer(numFramesWritten));
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Release the COM object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (audioCaptureClientInterface != null)
|
||||
{
|
||||
// althugh GC would do this for us, we want it done now
|
||||
// to let us reopen WASAPI
|
||||
Marshal.ReleaseComObject(audioCaptureClientInterface);
|
||||
audioCaptureClientInterface = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
296
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioClient.cs
Normal file
296
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioClient.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Windows Vista CoreAudio AudioClient
|
||||
/// </summary>
|
||||
public class AudioClient : IDisposable
|
||||
{
|
||||
IAudioClient audioClientInterface;
|
||||
WaveFormat mixFormat;
|
||||
AudioRenderClient audioRenderClient;
|
||||
AudioCaptureClient audioCaptureClient;
|
||||
|
||||
internal AudioClient(IAudioClient audioClientInterface)
|
||||
{
|
||||
this.audioClientInterface = audioClientInterface;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mix Format,
|
||||
/// Can be called before initialize
|
||||
/// </summary>
|
||||
public WaveFormat MixFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
if(mixFormat == null)
|
||||
{
|
||||
IntPtr waveFormatPointer;
|
||||
audioClientInterface.GetMixFormat(out waveFormatPointer);
|
||||
//WaveFormatExtensible waveFormat = new WaveFormatExtensible(44100,32,2);
|
||||
//Marshal.PtrToStructure(waveFormatPointer, waveFormat);
|
||||
WaveFormat waveFormat = WaveFormat.MarshalFromPtr(waveFormatPointer);
|
||||
Marshal.FreeCoTaskMem(waveFormatPointer);
|
||||
mixFormat = waveFormat;
|
||||
return waveFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mixFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the Audio Client
|
||||
/// </summary>
|
||||
/// <param name="shareMode">Share Mode</param>
|
||||
/// <param name="streamFlags">Stream Flags</param>
|
||||
/// <param name="bufferDuration">Buffer Duration</param>
|
||||
/// <param name="periodicity">Periodicity</param>
|
||||
/// <param name="waveFormat">Wave Format</param>
|
||||
/// <param name="audioSessionGuid">Audio Session GUID (can be null)</param>
|
||||
public void Initialize(AudioClientShareMode shareMode,
|
||||
AudioClientStreamFlags streamFlags,
|
||||
long bufferDuration,
|
||||
long periodicity,
|
||||
WaveFormat waveFormat,
|
||||
Guid audioSessionGuid)
|
||||
{
|
||||
audioClientInterface.Initialize(shareMode, streamFlags, bufferDuration, periodicity, waveFormat, ref audioSessionGuid);
|
||||
// may have changed the mix format so reset it
|
||||
mixFormat = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer size (must initialize first)
|
||||
/// </summary>
|
||||
public int BufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
uint bufferSize;
|
||||
audioClientInterface.GetBufferSize(out bufferSize);
|
||||
return (int) bufferSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the stream latency (must initialize first)
|
||||
/// </summary>
|
||||
public long StreamLatency
|
||||
{
|
||||
get
|
||||
{
|
||||
return audioClientInterface.GetStreamLatency();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current padding (must initialize first)
|
||||
/// </summary>
|
||||
public int CurrentPadding
|
||||
{
|
||||
get
|
||||
{
|
||||
int currentPadding;
|
||||
audioClientInterface.GetCurrentPadding(out currentPadding);
|
||||
return currentPadding;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default device period (can be called before initialize)
|
||||
/// </summary>
|
||||
public long DefaultDevicePeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
long defaultDevicePeriod;
|
||||
long minimumDevicePeriod;
|
||||
audioClientInterface.GetDevicePeriod(out defaultDevicePeriod, out minimumDevicePeriod);
|
||||
return defaultDevicePeriod;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the minimum device period (can be called before initialize)
|
||||
/// </summary>
|
||||
public long MinimumDevicePeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
long defaultDevicePeriod;
|
||||
long minimumDevicePeriod;
|
||||
audioClientInterface.GetDevicePeriod(out defaultDevicePeriod, out minimumDevicePeriod);
|
||||
return minimumDevicePeriod;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: GetService:
|
||||
// IID_IAudioCaptureClient
|
||||
// IID_IAudioClock
|
||||
// IID_IAudioSessionControl
|
||||
// IID_IAudioStreamVolume
|
||||
// IID_IChannelAudioVolume
|
||||
// IID_ISimpleAudioVolume
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AudioRenderClient service
|
||||
/// </summary>
|
||||
public AudioRenderClient AudioRenderClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (audioRenderClient == null)
|
||||
{
|
||||
object audioRenderClientInterface;
|
||||
Guid audioRenderClientGuid = new Guid("F294ACFC-3146-4483-A7BF-ADDCA7C260E2");
|
||||
audioClientInterface.GetService(ref audioRenderClientGuid, out audioRenderClientInterface);
|
||||
audioRenderClient = new AudioRenderClient((IAudioRenderClient)audioRenderClientInterface);
|
||||
}
|
||||
return audioRenderClient;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the AudioCaptureClient service
|
||||
/// </summary>
|
||||
public AudioCaptureClient AudioCaptureClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (audioCaptureClient == null)
|
||||
{
|
||||
object audioCaptureClientInterface;
|
||||
Guid audioCaptureClientGuid = new Guid("c8adbd64-e71e-48a0-a4de-185c395cd317");
|
||||
audioClientInterface.GetService(ref audioCaptureClientGuid, out audioCaptureClientInterface);
|
||||
audioCaptureClient = new AudioCaptureClient((IAudioCaptureClient)audioCaptureClientInterface);
|
||||
}
|
||||
return audioCaptureClient;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether if the specified output format is supported
|
||||
/// </summary>
|
||||
/// <param name="shareMode">The share mode.</param>
|
||||
/// <param name="desiredFormat">The desired format.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [is format supported] [the specified share mode]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsFormatSupported(AudioClientShareMode shareMode,
|
||||
WaveFormat desiredFormat)
|
||||
{
|
||||
WaveFormatExtensible closestMatchFormat;
|
||||
return IsFormatSupported(shareMode, desiredFormat, out closestMatchFormat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the specified output format is supported in shared mode
|
||||
/// </summary>
|
||||
/// <param name="shareMode">Share Mode</param>
|
||||
/// <param name="desiredFormat">Desired Format</param>
|
||||
/// <param name="closestMatchFormat">Output The closest match format.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if [is format supported] [the specified share mode]; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat)
|
||||
{
|
||||
int hresult = audioClientInterface.IsFormatSupported(shareMode, desiredFormat, out closestMatchFormat);
|
||||
// S_OK is 0, S_FALSE = 1
|
||||
if (hresult == 0)
|
||||
{
|
||||
// directly supported
|
||||
return true;
|
||||
}
|
||||
if (hresult == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (hresult == (int)AudioClientErrors.UnsupportedFormat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(hresult);
|
||||
}
|
||||
// shouldn't get here
|
||||
throw new NotSupportedException("Unknown hresult " + hresult.ToString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts the audio stream
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
audioClientInterface.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the audio stream.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
audioClientInterface.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Event Handle for buffer synchro.
|
||||
/// </summary>
|
||||
/// <param name="eventWaitHandle">The Wait Handle to setup</param>
|
||||
public void SetEventHandle(EventWaitHandle eventWaitHandle)
|
||||
{
|
||||
audioClientInterface.SetEventHandle(eventWaitHandle.SafeWaitHandle.DangerousGetHandle());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the audio stream
|
||||
/// Reset is a control method that the client calls to reset a stopped audio stream.
|
||||
/// Resetting the stream flushes all pending data and resets the audio clock stream
|
||||
/// position to 0. This method fails if it is called on a stream that is not stopped
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
audioClientInterface.Reset();
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (audioClientInterface != null)
|
||||
{
|
||||
if (audioRenderClient != null)
|
||||
{
|
||||
audioRenderClient.Dispose();
|
||||
audioRenderClient = null;
|
||||
}
|
||||
if (audioCaptureClient != null)
|
||||
{
|
||||
audioCaptureClient.Dispose();
|
||||
audioCaptureClient = null;
|
||||
}
|
||||
Marshal.ReleaseComObject(audioClientInterface);
|
||||
audioClientInterface = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Client Buffer Flags
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AudioClientBufferFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// None
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY
|
||||
/// </summary>
|
||||
DataDiscontinuity = 0x1,
|
||||
/// <summary>
|
||||
/// AUDCLNT_BUFFERFLAGS_SILENT
|
||||
/// </summary>
|
||||
Silent = 0x2,
|
||||
/// <summary>
|
||||
/// AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR
|
||||
/// </summary>
|
||||
TimestampError = 0x4
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// AUDCLNT_SHAREMODE
|
||||
/// </summary>
|
||||
public enum AudioClientShareMode
|
||||
{
|
||||
/// <summary>
|
||||
/// AUDCLNT_SHAREMODE_SHARED,
|
||||
/// </summary>
|
||||
Shared,
|
||||
/// <summary>
|
||||
/// AUDCLNT_SHAREMODE_EXCLUSIVE
|
||||
/// </summary>
|
||||
Exclusive,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// AUDCLNT_STREAMFLAGS
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum AudioClientStreamFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// None
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// AUDCLNT_STREAMFLAGS_CROSSPROCESS
|
||||
/// </summary>
|
||||
CrossProcess = 0x00010000,
|
||||
/// <summary>
|
||||
/// AUDCLNT_STREAMFLAGS_LOOPBACK
|
||||
/// </summary>
|
||||
Loopback = 0x00020000,
|
||||
/// <summary>
|
||||
/// AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
||||
/// </summary>
|
||||
EventCallback = 0x00040000,
|
||||
/// <summary>
|
||||
/// AUDCLNT_STREAMFLAGS_NOPERSIST
|
||||
/// </summary>
|
||||
NoPersist = 0x00080000,
|
||||
}
|
||||
}
|
||||
211
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioEndpointVolume.cs
Normal file
211
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioEndpointVolume.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume
|
||||
/// </summary>
|
||||
public class AudioEndpointVolume : IDisposable
|
||||
{
|
||||
private IAudioEndpointVolume _AudioEndPointVolume;
|
||||
private AudioEndpointVolumeChannels _Channels;
|
||||
private AudioEndpointVolumeStepInformation _StepInformation;
|
||||
private AudioEndpointVolumeVolumeRange _VolumeRange;
|
||||
private EEndpointHardwareSupport _HardwareSupport;
|
||||
private AudioEndpointVolumeCallback _CallBack;
|
||||
|
||||
/// <summary>
|
||||
/// On Volume Notification
|
||||
/// </summary>
|
||||
public event AudioEndpointVolumeNotificationDelegate OnVolumeNotification;
|
||||
|
||||
/// <summary>
|
||||
/// Volume Range
|
||||
/// </summary>
|
||||
public AudioEndpointVolumeVolumeRange VolumeRange
|
||||
{
|
||||
get
|
||||
{
|
||||
return _VolumeRange;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hardware Support
|
||||
/// </summary>
|
||||
public EEndpointHardwareSupport HardwareSupport
|
||||
{
|
||||
get
|
||||
{
|
||||
return _HardwareSupport;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step Information
|
||||
/// </summary>
|
||||
public AudioEndpointVolumeStepInformation StepInformation
|
||||
{
|
||||
get
|
||||
{
|
||||
return _StepInformation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Channels
|
||||
/// </summary>
|
||||
public AudioEndpointVolumeChannels Channels
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Channels;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Master Volume Level
|
||||
/// </summary>
|
||||
public float MasterVolumeLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
float result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.GetMasterVolumeLevel(out result));
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.SetMasterVolumeLevel(value, Guid.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Master Volume Level Scalar
|
||||
/// </summary>
|
||||
public float MasterVolumeLevelScalar
|
||||
{
|
||||
get
|
||||
{
|
||||
float result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.GetMasterVolumeLevelScalar(out result));
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.SetMasterVolumeLevelScalar(value, Guid.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mute
|
||||
/// </summary>
|
||||
public bool Mute
|
||||
{
|
||||
get
|
||||
{
|
||||
bool result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.GetMute(out result));
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.SetMute(value, Guid.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Volume Step Up
|
||||
/// </summary>
|
||||
public void VolumeStepUp()
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.VolumeStepUp(Guid.Empty));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Volume Step Down
|
||||
/// </summary>
|
||||
public void VolumeStepDown()
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.VolumeStepDown(Guid.Empty));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Audio endpoint volume
|
||||
/// </summary>
|
||||
/// <param name="realEndpointVolume">IAudioEndpointVolume COM interface</param>
|
||||
internal AudioEndpointVolume(IAudioEndpointVolume realEndpointVolume)
|
||||
{
|
||||
uint HardwareSupp;
|
||||
|
||||
_AudioEndPointVolume = realEndpointVolume;
|
||||
_Channels = new AudioEndpointVolumeChannels(_AudioEndPointVolume);
|
||||
_StepInformation = new AudioEndpointVolumeStepInformation(_AudioEndPointVolume);
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.QueryHardwareSupport(out HardwareSupp));
|
||||
_HardwareSupport = (EEndpointHardwareSupport)HardwareSupp;
|
||||
_VolumeRange = new AudioEndpointVolumeVolumeRange(_AudioEndPointVolume);
|
||||
_CallBack = new AudioEndpointVolumeCallback(this);
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.RegisterControlChangeNotify(_CallBack));
|
||||
}
|
||||
internal void FireNotification(AudioVolumeNotificationData NotificationData)
|
||||
{
|
||||
AudioEndpointVolumeNotificationDelegate del = OnVolumeNotification;
|
||||
if (del != null)
|
||||
{
|
||||
del(NotificationData);
|
||||
}
|
||||
}
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_CallBack != null)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.UnregisterControlChangeNotify(_CallBack));
|
||||
_CallBack = null;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer
|
||||
/// </summary>
|
||||
~AudioEndpointVolume()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
// This class implements the IAudioEndpointVolumeCallback interface,
|
||||
// it is implemented in this class because implementing it on AudioEndpointVolume
|
||||
// (where the functionality is really wanted, would cause the OnNotify function
|
||||
// to show up in the public API.
|
||||
internal class AudioEndpointVolumeCallback : IAudioEndpointVolumeCallback
|
||||
{
|
||||
private AudioEndpointVolume _Parent;
|
||||
|
||||
internal AudioEndpointVolumeCallback(AudioEndpointVolume parent)
|
||||
{
|
||||
_Parent = parent;
|
||||
}
|
||||
|
||||
public void OnNotify(ref AudioVolumeNotificationDataStruct data)
|
||||
//public int OnNotify(IntPtr NotifyData)
|
||||
{
|
||||
//Since AUDIO_VOLUME_NOTIFICATION_DATA is dynamic in length based on the
|
||||
//number of audio channels available we cannot just call PtrToStructure
|
||||
//to get all data, thats why it is split up into two steps, first the static
|
||||
//data is marshalled into the data structure, then with some IntPtr math the
|
||||
//remaining floats are read from memory.
|
||||
//
|
||||
//AudioVolumeNotificationDataStruct data = (AudioVolumeNotificationDataStruct)Marshal.PtrToStructure(NotifyData, typeof(AudioVolumeNotificationDataStruct));
|
||||
|
||||
//Determine offset in structure of the first float
|
||||
//IntPtr Offset = Marshal.OffsetOf(typeof(AudioVolumeNotificationDataStruct), "ChannelVolume");
|
||||
//Determine offset in memory of the first float
|
||||
//IntPtr FirstFloatPtr = (IntPtr)((long)NotifyData + (long)Offset);
|
||||
|
||||
//float[] voldata = new float[data.nChannels];
|
||||
|
||||
//Read all floats from memory.
|
||||
//for (int i = 0; i < data.nChannels; i++)
|
||||
//{
|
||||
// voldata[i] = data.fMasterVolume;
|
||||
//}
|
||||
|
||||
//Create combined structure and Fire Event in parent class.
|
||||
AudioVolumeNotificationData NotificationData = new AudioVolumeNotificationData(data.guidEventContext, data.bMuted, data.fMasterVolume);
|
||||
_Parent.FireNotification(NotificationData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume Channel
|
||||
/// </summary>
|
||||
public class AudioEndpointVolumeChannel
|
||||
{
|
||||
private uint _Channel;
|
||||
private IAudioEndpointVolume _AudioEndpointVolume;
|
||||
|
||||
internal AudioEndpointVolumeChannel(IAudioEndpointVolume parent, int channel)
|
||||
{
|
||||
_Channel = (uint)channel;
|
||||
_AudioEndpointVolume = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Volume Level
|
||||
/// </summary>
|
||||
public float VolumeLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
float result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndpointVolume.GetChannelVolumeLevel(_Channel,out result));
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndpointVolume.SetChannelVolumeLevel(_Channel, value,Guid.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Volume Level Scalar
|
||||
/// </summary>
|
||||
public float VolumeLevelScalar
|
||||
{
|
||||
get
|
||||
{
|
||||
float result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndpointVolume.GetChannelVolumeLevelScalar(_Channel, out result));
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(_AudioEndpointVolume.SetChannelVolumeLevelScalar(_Channel, value, Guid.Empty));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume Channels
|
||||
/// </summary>
|
||||
public class AudioEndpointVolumeChannels
|
||||
{
|
||||
IAudioEndpointVolume _AudioEndPointVolume;
|
||||
AudioEndpointVolumeChannel[] _Channels;
|
||||
|
||||
/// <summary>
|
||||
/// Channel Count
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int result;
|
||||
Marshal.ThrowExceptionForHR(_AudioEndPointVolume.GetChannelCount(out result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indexer - get a specific channel
|
||||
/// </summary>
|
||||
public AudioEndpointVolumeChannel this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Channels[index];
|
||||
}
|
||||
}
|
||||
|
||||
internal AudioEndpointVolumeChannels(IAudioEndpointVolume parent)
|
||||
{
|
||||
int ChannelCount;
|
||||
_AudioEndPointVolume = parent;
|
||||
|
||||
ChannelCount = Count;
|
||||
_Channels = new AudioEndpointVolumeChannel[ChannelCount];
|
||||
for (int i = 0; i < ChannelCount; i++)
|
||||
{
|
||||
_Channels[i] = new AudioEndpointVolumeChannel(_AudioEndPointVolume, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume Notifiaction Delegate
|
||||
/// </summary>
|
||||
/// <param name="data">Audio Volume Notification Data</param>
|
||||
public delegate void AudioEndpointVolumeNotificationDelegate( AudioVolumeNotificationData data);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume Step Information
|
||||
/// </summary>
|
||||
public class AudioEndpointVolumeStepInformation
|
||||
{
|
||||
private uint _Step;
|
||||
private uint _StepCount;
|
||||
internal AudioEndpointVolumeStepInformation(IAudioEndpointVolume parent)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(parent.GetVolumeStepInfo(out _Step, out _StepCount));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step
|
||||
/// </summary>
|
||||
public uint Step
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Step;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// StepCount
|
||||
/// </summary>
|
||||
public uint StepCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return _StepCount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// modified for NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume Volume Range
|
||||
/// </summary>
|
||||
public class AudioEndpointVolumeVolumeRange
|
||||
{
|
||||
float _VolumeMindB;
|
||||
float _VolumeMaxdB;
|
||||
float _VolumeIncrementdB;
|
||||
|
||||
internal AudioEndpointVolumeVolumeRange(IAudioEndpointVolume parent)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(parent.GetVolumeRange(out _VolumeMindB,out _VolumeMaxdB,out _VolumeIncrementdB));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum Decibels
|
||||
/// </summary>
|
||||
public float MinDecibels
|
||||
{
|
||||
get
|
||||
{
|
||||
return _VolumeMindB;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum Decibels
|
||||
/// </summary>
|
||||
public float MaxDecibels
|
||||
{
|
||||
get
|
||||
{
|
||||
return _VolumeMaxdB;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment Decibels
|
||||
/// </summary>
|
||||
public float IncrementDecibels
|
||||
{
|
||||
get
|
||||
{
|
||||
return _VolumeIncrementdB;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Meter Information
|
||||
/// </summary>
|
||||
public class AudioMeterInformation
|
||||
{
|
||||
private IAudioMeterInformation _AudioMeterInformation;
|
||||
private EEndpointHardwareSupport _HardwareSupport;
|
||||
private AudioMeterInformationChannels _Channels;
|
||||
|
||||
internal AudioMeterInformation(IAudioMeterInformation realInterface)
|
||||
{
|
||||
int HardwareSupp;
|
||||
|
||||
_AudioMeterInformation = realInterface;
|
||||
Marshal.ThrowExceptionForHR(_AudioMeterInformation.QueryHardwareSupport(out HardwareSupp));
|
||||
_HardwareSupport = (EEndpointHardwareSupport)HardwareSupp;
|
||||
_Channels = new AudioMeterInformationChannels(_AudioMeterInformation);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peak Values
|
||||
/// </summary>
|
||||
public AudioMeterInformationChannels PeakValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Channels;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hardware Support
|
||||
/// </summary>
|
||||
public EEndpointHardwareSupport HardwareSupport
|
||||
{
|
||||
get
|
||||
{
|
||||
return _HardwareSupport;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Master Peak Value
|
||||
/// </summary>
|
||||
public float MasterPeakValue
|
||||
{
|
||||
get
|
||||
{
|
||||
float result;
|
||||
Marshal.ThrowExceptionForHR(_AudioMeterInformation.GetPeakValue(out result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Meter Information Channels
|
||||
/// </summary>
|
||||
public class AudioMeterInformationChannels
|
||||
{
|
||||
IAudioMeterInformation _AudioMeterInformation;
|
||||
|
||||
/// <summary>
|
||||
/// Metering Channel Count
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int result;
|
||||
Marshal.ThrowExceptionForHR(_AudioMeterInformation.GetMeteringChannelCount(out result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Peak value
|
||||
/// </summary>
|
||||
/// <param name="index">Channel index</param>
|
||||
/// <returns>Peak value</returns>
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
float[] peakValues = new float[Count];
|
||||
GCHandle Params = GCHandle.Alloc(peakValues, GCHandleType.Pinned);
|
||||
Marshal.ThrowExceptionForHR(_AudioMeterInformation.GetChannelsPeakValues(peakValues.Length, Params.AddrOfPinnedObject()));
|
||||
Params.Free();
|
||||
return peakValues[index];
|
||||
}
|
||||
}
|
||||
|
||||
internal AudioMeterInformationChannels(IAudioMeterInformation parent)
|
||||
{
|
||||
_AudioMeterInformation = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioRenderClient.cs
Normal file
60
CUETools.Codecs.CoreAudio/CoreAudioApi/AudioRenderClient.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Render Client
|
||||
/// </summary>
|
||||
public class AudioRenderClient : IDisposable
|
||||
{
|
||||
IAudioRenderClient audioRenderClientInterface;
|
||||
|
||||
internal AudioRenderClient(IAudioRenderClient audioRenderClientInterface)
|
||||
{
|
||||
this.audioRenderClientInterface = audioRenderClientInterface;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the buffer
|
||||
/// </summary>
|
||||
/// <param name="numFramesRequested">Number of frames requested</param>
|
||||
/// <returns>Pointer to the buffer</returns>
|
||||
public IntPtr GetBuffer(int numFramesRequested)
|
||||
{
|
||||
return audioRenderClientInterface.GetBuffer(numFramesRequested);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release buffer
|
||||
/// </summary>
|
||||
/// <param name="numFramesWritten">Number of frames written</param>
|
||||
/// <param name="bufferFlags">Buffer flags</param>
|
||||
public void ReleaseBuffer(int numFramesWritten,AudioClientBufferFlags bufferFlags)
|
||||
{
|
||||
audioRenderClientInterface.ReleaseBuffer(numFramesWritten, bufferFlags);
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
/// <summary>
|
||||
/// Release the COM object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (audioRenderClientInterface != null)
|
||||
{
|
||||
// althugh GC would do this for us, we want it done now
|
||||
// to let us reopen WASAPI
|
||||
Marshal.ReleaseComObject(audioRenderClientInterface);
|
||||
audioRenderClientInterface = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Volume Notification Data
|
||||
/// </summary>
|
||||
public class AudioVolumeNotificationData
|
||||
{
|
||||
private Guid _EventContext;
|
||||
private bool _Muted;
|
||||
private float _MasterVolume;
|
||||
private int _Channels;
|
||||
private float[] _ChannelVolume;
|
||||
|
||||
/// <summary>
|
||||
/// Event Context
|
||||
/// </summary>
|
||||
public Guid EventContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _EventContext;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Muted
|
||||
/// </summary>
|
||||
public bool Muted
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Muted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Master Volume
|
||||
/// </summary>
|
||||
public float MasterVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
return _MasterVolume;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Channels
|
||||
/// </summary>
|
||||
public int Channels
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Channels;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Channel Volume
|
||||
/// </summary>
|
||||
public float[] ChannelVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ChannelVolume;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Audio Volume Notification Data
|
||||
/// </summary>
|
||||
/// <param name="eventContext"></param>
|
||||
/// <param name="muted"></param>
|
||||
/// <param name="masterVolume"></param>
|
||||
/// <param name="channelVolume"></param>
|
||||
public AudioVolumeNotificationData(Guid eventContext, bool muted, float masterVolume, float[] channelVolume)
|
||||
{
|
||||
_EventContext = eventContext;
|
||||
_Muted = muted;
|
||||
_MasterVolume = masterVolume;
|
||||
_Channels = channelVolume.Length;
|
||||
_ChannelVolume = channelVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Audio Volume Notification Data
|
||||
/// </summary>
|
||||
/// <param name="eventContext"></param>
|
||||
/// <param name="muted"></param>
|
||||
/// <param name="masterVolume"></param>
|
||||
/// <param name="channels"></param>
|
||||
public AudioVolumeNotificationData(Guid eventContext, bool muted, float masterVolume)
|
||||
{
|
||||
_EventContext = eventContext;
|
||||
_Muted = muted;
|
||||
_MasterVolume = masterVolume;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
CUETools.Codecs.CoreAudio/CoreAudioApi/DataFlow.cs
Normal file
31
CUETools.Codecs.CoreAudio/CoreAudioApi/DataFlow.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// The EDataFlow enumeration defines constants that indicate the direction
|
||||
/// in which audio data flows between an audio endpoint device and an application
|
||||
/// </summary>
|
||||
public enum DataFlow
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio rendering stream.
|
||||
/// Audio data flows from the application to the audio endpoint device, which renders the stream.
|
||||
/// </summary>
|
||||
Render,
|
||||
/// <summary>
|
||||
/// Audio capture stream. Audio data flows from the audio endpoint device that captures the stream,
|
||||
/// to the application
|
||||
/// </summary>
|
||||
Capture,
|
||||
/// <summary>
|
||||
/// Audio rendering or capture stream. Audio data can flow either from the application to the audio
|
||||
/// endpoint device, or from the audio endpoint device to the application.
|
||||
/// </summary>
|
||||
All
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
52
CUETools.Codecs.CoreAudio/CoreAudioApi/DeviceState.cs
Normal file
52
CUETools.Codecs.CoreAudio/CoreAudioApi/DeviceState.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// adapted for NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Device State
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum DeviceState
|
||||
{
|
||||
/// <summary>
|
||||
/// DEVICE_STATE_ACTIVE
|
||||
/// </summary>
|
||||
Active = 0x00000001,
|
||||
/// <summary>
|
||||
/// DEVICE_STATE_UNPLUGGED
|
||||
/// </summary>
|
||||
Unplugged = 0x00000002,
|
||||
/// <summary>
|
||||
/// DEVICE_STATE_NOTPRESENT
|
||||
/// </summary>
|
||||
NotPresent = 0x00000004,
|
||||
/// <summary>
|
||||
/// DEVICE_STATEMASK_ALL
|
||||
/// </summary>
|
||||
All = 0x00000007
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Endpoint Hardware Support
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum EEndpointHardwareSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume
|
||||
/// </summary>
|
||||
Volume = 0x00000001,
|
||||
/// <summary>
|
||||
/// Mute
|
||||
/// </summary>
|
||||
Mute = 0x00000002,
|
||||
/// <summary>
|
||||
/// Meter
|
||||
/// </summary>
|
||||
Meter = 0x00000004
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
internal struct AudioVolumeNotificationDataStruct
|
||||
{
|
||||
public Guid guidEventContext;
|
||||
public bool bMuted;
|
||||
public float fMasterVolume;
|
||||
public uint nChannels;
|
||||
public float ChannelVolume;
|
||||
|
||||
//Code Should Compile at warning level4 without any warnings,
|
||||
//However this struct will give us Warning CS0649: Field [Fieldname]
|
||||
//is never assigned to, and will always have its default value
|
||||
//You can disable CS0649 in the project options but that will disable
|
||||
//the warning for the whole project, it's a nice warning and we do want
|
||||
//it in other places so we make a nice dummy function to keep the compiler
|
||||
//happy.
|
||||
private void FixCS0649()
|
||||
{
|
||||
guidEventContext = Guid.Empty;
|
||||
bMuted = false;
|
||||
fMasterVolume = 0;
|
||||
nChannels = 0;
|
||||
ChannelVolume = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
49
CUETools.Codecs.CoreAudio/CoreAudioApi/Interfaces/Blob.cs
Normal file
49
CUETools.Codecs.CoreAudio/CoreAudioApi/Interfaces/Blob.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// Adapted for NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
internal struct Blob
|
||||
{
|
||||
public int Length;
|
||||
public IntPtr Data;
|
||||
|
||||
//Code Should Compile at warning level4 without any warnings,
|
||||
//However this struct will give us Warning CS0649: Field [Fieldname]
|
||||
//is never assigned to, and will always have its default value
|
||||
//You can disable CS0649 in the project options but that will disable
|
||||
//the warning for the whole project, it's a nice warning and we do want
|
||||
//it in other places so we make a nice dummy function to keep the compiler
|
||||
//happy.
|
||||
private void FixCS0649()
|
||||
{
|
||||
Length = 0;
|
||||
Data = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
CUETools.Codecs.CoreAudio/CoreAudioApi/Interfaces/ClsCtx.cs
Normal file
39
CUETools.Codecs.CoreAudio/CoreAudioApi/Interfaces/ClsCtx.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// is defined in WTypes.h
|
||||
/// </summary>
|
||||
[Flags]
|
||||
enum ClsCtx
|
||||
{
|
||||
INPROC_SERVER = 0x1,
|
||||
INPROC_HANDLER = 0x2,
|
||||
LOCAL_SERVER = 0x4,
|
||||
INPROC_SERVER16 = 0x8,
|
||||
REMOTE_SERVER = 0x10,
|
||||
INPROC_HANDLER16 = 0x20,
|
||||
//RESERVED1 = 0x40,
|
||||
//RESERVED2 = 0x80,
|
||||
//RESERVED3 = 0x100,
|
||||
//RESERVED4 = 0x200,
|
||||
NO_CODE_DOWNLOAD = 0x400,
|
||||
//RESERVED5 = 0x800,
|
||||
NO_CUSTOM_MARSHAL = 0x1000,
|
||||
ENABLE_CODE_DOWNLOAD = 0x2000,
|
||||
NO_FAILURE_LOG = 0x4000,
|
||||
DISABLE_AAA = 0x8000,
|
||||
ENABLE_AAA = 0x10000,
|
||||
FROM_DEFAULT_CONTEXT = 0x20000,
|
||||
ACTIVATE_32_BIT_SERVER = 0x40000,
|
||||
ACTIVATE_64_BIT_SERVER = 0x80000,
|
||||
ENABLE_CLOAKING = 0x100000,
|
||||
PS_DLL = unchecked ( (int) 0x80000000 ),
|
||||
INPROC = INPROC_SERVER | INPROC_HANDLER,
|
||||
SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
|
||||
ALL = SERVER | INPROC_HANDLER
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
enum AudioClientErrors
|
||||
{
|
||||
/// <summary>
|
||||
/// AUDCLNT_E_NOT_INITIALIZED
|
||||
/// </summary>
|
||||
NotInitialized = unchecked((int)0x88890001),
|
||||
/// <summary>
|
||||
/// AUDCLNT_E_UNSUPPORTED_FORMAT
|
||||
/// </summary>
|
||||
UnsupportedFormat = unchecked((int)0x88890008),
|
||||
/// <summary>
|
||||
/// AUDCLNT_E_DEVICE_IN_USE
|
||||
/// </summary>
|
||||
DeviceInUse = unchecked((int)0x8889000A),
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
|
||||
|
||||
[Guid("C8ADBD64-E71E-48a0-A4DE-185C395CD317"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IAudioCaptureClient
|
||||
{
|
||||
/*HRESULT GetBuffer(
|
||||
BYTE** ppData,
|
||||
UINT32* pNumFramesToRead,
|
||||
DWORD* pdwFlags,
|
||||
UINT64* pu64DevicePosition,
|
||||
UINT64* pu64QPCPosition
|
||||
);*/
|
||||
|
||||
int GetBuffer(
|
||||
out IntPtr dataBuffer,
|
||||
out int numFramesToRead,
|
||||
out AudioClientBufferFlags bufferFlags,
|
||||
out long devicePosition,
|
||||
out long qpcPosition);
|
||||
|
||||
int ReleaseBuffer(int numFramesRead);
|
||||
|
||||
int GetNextPacketSize(out int numFramesInNextPacket);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.Wave;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// n.b. WORK IN PROGRESS - this code will probably do nothing but crash at the moment
|
||||
/// Defined in AudioClient.h
|
||||
/// </summary>
|
||||
[Guid("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IAudioClient
|
||||
{
|
||||
void Initialize(AudioClientShareMode shareMode,
|
||||
AudioClientStreamFlags StreamFlags,
|
||||
long hnsBufferDuration, // REFERENCE_TIME
|
||||
long hnsPeriodicity, // REFERENCE_TIME
|
||||
[In] WaveFormat pFormat,
|
||||
[In] ref Guid AudioSessionGuid);
|
||||
|
||||
/// <summary>
|
||||
/// The GetBufferSize method retrieves the size (maximum capacity) of the endpoint buffer.
|
||||
/// </summary>
|
||||
void GetBufferSize(out uint bufferSize);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.I8)]
|
||||
long GetStreamLatency();
|
||||
|
||||
void GetCurrentPadding(out int currentPadding);
|
||||
|
||||
[PreserveSig]
|
||||
int IsFormatSupported(
|
||||
AudioClientShareMode shareMode,
|
||||
[In] WaveFormat pFormat,
|
||||
[Out, MarshalAs(UnmanagedType.LPStruct)] out WaveFormatExtensible closestMatchFormat);
|
||||
|
||||
void GetMixFormat(out IntPtr deviceFormatPointer);
|
||||
|
||||
// REFERENCE_TIME is 64 bit int
|
||||
void GetDevicePeriod(out long defaultDevicePeriod, out long minimumDevicePeriod);
|
||||
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetEventHandle(IntPtr eventHandle);
|
||||
|
||||
void GetService(ref Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IAudioEndpointVolume
|
||||
{
|
||||
int RegisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
|
||||
int UnregisterControlChangeNotify(IAudioEndpointVolumeCallback pNotify);
|
||||
int GetChannelCount(out int pnChannelCount);
|
||||
int SetMasterVolumeLevel(float fLevelDB, Guid pguidEventContext);
|
||||
int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);
|
||||
int GetMasterVolumeLevel(out float pfLevelDB);
|
||||
int GetMasterVolumeLevelScalar(out float pfLevel);
|
||||
int SetChannelVolumeLevel(uint nChannel, float fLevelDB, Guid pguidEventContext);
|
||||
int SetChannelVolumeLevelScalar(uint nChannel, float fLevel, Guid pguidEventContext);
|
||||
int GetChannelVolumeLevel(uint nChannel, out float pfLevelDB);
|
||||
int GetChannelVolumeLevelScalar(uint nChannel, out float pfLevel);
|
||||
int SetMute([MarshalAs(UnmanagedType.Bool)] Boolean bMute, Guid pguidEventContext);
|
||||
int GetMute(out bool pbMute);
|
||||
int GetVolumeStepInfo(out uint pnStep, out uint pnStepCount);
|
||||
int VolumeStepUp(Guid pguidEventContext);
|
||||
int VolumeStepDown(Guid pguidEventContext);
|
||||
int QueryHardwareSupport(out uint pdwHardwareSupportMask);
|
||||
int GetVolumeRange(out float pflVolumeMindB, out float pflVolumeMaxdB, out float pflVolumeIncrementdB);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("657804FA-D6AD-4496-8A60-352752AF4F89"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IAudioEndpointVolumeCallback
|
||||
{
|
||||
//int OnNotify(IntPtr NotifyData);
|
||||
void OnNotify(ref AudioVolumeNotificationDataStruct pNotifyData);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IAudioMeterInformation
|
||||
{
|
||||
int GetPeakValue(out float pfPeak);
|
||||
int GetMeteringChannelCount(out int pnChannelCount);
|
||||
int GetChannelsPeakValues(int u32ChannelCount, [In] IntPtr afPeakValues);
|
||||
int QueryHardwareSupport(out int pdwHardwareSupportMask);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("F294ACFC-3146-4483-A7BF-ADDCA7C260E2"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IAudioRenderClient
|
||||
{
|
||||
IntPtr GetBuffer(int numFramesRequested);
|
||||
void ReleaseBuffer(int numFramesWritten, AudioClientBufferFlags bufferFlags);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("D666063F-1587-4E43-81F1-B948E807363F"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IMMDevice
|
||||
{
|
||||
// activationParams is a propvariant
|
||||
int Activate(ref Guid id, ClsCtx clsCtx, IntPtr activationParams,
|
||||
[MarshalAs(UnmanagedType.IUnknown)] out object interfacePointer);
|
||||
|
||||
int OpenPropertyStore(StorageAccessMode stgmAccess, out IPropertyStore properties);
|
||||
|
||||
int GetId(out string id);
|
||||
|
||||
int GetState(out DeviceState state);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IMMDeviceCollection
|
||||
{
|
||||
int GetCount(out int numDevices);
|
||||
int Item(int deviceNumber, out IMMDevice device);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IMMDeviceEnumerator
|
||||
{
|
||||
int EnumAudioEndpoints(DataFlow dataFlow, DeviceState stateMask,
|
||||
out IMMDeviceCollection devices);
|
||||
|
||||
int GetDefaultAudioEndpoint(DataFlow dataFlow, Role role, out IMMDevice endpoint);
|
||||
|
||||
int GetDevice(string id, out IMMDevice deviceName);
|
||||
|
||||
int RegisterEndpointNotificationCallback(IMMNotificationClient client);
|
||||
|
||||
int UnregisterEndpointNotificationCallback(IMMNotificationClient client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// defined in MMDeviceAPI.h
|
||||
/// </summary>
|
||||
[Guid("1BE09788-6894-4089-8586-9A2A6C265AC5"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IMMEndpoint
|
||||
{
|
||||
int GetDataFlow(out DataFlow dataFlow);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
[Guid("7991EEC9-7E89-4D85-8390-6C703CEC60C0"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IMMNotificationClient
|
||||
{
|
||||
int OnDeviceStateChanged(string deviceId, int newState);
|
||||
|
||||
int OnDeviceAdded(string pwstrDeviceId);
|
||||
|
||||
int OnDeviceRemoved(string deviceId);
|
||||
|
||||
int OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId);
|
||||
|
||||
int OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// is defined in propsys.h
|
||||
/// </summary>
|
||||
[Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"),
|
||||
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
interface IPropertyStore
|
||||
{
|
||||
int GetCount(out int propCount);
|
||||
int GetAt(int property, out PropertyKey key);
|
||||
int GetValue(ref PropertyKey key, out PropVariant value);
|
||||
int SetValue(ref PropertyKey key, ref PropVariant value);
|
||||
int Commit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// implements IMMDeviceEnumerator
|
||||
/// </summary>
|
||||
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
|
||||
class MMDeviceEnumeratorComObject
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// MMDevice STGM enumeration
|
||||
/// </summary>
|
||||
enum StorageAccessMode
|
||||
{
|
||||
Read,
|
||||
Write,
|
||||
ReadWrite
|
||||
}
|
||||
}
|
||||
219
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDevice.cs
Normal file
219
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDevice.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// modified for NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// MM Device
|
||||
/// </summary>
|
||||
public class MMDevice
|
||||
{
|
||||
#region Variables
|
||||
private IMMDevice deviceInterface;
|
||||
private PropertyStore _PropertyStore;
|
||||
private AudioMeterInformation _AudioMeterInformation;
|
||||
private AudioEndpointVolume _AudioEndpointVolume;
|
||||
private AudioClient audioClient;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Guids
|
||||
private static Guid IID_IAudioMeterInformation = new Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064");
|
||||
private static Guid IID_IAudioEndpointVolume = new Guid("5CDF2C82-841E-4546-9722-0CF74078229A");
|
||||
private static Guid IID_IAudioClient = new Guid("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2");
|
||||
#endregion
|
||||
|
||||
#region Init
|
||||
private void GetPropertyInformation()
|
||||
{
|
||||
IPropertyStore propstore;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.OpenPropertyStore(StorageAccessMode.Read, out propstore));
|
||||
_PropertyStore = new PropertyStore(propstore);
|
||||
}
|
||||
|
||||
private void GetAudioClientInterface()
|
||||
{
|
||||
object result;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.Activate(ref IID_IAudioClient, ClsCtx.ALL, IntPtr.Zero, out result));
|
||||
audioClient = new AudioClient(result as IAudioClient);
|
||||
}
|
||||
|
||||
private void GetAudioMeterInformation()
|
||||
{
|
||||
object result;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.Activate(ref IID_IAudioMeterInformation, ClsCtx.ALL, IntPtr.Zero, out result));
|
||||
_AudioMeterInformation = new AudioMeterInformation(result as IAudioMeterInformation);
|
||||
}
|
||||
|
||||
private void GetAudioEndpointVolume()
|
||||
{
|
||||
object result;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.Activate(ref IID_IAudioEndpointVolume, ClsCtx.ALL, IntPtr.Zero, out result));
|
||||
_AudioEndpointVolume = new AudioEndpointVolume(result as IAudioEndpointVolume);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Audio Client
|
||||
/// </summary>
|
||||
public AudioClient AudioClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (audioClient == null)
|
||||
{
|
||||
GetAudioClientInterface();
|
||||
}
|
||||
return audioClient;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Audio Meter Information
|
||||
/// </summary>
|
||||
public AudioMeterInformation AudioMeterInformation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_AudioMeterInformation == null)
|
||||
GetAudioMeterInformation();
|
||||
|
||||
return _AudioMeterInformation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Audio Endpoint Volume
|
||||
/// </summary>
|
||||
public AudioEndpointVolume AudioEndpointVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_AudioEndpointVolume == null)
|
||||
GetAudioEndpointVolume();
|
||||
|
||||
return _AudioEndpointVolume;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Properties
|
||||
/// </summary>
|
||||
public PropertyStore Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_PropertyStore == null)
|
||||
GetPropertyInformation();
|
||||
return _PropertyStore;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Friendly name
|
||||
/// </summary>
|
||||
public string FriendlyName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_PropertyStore == null)
|
||||
{
|
||||
GetPropertyInformation();
|
||||
}
|
||||
if (_PropertyStore.Contains(PropertyKeys.PKEY_DeviceInterface_FriendlyName))
|
||||
{
|
||||
return (string)_PropertyStore[PropertyKeys.PKEY_DeviceInterface_FriendlyName].Value;
|
||||
}
|
||||
else
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Device ID
|
||||
/// </summary>
|
||||
public string ID
|
||||
{
|
||||
get
|
||||
{
|
||||
string Result;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.GetId(out Result));
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data Flow
|
||||
/// </summary>
|
||||
public DataFlow DataFlow
|
||||
{
|
||||
get
|
||||
{
|
||||
DataFlow Result;
|
||||
IMMEndpoint ep = deviceInterface as IMMEndpoint;
|
||||
ep.GetDataFlow(out Result);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Device State
|
||||
/// </summary>
|
||||
public DeviceState State
|
||||
{
|
||||
get
|
||||
{
|
||||
DeviceState Result;
|
||||
Marshal.ThrowExceptionForHR(deviceInterface.GetState(out Result));
|
||||
return Result;
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
internal MMDevice(IMMDevice realDevice)
|
||||
{
|
||||
deviceInterface = realDevice;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// To string
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return FriendlyName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
96
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDeviceCollection.cs
Normal file
96
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDeviceCollection.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// updated for NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Multimedia Device Collection
|
||||
/// </summary>
|
||||
public class MMDeviceCollection : IEnumerable<MMDevice>
|
||||
{
|
||||
private IMMDeviceCollection _MMDeviceCollection;
|
||||
|
||||
/// <summary>
|
||||
/// Device count
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int result;
|
||||
Marshal.ThrowExceptionForHR(_MMDeviceCollection.GetCount(out result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get device by index
|
||||
/// </summary>
|
||||
/// <param name="index">Device index</param>
|
||||
/// <returns>Device at the specified index</returns>
|
||||
public MMDevice this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
IMMDevice result;
|
||||
_MMDeviceCollection.Item(index, out result);
|
||||
return new MMDevice(result);
|
||||
}
|
||||
}
|
||||
|
||||
internal MMDeviceCollection(IMMDeviceCollection parent)
|
||||
{
|
||||
_MMDeviceCollection = parent;
|
||||
}
|
||||
|
||||
#region IEnumerable<MMDevice> Members
|
||||
|
||||
/// <summary>
|
||||
/// Get Enumerator
|
||||
/// </summary>
|
||||
/// <returns>Device enumerator</returns>
|
||||
public IEnumerator<MMDevice> GetEnumerator()
|
||||
{
|
||||
for (int index = 0; index < Count; index++)
|
||||
{
|
||||
yield return this[index];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
89
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDeviceEnumerator.cs
Normal file
89
CUETools.Codecs.CoreAudio/CoreAudioApi/MMDeviceEnumerator.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// updated for use in NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// MM Device Enumerator
|
||||
/// </summary>
|
||||
public class MMDeviceEnumerator
|
||||
{
|
||||
private IMMDeviceEnumerator _realEnumerator;
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate Audio Endpoints
|
||||
/// </summary>
|
||||
/// <param name="dataFlow">Desired DataFlow</param>
|
||||
/// <param name="dwStateMask">State Mask</param>
|
||||
/// <returns>Device Collection</returns>
|
||||
public MMDeviceCollection EnumerateAudioEndPoints(DataFlow dataFlow, DeviceState dwStateMask)
|
||||
{
|
||||
IMMDeviceCollection result;
|
||||
Marshal.ThrowExceptionForHR(_realEnumerator.EnumAudioEndpoints(dataFlow, dwStateMask, out result));
|
||||
return new MMDeviceCollection(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Default Endpoint
|
||||
/// </summary>
|
||||
/// <param name="dataFlow">Data Flow</param>
|
||||
/// <param name="role">Role</param>
|
||||
/// <returns>Device</returns>
|
||||
public MMDevice GetDefaultAudioEndpoint(DataFlow dataFlow, Role role)
|
||||
{
|
||||
IMMDevice _Device = null;
|
||||
Marshal.ThrowExceptionForHR(((IMMDeviceEnumerator)_realEnumerator).GetDefaultAudioEndpoint(dataFlow, role, out _Device));
|
||||
return new MMDevice(_Device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get device by ID
|
||||
/// </summary>
|
||||
/// <param name="ID">Device ID</param>
|
||||
/// <returns>Device</returns>
|
||||
public MMDevice GetDevice(string ID)
|
||||
{
|
||||
IMMDevice _Device = null;
|
||||
Marshal.ThrowExceptionForHR(((IMMDeviceEnumerator)_realEnumerator).GetDevice(ID, out _Device));
|
||||
return new MMDevice(_Device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new MM Device Enumerator
|
||||
/// </summary>
|
||||
public MMDeviceEnumerator()
|
||||
{
|
||||
if (System.Environment.OSVersion.Version.Major < 6)
|
||||
{
|
||||
throw new NotSupportedException("This functionality is only supported on Windows Vista or newer.");
|
||||
}
|
||||
_realEnumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
|
||||
}
|
||||
}
|
||||
}
|
||||
157
CUETools.Codecs.CoreAudio/CoreAudioApi/PropVariant.cs
Normal file
157
CUETools.Codecs.CoreAudio/CoreAudioApi/PropVariant.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// adapted for use in NAudio
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// from Propidl.h.
|
||||
/// http://msdn.microsoft.com/en-us/library/aa380072(VS.85).aspx
|
||||
/// contains a union so we have to do an explicit layout
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct PropVariant
|
||||
{
|
||||
[FieldOffset(0)] short vt;
|
||||
[FieldOffset(2)] short wReserved1;
|
||||
[FieldOffset(4)] short wReserved2;
|
||||
[FieldOffset(6)] short wReserved3;
|
||||
[FieldOffset(8)] sbyte cVal;
|
||||
[FieldOffset(8)] byte bVal;
|
||||
[FieldOffset(8)] short iVal;
|
||||
[FieldOffset(8)] ushort uiVal;
|
||||
[FieldOffset(8)] int lVal;
|
||||
[FieldOffset(8)] uint ulVal;
|
||||
[FieldOffset(8)] int intVal;
|
||||
[FieldOffset(8)] uint uintVal;
|
||||
[FieldOffset(8)] long hVal;
|
||||
[FieldOffset(8)] long uhVal;
|
||||
[FieldOffset(8)] float fltVal;
|
||||
[FieldOffset(8)] double dblVal;
|
||||
[FieldOffset(8)] bool boolVal;
|
||||
[FieldOffset(8)] int scode;
|
||||
//CY cyVal;
|
||||
[FieldOffset(8)] DateTime date;
|
||||
[FieldOffset(8)] System.Runtime.InteropServices.ComTypes.FILETIME filetime;
|
||||
//CLSID* puuid;
|
||||
//CLIPDATA* pclipdata;
|
||||
//BSTR bstrVal;
|
||||
//BSTRBLOB bstrblobVal;
|
||||
[FieldOffset(8)] Blob blobVal;
|
||||
//LPSTR pszVal;
|
||||
[FieldOffset(8)] IntPtr pwszVal; //LPWSTR
|
||||
//IUnknown* punkVal;
|
||||
/*IDispatch* pdispVal;
|
||||
IStream* pStream;
|
||||
IStorage* pStorage;
|
||||
LPVERSIONEDSTREAM pVersionedStream;
|
||||
LPSAFEARRAY parray;
|
||||
CAC cac;
|
||||
CAUB caub;
|
||||
CAI cai;
|
||||
CAUI caui;
|
||||
CAL cal;
|
||||
CAUL caul;
|
||||
CAH cah;
|
||||
CAUH cauh;
|
||||
CAFLT caflt;
|
||||
CADBL cadbl;
|
||||
CABOOL cabool;
|
||||
CASCODE cascode;
|
||||
CACY cacy;
|
||||
CADATE cadate;
|
||||
CAFILETIME cafiletime;
|
||||
CACLSID cauuid;
|
||||
CACLIPDATA caclipdata;
|
||||
CABSTR cabstr;
|
||||
CABSTRBLOB cabstrblob;
|
||||
CALPSTR calpstr;
|
||||
CALPWSTR calpwstr;
|
||||
CAPROPVARIANT capropvar;
|
||||
CHAR* pcVal;
|
||||
UCHAR* pbVal;
|
||||
SHORT* piVal;
|
||||
USHORT* puiVal;
|
||||
LONG* plVal;
|
||||
ULONG* pulVal;
|
||||
INT* pintVal;
|
||||
UINT* puintVal;
|
||||
FLOAT* pfltVal;
|
||||
DOUBLE* pdblVal;
|
||||
VARIANT_BOOL* pboolVal;
|
||||
DECIMAL* pdecVal;
|
||||
SCODE* pscode;
|
||||
CY* pcyVal;
|
||||
DATE* pdate;
|
||||
BSTR* pbstrVal;
|
||||
IUnknown** ppunkVal;
|
||||
IDispatch** ppdispVal;
|
||||
LPSAFEARRAY* pparray;
|
||||
PROPVARIANT* pvarVal;
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to gets blob data
|
||||
/// </summary>
|
||||
byte[] GetBlob()
|
||||
{
|
||||
byte[] Result = new byte[blobVal.Length];
|
||||
Marshal.Copy(blobVal.Data, Result, 0, Result.Length);
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property value
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
VarEnum ve = (VarEnum)vt;
|
||||
switch (ve)
|
||||
{
|
||||
case VarEnum.VT_I1:
|
||||
return bVal;
|
||||
case VarEnum.VT_I2:
|
||||
return iVal;
|
||||
case VarEnum.VT_I4:
|
||||
return lVal;
|
||||
case VarEnum.VT_I8:
|
||||
return hVal;
|
||||
case VarEnum.VT_INT:
|
||||
return iVal;
|
||||
case VarEnum.VT_UI4:
|
||||
return ulVal;
|
||||
case VarEnum.VT_LPWSTR:
|
||||
return Marshal.PtrToStringUni(pwszVal);
|
||||
case VarEnum.VT_BLOB:
|
||||
return GetBlob();
|
||||
}
|
||||
throw new NotImplementedException("PropVariant " + ve.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyKey.cs
Normal file
21
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyKey.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// PROPERTYKEY is defined in wtypes.h
|
||||
/// </summary>
|
||||
public struct PropertyKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Format ID
|
||||
/// </summary>
|
||||
public Guid formatId;
|
||||
/// <summary>
|
||||
/// Property ID
|
||||
/// </summary>
|
||||
public int propertyId;
|
||||
}
|
||||
}
|
||||
71
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyKeys.cs
Normal file
71
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyKeys.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Property Keys
|
||||
/// </summary>
|
||||
public static class PropertyKeys
|
||||
{
|
||||
/// <summary>
|
||||
/// PKEY_DeviceInterface_FriendlyName
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_DeviceInterface_FriendlyName = new Guid(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_FormFactor
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_FormFactor = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_ControlPanelPageProvider
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_ControlPanelPageProvider = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_Association
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_Association = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_PhysicalSpeakers
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_PhysicalSpeakers = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_GUID
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_GUID = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_Disable_SysFx
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_Disable_SysFx = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEndpoint_FullRangeSpeakers
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEndpoint_FullRangeSpeakers = new Guid(0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e);
|
||||
/// <summary>
|
||||
/// PKEY_AudioEngine_DeviceFormat
|
||||
/// </summary>
|
||||
public static readonly Guid PKEY_AudioEngine_DeviceFormat = new Guid(0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c);
|
||||
|
||||
}
|
||||
}
|
||||
143
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyStore.cs
Normal file
143
CUETools.Codecs.CoreAudio/CoreAudioApi/PropertyStore.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// this version modified for NAudio from Ray Molenkamp's original
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Property Store class, only supports reading properties at the moment.
|
||||
/// </summary>
|
||||
public class PropertyStore
|
||||
{
|
||||
private IPropertyStore storeInterface;
|
||||
|
||||
/// <summary>
|
||||
/// Property Count
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
int result;
|
||||
Marshal.ThrowExceptionForHR(storeInterface.GetCount(out result));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets property by index
|
||||
/// </summary>
|
||||
/// <param name="index">Property index</param>
|
||||
/// <returns>The property</returns>
|
||||
public PropertyStoreProperty this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
PropVariant result;
|
||||
PropertyKey key = Get(index);
|
||||
Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out result));
|
||||
return new PropertyStoreProperty(key, result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains property guid
|
||||
/// </summary>
|
||||
/// <param name="guid">Looks for a specific Guid</param>
|
||||
/// <returns>True if found</returns>
|
||||
public bool Contains(Guid guid)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
PropertyKey key = Get(i);
|
||||
if (key.formatId == guid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indexer by guid
|
||||
/// </summary>
|
||||
/// <param name="guid">Property guid</param>
|
||||
/// <returns>Property or null if not found</returns>
|
||||
public PropertyStoreProperty this[Guid guid]
|
||||
{
|
||||
get
|
||||
{
|
||||
PropVariant result;
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
PropertyKey key = Get(i);
|
||||
if (key.formatId == guid)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out result));
|
||||
return new PropertyStoreProperty(key, result);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets property key at sepecified index
|
||||
/// </summary>
|
||||
/// <param name="index">Index</param>
|
||||
/// <returns>Property key</returns>
|
||||
public PropertyKey Get(int index)
|
||||
{
|
||||
PropertyKey key;
|
||||
Marshal.ThrowExceptionForHR(storeInterface.GetAt(index, out key));
|
||||
return key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets property value at specified index
|
||||
/// </summary>
|
||||
/// <param name="index">Index</param>
|
||||
/// <returns>Property value</returns>
|
||||
public PropVariant GetValue(int index)
|
||||
{
|
||||
PropVariant result;
|
||||
PropertyKey key = Get(index);
|
||||
Marshal.ThrowExceptionForHR(storeInterface.GetValue(ref key, out result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new property store
|
||||
/// </summary>
|
||||
/// <param name="store">IPropertyStore COM interface</param>
|
||||
internal PropertyStore(IPropertyStore store)
|
||||
{
|
||||
this.storeInterface = store;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
LICENSE
|
||||
-------
|
||||
Copyright (C) 2007 Ray Molenkamp
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this source code or the software it produces.
|
||||
|
||||
Permission is granted to anyone to use this source code for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
// modified from Ray Molenkamp's original
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.CoreAudioApi.Interfaces;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Property Store Property
|
||||
/// </summary>
|
||||
public class PropertyStoreProperty
|
||||
{
|
||||
private PropertyKey propertyKey;
|
||||
private PropVariant propertyValue;
|
||||
|
||||
internal PropertyStoreProperty(PropertyKey key, PropVariant value)
|
||||
{
|
||||
propertyKey = key;
|
||||
propertyValue = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property Key
|
||||
/// </summary>
|
||||
public PropertyKey Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return propertyKey;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property Value
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return propertyValue.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
CUETools.Codecs.CoreAudio/CoreAudioApi/Role.cs
Normal file
26
CUETools.Codecs.CoreAudio/CoreAudioApi/Role.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// The ERole enumeration defines constants that indicate the role
|
||||
/// that the system has assigned to an audio endpoint device
|
||||
/// </summary>
|
||||
public enum Role
|
||||
{
|
||||
/// <summary>
|
||||
/// Games, system notification sounds, and voice commands.
|
||||
/// </summary>
|
||||
Console,
|
||||
/// <summary>
|
||||
/// Music, movies, narration, and live music recording
|
||||
/// </summary>
|
||||
Multimedia,
|
||||
/// <summary>
|
||||
/// Voice communications (talking to another person).
|
||||
/// </summary>
|
||||
Communications,
|
||||
}
|
||||
}
|
||||
216
CUETools.Codecs.CoreAudio/CoreAudioApi/WasapiCapture.cs
Normal file
216
CUETools.Codecs.CoreAudio/CoreAudioApi/WasapiCapture.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NAudio.Wave;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NAudio.CoreAudioApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Audio Capture using Wasapi
|
||||
/// See http://msdn.microsoft.com/en-us/library/dd370800%28VS.85%29.aspx
|
||||
/// </summary>
|
||||
public class WasapiCapture : IWaveIn
|
||||
{
|
||||
private const long REFTIMES_PER_SEC = 10000000;
|
||||
private const long REFTIMES_PER_MILLISEC = 10000;
|
||||
private volatile bool stop;
|
||||
private byte[] recordBuffer;
|
||||
private Thread captureThread;
|
||||
private AudioClient audioClient;
|
||||
private int bytesPerFrame;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates recorded data is available
|
||||
/// </summary>
|
||||
public event EventHandler<WaveInEventArgs> DataAvailable;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that all recorded data has now been received.
|
||||
/// </summary>
|
||||
public event EventHandler RecordingStopped;
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the WASAPI capture class
|
||||
/// </summary>
|
||||
public WasapiCapture() :
|
||||
this(GetDefaultCaptureDevice())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialises a new instance of the WASAPI capture class
|
||||
/// </summary>
|
||||
/// <param name="captureDevice">Capture device to use</param>
|
||||
public WasapiCapture(MMDevice captureDevice)
|
||||
{
|
||||
this.audioClient = captureDevice.AudioClient;
|
||||
WaveFormat = audioClient.MixFormat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recording wave format
|
||||
/// </summary>
|
||||
public WaveFormat WaveFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default audio capture device
|
||||
/// </summary>
|
||||
/// <returns>The default audio capture device</returns>
|
||||
public static MMDevice GetDefaultCaptureDevice()
|
||||
{
|
||||
MMDeviceEnumerator devices = new MMDeviceEnumerator();
|
||||
return devices.GetDefaultAudioEndpoint(DataFlow.Capture, Role.Console);
|
||||
}
|
||||
|
||||
private void InitializeCaptureDevice()
|
||||
{
|
||||
long requestedDuration = REFTIMES_PER_MILLISEC * 100;
|
||||
|
||||
if (!audioClient.IsFormatSupported(AudioClientShareMode.Shared, WaveFormat))
|
||||
{
|
||||
throw new ArgumentException("Unsupported Wave Format");
|
||||
}
|
||||
|
||||
audioClient.Initialize(AudioClientShareMode.Shared,
|
||||
AudioClientStreamFlags.None,
|
||||
requestedDuration,
|
||||
0,
|
||||
WaveFormat,
|
||||
Guid.Empty);
|
||||
|
||||
int bufferFrameCount = audioClient.BufferSize;
|
||||
bytesPerFrame = WaveFormat.Channels * WaveFormat.BitsPerSample / 8;
|
||||
recordBuffer = new byte[bufferFrameCount * bytesPerFrame];
|
||||
Debug.WriteLine(string.Format("record buffer size = {0}", recordBuffer.Length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start Recording
|
||||
/// </summary>
|
||||
public void StartRecording()
|
||||
{
|
||||
InitializeCaptureDevice();
|
||||
ThreadStart start = delegate { this.CaptureThread(this.audioClient); };
|
||||
this.captureThread = new Thread(start);
|
||||
|
||||
Debug.WriteLine("Thread starting...");
|
||||
this.stop = false;
|
||||
this.captureThread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop Recording
|
||||
/// </summary>
|
||||
public void StopRecording()
|
||||
{
|
||||
if (this.captureThread != null)
|
||||
{
|
||||
this.stop = true;
|
||||
|
||||
Debug.WriteLine("Thread ending...");
|
||||
|
||||
// wait for thread to end
|
||||
this.captureThread.Join();
|
||||
this.captureThread = null;
|
||||
|
||||
Debug.WriteLine("Done.");
|
||||
|
||||
this.stop = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CaptureThread(AudioClient client)
|
||||
{
|
||||
Debug.WriteLine(client.BufferSize);
|
||||
int bufferFrameCount = audioClient.BufferSize;
|
||||
|
||||
// Calculate the actual duration of the allocated buffer.
|
||||
long actualDuration = (long)((double)REFTIMES_PER_SEC *
|
||||
bufferFrameCount / WaveFormat.SampleRate);
|
||||
int sleepMilliseconds = (int)(actualDuration / REFTIMES_PER_MILLISEC / 2);
|
||||
|
||||
AudioCaptureClient capture = client.AudioCaptureClient;
|
||||
client.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Debug.WriteLine(string.Format("sleep: {0} ms", sleepMilliseconds));
|
||||
while (!this.stop)
|
||||
{
|
||||
Thread.Sleep(sleepMilliseconds);
|
||||
ReadNextPacket(capture);
|
||||
}
|
||||
|
||||
client.Stop();
|
||||
|
||||
if (RecordingStopped != null)
|
||||
{
|
||||
RecordingStopped(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (capture != null)
|
||||
{
|
||||
capture.Dispose();
|
||||
}
|
||||
if (client != null)
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
|
||||
client = null;
|
||||
capture = null;
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("stop wasapi");
|
||||
}
|
||||
|
||||
private void ReadNextPacket(AudioCaptureClient capture)
|
||||
{
|
||||
IntPtr buffer;
|
||||
int framesAvailable;
|
||||
AudioClientBufferFlags flags;
|
||||
int packetSize = capture.GetNextPacketSize();
|
||||
int recordBufferOffset = 0;
|
||||
//Debug.WriteLine(string.Format("packet size: {0} samples", packetSize / 4));
|
||||
|
||||
while (packetSize != 0)
|
||||
{
|
||||
buffer = capture.GetBuffer(out framesAvailable, out flags);
|
||||
|
||||
int bytesAvailable = framesAvailable * bytesPerFrame;
|
||||
|
||||
//Debug.WriteLine(string.Format("got buffer: {0} frames", framesAvailable));
|
||||
|
||||
// if not silence...
|
||||
if ((flags & AudioClientBufferFlags.Silent) != AudioClientBufferFlags.Silent)
|
||||
{
|
||||
Marshal.Copy(buffer, recordBuffer, recordBufferOffset, bytesAvailable);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Clear(recordBuffer, recordBufferOffset, bytesAvailable);
|
||||
}
|
||||
recordBufferOffset += bytesAvailable;
|
||||
capture.ReleaseBuffer(framesAvailable);
|
||||
packetSize = capture.GetNextPacketSize();
|
||||
}
|
||||
if (DataAvailable != null)
|
||||
{
|
||||
DataAvailable(this, new WaveInEventArgs(recordBuffer, recordBufferOffset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
StopRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user