I would like to know how to write to a .wav file, I have written the following code which supposedly writes data to the file. But when I try to play the sound file it says the file is corrupt / empty.
try
{
SaveFileDialog save = new SaveFileDialog();
save.Filter = "Wave File (*.wav)|*.wav;";
if (save.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
using (FileStream FS = new FileStream(save.FileName, FileMode.Open, FileAccess.Write))
{
BinaryWriter wr = new BinaryWriter(FS);
int subchunk1Size = 16;
short audioFormat = 1;
short bitsPerSample = 64;
short numChannels = 2;
int sampleRate = Convert.ToInt32(samplingRateBox.Text);
int byteRate = sampleRate * numChannels * (bitsPerSample / 8);
short blockAlign = (short)(numChannels * (bitsPerSample / 8));
int numSamples = Convert.ToInt32(numberOfsamplesBox.Text);
int subChunk2Size = numSamples * numChannels * (bitsPerSample / 8);
int chunkSize = 4 + (8 + subchunk1Size) + (8 + subChunk2Size);
wr.Write(getBytes("RIFF"));
wr.Write(chunkSize);
wr.Write(getBytes("WAVE"));
wr.Write(getBytes("fmt"));
wr.Write((byte)32);
wr.Write(subchunk1Size);
wr.Write(audioFormat);
wr.Write(numChannels);
wr.Write(sampleRate);
wr.Write(byteRate);
wr.Write(blockAlign);
wr.Write(bitsPerSample);
wr.Write(getBytes("data"));
wr.Write(subChunk2Size);
double[] primArray = new double[samples.Length];
byte[] byteArray = new byte[samples.Length * 8];
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Real);
}
byteArray = doubleToBytes(primArray);
for (int i = 0; i < samples.Length; i++)
{
wr.Write(byteArray[i]);
}
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Imaginary);
}
byteArray = doubleToBytes(primArray);
for (int i = 0; i < samples.Length; i++)
{
wr.Write(byteArray[i]);
}
wr.Close();
wr.Dispose();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
As you can see I have tried converting from Complex to double, plus the header.
The sampling rate and number of samples all come from textboxes. Plus I am assuming the bit depth is that of a double.
I have also tried using this method, however the length of the audio file is 0.
This used the NAudio library.
NAudio.Wave.WaveFileWriter waveWriter = null;
WaveIn wi = new WaveIn();
double[] primArray = new double[samples.Length];
for (int i = 0; i < samples.Length; i++)
{
primArray[i] = Convert.ToDouble(samples[i].Real);
}
SaveFileDialog save = new SaveFileDialog();
save.Filter = "Wave File (*.wav)|*.wav;";
if (save.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
wi = new NAudio.Wave.WaveIn();
wi.WaveFormat = new WaveFormat(samplingRate,1);
waveWriter = new WaveFileWriter(save.FileName, wi.WaveFormat);
byte[] byteArray = new byte[samples.Length*8];
byteArray = doubleToBytes(primArray);
waveWriter.Write(byteArray, 0, byteArray.Length);
i have next code to convert ADPCM wav in PCM wave how you can do without intermediate storage file to disk here WaveFileWriter.CreateWaveFile("D:\\pcm16000.wav", upsampler);
public static byte[] ADPcmToPcm(string waveFileName, int bitRate = 128)
{
using (var reader = new WaveFileReader(waveFileName))
using (var converter = WaveFormatConversionStream.CreatePcmStream(reader))
using (var upsampler = new WaveFormatConversionStream(new WaveFormat(16000, converter.WaveFormat.Channels), converter))
{
WaveFileWriter.CreateWaveFile("D:\\pcm16000.wav", upsampler);
FileStream fs = new FileStream("d:\\pcm16000.wav", FileMode.Open, FileAccess.Read);
byte [] bytes = new byte[fs.Length];
int bytesToRead = (int)fs.Length;
int bytesRead = 0;
while (bytesToRead > 0)
{
int n = fs.Read(bytes, bytesRead, bytesToRead);
if (n == 0) break;
bytesRead += n;
bytesToRead -= n;
}
bytesToRead = bytes.Length;
return bytes;
}
}
For some time I've been a bit desperately trying to implement a TLS 1.1 in my application. The reason behind this is the usage of SocketType.Raw sockets, so no SslStream or other higher-level classes are available to me.
So far I'm stuck at Finished message in TLS handshake protocol - keep on receiving bad_record_mac(20) in server response. Cipher suite is 0x0005 - TLS_RSA_WITH_RC4_128_SHA.
Here's some sample code on what's happening:
byte[] client_random, server_random = new byte[28];
byte[] pre_master_secret, master_secret;
byte[] client_write_MAC_secret, server_write_MAC_secret, client_write_key, server_write_key;
byte[] handshake_messages, verify_data;
RSACryptoServiceProvider rsa;
List<X509Certificate2> certificates = new List<X509Certificate2>();
//certificates are added
rsa = (RSACryptoServiceProvider)certificates.First().PublicKey.Key;
private byte[] ClientKeyExchange()
{
pre_master_secret = new byte[48];
(new Random()).NextBytes(pre_master_secret);
//version 0302 for TLS 1.1
pre_master_secret[0] = 3;
pre_master_secret[1] = 2;
byte[] cryptedData = rsa.Encrypt(pre_master_secret, false);
//"1603020086"
string tmp_string = "100000820080" + Utils.BitConverter.ToString(cryptedData).Replace("-", "");
AddHandShakeData(Utils.BitConverter.StringToByteArray(tmp_string));
tmp_string =
"1603020086"
+ tmp_string
+ "140302000101" //Cipher Change Spec
+ "";
return Utils.BitConverter.StringToByteArray(tmp_string);
}
private void ComputeMasterSecret()
{
byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("master secret", Encoding.ASCII));
byte[] seed = new byte[client_random.Length + server_random.Length];
Buffer.BlockCopy(client_random, 0, seed, 0, client_random.Length);
Buffer.BlockCopy(server_random, 0, seed, client_random.Length, server_random.Length);
master_secret = PRF(pre_master_secret, label, seed, 48);
}
private void ComputeKeys()
{
byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("key expansion", Encoding.ASCII));
byte[] seed = new byte[client_random.Length + server_random.Length];
Buffer.BlockCopy(client_random, 0, seed, 0, client_random.Length);
Buffer.BlockCopy(server_random, 0, seed, client_random.Length, server_random.Length);
byte[] key_material = PRF(master_secret, label, seed, 72);
client_write_MAC_secret = new byte[20];
Buffer.BlockCopy(key_material, 0, client_write_MAC_secret, 0, 20);
server_write_MAC_secret = new byte[20];
Buffer.BlockCopy(key_material, 20, server_write_MAC_secret, 0, 20);
client_write_key = new byte[16];
Buffer.BlockCopy(key_material, 40, client_write_key, 0, 16);
server_write_key = new byte[16];
Buffer.BlockCopy(key_material, 56, server_write_key, 0, 16);
}
private void ComputeVerifyData()
{
byte[] label = Utils.BitConverter.StringToByteArray(Utils.BitConverter.ConvertStringToHex("client finished", Encoding.ASCII));
SHA1 sha1 = SHA1.Create();
MD5 md5 = MD5.Create();
md5.ComputeHash(handshake_messages);
sha1.ComputeHash(handshake_messages);
byte[] seed = new byte[md5.HashSize / 8 + sha1.HashSize / 8];
Buffer.BlockCopy(md5.Hash, 0, seed, 0, md5.HashSize / 8);
Buffer.BlockCopy(sha1.Hash, 0, seed, md5.HashSize / 8, sha1.HashSize / 8);
verify_data = PRF(master_secret, label, seed, 12);
}
private byte[] PRF(byte[] secret, byte[] label, byte[] seed, int output_size)
{
int md5_iterations = (int)Math.Ceiling((double)output_size / 16),
sha1_iterations = (int)Math.Ceiling((double)output_size / 20);
byte[] md5_data = new byte[output_size],
sha1_data = new byte[output_size];
//особое колдунство для нечетного числа
byte[] secret_1 = new byte[(int)Math.Ceiling((double)secret.Length / 2)],
secret_2 = new byte[(int)Math.Ceiling((double)secret.Length / 2)];
Buffer.BlockCopy(secret, 0, secret_1, 0, secret_1.Length);
Buffer.BlockCopy(secret, secret.Length / 2, secret_2, 0, secret_2.Length);
byte[] A = new byte[label.Length + seed.Length];
Buffer.BlockCopy(label, 0, A, 0, label.Length);
Buffer.BlockCopy(seed, 0, A, label.Length, seed.Length);
byte[] tmp = new byte[md5_iterations * 16];
//A(1) ?
//A = P_MD5(secret_1, A);
for (int i = 0; i < md5_iterations; i++)
{
A = P_MD5(secret_1, A);
Buffer.BlockCopy(A, 0, tmp, i * A.Length, A.Length);
}
Buffer.BlockCopy(tmp, 0, md5_data, 0, md5_data.Length); //output_size = md5_data.Length
tmp = new byte[sha1_iterations * 20];
//does it have to start with A(1) ?
//A = P_SHA1(secret_2, A);
for (int i = 0; i < sha1_iterations; i++)
{
A = P_SHA1(secret_2, A);
Buffer.BlockCopy(A, 0, tmp, i * A.Length, A.Length);
}
Buffer.BlockCopy(tmp, 0, sha1_data, 0, sha1_data.Length); //output_size = sha1_data.Length
for (int i = 0; i < output_size; i++)
md5_data[i] = (byte)(md5_data[i] ^ sha1_data[i]);
return md5_data;
}
private byte[] P_MD5(byte[] secret /*это ключ?*/, byte[] seed /*это дата?*/)
{
HMACMD5 HMD5 = new HMACMD5(secret);
HMD5.ComputeHash(seed);
return HMD5.Hash;
}
private byte[] P_SHA1(byte[] secret /*это ключ?*/, byte[] seed /*это дата?*/)
{
HMACSHA1 HSHA1 = new HMACSHA1(secret);
HSHA1.ComputeHash(seed);
return HSHA1.Hash;
}
private byte[] MAC(byte[] secret, byte[] data)
{
byte[] secret_64 = new byte[64];
Buffer.BlockCopy(secret, 0, secret_64, 0, secret.Length);
for (int i = 0; i < 64; i++)
secret_64[i] = (byte)(secret_64[i] ^ (byte)54);
byte[] xor_output_data = new byte[64 + data.Length];
Buffer.BlockCopy(secret_64, 0, xor_output_data, 0, 64);
Buffer.BlockCopy(data, 0, xor_output_data, 64, data.Length);
SHA1 sha1 = SHA1.Create();
sha1.ComputeHash(xor_output_data);
secret_64 = new byte[64];
Buffer.BlockCopy(secret, 0, secret_64, 0, secret.Length);
for (int i = 0; i < 64; i++)
secret_64[i] = (byte)(secret_64[i] ^ (byte)92);
xor_output_data = new byte[64 + sha1.HashSize / 8];
Buffer.BlockCopy(secret_64, 0, xor_output_data, 0, 64);
Buffer.BlockCopy(sha1.Hash, 0, xor_output_data, 64, sha1.HashSize / 8);
sha1.ComputeHash(xor_output_data);
return sha1.Hash;
}
public void RC4(ref Byte[] bytes, Byte[] key)
{
Byte[] s = new Byte[128];
Byte[] k = new Byte[128];
Byte temp;
int i, j;
for (i = 0; i < 128; i++)
{
s[i] = (Byte)i;
k[i] = key[i % key.GetLength(0)];
}
j = 0;
for (i = 0; i < 128; i++)
{
j = (j + s[i] + k[i]) % 128;
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
i = j = 0;
for (int x = 0; x < bytes.GetLength(0); x++)
{
i = (i + 1) % 128;
j = (j + s[i]) % 128;
temp = s[i];
s[i] = s[j];
s[j] = temp;
int t = (s[i] + s[j]) % 128;
bytes[x] ^= s[t];
}
}
Obviously, reading such a bunch of code ain't being the best way to spend your time, so I'd like to add some questions that, hopefully, can help a lot:
HMAC_MD5 and HMAC_SHA1 - in .Net implementation they take key and they take input byte[] to compute hash from. According to RFC4346:
First, we define a data expansion function, P_hash(secret, data)
which uses a single hash function to expand a secret and seed into an
arbitrary quantity of output:
P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
HMAC_hash(secret, A(2) + seed) +
HMAC_hash(secret, A(3) + seed) + ...
Where + indicates concatenation.
A() is defined as:
A(0) = seed
A(i) = HMAC_hash(secret, A(i-1))
What is seed? Is it data we compute hash from? Secret = key, so far I understand. Also, do we start P_hash with A(1)?
Thanks in advance!
Seed is Client_random + Server_random. You need to preserve them from preceding steps of the handshake, the client_hello and server_hello.
A(0) = seed
A(i) = HMAC_hash(secret,A(i-1)) for i>0
The output of the A() function consists of A(1), A(2), A(3)...
I have been assigned to convert a C++ app to C#.
I want to convert the following code in C# where rate_buff is a double[3,9876] two dimensional array.
if ((fread((char*) rate_buff,
(size_t) record_size,
(size_t) record_count,
stream)) == (size_t) record_count)
If I correctly guessed your requirements, this is what you want:
int record_size = 9876;
int record_count = 3;
double[,] rate_buff = new double[record_count, record_size];
// open the file
using (Stream stream = File.OpenRead("some file path"))
{
// create byte buffer for stream reading that is record_size * sizeof(double) in bytes
byte[] buffer = new byte[record_size * sizeof(double)];
for (int i = 0; i < record_count; i++)
{
// read one record
if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
throw new InvalidDataException();
// copy the doubles out of the byte buffer into the two dimensional array
// note this assumes machine-endian byte order
for (int j = 0; j < record_size; j++)
rate_buff[i, j] = BitConverter.ToDouble(buffer, j * sizeof(double));
}
}
Or more concisely with a BinaryReader:
int record_size = 9876;
int record_count = 3;
double[,] rate_buff = new double[record_count, record_size];
// open the file
using (BinaryReader reader = new BinaryReader(File.OpenRead("some file path")))
{
for (int i = 0; i < record_count; i++)
{
// read the doubles out of the byte buffer into the two dimensional array
// note this assumes machine-endian byte order
for (int j = 0; j < record_size; j++)
rate_buff[i, j] = reader.ReadDouble();
}
}
This question is a follow-up of this Question
I have written a small method to fill a byte[] just like the MemoryStream :
public static Stream FillWithPadding(Stream MS, int Count)
{
byte[] buffer = new byte[64];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = 0xFF;
}
while (Count > buffer.Length)
{
MS.Write(buffer, 0, buffer.Length);
Count -= buffer.Length;
}
MS.Write(buffer, 0, Count);
return MS;
}
public static byte[] FillWithPadding(byte[] Buffer, int Count)
{
using (MemoryStream MS = new MemoryStream())
{
MS.Write(Buffer, 0, Buffer.Length);
MemoryStream msw = FillWithPadding(MS, Count) as MemoryStream;
return msw.GetBuffer();
}
}
This code is not working!!
Instead it is creating 0xFF + 0x00 at the End!
Can anyone Please clear-up, Why this does not work??
MemoryStream.GetBuffer() returns internal byte array that MemoryStream uses to store data. Initially it filled with 0, and filled up to stream length by Write's.
Most likely you want to use MemoryStream.ToArray() instead that returns copy of the buffer truncated to actual length.
That's the position in the Stream Now.
use MS.Position = 0 before Write.
public static Stream FillWithPadding(Stream MS, int Count)
{
byte[] buffer = new byte[64];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = 0xFF;
}
MS.Position = 0;
while (Count > buffer.Length)
{
MS.Write(buffer, 0, buffer.Length);
Count -= buffer.Length;
}
MS.Write(buffer, 0, Count);
return MS;
}