/// <summary>
        /// Transposes down the sample rate, causing the observed playback
        /// 'rate' of the sound to increase
        /// </summary>
        private void Downsample(ArrayPtr <TSampleType> src, int numSamples)
        {
            // If the parameter 'uRate' value is larger than 'SCALE', first apply the
            // anti-alias filter to remove high frequencies (prevent them from folding
            // over the lover frequencies), then transpose.

            // Add the new samples to the end of the storeBuffer
            _storeBuffer.PutSamples(src, numSamples);

            // Anti-alias filter the samples to prevent folding and output the filtered
            // data to tempBuffer. Note : because of the FIR filter length, the
            // filtering routine takes in 'filter_length' more samples than it outputs.
            Debug.Assert(_tempBuffer.IsEmpty);
            var sizeTemp = _storeBuffer.AvailableSamples;

            int count = _antiAliasFilter.Evaluate(_tempBuffer.PtrEnd(sizeTemp), _storeBuffer.PtrBegin(), sizeTemp, _channels);

            if (count == 0)
            {
                return;
            }

            // Remove the filtered samples from 'storeBuffer'
            _storeBuffer.ReceiveSamples(count);

            // Transpose the samples (+16 is to reserve some slack in the destination buffer)
            sizeTemp = (int)(numSamples / Rate + 16.0f);
            count    = Transpose(_outputBuffer.PtrEnd(sizeTemp), _tempBuffer.PtrBegin(), count);
            _outputBuffer.PutSamples(count);
        }
예제 #2
0
        public virtual int Transpose(FifoSampleBuffer <TSampleType> dest, FifoSampleBuffer <TSampleType> src)
        {
            int numSrcSamples = src.AvailableSamples;
            int sizeDemand    = (int)(numSrcSamples / rate) + 8;
            int numOutput;

            ArrayPtr <TSampleType> psrc  = src.PtrBegin();
            ArrayPtr <TSampleType> pdest = dest.PtrEnd(sizeDemand);

#if !USE_MULTICH_ALWAYS
            if (channels == 1)
            {
                numOutput = TransposeMono(pdest, psrc, ref numSrcSamples);
            }
            else if (channels == 2)
            {
                numOutput = TransposeStereo(pdest, psrc, ref numSrcSamples);
            }
            else
#endif
            {
                Debug.Assert(channels > 0);
                numOutput = TransposeMulti(pdest, psrc, ref numSrcSamples);
            }
            dest.PutSamples(numOutput);
            src.ReceiveSamples(numSrcSamples);
            return(numOutput);
        }
예제 #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
        public int Evaluate(FifoSampleBuffer <TSampleType> dest, FifoSampleBuffer <TSampleType> src)
        {
            ArrayPtr <TSampleType> pdest;
            ArrayPtr <TSampleType> psrc;
            int numSrcSamples;
            int result;
            int numChannels = src.GetChannels();

            Debug.Assert(numChannels == dest.GetChannels());

            numSrcSamples = src.AvailableSamples;
            psrc          = src.PtrBegin();
            pdest         = dest.PtrEnd(numSrcSamples);
            result        = _firFilter.Evaluate(pdest, psrc, numSrcSamples, numChannels);
            src.ReceiveSamples(result);
            dest.PutSamples(result);

            return(result);
        }