static SoundIoFormats() { if (BitConverter.IsLittleEndian) { S16NE = SoundIoFormat.S16LE; U16NE = SoundIoFormat.U16LE; S24NE = SoundIoFormat.S24LE; U24NE = SoundIoFormat.U24LE; S32NE = SoundIoFormat.S32LE; U32NE = SoundIoFormat.U32LE; Float32NE = SoundIoFormat.Float32LE; Float64NE = SoundIoFormat.Float64LE; S16FE = SoundIoFormat.S16BE; U16FE = SoundIoFormat.U16BE; S24FE = SoundIoFormat.S24BE; U24FE = SoundIoFormat.U24BE; S32FE = SoundIoFormat.S32BE; U32FE = SoundIoFormat.U32BE; Float32FE = SoundIoFormat.Float32BE; Float64FE = SoundIoFormat.Float64BE; } else { S16NE = SoundIoFormat.S16BE; U16NE = SoundIoFormat.U16BE; S24NE = SoundIoFormat.S24BE; U24NE = SoundIoFormat.U24BE; S32NE = SoundIoFormat.S32BE; U32NE = SoundIoFormat.U32BE; Float32NE = SoundIoFormat.Float32BE; Float64NE = SoundIoFormat.Float64BE; S16FE = SoundIoFormat.S16LE; U16FE = SoundIoFormat.U16LE; S24FE = SoundIoFormat.S24LE; U24FE = SoundIoFormat.U24LE; S32FE = SoundIoFormat.S32LE; U32FE = SoundIoFormat.U32LE; Float32FE = SoundIoFormat.Float32LE; Float64FE = SoundIoFormat.Float64LE; } }
internal static extern bool SoundIoDeviceSupportsFormat( [In] IntPtr device, [In] SoundIoFormat format );
internal static extern IntPtr SoundIoFormatString( [In] SoundIoFormat format );
internal static extern int SoundIoGetBytesPerSample( [In] SoundIoFormat format );
internal static extern bool soundio_device_supports_format([CTypeDetails("Pointer<SoundIoDevice>")] System.IntPtr @device, SoundIoFormat @format);
internal static extern System.IntPtr soundio_format_string(SoundIoFormat @format);
internal static extern int soundio_get_bytes_per_second(SoundIoFormat @format, int @channel_count, int @sample_rate);
internal static extern int soundio_get_bytes_per_frame(SoundIoFormat @format, int @channel_count);
internal static extern int soundio_get_bytes_per_sample(SoundIoFormat @format);
/// <summary> /// Whether specified <see cref="SoundIoFormat"/> is supported by the device. /// </summary> /// <param name="format">Format to validate support for.</param> /// <returns>Value indicating whether format is supported.</returns> public bool SupportsFormat(SoundIoFormat format) { return(NativeMethods.SoundIoDeviceSupportsFormat(handle, format)); }
public static int Main(string[] args) { string exe = "SoundIORecord"; SoundIoBackend backend = SoundIoBackend.None; string deviceId = null; bool isRaw = true; string outfile = "1.pcm"; SoundIoError err; for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.StartsWith("--")) { if (arg.CompareTo("--raw") == 0) { isRaw = true; } else if (++i > args.Length) { return(Usage(exe)); } else if (arg.CompareTo("--backend") == 0) { backend = (SoundIoBackend)Enum.Parse(typeof(SoundIoBackend), args[i]); } else if (arg.CompareTo("--device") == 0) { deviceId = args[i]; } else { return(Usage(exe)); } } else if (outfile == null) { outfile = arg; } else { return(Usage(exe)); } } if (outfile == null) { return(Usage(exe)); } using (SoundIO soundIo = new SoundIO()) { err = (backend == SoundIoBackend.None) ? soundIo.Connect() : soundIo.ConnectBackend(backend); if (err != SoundIoError.None) { Console.Error.WriteLine("Error connecting: {0}.", err.GetErrorMessage()); return(1); } soundIo.FlushEvents(); SoundIODevice selectedDevice = null; if (deviceId != null) { foreach (var dev in soundIo) { if (dev.Aim == SoundIoDeviceAim.Input && dev.Id.Equals(deviceId) && dev.IsRaw == isRaw) { selectedDevice = dev; break; } } if (selectedDevice == null) { Console.Error.WriteLine("Invalid device id: {0}.", deviceId); return(1); } selectedDevice.AddRef(); // Enumerator cleans up itself on dispose } else { selectedDevice = soundIo.GetDefaultInputDevice(); if (selectedDevice == null) { Console.Error.WriteLine("No input devices available."); return(1); } } Console.WriteLine("Device: {0}.", selectedDevice.Name); if (selectedDevice.ProbeError != 0) { Console.Error.WriteLine("Unable to probe device: {0}.", selectedDevice.ProbeError.GetErrorMessage()); return(1); } selectedDevice.SortChannelLayouts(); int sampleRate = prioritizedSampleRates.FirstOrDefault(sr => selectedDevice.SupportsSampleRate(sr)); if (sampleRate == 0) { sampleRate = selectedDevice.SampleRates[0].Max; } SoundIoFormat fmt = prioritizedFormats.FirstOrDefault(f => selectedDevice.SupportsFormat(f)); if (fmt == SoundIoFormat.Invalid) { fmt = selectedDevice.Formats[0]; } using (SoundIOInStream instream = new SoundIOInStream(selectedDevice)) { instream.Format = fmt; instream.SampleRate = sampleRate; instream.OnReadCallback = ReadCallback; instream.OnOverflowCallback = OverflowCallback; err = instream.Open(); if (err != SoundIoError.None) { Console.Error.WriteLine("Unable to open input stream: {0}.", err.GetErrorMessage()); return(1); } Console.WriteLine("{0} {1}Hz {2} interleaved", instream.Layout.Name, sampleRate, fmt.GetFormatString()); const int ringBufferDurationSeconds = 30; int capacity = ringBufferDurationSeconds * instream.SampleRate * instream.BytesPerFrame; SoundIORingBuffer ringBuffer = new SoundIORingBuffer(soundIo, capacity); instream.UserData = ringBuffer.Handle; ringBuffers.Add(ringBuffer.Handle, ringBuffer); err = instream.Start(); if (err != SoundIoError.None) { Console.Error.WriteLine("Unable to start input device: {0}.", err.GetErrorMessage()); return(1); } Console.WriteLine("Recording data for 10 seconds."); int timeout = 100; using (var fs = File.OpenWrite(outfile)) { byte[] buffer = new byte[capacity]; while (true) // No memory allocations allowed { soundIo.FlushEvents(); Thread.Sleep(100); int fillBytes = ringBuffer.FillCount; IntPtr readBuf = ringBuffer.ReadPointer; Marshal.Copy(readBuf, buffer, 0, fillBytes); fs.Write(buffer, 0, fillBytes); ringBuffer.AdvanceReadPointer(fillBytes); if (--timeout <= 0) { break; } } } } selectedDevice.Release(); return(0); } }
/// <summary> /// Retrieves format string for specified sound format. /// </summary> /// <param name="format">Format for which to retrieve value.</param> /// <returns>Format string for specified sound format.</returns> public static string GetFormatString(this SoundIoFormat format) { return(Marshal.PtrToStringAnsi(NativeMethods.SoundIoFormatString(format))); }
/// <summary> /// Retrieves number of bytes required per second for specified format, channel count and sample rate. /// </summary> /// <param name="format">Format for which to retrieve value.</param> /// <param name="channelCount">Number of channels.</param> /// <param name="sampleRate">Sample rate.</param> /// <returns>Number of bytes per sample for specified format, channel count and sample rate.</returns> public static int GetBytesPerSecond(this SoundIoFormat format, int channelCount, int sampleRate) { return(GetBytesPerFrame(format, channelCount) * sampleRate); }
/// <summary> /// Retrieves number of bytes required per frame for specified format and channel count. /// </summary> /// <param name="format">Format for which to retrieve value.</param> /// <param name="channelCount">Number of channels.</param> /// <returns>Number of bytes per sample for specified format and channel count.</returns> public static int GetBytesPerFrame(this SoundIoFormat format, int channelCount) { return(GetBytesPerSample(format) * channelCount); }
/// <summary> /// Retrieves number of bytes required per sample for specified format. /// </summary> /// <param name="format">Format for which to retrieve value.</param> /// <returns>Number of bytes per sample for specified format.</returns> public static int GetBytesPerSample(this SoundIoFormat format) { return(NativeMethods.SoundIoGetBytesPerSample(format)); }