I have b1 and b2 which are all in byte, I am using serialport.write to send them separately. Can I send them at the same time? As in using one command instead of two. My existing code:
private void SConvert_Click(object sender, EventArgs e)
{
byte[] b1 = null, b2 = null;
string[] coords = textBox1.Text.Split('\n');
for (int i = 0; i <= coords.Length - 1; i++)
{
if (coords[i].Length > 0)
{
GetValue(coords[i], out b1, out b2);
}
if (serialPort.IsOpen)
{
serialPort.Write(b1, 0, 4);
serialPort.Write(b2, 0, 4);
}
}
}
private void GetValue(string strValue, out byte[] b1, out byte[] b2)
{
string S1, S2, S = strValue;
string[] x = S.Split(',');
string y = x[0].ToString();//{lat=-36.123333
string z = x[1].ToString();//lng=174.333333} // index outside bounds of the array
S1 = y.Substring(y.IndexOf('=') + 1);
string z1 = z.Replace("}", "0"); // replace } by 0 since do not know length of }
S2 = z1.Substring(z1.IndexOf('=') + 1);
float f1 = float.Parse(S1), f2 = float.Parse(S2);
b1 = System.BitConverter.GetBytes(f1);
b2 = System.BitConverter.GetBytes(f2);
}
Instead of
serialPort.Write(b1, 0, 4);
serialPort.Write(b2, 0, 4);
you could do just
serialPort.Write(b1.Concat(b2).ToArray(), 0, b1.Length + b2.Length);
I assume you'd like to send two byte arrays at once. Solution is simple: merge them, and send it.
byte[] buf = new byte[b1.Length + b2.Length];
Array.Copy(buf, 0, b1);
Array.Copy(buf, 0, b2, b1.Length, b2.Length);
serialPort.Write(buf, 0, buf.Length);
See also: Merging two arrays in .NET
Related
Destination array was not long enough. Check destIndex and length, and the array's lower bounds <- what is this error???
how can i fix it?
This error occur after i add Array.Copy
i have no idea....
static byte[] sendData = new byte[5];
static int sendCount = 0;
try
{
Console.Write("->");
string text = Console.ReadLine();
foreach(string s in text.Split(' '))
{
if(null != s && "" != s)
{
sendData[sendCount++] = Convert.ToByte(s, 16);
}
}
byte[] LRC = new byte[1];
LRC = BitConverter.GetBytes((Int16)sendData[2] ^ sendData[3] ^ sendData[4]);
byte[] hexData = new byte[sendData.Length + LRC.Length];
Array.Copy(sendData, 0, hexData, 0, 5); // <-- error occurs this point
Array.Copy(LRC, 0, hexData, hexData.Length + 1, 1);//<-or this point
port.Write(hexData, 0, hexData.Length);
Array.Clear(sendData, 0, sendData.Length);
Array.Clear(LRC, 0, LRC.Length);
Array.Clear(hexData, 0, hexData.Length);
sendCount = 0;
}
catch(Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Check Data");
}
Answering on concrete question, the definition of the copy method:
public static void Copy (
Array sourceArray, int sourceIndex,
Array destinationArray, int destinationIndex,
int length);
In your case
Array.Copy(LRC, 0, hexData, hexData.Length + 1, 1);
So, you are trying to copy bytes to array hexData to the index hexData.Length + 1 that is basically out of its boundaries.
I have no idea what you are trying to implement, but you should make sure that destination index during the copy is less or equal than hexData.Length - 1 (also taking into account the length).
I want to convert a string to byte and output it as byte array.
example: string: 3074 output: 0C02
private static byte[] ConvertHexToBytes(string input)
{
var result = new byte[(input.Length + 1) / 2];
var offset = 0;
if (input.Length % 2 == 1)
{
result[0] = (byte)Convert.ToUInt32(input[0] + "", 16);
offset = 1;
}
for (int i = 0; i < input.Length / 2; i++)
{
result[i + offset] = (byte)Convert.ToUInt32(input.Substring(i * 2 + offset, 2), 16);
}
return result;
}
private static void SetValue(string input)
{
byte[] port = ConvertHexToBytes(input);
byte[] port = new byte[] { byte.Parse("" + port[0]), byte.Parse("" + port[1]) };
}
I am getting 3074 instead of the 0C02.
Just figured it out, here is my code
private static void SetValue(string input)
{
byte[] port = BitConverter.GetBytes(int.Parse(input));
byte[] res= new byte[] { port[1], port[0] };
}
It seems you're working with int, not string ("I want to convert a string to byte...")
int input = 3074; // 00 00 0C 02
And you want to trim leading zeroes and get "0C02" string; you can do it with a help of Linq:
byte[] result =
(BitConverter.IsLittleEndian
? BitConverter.GetBytes(input).Reverse()
: BitConverter.GetBytes(input))
.SkipWhile(b => b == 0)
.DefaultIfEmpty() // we don't want trim all in case of input == 0
.ToArray();
Test:
// "0C02"
Console.WriteLine(string.Concat(result.Select(b => b.ToString("X2"))));
Combining it all into the proposed method:
private static void SetValue(string input) {
byte[] res =
(BitConverter.IsLittleEndian
? BitConverter.GetBytes(int.Parse(input)).Reverse()
: BitConverter.GetBytes(int.Parse(input)))
.SkipWhile(b => b == 0)
.DefaultIfEmpty() // we don't want trim all in case of input == 0
.ToArray();
// Console.WriteLine(string.Concat(res.Select(b => b.ToString("X2"))));
//TODO: relevant code here
}
A solution which will work independent of the endianess of your system architecture which will make things more portable:
byte[] bytes = BitConverter.GetBytes(input);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
Console.WriteLine("byte array: " +
BitConverter.ToString(bytes).Replace("-", string.Empty));
Below is an interview question about using recursion to add two arrays.
I can't figure it out though because it does not seem to allow any kind of index to keep track of where you are, I have been down a few roads - trying to test for null / default values in the array but because it is a byte[] type nothing worked.
Any help would be great thanks - this is not a homework question.
public AddResult UsingARecursiveAlgorithm_ValuesAreAdded(byte[] a, byte[] b)
{
var result = AddRecursive(a, b);
// Assert
return new AddResult(a, b, result);
}
e.g.
Input : { 1, 1, 1 }, { 1, 1, 1 }
Result: { 2, 2, 2 }
Input : { 1, 1, 255 }, { 0, 0, 1 }
Result: { 1, 2, 0 }
Conditions:
a & b are never null, and are always of the same length.
The algorithm should be non destructive to the inputs.
Edit: the second result is incorrect. It should be { 1,1,0 } -that's the way it was presented though.
private int carry = 0;
public byte[] AddRecursive(byte[] a, byte[] b)
{
//Start from bottom of the byte[] array
a = a.Reverse().ToArray();
b = b.Reverse().ToArray();
if (a.Length == 0) return new byte[] { };
int tempresult = a[0] + b[0] + carry;
byte[] z = new byte[]
{ (byte)(tempresult) };
carry = tempresult / (byte.MaxValue + 1);
return z.Concat(AddRecursive(a.Skip(1).ToArray(), b.Skip(1).ToArray())).ToArray();
}
//Test//
[Test]
public void Add_UsingARecursiveAlgorithm_ValuesAreAdded()
{
//First Test
byte[] expectedResult = addthisaddthat.AddRecursive(new byte[] { 1, 1, 1 }, new byte[] { 1, 1, 1 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 2, 2, 2 }));
//Sec Test
expectedResult = addthisaddthat.AddRecursive(new byte[] { 1, 1, 255 }, new byte[] { 0, 0, 1 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 1, 2, 0 }));
//Third Test
expectedResult = addthisaddthat.AddRecursive(new byte[] { 255, 255, 255 }, new byte[] { 255, 255, 255 }).Reverse().ToArray();
Assert.That(expectedResult, Is.EqualTo(new byte[] { 255, 255, 254 }));
}
Ok here is some rather "ugly" code that does what you want. I tried to write it for clarity rather than brevity:
static byte[] AddArray(byte[] ary1, byte[] ary2) {
System.Diagnostics.Debug.Assert(ary1.Length == ary2.Length);
if ((ary1 == null) || (ary2 == null)) {
throw new ArgumentException("Empty or null array");
}
// sum the last element
var ix = ary1.Length - 1;
var sum = (ary1[ix] + ary2[ix]);
if (sum > byte.MaxValue) {
if (ix == 0) {
throw new ArgumentException("Overflow");
}
// Add carry by recursing on ary1
var carry = (byte) (sum - byte.MaxValue);
var carryAry = new byte[ary1.Length];
carryAry[ix - 1] = carry;
ary1 = AddArray(ary1, carryAry);
}
if ((ary1.Length == 1) || (ary2.Length == 1)) {
return new byte[] { (byte) sum }; // end recursion
}
// create the remainder, elements from 0 it (len-1)
var ary1Remainder = new byte[ary1.Length - 1];
var ary2Remainder = new byte[ary2.Length - 1];
Array.Copy(ary1, 0, ary1Remainder, 0, ary1.Length - 1);
Array.Copy(ary2, 0, ary2Remainder, 0, ary2.Length - 1);
// recurse
var remainder = AddArray(ary1Remainder, ary2Remainder);
// build return array (using linq Concat)
var rv = (remainder.Concat(new byte[] { (byte) sum }));
return rv.ToArray(); // return as an array
}
This would be cleaner without all the casting and ToArray required because the values are byte[] and not IEnumerable<int>, but:
private byte[] AddRecursive(byte[] a, byte[] b) {
if (a.Length == 0) return new byte[]{};
return
new byte[] { (byte)(a[0] + b[0]) }.Concat(
AddRecursive(a.Skip(1).ToArray(), b.Skip(1).ToArray())
).ToArray();
}
Maybe your interviewer had something like this in mind:
using System;
using System.Linq;
public class Program
{
public static byte[] Add(byte[] a, byte[] b, int index = -1)
{
if (index < 0)
{
return Add((byte[])a.Clone(), b, 0);
}
if (index < a.Length)
{
Add(a, b, index + 1);
a[index] += b[index];
}
return a;
}
public static void Main(string[] args)
{
var r1 = Add(new byte[] { 1, 1, 1 }, new byte[] { 1, 1, 1 });
var r2 = Add(new byte[] { 1, 1, 255 }, new byte[] { 0, 0, 1 });
var r3 = Add(new byte[] { 0, 100, 200 }, new byte[] { 3, 2, 1 });
// Outputs: 2, 2, 2
Console.WriteLine(string.Join(", ", r1.Select(n => "" + n).ToArray()));
// Outputs: 1, 1, 0
Console.WriteLine(string.Join(", ", r2.Select(n => "" + n).ToArray()));
// Outputs: 3, 102, 201
Console.WriteLine(string.Join(", ", r3.Select(n => "" + n).ToArray()));
}
}
https://dotnetfiddle.net/UqSQb3
Note this (only partial) solution doesn't handle the carry on byte overflows, though.
'Hope this helps,
My game has two clients & one server. client1 sends data to client2 by placing data on server & client2 retrieving from server. Similarly client2 sends data to client1 via server.
When I send data from Client1 to client2 everything is fine but when client2 sends data to client1 it receives irrelevant data.
What I believe is during first communication, whatever data is on server is not clearing & so while Clien2 is sending data back to client1, the data overlaps with the data on server & sends irrelevant data.
I am using same code for all client but multiple instances of client code.
Below is the code I am using :-
private void OnKeyDown1(object sender, KeyEventArgs e)
{
tbxno = 1;
if (e.Key == Key.Enter || e.Key == Key.Return)
{
// Disable further edit on textbox
playerTbx1.IsReadOnly = true;
// Compare answers entered by user
char[] letters = new char[playerTbx1.Text.Length];
StringReader sr = new StringReader(playerTbx1.Text);
sr.Read(letters, 0, playerTbx1.Text.Length);
int c = 0;
Console.WriteLine(word[i - 1]);
string label = MainWordLabel.Content.ToString();
while (label.Contains(letters[c].ToString()))
{
c++;
if (c == letters.Length)
break;
}
int count = c;
MessageBox.Show("No. of words matching : " + c);
// Score calculation
score += c * 5;
PlayerScoreTbx.Text = score.ToString();
//Send data to server
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(playerTbx1.Text);
byte[] length = new byte[2];
length[0] = (byte)(playerTbx1.Text.Length % 256);
length[1] = (byte)(playerTbx1.Text.Length / 256);
byte[] usernameBuffer = System.Text.Encoding.ASCII.GetBytes(Username_Textbox.Text);
byte[] unamelength = new byte[2];
unamelength[0] = (byte)(Username_Textbox.Text.Length % 256);
unamelength[1] = (byte)(Username_Textbox.Text.Length / 256);
byte[] scoreBuffer = System.Text.Encoding.ASCII.GetBytes(PlayerScoreTbx.Text);
byte[] scoreLength = new byte[2];
scoreLength[0] = (byte)(PlayerScoreTbx.Text.Length % 256);
scoreLength[1] = (byte)(PlayerScoreTbx.Text.Length / 256);
byte[] tno = new byte[1];
tno[0] = (byte)tbxno;
tcpClient.Client.Send(length);
tcpClient.Client.Send(buffer);
tcpClient.Client.Send(unamelength);
tcpClient.Client.Send(usernameBuffer);
tcpClient.Client.Send(scoreLength);
tcpClient.Client.Send(scoreBuffer);
tcpClient.Client.Send(tno);
}
}
while recieving data back from server :-
void getdata()
{
while (tcpsocket.Connected)
{
NetworkStream stream = tcpClient.GetStream();
byte[] userName = new byte[1024];
byte[] buffer = new byte[256];
byte[] length = new byte[2];
byte[] userlength = new byte[2];
byte[] scoreBuffer = new byte[1024];
byte[] scoreLength = new byte[2];
// read length of username
int readUserlength = stream.Read(userlength, 0, 2);
int userLength = userlength[0] + (userlength[1] * 256);
// read username
stream.Read(userName, 0, userLength);
string userReceived = System.Text.Encoding.ASCII.GetString(userName, 0, userLength);
// read length of score
int readUScore = stream.Read(scoreLength, 0, 2);
int lengthOfScore = scoreLength[0] + (scoreLength[1] * 256);
// read score
stream.Read(scoreBuffer, 0, lengthOfScore);
string score = System.Text.Encoding.ASCII.GetString(scoreBuffer, 0, lengthOfScore);
// check if the same client is not receiving data
this.Dispatcher.Invoke(() =>
{
if (userReceived.Equals(Username_Textbox.Text) == false)
{
int readlength = stream.Read(length, 0, 2);
int dataLength = length[0] + (length[1] * 256);
stream.Read(buffer, 0, dataLength);
string data = System.Text.Encoding.ASCII.GetString(buffer,0,dataLength);
byte[] tbox = new byte[1];
stream.Read(tbox, 0, 1);
int count = tbox[0];
this.Dispatcher.Invoke(() =>
{
OppTbx1.Text = data;
OppScoreTbx.Text = score;
});
}
});
}
}
Codes on Server :-
public delegate void Disconnected(ClientManager item);
public delegate void MessageReceived(string item, string username, string score, byte textbox);
public class ClientManager
{
public Socket socket { get; set; }
private NetworkStream networkStream;
public event Disconnected OnDisconnected;
public event MessageReceived OnMessage;
public ClientManager(Socket clientSocket)
{
this.socket = clientSocket;
this.networkStream = new NetworkStream(this.socket);
Task.Factory.StartNew(() =>
{
while (socket.Connected)
{
// TextBox Data
byte[] dataBuffer = new byte[1024];
byte[] length = new byte[2];
int readlength = this.networkStream.Read(length, 0, 2);
if (readlength == 0)
break;
int dataLength = length[0] + (length[1] * 256);
int readDataBytes = this.networkStream.Read(dataBuffer, 0, dataLength);
if (readDataBytes == 0)
break;
string data = System.Text.Encoding.ASCII.GetString(dataBuffer, 0, dataLength);
// Username Information
byte[] username = new byte[1024];
byte[] userlength = new byte[2];
int readLengthbytes = this.networkStream.Read(userlength, 0, 2);
if (readLengthbytes == 0)
break;
int userLength = userlength[0] + (userlength[1] * 256);
int readUsername = this.networkStream.Read(username, 0, userLength);
if (readUsername == 0)
break;
string usernameString = System.Text.Encoding.ASCII.GetString(username, 0, userLength);
// score
byte[] scoreBuffer = new byte[1024];
byte[] scorLength = new byte[2];
int readscorelength = this.networkStream.Read(scorLength, 0, 2);
if (readscorelength == 0)
break;
int lenghtOfScore = scorLength[0] + (scorLength[1] * 256);
int readscore = this.networkStream.Read(scoreBuffer, 0, lenghtOfScore);
if (readscore == 0)
break;
string score = System.Text.Encoding.ASCII.GetString(scoreBuffer, 0, lenghtOfScore);
byte[] tbx = new byte[1];
this.networkStream.Read(tbx,0,1);
//send data,sername & score
OnMessage(data, usernameString, score, tbx[0]);
}
//socket.Disconnect(false);
if (OnDisconnected != null)
OnDisconnected(this);
});
}
}
}
sending to client back :-
void SendChatMessage(string message, string username,string score, byte tbox)
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
byte[] length = new byte[2];
length[0] = (byte)(message.Length % 256);
length[1] = (byte)(message.Length / 256);
byte[] usernameBuffer = System.Text.Encoding.ASCII.GetBytes(username);
byte[] userlength = new byte[2];
userlength[0] = (byte)(username.Length % 256);
userlength[1] = (byte)(username.Length / 256);
byte[] scoreBuffer = System.Text.Encoding.ASCII.GetBytes(score);
byte[] scoreLength = new byte[2];
scoreLength[0] = (byte)(score.Length % 256);
scoreLength[1] = (byte)(score.Length / 256);
byte[] tbxCount = new byte[1];
tbxCount[0] = tbox;
Task.Factory.StartNew(() =>
{
lock (tcpClients)
{
foreach (var item in tcpClients)
{
try
{
item.socket.Send(userlength);
item.socket.Send(usernameBuffer);
item.socket.Send(scoreLength);
item.socket.Send(scoreBuffer);
item.socket.Send(length);
item.socket.Send(data);
item.socket.Send(tbxCount);
}
catch (Exception ex)
{
ex.GetBaseException();
}
}
}
});
}
}
As invarably seen in such questions, you are ignoring the count returned by Read() and assuming that the read filled the buffer. It isn't specified to do that, or to transfer any more than one byte: zero bytes in non-blocking mode. You need to loop until you have all the data expected or required.
I am trying to encode a recorded audio using Nspeex and then transfer it over internet and decode on the other end. I am doing all this in Windows Phone 7/8. To encode and decode I am using following code. But while decoding I am not getting the result back correctly which I can play again. Can anyone provide me with encoding and decoding code which runs on WP7/8 recorded audio:
private static Microphone mic = Microphone.Default;
private static byte[] EncodeSpeech(byte[] buf, int len)
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexEncoder encoder = new SpeexEncoder(mode);
// set encoding quality to lowest (which will generate the smallest size in the fastest time)
encoder.Quality = 1;
int inDataSize = len / 2;
// convert to short array
short[] data = new short[inDataSize];
int sampleIndex = 0;
for (int index = 0; index < len; index += 2, sampleIndex++)
{
data[sampleIndex] = BitConverter.ToInt16(buf, index);
}
// note: the number of samples per frame must be a multiple of encoder.FrameSize
inDataSize = inDataSize - inDataSize % encoder.FrameSize;
var encodedData = new byte[len];
int encodedBytes = encoder.Encode(data, 0, inDataSize, encodedData, 0, len);
if (encodedBytes != 0)
{
// each chunk is laid out as follows:
// | 4-byte total chunk size | 4-byte encoded buffer size | <encoded-bytes> |
byte[] inDataSizeBuf = BitConverter.GetBytes(inDataSize);
byte[] sizeBuf = BitConverter.GetBytes(encodedBytes + inDataSizeBuf.Length);
byte[] returnBuf = new byte[encodedBytes + sizeBuf.Length + inDataSizeBuf.Length];
sizeBuf.CopyTo(returnBuf, 0);
inDataSizeBuf.CopyTo(returnBuf, sizeBuf.Length);
Array.Copy(encodedData, 0, returnBuf, sizeBuf.Length + inDataSizeBuf.Length, encodedBytes);
return returnBuf;
}
else
return buf;
}
private byte[] DecodeSpeech(byte[] buf)
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexDecoder decoder = new SpeexDecoder(mode);
byte[] inDataSizeBuf = new byte[4];
byte[] sizeBuf = new byte[4];
byte[] encodedBuf = new byte[buf.Length - 8];
Array.Copy(buf, 0, sizeBuf, 0, 4);
Array.Copy(buf, 4, inDataSizeBuf, 0, 4);
Array.Copy(buf, 8, encodedBuf, 0, buf.Length - 8);
int inDataSize = BitConverter.ToInt32(inDataSizeBuf, 0);
int size = BitConverter.ToInt32(sizeBuf, 0);
short[] decodedBuf = new short[inDataSize];
int decodedSize = decoder.Decode(encodedBuf, 0, encodedBuf.Length, decodedBuf, 0, false);
byte[] returnBuf = new byte[inDataSize * 2];
for (int index = 0; index < decodedBuf.Length; index++)
{
byte[] temp = BitConverter.GetBytes(decodedBuf[index]);
Array.Copy(temp, 0, returnBuf, index * 2, 2);
}
return returnBuf;
}
private static BandMode GetBandMode(int sampleRate)
{
if (sampleRate <= 8000)
return BandMode.Narrow;
if (sampleRate <= 16000)
return BandMode.Wide;
return BandMode.UltraWide;
}
I think your problem may be that you are newing up a new SpeexEncoder every time you want to encode audio. You should try making that a member for your class and re-use it.
I looked at the code for Nspeex I noticed that SpeexEncoder uses NbEncoder for the narrow band. In that class it looks like it keeps a history of some previous audio data in order perform the encoding. This should mean that the output for different instances of encoders would not go together.
private static Microphone mic = Microphone.Default;
private static SpeexEncoder encoder = CreateEncoder();
private static SpeexEncoder CreateEncoder()
{
BandMode mode = GetBandMode(mic.SampleRate);
SpeexEncoder encoder = new SpeexEncoder(mode);
// set encoding quality to lowest (which will generate the smallest size in the fastest time)
encoder.Quality = 1;
return encoder;
}
private static byte[] EncodeSpeech(byte[] buf, int len)
{
int inDataSize = len / 2;
...