222 lines
3.8 KiB
C#
222 lines
3.8 KiB
C#
#region License
|
|
/* FNA - XNA4 Reimplementation for Desktop Platforms
|
|
* Copyright 2009-2018 Ethan Lee and the MonoGame Team
|
|
*
|
|
* Released under the Microsoft Public License.
|
|
* See LICENSE for details.
|
|
*/
|
|
#endregion
|
|
|
|
#region Using Statements
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Runtime.InteropServices;
|
|
#endregion
|
|
|
|
namespace Microsoft.Xna.Framework.Audio
|
|
{
|
|
public class Microphone
|
|
{
|
|
#region Public Static Properties
|
|
|
|
public static ReadOnlyCollection<Microphone> All
|
|
{
|
|
get;
|
|
internal set;
|
|
}
|
|
|
|
public static Microphone Default
|
|
{
|
|
get
|
|
{
|
|
if (All.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
return All[0];
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
public TimeSpan BufferDuration
|
|
{
|
|
get
|
|
{
|
|
return bufferDuration;
|
|
}
|
|
set
|
|
{
|
|
if ( value.Milliseconds < 100 ||
|
|
value.Milliseconds > 1000 ||
|
|
value.Milliseconds % 10 != 0 )
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
bufferDuration = value;
|
|
}
|
|
}
|
|
|
|
public bool IsHeadset
|
|
{
|
|
get
|
|
{
|
|
// FIXME: I think this is just for Windows Phone? -flibit
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public int SampleRate
|
|
{
|
|
get
|
|
{
|
|
return SAMPLERATE;
|
|
}
|
|
}
|
|
|
|
public MicrophoneState State
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Variables
|
|
|
|
public readonly string Name;
|
|
|
|
#endregion
|
|
|
|
#region Private Variables
|
|
|
|
private TimeSpan bufferDuration;
|
|
private IntPtr nativeMic;
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
public event EventHandler<EventArgs> BufferReady;
|
|
|
|
#endregion
|
|
|
|
#region Private Constants
|
|
|
|
/* FIXME: This is what XNA4 aims for, but it _could_ be lower.
|
|
* Something work looking at is falling back to lower sample rates in
|
|
* powers of two, i.e. 44100, 22050, 11025, etc.
|
|
* -flibit
|
|
*/
|
|
private const int SAMPLERATE = 44100;
|
|
|
|
#endregion
|
|
|
|
#region Internal Constructor
|
|
|
|
internal Microphone(string name)
|
|
{
|
|
Name = name;
|
|
bufferDuration = TimeSpan.FromSeconds(1.0);
|
|
State = MicrophoneState.Stopped;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
public int GetData(byte[] buffer)
|
|
{
|
|
return GetData(buffer, 0, buffer.Length);
|
|
}
|
|
|
|
public int GetData(byte[] buffer, int offset, int count)
|
|
{
|
|
if (buffer == null)
|
|
{
|
|
throw new ArgumentException("buffer is null!");
|
|
}
|
|
if (offset < 0 || offset > buffer.Length)
|
|
{
|
|
throw new ArgumentException("offset");
|
|
}
|
|
if (count <= 0 || (offset + count) > buffer.Length)
|
|
{
|
|
throw new ArgumentException("count");
|
|
}
|
|
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
|
int read = AudioDevice.ALDevice.CaptureSamples(
|
|
nativeMic,
|
|
handle.AddrOfPinnedObject() + offset,
|
|
count
|
|
);
|
|
handle.Free();
|
|
return read;
|
|
}
|
|
|
|
public TimeSpan GetSampleDuration(int sizeInBytes)
|
|
{
|
|
return SoundEffect.GetSampleDuration(
|
|
sizeInBytes,
|
|
SampleRate,
|
|
AudioChannels.Mono
|
|
);
|
|
}
|
|
|
|
public int GetSampleSizeInBytes(TimeSpan duration)
|
|
{
|
|
return SoundEffect.GetSampleSizeInBytes(
|
|
duration,
|
|
SampleRate,
|
|
AudioChannels.Mono
|
|
);
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (State == MicrophoneState.Stopped)
|
|
{
|
|
nativeMic = AudioDevice.ALDevice.StartDeviceCapture(
|
|
Name,
|
|
SampleRate,
|
|
GetSampleSizeInBytes(bufferDuration)
|
|
);
|
|
if (nativeMic == IntPtr.Zero)
|
|
{
|
|
throw new NoMicrophoneConnectedException(Name);
|
|
}
|
|
AudioDevice.ActiveMics.Add(this);
|
|
State = MicrophoneState.Started;
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
if (State == MicrophoneState.Started)
|
|
{
|
|
AudioDevice.ActiveMics.Remove(this);
|
|
AudioDevice.ALDevice.StopDeviceCapture(nativeMic);
|
|
nativeMic = IntPtr.Zero;
|
|
State = MicrophoneState.Stopped;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Internal Methods
|
|
|
|
internal void CheckBuffer()
|
|
{
|
|
if ( BufferReady != null &&
|
|
AudioDevice.ALDevice.CaptureHasSamples(nativeMic) )
|
|
{
|
|
BufferReady(this, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|