Example #1
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);
        }
Example #2
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);
            }
        }
Example #3
0
        static void write_callback(SoundIOOutStream outstream, int frame_count_min, int frame_count_max)
        {
            SoundIOChannelAreas areas = default(SoundIOChannelAreas);
            int frames_left           = 0;
            int frame_count           = 0;

            var read_ptr   = ring_buffer.ReadPointer;
            int fill_bytes = ring_buffer.FillCount;
            int fill_count = fill_bytes / outstream.BytesPerFrame;

            if (frame_count_min > fill_count)
            {
                // Ring buffer does not have enough data, fill with zeroes.
                frames_left = frame_count_min;
                for (; ;)
                {
                    frame_count = frames_left;
                    if (frame_count <= 0)
                    {
                        return;
                    }
                    areas = outstream.BeginWrite(ref frame_count);
                    if (frame_count <= 0)
                    {
                        return;
                    }
                    var chCount = outstream.Layout.ChannelCount;
                    for (int frame = 0; frame < frame_count; frame += 1)
                    {
                        for (int ch = 0; ch < chCount; ch += 1)
                        {
                            var area = areas.GetArea(ch);
                            // FIXME: there should be more efficient way for memset(ptr, 0);
                            for (int i = 0; i < outstream.BytesPerSample; i++)
                            {
                                Marshal.WriteByte(area.Pointer, 0);
                            }
                            area.Pointer += area.Step;
                        }
                    }
                    outstream.EndWrite();
                    frames_left -= frame_count;
                }
            }

            int read_count = Math.Min(frame_count_max, fill_count);

            frames_left = read_count;

            while (frames_left > 0)
            {
                frame_count = frames_left;

                areas = outstream.BeginWrite(ref frame_count);

                if (frame_count <= 0)
                {
                    break;
                }

                var chCount  = outstream.Layout.ChannelCount;
                var copySize = outstream.BytesPerSample;
                for (int frame = 0; frame < frame_count; frame += 1)
                {
                    unsafe {
                        for (int ch = 0; ch < chCount; ch += 1)
                        {
                            var area = areas.GetArea(ch);
                            Buffer.MemoryCopy((void *)read_ptr, (void *)area.Pointer, copySize, copySize);
                            area.Pointer += area.Step;
                            read_ptr     += outstream.BytesPerSample;
                        }
                    }
                }
                outstream.EndWrite();

                frames_left -= frame_count;
            }
            ring_buffer.AdvanceReadPointer(read_count * outstream.BytesPerFrame);
        }