public override void Start()
        {
            _outputStream.Start();
            _outputStream.Pause(false);

            _driver.FlushContextEvents();
        }
예제 #2
0
        static void WriteCallback(SoundIOOutStream stream, int frameCountMin, int frameCountMax)
        {
            double floatSampleRate = stream.SampleRate;
            double secondsPerFrame = 1.0 / floatSampleRate;
            SoundIOChannelAreas areas;
            SoundIoError        err;
            int framesLeft = frameCountMax;

            while (true)
            {
                int frameCount = framesLeft;
                err = stream.BeginWrite(out areas, ref frameCount);
                if (err != SoundIoError.None)
                {
                    throw new SoundIOException(string.Format("Unrecoverable stream error: {0}.", err.GetErrorMessage()));
                }

                if (areas == null || frameCount == 0)
                {
                    break;
                }

                SoundIOChannelLayout layout = stream.Layout;

                double pitch            = 440.0;
                double radiansPerSecond = pitch * 2.0 * Math.PI;
                for (int frame = 0; frame < frameCount; frame++)
                {
                    double sample = Math.Sin((secondsOffset + frame * secondsPerFrame) * radiansPerSecond);
                    for (int channel = 0; channel < layout.ChannelCount; channel += 1)
                    {
                        writeSample(areas[channel].Pointer, sample);
                        areas[channel].AdvancePointer();
                    }
                }
                secondsOffset = (secondsOffset + secondsPerFrame * frameCount) % 1.0;

                err = stream.EndWrite();
                if (err != SoundIoError.None)
                {
                    Console.WriteLine("EndWrite failed with error: {0}.", err);
                    if (err == SoundIoError.Underflow)
                    {
                        return;
                    }

                    throw new SoundIOException(string.Format("Unrecoverable stream error: {0}.", err.GetErrorMessage()));
                }

                framesLeft -= frameCount;
                if (framesLeft <= 0)
                {
                    break;
                }
            }

            stream.Pause(wantPause);
        }
예제 #3
0
        static void write_callback(SoundIOOutStream outstream, int frame_count_min, int frame_count_max)
        {
            double float_sample_rate = outstream.SampleRate;
            double seconds_per_frame = 1.0 / float_sample_rate;

            int frames_left = frame_count_max;
            int frame_count = 0;

            for (; ;)
            {
                frame_count = frames_left;
                var results = outstream.BeginWrite(ref frame_count);

                if (frame_count == 0)
                {
                    break;
                }

                SoundIOChannelLayout layout = outstream.Layout;

                double pitch = 440.0;
                double radians_per_second = pitch * 2.0 * Math.PI;
                for (int frame = 0; frame < frame_count; frame += 1)
                {
                    double sample = Math.Sin((seconds_offset + frame * seconds_per_frame) * radians_per_second);
                    for (int channel = 0; channel < layout.ChannelCount; channel += 1)
                    {
                        var area = results.GetArea(channel);
                        write_sample(area.Pointer, sample);
                        area.Pointer += area.Step;
                    }
                }
                seconds_offset = Math.IEEERemainder(seconds_offset + seconds_per_frame * frame_count, 1.0);

                outstream.EndWrite();

                frames_left -= frame_count;
                if (frames_left <= 0)
                {
                    break;
                }
            }

            outstream.Pause(want_pause);
        }
예제 #4
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);
        }
예제 #5
0
        public static void WriteCallback(SoundIOOutStream stream, int frameCountMin, int frameCountMax)
        {
            SoundIoError err;
            DateTime     callbackTime = DateTime.Now;

            // loop to utilize as much as the frameCountMax as possible
            while (frameCountMax > 0)
            {
                int frameCount = frameCountMax;
                if ((err = stream.BeginWrite(out SoundIOChannelAreas areas, ref frameCount)) != SoundIoError.None)
                {
                    Console.WriteLine("unrecoverable stream error: {0}", err.GetErrorMessage());
                    _fileDone = true;
                }

                if (frameCount == 0)
                {
                    break;
                }

                var bufferCount = frameCount * stream.Layout.ChannelCount;

                // if buffer is done add silence based on latency to allow stream to complete through
                // audio path before stream is Disposed()
                if (_waveFile.Position >= _waveFile.Length)
                {
                    if (_startSilence)
                    {
                        // windows latency is a little higher (using DateTime to determine the callback time delay)
                        // and needs to be accoutned for...
                        _latencySeconds         -= (DateTime.Now - callbackTime).TotalMilliseconds / 1000.0;
                        _silentSamplesRemaining  = (int)((stream.SampleRate * stream.Layout.ChannelCount) * _latencySeconds);
                        _silentSamplesRemaining -= _silentSamplesAlreadySent;
                        _startSilence            = false;
                    }

                    int silentBufferSize;
                    if (_silentSamplesRemaining > bufferCount)
                    {
                        silentBufferSize         = bufferCount;
                        _silentSamplesRemaining -= bufferCount;
                    }
                    else
                    {
                        silentBufferSize        = _silentSamplesRemaining;
                        _silentSamplesRemaining = 0;
                    }

                    if (silentBufferSize > 0)
                    {
                        // create a new buffer initialized to 0 and copy to native buffer
                        var silenceBuffer = new float[silentBufferSize];
                        stream.CopyTo(silenceBuffer, 0, areas, silentBufferSize);
                    }
                    if (_silentSamplesRemaining == 0)
                    {
                        _fileDone = true;
                        stream.EndWrite();
                        stream.Pause(true);
                        return;
                    }
                    // if the remaining audioBuffer will only partially fill the frameCount
                    // copy the remaining amount and set the startSilence flag to allow
                    // stream to play to the end.
                }
                else if (_waveFile.Position + (frameCount * _waveFile.WaveFormat.Channels) >= _waveFile.Length)
                {
                    float[] audioBuffer       = new float[bufferCount];
                    var     actualSamplesRead = _sampleProvider.Read(audioBuffer, 0, bufferCount);
                    stream.CopyTo(audioBuffer, 0, areas, bufferCount);

                    _silentSamplesAlreadySent = bufferCount - actualSamplesRead;
                    _latencySeconds           = 0.0;
                    _startSilence             = true;
                }
                else
                {
                    // copy audioBuffer data to native buffer and advance the bufferPos
                    float[] audioBuffer       = new float[bufferCount];
                    var     actualSamplesRead = _sampleProvider.Read(audioBuffer, 0, bufferCount);
                    stream.CopyTo(audioBuffer, 0, areas, actualSamplesRead);

                    if (_waveFile.Position >= _waveFile.Length)
                    {
                        _latencySeconds = 0.0;
                        _startSilence   = true;
                    }
                }

                if ((err = stream.EndWrite()) != SoundIoError.None)
                {
                    if (err == SoundIoError.Underflow)
                    {
                        return;
                    }
                    Console.WriteLine("Unrecoverable stream error: {0}", err.GetErrorMessage());
                    _fileDone = true;
                }

                if (_startSilence)
                {
                    // get actual latency in order to compute number of silent frames
                    stream.GetLatency(out _latencySeconds);
                    callbackTime = DateTime.Now;
                }

                // loop until frameCountMax is used up
                frameCountMax -= frameCount;
            }
            return;
        }