/// <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); } } }
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"); }
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"); }
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; } }
/// <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); } } }
/// <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; } } }