static int ListDevices(SoundIO soundIo) { int outputCount = soundIo.GetOutputDeviceCount(); int inputCount = soundIo.GetInputDeviceCount(); int defaultOutput = soundIo.GetDefaultOutputDeviceIndex(); int defaultInput = soundIo.GetDefaultInputDeviceIndex(); Console.WriteLine("--------Input Devices--------"); for (int i = 0; i < inputCount; i++) { SoundIODevice device = soundIo.GetInputDevice(i); PrintDevice(device, defaultInput == i); device.Release(); } Console.WriteLine("\n--------Output Devices--------\n"); for (int i = 0; i < outputCount; i++) { SoundIODevice device = soundIo.GetOutputDevice(i); PrintDevice(device, defaultOutput == i); device.Release(); } Console.WriteLine("\n{0} devices found.", inputCount + outputCount); return(0); }
public void Init(SoundIODevice device) { OutputDevice = device; if (OutputDevice.ProbeError != 0) { throw new Exception($"Probe Error : {OutputDevice.ProbeError}"); } Console.WriteLine($"Device Name : {OutputDevice.Name}"); outstream = OutputDevice.CreateOutStream(); outstream.WriteCallback = (min, max) => write_callback(outstream, min, max); outstream.UnderflowCallback = () => underflow_callback(outstream); outstream.SoftwareLatency = 0; outstream.SampleRate = Source.Format.SampleRate; if (OutputDevice.SupportsFormat(SoundIODevice.Float32NE)) { outstream.Format = SoundIODevice.Float32NE; } else { outstream.Dispose(); outstream = null; throw new Exception("No suitable format"); } outstream.Open(); if (outstream.LayoutErrorMessage != null) { Console.WriteLine("Layout Error : " + outstream.LayoutErrorMessage); } }
public void Initialize(SoundIODevice device, AudioFormat format) { if (format.Channels != 1) { throw new OutputInitializationException("Format must qualify channels == 1"); } Device = device; Format = format; var bytesPerSample = format.BitDepth / 8; var capacity = Format.SampleRate * Format.Channels * bytesPerSample * 30; ringBuffer = new RingBuffer <float>((uint)capacity); if (Device.ProbeError != 0) { throw new OutputInitializationException($"Probe Error : {Device.ProbeError}"); } outstream = Device.CreateOutStream(); outstream.WriteCallback = (min, max) => write_callback(outstream, min, max); outstream.UnderflowCallback = () => underflow_callback(outstream); outstream.SampleRate = Format.SampleRate; outstream.SoftwareLatency = DesiredLatency.TotalSeconds; outstream.Format = SoundIODevice.S16NE; outstream.Open(); outstream.Layout = SoundIOChannelLayout.GetDefault(Format.Channels); outstream.SoftwareLatency = DesiredLatency.TotalSeconds; api.FlushEvents(); ActualLatency = TimeSpan.FromSeconds(outstream.SoftwareLatency); }
static void PrintDevice(SoundIODevice dev) { Console.WriteLine($" {dev.Id} - {dev.Name}"); foreach (var pi in typeof(SoundIODevice).GetProperties()) { Console.WriteLine($" {pi.Name}: {pi.GetValue (dev)}"); } }
/// <summary> /// Constructs a new instance of a <see cref="SoundIoAudioOut"/> /// </summary> public SoundIoAudioOut() { m_AudioContext = new SoundIO(); m_AudioContext.Connect(); m_AudioContext.FlushEvents(); m_AudioDevice = m_AudioContext.GetOutputDevice(m_AudioContext.DefaultOutputDeviceIndex); m_TrackPool = new SoundIoAudioTrackPool(m_AudioContext, m_AudioDevice, MaximumTracks); }
/// <summary> /// Constructs a new instance of a <see cref="SoundIoAudioOut"/> /// </summary> public SoundIoAudioOut() { _audioContext = new SoundIO(); _audioContext.Connect(); _audioContext.FlushEvents(); _audioDevice = FindNonRawDefaultAudioDevice(_audioContext, true); _trackPool = new SoundIoAudioTrackPool(_audioContext, _audioDevice, MaximumTracks); }
/// <summary> /// Constructs a new instance of a <see cref="SoundIoAudioTrack"/> /// </summary> /// <param name="trackId">The track ID</param> /// <param name="audioContext">The SoundIO audio context</param> /// <param name="audioDevice">The SoundIO audio device</param> public SoundIoAudioTrack(int trackId, SoundIO audioContext, SoundIODevice audioDevice) { TrackID = trackId; AudioContext = audioContext; AudioDevice = audioDevice; State = PlaybackState.Stopped; ReleasedBuffers = new ConcurrentQueue <long>(); m_Buffer = new SoundIoRingBuffer(); m_ReservedBuffers = new ConcurrentQueue <SoundIoBuffer>(); }
public SoundIoHardwareDeviceDriver() { _audioContext = new SoundIO(); _updateRequiredEvent = new ManualResetEvent(false); _sessions = new List <SoundIoHardwareDeviceSession>(); _audioContext.Connect(); _audioContext.FlushEvents(); _audioDevice = FindNonRawDefaultAudioDevice(_audioContext, true); }
public SoundIoHardwareDeviceDriver() { _audioContext = new SoundIO(); _updateRequiredEvent = new ManualResetEvent(false); _pauseEvent = new ManualResetEvent(true); _sessions = new ConcurrentDictionary <SoundIoHardwareDeviceSession, byte>(); _audioContext.Connect(); _audioContext.FlushEvents(); _audioDevice = FindNonRawDefaultAudioDevice(_audioContext, true); }
public void Initialize(SoundIODevice device, AudioFormat format) { try { Device = device; initInternal(format); } catch (Exception) { Device = null; throw; } }
public void Initialize(SoundIODevice device) { if (device is null) { throw new ArgumentNullException(nameof(device)); } if (IsInitialized) { throw new InvalidOperationException("Output device was already initialized"); } IsInitialized = false; var output = new SoundioOutput(); output.Initialize(device, SharedFormat); Output = output; IsInitialized = true; }
/// <summary> /// Searches for a shared version of the default audio device /// </summary> /// <param name="audioContext">The <see cref="SoundIO"/> audio context</param> /// <param name="fallback">Whether to fallback to the raw default audio device if a non-raw device cannot be found</param> private static SoundIODevice FindNonRawDefaultAudioDevice(SoundIO audioContext, bool fallback = false) { SoundIODevice defaultAudioDevice = audioContext.GetOutputDevice(audioContext.DefaultOutputDeviceIndex); if (!defaultAudioDevice.IsRaw) { return(defaultAudioDevice); } for (int i = 0; i < audioContext.BackendCount; i++) { SoundIODevice audioDevice = audioContext.GetOutputDevice(i); if (audioDevice.Id == defaultAudioDevice.Id && !audioDevice.IsRaw) { return(audioDevice); } } return(fallback ? defaultAudioDevice : null); }
/// <summary> /// Determines if SoundIO can connect to a supported backend /// </summary> /// <returns></returns> private static bool IsSupportedInternal() { SoundIO context = null; SoundIODevice device = null; SoundIOOutStream stream = null; bool backendDisconnected = false; try { context = new SoundIO(); context.OnBackendDisconnect = (i) => { backendDisconnected = true; }; context.Connect(); context.FlushEvents(); if (backendDisconnected) { return(false); } if (context.OutputDeviceCount == 0) { return(false); } device = FindNonRawDefaultAudioDevice(context); if (device == null || backendDisconnected) { return(false); } stream = device.CreateOutStream(); if (stream == null || backendDisconnected) { return(false); } return(true); } catch { return(false); } finally { if (stream != null) { stream.Dispose(); } if (context != null) { context.Dispose(); } } }
static void Main(string[] args) { Source.Function = FunctionType.Sin; EnvelopeGenerator = new VolumeEnvelope(Source); EnvelopeGenerator.Released += EnvelopeGeneratorOnReleased; Player = new AudioPlayer(EnvelopeGenerator); foreach (var (i, dev) in Player.Devices.Select((dev, i) => (i, dev))) { if (i == Player.DefaultDeviceIndex) { Console.WriteLine($"[{i}][Default] {dev.Name}"); } else { Console.WriteLine($"[{i}] {dev.Name}"); } } SoundIODevice device = null; while (device == null) { Console.Write("Device Index > "); var num = Console.ReadLine(); if (int.TryParse(num, out var i) && i >= 0 && i < Player.Devices.Count) { device = Player.Devices[i]; break; } } try { Player.Init(device); } catch (Exception ex) { Console.WriteLine(ex); Player.Dispose(); return; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { Input = new LinuxInput(); } else { Input = new CommonInput(); } Input.Attack += InputOnAttack; Input.Release += InputOnRelease; Input.Exit += InputOnExit; Input.Listen(); while (!exit) { Thread.Sleep(100); } Player.Dispose(); Input.Stop(); }
public static int Main(string[] args) { string exe = "SoundIOSine"; SoundIoBackend backend = SoundIoBackend.None; string deviceId = null; bool raw = false; string streamName = null; double latency = 0.0; int sampleRate = 0; SoundIoError err; SoundIODevice device = null; for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.StartsWith("--")) { if (arg.CompareTo("--raw") == 0) { raw = true; } else { i++; 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 if (arg.CompareTo("--name") == 0) { streamName = args[i]; } else if (arg.CompareTo("--latency") == 0) { latency = double.Parse(args[i]); } else if (arg.CompareTo("--sample-rate") == 0) { sampleRate = int.Parse(args[i]); } else { return(Usage(exe)); } } } else { return(Usage(exe)); } } SoundIO soundIo = new SoundIO(); err = (backend == SoundIoBackend.None) ? soundIo.Connect() : soundIo.ConnectBackend(backend); if (err != SoundIoError.None) { Console.Error.WriteLine("Unable to connect to backend: {0}.", err.GetErrorMessage()); return(1); } Console.WriteLine("Backend: {0}.", soundIo.CurrentBackend); soundIo.FlushEvents(); if (deviceId != null) { foreach (var dev in soundIo) { if (dev.Aim == SoundIoDeviceAim.Output && dev.Id.Equals(deviceId) && dev.IsRaw == raw) { device = dev; break; } } if (device == null) { Console.Error.WriteLine("Output device not found."); return(1); } device.AddRef(); // Enumerator cleans up itself on dispose } else { device = soundIo.GetDefaultOutputDevice(); } Console.WriteLine("Output device: {0}.", device.Name); if (device.ProbeError != SoundIoError.None) { Console.Error.WriteLine("Cannot probe device: {0}.", device.ProbeError.GetErrorMessage()); return(1); } SoundIOOutStream outstream = new SoundIOOutStream(device); outstream.OnWriteCallback = WriteCallback; outstream.OnUnderflowCallback = UnderflowCallback; if (streamName != null) { outstream.Name = streamName; } outstream.SoftwareLatency = latency; if (sampleRate != 0) { outstream.SampleRate = sampleRate; } if (device.SupportsFormat(SoundIoFormats.Float32NE)) { outstream.Format = SoundIoFormats.Float32NE; writeSample = WriteSampleFloat32NE; } else if (device.SupportsFormat(SoundIoFormats.Float64NE)) { outstream.Format = SoundIoFormats.Float64NE; writeSample = WriteSampleFloat64NE; } else if (device.SupportsFormat(SoundIoFormats.S32NE)) { outstream.Format = SoundIoFormats.S32NE; writeSample = WriteSampleS32NE; } else if (device.SupportsFormat(SoundIoFormats.S16NE)) { outstream.Format = SoundIoFormats.S16NE; writeSample = WriteSampleS16NE; } else { Console.Error.WriteLine("No suitable format available."); return(1); } err = outstream.Open(); if (err != SoundIoError.None) { Console.Error.WriteLine("Unable to open device: {0}.", err.GetErrorMessage()); return(1); } Console.WriteLine("Software latency: {0:N6}.", outstream.SoftwareLatency); Console.WriteLine( "\t'p' - pause\n" + "\t'u' - unpause\n" + "\t'P' - pause from within callback\n" + "\t'c' - clear buffer\n" + "\t'q' - quit\n"); if (outstream.LayoutError != SoundIoError.None) { Console.Error.WriteLine("Unable to set channel layout: {0}.", outstream.LayoutError.GetErrorMessage()); } err = outstream.Start(); if (err != SoundIoError.None) { Console.Error.WriteLine("Unable to start device {0}.", err.GetErrorMessage()); return(1); } while (true) { soundIo.FlushEvents(); int c = Console.Read(); if (c == 'p') { err = outstream.Pause(true); Console.Error.WriteLine("Pausing result: {0}.", err.GetErrorMessage()); } else if (c == 'P') { wantPause = true; } else if (c == 'u') { wantPause = false; err = outstream.Pause(false); Console.Error.WriteLine("Unpausing result: {0}.", err.GetErrorMessage()); } else if (c == 'c') { err = outstream.ClearBuffer(); Console.Error.WriteLine("Clear buffer result: {0}.", err.GetErrorMessage()); } else if (c == 'q') { break; } else if (c == '\r' || c == '\n') { // ignore } else { Console.Error.WriteLine("Unrecognized command: {0}.", (char)c); } } outstream.Dispose(); device.Release(); soundIo.Dispose(); return(0); }
public static int Main(string[] args) { int sampleRate; string filename = null; SoundIoBackend backend = SoundIoBackend.None; string deviceId = null; bool isRaw = false; SoundIoError err; try { if (args.Length < 1) { Usage(); return(1); } for (int i = 0; i < args.Length; i++) { string arg = args[i]; if (arg.StartsWith("--")) { if (++i > args.Length) { return(Usage()); } 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()); } } else { if (File.Exists(args[i])) { filename = args[i]; } else { Usage(); return(1); } } } if (string.IsNullOrEmpty(filename)) { throw new Exception("Input file name can not null."); } } catch (IndexOutOfRangeException) { Usage(); return(1); } using (_soundIO = new SoundIO()) { using (_waveFile = new WaveFileReader(filename)) { _channels = _waveFile.WaveFormat.Channels; sampleRate = _waveFile.WaveFormat.SampleRate; _soundIO.Connect(); _soundIO.FlushEvents(); SoundIODevice device = null; if (deviceId != null) { foreach (var dev in _soundIO) { if (dev.Aim == SoundIoDeviceAim.Output && dev.Id.Equals(deviceId) && dev.IsRaw == isRaw) { device = dev; break; } } if (device == null) { Console.Error.WriteLine("Output device not found."); return(1); } device.AddRef(); // Enumerator cleans up itself on dispose } else { device = _soundIO.GetDefaultOutputDevice(); } Console.WriteLine("Device: {0}.", device.Name); if (device.ProbeError != SoundIoError.None) { Console.WriteLine("Cannot probe device: {0}", device.ProbeError); return(1); } Console.WriteLine("Output device: {0}", device.Name); if (device.ProbeError != SoundIoError.None) { Console.WriteLine("Cannot probe device: {0}", device.ProbeError); return(1); } var outstream = new SoundIOOutStream(device) { OnWriteCallback = WriteCallback, OnUnderflowCallback = UnderflowCallback, Name = "sio_play", SampleRate = sampleRate }; // look for maching layout for wav file... var foundLayout = false; foreach (var layout in device.Layouts) { if (layout.ChannelCount == _channels) { outstream.Layout = layout; foundLayout = true; break; } } // TODO: may need to look at endian issues and other formats... // when paired with NAudioLite, ISampleProvider the conversion to Float32 is automatic. if (device.SupportsFormat(SoundIoFormats.Float32NE)) { outstream.Format = SoundIoFormats.Float32NE; } else if (device.SupportsFormat(SoundIoFormats.Float64NE)) { outstream.Format = SoundIoFormats.Float64NE; } else if (device.SupportsFormat(SoundIoFormats.S32NE)) { outstream.Format = SoundIoFormats.S32NE; } else if (device.SupportsFormat(SoundIoFormats.S16NE)) { outstream.Format = SoundIoFormats.S16NE; } else { Console.WriteLine("No suitable device format available."); return(1); } Console.WriteLine(); Console.WriteLine("Playing file: {0}, Format: {1}", Path.GetFullPath(filename), _waveFile.WaveFormat); err = outstream.Open(); if (err != SoundIoError.None) { Console.WriteLine($"Unable to open device: {err.GetErrorMessage()}, with sample rate: {outstream.LayoutError}"); return(1); } if (outstream.LayoutError != SoundIoError.None) { Console.WriteLine($"Unable to set channel layout: {err.GetErrorMessage()}"); } // revisit layout... // if no suitable layout found if (!foundLayout) { Console.WriteLine("No native channel layout found, Device Channels: {0}, Wav File Channels: {1}, requires sampler...", outstream.Layout.ChannelCount, _channels); } // get sample provider that matches outstream.Layout if (outstream.Layout.ChannelCount == 1) { // mono if (_waveFile.WaveFormat.Channels == 1) { _sampleProvider = _waveFile.ToSampleProvider(); } else { _sampleProvider = _waveFile.ToSampleProvider().ToMono(); } } else if (outstream.Layout.ChannelCount == 2) { //stereo if (_waveFile.WaveFormat.Channels == 1) { _sampleProvider = _waveFile.ToSampleProvider().ToStereo(); } else { _sampleProvider = _waveFile.ToSampleProvider(); } } outstream.Start(); _soundIO.OnBackendDisconnect += SoundIo_OnBackendDisconnected; while (!_fileDone) { System.Threading.Thread.Sleep(100); _soundIO.FlushEvents(); } System.Threading.Thread.Sleep(500); if (_fileDone && outstream != null) { outstream.Dispose(); outstream = null; } Console.WriteLine("End Program"); return(0); } } }
public static int Main(string [] args) { string in_device_id = null, out_device_id = null; string backend_name = null; bool in_raw = false, out_raw = false; double microphone_latency = 0.2; // seconds foreach (var arg in args) { switch (arg) { case "--in_raw": in_raw = true; continue; case "--out_raw": out_raw = true; continue; default: if (arg.StartsWith("--backend:")) { backend_name = arg.Substring(arg.IndexOf(':') + 1); } else if (arg.StartsWith("--in-device:")) { in_device_id = arg.Substring(arg.IndexOf(':') + 1); } else if (arg.StartsWith("--out-device:")) { out_device_id = arg.Substring(arg.IndexOf(':') + 1); } else if (arg.StartsWith("--latency:")) { microphone_latency = double.Parse(arg.Substring(arg.IndexOf(':') + 1)); } 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 in_device = in_device_id == null?api.GetInputDevice(api.DefaultInputDeviceIndex) : Enumerable.Range(0, api.InputDeviceCount) .Select(i => api.GetInputDevice(i)) .FirstOrDefault(d => d.Id == in_device_id && d.IsRaw == in_raw); if (in_device == null) { Console.Error.WriteLine("Input device " + in_device_id + " not found."); return(1); } Console.WriteLine("input device: " + in_device.Name); if (in_device.ProbeError != 0) { Console.Error.WriteLine("Cannot probe input device " + in_device_id + "."); return(1); } var out_device = out_device_id == null?api.GetOutputDevice(api.DefaultOutputDeviceIndex) : Enumerable.Range(0, api.OutputDeviceCount) .Select(i => api.GetOutputDevice(i)) .FirstOrDefault(d => d.Id == out_device_id && d.IsRaw == out_raw); if (out_device == null) { Console.Error.WriteLine("Output device " + out_device_id + " not found."); return(1); } Console.WriteLine("output device: " + out_device.Name); if (out_device.ProbeError != 0) { Console.Error.WriteLine("Cannot probe output device " + out_device_id + "."); return(1); } out_device.SortDeviceChannelLayouts(); var layout = SoundIODevice.BestMatchingChannelLayout(out_device, in_device); if (layout.IsNull) { throw new InvalidOperationException("channel layouts not compatible"); // panic() } var sample_rate = prioritized_sample_rates.FirstOrDefault(sr => in_device.SupportsSampleRate(sr) && out_device.SupportsSampleRate(sr)); if (sample_rate == default(int)) { throw new InvalidOperationException("incompatible sample rates"); // panic() } var fmt = prioritized_formats.FirstOrDefault(f => in_device.SupportsFormat(f) && out_device.SupportsFormat(f)); if (fmt == default(SoundIOFormat)) { throw new InvalidOperationException("incompatible sample formats"); // panic() } var instream = in_device.CreateInStream(); instream.Format = fmt; instream.SampleRate = sample_rate; instream.Layout = layout; instream.SoftwareLatency = microphone_latency; instream.ReadCallback = (fmin, fmax) => read_callback(instream, fmin, fmax); instream.Open(); var outstream = out_device.CreateOutStream(); outstream.Format = fmt; outstream.SampleRate = sample_rate; outstream.Layout = layout; outstream.SoftwareLatency = microphone_latency; outstream.WriteCallback = (fmin, fmax) => write_callback(outstream, fmin, fmax); outstream.UnderflowCallback = () => underflow_callback(outstream); outstream.Open(); int capacity = (int)(microphone_latency * 2 * instream.SampleRate * instream.BytesPerFrame); ring_buffer = api.CreateRingBuffer(capacity); var buf = ring_buffer.WritePointer; int fill_count = (int)(microphone_latency * outstream.SampleRate * outstream.BytesPerFrame); // FIXME: there should be more efficient way for memset() for (int i = 0; i < fill_count; i++) { Marshal.WriteByte(buf, i, 0); } ring_buffer.AdvanceWritePointer(fill_count); instream.Start(); outstream.Start(); for (;;) { api.WaitEvents(); } outstream.Dispose(); instream.Dispose(); in_device.RemoveReference(); out_device.RemoveReference(); api.Dispose(); return(0); }
private bool InitAudio(string[] args, bool noShell) { var path = args.GetString("--audio"); AudioConfig audio; try { using var sr = new StreamReader(path); audio = AudioConfig.Deserialize(sr.ReadToEnd()); } catch (Exception ex) { Console.WriteLine(ex); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Failed to open the audio configuration file"); Console.ResetColor(); return(false); } Input = new SoundioInput(); SoundIODevice inputDevice = null; foreach (var device in Input.Devices) { if (device.Name == audio.InputDevice) { inputDevice = device; break; } } if (inputDevice != null) { Input.Initialize(inputDevice, audio.Format); SayInitialized($"Input {inputDevice.Name}, latency {Input.SoftwareLatency.TotalMilliseconds}ms"); } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Input device was not found ({audio.InputDevice})"); Console.ResetColor(); return(false); } if (audio.OutputDevice != null) { SoundIODevice outputDevice = null; Output = new SoundioOutput(); foreach (var device in Output.Devices) { if (device.Name == audio.OutputDevice) { outputDevice = device; break; } } if (outputDevice != null) { Output.Initialize(outputDevice, audio.Format); SayInitialized($"Output {outputDevice.Name}, latency {Output.SoftwareLatency.TotalMilliseconds}ms"); } else { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Output device was not found ({audio.OutputDevice})"); Console.ResetColor(); if (noShell) { return(false); } else { return(ConsoleHelper.ReadYesNo("Proceed anyway? [yes/no] > ")); } } } return(true); }
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); } }
static void PrintDevice(SoundIODevice device, bool isDefault) { string defaultStr = isDefault ? " (default)" : string.Empty; string rawStr = device.IsRaw ? " (raw)" : string.Empty; Console.WriteLine("{0}{1}{2}", device.Name, defaultStr, rawStr); if (shortOutput) { return; } Console.WriteLine(" Id: {0}.", device.Id); if (device.ProbeError != SoundIoError.None) { Console.Error.WriteLine(" Probe error: {0}.", device.ProbeError.GetErrorMessage()); } else { Console.WriteLine(" Channel layouts:"); for (int i = 0; i < device.LayoutCount; i++) { Console.Write(" "); PrintChannelLayout(device.Layouts[i]); Console.WriteLine(); } if (device.CurrentLayout.ChannelCount > 0) { Console.Write(" Current layout: "); PrintChannelLayout(device.CurrentLayout); Console.WriteLine(); } Console.WriteLine(" Sample rates:"); for (int i = 0; i < device.SamleRateCount; i++) { SoundIoSampleRateRange range = device.SampleRates[i]; Console.WriteLine(" {0} - {1}", range.Min, range.Max); } if (device.CurrentSampleRate != 0) { Console.WriteLine(" Current sample rate: {0}.", device.CurrentSampleRate); } Console.Write(" Formats: "); for (int i = 0; i < device.FormatCount; i++) { string comma = (i == device.FormatCount - 1) ? string.Empty : ", "; Console.Write("{0}{1}", device.Formats[i].GetFormatString(), comma); } Console.WriteLine(); if (device.CurrentFormat != SoundIoFormat.Invalid) { Console.WriteLine(" Current format: {0}.", device.CurrentFormat.GetFormatString()); } Console.WriteLine(" Min software latency: {0:N8} sec.", device.SoftwareLatencyMin); Console.WriteLine(" Max software latency: {0:N8} sec.", device.SoftwareLatencyMax); if (device.SoftwareLatencyCurrent != 0) { Console.WriteLine(" Current software latency: {0:N8} sec.", device.SoftwareLatencyCurrent); } } Console.WriteLine(); }