台式机(无内置麦克风)无法选择并启用语音输入的解决方法
Hey there! Let's work through this microphone selection issue you're having with your C# voice recording program. I’ve got practical solutions for both C# (yes, it’s totally doable!) and C++ to help you get your program running on desktops without built-in mics.
C# Solutions: Enumerate and Select Microphones
You mentioned thinking C# might be tricky, but there are straightforward ways to handle this—either with a trusted third-party library or direct Windows API calls.
Option 1: Use NAudio (Simplest, Most Popular Approach)
NAudio is a widely used .NET library for audio processing that makes enumerating and selecting input devices a breeze.
First, install the NAudio package via NuGet (search for NAudio in your package manager). Then use this code to list and select microphones:
using NAudio.Wave; // Step 1: List all available input microphones var deviceCount = WaveIn.DeviceCount; for (int i = 0; i < deviceCount; i++) { var deviceInfo = WaveIn.GetCapabilities(i); Console.WriteLine($"Device {i}: {deviceInfo.ProductName}"); } // Step 2: Select a device and start recording (example uses index 0) WaveIn waveIn = new WaveIn(); waveIn.DeviceNumber = 0; // Set this to the index the user selects waveIn.WaveFormat = new WaveFormat(44100, 1); // 44.1kHz, mono audio // Handle incoming audio data waveIn.DataAvailable += (sender, e) => { // Replace this with your analysis or file-writing logic using (var writer = new WaveFileWriter("recording.wav", waveIn.WaveFormat)) { writer.Write(e.Buffer, 0, e.BytesRecorded); } }; waveIn.StartRecording();
Don’t forget to clean up resources when you’re done: call waveIn.StopRecording() and waveIn.Dispose() to avoid memory leaks.
Option 2: Windows Core Audio API (No Third-Party Libraries)
If you want to avoid external dependencies, you can directly interface with Windows’ Core Audio API via COM interop. This is more verbose but gives you full control:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; [ComImport] [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] internal class MMDeviceEnumerator { } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDeviceEnumerator { int EnumAudioEndpoints(EDataFlow dataFlow, DEVICE_STATE dwStateMask, out IMMDeviceCollection ppDevices); } [Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDeviceCollection { int GetCount(out uint pcDevices); int Item(uint nDevice, out IMMDevice ppDevice); } [Guid("D666063F-1587-4E43-81F1-B948E807363F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IMMDevice { int GetId([MarshalAs(UnmanagedType.LPWStr)] out string ppstrId); int GetState(out uint pdwState); } internal enum EDataFlow { eRender, eCapture, eAll } internal enum DEVICE_STATE { ACTIVE = 0x00000001, ALL = 0x0000000F } public static List<string> GetActiveMicrophones() { var microphones = new List<string>(); var enumerator = new MMDeviceEnumerator() as IMMDeviceEnumerator; enumerator.EnumAudioEndpoints(EDataFlow.eCapture, DEVICE_STATE.ACTIVE, out var deviceCollection); deviceCollection.GetCount(out uint count); for (uint i = 0; i < count; i++) { deviceCollection.Item(i, out var device); device.GetId(out var deviceId); microphones.Add(deviceId); Marshal.ReleaseComObject(device); } Marshal.ReleaseComObject(deviceCollection); Marshal.ReleaseComObject(enumerator); return microphones; }
Once you have the device IDs, you can extend this code to get friendly device names and connect to the audio capture pipeline for recording.
C++ Solutions: Direct Windows API Calls
If you’d rather use C++, you can leverage Windows’ native multimedia APIs for full low-level control.
Enumerate Microphones with the waveIn API
This uses the classic Windows Multimedia API to list and select microphones:
#include <windows.h> #include <mmsystem.h> #include <iostream> #include <vector> #pragma comment(lib, "winmm.lib") // Get list of all active microphones std::vector<WAVEINCAPS> GetMicrophoneList() { std::vector<WAVEINCAPS> microphones; UINT deviceCount = waveInGetNumDevs(); for (UINT i = 0; i < deviceCount; i++) { WAVEINCAPS caps; if (waveInGetDevCaps(i, &caps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) { microphones.push_back(caps); std::wcout << L"Device " << i << L": " << caps.szPname << std::endl; } } return microphones; } // Callback to handle incoming audio data void CALLBACK WaveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { if (uMsg == WIM_DATA) { WAVEHDR* pHeader = reinterpret_cast<WAVEHDR*>(dwParam1); // Add your audio analysis or file-writing logic here waveInAddBuffer(hWaveIn, pHeader, sizeof(WAVEHDR)); } } // Start recording from a selected device void StartRecording(UINT deviceId) { HWAVEIN hWaveIn; WAVEFORMATEX wfx{}; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = 44100; wfx.wBitsPerSample = 16; wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample) / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; MMRESULT result = waveInOpen(&hWaveIn, deviceId, &wfx, (DWORD_PTR)WaveInProc, 0, CALLBACK_FUNCTION); if (result == MMSYSERR_NOERROR) { // Initialize and add audio buffers here waveInStart(hWaveIn); } }
Key Tips for Success
- Always check microphone permissions: On Windows 10/11, your app needs explicit permission to access microphones. Make sure this is enabled in System Settings > Privacy & Security > Microphone.
- Let users select a device: Instead of hardcoding a device index, display the list of available microphones and let the user pick one—this avoids issues if devices are added/removed.
- Clean up resources: Always release handles and dispose objects when you’re done recording to prevent memory leaks.
内容的提问来源于stack exchange,提问作者David Machitidze

