I'm trying to convert a base64 into a byte[] and in a audioClip but i'm getting some noise in my sound.
I'm using this class to convert byte[] to AudioClip.
using UnityEngine;
using System.Collections;
using System.IO;
using System;
namespace WWUtils.Audio{
public class WAV {
// properties
public float[] LeftChannel { get; internal set; }
public float[] RightChannel { get; internal set; }
public int ChannelCount { get; internal set; }
public int SampleCount { get; internal set; }
public int Frequency { get; internal set; }
// convert two bytes to one float in the range -1 to 1
static float bytesToFloat(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 / 32768.0F;
}
static int bytesToInt(byte[] bytes,int offset=0){
int value=0;
for(int i=0;i<4;i++){
value |= ((int)bytes[offset+i])<<(i*8);
}
return value;
}
private static byte[] GetBytes(string filename){
return File.ReadAllBytes(filename);
}
// Returns left and right double arrays. 'right' will be null if sound is mono.
public WAV(string filename):
this(GetBytes(filename)) {}
public WAV(byte[] wav){
// Determine if mono or stereo
ChannelCount = wav[22]; // Forget byte 23 as 99.999% of WAVs are 1 or 2 channels
// Get the frequency
Frequency = bytesToInt(wav,24);
// Get past all the other sub chunks to get to the data subchunk:
int pos = 12; // First Subchunk ID from 12 to 16
// 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 += 8;
// Pos is now positioned to start of actual sound data.
SampleCount = (wav.Length - pos)/2; // 2 bytes per sample (16 bit sound mono)
if (ChannelCount == 2) SampleCount /= 2; // 4 bytes per sample (16 bit stereo)
// Allocate memory (right will be null if only mono sound)
LeftChannel = new float[SampleCount];
if (ChannelCount == 2) RightChannel = new float[SampleCount];
else RightChannel = null;
// Write to double array/s:
int i=0;
while (pos < wav.Length) {
LeftChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);
pos += 2;
if (ChannelCount == 2) {
RightChannel[i] = bytesToFloat(wav[pos], wav[pos + 1]);
pos += 2;
}
i++;
}
}
public override string ToString (){
return string.Format ("[WAV: LeftChannel={0}, RightChannel={1}, ChannelCount={2}, SampleCount={3}, Frequency={4}]", LeftChannel, RightChannel, ChannelCount, SampleCount, Frequency);
}
}
}
And this to play audioClip
var recByte = System.Convert.FromBase64String(base64);
WAV wav = new WAV(recByte);
AudioClip audioClip = AudioClip.Create("soundLenny-Result",
wav.SampleCount, 1, wav.Frequency, false, false);
audioClip.SetData(wav.LeftChannel, 0);
//PlayClip...
I'm trying to convert one of the following types. https://learn.microsoft.com/pt-br/azure/cognitive-services/speech-service/rest-text-to-speech#audio-outputs
with this riff-16khz-16bit-mono-pcm i get some noise on audio.
i'm tryng to convert this format riff-24khz-16bit-mono-pcm.
If i use riff-24khz-16bit-mono-pcm i get a IndexOutOfRangeException, if a use riff-16khz-16bit-mono-pcm audio is noise
This is the error.
IndexOutOfRangeException: Index was outside the bounds of the array. WWUtils.Audio.WAV..ctor (System.Byte[] wav) (at Assets/Scripts/WAV.cs:68)
If i make this with an microphone recorded wav file the script works fine. How can i correct this?
Related
I have a problem that just baffles me. I import a .wav file and read them as bytes. Then I turn them into integers that I then all divide by 2 (or some other number) in order to decrease the volume. Then I make a new .wav file into which I put the new data. The result is loud and heavy distortion over the original track.
Scroll to the Main() method for the relevant (C#-)code:
using System;
using System.IO;
namespace ConsoleApp2 {
class basic {
public static byte[] bit32(int num) { //turns int into byte array of length 4
byte[] numbyt = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
int pow;
for (int k = 3; k >= 0; k--) {
pow = (int)Math.Pow(16, 2*k + 1);
numbyt[k] += (byte)(16*(num/pow));
num -= numbyt[k]*(pow/16);
numbyt[k] += (byte)(num/(pow/16));
num -= (num/(pow/16))*pow/16;
}
return numbyt;
}
public static byte[] bit16(int num) { //turns int into byte array of length 2
if (num < 0) {
num += 65535;
}
byte[] numbyt = new byte[2] { 0x00, 0x00 };
int pow;
for (int k = 1; k >= 0; k--) {
pow = (int)Math.Pow(16, 2*k + 1);
numbyt[k] += (byte)(16*(num/pow));
num -= numbyt[k]*(pow/16);
numbyt[k] += (byte)(num/(pow/16));
num -= (num/(pow/16))*pow/16;
}
return numbyt;
}
public static int bitint16(byte[] numbyt) { //turns byte array of length 2 into int
int num = 0;
num += (int)Math.Pow(16, 2)*numbyt[1];
num += numbyt[0];
return num;
}
}
class wavfile: FileStream {
public wavfile(string name, int len) : base(name, FileMode.Create) {
int samplerate = 44100;
byte[] riff = new byte[] { 0x52, 0x49, 0x46, 0x46 };
this.Write(riff, 0, 4);
byte[] chunksize;
chunksize = basic.bit32(36 + len*4);
this.Write(chunksize, 0, 4);
byte[] wavebyte = new byte[4] { 0x57, 0x41, 0x56, 0x45 };
this.Write(wavebyte, 0, 4);
byte[] fmt = new byte[] { 0x66, 0x6d, 0x74, 0x20 };
this.Write(fmt, 0, 4);
byte[] subchunk1size = new byte[] { 0x10, 0x00, 0x00, 0x00 };
this.Write(subchunk1size, 0, 4);
byte[] formchann = new byte[] { 0x01, 0x00, 0x02, 0x00 };
this.Write(formchann, 0, 4);
byte[] sampleratebyte = basic.bit32(samplerate);
this.Write(sampleratebyte, 0, 4);
byte[] byterate = basic.bit32(samplerate*4);
this.Write(byterate, 0, 4);
byte[] blockalign = new byte[] { 0x04, 0x00 };
this.Write(blockalign, 0, 2);
byte[] bits = new byte[] { 0x10, 0x00 };
this.Write(bits, 0, 2);
byte[] data = new byte[] { 0x64, 0x61, 0x74, 0x61 };
this.Write(data, 0, 4);
byte[] samplesbyte = basic.bit32(len*4);
this.Write(samplesbyte, 0, 4);
}
public void sound(int[] w, int len, wavfile wavorigin = null) {
byte[] wavbyt = new byte[len*4];
for (int t = 0; t < len*2; t++) {
byte[] wavbit16 = basic.bit16(w[t]);
wavbyt[2*t] = wavbit16[0];
wavbyt[2*t + 1] = wavbit16[1];
}
this.Write(wavbyt, 0, len*4);
System.Media.SoundPlayer player = new System.Media.SoundPlayer();
player.SoundLocation = this.Name;
while (true) {
player.Play();
Console.WriteLine("repeat?");
if (Console.ReadLine() == "no") {
break;
}
}
}
}
class Program {
static void Main() {
int[] song = new int[45000*2];
byte[] songbyt = File.ReadAllBytes("name.wav"); //use your stereo, 16bits per sample wav-file
for (int t = 0; t < 45000*2; t++) {
byte[] songbytsamp = new byte[2] { songbyt[44 + 2*t], songbyt[44 + 2*t + 1] }; //I skip the header
song[t] = basic.bitint16(songbytsamp)/2; //I divide by 2 here, remove the "/2" to hear the normal sound again
//song[t] *= 2;
}
wavfile wav = new wavfile("test.wav", 45000); //constructor class that writes the header of a .wav file
wav.sound(song, 45000); //method that writes the data from "song" into the .wav file
}
}
}
The problem is not the rounding down that happens when you divide an odd number by 2; you can uncomment the line that says song[t] *= 2; and hear for yourself that all of the distortion has completely disappeared again.
I must be making a small stupid mistake somewhere, but I cannot find it. I just want to make the sound data quieter to avoid distortion when I add more sounds to it.
Well, I knew it would be something stupid, and I was right. I forgot to account for the fact that negative numbers are written in signed 16 bit language as the numbers above 2^15, and when you divide by 2, you push them into (very large) positive values. I altered my code to substract 2^16 from any number that's above 2^15 before dividing by 2. I have to thank this person though: How to reduce volume of wav stream?
If this means that my question was a duplicate, then go ahead and delete it, but I'm letting it stay for now, because someone else might find it helpful.
Using Math.Pow to do bit and byte operations is a really bad idea. That function takes double values as inputs and returns a double. It also does exponentiation (not a trivial operation). Using traditional bit shift and mask operations is clearer, much faster and less likely to introduce noise (because of the inaccuracy of doubles).
As you noticed, you really want to work with unsigned quantities (like uint/UInt32 and ushort/UInt16). Sign extension trips up everyone when doing this sort of work.
This is not a full answer to your question, but it does present a way to do the byte operations that is arguably better.
First, create a small struct to hold a combination of a bit-mask and a shift quantity:
public struct MaskAndShift {
public uint Mask {get; set;}
public int Shift {get; set;}
}
Then I create two arrays of these structs for describing what should be done to extract individual bytes from a uint or a ushort. I put them both in a static class named Worker:
public static class Worker {
public static MaskAndShift[] Mask32 = new MaskAndShift[] {
new MaskAndShift {Mask = 0xFF000000, Shift = 24},
new MaskAndShift {Mask = 0x00FF0000, Shift = 16},
new MaskAndShift {Mask = 0x0000FF00, Shift = 8},
new MaskAndShift {Mask = 0x000000FF, Shift = 0},
};
public static MaskAndShift[] Mask16 = new MaskAndShift[] {
new MaskAndShift {Mask = 0x0000FF00, Shift = 8},
new MaskAndShift {Mask = 0x000000FF, Shift = 0},
};
}
Looking at the first entry in the first array, it says "to extract the first byte from a uint, mask that uint with 0xFF000000 and shift the result 24 bits to the right". If you have endian-ness issues, you can simply re-order the entries in the array.
Then I created this static function (in the Worker class) to convert a uint / UInt32 to an array of four bytes:
public static byte[] UintToByteArray (uint input) {
var bytes = new byte[4];
int i = 0;
foreach (var maskPair in Mask32) {
var masked = input & maskPair.Mask;
if (maskPair.Shift != 0) {
masked >>= maskPair.Shift;
}
bytes[i++] = (byte) masked;
}
return bytes;
}
The code to do the same operation for a 16 bit ushort (aka UInt16) looks nearly the same (there's probably an opportunity for some refactoring here):
public static byte[] UShortToByteArray (ushort input) {
var bytes = new byte[2];
int i = 0;
foreach (var maskPair in Mask16) {
var masked = input & maskPair.Mask;
if (maskPair.Shift != 0) {
masked >>= maskPair.Shift;
}
bytes[i++] = (byte) masked;
}
return bytes;
}
The reverse operation is much simpler (however, if you have endian-ness issues, you'll need to write the code). Here I just take the entries of the array, add them into a value and shift the result:
public static uint ByteArrayToUint (byte[] bytes) {
uint result = 0;
//note that the first time through, result is zero, so shifting is a noop
foreach (var b in bytes){
result <<= 8;
result += b;
}
return result;
}
Doing this for the 16 bit version ends up being effectively the same code, so...
public static ushort ByteArrayToUshort (byte[] bytes) {
return (ushort) ByteArrayToUint(bytes);
}
Bit-twiddling never works the first time. So I wrote some test code:
public static void Main(){
//pick a nice obvious pattern
uint bit32Test = (((0xF1u * 0x100u) + 0xE2u) * 0x100u + 0xD3u) * 0x100u + 0xC4u;
Console.WriteLine("Start");
Console.WriteLine("Input 32 Value: " + bit32Test.ToString("X"));
var bytes32 = Worker.UintToByteArray(bit32Test);
foreach (var b in bytes32){
Console.WriteLine(b.ToString("X"));
}
Console.WriteLine();
ushort bit16Test = (ushort)((0xB5u * 0x100u) + 0xA6u);
Console.WriteLine("Input 16 Value: " + bit16Test.ToString("X"));
var bytes16 = Worker.UShortToByteArray(bit16Test);
foreach (var b in bytes16){
Console.WriteLine(b.ToString("X"));
}
Console.WriteLine("\r\nNow the reverse");
uint reconstitued32 = Worker.ByteArrayToUint(bytes32);
Console.WriteLine("Reconstituted 32: " + reconstitued32.ToString("X"));
ushort reconstitued16 = Worker.ByteArrayToUshort(bytes16);
Console.WriteLine("Reconstituted 16: " + reconstitued16.ToString("X"));
}
The output from that test code looks like:
Start
Input 32 Value: F1E2D3C4
F1
E2
D3
C4
Input 16 Value: B5A6
B5
A6
Now the reverse
Reconstituted 32: F1E2D3C4
Reconstituted 16: B5A6
Also note that I do everything in hexadecimal - it makes everything so much easier to read and to understand.
I have an object that has the following variables:
bool firstBool;
float firstFloat; (0.0 to 1.0)
float secondFloat (0.0 to 1.0)
int firstInt; (0 to 10,000)
I was using a ToString method to get a string that I can send over the network. Scaling up I have encountered issues with the amount of data this is taking up.
the string looks like this at the moment:
"false:1.0:1.0:10000" this is 19 characters at 2 bytes per so 38 bytes
I know that I can save on this size by manually storing the data in 4 bytes like this:
A|B|B|B|B|B|B|B
C|C|C|C|C|C|C|D
D|D|D|D|D|D|D|D
D|D|D|D|D|X|X|X
A = bool(0 or 1), B = int(0 to 128), C = int(0 to 128), D = int(0 to 16384), X = Leftover bits
I convert the float(0.0 to 1.0) to int(0 to 128) since I can rebuild them on the other end and the accuracy isn't super important.
I have been experimenting with BitArray and byte[] to convert the data into and out of the binary structure.
After some experiments I ended up with this serialization process(I know it needs to be cleaned up and optimized)
public byte[] Serialize() {
byte[] firstFloatBytes = BitConverter.GetBytes(Mathf.FloorToInt(firstFloat * 128)); //Convert the float to int from (0 to 128)
byte[] secondFloatBytes = BitConverter.GetBytes(Mathf.FloorToInt(secondFloat * 128)); //Convert the float to int from (0 to 128)
byte[] firstIntData = BitConverter.GetBytes(Mathf.FloorToInt(firstInt)); // Get the bytes for the int
BitArray data = new BitArray(32); // create the size 32 bitarray to hold all the data
int i = 0; // create the index value
data[i] = firstBool; // set the 0 bit
BitArray ffBits = new BitArray(firstFloatBytes);
for(i = 1; i < 8; i++) {
data[i] = ffBits[i-1]; // Set bits 1 to 7
}
BitArray sfBits = new BitArray(secondFloatBytes);
for(i = 8; i < 15; i++) {
data[i] = sfBits[i-8]; // Set bits 8 to 14
}
BitArray fiBits = new BitArray(firstIntData);
for(i = 15; i < 29; i++) {
data[i] = fiBits[i-15]; // Set bits 15 to 28
}
byte[] output = new byte[4]; // create a byte[] to hold the output
data.CopyTo(output,0); // Copy the bits to the byte[]
return output;
}
Getting the information back out of this structure is much more complicated than getting it into this form. I figure I can probably workout something using the bitwise operators and bitmasks.
This is proving to be more complicated than I was expecting. I thought it would be very easy to access the bits of a byte[] to manipulate the data directly, extract ranges of bits, then convert back to the values required to rebuild the object. Are there best practices for this type of data serialization? Does anyone know of a tutorial or example reference I could read?
Standard and efficient serialization methods are:
Using BinaryWriter / BinaryReader:
public byte[] Serialize()
{
using(var s = new MemoryStream())
using(var w = new BinaryWriter(s))
{
w.Write(firstBool);
w.Write(firstFloat);
...
return s.ToArray();
}
}
public void Deserialize(byte[] bytes)
{
using(var s = new MemoryStream(bytes))
using(var r = new BinaryReader(s))
{
firstBool = r.ReadBool();
firstFload = r.ReadFloat();
...
}
}
Using protobuf.net
BinaryWriter / BinaryReader is much faster (around 7 times). Protobuf is more flexible, easy to use, very popular and serializes into around 33% fewer bytes. (of course these numbers are orders of magnitude and depend on what you serialize and how).
Now basically BinaryWriter will write 1 + 4 + 4 + 4 = 13 bytes. You shrink it to 5 bytes by converting the values to bool, byte, byte, short first by rounding it the way you want. Finally it's easy to merge the bool with one of your bytes to get 4 bytes if you really want to.
I don't really discourage manual serialization. But it has to be worth the price in terms of performance. The code is quite unreadable. Use bit masks and binary shifts on bytes directly but keep it as simple as possible. Don't use BitArray. It's slow and not more readable.
Here is a simple method for pack/unpack. But you loose accuracy converting a float to only 7/8 bits
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
foreach (Data data in Data.input)
{
Data.Print(data);
Data results = Data.Unpack(Data.Pack(data));
Data.Print(results);
}
Console.ReadLine();
}
}
public class Data
{
public static List<Data> input = new List<Data>() {
new Data() { firstBool = true, firstFloat = 0.2345F, secondFloat = 0.432F, firstInt = 12},
new Data() { firstBool = true, firstFloat = 0.3445F, secondFloat = 0.432F, firstInt = 11},
new Data() { firstBool = false, firstFloat = 0.2365F, secondFloat = 0.432F, firstInt = 9},
new Data() { firstBool = false, firstFloat = 0.545F, secondFloat = 0.432F, firstInt = 8},
new Data() { firstBool = true, firstFloat = 0.2367F, secondFloat = 0.432F, firstInt = 7}
};
public bool firstBool { get; set; }
public float firstFloat {get; set; } //(0.0 to 1.0)
public float secondFloat {get; set; } //(0.0 to 1.0)
public int firstInt { get; set; } //(0 to 10,000)
public static byte[] Pack(Data data)
{
byte[] results = new byte[4];
results[0] = (byte)((data.firstBool ? 0x80 : 0x00) | (byte)(data.firstFloat * 128));
results[1] = (byte)(data.secondFloat * 256);
results[2] = (byte)((data.firstInt >> 8) & 0xFF);
results[3] = (byte)(data.firstInt & 0xFF);
return results;
}
public static Data Unpack(byte[] data)
{
Data results = new Data();
results.firstBool = ((data[0] & 0x80) == 0) ? false : true;
results.firstFloat = ((float)(data[0] & 0x7F)) / 128.0F;
results.secondFloat = (float)data[1] / 256.0F;
results.firstInt = (data[2] << 8) | data[3];
return results;
}
public static void Print(Data data)
{
Console.WriteLine("Bool : '{0}', 1st Float : '{1}', 2nd Float : '{2}', Int : '{3}'",
data.firstBool,
data.firstFloat,
data.secondFloat,
data.firstInt
);
}
}
}
I am trying to program a PLC address generator. However there I need to make bit wise addition to find the next available address.
Meaning if I start with the adress 0.0 and add 2 bit then the next free adress would be 0.3. It goes up until 0.7 then then next adress is 1.0 up to 1.7 then 2.0 and so on.
Depending on what datatype I add to the addition the next free adress should be calculated.
For example a bool is one bit. 0.1 -> 0.2 -> 0.3 and so on
A Byte has 8 bits if I add a byte and the last free adress was 0.4 the next free address should be 2.0.
A Word has 16 Bits so 0.0 -> 2.0 -> 4.0 and so on.
A Double Word has 32 Bits so 0.0 -> 4.0 -> 8.0 and so on.
I am looking for an implementation in c# where I can add the different types as input and it adds it and gives me corresponding address and stores then next free address internal for the next operation.
For example:
Type Startaddress
1 Bool 0.0 (->0.1)
2 Bool 0.1 (->0.2)
3 Byte 1.0 (->1.7) as 8 bits are required
4 Bool 2.0 (->2.1)
5 Word 3.0 (->4.7) as 16 bits are required
6 Double Word 5.0 (->8.7) as 32 bits are required
Any idea how I could implement that apart from a lot of if else and loop? I am looking for an elegant overloaded operator approach.
The only "trick" to your problem is the notation of .0-.7 for bit addresses and the C# types don't match up exactly with the types in your specification.
The main class I show here stores the address as bit offset internally, and provides the integer and decimal fraction through the fAddress() method.
Your example shows alignment on byte boundaries, but doesn't align words or double words--so that's what I implemented. Comments show how to do that differently if the PLC cares.
You'll need to add the code to store values at the byte.bit type addresses.
using System;
namespace PLCAddress
{
class Program
{
static void Main(string[] args)
{
PLCAddress a = new PLCAddress();
float address;
bool boolA = true;
byte byteA = 7;
ushort wordA = 65535;
uint dblwordA = 4294967295;
address = a.Store(boolA);
Console.WriteLine(address.ToString());
address = a.Store(boolA);
Console.WriteLine(address.ToString());
address = a.Store(byteA);
Console.WriteLine(address.ToString());
address = a.Store(boolA);
Console.WriteLine(address.ToString());
address = a.Store(wordA);
Console.WriteLine(address.ToString());
address = a.Store(dblwordA);
Console.WriteLine(address.ToString());
}
}
public class PLCAddress
{
protected uint _address;
public PLCAddress()
{
_address = 0;
}
public float Store(bool b)
{
float rv = fAddress();
_address += 1;
return rv;
}
public float Store(byte b)
{
float rv = fAddress(8);
_address += 8;
return rv;
}
public float Store(ushort b)
{
float rv = fAddress(8); // use fAddress(16) if words need to be on word boundaries
_address += 16;
return rv;
}
public float Store(uint b)
{
float rv = fAddress(8); // use fAddress(32) if double words need to be on double word boundaries
_address += 32;
return rv;
}
protected float fAddress()
{
return (float)Whole + (float)Fraction / 10;
}
protected float fAddress(uint alignment)
{
uint roundup = alignment - 1;
uint mask = ~roundup;
uint AlignedAddress = _address + roundup;
AlignedAddress = AlignedAddress & mask;
_address = AlignedAddress;
return fAddress();
}
protected uint Whole
{
get { return _address / 8; }
}
protected uint Fraction
{
get { return _address % 8; }
}
}
}
You can store these addresses in an int - the lower part in the first 3 bits, the rest in the rest of the bits and get the address from there. This allows you to do normal arithmetic on these addresses and numbers. If the address is in a string you can do something like this:
public static int ToIntAddress(this string str)
{
var values = str.Split('.');
int lower = int.Parse(values[1]);
int higher = int.Parse(values[0]) << 3;
return lower + higher;
}
public static string ToAddress(this int address) => $"{address >> 3}.{address & 0b0111}";
("3.0".ToIntAddress() + 15).ToAddress() // "4.7"
("5.0".ToIntAddress() + 31).ToAddress() // "8.7"
("0.4".ToIntAddress() + 7).ToAddress() // "1.3"
I personally prefer an object oriented approach:
public class MemoryManager
{
private int _dataSize = 0;
public enum DataTypes
{
Bool = 1,
Byte = 8,
Word = 16,
DWord = 32
}
public MemoryLocation Add(DataTypes type)
{
var address = GetCurrentAddress();
_dataSize += (int)type;
return address;
}
private MemoryLocation GetCurrentAddress()
{
int currentByteLocation = _dataSize / 8;
int currentBitLocation = _dataSize % 8;
return new MemoryLocation(currentByteLocation, currentBitLocation);
}
}
public class MemoryLocation
{
public MemoryLocation(int byteLocation, int bitIndex)
{
ByteLocation = byteLocation;
BitIndex = bitIndex;
}
public int ByteLocation { get; private set; }
public int BitIndex { get; private set; }
public override string ToString()
{
return string.Format("[{0},{1}]", ByteLocation, BitIndex);
}
}
I whipped this out real quick but you can use other more streamlined methods to generate the next address.
You can use this:
public int BitWiseAdd()
{
int FirstNumber = 50;
int SecondNumber = 60;
while (SecondNumber !=0)
{
int carry = FirstNumber & SecondNumber;
FirstNumber = FirstNumber ^ SecondNumber;
SecondNumber = carry << 1;
}
return FirstNumber;
}
I want to send integer numbers (between 101 and 1616)from the c# program to the arduino Uno using a usb port.
I know how to use registers of the arduino Uno and wanted to know if there is a interrupt when reviving data over this USB port.
At the moment I am using this but it isn't working.
if(Serial.available()!=0)
{
input= (unsigned char)Serial.read();
}
And on the C# program I am using this code:
byte[] b = BitConverter.GetBytes(MyIntx);
SerialPort.Write(b, 0, 4);
How can i send bigger numbers between the c# program and the arduino uno?
And is there a special interrupt for receiving these type of numbers?
What you need to do is send byte by byte. There are complex solutions and there are easy ones
Complex: from https://www.baldengineer.com/arduino-multi-digit-integers.html
void setup() {
Serial.begin(9600);
}
unsigned int integerValue=0; // Max value is 65535
char incomingByte;
void loop() {
if (Serial.available() > 0) { // something came across serial
integerValue = 0; // throw away previous integerValue
while(1) { // force into a loop until 'n' is received
incomingByte = Serial.read();
if (incomingByte == '\n') break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
integerValue *= 10; // shift left 1 decimal place
// convert ASCII to integer, add, and shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue);
}
Serial.println(integerValue); // Do something with the value
}
}
My Version:
Convert Int to Char, Send byte by byte and In Arduino Convert it back to Int.
int x=150;
string x_char = x.ToString();
for(int i=0;i<x_char.length();i++)
{
//Send Each Character to Arduino "c_char[i]".
}
//Send a new line or any special character to mark the break. For Instance "\n";
IN Arduino:
String a;
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
while(Serial.available()) {
a= Serial.readStringUntil('\n'); //Read until new line
x = Serial.parseInt(); //This is your Integer value
}
}
Connect();
if (serialPort1.IsOpen)
{
int MyInt = ToInt32(lblMixerCase.Text);
byte[] b = GetBytes(MyInt);
serialPort1.Write(b, 0, 1);
int MyInt2 = ToInt32(txtRPM.Text);
if (MyInt2<=255)
{
byte[] z = GetBytes(MyInt2);
serialPort1.Write(z, 0, 1); //For first 1 byte numbers
}
else if (MyInt2<=510)
{
byte[] r = GetBytes(MyInt2);
serialPort1.Write(r, 0, 2); for 2 byte numbers
}
else if (MyInt2<=765)
{
byte[] a = GetBytes(MyInt2);
serialPort1.Write(a, 0, 3); //for 3 byte numbers
}
else if (MyInt2<=1020)
{
byte[] q = GetBytes(MyInt2);
serialPort1.Write(q, 0, 4); //for 4 byte numbers
}
Is there a method (in c#/.net) that would left-shift (bitwise) each short in a short[] that would be faster then doing it in a loop?
I am talking about data coming from a digital camera (16bit gray), the camera only uses the lower 12 bits. So to see something when rendering the data it needs to be shifted left by 4.
This is what I am doing so far:
byte[] RawData; // from camera along with the other info
if (pf == PixelFormats.Gray16)
{
fixed (byte* ptr = RawData)
{
short* wptr = (short*)ptr;
short temp;
for (int line = 0; line < ImageHeight; line++)
{
for (int pix = 0; pix < ImageWidth; pix++)
{
temp = *(wptr + (pix + line * ImageWidth));
*(wptr + (pix + line * ImageWidth)) = (short)(temp << 4);
}
}
}
}
Any ideas?
I don't know of a library method that will do it, but I have some suggestions that might help. This will only work if you know that the upper four bits of the pixel are definitely zero (rather than garbage). (If they are garbage, you'd have to add bitmasks to the below). Basically I would propose:
Using a shift operator on a larger data type (int or long) so that you are shifting more data at once
Getting rid of the multiply operations inside your loop
Doing a little loop unrolling
Here is my code:
using System.Diagnostics;
namespace ConsoleApplication9 {
class Program {
public static void Main() {
Crazy();
}
private static unsafe void Crazy() {
short[] RawData={
0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777, 0x888,
0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff, 0x123, 0x456,
//extra sentinel value which is just here to demonstrate that the algorithm
//doesn't go too far
0xbad
};
const int ImageHeight=2;
const int ImageWidth=9;
var numShorts=ImageHeight*ImageWidth;
fixed(short* rawDataAsShortPtr=RawData) {
var nextLong=(long*)rawDataAsShortPtr;
//1 chunk of 4 longs
// ==8 ints
// ==16 shorts
while(numShorts>=16) {
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
numShorts-=16;
}
var nextShort=(short*)nextLong;
while(numShorts>0) {
*nextShort=(short)(*nextShort<<4);
nextShort++;
numShorts--;
}
}
foreach(var item in RawData) {
Debug.Print("{0:X4}", item);
}
}
}
}