はじめに
C#(.NET)のライブラリで、NAudioという有名ライブラリがあります。NuGetの情報で見てみると、626,000回もダウンロードされているので信頼性はあるのかなと思います。今回はこのライブラリを使って録音をする処理を書いてみましたのでご紹介いたします。
ソースコード
以下ソースコードの全文になります、btnStart_Click イベントで録画の開始を行い、btnStop_Clickイベントで録画終了となります。
using NAudio.Wave;
using NAudio.Codecs;
using NAudio.CoreAudioApi;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NAudioTest
{
public partial class Form1 : Form
{
WaveInEvent waveIn;
WaveFileWriter waveWriter;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
// 録音デバイスを選びたい場合は、WaveInEvent.DeviceCount、WaveInEvent.GetCapabilities を使って探してください。
var deviceNumber = 0;
// 録画処理を開始
// WaveIn だと、「System.InvalidOperationException: 'Use WaveInEvent to record on a background thread'」のエラーが発生する
// waveIn = new WaveIn();
waveIn = new WaveInEvent();
waveIn.DeviceNumber = deviceNumber;
waveIn.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(deviceNumber).Channels);
waveWriter = new WaveFileWriter("C:\\temp\\test1.wav", waveIn.WaveFormat);
waveIn.DataAvailable += (_, ee) =>
{
waveWriter.Write(ee.Buffer, 0, ee.BytesRecorded);
waveWriter.Flush();
};
waveIn.RecordingStopped += (_, __) =>
{
waveWriter.Flush();
};
waveIn.StartRecording();
}
private void btnStop_Click(object sender, EventArgs e)
{
waveIn?.StopRecording();
waveIn?.Dispose();
waveIn = null;
waveWriter?.Close();
waveWriter = null;
}
}
}
トラブルシューティング
エラー1
メインスレッド以外で実行すると、「System.InvalidOperationException: ‘Use WaveInEvent to record on a background thread’」のエラーが表示される。
WaveIn ではなく WaveInEvent を使用しましょう!
MP3で録音したい
NAudio.Lameを使いましょう、ぱっと見ではありますが WaveFileWriter と同じインターフェースで書き出しが行るっぽいので差し替えだけでいけると思います。
指定したデバイスで録音したい
以下のように、deviceNumber を書き換える処理を追加する、以下ではデバイス名に特定の文字が含まれるデバイスを選択している。
int deviceNumber = -1;
for(int i = 0; i < WaveIn.DeviceCount; i++)
{
var cap = WaveIn.GetCapabilities(i);
if (cap.ProductName.Contains(デバイス名をここに指定))
deviceNumber = i;
}