Naudio - putting audio stream into values [-1,1] - c#

Hi all I need to put my audio stream into values of [-1,1].
Can someone tell me a good approach. I was reading byte array and float array from stream but I don't know what to do next.
Here is my code:
float[] bytes=new float[stream.Length];
float biggest= 0;
for (int i = 0; i < stream.Length; i++)
{
bytes[i] = (byte)stream.ReadByte();
if (bytes[i] > biggest)
{
biggest=bytes[i];
}
}
and I don't know how to put values into stream. Because byte is only positive values. And I need to have from [-1,1]
for (int i = 0; i < bytes.Count(); i++)
{
bytes[i] = (byte)(bytes[i] * (1 / biggest));
}

In your second code snippet, you're scaling the values, but using integers to do it. Have you tried just using the float values directly:
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] /= biggest; // scale bytes to 0..1
bytes[i] *= 2; // scale bytes to 0..2
bytes[i]--; // scale bytes to -1..1
}
Btw bytes is a more-than-slightly-confusing variable name for an array of floats.

Related

Mirroring in image vertical from a byte array

I want to create a DataMatrix decoder in C#. I'm using the ZXing.NET libary for this. I already coded a QR decoder with ZXing, but somehow for the DataMatrix decoder i need to mirror the picture to get it successful decoded.
So i have in image (128x128) its data is stored in a byte 1d array. The bytes in the array are representing the color of each pixel, so byte[0] would be the color of the pixel (0/0).
Now i want to mirror the picture and save the mirrored picture in another byte array
Can somebody tell me how to do this?
I guess you're looking for something like this:
Mirror vertically:
byte[] MirrorY(int size, byte[] inputArray)
{
byte[] reversedArray = new byte[inputArray.Length];
for (int i = 0; i < inputArray.Length/size; i++){
System.Array.Copy(inputArray, reversedArray.Length - (i+ 1) * size, reversedArray, i* size, size);
}
return reversedArray;
}
Mirror horizontally:
byte[] MirrorX(int size, byte[] inputArray)
{
byte[] reversedArray = new byte[inputArray.Length];
for (int i = 0; i < inputArray.Length/size; i++){
for (int j = 0; j < size; j++){
reversedArray [i * size + j] = inputArray [(i + 1) * size - j - 1];
}
}
return reversedArray;
}

How to append/insert bytes? [duplicate]

I want to add some string in the middle of image metadata block. Under some specific marker. I have to do it on bytes level since .NET has no support for custom metadata fields.
The block is built like 1C 02 XX YY YY ZZ ZZ ZZ ... where XX is the ID of the field I need to append and YY YY is the size of it, ZZ = data.
I imagine it should be more or less possible to read all the image data up to this marker (1C 02 XX) then increase the size bytes (YY YY), add data at the end of ZZ and then add the rest of the original file? Is this correct?
How should I go on with it? It needs to work as fast as possible with 4-5 MB JPEG files.
In general there is no way to speed up this operation. You have to read at least portion that needs to be moved and write it again in updated file. Creating new file and copying content to it may be faster if you can parallelize read and write operations.
Note: In you particular case it may not be possible to just insert content in the middle of the file as most of file formats are not designed with such modifcations in mind. Often there are offsets to portions of the file that will be invalid when you shift part of the file. Specifying what file format you trying to work with may help other people to provide better approaches.
Solved the problem with this code:
List<byte> dataNew = new List<byte>();
byte[] data = File.ReadAllBytes(jpegFilePath);
int j = 0;
for (int i = 1; i < data.Length; i++)
{
if (data[i - 1] == (byte)0x1C) // 1C IPTC
{
if (data[i] == (byte)0x02) // 02 IPTC
{
if (data[i + 1] == (byte)fileByte) // IPTC field_number, i.e. 0x78 = IPTC_120
{
j = i;
break;
}
}
}
}
for (int i = 0; i < j + 2; i++) // add data from file before this field
dataNew.Add(data[i]);
int countOld = (data[j + 2] & 255) << 8 | (data[j + 3] & 255); // curr field length
int countNew = valueToAdd.Length; // new string length
int newfullSize = countOld + countNew; // sum
byte[] newSize = BitConverter.GetBytes((Int16)newfullSize); // Int16 on 2 bytes (to use 2 bytes as size)
Array.Reverse(newSize); // changes order 10 00 to 00 10
for (int i = 0; i < newSize.Length; i++) // add changed size
dataNew.Add(newSize[i]);
for (int i = j + 4; i < j + 4 + countOld; i++) // add old field value
dataNew.Add(data[i]);
byte[] newString = ASCIIEncoding.ASCII.GetBytes(valueToAdd);
for (int i = 0; i < newString.Length; i++) // append with new field value
dataNew.Add(newString[i]);
for (int i = j + 4 + newfullSize; i < data.Length; i++) // add rest of the file
dataNew.Add(data[i]);
byte[] finalArray = dataNew.ToArray();
File.WriteAllBytes(Path.Combine(Path.GetDirectoryName(jpegFilePath), "newfile.jpg"), finalArray);
Here is an easy and quite fast solution. It moves all bytes after given offset to their new position according to given extraBytes, so you can insert your data.
public void ExpandFile(FileStream stream, long offset, int extraBytes)
{
// http://stackoverflow.com/questions/3033771/file-io-with-streams-best-memory-buffer-size
const int SIZE = 4096;
var buffer = new byte[SIZE];
var length = stream.Length;
// Expand file
stream.SetLength(length + extraBytes);
var pos = length;
int to_read;
while (pos > offset)
{
to_read = pos - SIZE >= offset ? SIZE : (int)(pos - offset);
pos -= to_read;
stream.Position = pos;
stream.Read(buffer, 0, to_read);
stream.Position = pos + extraBytes;
stream.Write(buffer, 0, to_read);
}
Need to be checked, though...

How can I retrieve the highest point from a list of points?

I want extract the high amplitude portion from the audio and related time. Please help me with how I can return the value of x,y axis then sort the value of to get highest point.
NAudio.Wave.WaveChannel32 wave = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName));
byte[] Buffer = new byte[163840];
int read = 0;
while (wave.Position < wave.Length)
{
read = wave.Read(Buffer, 0, 16384);
}
for (int i = 0; i < read / 4; i++)
{
chart1.Series["wave"].Points.Add(BitConverter.ToSingle(Buffer, i * 4));
}
Use the following expression to return the max in your list.
chart1.Series["wave"].Points.ToList().Max()

32-bit Grayscale Tiff with floating point pixel values to array using LibTIFF.NET C#

I just started using LibTIFF.NET in my c# application to read Tiff images as heightmaps obtained from ArcGIS servers. All I need is to populate an array with image's pixel values for terrain generation based on smooth gradients. The image is a LZW compressed 32-bit Grayscale Tiff with floating point pixel values representing elevaion in meters.
It's been some days now that I struggle to return right values but all I get is just "0" values assuming it's a total black or white image!
Here's the code so far: (Updated - Read Update 1)
using (Tiff inputImage = Tiff.Open(fileName, "r"))
{
int width = inputImage.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = inputImage.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int bytesPerPixel = 4;
int count = (int)inputImage.RawTileSize(0); //Has to be: "width * height * bytesPerPixel" ?
int resolution = (int)Math.Sqrt(count);
byte[] inputImageData = new byte[count]; //Has to be: byte[] inputImageData = new byte[width * height * bytesPerPixel];
int offset = 0;
for (int i = 0; i < inputImage.NumberOfTiles(); i++)
{
offset += inputImage.ReadEncodedTile(i, inputImageData, offset, (int)inputImage.RawTileSize(i));
}
float[,] outputImageData = new float[resolution, resolution]; //Has to be: float[,] outputImageData = new float[width * height];
int length = inputImageData.Length;
Buffer.BlockCopy(inputImageData, 0, outputImageData, 0, length);
using (StreamWriter sr = new StreamWriter(fileName.Replace(".tif", ".txt"))) {
string row = "";
for(int i = 0; i < resolution; i++) { //Change "resolution" to "width" in order to have correct array size
for(int j = 0; j < resolution; j++) { //Change "resolution" to "height" in order to have correct array size
row += outputImageData[i, j] + " ";
}
sr.Write(row.Remove(row.Length - 1) + Environment.NewLine);
row = "";
}
}
}
Sample Files & Results: http://terraunity.com/SampleElevationTiff_Results.zip
Already searched everywhere on internet and couldn't find the solution for this specific issue. So I really appreciate the help which makes it useful for others too.
Update 1:
Changed the code based on Antti Leppänen's answer but got weird results which seems to be a bug or am I missing something? Please see uploaded zip file to see the results with new 32x32 tiff images here:
http://terraunity.com/SampleElevationTiff_Results.zip
Results:
LZW Compressed: RawStripSize = ArraySize = 3081 = 55x55 grid
Unompressed: RawStripSize = ArraySize = 65536 = 256x256 grid
Has to be: RawStripSize = ArraySize = 4096 = 32x32 grid
As you see the results, LibTIFF skips some rows and gives irrelevant orderings and it even gets worse if the image size is not power of 2!
Your example file seems to be tiled tiff and not stripped. Console says:
ElevationMap.tif: Can not read scanlines from a tiled image
I changed your code to read tiles. This way it seems to be reading data.
for (int i = 0; i < inputImage.NumberOfTiles(); i++)
{
offset += inputImage.ReadEncodedTile(i, inputImageData, offset, (int)inputImage.RawTileSize(i));
}
I know it could be late, but I had the same mistake recently and I found the solution, so it could be helpful. The mistake is in the parameter count of the function Tiff.ReadEncodedTile(tile, buffer, offset, count). It must be the decompressed bytes size, not the compressed bytes size. That's the reason why you have not all the information, because you are not saving the whole data in your buffer. See how-to-translate-tiff-readencodedtile-to-elevation-terrain-matrix-from-height.
A fast method to read a floating point tiff.
public static unsafe float[,] ReadTiff(Tiff image)
{
const int pixelStride = 4; // bytes per pixel
int imageWidth = image.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int imageHeight = image.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
float[,] result = new float[imageWidth, imageHeight];
int tileCount = image.NumberOfTiles();
int tileWidth = image.GetField(TiffTag.TILEWIDTH)[0].ToInt();
int tileHeight = image.GetField(TiffTag.TILELENGTH)[0].ToInt();
int tileStride = (imageWidth + tileWidth - 1) / tileWidth;
int bufferSize = tileWidth * tileHeight * pixelStride;
byte[] buffer = new byte[bufferSize];
fixed (byte* bufferPtr = buffer)
{
float* array = (float*)bufferPtr;
for (int t = 0; t < tileCount; t++)
{
image.ReadEncodedTile(t, buffer, 0, buffer.Length);
int x = tileWidth * (t % tileStride);
int y = tileHeight * (t / tileStride);
var copyWidth = Math.Min(tileWidth, imageWidth - x);
var copyHeight = Math.Min(tileHeight, imageHeight - y);
for (int j = 0; j < copyHeight; j++)
{
for (int i = 0; i < copyWidth; i++)
{
result[x + i, y + j] = array[j * tileWidth + i];
}
}
}
}
return result;
}

C# Signal Processing Plotting Rapid Data

I have a circuit that sends me two different data from sensors. Data is coming as packets. First data is '$' to separate one packet to another. After '$' it sends 16 bytes microphone data and 1 byte pulse sensor data. I have an array to store incoming data and after plotting the data in each 20 ms, i start to write new bytes from zero index of array. I need to plot these data to different graphs using ZedGraph. However i could not separate those data correctly. Sometimes one or more data of audio are shown in other graph. Here is my code:
for (int i = 0; i < 4; i++)
{
if (data[i * 18] == Convert.ToByte('$'))
{
for (int x = ((i * 18) + 1); x < ((i * 18) + 17); x++)
{
listAuido.Add(time, data[x]);
}
for (int a = ((i * 18) + 17); a < ((i * 18) + 18); a++)
{
listPulse.Add(time, data[a]);
}
}
}
How can i solve this issue?
Circuit settings: BaudRate: 38400, Frequency: 200hz, CommunicationType: RS232.
Port Settings:ReadTimeOut=5 WrtieTimeOut=5;
While reading data i am using codes below. Read_Data1 refers data[] the code above. I have a counter and after plotting the data its value equals zero and i prevent my buffer index out of range exception
byte[] Read_Data1 = new byte[1000];
private void myPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!myPort.IsOpen)
return;
if (myPort.BytesToRead > 0)
{
byte[] buffer = new byte[myPort.BytesToRead];
myPort.Read(buffer, 0, buffer.Length);
DataConversion.bytetobyte(Read_Data1, buffer, buffer.Length, count);
count += buffer.Length;
DataRecord.SaveBytesToFile(buffer, save.FileName);
}
}
public static void bytetobyte(byte[] Storage, byte[] databyte, int datacount, int count)
{
int abc;
for (abc = 0; abc < datacount; abc++)
{
Storage[abc + count] = databyte[abc];
}
}
Without seeing the data stream its hard to understand exactly what's going on but when you multiply by 18 the offset will be different as i increases. in order for that to work you need to be sure that exactly 4 packets are actually in the buffer at this time or things might get weird. Having worked a far bit with rs232 connected measurement hardware I often find that their software is not all that consistent, so I'd be careful about assuming the data is there :)
Look into how and when you're reading data into the data buffer, are you sure it contains fresh data everytime you call your code?
The loop looks correct but its a little difficult to read, I'd rewrite it as
for (int i = 0; i < 4; i++)
{
if (data[i * 18] == Convert.ToByte('$'))
{
for (int x = 0; x < 16; x++)
{
listAuido.Add(time, data[(i * 18) +1 + x]);
}
for (int a = 0; a < 1; a++) // this doesn't really need to be a loop
{
listPulse.Add(time, data[ ((i * 18) + 17)+ a]);
}
}
I looked at the code you added but its not immediately clear how the first bit of code is called by the second. I still think that there is something with the buffer handling that is causing your issue, but you could possibly eliminate that but using the buffer built into the serial port and just one byte at the time:
while(true){ //you could do this on a separate thread or on a timer
if(port.ReadByte() == Convert.ToByte('$')){
for (int x = 0; x < 16; x++)
listAuido.Add(time, port.ReadByte());
listPulse.Add(time, port.ReadByte());
}
}

Categories

Resources