正如标题所示,我希望在.NET Core中捕捉麦克风的音频。对我来说,跨平台很重要。我已经在Windows、Linux和OSX上的OpenCV中做了很多视频处理。音频是我拼图中缺失的一块。
vhipe2zx1#
NETCore是一个非常好的OpenTK跨平台端口。使用它的AudioCapture类,我已经能够捕捉跨不同操作系统平台的麦克风数据。
AudioCapture
using (var audioCapture = new AudioCapture(_recorders.First(), _sampling_rate, ALFormat.Mono16, buffer_length_samples)) { audioCapture.Start(); int available_samples = audioCapture.AvailableSamples; _buffer = _pool.Rent(MathHelper.NextPowerOfTwo((int)((available_samples * _sampleToByte / (double)BlittableValueType.StrideOf(_buffer)) + 0.5))); if (available_samples > 0) { audioCapture.ReadSamples(_buffer, available_samples); } else { _pool.Return(_buffer); } }
编辑:基于OpenTK示例中的Parrot项目。
Parrot
iqih9akk2#
不幸的是,我不知道有什么API或库可以为您做到这一点。如果别人也不知道,那么你有两个选择:1.自己编写一个跨平台API(看看CoreFx或CoreFxLab repos),在Windows上,您可能使用P/Invoke来使用系统DLL,在其他平台上,您需要其他东西1.获取一个跨平台的记录器可执行文件,并从您的.net核心功能中与之接口
pkwftd7m3#
我以前在.NET核心上写过一个录音机应用程序,但它不再是我的财产了......然而,这里有我在工作时使用的the library。LibsoundIO Sharp能够将配置扩展到输入或输出的采样率等方面,并提供了如下示例:
class Record { static SoundIORingBuffer ring_buffer = null; static SoundIOFormat [] prioritized_formats = { SoundIODevice.Float32NE, SoundIODevice.Float32FE, SoundIODevice.S32NE, SoundIODevice.S32FE, SoundIODevice.S24NE, SoundIODevice.S24FE, SoundIODevice.S16NE, SoundIODevice.S16FE, SoundIODevice.Float64NE, SoundIODevice.Float64FE, SoundIODevice.U32NE, SoundIODevice.U32FE, SoundIODevice.U24NE, SoundIODevice.U24FE, SoundIODevice.U16NE, SoundIODevice.U16FE, SoundIOFormat.S8, SoundIOFormat.U8, SoundIOFormat.Invalid, }; static readonly int [] prioritized_sample_rates = { 48000, 44100, 96000, 24000, 0, }; public static int Main (string [] args) { string device_id = null; string backend_name = null; bool raw = false; string outfile = null; foreach (var arg in args) { switch (arg) { case "--raw": raw = true; continue; default: if (arg.StartsWith ("--backend:")) backend_name = arg.Substring (arg.IndexOf (':') + 1); else if (arg.StartsWith ("--device:")) device_id = arg.Substring (arg.IndexOf (':') + 1); else outfile = arg; continue; } } var api = new SoundIO (); var backend = backend_name == null ? SoundIOBackend.None : (SoundIOBackend)Enum.Parse (typeof (SoundIOBackend), backend_name); if (backend == SoundIOBackend.None) api.Connect (); else api.ConnectBackend (backend); Console.WriteLine ("backend: " + api.CurrentBackend); api.FlushEvents (); var device = device_id == null ? api.GetInputDevice (api.DefaultInputDeviceIndex) : Enumerable.Range (0, api.InputDeviceCount) .Select (i => api.GetInputDevice (i)) .FirstOrDefault (d => d.Id == device_id && d.IsRaw == raw); if (device == null) { Console.Error.WriteLine ("device " + device_id + " not found."); return 1; } Console.WriteLine ("device: " + device.Name); if (device.ProbeError != 0) { Console.Error.WriteLine ("Cannot probe device " + device_id + "."); return 1; } var sample_rate = prioritized_sample_rates.First (sr => device.SupportsSampleRate (sr)); var fmt = prioritized_formats.First (f => device.SupportsFormat (f)); var instream = device.CreateInStream (); instream.Format = fmt; instream.SampleRate = sample_rate; instream.ReadCallback = (fmin, fmax) => read_callback (instream, fmin, fmax); instream.OverflowCallback = () => overflow_callback (instream); instream.Open (); const int ring_buffer_duration_seconds = 30; int capacity = (int)(ring_buffer_duration_seconds * instream.SampleRate * instream.BytesPerFrame); ring_buffer = api.CreateRingBuffer (capacity); var buf = ring_buffer.WritePointer; instream.Start (); Console.WriteLine ("Type CTRL+C to quit by killing process..."); using (var fs = File.OpenWrite (outfile)) { var arr = new byte [capacity]; unsafe { fixed (void* arrptr = arr) { for (; ; ) { api.FlushEvents (); Thread.Sleep (1000); int fill_bytes = ring_buffer.FillCount; var read_buf = ring_buffer.ReadPointer; Buffer.MemoryCopy ((void*)read_buf, arrptr, fill_bytes, fill_bytes); fs.Write (arr, 0, fill_bytes); ring_buffer.AdvanceReadPointer (fill_bytes); } } } } instream.Dispose (); device.RemoveReference (); api.Dispose (); return 0; } static void read_callback (SoundIOInStream instream, int frame_count_min, int frame_count_max) { var write_ptr = ring_buffer.WritePointer; int free_bytes = ring_buffer.FreeCount; int free_count = free_bytes / instream.BytesPerFrame; if (frame_count_min > free_count) throw new InvalidOperationException ("ring buffer overflow"); // panic() int write_frames = Math.Min (free_count, frame_count_max); int frames_left = write_frames; for (; ; ) { int frame_count = frames_left; var areas = instream.BeginRead (ref frame_count); if (frame_count == 0) break; if (areas.IsEmpty) { // Due to an overflow there is a hole. Fill the ring buffer with // silence for the size of the hole. for (int i = 0; i < frame_count * instream.BytesPerFrame; i++) Marshal.WriteByte (write_ptr + i, 0); Console.Error.WriteLine ("Dropped {0} frames due to internal overflow", frame_count); } else { for (int frame = 0; frame < frame_count; frame += 1) { int chCount = instream.Layout.ChannelCount; int copySize = instream.BytesPerSample; unsafe { for (int ch = 0; ch < chCount; ch += 1) { var area = areas.GetArea (ch); Buffer.MemoryCopy ((void*)area.Pointer, (void*)write_ptr, copySize, copySize); area.Pointer += area.Step; write_ptr += copySize; } } } } instream.EndRead (); frames_left -= frame_count; if (frames_left <= 0) break; } int advance_bytes = write_frames * instream.BytesPerFrame; ring_buffer.AdvanceWritePointer (advance_bytes); } static int overflow_callback_count = 0; static void overflow_callback (SoundIOInStream instream) { Console.Error.WriteLine ("overflow {0}", overflow_callback_count++); } }
Adapted from sio-record/Program.cs就.NET核心而言,您可以将其作为独立项目留在单例类中,或者如果您正在处理一个具有DI容器的项目,只需将其作为单例放入即可。话虽如此,您需要libsoundio来使事情工作,因为毕竟,它就像音频和libsoundio的“java”一样,sharp是C#的 Package 器。
0s0u357o4#
我编写了一个简单的程序,使用OpenTK.OpenAL nuGet-package打印当前音量。
using OpenTK.Audio.OpenAL; using System; Console.WriteLine("Default Mic:\n"+ ALC.GetString(ALDevice.Null, AlcGetString.CaptureDefaultDeviceSpecifier)); Console.WriteLine("Mic List:\n"+ string.Join("\n", ALC.GetString(ALDevice.Null, AlcGetStringList.CaptureDeviceSpecifier))); int bufferLength = 10 * 16000;//10 sec ALCaptureDevice mic= ALC.CaptureOpenDevice(null,16000,ALFormat.Mono8, bufferLength);//opens default mic //null specifies default Console.WriteLine("Using:"); Console.WriteLine(ALC.GetString(new ALDevice(mic.Handle), AlcGetString.DeviceSpecifier)); ALC.CaptureStart(mic); byte[] buffer = new byte[bufferLength]; for (int i = 0; i < 1000; ++i) { Thread.Sleep(100); int samplesAvailable = ALC.GetAvailableSamples(mic); ALC.CaptureSamples(mic, buffer, samplesAvailable); if(samplesAvailable>0) //Console.WriteLine(new string('|', (buffer[..samplesAvailable].Max())*80/256 )); Console.WriteLine(new string('|', (buffer[..samplesAvailable].Select(x => Math.Abs((int)(x)-128)).Max()) * 80/ 128)); } ALC.CaptureStop(mic); ALC.CaptureCloseDevice(mic);
4条答案
按热度按时间vhipe2zx1#
NETCore是一个非常好的OpenTK跨平台端口。
使用它的
AudioCapture
类,我已经能够捕捉跨不同操作系统平台的麦克风数据。编辑:基于OpenTK示例中的
Parrot
项目。iqih9akk2#
不幸的是,我不知道有什么API或库可以为您做到这一点。
如果别人也不知道,那么你有两个选择:
1.自己编写一个跨平台API(看看CoreFx或CoreFxLab repos),在Windows上,您可能使用P/Invoke来使用系统DLL,在其他平台上,您需要其他东西
1.获取一个跨平台的记录器可执行文件,并从您的.net核心功能中与之接口
pkwftd7m3#
我以前在.NET核心上写过一个录音机应用程序,但它不再是我的财产了......然而,这里有我在工作时使用的the library。
LibsoundIO Sharp能够将配置扩展到输入或输出的采样率等方面,并提供了如下示例:
Adapted from sio-record/Program.cs
就.NET核心而言,您可以将其作为独立项目留在单例类中,或者如果您正在处理一个具有DI容器的项目,只需将其作为单例放入即可。
话虽如此,您需要libsoundio来使事情工作,因为毕竟,它就像音频和libsoundio的“java”一样,sharp是C#的 Package 器。
0s0u357o4#
我编写了一个简单的程序,使用OpenTK.OpenAL nuGet-package打印当前音量。