Пример #1
0
        /// <summary>
        /// Resamples input data to output data according to the configuration of the resampler.
        ///
        /// The input and output data is expected to be interleaved with the number of channels
        /// supplied in the constructor.
        ///
        /// All data sizes are byte sizes. E.g. to get the number of output samples, divide the
        /// output length by 4 (to get the number of float samples) and then by the number of
        /// channels to get the number of samples for a single channel.
        /// </summary>
        /// <param name="input">a byte array of interleaved float samples</param>
        /// <param name="inputOffset">the byte offset in the input array</param>
        /// <param name="inputLength">the byte length available in the input array</param>
        /// <param name="output">a byte array of interleaved float samples</param>
        /// <param name="outputOffset">the byte offset in the output array</param>
        /// <param name="outputLength">the byte length available in the output array</param>
        /// <param name="endOfInput">set to true if there is no more input data</param>
        /// <param name="inputLengthUsed">the number of bytes read</param>
        /// <param name="outputLengthGenerated">the number of bytes output</param>
        /// <exception cref="SoxrException">if an error happens during processing, see error message for details</exception>
        public void Process(byte[] input, int inputOffset, int inputLength,
                            byte[] output, int outputOffset, int outputLength,
                            bool endOfInput, out int inputLengthUsed, out int outputLengthGenerated)
        {
            // Only 32-bit float samples are supported
            int sampleBlockByteSize = 4 * channels;

            UIntPtr ilen  = new UIntPtr((uint)(inputLength / sampleBlockByteSize));
            UIntPtr olen  = new UIntPtr((uint)(outputLength / sampleBlockByteSize));
            UIntPtr idone = UIntPtr.Zero;
            UIntPtr odone = UIntPtr.Zero;

            if (outputLength == 0 && output.Length == 0)
            {
                output = new byte[1];
            }

            unsafe
            {
                fixed(byte *inputBytes = &input[inputOffset], outputBytes = &output[outputOffset])
                {
                    SoxrError error = InteropWrapper.soxr_process(soxr,
                                                                  endOfInput ? null : inputBytes, ilen, out idone,
                                                                  outputBytes, olen, out odone);

                    if (error != SoxrError.Zero)
                    {
                        throw new SoxrException("Processing failed: " + GetError(error));
                    }
                }
            }

            inputLengthUsed       = (int)(idone.ToUInt32() * sampleBlockByteSize);
            outputLengthGenerated = (int)(odone.ToUInt32() * sampleBlockByteSize);
        }
Пример #2
0
        /// <summary>
        /// Creates a new resampler with the supplied quality parameters.
        ///
        /// Can be used to create a variable-rate resampler by supplying SOXR_HQ as recipe
        /// and SOXR_VR as flag. For a variable resampler, inputRate/outputRate must equate
        /// to the maximum IO ratio that will be set by calling SetRatio. To set the initial
        /// ratio, call SetRatio with a transitionLength of 0 on the created instance.
        /// </summary>
        /// <param name="inputRate"></param>
        /// <param name="outputRate"></param>
        /// <param name="channels"></param>
        /// <param name="qualityRecipe"></param>
        /// <param name="qualityFlags"></param>
        /// <exception cref="SoxrException">when parameters are incorrect; see error message for details</exception>
        public SoxResampler(double inputRate, double outputRate, int channels,
                            QualityRecipe qualityRecipe, QualityFlags qualityFlags)
        {
            if (inputRate <= 0 || outputRate <= 0 || channels <= 0)
            {
                throw new SoxrException("one or more parameters are invalid (zero or negative)");
            }

            SoxrError error = SoxrError.Zero;

            // Apply the default configuration as per soxr.c
            InteropWrapper.SoxrIoSpec      ioSpec = InteropWrapper.soxr_io_spec(Datatype.SOXR_FLOAT32_I, Datatype.SOXR_FLOAT32_I);
            InteropWrapper.SoxrQualitySpec qSpec  = InteropWrapper.soxr_quality_spec(qualityRecipe, qualityFlags);
            InteropWrapper.SoxrRuntimeSpec rtSpec = InteropWrapper.soxr_runtime_spec(1);

            if (qualityFlags == QualityFlags.SOXR_VR)
            {
                if (qualityRecipe != QualityRecipe.SOXR_HQ)
                {
                    throw new SoxrException("Invalid parameters: variable rate resampling only works with the HQ recipe");
                }
                variableRate = true;
                maxRatio     = inputRate / outputRate;
            }

            soxr = InteropWrapper.soxr_create(inputRate, outputRate, (uint)channels,
                                              out error, ref ioSpec, ref qSpec, ref rtSpec);

            if (error != SoxrError.Zero)
            {
                throw new SoxrException(GetError(error));
            }

            this.channels = channels;
        }
Пример #3
0
        /// <summary>
        /// Clear internal state (e.g. buffered data) for a fresh resampling session,
        /// but keeping the same configuration.
        ///
        /// Warning: Clearing clears too much of the internal state, which seems to be
        /// a bug: http://sourceforge.net/p/soxr/discussion/general/thread/15725968/
        /// In variable rate mode, clearing works if the ratio is set afterwards. Without
        /// setting the rate it is zero, leading to an exception at the next Process call.
        /// In fixed rate mode, a new resampler should be instantiated instead of clearing,
        /// because this class does not permit setting the ratio in fixed mode.
        /// </summary>
        /// <exception cref="SoxrException">when clearing fails, see error message for details</exception>
        public void Clear()
        {
            SoxrError error = InteropWrapper.soxr_clear(soxr);

            if (error != SoxrError.Zero)
            {
                throw new SoxrException("Cannot clear state: " + GetError(error));
            }
        }
Пример #4
0
 /// <summary>
 /// Deletes the current resampler instance and frees its memory.
 /// To be called on destruction.
 /// </summary>
 private void Delete()
 {
     // Check if an instance is existing and only delete it if this is the case, avoiding
     // an exception if called multiple times (i.e. by Dispose and the destructor).
     if (soxr != SoxrInstance.Zero)
     {
         InteropWrapper.soxr_delete(soxr);
         soxr = SoxrInstance.Zero;
     }
 }
Пример #5
0
        /// <summary>
        /// Transitions to a new resampling ratio for variable-rate resampling over the given length.
        /// Set the length to 0 for an instant change.
        /// The ratio is the factor that the input rate must be multiplied with to get the output rate.
        /// </summary>
        /// <param name="ratio">the new resampling ratio</param>
        /// <param name="transitionLength">the length over which to linearly transition to the new ratio</param>
        /// <exception cref="SoxrException">when the resampler is not configured for variable-rate resampling</exception>
        public void SetRatio(double ratio, int transitionLength)
        {
            if (!variableRate)
            {
                throw new SoxrException("Illegal call: set_io_ratio only works in variable-rate resampling mode");
            }
            else if (ratio > maxRatio)
            {
                throw new SoxrException("Ratio exceeds max bound specified in constructor");
            }

            SoxrError error = InteropWrapper.soxr_set_io_ratio(soxr, 1.0 / ratio, new UIntPtr((uint)transitionLength));

            if (error != SoxrError.Zero)
            {
                throw new SoxrException("Error changing IO ratio: " + GetError(error));
            }
        }
Пример #6
0
        /// <summary>
        /// Returns the most recent error message.
        /// </summary>
        public string GetError()
        {
            SoxrError ptr = InteropWrapper.soxr_error(soxr);

            return(GetError(ptr));
        }
Пример #7
0
 public double GetOutputDelay()
 {
     return(InteropWrapper.soxr_delay(soxr));
 }