UWP stream to float array c# - c#

I have a problem turning a RandomAccessStream into a float array. The float array contains values that are NaN. I can't tell if they come from the stream, the byte array or the float array. Performance & quality are important in this so if there is a better way to do this let me know.
Last count I was getting 122 NaN's.
thanks
private async void button_Click(object sender, RoutedEventArgs e)
{
string text = "this is text";
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
SpeechSynthesisStream synthesisStream = await synthesizer.SynthesizeTextToStreamAsync(text);
Stopwatch watch = new Stopwatch();
watch.Start();
ProcessStream(synthesisStream.CloneStream());
watch.Stop();
// Performance is important
Debug.WriteLine(watch.Elapsed);
}
private async void ProcessStream(IRandomAccessStream stream)
{
// Create a buffer (somewhere to put the stream)
byte[] bytes = new byte[stream.Size];
// Add stream data to buffer (Following or After that) same result
// IBuffer x = await stream.ReadAsync(bytes.AsBuffer(), (uint)stream.Size, InputStreamOptions.None);
using (DataReader reader = new DataReader(stream))
{
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bytes);
}
// Change buffer(in bytes) to a float array
float[] floatArray = MainPage.ConvertByteToFloat(bytes.ToArray());
int nanCount = 0;
for (var index = 0; index < floatArray.Length; index++)
{
float value = floatArray[index];
if (float.IsNaN(value))
{
nanCount++;
}
}
Debug.WriteLine("Nan count: " + nanCount);
}
public static float[] ConvertByteToFloat(byte[] array)
{
float[] floatArr = new float[array.Length / 4];
for (int i = 0; i < floatArr.Length; i++)
{
if (BitConverter.IsLittleEndian)
{
Array.Reverse(array, i * 4, 4);
}
floatArr[i] = BitConverter.ToSingle(array, i * 4);
}
return floatArr;
}

Found the answer At this SO post
Basically I did not know that the 32 bit wav format stored its data in a 16 bit format.

Related

how can i modify a small section of bytes in a memory stream, that was written to using binarywriter

how do i edit the first four bytes in memory stream? Imagine "bytes" in the following code is a few 100 bytes long. i need to write a place holder of say, 4 bytes of value 0 and come back and update those bytes to new values.
static MemoryStream stream = new MemoryStream();
static BinaryWriter writer = new BinaryWriter(stream);
writer.Write(bytes);
How about this solution:
static void UpdateNthLong(MemoryStream ms, long idx, long newValue)
{
var currPos = ms.Position;
try
{
var offset = sizeof(long) * idx;
ms.Position = offset;
var bw = new BinaryWriter(ms);
bw.Write(newValue);
}
finally { ms.Position = currPos; }
}
static void ShowByteArray(byte[] array)
{
Console.WriteLine("Size: {0}", array.Length);
for(int i = 0; i < array.Length; i++)
{
Console.WriteLine("{0} => {1}", i, array[i]);
}
}
static void Main(string[] args)
{
using (var ms = new MemoryStream())
{
var bw = new BinaryWriter(ms);
bw.Write(1L); // 0-th
bw.Write(2L); // 1-th
bw.Write(3L); // 2-th
bw.Write(4L); // 3-th
var bytes = ms.ToArray();
Console.WriteLine("Before update:");
ShowByteArray(bytes);
// Update 0-th
UpdateNthLong(ms, 0, 0xFFFFFFFFFFFFFF);
// Update 3-th
UpdateNthLong(ms, 3, 0xBBBBBBBBBBBBBBB);
bytes = ms.ToArray();
Console.WriteLine("After update:");
ShowByteArray(bytes);
}
}

C# Issue Using RSA Decryption To Decrypt

Hello Stackoverflow users, I am working on assignment regarding RSA encryption and decryption and have hit a sticky spot.
Using Visual Studio I have created a simple form with 2 textboxes (one for the plain text message and the other to display the encrypted message) and 4 buttons (2 clear buttons to clear corresponding textboxes and an encryption button and decryption button).
public partial class Form1 : Form
{
//Strings to hold public & private keys
String publicKey, privateKey;
UnicodeEncoding encoder = new UnicodeEncoding();
public Form1()
{
RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
InitializeComponent();
privateKey = myRSA.ToXmlString(true);
publicKey = myRSA.ToXmlString(false);
}
private void btnClr1_Click(object sender, EventArgs e)
{
txtPlain.Text = "";
txtPlain.Refresh();
}
private void btnClr2_Click(object sender, EventArgs e)
{
txtCypher.Text = "";
txtCypher.Refresh();
}
private void btnEncrypt_Click(object sender, EventArgs e)
{
var myRSA = new RSACryptoServiceProvider();
//Set cryptoserviceprovider with the proper key
myRSA.FromXmlString(publicKey);
//Encode the data to encrypt as a byte array
var dataToEncrypt = encoder.GetBytes(txtPlain.Text);
//Encrypt the byte array
var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray();
var length = encryptedByteArray.Count();
var item = 0;
var sb = new StringBuilder();
//Change each byte in the encrypted byte array to text
foreach(var x in encryptedByteArray)
{
item++;
sb.Append(x);
if (item < length) sb.Append(",");
}
txtCypher.Text = sb.ToString();
}
private void btnDecrypt_Click(object sender, EventArgs e)
{
var myRSA = new RSACryptoServiceProvider();
//Split data into an array
var dataArray = txtCypher.Text.Split(new char[] { ',' });
//Convert chars to bytes
byte[] dataByte = new byte[dataArray.Length];
for(int i = 0; i < dataArray.Length; i++) dataByte[i] = Convert.ToByte(dataArray[i]);
//Decrypt the byte array
myRSA.FromXmlString(privateKey);
var decryptedBytes = myRSA.Decrypt(dataByte, false);
//place into cypher text box
txtPlain.Text = encoder.GetString(decryptedBytes);
}
}
I have no issues with encrypting and decrypting messages (as long as they don't exceed the RSA key size, obviously).
So I am working to modify my program to allow for any size messages to be encrypted and decrypted.
This is the code I have come up with to allow for any size to be encrypted (which seems to work)
private void btnEncrypt_Click(object sender, EventArgs e)
{
var myRSA = new RSACryptoServiceProvider();
//Set cryptoserviceprovider with the proper key
myRSA.FromXmlString(publicKey);
//Encode the data to encrypt as a byte array
var dataToEncrypt = encoder.GetBytes(txtPlain.Text);
//store dataLength
int dataLength = dataToEncrypt.Length;
//Check if dataLength > 128
if (dataLength > 128)
{
//Divide dataLength by 128 to determine how many cycles will be needed
double numOfCycles = (dataLength / 117);
//round up to nearest whole number
cycles = (int)Math.Ceiling(numOfCycles);
//for however many cycles
for (int i = 0; i < cycles; i++)
{
var myByteArray = new byte[117];
for (int j = 0; j < 117; j++)
{
int currentByte = i * 117 + j;
myByteArray[j] = dataToEncrypt[currentByte];
}
var encryptedByteArray = myRSA.Encrypt(myByteArray, false).ToArray();
var length = encryptedByteArray.Count();
var item = 0;
//Change each byte in the encrypted byte array to text
foreach (var x in encryptedByteArray)
{
item++;
sb.Append(x);
if (item < length) sb.Append(",");
}
txtCypher.Text = sb.ToString();
}
}
else
{
var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray();
var length = encryptedByteArray.Count();
var item = 0;
var sb = new StringBuilder();
//Change each byte in the encrypted byte array to text
foreach(var x in encryptedByteArray)
{
item++;
sb.Append(x);
if (item < length) sb.Append(",");
}
txtCypher.Text = sb.ToString();
}
}
And this is the code that I have come up with to handle decryption of any size message (which is what is giving me errors)
private void btnDecrypt_Click(object sender, EventArgs e)
{
var myRSA = new RSACryptoServiceProvider();
//Split data into an array
var dataArray = txtCypher.Text.Split(new char[] { ',' });
int length = dataArray.Count();
float numOfCycles = (length / 117);
int cycles = (int)Math.Ceiling(numOfCycles);
for (int i = 0; i < cycles; i++)
{
byte[] dataByte = new byte[117];
for(int j = 0; j < 117; j++)
{
//Convert chars to bytes
dataByte[j] = Convert.ToByte(dataArray[ i * 117 + j ]);
}
//Decrypt the byte array
myRSA.FromXmlString(privateKey);
var decryptedBytes = myRSA.Decrypt(dataByte, false);
txtPlain.Text += encoder.GetString(decryptedBytes);
}
}
The errors that it being thrown is:
`System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll. Additional information: Bad Data.`
from line 133: var decryptedBytes = myRSA.Decrypt(dataByte, false);
Any help/advice would be greatly appreciated! Thanks all!
As Luke Park said, it's generally considered bad practice to try to make RSA a chained algorithm. It's purpose is for secure "key exchange", meaning the encrypted contents are 'supposed' to be symmetric encryption information.
However, if you're determined to go down this road; the problem is that RSA-Encrypt always produces an output whose length is the key size. Your code is assuming 117 bytes in => 117 bytes out; and that's just not the case.
Since RSA-Decrypt expects that you have prepared the data with RSA-Encrypt, it reports "Bad Data" because you haven't given it a valid datagram (a valid one would have length equal to the keysize).

"Buffer full" exception

I'm trying to create application that sends and receives audio. I have 2
BufferedWaveProvider's.
For the first one I do
private void AsioOut_AudioAvailable(object sender, AsioAudioAvailableEventArgs e)
{
float[] sourceAudio = new float[e.SamplesPerBuffer*e.InputBuffers.Length];
e.GetAsInterleavedSamples(sourceAudio);
float[] proccesedAudio = new float[settings.BufferSize];
byte[] result = new byte[settings.BufferSize*4];
byte[] sendingAudio = new byte[e.SamplesPerBuffer*4];
for (int j = 1, q = 0; j < sourceAudio.Length; j += 2, q++)
proccesedAudio[q] = sourceAudio[j];
//...audio is beeing proccesed by VSTHost...
result.CopyTo(sendingAudio,0);
if (connection.IsConnected)
Task.Run(() => connection.Send(sendingAudio)); //Proccesed audio sends by socket
inputAudioBufferedWaveProvider.AddSamples(result, 0, result.Length);
}
For the second one I do
private void AudioReceiving()
{
while (isAudioReceiving)
{
incomingBytes = connection.AudioReceiving(); //Socket receives bytes
incomingAudioBufferedWaveProvider.AddSamples(incomingBytes, 0, incomingBytes.Length);
}
}
Those 2 BufferedWiveProvider's is mixing by the MixingSampleProvider.
mixingProvider = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(Convert.ToInt32(settings.SampleRate), 2));
mixingProvider.AddMixerInput(inputAudioPanningProvider);
mixingProvider.AddMixerInput(incomingAudioPanningProvider);
mixingProvider.ReadFully = true;
asioOut.InitRecordAndPlayback(new SampleToWaveProvider(mixingProvider),2,Convert.ToInt32(settings.SampleRate));
After 3-4 minutes after starting application I get exception (Buffer full). I think problem with buffer that being filled by bytes received from network.
What I'm doing wrong?

.Net How to play audio samples directly

I have audio samples extracted through NAudio, i know parameters:
channels
bytes per sample,
samplerate
How to play that samples by using .Net api / or other .Net library
Here code:
openFileDialog1.ShowDialog();
using (var reader = new Mp3FileReader(openFileDialog1.FileName))
{
var pcmLength = (int)reader.Length;
var _leftBuffer = new byte[pcmLength / 2];
var buffer = new byte[pcmLength];
var bytesRead = reader.Read(buffer, 0, pcmLength);
int index = 0;
for (int i = 0; i < bytesRead; i += 4)
{
//extracting only left channel
_leftBuffer[index] = buffer[i];
index++;
_leftBuffer[index] = buffer[i + 1];
index++;
}
// How to play _leftBuffer (Single channel, 2 bytes per sample, 44100 samples per secound)
}
First, you need to implement IWaveProvider or user one of the IWaveProvider implementations that come with NAudio like WaveProvider16, for example. Next, Initialize a WaveOut object with your IWaveProvider using WaveOut.Init(IWaveProvider Provider), and finally, call WaveOut.Play().
YES, I have found a solution: A low-level audio player in C#
Full worked code:
public partial class Form1 : Form
{
private byte[] _leftBuffer;
private BiQuadFilter _leftFilter;
private BiQuadFilter _rightFilter;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
using (var reader = new Mp3FileReader(openFileDialog1.FileName))
{
var pcmLength = (int)reader.Length;
_leftBuffer = new byte[pcmLength / 2];
var buffer = new byte[pcmLength];
var bytesRead = reader.Read(buffer, 0, pcmLength);
int index = 0;
for (int i = 0; i < bytesRead; i += 4)
{
_leftBuffer[index] = buffer[i];
index++;
_leftBuffer[index] = buffer[i + 1];
index++;
}
var player = new WaveLib.WaveOutPlayer(-1, new WaveLib.WaveFormat(44100, 16, 1), _leftBuffer.Length, 1, (data, size) =>
{
byte[] b = _leftBuffer;
System.Runtime.InteropServices.Marshal.Copy(b, 0, data, size);
});
}
}
}

Byte array to int16 array

Is there a more efficient way to convert byte array to int16 array ?? or is there a way to use Buffer.BlockCopy to copy evry two byte to int16 array ???
public static int[] BYTarrToINT16arr(string fileName)
{
try
{
int bYte = 2;
byte[] buf = File.ReadAllBytes(fileName);
int bufPos = 0;
int[] data = new int[buf.Length/2];
byte[] bt = new byte[bYte];
for (int i = 0; i < buf.Length/2; i++)
{
Array.Copy(buf, bufPos, bt, 0, bYte);
bufPos += bYte;
Array.Reverse(bt);
data[i] = BitConverter.ToInt16(bt, 0);
}
return data;
}
catch
{
return null;
}
}
Use a FileStream and a BinaryReader. Something like this:
var int16List = List<Int16>();
using (var stream = new FileStream(filename, FileMode.Open))
using (var reader = new BinaryReader(stream))
{
try
{
while (true)
int16List.Add(reader.ReadInt16());
}
catch (EndOfStreamException ex)
{
// We've read the whole file
}
}
return int16List.ToArray();
You can also read the whole file into a byte[], and then use a MemoryStream instead of the FileStream if you want.
If you do this then you'll also be able to size the List approrpriately up front and make it a bit more efficient.
Apart from having an off-by-one possibility in case the number of bytes is odd (you'll miss the last byte) your code is OK. You can optimize it by dropping the bt array altogether, swapping i*2 and i*2+1 bytes before calling BitConverter.ToInt16, and passing i*2 as the starting index to the BitConverter.ToInt16 method.
This works if you don't mind using interopservices. I assume it is faster than the other techniques.
using System.Runtime.InteropServices;
public Int16[] Copy_Byte_Buffer_To_Int16_Buffer(byte[] buffer)
{
Int16[] result = new Int16[1];
int size = buffer.Length;
if ((size % 2) != 0)
{
/* Error here */
return result;
}
else
{
result = new Int16[size/2];
IntPtr ptr_src = Marshal.AllocHGlobal (size);
Marshal.Copy (buffer, 0, ptr_src, size);
Marshal.Copy (ptr_src, result, 0, result.Length);
Marshal.FreeHGlobal (ptr_src);
return result;
}
}
var bytes = File.ReadAllBytes(path);
var ints = bytes.TakeWhile((b, i) => i % 2 == 0).Select((b, i) => BitConverter.ToInt16(bytes, i));
if (bytes.Length % 2 == 1)
{
ints = ints.Union(new[] {BitConverter.ToInt16(new byte[] {bytes[bytes.Length - 1], 0}, 0)});
}
return ints.ToArray();
try...
int index = 0;
var my16s = bytes.GroupBy(x => (index++) / 2)
.Select(x => BitConverter.ToInt16(x.Reverse().ToArray(),0)).ToList();

Categories

Resources