Пример #1
0
        /// <summary>
        /// Copies the interleaved channels of audio samples, in integer format.
        /// </summary>
        /// <remarks>
        /// The samples are signed and right-justified. Stereo samples are interleaved, beginning with the left
        /// channel.
        /// </remarks>
        /// <param name="destination">The destination.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ObjectDisposedException">This <see cref="SampleBuffer"/> has been disposed.</exception>
        /// <exception cref="ArgumentException"><paramref name="destination"/> is not long enough to store the samples.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bitsPerSample"/> is out of range.</exception>
        public void CopyToInterleaved(Span <int> destination, int bitsPerSample)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(GetType().ToString());
            }
            if (_buffer == null)
            {
                return;
            }

            if (destination.Length < Frames * Channels)
            {
                throw new ArgumentException("destination is not long enough to store the samples.",
                                            nameof(destination));
            }
            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample), "bitsPerSample is out of range.");
            }

            if (Channels == 1 || IsInterleaved)
            {
                SampleProcessor.Convert(_buffer.Memory.Span.Slice(0, Frames * Channels), destination, bitsPerSample);
            }
            else
            {
                Span <float> interleavedBuffer = stackalloc float[Frames * 2];
                SampleProcessor.Interleave(
                    _buffer.Memory.Span.Slice(0, Frames),
                    _buffer.Memory.Span.Slice(Frames, Frames),
                    interleavedBuffer);
                SampleProcessor.Convert(interleavedBuffer, destination, bitsPerSample);
            }
        }
Пример #2
0
        /// <summary>
        /// Copies both channels of audio samples in integer format.
        /// </summary>
        /// <remarks>
        /// The samples are floating-point values normalized within -1.0 and 1.0.
        /// </remarks>
        /// <param name="leftDestination">The destination for the left channel.</param>
        /// <param name="rightDestination">The destination for the right channel.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ObjectDisposedException">This <see cref="SampleBuffer"/> has been disposed.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the Channels property does not equal 2.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bitsPerSample"/> is out of range.</exception>
        public void CopyTo(Span <int> leftDestination, Span <int> rightDestination, int bitsPerSample)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(GetType().ToString());
            }
            if (_buffer == null)
            {
                return;
            }

            if (Channels != 2)
            {
                throw new InvalidOperationException("Not a 2-channel SampleBuffer.");
            }

            if (IsInterleaved)
            {
                Span <float> leftBuffer  = stackalloc float[Frames];
                Span <float> rightBuffer = stackalloc float[Frames];
                SampleProcessor.DeInterleave(_buffer.Memory.Span.Slice(0, Frames * 2), leftBuffer, rightBuffer);
                SampleProcessor.Convert(leftBuffer, leftDestination, bitsPerSample);
                SampleProcessor.Convert(rightBuffer, rightDestination, bitsPerSample);
            }
            else
            {
                SampleProcessor.Convert(_buffer.Memory.Span.Slice(0, Frames), leftDestination, bitsPerSample);
                SampleProcessor.Convert(_buffer.Memory.Span.Slice(Frames, Frames), rightDestination, bitsPerSample);
            }
        }
Пример #3
0
        /// <summary>
        /// Copies the interleaved channels of audio samples, in normalized floating-point format.
        /// </summary>
        /// <remarks>
        /// The samples are floating-point values normalized within -1.0 and 1.0. Stereo samples are interleaved,
        /// beginning with the left channel.
        /// </remarks>
        /// <param name="destination">The destination.</param>
        /// <exception cref="ObjectDisposedException">This <see cref="SampleBuffer"/> has been disposed.</exception>
        /// <exception cref="ArgumentException"><paramref name="destination"/> is not long enough to store the samples.
        /// </exception>
        public void CopyToInterleaved(Span <float> destination)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(GetType().ToString());
            }
            if (_buffer == null)
            {
                return;
            }

            if (destination.Length < Frames * Channels)
            {
                throw new ArgumentException("destination is not long enough to store the samples.",
                                            nameof(destination));
            }

            if (Channels == 1 || IsInterleaved)
            {
                _buffer.Memory.Span.Slice(0, Frames * Channels).CopyTo(destination);
            }
            else
            {
                SampleProcessor.Interleave(
                    _buffer.Memory.Span.Slice(0, Frames),
                    _buffer.Memory.Span.Slice(Frames, Frames),
                    destination);
            }
        }
Пример #4
0
        /// <summary>
        /// Copies both channels of audio samples in normalized floating-point format.
        /// </summary>
        /// <remarks>
        /// The samples are floating-point values normalized within -1.0 and 1.0.
        /// </remarks>
        /// <param name="leftDestination">The destination for the left channel.</param>
        /// <param name="rightDestination">The destination for the right channel.</param>
        /// <exception cref="ObjectDisposedException">This <see cref="SampleBuffer"/> has been disposed.</exception>
        /// <exception cref="InvalidOperationException">Thrown if the Channels property does not equal 2.</exception>
        public void CopyTo(Span <float> leftDestination, Span <float> rightDestination)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(GetType().ToString());
            }
            if (_buffer == null)
            {
                return;
            }

            if (Channels != 2)
            {
                throw new InvalidOperationException("Not a 2-channel SampleBuffer.");
            }

            if (IsInterleaved)
            {
                SampleProcessor.DeInterleave(
                    _buffer.Memory.Span.Slice(0, Frames * 2),
                    leftDestination,
                    rightDestination);
            }
            else
            {
                _buffer.Memory.Span.Slice(0, Frames).CopyTo(leftDestination);
                _buffer.Memory.Span.Slice(Frames, Frames).CopyTo(rightDestination);
            }
        }
Пример #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SampleBuffer"/> class using interleaved integer samples.
        /// </summary>
        /// <param name="interleavedSamples">The interleaved samples.</param>
        /// <param name="channels">The channels.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ArgumentException">Thrown if <paramref name="interleavedSamples"/> is not a multiple of
        /// channels.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="channels"/> or
        /// <paramref name="bitsPerSample"/> is out of range.</exception>
        public SampleBuffer(ReadOnlySpan <int> interleavedSamples, int channels, int bitsPerSample)
        {
            if (channels < 1 || channels > 2)
            {
                throw new ArgumentOutOfRangeException(nameof(channels),
                                                      $"{nameof(channels)} must be 1 or 2.");
            }
            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample),
                                                      $"{nameof(bitsPerSample)} is out of range.");
            }
            if (interleavedSamples.Length % channels != 0)
            {
                throw new ArgumentException($"{nameof(interleavedSamples)} has an invalid length.",
                                            nameof(interleavedSamples));
            }

            Channels = channels;
            Frames   = interleavedSamples.Length / channels;
            _buffer  = MemoryPool <float> .Shared.Rent(Frames *channels);

            if (channels > 1)
            {
                IsInterleaved = true;
            }

            // ReSharper disable once PossibleNullReferenceException
            SampleProcessor.Convert(interleavedSamples, _buffer.Memory.Span, bitsPerSample);
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SampleBuffer"/> class using interleaved integer samples, which
        /// are packed on the byte boundary according to <paramref name="bitsPerSample"/>.
        /// </summary>
        /// <param name="interleavedSamples">The interleaved samples.</param>
        /// <param name="channels">The # of channels.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ArgumentException">Thrown if <paramref name="interleavedSamples"/> is not a valid length.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="channels"/> or
        /// <paramref name="bitsPerSample"/> is out of range.</exception>
        public SampleBuffer(ReadOnlySpan <byte> interleavedSamples, int channels, int bitsPerSample)
        {
            if (channels < 1 || channels > 2)
            {
                throw new ArgumentOutOfRangeException(nameof(channels),
                                                      $"{nameof(channels)} must be 1 or 2.");
            }
            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample),
                                                      $"{nameof(bitsPerSample)} is out of range.");
            }
            var bytesPerSample = (int)Math.Ceiling(bitsPerSample / 8.0);

            if (interleavedSamples.Length % (channels * bytesPerSample) != 0)
            {
                throw new ArgumentException($"{nameof(interleavedSamples)} has an invalid length.",
                                            nameof(interleavedSamples));
            }

            Channels = channels;
            Frames   = interleavedSamples.Length / channels / bytesPerSample;
            _buffer  = MemoryPool <float> .Shared.Rent(Frames *channels);

            if (channels > 1)
            {
                IsInterleaved = true;
            }

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (bytesPerSample)
            {
            case 1:
                // ReSharper disable once PossibleNullReferenceException
                SampleProcessor.Convert(interleavedSamples, _buffer.Memory.Span, bitsPerSample);
                break;

            case 2:
                var interleavedInt16Samples = MemoryMarshal.Cast <byte, short>(interleavedSamples);
                // ReSharper disable once PossibleNullReferenceException
                SampleProcessor.Convert(interleavedInt16Samples, _buffer.Memory.Span, bitsPerSample);
                break;

            case 3:
                var interleavedInt24Samples = MemoryMarshal.Cast <byte, Int24>(interleavedSamples);
                // ReSharper disable once PossibleNullReferenceException
                SampleProcessor.Convert(interleavedInt24Samples, _buffer.Memory.Span, bitsPerSample);
                break;

            case 4:
                var interleavedInt32Samples = MemoryMarshal.Cast <byte, int>(interleavedSamples);
                // ReSharper disable once PossibleNullReferenceException
                SampleProcessor.Convert(interleavedInt32Samples, _buffer.Memory.Span, bitsPerSample);
                break;
            }
        }
Пример #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SampleBuffer"/> class for a single channel, using integer
        /// samples.
        /// </summary>
        /// <param name="monoSamples">The samples.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="bitsPerSample"/> is out of range.
        /// </exception>
        public SampleBuffer(ReadOnlySpan <int> monoSamples, int bitsPerSample)
        {
            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample),
                                                      $"{nameof(bitsPerSample)} is out of range.");
            }

            Channels = 1;
            Frames   = monoSamples.Length;
            _buffer  = MemoryPool <float> .Shared.Rent(Frames);

            // ReSharper disable once PossibleNullReferenceException
            SampleProcessor.Convert(monoSamples, _buffer.Memory.Span, bitsPerSample);
        }
Пример #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SampleBuffer"/> class for 2 channels, using integer samples.
        /// </summary>
        /// <param name="leftSamples">The left channel samples.</param>
        /// <param name="rightSamples">The right channel samples.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ArgumentException">Thrown if <paramref name="rightSamples"/> has a different length than
        /// <paramref name="leftSamples"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="bitsPerSample"/> is out of range.
        /// </exception>
        public SampleBuffer(ReadOnlySpan <int> leftSamples, ReadOnlySpan <int> rightSamples, int bitsPerSample)
        {
            if (leftSamples.Length != rightSamples.Length)
            {
                throw new ArgumentException(
                          $"{nameof(rightSamples)} does not match the length of {nameof(leftSamples)}", nameof(rightSamples));
            }
            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample),
                                                      $"{nameof(bitsPerSample)} is out of range.");
            }

            Channels = 2;
            Frames   = leftSamples.Length;
            _buffer  = MemoryPool <float> .Shared.Rent(Frames * 2);

            // ReSharper disable once PossibleNullReferenceException
            SampleProcessor.Convert(leftSamples, _buffer.Memory.Span.Slice(0, Frames), bitsPerSample);
            SampleProcessor.Convert(rightSamples, _buffer.Memory.Span.Slice(Frames), bitsPerSample);
        }
Пример #9
0
        /// <summary>
        /// Copies the interleaved channels of audio samples, in packed integer format.
        /// </summary>
        /// <remarks>
        /// The samples are stored as little-endian integers, aligned at the byte boundary. If
        /// <paramref name="bitsPerSample"/> is 8 or less, they are unsigned. Otherwise, they are signed. Stereo
        /// samples are interleaved, beginning with the left channel.
        /// </remarks>
        /// <param name="destination">The destination.</param>
        /// <param name="bitsPerSample">The # of bits per sample.</param>
        /// <exception cref="ObjectDisposedException">This <see cref="SampleBuffer"/> has been disposed.</exception>
        /// <exception cref="ArgumentException"><paramref name="destination"/> is not long enough to store the samples.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bitsPerSample"/> is out of range.</exception>
        public void CopyToInterleaved(Span <byte> destination, int bitsPerSample)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(GetType().ToString());
            }
            if (_buffer == null)
            {
                return;
            }

            if (bitsPerSample < 1 || bitsPerSample > 32)
            {
                throw new ArgumentOutOfRangeException(nameof(bitsPerSample), "bitsPerSample is out of range.");
            }
            var bytesPerSample = (int)Math.Ceiling(bitsPerSample / 8.0);

            if (destination.Length < Frames * Channels * bytesPerSample)
            {
                throw new ArgumentException("destination is not long enough to store the samples.",
                                            nameof(destination));
            }

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (bytesPerSample)
            {
            case 1:
                if (Channels == 1 || IsInterleaved)
                {
                    SampleProcessor.Convert(
                        _buffer.Memory.Span.Slice(0, Frames * Channels),
                        destination,
                        bitsPerSample);
                }
                else
                {
                    Span <float> interleavedBuffer = stackalloc float[Frames * 2];
                    SampleProcessor.Interleave(
                        _buffer.Memory.Span.Slice(0, Frames),
                        _buffer.Memory.Span.Slice(Frames, Frames),
                        interleavedBuffer);
                    SampleProcessor.Convert(interleavedBuffer, destination, bitsPerSample);
                }
                break;

            case 2:
                var int16Destination = MemoryMarshal.Cast <byte, short>(destination);
                if (Channels == 1 || IsInterleaved)
                {
                    SampleProcessor.Convert(
                        _buffer.Memory.Span.Slice(0, Frames * Channels),
                        int16Destination,
                        bitsPerSample);
                }
                else
                {
                    Span <float> interleavedBuffer = stackalloc float[Frames * 2];
                    SampleProcessor.Interleave(
                        _buffer.Memory.Span.Slice(0, Frames),
                        _buffer.Memory.Span.Slice(Frames, Frames),
                        interleavedBuffer);
                    SampleProcessor.Convert(interleavedBuffer, int16Destination, bitsPerSample);
                }
                break;

            case 3:
                var int24Destination = MemoryMarshal.Cast <byte, Int24>(destination);
                if (Channels == 1 || IsInterleaved)
                {
                    SampleProcessor.Convert(
                        _buffer.Memory.Span.Slice(0, Frames * Channels),
                        int24Destination,
                        bitsPerSample);
                }
                else
                {
                    Span <float> interleavedBuffer = stackalloc float[Frames * 2];
                    SampleProcessor.Interleave(
                        _buffer.Memory.Span.Slice(0, Frames),
                        _buffer.Memory.Span.Slice(Frames, Frames),
                        interleavedBuffer);
                    SampleProcessor.Convert(interleavedBuffer, int24Destination, bitsPerSample);
                }
                break;

            case 4:
                var int32Destination = MemoryMarshal.Cast <byte, int>(destination);
                if (Channels == 1 || IsInterleaved)
                {
                    SampleProcessor.Convert(
                        _buffer.Memory.Span.Slice(0, Frames * Channels),
                        int32Destination,
                        bitsPerSample);
                }
                else
                {
                    Span <float> interleavedBuffer = stackalloc float[Frames * 2];
                    SampleProcessor.Interleave(
                        _buffer.Memory.Span.Slice(0, Frames),
                        _buffer.Memory.Span.Slice(Frames, Frames),
                        interleavedBuffer);
                    SampleProcessor.Convert(interleavedBuffer, int32Destination, bitsPerSample);
                }
                break;
            }
        }