Beispiel #1
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;
        }