/// <summary>
        /// Output samples from beginning of the sample buffer. Copies requested
        /// samples to  output buffer and removes them from the sample buffer.
        /// If there are less than
        /// <paramref name="maxSamples"/> samples in the buffer, returns all
        /// that available.
        /// </summary>
        /// <param name="output">Buffer where to copy output samples.</param>
        /// <param name="maxSamples">How many samples to receive at max.</param>
        /// <returns>Number of samples returned.</returns>
        public override int ReceiveSamples(ArrayPtr <TSampleType> output, int maxSamples)
        {
            int num = (maxSamples > _samplesInBuffer) ? _samplesInBuffer : maxSamples;

            ArrayPtr <TSampleType> .CopyBytes(output, PtrBegin(), _channels *SIZEOF_SAMPLETYPE *num);

            return(ReceiveSamples(num));
        }
        /// <summary>
        /// Rewind the buffer by moving data from position pointed by
        /// <see cref="_bufferPos"/> to real  beginning of the buffer.
        /// </summary>
        /// <remarks>
        /// if output location pointer <see cref="_bufferPos"/> isn't zero,
        /// 'rewinds' the buffer and zeroes this pointer by copying samples from
        /// the <see cref="_bufferPos"/> pointer  location on to the beginning
        /// of the buffer.
        /// </remarks>
        private void Rewind()
        {
            if ((_buffer == null) || (_bufferPos == 0))
            {
                return;
            }

            ArrayPtr <TSampleType> .CopyBytes(_buffer, PtrBegin(), SIZEOF_SAMPLETYPE *_channels *_samplesInBuffer);

            _bufferPos = 0;
        }
Пример #3
0
        /// <summary>
        /// Processes as many processing frames of the samples <see cref="_inputBuffer"/>, store
        /// the result into <see cref="_outputBuffer"/>
        /// </summary>
        private void ProcessSamples()
        {
            // Process samples as long as there are enough samples in '_inputBuffer'
            // to form a processing frame.
            while (_inputBuffer.AvailableSamples >= _sampleReq)
            {
                // If tempo differs from the normal ('SCALE'), scan for the best overlapping
                // position
                int offset = SeekBestOverlapPosition(_inputBuffer.PtrBegin());

                // Mix the samples in the '_inputBuffer' at position of 'offset' with the
                // samples in 'midBuffer' using sliding overlapping
                // ... first partially overlap with the end of the previous sequence
                // (that's in 'midBuffer')
                Overlap(_outputBuffer.PtrEnd(_overlapLength), _inputBuffer.PtrBegin(), offset);
                _outputBuffer.PutSamples(_overlapLength);

                // ... then copy sequence samples from '_inputBuffer' to output:

                // length of sequence
                int temp = (_seekWindowLength - 2 * _overlapLength);

                // crosscheck that we don't have buffer overflow...
                if (_inputBuffer.AvailableSamples < (offset + temp + _overlapLength * 2))
                {
                    continue; // just in case, shouldn't really happen
                }

                _outputBuffer.PutSamples(_inputBuffer.PtrBegin() + _channels * (offset + _overlapLength), temp);

                // Copies the end of the current sequence from '_inputBuffer' to
                // 'midBuffer' for being mixed with the beginning of the next
                // processing sequence and so on
                Debug.Assert((offset + temp + _overlapLength * 2) <= _inputBuffer.AvailableSamples);
                ArrayPtr <TSampleType> .CopyBytes(_midBuffer, _inputBuffer.PtrBegin() + _channels *(offset + temp + _overlapLength),
                                                  _channels *SIZEOF_SAMPLETYPE *_overlapLength);

                // Remove the processed samples from the input buffer. Update
                // the difference between integer & nominal skip step to '_skipFract'
                // in order to prevent the error from accumulating over time.
                _skipFract += _nominalSkip; // real skip size
                var ovlSkip = (int)_skipFract;
                _skipFract -= ovlSkip;      // maintain the fraction part, i.e. real vs. integer skip
                _inputBuffer.ReceiveSamples(ovlSkip);
            }
        }
Пример #4
0
        /// <summary>
        /// Set filter coefficients and length.
        /// </summary>
        /// <exception cref="ArgumentException">FIR filter length not divisible
        /// by 8</exception>
        public virtual void SetCoefficients(ArrayPtr <TSampleType> coeffs, int newLength, int resultDivFactor)
        {
            Debug.Assert(newLength > 0);
            if ((newLength % 8) != 0)
            {
                throw new ArgumentException("FIR filter length not divisible by 8");
            }

            _lengthDiv8 = newLength / 8;
            _length     = _lengthDiv8 * 8;
            Debug.Assert(_length == newLength);
            _resultDivFactor = resultDivFactor;

            var numPtr = new TSampleType[_length];

            _filterCoeffs = numPtr;
            ArrayPtr <TSampleType> .CopyBytes(_filterCoeffs, coeffs, _length *SIZEOF_SAMPLETYPE);
        }
        /// <summary>
        /// Ensures that the buffer has capacity for at least this many samples.
        /// </summary>
        private void EnsureCapacity(int capacityRequirement)
        {
            if (capacityRequirement > GetCapacity())
            {
                // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
                _sizeInBytes = (int)((capacityRequirement * _channels * SIZEOF_SAMPLETYPE + 4095) & unchecked ((uint)-4096));
                Debug.Assert(_sizeInBytes % 2 == 0);
                var temp = new TSampleType[_sizeInBytes / SIZEOF_SAMPLETYPE + 16 / SIZEOF_SAMPLETYPE];

                if (_samplesInBuffer != 0)
                {
                    ArrayPtr <TSampleType> .CopyBytes(temp, PtrBegin(), _samplesInBuffer *_channels *SIZEOF_SAMPLETYPE);
                }

                _buffer    = temp;
                _bufferPos = 0;
            }
            else
            {
                // simply rewind the buffer (if necessary)
                Rewind();
            }
        }
        /// <summary>
        /// Adds <paramref name="numSamples"/> pcs of samples from the
        /// <paramref name="samples"/> memory position to the sample buffer.
        /// </summary>
        /// <param name="samples">Pointer to samples.</param>
        /// <param name="numSamples">Number of samples to insert.</param>
        public override void PutSamples(ArrayPtr <TSampleType> samples, int numSamples)
        {
            ArrayPtr <TSampleType> .CopyBytes(PtrEnd(numSamples), samples, SIZEOF_SAMPLETYPE *numSamples *_channels);

            _samplesInBuffer += numSamples;
        }