Example #1
0
        public void ProcessRateHalf()
        {
            var r = new SoxResampler(1.0d, 0.5d, 1);

            int inSize  = 4 * 10;
            int outSize = 12;

            var sampleDataIn          = new byte[inSize];
            var sampleDataOut         = new byte[outSize];
            int inputLengthUsed       = 0;
            int outputLengthGenerated = 0;

            int remainingIn = inSize;
            int totalIn = 0, totalOut = 0;

            do
            {
                r.Process(sampleDataIn, 0, remainingIn, sampleDataOut, 0, outSize,
                          remainingIn == 0, out inputLengthUsed, out outputLengthGenerated);
                totalIn     += inputLengthUsed;
                totalOut    += outputLengthGenerated;
                remainingIn -= inputLengthUsed;
            }while (inputLengthUsed > 0 || outputLengthGenerated > 0);

            Assert.AreEqual(inSize, totalIn, "not all data has been read");
            Assert.AreEqual(inSize / 2, totalOut, "not all data has been put out");
        }
Example #2
0
        /// <summary>
        /// Reads resampled data from the stream.
        /// </summary>
        /// <remarks>
        /// this function has been extensively analyzed and should not contain any bugs
        /// </remarks>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            // TODO debug this block (it might give problems if the sampling rate of the stream is changed
            //      dynamically - there might be source stream position issues (because of the SRC prereading,
            //      and there might be local buffering issues in terms of the buffer containing unfitting samples)
            if (properties.SampleRate == sourceStream.Properties.SampleRate)
            {
                int bytesRead = sourceStream.Read(buffer, offset, count);
                position += bytesRead;
                return(bytesRead);
            }

            int  inputLengthUsed, outputLengthGenerated;
            bool endOfStream = false;

            // loop while the sample rate converter consumes samples until it produces an output
            do
            {
                sourceBuffer.FillIfEmpty(sourceStream, count);
                // if the sourceBufferFillLevel is 0 at this position, the end of the source stream has been reached,
                // and endOfInput needs to be set to true in order to retrieve eventually buffered samples from
                // the sample rate converter
                // this is also the reason why the source stream's Read() method may be called multiple times although
                // it already signalled that it has reached the end of the stream
                endOfStream = sourceStream.Position >= sourceStream.Length && sourceBuffer.Empty;
                soxr.Process(sourceBuffer.Data, sourceBuffer.Offset, sourceBuffer.Count,
                             buffer, offset, count, endOfStream, out inputLengthUsed, out outputLengthGenerated);
                sourceBuffer.Read(inputLengthUsed);
            }while (inputLengthUsed > 0 && outputLengthGenerated == 0);

            position += outputLengthGenerated;

            // in some cases it can happen that the SRC returns more data than the stream length suggests,
            // this data is cut off here to avoid a stream position that is greater than the stream's length.
            // NOTE max observed overflow: 8 bytes (1 2ch 32bit sample)
            long length = Length;

            if (length == 0)
            {
                // This is a special case in which the length suddenly drops to zero, which can happen when reading
                // from a dynamic source (e.g. a mixer). In this case no valid overflow can be calculated, so just
                // return the read bytes.
                return(outputLengthGenerated);
            }
            else if (position > length)
            {
                int overflow = (int)(position - length);
                // The resampler is expected to return a few samples too much, and they can just be thrown away
                // http://comments.gmane.org/gmane.comp.audio.src.general/168
                Debug.WriteLine("ResamplingStream overflow: {0} bytes cut off", overflow);
                position -= overflow;
                return(outputLengthGenerated - overflow);
            }
            else if (position < length && inputLengthUsed == 0 && outputLengthGenerated == 0 && endOfStream)
            {
                int underflow = (int)(length - position);
                if (count < underflow)
                {
                    underflow = count;
                }
                Debug.WriteLine("ResamplingStream UNDERFLOW WARNING: {0} bytes added", underflow);
                position += underflow;
                Array.Clear(buffer, offset, underflow); // set bytes to zero
                return(underflow);
            }

            return(outputLengthGenerated);
        }