Send larger messages than 126 bytes websockets - c#

Now I'm working on Websockets, I'm new in that, I finally can send a message of 126 bytes, but I need send longer messages but when I try the connection is closed automatically, my code is:
public void sendMessage(Stream stream, string message)
{
try
{
List<byte> lb = new List<byte>();
string aux = message;
bool flagStart = false;
int size;
while (message.Length > _maxLengthMessage)
{
lb = new List<byte>();
// I cut the mesasge in smaller pieces to send
message = aux.Substring(0, _maxLengthMessage);
aux = aux.Substring(_maxLengthMessage);
if (!flagStart)
{
// In doc of Websockets i sign this piece: not the end, text
lb.Add(0x01);
flagStart = !flagStart;
}
else
{
// In doc of Websockets i sign this piece: not the end, continuation
lb.Add(0x00);
}
size = message.Length;
lb.Add((byte)size);
lb.AddRange(Encoding.UTF8.GetBytes(message));
stream.Write(lb.ToArray(), 0, size + 2);
}
lb = new List<byte>();
if (!flagStart)
{
// If is this the only message we mark with: end of message, text
lb.Add(0x81);
flagStart = !flagStart;
}
else
{
//else Is the end of the message but is the continuation frame
lb.Add(0x80);
}
size = aux.Length;
lb.Add((byte)size);
lb.AddRange(Encoding.UTF8.GetBytes(aux));
//lb.AddRange(Encoding.UTF8.GetBytes(i.ToString()));
stream.Write(lb.ToArray(), 0, size+2);
}
catch (Exception ex)
{
throw ex;
}
}
Some answers say "Go to the The WebSocket protocol", but it didn't work for me.

Your code to write the message length needs to be extended. The extended payload in the data framing diagram of the protocol spec shows what's missing.
For messages up to 125 bytes, your code is correct.
For messages > 125 but <= 65536 bytes, you need to write 3 bytes - the first byte is 126; the following 2 bytes give the message length.
For messages > 65536 bytes, you need to write 9 bytes - the first byte is 127; the following 8 bytes give the message length.

Ye, you have to create correct frame, here is the method:
static private byte[] CreateFrame(string message, MessageType messageType = MessageType.Text, bool messageContinues = false)
{
byte b1 = 0;
byte b2 = 0;
switch (messageType)
{
case MessageType.Continuos:
b1 = 0;
break;
case MessageType.Text:
b1 = 1;
break;
case MessageType.Binary:
b1 = 2;
break;
case MessageType.Close:
b1 = 8;
break;
case MessageType.Ping:
b1 = 9;
break;
case MessageType.Pong:
b1 = 10;
break;
}
b1 = (byte)(b1 + 128); // set FIN bit to 1
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
if (messageBytes.Length < 126)
{
b2 = (byte)messageBytes.Length;
}
else
{
if (messageBytes.Length < Math.Pow(2,16)-1)
{
b2 = 126;
}
else
{
b2 = 127;
}
}
byte[] frame = null;
if(b2 < 126)
{
frame = new byte[messageBytes.Length + 2];
frame[0] = b1;
frame[1] = b2;
Array.Copy(messageBytes, 0, frame, 2, messageBytes.Length);
}
if(b2 == 126)
{
frame = new byte[messageBytes.Length + 4];
frame[0] = b1;
frame[1] = b2;
byte[] lenght = BitConverter.GetBytes(messageBytes.Length);
frame[2] = lenght[1];
frame[3] = lenght[0];
Array.Copy(messageBytes, 0, frame, 4, messageBytes.Length);
}
if(b2 == 127)
{
frame = new byte[messageBytes.Length + 10];
frame[0] = b1;
frame[1] = b2;
byte[] lenght = BitConverter.GetBytes((long)messageBytes.Length);
for(int i = 7, j = 2; i >= 0; i--, j++)
{
frame[j] = lenght[i];
}
}
return frame;
}

Related

How to convert Android AudioFormat.ENCODING_PCM_16BIT into uLaw or Linear in C#

I have developed two UDP multicast apps using .NET and Android. Both applications have Sender and Receiver. They are working well when I am using the same app on different devices/pc. But when I try to receive the stream from .NET App to Android or Android to .NET then getting noise voice. I have checked both apps' streaming metadata (byte) and their format is different. Android Audio Format is: AudioFormat.ENCODING_PCM_16BIT for Encoding and C# Receiver convert the coming bytes uLaw To Linear. I understand due to different algorithm implementation in both app, they are not taking the stream. Please check my code snippets for C# & Android.
C# Codes
public static Byte[] MuLawToLinear(Byte[] bytes, int bitsPerSample, int channels)
{
//Anzahl Spuren
int blockAlign = channels * bitsPerSample / 8;
//Für jeden Wert
Byte[] result = new Byte[bytes.Length * blockAlign];
for (int i = 0, counter = 0; i < bytes.Length; i++, counter += blockAlign)
{
//In Bytes umwandeln
int value = MulawToLinear(bytes[i]);
Byte[] values = BitConverter.GetBytes(value);
switch (bitsPerSample)
{
case 8:
switch (channels)
{
//8 Bit 1 Channel
case 1:
result[counter] = values[0];
break;
//8 Bit 2 Channel
case 2:
result[counter] = values[0];
result[counter + 1] = values[0];
break;
}
break;
case 16:
switch (channels)
{
//16 Bit 1 Channel
case 1:
result[counter] = values[0];
result[counter + 1] = values[1];
break;
//16 Bit 2 Channels
case 2:
result[counter] = values[0];
result[counter + 1] = values[1];
result[counter + 2] = values[0];
result[counter + 3] = values[1];
break;
}
break;
}
}
return result;
}
Android Codes
// Audio Configuration.
int sampleRate = 16000; // How much will be ideal?
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
boolean status = true;
String ip = getIntent().getStringExtra("ip");
final InetAddress destination = InetAddress
.getByName(ip);
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRate, channelConfig, audioFormat, minBufSize);
recorder.startRecording();
while (status) {
if (!startStreamThread) {
socket.disconnect();
socket.leaveGroup(destination);
break;
}
byte[] bytes = new byte[2 + buffer.length];
bytes[0] = 1;
bytes[1] = 2;
System.arraycopy(buffer, 0, bytes, 2, buffer.length);
String deviceIp = getIpAddress();
minBufSize = recorder.read(bytes, 0, bytes.length);
// putting buffer in the packet
packet = new DatagramPacket(bytes, bytes.length,
destination, DEFAULT_PORT);
Log.e("NewOutgoing", "" + packet.getData());
Log.e("NewDEstination; ", "" + destination);
// packet.setData(deviceIp.getBytes());
socket.send(packet);
}

Modbus function 0x06

Faced a problem. There is a 0x03 function, but I need to redo it in 0x06, I don’t understand how to do it.
I know that function 06 does not have a variable part. The value of one register is always transferred to it. But I can not understand what needs to be corrected. Please, help.
Here I create a package for functions:
private void BuildMessage(byte address, byte type, ushort start, ushort registers, ref byte[] message)
{
if (type == 3 || type == 16)
{
//Array to receive CRC bytes:
byte[] CRC = new byte[2];
message[0] = address;
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
message[4] = (byte)(registers >> 8);
message[5] = (byte)registers;
GetCRC(message, ref CRC);
message[message.Length - 2] = CRC[0];
message[message.Length - 1] = CRC[1];
}
else if (type == 6)
{
byte[] CRC = new byte[2];
message[0] = address;
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
message[4] = (byte)(registers >> 8);
message[5] = (byte)registers;
GetCRC(message, ref CRC);
message[6] = CRC[0];
message[7] = CRC[1];
}
}
This is my function number 3:
public bool SendFunc(int funcNumer, string connectType, byte address, ushort start, ushort registers, ref short[] values)
{
#region №3
if (funcNumer == 3)
{
#region serial-port
if (connectType.Equals("COM"))
{
//Ensure port is open:
if (sp.IsOpen)
{
//Clear in/out buffers:
sp.DiscardOutBuffer();
sp.DiscardInBuffer();
//Function 3 request is always 8 bytes:
byte[] message = new byte[8];
//Function 3 response buffer:
byte[] response = new byte[5 + 2 * registers];
//Build outgoing modbus message:
BuildMessage(address, (byte)3, start, registers, ref message);
//Send modbus message to Serial Port:
try
{
sp.Write(message, 0, message.Length);
GetResponse("COM", ref response);
}
catch (Exception err)
{
modbusStatus = "" + err.Message;
return false;
}
//Evaluate message:
if (CheckResponse(response))
{
//Return requested register values:
for (int i = 0; i < (response.Length - 5) / 2; i++)
{
values[i] = response[2 * i + 3];
values[i] <<= 8;
values[i] += response[2 * i + 4];
}
modbusStatus = "";
return true;
}
else
{
modbusStatus = "";
return false;
}
}
else
{
modbusStatus = "";
return false;
}
}
And here I am trying to implement function number 6:
if (funcNumer == 6)
{
#region serial-port
if (connectType.Equals("COM"))
{
//Ensure port is open:
if (sp.IsOpen)
{
//Clear in/out buffers:
sp.DiscardOutBuffer();
sp.DiscardInBuffer();
//Function 3 request is always 8 bytes:
byte[] message = new byte[8];
//Function 3 response buffer:
byte[] response = new byte[5 + 2 * registers];
//Build outgoing modbus message:
BuildMessage(address, (byte)6, start, registers, ref message);
//Send modbus message to Serial Port:
try
{
sp.Write(message, 0, message.Length);
GetResponse("COM", ref response);
}
catch (Exception err)
{
modbusStatus = "" + err.Message;
return false;
}
//Evaluate message:
if (CheckResponse(response))
{
//Return requested register values:
for (int i = 0; i < (response.Length - 5) / 2; i++)
{
values[i] = response[2 * i + 3];
values[i] <<= 8;
values[i] += response[2 * i + 4];
}
modbusStatus = "";
return true;
}
else
{
modbusStatus = "";
return false;
}
}
else
{
modbusStatus = "";
return false;
}
}
This is my function to check the response:
private bool CheckResponse(byte[] response)
{
//Perform a basic CRC check:
byte[] CRC = new byte[2];
GetCRC(response, ref CRC);
if (CRC[0] == response[response.Length - 2] && CRC[1] == response[response.Length - 1])
return true;
else
return false;
}
This is my function for get response:
private void GetResponse(string connect, ref byte[] response)
{
if (connect.Equals("COM"))
{
for (int i = 0; i < response.Length; i++)
{
response[i] = (byte)(sp.ReadByte());
}
}
else if (connect.Equals("TCP"))
{
NetworkStream stream = tcpClient.GetStream();
for (int i = 0; i < response.Length; i++)
{
response[i] = (byte)(stream.ReadByte());
}
}
else
{
}
}
The difference between Modbus function 0x03 and 0x06 is actually the part of the code you did not show on your question: CheckResponse(response).
Function 0x03 reads a number of registers, and the values in those registers (coming from the slave) are included in the response.
Function 0x06 writes a single register and gives an echo back. So the response is the same as the query.
With that information, it should be easy to modify your code: remove the for loop where you retrieve the register values.
Other than that you might need to modify your CheckResponse() function too, but that should also be quite straight forward: just check the response is exactly the same as the query (message).
EDIT: if your CheckResponse()` function only checks for the correct CRC on the responses I suppose you can keep it as it is.

How can I get the data of 8bit wav file

I'm making a demo about sound in WindowsForm, I created 3 classes for taking data of wave file. Code is below:
RiffBlock
public class RiffBlock
{
private byte[] riffID;
private uint riffSize;
private byte[] riffFormat;
public byte[] RiffID
{
get { return riffID; }
}
public uint RiffSize
{
get { return (riffSize); }
}
public byte[] RiffFormat
{
get { return riffFormat; }
}
public RiffBlock()
{
riffID = new byte[4];
riffFormat = new byte[4];
}
public void ReadRiff(FileStream inFS)
{
inFS.Read(riffID, 0, 4);
BinaryReader binRead = new BinaryReader(inFS);
riffSize = binRead.ReadUInt32();
inFS.Read(riffFormat, 0, 4);
}
}
FormatBlock
public class FormatBlock
{
private byte[] fmtID;
private uint fmtSize;
private ushort fmtTag;
private ushort fmtChannels;
private uint fmtSamplesPerSec;
private uint fmtAverageBytesPerSec;
private ushort fmtBlockAlign;
private ushort fmtBitsPerSample;
public byte[] FmtID
{
get { return fmtID; }
}
public uint FmtSize
{
get { return fmtSize; }
}
public ushort FmtTag
{
get { return fmtTag; }
}
public ushort Channels
{
get { return fmtChannels; }
}
public uint SamplesPerSec
{
get { return fmtSamplesPerSec; }
}
public uint AverageBytesPerSec
{
get { return fmtAverageBytesPerSec; }
}
public ushort BlockAlign
{
get { return fmtBlockAlign; }
}
public ushort BitsPerSample
{
get { return fmtBitsPerSample; }
}
public FormatBlock()
{
fmtID = new byte[4];
}
public void ReadFmt(FileStream inFS)
{
inFS.Read(fmtID, 0, 4);
BinaryReader binRead = new BinaryReader(inFS);
fmtSize = binRead.ReadUInt32();
fmtTag = binRead.ReadUInt16();
fmtChannels = binRead.ReadUInt16();
fmtSamplesPerSec = binRead.ReadUInt32();
fmtAverageBytesPerSec = binRead.ReadUInt32();
fmtBlockAlign = binRead.ReadUInt16();
fmtBitsPerSample = binRead.ReadUInt16();
// This accounts for the variable format header size
// 12 bytes of Riff Header, 4 bytes for FormatId, 4 bytes for FormatSize & the Actual size of the Format Header
inFS.Seek(fmtSize + 20, System.IO.SeekOrigin.Begin);
}
}
DataBlock
public class DataBlock
{
private byte[] dataID;
private uint dataSize;
private Int16[] data;
private int dataNumSamples;
public byte[] DataID
{
get { return dataID; }
}
public uint DataSize
{
get { return dataSize; }
}
public Int16 this[int pos]
{
get { return data[pos]; }
}
public int NumSamples
{
get { return dataNumSamples; }
}
public DataBlock()
{
dataID = new byte[4];
}
public void ReadData(FileStream inFS)
{
inFS.Read(dataID, 0, 4);
BinaryReader binRead = new BinaryReader(inFS);
dataSize = binRead.ReadUInt32();
data = new Int16[dataSize];
inFS.Seek(40, SeekOrigin.Begin);
dataNumSamples = (int)(dataSize / 2);
for (int i = 0; i < dataNumSamples; i++)
{
data[i] = binRead.ReadInt16();
}
}
}
It works ok with only 16bit wave file, but when I choose a 8 bit wav file or another, the result of this command dataSize = binRead.ReadUInt32();is only 4 although the file size is big.
How I can get the data of 8bit, 24bit... wav file?
Some solutions is appreciated, thank you very much.
Your reading methodology is flawed. The length is correct but for an 8 bits per sample file you should be reading bytes not words; as it stands the data will be incorrect and the value returned by the NumSamples property will be wrong.
In my case, the sub chunk size is 1160, the number of channels is 1 (mono) and the bits per sample is 8 (byte). You will need to decode the bits per sample and adjust your reading accordingly. For the WAV file I used, your program allocated a data array the correct length but 16 bit, divided the data length by 2 and called this the number of samples (wrong, it should be 1160) and then proceeded to read 580 word values from the stream.
Edit: My ancient code will not cut it in the modern age (I seem to recall having to modify it some years ago to cope with at least one additional chunk type but the details escape me).
This is what you get; anything more and your question should read "Could someone write me a program to load WAV files", as it is, we are way beyond the original question and it is time for you to knuckle down and make it work how you need it to :-)
References:
http://www.neurophys.wisc.edu/auditory/riff-format.txt
http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
http://www.shikadi.net/moddingwikiResource_Interchange_File_Format_(RIFF)
http://soundfile.sapp.org/doc/WaveFormat/
All are very useful.
///<summary>
///Reads up to 16 bit WAV files
///</summary>
///<remarks> Things have really changed in the last 15 years</remarks>
public class RiffLoader
{
public enum RiffStatus { Unknown = 0, OK, FileError, FormatError, UnsupportedFormat };
LinkedList<Chunk> chunks = new LinkedList<Chunk>();
RiffStatus status = RiffStatus.Unknown;
List<String> errorMessages = new List<string>();
String source;
public String SourceName { get { return source; } }
public RiffStatus Status { get { return status; } }
public String[] Messages { get { return errorMessages.ToArray(); } }
enum chunkType { Unknown = 0, NoMore, Riff, Fmt, Fact, Data, Error = -1 };
static Int32 scan32bits(byte[] source, int offset = 0)
{
return source[offset] | source[offset + 1] << 8 | source[offset + 2] << 16 | source[offset + 3] << 24;
}
static Int32 scan16bits(byte[] source, int offset = 0)
{
return source[offset] | source[offset + 1] << 8;
}
static Int32 scan8bits(byte[] source, int offset = 0)
{
return source[offset];
}
abstract class Chunk
{
public chunkType Ident = chunkType.Unknown;
public int ByteCount = 0;
}
class RiffChunk : Chunk
{
public RiffChunk(int count)
{
this.Ident = chunkType.Riff;
this.ByteCount = count;
}
}
class FmtChunk : Chunk
{
int formatCode = 0;
int channels = 0;
int samplesPerSec = 0;
int avgBytesPerSec = 0;
int blockAlign = 0;
int bitsPerSample = 0;
int significantBits = 0;
public int Format { get { return formatCode; } }
public int Channels { get { return channels; } }
public int BlockAlign { get { return blockAlign; } }
public int BytesPerSample { get { return bitsPerSample / 8 + ((bitsPerSample % 8) > 0 ? 1 : 0); } }
public int BitsPerSample
{
get
{
if (significantBits > 0)
return significantBits;
return bitsPerSample;
}
}
public FmtChunk(byte[] buffer) : base()
{
int size = buffer.Length;
// if the length is 18 then buffer 16,17 should be 00 00 (I don't bother checking)
if (size != 16 && size != 18 && size != 40)
return;
formatCode = scan16bits(buffer, 0);
channels = scan16bits(buffer, 2);
samplesPerSec = scan32bits(buffer, 4);
avgBytesPerSec = scan32bits(buffer, 8);
blockAlign = scan16bits(buffer, 12);
bitsPerSample = scan16bits(buffer, 14);
if (formatCode == 0xfffe) // EXTENSIBLE
{
if (size != 40)
return;
significantBits = scan16bits(buffer, 18);
// skiping speaker map
formatCode = scan16bits(buffer, 24); // first two bytes of the GUID
// the rest of the GUID is fixed, decode it and check it if you wish
}
this.Ident = chunkType.Fmt;
this.ByteCount = size;
}
}
class DataChunk : Chunk
{
byte[] samples = null;
///<summary>
///Create a data chunk
///<para>
///The supplied buffer must be correctly sized with zero offset and must be purely for this class
///</para>
///<summary>
///<param name="buffer">source array</param>
public DataChunk(byte[] buffer)
{
this.Ident = chunkType.Data;
this.ByteCount = buffer.Length;
samples = buffer;
}
public enum SampleStatus { OK, Duff }
public class Samples
{
public SampleStatus Status = SampleStatus.Duff;
public List<int[]> Channels = new List<int[]>();
#if false // debugger helper method
/*
** Change #if false to #if true to include this
** Break at end of GetSamples on "return retval"
** open immediate window and type retval.DumpLast(16)
** look in output window for dump of last 16 entries
*/
public int DumpLast(int count)
{
for (int i = Channels[0].Length - count; i < Channels[0].Length; i++)
Console.WriteLine(String.Format("{0:X4} {1:X4},{2:X4}", i, Channels[0][i], Channels[1][i]));
return 0;
}
#endif
}
/*
** Return the decoded samples
*/
public Samples GetSamples(FmtChunk format)
{
Samples retval = new Samples();
int samplesPerChannel = this.ByteCount / (format.BytesPerSample * format.Channels);
int mask = 0, sign=0;
int [][] samples = new int [format.Channels][];
for (int c = 0; c < format.Channels; c++)
samples[c] = new int[samplesPerChannel];
if (format.BitsPerSample >= 8 && format.BitsPerSample <= 16) // 24+ is left as an excercise
{
sign = (int)Math.Floor(Math.Pow(2, format.BitsPerSample - 1));
mask = (int)Math.Floor(Math.Pow(2, format.BitsPerSample)) - 1;
int offset = 0, index = 0;
int s = 0;
while (index < samplesPerChannel)
{
for (int c = 0; c < format.Channels; c++)
{
switch (format.BytesPerSample)
{
case 1:
s = scan8bits(this.samples, offset) & mask;
break;
case 2:
s = scan16bits(this.samples, offset) & mask;
break;
}
// sign extend the data to Int32
samples[c][index] = s | ((s & sign) != 0 ? ~mask : 0);
offset += format.BytesPerSample;
}
++index;
}
retval.Channels = new List<int[]>(samples);
retval.Status = SampleStatus.OK;
}
return retval;
}
}
class FactChunk : Chunk
{
int samplesPerChannel;
public int SamplesPerChannel { get { return samplesPerChannel; } }
public FactChunk(byte[] buffer)
{
this.Ident = chunkType.Fact;
this.ByteCount = buffer.Length;
if (buffer.Length >= 4)
samplesPerChannel = scan32bits(buffer);
}
}
class DummyChunk : Chunk
{
public DummyChunk(int size, chunkType type = chunkType.Unknown)
{
this.Ident = type;
this.ByteCount = size;
}
}
public RiffLoader(String fileName)
{
source = fileName;
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (BinaryReader reader = new BinaryReader(fs))
{
Chunk c = getChunk(fs, reader);
if (c.Ident != chunkType.Riff)
{
status = RiffStatus.FileError;
errorMessages.Add(String.Format("Error loading \"{0}\": No valid header"));
}
chunks.AddLast(c);
c = getChunk(fs, reader);
if (c.Ident != chunkType.Fmt)
{
status = RiffStatus.FileError;
errorMessages.Add(String.Format("Error loading \"{0}\": No format chunk"));
}
chunks.AddLast(c);
/*
** From now on we just keep scanning to the end of the file
*/
while (fs.Position < fs.Length)
{
c = getChunk(fs, reader);
switch (c.Ident)
{
case chunkType.Fact:
case chunkType.Data:
chunks.AddLast(c);
break;
case chunkType.Unknown:
break; // skip it - don't care what it is
}
}
FmtChunk format = null;
foreach (var chunk in chunks)
{
switch(chunk.Ident)
{
case chunkType.Fmt:
format = chunk as FmtChunk;
break;
case chunkType.Data:
if (format != null)
{
DataChunk dc = chunk as DataChunk;
var x = dc.GetSamples(format);
}
break;
}
}
}
}
catch (Exception e)
{
status = RiffStatus.FileError;
errorMessages.Add(String.Format("Error loading \"{0}\": {1}", e.Message));
}
}
/*
** Get a chunk of data from the file - knows nothing of the internal format of the chunk.
*/
Chunk getChunk(FileStream stream, BinaryReader reader)
{
byte[] buffer;
int size;
buffer = reader.ReadBytes(8);
if (buffer.Length == 8)
{
String prefix = new String(Encoding.ASCII.GetChars(buffer, 0, 4));
size = scan32bits(buffer, 4);
if (size + stream.Position <= stream.Length) // skip if there isn't enough data
{
if (String.Compare(prefix, "RIFF") == 0)
{
/*
** only "WAVE" type is acceptable
**
** Don't read size bytes or the entire file will end up in the RIFF chunk
*/
if (size >= 4)
{
buffer = reader.ReadBytes(4);
String ident = new String(Encoding.ASCII.GetChars(buffer, 0, 4));
if (String.CompareOrdinal(ident, "WAVE") == 0)
return new RiffChunk(size - 4);
}
}
else if (String.Compare(prefix, "fmt ") == 0)
{
if (size >= 16)
{
buffer = reader.ReadBytes(size);
if (buffer.Length == size)
return new FmtChunk(buffer);
}
}
else if (String.Compare(prefix, "fact") == 0)
{
if (size >= 4)
{
buffer = reader.ReadBytes(4);
if (buffer.Length == size)
return new FactChunk(buffer);
}
}
else if (String.Compare(prefix, "data") == 0)
{
// assume that there has to be data
if (size > 0)
{
buffer = reader.ReadBytes(size);
if ((size & 1) != 0) // odd length?
{
if (stream.Position < stream.Length)
reader.ReadByte();
else
size = -1; // force an error - there should be a pad byte
}
if (buffer.Length == size)
return new DataChunk(buffer);
}
}
else
{
/*
** there are a number of weird and wonderful block types - assume there has to be data
*/
if (size > 0)
{
buffer = reader.ReadBytes(size);
if ((size & 1) != 0) // odd length?
{
if (stream.Position < stream.Length)
reader.ReadByte();
else
size = -1; // force an error - there should be a pad byte
}
if (buffer.Length == size)
{
DummyChunk skip = new DummyChunk(size);
return skip;
}
}
}
}
}
return new DummyChunk(0, chunkType.Error);
}
}
You will need to add properties as required and code to navigate the returned linked list. Particular properties you may need are the sample rates in the format block, assuming you are going to process the data in some way.
Adding 24 to 32 bits is simple, if you need to go beyond 32 bits you will have to switch to int64's.
I have tested it with some good samples from http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html, as well as your 8 bit file, and it decodes OK and seems to have the correct data.
You should be more than capable of making it work now, good luck.
Edit (again, like the proverbial dog...):
Of course, I should have sign extended the value, so DataChunk.GetSamples() now does that. Looking at the Codeproject files (it isn't the greatest code by the way, but the guy does say that he is only just learning C#, so fair play for tackling a graphical user control) it is obvious that the data is signed. It's a shame that he didn't standardise his source to be an array of Int32's, then it wouldn't matter how many bits the WAV was encoded in.
You could use the Naudio library:
https://naudio.codeplex.com/ (take a look at their website, there are quite a lot of tutorials).
Hope this helps :).

Receiving irrelevant data from network on second call to network using tcp sockets

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.

c# Pitch shift of wave files

I'm currently trying to do pitch shifting of a wave file using this algorithm
https://sites.google.com/site/mikescoderama/pitch-shifting
Here my code which use the above implementation, but with no luck. The outputted wave file seems to be corrupted or not valid.
The code is quite simple, except for the pitch shift algorithm :)
It load a wave file, it reads the wave file data and put it in a
byte[] array.
Then it "normalize" bytes data into -1.0f to 1.0f format (as
requested by the creator of the pitch shift algorithm).
It applies the pitch shift algorithm and then convert back the
normalized data into a bytes[] array.
Finally saves a wave file with the same header of the original wave
file and the pitch shifted data.
Am I missing something?
static void Main(string[] args)
{
// Read the wave file data bytes
byte[] waveheader = null;
byte[] wavedata = null;
using (BinaryReader reader = new BinaryReader(File.OpenRead("sound.wav")))
{
// Read first 44 bytes (header);
waveheader= reader.ReadBytes(44);
// Read data
wavedata = reader.ReadBytes((int)reader.BaseStream.Length - 44);
}
short nChannels = BitConverter.ToInt16(waveheader, 22);
int sampleRate = BitConverter.ToInt32(waveheader, 24);
short bitRate = BitConverter.ToInt16(waveheader, 34);
// Normalized data store. Store values in the format -1.0 to 1.0
float[] in_data = new float[wavedata.Length / 2];
// Normalize wave data into -1.0 to 1.0 values
using(BinaryReader reader = new BinaryReader(new MemoryStream(wavedata)))
{
for (int i = 0; i < in_data.Length; i++)
{
if(bitRate == 16)
in_data[i] = reader.ReadInt16() / 32768f;
if (bitRate == 8)
in_data[i] = (reader.ReadByte() - 128) / 128f;
}
}
//PitchShifter.PitchShift(1f, in_data.Length, (long)1024, (long)32, sampleRate, in_data);
// Backup wave data
byte[] copydata = new byte[wavedata.Length];
Array.Copy(wavedata, copydata, wavedata.Length);
// Revert data to byte format
Array.Clear(wavedata, 0, wavedata.Length);
using (BinaryWriter writer = new BinaryWriter(new MemoryStream(wavedata)))
{
for (int i = 0; i < in_data.Length; i++)
{
if(bitRate == 16)
writer.Write((short)(in_data[i] * 32768f));
if (bitRate == 8)
writer.Write((byte)((in_data[i] * 128f) + 128));
}
}
// Compare new wavedata with copydata
if (wavedata.SequenceEqual(copydata))
{
Console.WriteLine("Data has no changes");
}
else
{
Console.WriteLine("Data has changed!");
}
// Save modified wavedata
string targetFilePath = "sound_low.wav";
if (File.Exists(targetFilePath))
File.Delete(targetFilePath);
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(targetFilePath)))
{
writer.Write(waveheader);
writer.Write(wavedata);
}
Console.ReadLine();
}
The algorithm here works fine
https://sites.google.com/site/mikescoderama/pitch-shifting
My mistake was on how i was reading the wave header and wave data. I post here the fully working code
WARNING: this code works only for PCM 16 bit (stereo/mono) waves. Can be easily adapted to works with PCM 8 bit.
static void Main(string[] args)
{
// Read header, data and channels as separated data
// Normalized data stores. Store values in the format -1.0 to 1.0
byte[] waveheader = null;
byte[] wavedata = null;
int sampleRate = 0;
float[] in_data_l = null;
float[] in_data_r = null;
GetWaveData("sound.wav", out waveheader, out wavedata, out sampleRate, out in_data_l, out in_data_r);
//
// Apply Pitch Shifting
//
if(in_data_l != null)
PitchShifter.PitchShift(2f, in_data_l.Length, (long)1024, (long)10, sampleRate, in_data_l);
if(in_data_r != null)
PitchShifter.PitchShift(2f, in_data_r.Length, (long)1024, (long)10, sampleRate, in_data_r);
//
// Time to save the processed data
//
// Backup wave data
byte[] copydata = new byte[wavedata.Length];
Array.Copy(wavedata, copydata, wavedata.Length);
GetWaveData(in_data_l, in_data_r, ref wavedata);
//
// Check if data actually changed
//
bool noChanges = true;
for (int i = 0; i < wavedata.Length; i++)
{
if (wavedata[i] != copydata[i])
{
noChanges = false;
Console.WriteLine("Data has changed!");
break;
}
}
if(noChanges)
Console.WriteLine("Data has no changes");
// Save modified wavedata
string targetFilePath = "sound_low.wav";
if (File.Exists(targetFilePath))
File.Delete(targetFilePath);
using (BinaryWriter writer = new BinaryWriter(File.OpenWrite(targetFilePath)))
{
writer.Write(waveheader);
writer.Write(wavedata);
}
Console.ReadLine();
}
// Returns left and right float arrays. 'right' will be null if sound is mono.
public static void GetWaveData(string filename, out byte[] header, out byte[] data, out int sampleRate, out float[] left, out float[] right)
{
byte[] wav = File.ReadAllBytes(filename);
// Determine if mono or stereo
int channels = wav[22]; // Forget byte 23 as 99.999% of WAVs are 1 or 2 channels
// Get sample rate
sampleRate = BitConverter.ToInt32(wav, 24);
int pos = 12;
// Keep iterating until we find the data chunk (i.e. 64 61 74 61 ...... (i.e. 100 97 116 97 in decimal))
while(!(wav[pos]==100 && wav[pos+1]==97 && wav[pos+2]==116 && wav[pos+3]==97)) {
pos += 4;
int chunkSize = wav[pos] + wav[pos + 1] * 256 + wav[pos + 2] * 65536 + wav[pos + 3] * 16777216;
pos += 4 + chunkSize;
}
pos += 4;
int subchunk2Size = BitConverter.ToInt32(wav, pos);
pos += 4;
// Pos is now positioned to start of actual sound data.
int samples = subchunk2Size / 2; // 2 bytes per sample (16 bit sound mono)
if (channels == 2)
samples /= 2; // 4 bytes per sample (16 bit stereo)
// Allocate memory (right will be null if only mono sound)
left = new float[samples];
if (channels == 2)
right = new float[samples];
else
right = null;
header = new byte[pos];
Array.Copy(wav, header, pos);
data = new byte[subchunk2Size];
Array.Copy(wav, pos, data, 0, subchunk2Size);
// Write to float array/s:
int i=0;
while (pos < subchunk2Size)
{
left[i] = BytesToNormalized_16(wav[pos], wav[pos + 1]);
pos += 2;
if (channels == 2)
{
right[i] = BytesToNormalized_16(wav[pos], wav[pos + 1]);
pos += 2;
}
i++;
}
}
// Return byte data from left and right float data. Ignore right when sound is mono
public static void GetWaveData(float[] left, float[] right, ref byte[] data)
{
// Calculate k
// This value will be used to convert float to Int16
// We are not using Int16.Max to avoid peaks due to overflow conversions
float k = (float)Int16.MaxValue / left.Select(x => Math.Abs(x)).Max();
// Revert data to byte format
Array.Clear(data, 0, data.Length);
int dataLenght = left.Length;
int byteId = -1;
using (BinaryWriter writer = new BinaryWriter(new MemoryStream(data)))
{
for (int i = 0; i < dataLenght; i++)
{
byte byte1 = 0;
byte byte2 = 0;
byteId++;
NormalizedToBytes_16(left[i], k, out byte1, out byte2);
writer.Write(byte1);
writer.Write(byte2);
if (right != null)
{
byteId++;
NormalizedToBytes_16(right[i], k, out byte1, out byte2);
writer.Write(byte1);
writer.Write(byte2);
}
}
}
}
// Convert two bytes to one double in the range -1 to 1
static float BytesToNormalized_16(byte firstByte, byte secondByte)
{
// convert two bytes to one short (little endian)
short s = (short)((secondByte << 8) | firstByte);
// convert to range from -1 to (just below) 1
return s / 32678f;
}
// Convert a float value into two bytes (use k as conversion value and not Int16.MaxValue to avoid peaks)
static void NormalizedToBytes_16(float value, float k, out byte firstByte, out byte secondByte)
{
short s = (short)(value * k);
firstByte = (byte)(s & 0x00FF);
secondByte = (byte)(s >> 8);
}
sorry to revive this but I tried that pitchshifter class and, while it works, I get crackles in the audio while pitching down(0.5f). You work out a way around that?

Categories