Blame |
Last modification |
View Log
| RSS feed
#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.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
namespace Examples
{
/// <summary>
/// A text-based diagnosis program for OpenAL.
/// The constructors will call the OpenAL commands, the Print() methods just show the information.
/// </summary>
[Example
("OpenAL diagnostics", ExampleCategory
.OpenAL,
"Test",
0,
true)]
class OpenALDiagnostics
{
public static void checkForErrors
()
{
{
IntPtr device
= Alc
.GetContextsDevice(Alc
.GetCurrentContext());
AlcError error
= Alc
.GetError(device
);
if (error
!= AlcError
.NoError)
Trace
.WriteLine("ALC ERROR: (" + error
+ ") " + Alc
.GetString(device,
(AlcGetString
)error
));
}
{
ALError error
= AL
.GetError();
if (error
!= ALError
.NoError)
Trace
.WriteLine("AL ERROR: (" + error
+ ") " + AL
.GetErrorString(error
));
}
}
[STAThread
]
static void Main
()
{
Trace
.Listeners.RemoveAt(0);
Trace
.Listeners.Add(new ConsoleTraceListener
());
Trace
.WriteLine("This application is currently running as " + (IntPtr
.Size == 4 ? "x86" : "x64"));
DeviceDiagnostic DevDiag
= new DeviceDiagnostic
();
DevDiag
.Print();
DevDiag
= null;
using (AudioContext A
= new AudioContext
())
{
AlcDiagnostic AlcDiag
= new AlcDiagnostic
(Alc
.GetContextsDevice(Alc
.GetCurrentContext()));
checkForErrors
();
AlcDiag
.Print();
AlcDiag
= null;
ALDiagnostic ALdiag
= new ALDiagnostic
(A
);
checkForErrors
();
ALdiag
.Print();
ALdiag
= null;
EfxDiagnostic EfxDiag
= new EfxDiagnostic
();
checkForErrors
();
EfxDiag
.Print();
EfxDiag
= null;
XRamDiagnostic XRamDiag
= new XRamDiagnostic
();
checkForErrors
();
XRamDiag
.Print();
XRamDiag
= null;
RecorderDiagnostic rec
= new RecorderDiagnostic
();
rec
.Print();
rec
= null;
}
// Trace.WriteLine("All done. Press Enter to exit.");
// Console.ReadLine();
}
}
class DeviceDiagnostic
{
#region Fields
public readonly IList
<string> AllPlaybackDevices
;
public readonly IList
<string> AllRecordingDevices
;
public readonly string DefaultPlaybackDevice
;
public readonly string DefaultRecordingDevice
;
#endregion Fields
public DeviceDiagnostic
()
{
Trace
.WriteLine("--- Device related errors ---");
AllPlaybackDevices
= AudioContext
.AvailableDevices;
AllRecordingDevices
= AudioCapture
.AvailableDevices;
DefaultPlaybackDevice
= AudioContext
.DefaultDevice;
DefaultRecordingDevice
= AudioCapture
.DefaultDevice;
}
public void Print
()
{
Trace
.WriteLine("--- Device related analysis ---");
Trace
.Indent();
{
Trace
.WriteLine("Default playback device: " + DefaultPlaybackDevice
);
Trace
.WriteLine("All known playback devices:");
Trace
.Indent();
{
foreach (string s
in AllPlaybackDevices
)
Trace
.WriteLine(s
);
}
Trace
.Unindent();
Trace
.WriteLine("Default recording device: " + DefaultRecordingDevice
);
Trace
.WriteLine("All known recording devices:");
Trace
.Indent();
{
foreach (string s
in AllRecordingDevices
)
Trace
.WriteLine(s
);
}
Trace
.Unindent();
}
Trace
.Unindent();
}
}
class AlcDiagnostic
{
#region Fields
private string[] Alc_Extension_C_Names
= new string[]
{
"ALC_ENUMERATE_ALL_EXT",
"ALC_ENUMERATION_EXT",
"ALC_EXT_ASA",
"ALC_EXT_ASA_DISTORTION",
"ALC_EXT_ASA_ROGER_BEEP",
"ALC_EXT_BRS_GAME_LICENSE_REQUIRED",
"ALC_EXT_capture",
"ALC_EXT_DEDICATED",
"ALC_EXT_EFX",
};
public readonly int MajorVersion
;
public readonly int MinorVersion
;
public readonly int EfxMajorVersion
;
public readonly int EfxMinorVersion
;
public readonly int EfxMaxAuxiliarySends
;
public readonly string ExtensionString
;
public readonly Dictionary
<string,
bool> Extensions
= new Dictionary
<string,
bool>();
#endregion Fields
public AlcDiagnostic
(IntPtr dev
)
{
Trace
.WriteLine("--- Alc related errors ---");
Alc
.GetInteger(dev, AlcGetInteger
.MajorVersion,
1,
out MajorVersion
);
Alc
.GetInteger(dev, AlcGetInteger
.MinorVersion,
1,
out MinorVersion
);
Alc
.GetInteger(dev, AlcGetInteger
.EfxMajorVersion,
1,
out EfxMajorVersion
);
Alc
.GetInteger(dev, AlcGetInteger
.EfxMinorVersion,
1,
out EfxMinorVersion
);
Alc
.GetInteger(dev, AlcGetInteger
.EfxMaxAuxiliarySends,
1,
out EfxMaxAuxiliarySends
);
ExtensionString
= Alc
.GetString(dev, AlcGetString
.Extensions);
foreach (string s
in Alc_Extension_C_Names
)
Extensions
.Add(s, Alc
.IsExtensionPresent(dev, s
));
}
public void Print
()
{
Trace
.WriteLine("--- Alc related analysis ---");
Trace
.Indent();
{
Trace
.WriteLine("Alc Version: " + MajorVersion
+ "." + MinorVersion
);
Trace
.WriteLine("Efx Version: " + EfxMajorVersion
+ "." + EfxMinorVersion
);
Trace
.WriteLine("Efx max. Auxiliary sends: " + EfxMaxAuxiliarySends
);
Trace
.WriteLine("Alc Extension string: " + ExtensionString
);
Trace
.WriteLine("Confirmed Alc Extensions:");
Trace
.Indent();
{
foreach (KeyValuePair
<string,
bool> pair
in Extensions
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
}
Trace
.Unindent();
}
}
class ALDiagnostic
{
#region Fields
private string[] AL_Extension_Names
= new string[]
{
"AL_EXT_ALAW",
"AL_EXT_BFORMAT",
"AL_EXT_double",
"AL_EXT_EXPONENT_DISTANCE",
"AL_EXT_float32",
"AL_EXT_FOLDBACK",
"AL_EXT_IMA4",
"AL_EXT_LINEAR_DISTANCE",
"AL_EXT_MCFORMATS",
"AL_EXT_mp3",
"AL_EXT_MULAW",
"AL_EXT_OFFSET",
"AL_EXT_vorbis",
"AL_LOKI_quadriphonic",
"EAX-RAM",
"EAX",
"EAX1.0",
"EAX2.0",
"EAX3.0",
"EAX3.0EMULATED",
"EAX4.0",
"EAX4.0EMULATED",
"EAX5.0"
};
public readonly Dictionary
<string,
bool> Extensions
= new Dictionary
<string,
bool>();
public readonly string DeviceName
;
public readonly float SpeedOfSound
;
public readonly string ExtensionString
;
public readonly string Renderer
;
public readonly string Vendor
;
public readonly string Version
;
public readonly ALDistanceModel DistanceModel
;
const uint MaxSourcesLimit
= 128;
public readonly uint MaxSources
;
#endregion Fields
public ALDiagnostic
(AudioContext ac
)
{
Trace
.WriteLine("--- AL related errors ---");
DeviceName
= ac
.CurrentDevice;
ExtensionString
= AL
.Get(ALGetString
.Extensions);
Renderer
= AL
.Get(ALGetString
.Renderer);
Vendor
= AL
.Get(ALGetString
.Vendor);
Version
= AL
.Get(ALGetString
.Version);
SpeedOfSound
= AL
.Get(ALGetFloat
.SpeedOfSound);
DistanceModel
= AL
.GetDistanceModel();
foreach (string s
in AL_Extension_Names
)
Extensions
.Add(s, AL
.IsExtensionPresent(s
));
AL
.GetError(); // clear it, need this for the source counting to work properly
uint[] dummy_sources
= new uint[MaxSourcesLimit
];
for (MaxSources
= 0; MaxSources
< MaxSourcesLimit
; MaxSources
++)
{
AL
.GenSource(out dummy_sources
[MaxSources
]);
if (AL
.GetError() != ALError
.NoError)
break;
}
for (int i
= 0; i
< MaxSources
; i
++)
AL
.DeleteSource(ref dummy_sources
[i
]);
}
public void Print
()
{
Trace
.WriteLine("--- AL related analysis ---");
Trace
.Indent();
{
Trace
.WriteLine("Used Device: "+DeviceName
);
Trace
.WriteLine("AL Renderer: " + Renderer
);
Trace
.WriteLine("AL Vendor: " + Vendor
);
Trace
.WriteLine("AL Version: " + Version
);
Trace
.WriteLine("AL Speed of sound: " + SpeedOfSound
);
Trace
.WriteLine("AL Distance Model: " + DistanceModel
.ToString());
Trace
.WriteLine("AL Maximum simultanous Sources: " + MaxSources
);
Trace
.WriteLine("AL Extension string: " + ExtensionString
);
Trace
.WriteLine("Confirmed AL Extensions:");
Trace
.Indent();
{
foreach (KeyValuePair
<string,
bool> pair
in Extensions
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
}
Trace
.Unindent();
}
}
class EfxDiagnostic
{
#region Fields
private EfxEffectType
[] EffectNames
= new EfxEffectType
[]
{
EfxEffectType
.Autowah,
EfxEffectType
.Chorus,
EfxEffectType
.Compressor,
EfxEffectType
.Distortion,
EfxEffectType
.EaxReverb,
EfxEffectType
.Echo,
EfxEffectType
.Equalizer,
EfxEffectType
.Flanger,
EfxEffectType
.FrequencyShifter,
EfxEffectType
.PitchShifter,
EfxEffectType
.Reverb,
EfxEffectType
.RingModulator,
EfxEffectType
.VocalMorpher,
};
private EfxFilterType
[] FilterNames
= new EfxFilterType
[]
{
EfxFilterType
.Bandpass,
EfxFilterType
.Highpass,
EfxFilterType
.Lowpass,
};
public readonly Dictionary
<string,
bool> Effects
= new Dictionary
<string,
bool>();
public readonly Dictionary
<string,
bool> Filters
= new Dictionary
<string,
bool>();
const uint MaxAuxiliaryEffectSlotsLimit
= 4;
public readonly uint MaxAuxiliaryEffectSlots
;
#endregion Fields
public EfxDiagnostic
()
{
Trace
.WriteLine("--- Efx related errors ---");
EffectsExtension Efx
= new EffectsExtension
();
Trace
.Assert(Efx
.IsInitialized);
#region Test for available Effects
uint effect
;
Efx
.GenEffect(out effect
);
AL
.GetError();
foreach (EfxEffectType e
in EffectNames
)
{
Efx
.BindEffect(effect, e
);
Effects
.Add(e
.ToString(), AL
.GetError() == ALError
.NoError);
}
Efx
.DeleteEffect(ref effect
);
#endregion Test for available Effects
#region Test for available Filters
uint filter
;
Efx
.GenFilter(out filter
);
AL
.GetError();
foreach (EfxFilterType f
in FilterNames
)
{
Efx
.Filter(filter, EfxFilteri
.FilterType,
(int)f
);
Filters
.Add(f
.ToString(), AL
.GetError() == ALError
.NoError);
}
Efx
.DeleteFilter(ref filter
);
#endregion Test for available Filters
AL
.GetError();
uint[] dummy_slots
= new uint[MaxAuxiliaryEffectSlotsLimit
];
for (MaxAuxiliaryEffectSlots
= 0; MaxAuxiliaryEffectSlots
< MaxAuxiliaryEffectSlotsLimit
; MaxAuxiliaryEffectSlots
++)
{
Efx
.GenAuxiliaryEffectSlot(out dummy_slots
[MaxAuxiliaryEffectSlots
]);
if (AL
.GetError() != ALError
.NoError)
break;
}
for (uint i
= 0; i
< MaxAuxiliaryEffectSlots
; i
++)
Efx
.DeleteAuxiliaryEffectSlot(ref dummy_slots
[i
]);
}
public void Print
()
{
Trace
.WriteLine("--- Efx related analysis ---");
Trace
.Indent();
{
Trace
.WriteLine("Efx Effects supported:");
Trace
.Indent();
{
foreach (KeyValuePair
<string,
bool> pair
in Effects
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
Trace
.WriteLine("Efx Filters supported:");
Trace
.Indent();
{
foreach (KeyValuePair
<string,
bool> pair
in Filters
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
Trace
.WriteLine("Efx max. Auxiliary Effect Slots: " + MaxAuxiliaryEffectSlots
);
}
Trace
.Unindent();
}
}
class XRamDiagnostic
{
#region Fields
private XRamExtension
.XRamStorage[] storagemodes
= new XRamExtension
.XRamStorage[]
{
XRamExtension
.XRamStorage.Hardware,
XRamExtension
.XRamStorage.Accessible,
XRamExtension
.XRamStorage.Automatic,
};
public readonly bool XRamFound
;
public readonly int RamTotal
;
public readonly int RamFree
;
public readonly Dictionary
<string,
bool> BufferModes
= new Dictionary
<string,
bool>();
#endregion Fields
public XRamDiagnostic
()
{
Trace
.WriteLine("--- X-RAM related errors ---");
XRamExtension XRam
= new XRamExtension
();
if (XRam
.IsInitialized)
{
XRamFound
= true;
RamTotal
= XRam
.GetRamSize;
RamFree
= XRam
.GetRamFree;
uint buffer
;
AL
.GenBuffer(out buffer
);
foreach (XRamExtension
.XRamStorage m
in storagemodes
)
{
bool result
= XRam
.SetBufferMode(1,
ref buffer, m
);
BufferModes
.Add(m
.ToString(), m
== XRam
.GetBufferMode(ref buffer
));
}
AL
.DeleteBuffer(ref buffer
);
}
else
XRamFound
= false;
}
public void Print
()
{
Trace
.WriteLine("--- X-RAM related analysis ---");
if (XRamFound
)
{
Trace
.Indent(); // *
Trace
.WriteLine("X-RAM extension found.");
}
else
{
Trace
.Indent();
{
Trace
.WriteLine("X-RAM extension is not available, skipping test.");
}
Trace
.Unindent();
return;
}
Trace
.WriteLine("Ram status (free/total) in bytes: " + RamFree
+ "/" + RamTotal
);
Trace
.WriteLine("Available buffer modes:");
Trace
.Indent();
{
foreach (KeyValuePair
<string,
bool> pair
in BufferModes
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
Trace
.Unindent(); // *
}
}
class RecorderDiagnostic
{
#region Fields
bool IsDeviceAvailable
;
bool BufferContentsAllZero
;
short MaxSample
= short.MinValue;
short MinSample
= short.MaxValue;
private AudioCapture r
;
Dictionary
<string, AlcError
> Errorlist
= new Dictionary
<string, AlcError
>();
string DeviceName
;
#endregion Fields
private void CheckRecorderError
(string location
)
{
AlcError err
= r
.CurrentError;
if (err
!= AlcError
.NoError)
Errorlist
.Add(location, err
);
}
public RecorderDiagnostic
()
{
Trace
.WriteLine("--- AudioCapture related errors ---");
IsDeviceAvailable
= false;
try
{
r
= new AudioCapture
(AudioCapture
.DefaultDevice,
16000, ALFormat
.Mono16,
4096);
}
catch (AudioDeviceException ade
)
{
Trace
.WriteLine("AudioCapture Exception caught: " + ade
.Message);
return;
}
IsDeviceAvailable
= true;
DeviceName
= r
.CurrentDevice;
CheckRecorderError
("Alc.CaptureOpenDevice");
r
.Start();
CheckRecorderError
("Alc.CaptureStart");
Thread
.Sleep(100);
r
.Stop();
CheckRecorderError
("Alc.CaptureStop");
byte[] Buffer
= new byte[8192];
Thread
.Sleep(10); // Wait for a few samples to become available.
int SamplesBefore
= r
.AvailableSamples;
CheckRecorderError
("Alc.GetInteger(...CaptureSamples...)");
r
.ReadSamples(Buffer,
(SamplesBefore
> 4096 ? 4096 : SamplesBefore
));
CheckRecorderError
("Alc.CaptureSamples");
int SamplesCaptured
= SamplesBefore
- r
.AvailableSamples;
uint ZeroCounter
= 0;
for (int i
= 0; i
< SamplesCaptured
* 2; i
++)
{
if (Buffer
[i
] == 0)
ZeroCounter
++;
}
for (int i
= 0; i
< SamplesCaptured
; i
++)
{
short sample
= BitConverter
.ToInt16(Buffer, i
* 2);
if (sample
> MaxSample
)
MaxSample
= sample
;
if (sample
< MinSample
)
MinSample
= sample
;
}
if (ZeroCounter
< SamplesCaptured
* 2 && SamplesCaptured
> 0)
BufferContentsAllZero
= false;
else
BufferContentsAllZero
= true;
r
.Dispose();
CheckRecorderError
("Alc.CaptureCloseDevice");
// no playback test needed due to Parrot test app.
/*
uint buf;
AL.GenBuffer(out buf);
AL.BufferData(buf, ALFormat.Mono16, BufferPtr, SamplesCaptured * 2, 16000);
uint src;
AL.GenSource(out src);
AL.BindBufferToSource(src, buf);
AL.Listener(ALListenerf.Gain, 16.0f);
AL.SourcePlay(src);
while (AL.GetSourceState(src) == ALSourceState.Playing)
{
Thread.Sleep(0);
}
AL.SourceStop(src);
AL.DeleteSource(ref src);
AL.DeleteBuffer(ref buf);
*/
}
public void Print
()
{
Trace
.WriteLine("--- AudioCapture related analysis ---");
if (!IsDeviceAvailable
)
{
Trace
.WriteLine("Capture Device could not be initlialized (no microphone plugged into the jack?). Skipping test.");
return;
}
Trace
.Indent();
{
Trace
.WriteLine("Using capture device: " + DeviceName
);
if (Errorlist
.Count > 0)
{
Trace
.WriteLine("Found Alc Errors:");
Trace
.Indent();
{
foreach (KeyValuePair
<string, AlcError
> pair
in Errorlist
)
Trace
.WriteLine(pair
.Key + ": " + pair
.Value);
}
Trace
.Unindent();
}
Trace
.WriteLine("Buffer contents after capture was all 0's: " + BufferContentsAllZero
);
Trace
.WriteLine("Sample min/max in recorded data: " + MinSample
+ " / " + MaxSample
);
}
Trace
.Unindent();
}
}
}