Just a snippet of code to share – I hadn’t tried to record from the system’s microphone before with Windows 10/UWP and I wanted to record PCM into a file so I had to spend 20 minutes trying to figure it out.
This sample was incredibly helpful and I stripped it down for my purposes to having a UI with a Start and a Stop button wired to these handlers below and that seemed to work in letting me record mono, 16K PCM, mono file with 16-bits per sample into a file on my desktop.
using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.Devices.Enumeration; using Windows.Media.Audio; using Windows.Media.Capture; using Windows.Media.Devices; using Windows.Media.MediaProperties; using Windows.Media.Render; using Windows.Storage; using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } async void OnStart(object sender, RoutedEventArgs e) { var file = await this.PickFileAsync(); if (file != null) { var result = await AudioGraph.CreateAsync( new AudioGraphSettings(AudioRenderCategory.Speech)); if (result.Status == AudioGraphCreationStatus.Success) { this.graph = result.Graph; var microphone = await DeviceInformation.CreateFromIdAsync( MediaDevice.GetDefaultAudioCaptureId(AudioDeviceRole.Default)); // In my scenario I want 16K sampled, mono, 16-bit output var outProfile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low); outProfile.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16); var outputResult = await this.graph.CreateFileOutputNodeAsync(file, outProfile); if (outputResult.Status == AudioFileNodeCreationStatus.Success) { this.outputNode = outputResult.FileOutputNode; var inProfile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.High); var inputResult = await this.graph.CreateDeviceInputNodeAsync( MediaCategory.Speech, inProfile.Audio, microphone); if (inputResult.Status == AudioDeviceNodeCreationStatus.Success) { inputResult.DeviceInputNode.AddOutgoingConnection( this.outputNode); this.graph.Start(); } } } } } async void OnStop(object sender, RoutedEventArgs e) { if (this.graph != null) { this.graph?.Stop(); await this.outputNode.FinalizeAsync(); // assuming that disposing the graph gets rid of the input/output nodes? this.graph?.Dispose(); this.graph = null; } } async Task<StorageFile> PickFileAsync() { FileSavePicker picker = new FileSavePicker(); picker.FileTypeChoices.Add("Wave File (PCM)", new List<string> { ".wav" }); picker.SuggestedStartLocation = PickerLocationId.Desktop; var file = await picker.PickSaveFileAsync(); return (file); } AudioGraph graph; AudioFileOutputNode outputNode; }
it’s clearly quite a rough bit of code – all mistakes are mine and I hadn’t tried out AudioGraph before.
Pingback: “Project Oxford”–Speaker Verification from a Windows 10/UWP App – Mike Taulty
It doesn’t work for me. It creates the file on the correct place but 0 bytes, without any audio in it.
Nvm, manifest issue.
Thanks for these – I am enjoying trying out all the new stuff. Your posts are just enough to get started and that helps a lot.
Just tried this and this statement:
inputResult.DeviceInputNode.AddOutgoingConnection(this.outputNode);
seems to be giving it fits. This error:
$exception {“Exception from HRESULT: 0x88960001”} System.Exception
Did you run across this? The manifest is set to Microphone and a cursory inspection seems like everything is working fine.
TIA…
Hi,
I did find that some combinations of input and output seemed to throw fairly esoteric exceptions for me (fortunately, not the one that I actually wanted). Maybe try tweaking a parameter or two?
Mike.
Hi,
Sorry that this is so much later than when you asked the question. I hit the exact same error with that code today by running it on a different machine and then scratching my head over what was happening.
I suspect that I was being too specific about the input end of the equation here because I don’t really care where the input comes from – my main concern is around getting a particular format of audio out (PCM, 16Kbps, mono, 16-bit).
I revised my code to look like this…
var result = await AudioGraph.CreateAsync(
new AudioGraphSettings(AudioRenderCategory.Media));
if (result.Status == AudioGraphCreationStatus.Success)
{
this.graph = result.Graph;
// Low gives us 1 channel, 16-bits per sample, 16K sample rate.
var outProfile = MediaEncodingProfile.CreateWav(AudioEncodingQuality.Low);
outProfile.Audio = AudioEncodingProperties.CreatePcm(16000, 1, 16);
// I want to write to a file.
var outputResult = await this.graph.CreateFileOutputNodeAsync(
this.RecordingFile,
outProfile);
if (outputResult.Status == AudioFileNodeCreationStatus.Success)
{
this.outputNode = outputResult.FileOutputNode;
// I'll take input from whatever the default communications
// device is set to me on windows.
var inputResult = await this.graph.CreateDeviceInputNodeAsync(
MediaCategory.Communications);
if (inputResult.Status == AudioDeviceNodeCreationStatus.Success)
{
// Now wire the input to the output
inputResult.DeviceInputNode.AddOutgoingConnection(
this.outputNode);
this.graph.Start();
}
}
}
I hope that helps a little, it helped me get past that exception.
Mike
GetDefaultAudioCaptureId
Applies to: Windows Phone 8 and Windows Phone Silverlight 8.1 only