Esempio n. 1
0
        void write_callback(SoundIOOutStream outstream, int frame_count_min, int frame_count_max)
        {
            int frameCount = frame_count_max;

            if (frameCount <= 0)
            {
                return;
            }

            var results = outstream.BeginWrite(ref frameCount);
            var samples = new float[frameCount];

            var e = new OutputBufferEventArgs(frameCount);

            Buffer?.Invoke(this, e);
            if (e.Buffer != null)
            {
                ringBuffer.Enqueue(e.Buffer);
            }

            ringBuffer.Dequeue(samples, frameCount);

            var layout = outstream.Layout;

            for (int frame = 0; frame < frameCount; frame++)
            {
                for (int channel = 0; channel < layout.ChannelCount; channel++)
                {
                    var area = results.GetArea(channel);
                    // Raspberry Piではなぜかshortじゃないと音がプツプツする
                    write_short_sample(area.Pointer, samples[frame]);
                    area.Pointer += area.Step;
                }
            }

            outstream.EndWrite();

            unsafe void write_short_sample(IntPtr ptr, float sample)
            {
                short *buf = (short *)ptr;

                *buf = (short)(sample * short.MaxValue);
            }

            unsafe void write_float_sample(IntPtr ptr, float sample)
            {
                float *buf = (float *)ptr;

                *buf = sample;
            }
        }

        void underflow_callback(SoundIOOutStream outstream)
        {
            Underflow?.Invoke(this, EventArgs.Empty);
        }
    }
}
Esempio n. 2
0
        unsafe void write_callback(SoundIOOutStream outstream, int frame_count_min, int frame_count_max)
        {
            int frame_count = frame_count_max;
            var results     = outstream.BeginWrite(ref frame_count);

            SoundIOChannelLayout layout = outstream.Layout;

            int readBytes = frame_count * outstream.BytesPerFrame;
            int readCount = 0;
            int tryCount  = -1;
            int read;

            while (readBytes - readCount > 0 && tryCount++ < UnderflowRetryCount)
            {
                int bufferLength = (int)_ringBuffer.GetLength();
                if (bufferLength % outstream.BytesPerSample != 0)
                {
                    bufferLength -= outstream.BytesPerSample - (bufferLength % outstream.BytesPerSample);
                }

                read       = Math.Min(bufferLength, readBytes - readCount);
                readCount += read;

                byte[] buffer = new byte[read];
                _ringBuffer.Dequeue(buffer);

                SoundIOChannelArea area;
                fixed(byte *buf = buffer)
                {
                    byte *ptr;

                    for (var i = 0; i < buffer.Length; i += outstream.BytesPerSample * layout.ChannelCount)
                    {
                        for (int channel = 0; layout.ChannelCount > channel; channel++)
                        {
                            area = results.GetArea(channel);

                            ptr = (byte *)area.Pointer;
                            for (int j = 0; j < outstream.BytesPerSample; j++)
                            {
                                *ptr = buf[i + j + (channel * outstream.BytesPerSample)];
                                ptr++;
                            }

                            area.Pointer += area.Step;
                        }
                    }
                }

                if (readBytes - readCount > 0)
                {
                    Underflow?.Invoke(this, new UnderflowEventArgs(readBytes - readCount));
                }
            }

            outstream.EndWrite();
        }
Esempio n. 3
0
        private void initInternal(AudioFormat format)
        {
            if (Device == null)
            {
                throw new Exception("No device is selected");
            }

            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?.Invoke(this, new UnderflowEventArgs(null));
            _outstream.ErrorCallback     = () => UnrecoverableError?.Invoke(this, EventArgs.Empty);
            _outstream.SampleRate        = format.SampleRate;
            _outstream.SoftwareLatency   = DesiredLatency.TotalSeconds;

            var soundioFormat = Soundio.ToSoundioFormat(format);

            _outstream.Format = soundioFormat ?? SoundIOFormat.Invalid;

            if (_outstream.LayoutErrorMessage != null)
            {
                var msg = _outstream.LayoutErrorMessage;
                Console.WriteLine($"Channel Layout Error : {msg}");
            }

            _outstream.Open();
            _api.FlushEvents();

            Format          = Soundio.ToManagedFormat(_outstream.Format, _outstream.SampleRate, _outstream.Layout.ChannelCount);
            SoftwareLatency = TimeSpan.FromSeconds(_outstream.SoftwareLatency);

            var bytesPerSample = _outstream.BytesPerSample;
            var capacity       = Format.SampleRate * Format.Channels * bytesPerSample *
                                 _bufferDuration.TotalSeconds;

            _ringBuffer = new RingBuffer <byte>((uint)capacity);
        }
Esempio n. 4
0
        protected override async Task BeforeEach()
        {
            underflow = await Underflow.New(RpcClient);

            // Peform contract deployments and other test setup.
        }