Skip to content

Commit

Permalink
added a document for ASIO recording
Browse files Browse the repository at this point in the history
  • Loading branch information
markheath committed Nov 29, 2017
1 parent ed46645 commit ea942a5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
87 changes: 87 additions & 0 deletions Docs/AsioRecording.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Recording with ASIO

The `AsioOut` class in NAudio allows you to both play back and record audio using an ASIO driver. ASIO is a driver format supported by many popular Digital Audio Workstation (DAW) applications on Windows, and usually offers very low latency for record and playback.

To use ASIO, you do need a soundcard that has an ASIO driver. Most professional soundcards have ASIO drivers, but you can also try the [ASIO4ALL](http://asio4all.com/) driver which enables ASIO for soundcards that don't have their own native ASIO driver.

Often you'll use `AsioOut` to play audio, or to play and record simultaneously. This article covers the scenario where we just want to record audio.

## Opening an ASIO device for recording

To discover the names of the installed ASIO drivers on your system you use `AsioOut.GetDriverNames()`.

We can use one of those driver names to pass to the constructor of `AsioOut`

```c#
var asioOut = new AsioOut(asioDriverName);
```

## Selecting Recording Channels

We may want to find out how many input channels are available on the device. We can get this with:

```c#
var inputChannels = asioOut.DriverInputChannelCount;
```

By default, ASIO will capture all input channels when you record, but if you have a multi-input soundcard, this may be overkill. If you want to select a sub-range of channels to record from, we can set the `InputChannelOffset` to the first channel to record on. And then here I set up a `recordChannelCount` variable which I will use when I start recording. So in this example, I'm recording on channels 4 and 5 (n.b. channel numbers are zero based).

Finally, I call `InitRecordAndPlayback`. This is a little bit ugly and future versions of NAudio may provide a nicer method, but the first parameter supplies the audio to be played. We're just recording, so this is null. The second argument is the number of channels to record (starting from `InputChannelOffset`). And the third argument is the desired sample rate. When we're playing we don;t need this as the sample rate of the input `IWaveProvider` will be used, but since we're just recording, we do need to specify the desired sample rate.

```c#
asioOut.InputChannelOffset = 4;
var recordChannelCount = 2;
var sampleRate = 44100;
asioOut.InitRecordAndPlayback(null, recordChannelCount, sampleRate);
```

## Start Recording

We need to subscribe to the `AudioAvailable` event in order to process audio received in the ASIO buffer callback.

And we kick off recording by calling `Play()`. Yes, again it's not very intuitively named for the scenario in which we're recording only, but it basically tells the ASIO driver to start capturing audio and call us on each buffer swap.

```c#
asioOut.AudioAvailable += OnAsioOutAudioAvailable;
asioOut.Play(); // start recording
```

## Handle received audio

When we receive audio we get access to the raw ASIO buffers in an `AsioAudioAvailableEventArgs` object.

Because ASIO is all about ultimate low latency, NAudio provides direct access to an `IntPtr` array called `InputBuffers` which contains the recorded buffer for each input channel. It also provides a `SamplesPerBuffer` property to tell you how many

But there's still a lot of work to be done. ASIO supports many different recording formats including 24 bit audio where there are 3 bytes per sample. You need to examine the `AsioSampleType` property of the `AsioAudioAvailableEventArgs` to know what format each sample is in.

So it can be a lot of work to access these samples in a meaningful format. NAudio provides a convenience method called `GetAsInterleavedSamples` to read samples from each input channel, turn them into IEEE floating point samples, and interleave them so they could be written to a WAV file. It supports the most common `AsioSampleType` properties, but not all of them.

Note that this example uses an overload of `GetAsInterleavedSamples` that always returns a new `float[]`. It's better for memory purposes to create your own `float[]` up front and pass that in instead.

Here's the simplest handler for `AudioAvailable` that just gets the audio as floating point samples and writes them to a `WaveFileReader` that we've set up in advance.

```c#
void OnAsioOutAudioAvailable(object sender, AsioAudioAvailableEventArgs e)
{
var samples = e.GetAsInterleavedSamples();
writer.WriteSamples(samples, 0, samples.Length);
}
```

For a real application, you'd probably want to write your own logic in here to access the samples and pass them on to whatever processing logic you need.

## Stop Recording

We stop recording by calling Stop().

```c#
asioOut.Stop();
```

As with other NAudio `IWavePlayer` implementations, we'll get a `PlaybackStopped` event firing when the driver stops.

And of course we should remember to `Dispose` our instance of `AsioOut` when we're done with it.

```c#
asioOut.Dispose();
```
1 change: 1 addition & 0 deletions NAudio.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{778D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{BA7F6DBB-9FC4-49E6-92E4-621EFE4BBBBC}"
ProjectSection(SolutionItems) = preProject
Docs\AsioRecording.md = Docs\AsioRecording.md
Docs\ConcatenatingAudio.md = Docs\ConcatenatingAudio.md
Docs\ConvertBetweenStereoAndMono.md = Docs\ConvertBetweenStereoAndMono.md
Docs\ConvertMp3ToWav.md = Docs\ConvertMp3ToWav.md
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ NAudio comes with several demo applications which are the quickest way to see ho
- [Recording a WAV file from a WinForms application](Docs/RecordWavFileWinFormsWaveIn.md)
- [Capturing system audio with WasapiLoopbackCapture](Docs/WasapiLoopbackCapture.md)
- [Play and Record audio at the same time](http://markheath.net/post/how-to-record-and-play-audio-at-same)
- [Record Audio with ASIO](Docs/AsioRecording.md)

### Visualization

Expand Down

0 comments on commit ea942a5

Please sign in to comment.