Opentk/Source/Examples/OpenAL/1.1/Parrot.cs

239 lines
7.6 KiB
C#
Raw Normal View History

#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2009 the Open Toolkit library.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using OpenTK;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
namespace Examples
{
[Example("Parrot Audio Capture", ExampleCategory.OpenAL, "1.1", Documentation = "Parrot")]
public partial class Parrot : Form
{
#region Fields
AudioContext audio_context;
AudioCapture audio_capture;
int src;
short[] buffer = new short[512];
const byte SampleToByte = 2;
#endregion
#region Constructors
public Parrot()
{
InitializeComponent();
this.Text = "OpenAL Parrot (" + (IntPtr.Size == 4 ? "x86" : "x64") + ")";
// Add available capture devices to the combo box.
IList<string> recorders = AudioCapture.AvailableDevices;
for (int i = 0; i < recorders.Count; i++)
{
if (!String.IsNullOrEmpty(recorders[i]))
comboBox_RecorderSelection.Items.Add(recorders[i]);
}
if (comboBox_RecorderSelection.Items.Count > 0)
comboBox_RecorderSelection.SelectedIndex = 0;
}
#endregion
#region Events
private void button_Start_Click(object sender, EventArgs e)
{
if (audio_capture == null || !audio_capture.IsRunning)
{
button_Start.Text = "Stop Recording";
groupBox_RecorderParameters.Enabled = false;
this.StartRecording();
}
else
{
button_Start.Text = "Start Recording";
groupBox_RecorderParameters.Enabled = true;
this.StopRecording();
}
}
private void timer_UpdateSamples_Tick(object sender, EventArgs e)
{
this.UpdateSamples();
}
private void Parrot_FormClosing(object sender, FormClosingEventArgs e)
{
this.StopRecording();
}
#endregion
#region Private Members
void StartRecording()
{
try
{
audio_context = new AudioContext();
}
catch (AudioException ae)
{
MessageBox.Show("Fatal: Cannot continue without a playback device.\nException caught when opening playback device.\n" + ae.Message);
Application.Exit();
}
AL.Listener(ALListenerf.Gain, (float)numericUpDown_PlaybackGain.Value);
src = AL.GenSource();
int sampling_rate = (int)numericUpDown_Frequency.Value;
double buffer_length_ms = (double)numericUpDown_BufferLength.Value;
int buffer_length_samples = (int)((double)numericUpDown_BufferLength.Value * sampling_rate * 0.001 / BlittableValueType.StrideOf(buffer));
try
{
audio_capture = new AudioCapture((string)comboBox_RecorderSelection.SelectedItem,
sampling_rate, ALFormat.Mono16, buffer_length_samples);
}
catch (AudioDeviceException ade)
{
MessageBox.Show("Exception caught when opening recording device.\n" + ade.Message);
audio_capture = null;
}
if (audio_capture == null)
return;
audio_capture.Start();
timer_GetSamples.Start();
timer_GetSamples.Interval = (int)(buffer_length_ms / 2 + 0.5); // Tick when half the buffer is full.
}
void StopRecording()
{
timer_GetSamples.Stop();
if (audio_capture != null)
{
audio_capture.Stop();
audio_capture.Dispose();
audio_capture = null;
}
if (audio_context != null)
{
int r;
AL.GetSource(src, ALGetSourcei.BuffersQueued, out r);
ClearBuffers(r);
AL.DeleteSource(src);
audio_context.Dispose();
audio_context = null;
}
}
void UpdateSamples()
{
if (audio_capture == null)
return;
int available_samples = audio_capture.AvailableSamples;
if (available_samples * SampleToByte > buffer.Length * BlittableValueType.StrideOf(buffer))
{
buffer = new short[MathHelper.NextPowerOfTwo(
(int)(available_samples * SampleToByte / (double)BlittableValueType.StrideOf(buffer) + 0.5))];
}
if (available_samples > 0)
{
audio_capture.ReadSamples(buffer, available_samples);
int buf = AL.GenBuffer();
AL.BufferData(buf, ALFormat.Mono16, buffer, (int)(available_samples * BlittableValueType.StrideOf(buffer)), audio_capture.SampleFrequency);
AL.SourceQueueBuffer(src, buf);
label_SamplesConsumed.Text = "Samples consumed: " + available_samples;
if (AL.GetSourceState(src) != ALSourceState.Playing)
AL.SourcePlay(src);
}
ClearBuffers(0);
}
void ClearBuffers(int input)
{
if (audio_context == null || audio_context == null)
return;
int[] freedbuffers;
if (input == 0)
{
int BuffersProcessed;
AL.GetSource(src, ALGetSourcei.BuffersProcessed, out BuffersProcessed);
if (BuffersProcessed == 0)
return;
freedbuffers = AL.SourceUnqueueBuffers(src, BuffersProcessed);
}
else
{
freedbuffers = AL.SourceUnqueueBuffers(src, input);
}
AL.DeleteBuffers(freedbuffers);
}
#endregion
#region Main
[STAThread]
static void Main()
{
using (Parrot parrot = new Parrot())
{
parrot.ShowDialog();
}
}
#endregion
}
}