---
title: "Record from the microphone"
url: https://recursiveai.org/oneaudio/cookbook/record-microphone/
description: "Record audio from the default microphone in C# and save it as a 16-bit WAV file, with the RecursiveAI.OneAudio.Devices package and oneaudio’s WAV encoder."
version: "1.2.1"
---

# Record from the microphone

Record audio from the default microphone in C# and save it as a 16-bit WAV file, with the `RecursiveAI.OneAudio.Devices` package and oneaudio’s WAV encoder.

```sh
dotnet add package RecursiveAI.OneAudio --version 1.2.1
dotnet add package RecursiveAI.OneAudio.Devices --version 1.2.1
```

```csharp
using OneAudio;
using OneAudio.Devices;

// Record three seconds from the default input, 48 kHz mono, into a WAV file.
var options = new DeviceStreamOptions { SampleRate = 48000, Channels = 1 };
var format = new AudioFormat(48000, 1);
const long total = 3 * 48000L;

using var input = Audio.CreateInput(options);   // opens and starts the device
var settings = new WavEncoderSettings { SampleType = NativeSampleType.PcmSigned16 };
using (var wav = new WavEncoder(File.Create("take.wav"), format, settings,
                                leaveOpen: false))
{
    float[] block = new float[4800];            // 100 ms
    long written = 0;
    var timeout = DateTime.UtcNow.AddSeconds(8);
    while (written < total && DateTime.UtcNow < timeout)
    {
        int read = input.Read(block);           // frames; 0 when nothing waits
        if (read == 0) { Thread.Sleep(20); continue; }
        int keep = (int)Math.Min(read, total - written);
        wav.Write(block.AsSpan(0, keep));
        written += keep;
    }
}   // Dispose finishes the file

Console.WriteLine($"{input.BackendName}: {input.Device?.Id ?? "no device"}, " +
                  $"{input.State}, overruns {input.Counters.Overruns}");
using IAudioDecoder check = Audio.Open("take.wav");
AudioFormat f = check.Format;
Console.WriteLine($"take.wav: {f.SampleRate} Hz, {f.Channels} ch, " +
                  $"{check.LengthFrames / (double)f.SampleRate:F2} s, " +
                  $"{new FileInfo("take.wav").Length:N0} bytes");
```

```text
alsa: default, Running, overruns 0
take.wav: 48000 Hz, 1 ch, 3.00 s, 288,080 bytes
```

This ran on Linux, through ALSA’s `default` capture device to PipeWire, recording from a USB webcam microphone.

- `Audio.CreateInput(options)` opens the default input and starts it. Audio arrives as 32-bit floats at the rate and channel count you ask for, converted from whatever the hardware runs at.
- `Read` copies whatever has arrived, in whole frames, and returns 0 when nothing is waiting. It never blocks, so the loop sleeps briefly between reads.
- Captured audio waits in a buffer of `CaptureBufferMilliseconds` (1,000 by default). If you don’t read for longer than that, new audio is dropped and counted in `Overruns`.
- `WavEncoderSettings.SampleType` picks the stored type. The 288,080 bytes are 3 seconds of 16-bit mono at 48 kHz plus the header.
- To process audio as it arrives instead, pass a `CaptureCallback` to `Audio.CreateInput`. It runs on the device thread, so it must not allocate, lock or block.

On macOS and iOS, the program needs microphone permission. On iOS, set `DeviceStreamOptions.AppleSession` to `PlayAndRecord` and give the app a microphone usage description. On Windows, the microphone privacy setting has to allow desktop apps. A refused open says so in `LastError`.

A longer walk-through with a live level meter: [Record audio in C#](https://recursiveai.org/oneaudio/articles/record-audio-csharp/).
