예제 #1
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);
                }
            }
        }
예제 #2
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);
        }
예제 #3
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);
            }
        }