Example #1
0
        public InputStream(Device deviceToOwn)
        {
            _self   = GCHandle.Alloc(this);
            _device = deviceToOwn;
            _stream = InStream.Create(_device);

            try
            {
                if (_stream.IsInvalid)
                {
                    throw new InvalidOp("Stream allocation error");
                }

                if (_device.Layouts.Length == 0)
                {
                    throw new InvalidOp("No channel layout");
                }

                // Calculate the best latency.
                // TODO: Should we use the target frame rate instead of 1/60?
                var bestLatency = Math.Max(1.0 / 60, _device.SoftwareLatencyMin);

                // Stream properties
                _stream.Format           = Format.Float32LE;
                _stream.Layout           = _device.Layouts[0];
                _stream.SoftwareLatency  = bestLatency;
                _stream.ReadCallback     = _readCallback;
                _stream.OverflowCallback = _overflowCallback;
                _stream.ErrorCallback    = _errorCallback;
                _stream.UserData         = GCHandle.ToIntPtr(_self);

                var err = _stream.Open();

                if (err != Error.None)
                {
                    throw new InvalidOp($"Stream initialization error ({err})");
                }

                // We want the buffers to meet the following requirements:
                // - Doesn't overflow if the main thread pauses for 4 frames.
                // - Doesn't overflow if the callback is invoked 4 times a frame.
                var latency    = Math.Max(_stream.SoftwareLatency, bestLatency);
                var bufferSize = CalculateBufferSize((float)(latency * 4));

                // Ring/window buffer allocation
                _ring   = new RingBuffer(bufferSize);
                _window = new byte[bufferSize];

                // Start streaming.
                _stream.Start();
            }
            catch
            {
                // Dispose the resources on an exception.
                _stream.Dispose();
                _device.Dispose();
                _stream = null;
                _device = null;
                throw;
            }
        }