Example #1
0
        /// <summary>
        /// Overwrites a channel of a sample of the buffer.
        /// </summary>
        /// <param name="sample">A pointer to the first byte of the channel value to read from.</param>
        /// <param name="index">The index of the target sample to write to.</param>
        /// <param name="channel">The index of the channel to write to.</param>
        public unsafe void WriteChannel(byte *sample, int index, int channel)
        {
            if (mode != OperationMode.Convert)
            {
                int sampleStart = index * target.Format.Size + channel * target.Format.ChannelSize;

                fixed(byte *destPtr = target.RawData)
                {
                    MemoryOperations.Copy(destPtr + sampleStart, sample, target.Format.ChannelSize);
                }
            }
            else
            {
                // Read the sample to the buffer
                for (int j = 0; j < writeFormat.ChannelSize; j++)
                {
                    buffer[j] = sample[j];
                }

                fixed(byte *bufferPtr = buffer, destPtr = target.RawData)
                {
                    // Pass 1: Change the bit-depth
                    if (writeFormat.BitDepth != target.Format.BitDepth)
                    {
                        ChangeBitDepth(
                            bufferPtr,
                            1, // one channel
                            writeFormat.BitDepth,
                            target.Format.BitDepth
                            );
                    }

                    // Pass 2: Change the sign
                    if (shouldChangeSign)
                    {
                        if (shouldMakeSigned)
                        {
                            MakeSigned(bufferPtr, target.Format);
                        }
                        else
                        {
                            MakeUnsigned(bufferPtr, target.Format);
                        }
                    }

                    int sampleStart = index * target.Format.Size + channel * target.Format.ChannelSize;

                    MemoryOperations.Copy(destPtr + sampleStart, bufferPtr, target.Format.ChannelSize);
                }
            }
        }
Example #2
0
        private void TestByteArrayCopy(int size)
        {
            byte[] src = new byte[size];
            byte[] dst = new byte[size];

            mDebugger.Send($"Start Copy of {size} bytes");

            MemoryOperations.Fill(src, 42);

            mDebugger.Send("Copy Start");
            MemoryOperations.Copy(dst, src);
            mDebugger.Send("Copy End");

            Assert.AreEqual(src, dst, $"Copy failed Array src and dst with size {size} are not equals");

            mDebugger.Send("End");
        }
Example #3
0
        private void TestIntArrayCopy(int size)
        {
            int[] src = new int[size];
            int[] dst = new int[size];

            mDebugger.Send($"Start Copy of {size} integers");

            MemoryOperations.Fill(src, 42);

            mDebugger.Send("Copy Start");
            MemoryOperations.Copy(dst, src);
            mDebugger.Send("Copy End");

            Assert.IsTrue(AreArrayEquals(src, dst), $"Copy failed Array src and dst with size {size} are not equals");

            mDebugger.Send("End");
        }
Example #4
0
        private void HandleInterrupt(ref INTs.IRQContext aContext)
        {
            ushort sr = pTransferStatus.Word;

            if ((sr & IRQ_LVBCI) > 0)
            {
                // Last Valid Buffer interrupt
                pTransferStatus.Word = IRQ_LVBCI;
            }
            else if ((sr & IRQ_BCIS) > 0)
            {
                // Load a buffer ahead
                int next = lastValidIdx + 1;
                if (next >= BUFFER_COUNT)
                {
                    next -= BUFFER_COUNT;
                }

                BufferProvider.RequestBuffer(transferBuffer);

                fixed(byte *mainBufPtr = transferBuffer.RawData)
                {
                    MemoryOperations.Copy(
                        dest: bufferDescriptorList[next].pointer,
                        src: mainBufPtr,
                        size: bufferSizeBytes
                        );
                }

                // Set the index to the current one
                lastValidIdx++;
                if (lastValidIdx == BUFFER_COUNT)
                {
                    lastValidIdx = 0;
                }

                pLastValidEntry.Byte = lastValidIdx;
                pTransferStatus.Word = IRQ_BCIS;
            }
            else if ((sr & IRQ_FIFO_ERROR) > 0)
            {
                pTransferStatus.Word = IRQ_FIFO_ERROR;
            }
        }
Example #5
0
        /// <summary>
        /// Writes a sample to the buffer.
        /// </summary>
        /// <param name="sample">A pointer to the first byte of the sample write.</param>
        /// <param name="index">The index of the target sample to overwrite.</param>
        public unsafe void Write(byte *sample, int index)
        {
            if (mode == OperationMode.DirectCopy)
            {
                int sampleStart = index * target.Format.Size;

                fixed(byte *destPtr = target.RawData)
                {
                    MemoryOperations.Copy(destPtr + sampleStart, sample, target.Format.Size);
                }
            }
            else
            {
                // Read the sample to the buffer
                for (int j = 0; j < writeFormat.Size; j++)
                {
                    buffer[j] = sample[j];
                }

                // Pass 1: Upmix/downmix channels
                if (writeFormat.Channels < target.Format.Channels)
                {
                    UpmixChannels(
                        buffer,
                        writeFormat.Channels,
                        target.Format.Channels,
                        writeFormat
                        );
                }

                fixed(byte *bufferPtr = buffer, destPtr = target.RawData)
                {
                    // Pass 2: Change the bit-depth
                    if (writeFormat.BitDepth != target.Format.BitDepth)
                    {
                        ChangeBitDepth(
                            bufferPtr,
                            target.Format.Channels,
                            writeFormat.BitDepth,
                            target.Format.BitDepth
                            );
                    }

                    // Pass 3: Change the sign
                    if (shouldChangeSign)
                    {
                        if (shouldMakeSigned)
                        {
                            MakeSigned(bufferPtr, target.Format);
                        }
                        else
                        {
                            MakeUnsigned(bufferPtr, target.Format);
                        }
                    }

                    int sampleStart = index * target.Format.Size;

                    MemoryOperations.Copy(destPtr + sampleStart, bufferPtr, target.Format.Size);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Converts the specified samples to the specified target format.
        /// The specified buffer pointer must be large enough to hold both
        /// the input samples, and the converted output samples.
        /// </summary>
        protected static unsafe void ChangeBitDepth(byte *bufferPtr, byte channels, AudioBitDepth inputBitDepth, AudioBitDepth outputBitDepth)
        {
            // Convert the bit-depth
            //     We have to re-normalize the samples; from the source data type's min and max value,
            //     to the target data type's min and max values - this operation can be represented by
            //     the following formula:
            //        (value / max source data type value) * max target data type value
            //     For example, to convert a 16-bit sample 0x0E to a 32-bit sample:
            //        (14 / 32767) * 2147483647
            //     However, this approach, while the most obvious from a mathematical standpoint,
            //     uses floating-point math. This can be much slower than direct bit-manipulation.
            //     The code below will do the equivalent to the provided formula by using
            //     bit-manipulation operators, making the method much more performant.
            //
            //     By using bit-shifting, we do not have to change the sign of the samples
            //     which is useful for us as we convert the samples in several different passes.

            switch (inputBitDepth)
            {
            case AudioBitDepth.Bits8: {
                // 8 bit -> target bit depth
                byte[] samples = new byte[channels];

                fixed(byte *samplesPtr = samples)
                {
                    MemoryOperations.Copy(samplesPtr, bufferPtr, channels);
                    ChangeBitDepth(bufferPtr, outputBitDepth, channels, samplesPtr);
                }

                break;
            }

            case AudioBitDepth.Bits16: {
                // 16 bit -> target bit depth
                short[] samples = new short[channels];

                fixed(short *samplesPtr = samples)
                {
                    MemoryOperations.Copy((byte *)samplesPtr, bufferPtr, channels * sizeof(short));
                    ChangeBitDepth(bufferPtr, outputBitDepth, channels, samplesPtr);
                }

                break;
            }

            case AudioBitDepth.Bits24: {
                // 24 bit -> target bit depth
                int[] samples = new int[channels];

                for (int j = 0; j < channels; j++)
                {
                    samples[j] = ToInt24(bufferPtr, j * 3);
                }

                fixed(int *samplesPtr = samples)
                {
                    ChangeBitDepth24(bufferPtr, outputBitDepth, channels, samplesPtr);
                }

                break;
            }

            case AudioBitDepth.Bits32: {
                // 32 bit -> target bit depth
                int[] samples = new int[channels];

                fixed(int *samplesPtr = samples)
                {
                    MemoryOperations.Copy((byte *)samplesPtr, bufferPtr, channels * sizeof(int));
                    ChangeBitDepth(bufferPtr, outputBitDepth, channels, samplesPtr);
                }

                break;
            }
            }
        }