Click here to Skip to main content
15,897,371 members
Articles / Programming Languages / C#

Low Latency Audio using ASIO Drivers in .NET

Rate me:
Please Sign up or sign in to vote.
4.87/5 (30 votes)
7 May 2008CPOL10 min read 564.4K   10.4K   104  
Demonstrates access to your sound hardware with ASIO drivers
//
// BlueWave.Interop.Asio by Rob Philpott. Please send all bugs/enhancements to
// rob@bigdevelopments.co.uk.  This file and the code contained within is freeware and may be
// distributed and edited without restriction. You may be bound by licencing restrictions
// imposed by Steinberg - check with them prior to distributing anything.
// 

#pragma once
#pragma managed
using namespace System;

#include "AsioRedirect.h"

namespace BlueWave
{
	namespace Interop
	{
		namespace Asio
		{
				// represents an ASIO driver (also some static for all drivers)
				public ref class AsioDriver
				{
				internal:

					// we'll maintain a list of drivers
					static array<InstalledDriver^>^ _installedDrivers;

					// but you can only have one active at once
					static AsioDriver^ _instance;

					// our elusive COM interface
					IAsio* _pDriver;

					// a struct which specifies callback addresses
					ASIOCallbacks* _pCallbacks;

					// the number of input channels supported by the driver, and our max
					int _nInputs;

					// and the number of output channels
					int _nOutputs;

					// is it usefull to call outputReady each time we have updated the outputbuffers 
					ASIOError _outputReadySupport;

					// the static callback methods - we'll forward these to instance members
					static void OnSampleRateDidChange(ASIOSampleRate rate);
					static long OnAsioMessage(long selector, long value, void* message, double* opt);

					// select a driver once an instance of this class has been created
					void InternalSelectDriver(InstalledDriver^ installedDriver);

					// our instance based handlers
					void OnBufferSwitch(long doubleBufferIndex, ASIOBool directProcess);
					ASIOTime* OnBufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);

					// safety function to make sure all is well before attempting any operations
					void CheckInitialised();

					// the input channels
					array<Channel^>^ _inputChannels;

					// the output channels
					array<Channel^>^ _outputChannels;

					// C++ likes 'non-trivial' events
					EventHandler^ _bufferUpdateEvent;

					// return the instance of currently selected driver
					static property AsioDriver^ Instance { AsioDriver^ get(); }

				public:

					// returns the installed drivers
					static property array<InstalledDriver^>^ InstalledDrivers	{ array<InstalledDriver^>^ get(); }

					// select and initialise driver
					static AsioDriver^ SelectDriver(InstalledDriver^ installedDriver);

					// basic information properties
					property int					Version					{ int get(); }
					property String^				DriverName				{ String^ get(); }
					property String^				ErrorMessage			{ String^ get(); }
					property int					NumberInputChannels		{ int get(); }
					property int					NumberOutputChannels	{ int get(); }
					property BufferSize^			BufferSizex				{ BufferSize^ get(); }
					property double					SampleRate				{ double get();}
					property array<Channel^>^		InputChannels			{ array<Channel^>^ get(); }
					property array<Channel^>^		OutputChannels			{ array<Channel^>^ get(); }

					// basic methods
					void Start();
					void Stop();
					void ShowControlPanel();
					void CreateBuffers(bool useMaxBufferSize);
					void DisposeBuffers();
					void Release();
					void SetSampleRate(double rate);

					// and the buffer update event - bit strange the way this works in c++
					event EventHandler^ BufferUpdate
					{
						void add(EventHandler^ e) { _bufferUpdateEvent += e; }
						void remove(EventHandler^ e) { _bufferUpdateEvent -= e; }
					}
				};
			}
		}
	}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United Kingdom United Kingdom
I am a .NET architect/developer based in London working mostly on financial trading systems. My love of computers started at an early age with BASIC on a 3KB VIC20 and progressed onto a 32KB BBC Micro using BASIC and 6502 assembly language. From there I moved on to the blisteringly fast Acorn Archimedes using BASIC and ARM assembly.

I started developing with C++ since 1990, where it was introduced to me in my first year studying for a Computer Science degree at the University of Nottingham. I started professionally with Visual C++ version 1.51 in 1993.

I moved over to C# and .NET in early 2004 after a long period of denial that anything could improve upon C++.

Recently I did a bit of work in my old language of C++ and I now realise that frankly, it's a total pain in the arse.

Comments and Discussions