Sharing 2 arrays from CreateFileMappingW to C# using MemoryMappedFile - c#

I created a c++ project to test CreateFileMappingW, along with a struct where i create 2 arrays. I was able to read the first array in my C# project via MemoryMappedFile, but for some reason I couldn't get the values for the second array.
C++ code
#include <windows.h>
#include <stdio.h>
#include <iostream>
struct StructOfArray {
int array1[3];
int array2[2];
};
struct StructOfArray* datatoget;
HANDLE handle;
int main() {
handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(StructOfArray), L"DataSend");
datatoget = (struct StructOfArray*) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(StructOfArray));
datatoget->array1[0] = 10;
datatoget->array1[1] = 15;
datatoget->array1[2] = 20;
datatoget->array2[0] = 200;
datatoget->array2[1] = 203;
}
C# project:
int[] firstArray = new int[3];
int[] secondArray = new int[2];
string filePath = "DataSend";
mmf = MemoryMappedFile.OpenExisting(filePath);
mmfvs = mmf.CreateViewStream();
byte[] bPosition = new byte[1680];
mmfvs.Read(bPosition, 0, 1680);
Buffer.BlockCopy(bPosition, 0, firstArray, 0, bPosition.Length);//worked fine
Buffer.BlockCopy(bPosition, 0, secondtArray, 0, bPosition.Length);//did not work
for (int i = 0; i < 3; i++)
{
console.WritLine(firstArray[i])//worked fine
}
for (int i = 0; i < 2; i++)
{
console.WritLine(secondtArray[i])// not sure how to take second array
}

Use a MemoryMappedViewAccessor:
mmf = MemoryMappedFile.OpenExisting(filePath);
using (var accessor = mmf.CreateViewAccessor(0, Marshal.SizeOf(typeof(int)) * 5))
{
int intSize = Marshal.SizeOf(typeof(int));
//Read first array..
for (long i = 0; i < 3 * intSize; i += intSize)
{
int value = 0;
accessor.Read(i, out value);
firstArray[i] = value;
}
//Read second array..
for (long i = 0; i < 2 * intSize; i += intSize)
{
int value = 0;
accessor.Read(i, out value);
secondArrayArray[i] = value;
}
}
OR (your offsets are wrong.. you are literally calling BlockCopy with the exact same parameters but different arrays -- IE: same offsets: 0):
var intSize = Marshal.SizeOf(typeof(int));
//Copy first array..
Buffer.BlockCopy(bPosition, 0, firstArray, 0, intSize * firstArray.Length);
//Copy second array..
Buffer.BlockCopy(bPosition, intSize * firstArray.Length, secondArray, 0, intSize * secondArray.Length);

Related

C# How would I convert a group of integer variables to a byte array?

I have a group of integers that I want to send over a socket connection. What would be the cleanest way to convert the following variables into a byte array?
int var1 = 1;
int var2 = 2;
int var3 = 3;
Because I'm sending data via sockets, I would like to format the data using big-endianness. Thus for the three variables listed, I would want a 12 byte array such that
byte[0] = 0;
byte[1] = 0;
byte[2] = 0;
byte[3] = 1;
byte[4] = 0;
byte[5] = 0;
byte[6] = 0;
byte[7] = 2;
byte[8] = 0;
byte[9] = 0;
byte[10] = 0;
byte[11] = 3;
My search results are surprisingly coming up empty.
Edit: The suggested duplicate questions are different from what I'm asking. I do not have an "array of integers" or "a single integer" that I want to convert to a byte array. I have a group of individual array variables and am looking for the cleanest solution.
One way to do this would be to write a method that takes in a params int[] arg, which allows you to pass any number of int values to it.
Then you can create a byte[] based on the number of arguments, and populate it in a loop.
Since you want a Big-Endian result, we can use Array.Reverse to reverse the order of bytes returned from BitConverter.GetBytes for each argument, and then we can add each byte to the result array based on the index of the byte and the index of the argument:
public static byte[] GetBigEndianBytes(params int[] args)
{
var result = new byte[args.Length * sizeof(int)];
for (var argIndex = 0; argIndex < args.Length; argIndex++)
{
var bytes = BitConverter.GetBytes(args[argIndex]).Reverse().ToArray();
for (var byteIndex = 0; byteIndex < bytes.Length; byteIndex++)
{
result[byteIndex + argIndex * sizeof(int)] = bytes[byteIndex];
}
}
return result;
}
In use, this might look like:
private static void Main()
{
int var1 = 1;
int var2 = 2;
int var3 = 3;
var result = GetBigEndianBytes(var1, var2, var3);
// result = { 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3}

Buffer.BlockCopy Array 2d c++ to C# shared memory

I write a c++ program that send via memorystream a array multi to c# aplication. But i dont know hot to use BlockCopy to array multi:
this is my program c++ that send array multi
struct Pair {
std::pair<int, int> players;
};
struct Pair* p;
HANDLE handle;
float dataSend[70];
bool startShare()
{
try
{
handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(Pair), L"DataSend");
p = (struct Pair*) MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, sizeof(Pair));
return true;
}
catch (...)
{
return false;
}
}
for (int i = 0; i < 70; i++)
{
int r1 = rand() % 10 + 1;
int r2 = rand() % 10 + 1;
p->players = { r1,r2 };
}
example aoutput:
players 0 - [10][2]
players 1 - [100][22]
players 2 - [1][26]
players 3 - [50][211]
players 4 - [32][23]
my c# program read:
public static int[,] data = new int[70, 1];
public static MemoryMappedFile mmf;
public static MemoryMappedViewStream mmfvs;
static public bool MemOpen()
{
try
{
mmf = MemoryMappedFile.OpenExisting("DataSend");
mmfvs = mmf.CreateViewStream();
return true;
}
catch
{
return false;
}
}
// here need be somethings like byte[,] bPosition = new byte[70,1];
byte[] bPosition = new byte[70];
mmfvs.Read(bPosition, 0, 100);
Buffer.BlockCopy(bPosition, 0, data, 0, bPosition.Length);
for (int i = 0; i< data.Length; i++)
{
for(int j=0;j<1;j++)
{
Console.WriteLine(data[i][j]);
}
}
example receive :
data 0 - [10][2]
data 1 - [100][22]
data 2 - [1][26]
data 3 - [50][211]
data 4 - [32][23]
I write a c++ program that send via memorystream a array multi to c# aplication. But i dont know hot to use BlockCopy to array multi:
this is my program c++ that send array multi
Try following :
MemoryStream stream = new MemoryStream();
byte[] buffer = new byte[70 * 2 * sizeof(int)];
stream.Read(buffer, 0, 70 * 2 * sizeof(int));
for (int i = 0; i< 70; i++)
{
for (int j = 0; j < 2; j++)
{
Console.WriteLine(BitConverter.ToUInt32(buffer,(i * 2 * sizeof(int)) + (j * sizeof(int))));
}
}
IntPtr bufferPtr = Marshal.AllocHGlobal(BUFFER_SIZE);
//you need to allocate memory before calling the routing
byte[] buffer = new byte[BUFFER_SIZE];
Marshal.Copy(bufferPtr, buffer, 0, BUFFER_SIZE);
for (int i = 0; i < 70; i++)
{
for (int j = 0; j < 2; j++)
{
Console.WriteLine(BitConverter.ToUInt32(buffer, (i * 2 * sizeof(int)) + (j * sizeof(int))));
}
}
//method 2
int[,] array = new int[40, 2];
IntPtr bufferPtr2 = Marshal.AllocHGlobal(Marshal.SizeOf(array));
//call routine then you code below to fill managed memory.
Marshal.PtrToStructure(bufferPtr2, array);

Edit Wav File Samples for Increasing Amplitude using c#

I have the following c# code which reads a wave file into a byte array and then writes it into another array, creating a new wave file. I found it online and dont have much knowledge about it.
I want to change the values being written into the new array so that my amplitude is increased by let's say a value 'x' for the new wave file being generated.. Where and what should be the changes made?
private void ReadWavfiles(string fileName)
{
byte[] fa = File.ReadAllBytes(fileName);
int startByte = 0;
// look for data header
for (var x = 0; x < fa.Length; x++)
if (fa[x] == 'd' && fa[x + 1] == 'a' && fa[x + 2] == 't' && fa[x + 3] == 'a')
{
startByte = x + 8;
break;
}
var buff = new byte[fa.Length / 2];
var y = 0;
var length = fa.Length;
for (int s = startByte; s < length; s = s + 2)
buff[y++] = (byte)(fa[s + 1] * 0x100 + fa[s]);
write(buff, "D:\\as1.wav", "D:\\us1.wav");
WaveOut obj = new WaveOut();
obj.Init(new WaveFileReader("D:\\as1.wav"));
obj.Play();
}
private void write(byte[] buffer, string fileOut, string fileIn)
{
WaveFileReader reader = new WaveFileReader(fileIn);
int numChannels = reader.WaveFormat.Channels, sampleRate = reader.WaveFormat.SampleRate;
int BUFFER_SIZE = 1024 * 16;
using (WaveFileWriter writer = new WaveFileWriter(fileOut, new WaveFormat(sampleRate, 16, numChannels)))
{
int bytesRead;
while (true)
{
bytesRead = reader.Read(buffer, 0, BUFFER_SIZE);
if (bytesRead != 0)
writer.Write(buffer, 0, bytesRead);
else break;
}
writer.Close();
}
}

AccessViolationException with VST.NET and NAudio host application in C#

I'm trying to create a VSTstream class based on this thread: http://vstnet.codeplex.com/discussions/228692.
To record and playback the sound I'm using the AsioOut object that gives me available to IntPtr[] buffers type in the callback function OnAudioAvailable().
To do this I created the VSTstream class, taking example from the thread linked, appropriately modified to process directly the IntPtr[] buffers.
During the various processes of casting, however, it gives me an error of "AccessViolationException", probably due to the casting wrong.
I'm testing the VSTstream class opening the Jacobi.Vst.Samples.Delay.dll
EDIT: The error occurs on this line:
Marshal.Copy(sourceBuffer[1], rightBuf, 0, sampleCount/channels);
Does anyone know what I did wrong? If you need additional information or code I'm available.
Thanks to all.
OnAudioAvailable():
private void OnAudioAvailable(object sender, AsioAudioAvailableEventArgs e)
{
//No Effect
for (int i = 0; i < e.InputBuffers.Length; i++)
{
MoveMemory(e.OutputBuffers[i], e.InputBuffers[i], e.SamplesPerBuffer * e.InputBuffers.Length * 2);
}
//Effect
if (Parametri.effetto)
{
//Accendo i plugin
for (int i = 0; i < plugins.Count; i++)
{
plugins[i].MainsChanged(true);
plugins[i].StartProcess();
}
//Processo i sample
vstStream.ProcessSample(e.OutputBuffers, 0, e.SamplesPerBuffer * e.InputBuffers.Length * 2, e.InputBuffers);
//Spengo i plugin
for (int i = 0; i < plugins.Count; i++)
{
plugins[i].StopProcess();
plugins[i].MainsChanged(false);
}
}
e.WrittenToOutputBuffers = true;
}
VSTstream class:
class VSTstream
{
public List<IVstPluginCommandStub> plugins;
VstAudioBufferManager vstBufManIn, vstBufManOut;
private VstAudioBuffer[] vstBufIn = null;
private VstAudioBuffer[] vstBufOut = null;
private int sampleRate, channels, blockSize;
private float[] leftBuf, rightBuf;
public VSTstream(int sampleRate, int channels, int blockSize, List<IVstPluginCommandStub> plugins)
{
this.plugins = plugins;
this.sampleRate = sampleRate;
this.channels = channels;
this.blockSize = blockSize;
plugins[0].SetBlockSize(blockSize);
plugins[0].SetSampleRate((float)sampleRate);
vstBufManIn = new VstAudioBufferManager(channels, blockSize); //*channels
vstBufManOut = new VstAudioBufferManager(channels, blockSize);
//vstBufIn = vstBufManIn.ToArray();
//vstBufOut = vstBufManOut.ToArray();
vstBufIn = vstBufManIn.Cast<VstAudioBuffer>().ToArray();
vstBufOut = vstBufManOut.Cast<VstAudioBuffer>().ToArray();
leftBuf = new float[(blockSize * 4)/channels];
rightBuf = new float[(blockSize * 4)/channels];
}
public int ProcessSample(IntPtr[] destBuffer, int offset, int sampleCount, IntPtr[] sourceBuffer)
{
//da IntPtr[L][R] a Lfloat[]+Rfloat[]
Marshal.Copy(sourceBuffer[0], leftBuf, 0, sampleCount/channels);// (/channels)
Marshal.Copy(sourceBuffer[1], rightBuf, 0, sampleCount/channels);
unsafe
{
fixed (float* Lfloat = &leftBuf[0])
{
fixed (float* Rfloat = &rightBuf[0])
{
for (int i = 0; i < sampleCount / channels; i++)
{
vstBufIn[0][i] = *(Lfloat + i);
vstBufIn[1][i] = *(Rfloat + i);
}
}
}
}
//Qui dovrà rimanere solo 'ProcessReplacing();'
//plugins[0].MainsChanged(true);
//plugins[0].StartProcess();
plugins[0].ProcessReplacing(vstBufIn, vstBufOut);
//plugins[0].StopProcess();
//plugins[0].MainsChanged(false);
unsafe
{
float* tmpBufL = ((IDirectBufferAccess32)vstBufOut[0]).Buffer;
float* tmpBufR = ((IDirectBufferAccess32)vstBufOut[1]).Buffer;
for (int i = 0; i < (sampleCount / channels); i++)
{
leftBuf[i] = *(tmpBufL + i);
rightBuf[i] = *(tmpBufR + i);
}
}
//da Lfloat[]+Rfloat[] a IntPtr[L][R]
Marshal.Copy(leftBuf, 0, destBuffer[0], sampleCount/channels);
Marshal.Copy(rightBuf, 0, destBuffer[1], sampleCount/channels);
return sampleCount;
}
}

Float to 16bit, Stereo. Improve?

So i am converting Float 32bit, to 16Bit in Stereo. And as i don´t fully understand it myself, it´s pretty much copy paste sadly.
But i wonder if it can be improved, in either quality or speed?
Not that any of them are terrible or anything.
void SendWaloop(object sender, NAudio.Wave.WaveInEventArgs e)
{
byte[] newArray16Bit = new byte[e.BytesRecorded / 2];
short two;
float value;
for (int i = 0, j = 0; i < e.BytesRecorded; i += 4, j += 2)
{
value = (BitConverter.ToSingle(e.Buffer, i));
two = (short)(value * short.MaxValue);
newArray16Bit[j] = (byte)(two & 0xFF);
newArray16Bit[j + 1] = (byte)((two >> 8) & 0xFF);
}
if (connect == true && MuteMic.Checked == false)
{
udpSend.Send(newArray16Bit, newArray16Bit.Length, otherPartyIP.Address.ToString(), 1500);
}
}
So well, it´s converting the buffer from 32bit to 16bit, and send´s it with UDP, nothing weird.
Though for me this looks very complex, but from what i understand, it´s just removing every 4 byte or something like that.
EDIT:
unsafe
{
byte[] newArray16Bit = new byte[e.BytesRecorded / 2];
fixed (byte* sourcePtr = e.Buffer)
fixed (byte* targetPtr = newArray16Bit)
{
float* sourceTyped = (float*)sourcePtr;
short* targetTyped = (short*)targetPtr;
int count = e.BytesRecorded / 4;
for (int i = 0; i < count; i++)
{
targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
}
}
if (connect == true && MuteMic.Checked == false)
{
udpSend.Send(newArray16Bit, newArray16Bit.Length, otherPartyIP.Address.ToString(), 1500);
}
}
}
It would need testing, but I would probably try with some unsafe:
fixed(byte* sourcePtr = e.Buffer)
fixed(byte* targetPtr = newArray16Bit)
{
float* sourceTyped = (float*)sourcePtr;
short* targetTyped = (short*)targetPtr;
int count = e.BytesRecorded / 4;
for(int i = 0 ; i < count ; i++)
{
targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
}
}
To show that working identically:
using System;
static class Program
{
static void Main()
{
byte[] raw1 = new byte[64 * 1024];
new Random(12345).NextBytes(raw1); // 64k of random data
var raw2 = (byte[])raw1.Clone(); // just to rule out corruption
var result1 = OriginalImplFromTopPost(raw1, raw1.Length - 20);
var result2 = MyImpl(raw2, raw2.Length - 20);
bool areSame = Convert.ToBase64String(result1) == Convert.ToBase64String(result2);
Console.WriteLine(areSame); // True
}
public static unsafe byte[] MyImpl(byte[] source, int byteCount)
{
byte[] newArray16Bit = new byte[byteCount / 2];
fixed (byte* sourcePtr = source)
fixed (byte* targetPtr = newArray16Bit)
{
float* sourceTyped = (float*)sourcePtr;
short* targetTyped = (short*)targetPtr;
int count = byteCount / 4;
for (int i = 0; i < count; i++)
{
targetTyped[i] = (short)(sourceTyped[i] * short.MaxValue);
}
}
return newArray16Bit;
}
public static byte[] OriginalImplFromTopPost(byte[] source, int byteCount)
{
byte[] newArray16Bit = new byte[byteCount / 2];
short two;
float value;
for (int i = 0, j = 0; i < byteCount; i += 4, j += 2)
{
value = (BitConverter.ToSingle(source, i));
two = (short)(value * short.MaxValue);
newArray16Bit[j] = (byte)(two & 0xFF);
newArray16Bit[j + 1] = (byte)((two >> 8) & 0xFF);
}
return newArray16Bit;
}
}

Categories