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 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) { 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); } }