Exemplo n.º 1
0
        private void _resampleAudioData()
        {
            unsafe
            {
                var sampleCount = _temporaryBuffer.CurrentLength;
                var frames      = sampleCount / 2;
                fixed(float *conversionPtr = &_temporaryConversionBuffer[0])
                {
                    _temporaryBuffer.CopyTo(_temporaryPreconversionAudioBuffer, sampleCount);
                    fixed(short *shortDataPtr = &_temporaryPreconversionAudioBuffer[0])
                    {
                        SampleRate.src_short_to_float_array(shortDataPtr, conversionPtr,
                                                            sampleCount);
                    }

                    if (_resampleNeeded)
                    {
                        fixed(float *resamplePtr =
                              &_temporaryResampleBuffer[0])
                        {
                            var convert = new SampleRate.SRC_DATA()
                            {
                                data_in       = conversionPtr,
                                data_out      = resamplePtr,
                                input_frames  = frames,
                                output_frames = frames * 2,
                                src_ratio     = _audioResampleRatio
                            };
                            var res = SampleRate.src_process(_resamplerState, ref convert);

                            if (res != 0)
                            {
                                Logger.Error(SampleRate.src_strerror(res));
                            }
                            else
                            {
                                for (var i = 0; i < convert.output_frames_gen; i++)
                                {
                                    _temporaryStretcherBuffer[0][i] = _temporaryResampleBuffer[i * 2];
                                    _temporaryStretcherBuffer[1][i] = _temporaryResampleBuffer[i * 2 + 1];
                                }

                                _stretcher.Process(
                                    _temporaryStretcherBuffer,
                                    convert.output_frames_gen,
                                    false
                                    );

                                if (_stretcher.GetSamplesRequired() > 0)
                                {
                                    return;
                                }

                                var availableFrames = _stretcher.Available();
                                _stretcher.Retrieve(_temporaryStretcherBuffer, availableFrames);

                                for (var i = 0; i < availableFrames; i++)
                                {
                                    _temporaryResampleBuffer[i * 2]     = _temporaryStretcherBuffer[0][i];
                                    _temporaryResampleBuffer[i * 2 + 1] = _temporaryStretcherBuffer[1][i];
                                }

                                _audioBuffer.CopyFrom(_temporaryResampleBuffer, availableFrames * 2);
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("else");
//                        _audioBuffer.CopyFrom(_temporaryConversionBuffer, frames * 2);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public int Read(byte[] buffer, int offset, int count)
        {
            int numRead = 0;

            // Mismatched formats/interpretations:
            //
            // - Source returns raw bytes, lets us interpret.
            // - SoundTouch takes samples (Int16), counts one frame across all channels as a single sample (one left + one right == one sample).
            // - When converting to/from bytes, we need to count each channel in a frame as a separate sample (one left + one right == two samples).
            // - We implement IWaveProvider, the same as source, and are thus expected to return raw bytes.
            // - We may be asked for a number of bytes that isn't a multiple of the stretcher's output block size.
            // - We may be provided with source data that isn't a multiple of the stretcher's input block size.
            //
            // Hooray!

            if (_outputExtraBytes.Count > 0)
            {
                if (_outputExtraBytes.Count > count)
                {
                    _outputExtraBytes.CopyTo(0, buffer, offset, count);
                    _outputExtraBytes.RemoveRange(0, count);

                    return(count);
                }
                else
                {
                    _outputExtraBytes.CopyTo(buffer);

                    count   -= _outputExtraBytes.Count;
                    numRead += _outputExtraBytes.Count;

                    _outputExtraBytes.Clear();
                }
            }

            int bytesPerFrame = 2 * _source.WaveFormat.Channels;

            while (true)
            {
                int stretchedFramesToRead = (count + bytesPerFrame - 1) / bytesPerFrame;

                if (stretchedFramesToRead > _stretchedSamples[0].Length)
                {
                    stretchedFramesToRead = _stretchedSamples[0].Length;
                }

                if (_tempoChanged)
                {
                    _stretcher.SetTimeRatio(1.0 / _tempo);
                    _tempoChanged = false;
                }

                int numberOfFramesRead = (int)_stretcher.Retrieve(_stretchedSamples, stretchedFramesToRead);

                if (numberOfFramesRead == 0)
                {
                    int sourceBytesRead = _sourceExtraBytes.Count;

                    if (sourceBytesRead > 0)
                    {
                        _sourceExtraBytes.CopyTo(_sourceBuffer);
                        _sourceExtraBytes.Clear();
                    }

                    sourceBytesRead += _source.Read(_sourceBuffer, sourceBytesRead, _sourceBuffer.Length - sourceBytesRead);

                    SourceRead?.Invoke(this, EventArgs.Empty);

                    if (sourceBytesRead == 0)
                    {
                        // End of stream, zero pad
                        Array.Clear(buffer, offset, count);

                        numRead += count;

                        EndOfStream?.Invoke(this, EventArgs.Empty);

                        return(numRead);
                    }

                    int numberOfSourceSamplesPerChannel = sourceBytesRead / 2 / _source.WaveFormat.Channels;

                    int sourceBytesInSamples = numberOfSourceSamplesPerChannel * _source.WaveFormat.Channels * 2;

                    if (sourceBytesInSamples < sourceBytesRead)
                    {
                        // We got a misaligned read, stash the bytes we aren't going to process for the next pass.
                        for (int i = sourceBytesInSamples; i < sourceBytesRead; i++)
                        {
                            _sourceExtraBytes.Add(_sourceBuffer[i]);
                        }
                    }

                    for (int channel = 0; channel < _source.WaveFormat.Channels; channel++)
                    {
                        int channelOffset = channel * 2;

                        for (int i = 0; i < numberOfSourceSamplesPerChannel; i++)
                        {
                            int lo = _sourceBuffer[i * bytesPerFrame + channelOffset];
                            int hi = _sourceBuffer[i * bytesPerFrame + channelOffset + 1];

                            short sampleValue = unchecked ((short)((hi << 8) | lo));

                            _sourceSamples[channel][i] = sampleValue * (1.0f / 32768.0f);
                        }
                    }

                    _stretcher.Process(_sourceSamples, numberOfSourceSamplesPerChannel, final: false);
                }
                else
                {
                    int i       = 0;
                    int channel = 0;

                    while (i < numberOfFramesRead)
                    {
                        if (count == 0)
                        {
                            break;
                        }

                        float rawSample = _stretchedSamples[channel][i];

                        channel++;

                        if (channel == _source.WaveFormat.Channels)
                        {
                            channel = 0;
                            i++;
                        }

                        unchecked
                        {
                            short sample;

                            if (rawSample <= -1.0)
                            {
                                sample = -32768;
                            }
                            else if (rawSample >= 1.0)
                            {
                                sample = +32767;
                            }
                            else
                            {
                                int wideSample = (int)(rawSample * 32768.0f);

                                if (wideSample < -32768)
                                {
                                    sample = -32768;
                                }
                                else if (wideSample > 32767)
                                {
                                    sample = 32767;
                                }
                                else
                                {
                                    sample = (short)wideSample;
                                }
                            }

                            byte hi = (byte)(sample >> 8);
                            byte lo = (byte)(sample & 0xFF);

                            buffer[offset++] = lo;
                            numRead++;
                            count--;

                            if (count == 0)
                            {
                                _outputExtraBytes.Add(hi);
                                break;
                            }

                            buffer[offset++] = hi;
                            numRead++;
                            count--;
                        }
                    }

                    while (i < numberOfFramesRead)
                    {
                        float rawSample = _stretchedSamples[channel][i];

                        channel++;

                        if (channel == _source.WaveFormat.Channels)
                        {
                            channel = 0;
                            i++;
                        }

                        unchecked
                        {
                            short sample;

                            if (rawSample <= -1.0)
                            {
                                sample = -32768;
                            }
                            else if (rawSample >= 1.0)
                            {
                                sample = +32767;
                            }
                            else
                            {
                                int wideSample = (int)(rawSample * 32768.0f);

                                if (wideSample < -32768)
                                {
                                    sample = -32768;
                                }
                                else if (wideSample > 32767)
                                {
                                    sample = 32767;
                                }
                                else
                                {
                                    sample = (short)wideSample;
                                }
                            }

                            byte hi = (byte)(sample >> 8);
                            byte lo = (byte)(sample & 0xFF);

                            _outputExtraBytes.Add(lo);
                            _outputExtraBytes.Add(hi);
                        }
                    }

                    if (count == 0)
                    {
                        return(numRead);
                    }
                }
            }
        }