creating an integer array from .wav audio samples. NAudio C# - c#

I am very new to digital audio programming and am not sure on if what I am doing is correct to get the desired outcome. I am trying to take a .wav file, and save the individual samples in an array so i can analyze them. I am using NAudio AudioFileReader, the following code prints out a vast number of floating point numbers, I have no idea if they would be correct, or they are being altered when converted. Ideally I would like them as 32 bit integers. Any advice on how to get there and understand greatly appreciated.
AudioFileReader readertest = new AudioFileReader("C:\\Users\\minford\\Downloads\\Kalimba.wav");
int bytesnumber = (int)readertest.Length;
var buffer = new float[bytesnumber];
readertest.Read(buffer,0,bytesnumber);
for(int i = 0; i <buffer.Length; i++){
Console.Write(buffer[i]+ ", ");
}

Yes, this will print out all the samples as floating point normalised into the range +/- 1.0.
And yes, you will see lots of numbers as there will be many thousands of samples per second.
I'm not sure why you need them as 32 bit integers. It's likely that the original samples are 16 bit integers, which is the most common choice for WAV files. You can use WaveFileReader to read the raw data out into a byte array, and then use any one of several techniques for converting byte array to short array.

Related

Kinect Audio PCM Values

Im using kinect to extract audio and classifie its features, but i have a question. On http://msdn.microsoft.com/en-us/library/hh855698.aspx it says the audio.start method Opens an audio data stream (16-bit PCM format, sampled at 16 kHz) and starts capturing audio data streamed out of a sensor. The problem is that i dont know how pcm data is represented and i dont know if the method returns pcm true values or not. Because using the sdk examples i get values like 200, 56, 17 and i think audio values are more like -3*10^-5 .
So does anyone know how do i get the true PCM values? Or am i doing something wrong?
Thanks
I wouldn't expect any particular values. 16-bit PCM means it's a series of 16-bit integers, so -3*10-5 (-0.00003) isn't representable.
I would guess it's encoded with 16-bit signed integers (like a WAV file) which have a range of -32768 to 32767. If you're being very quiet the values will probably be close to 0. If you make a lot of noise you will see some higher values too.
Check out this diagram (from Wikipedia's article on PCM) which shows a sine wave encoded as PCM using 4-bit unsigned integers, which have a range of 0 to 15.
See how that 4-bit sine wave oscillates around 7? That's it's equilibrium. If it was a signed 4-bit integer (which has a range of -8 to 7) it would have the same shape, but its equilibrium would be 0 - the values would be shifted by -8 so it would oscillate around 0.
You can measure the distance from the equilibrium to the highest or lowest points of the sine wave to get its amplitude, or broadly, it's volume (which is why if you're quiet you will mostly see values near 0 in your signed 16-bit data). This is probably the easiest sort of feature detection you can do. You can find plenty of good explanations on the web about this, for example http://scienceaid.co.uk/physics/waves/sound.html.
You could save it to a file and play it back with something like Audacity if you're not sure. Fiddle with the input settings and you'll soon figure out the format.

computing 31 bit number / ignoring most significant bit

I am working on a piece of software that analyzes E01 bitstream images. Basically these are forensic data files that allow a user to compress all the data on a disk into a single file. The E01 format embeds data about the original data, including MD5 hash of the source and resulting data, etc. If you are interested in some light reading, the EWF/E01 specification is here. Onto my problem:
The e01 file contains a "table" section which is a series of 32 bit numbers that are offsets to other locations within the e01 file where the actual data chunks are located. I have successfully parsed this data out into a list doing the following:
this.ChunkLocations = new List<int>();
//hack:Will this overflow? We are adding to integers to a long?
long currentReadLocation = TableSectionDescriptorRef.OffsetFromFileStart + c_SECTION_DESCRIPTOR_LENGTH + c_TABLE_HEADER_LENGTH;
byte[] currReadBytes;
using (var fs = new FileStream(E01File.FullName, FileMode.Open))
{
fs.Seek(currentReadLocation, 0);
for (int i = 0; i < NumberOfEntries; i++)
{
currReadBytes = new byte[c_CHUNK_DATA_OFFSET_LENGTH];
fs.Read(currReadBytes,0, c_CHUNK_DATA_OFFSET_LENGTH);
this.ChunkLocations.Add(BitConverter.ToUInt32(currReadBytes, 0));
}
}
The c_CHUNK_DATA_OFFSET_LENGTH is 4 bytes/ "32 bit" number.
According to the ewf/e01 specification, "The most significant bit in the chunk data offset indicates if the chunk is compressed (1) or uncompressed (0)". This appears to be evidenced by the fact that, if I convert the offsets to ints, there are large negative numbers in the results (for chunks without compression,no doubt), but most of the other offsets appear to be correctly incremented, but every once in a while there is crazy data. The data in the ChunkLocations looks something like this:
346256
379028
-2147071848
444556
477328
510100
Where with -2147071848 it appears the MSB was flipped to indicate compression/lack of compression.
QUESTIONS: So, if the MSB is used to flag for the presence of compression, then really I'm dealing with at 31 bit number, right?
1. How do I ignore the MSB/ compute a 31 bit number in figuring the offset value?
2. This seems to be a strange standard since it would seem like it would significantly limit the size of the offsets you could have, so I'm questioning if I'm missing something? These offsets to seem correct when I navigate to these locations within the e01 file.
Thanks for any help!
This sort of thing is typical when dealing with binary formats. As dtb pointed out, 31 bits is probably plenty large for this application, because it can address offsets up to 2 GiB. So they use that extra bit as a flag to save space.
You can just mask off the bit with a bitwise AND:
const UInt32 COMPRESSED = 0x80000000; // Only bit 31 on
UInt32 raw_value = 0x80004000; // test value
bool compressed = (raw_value & COMPRESSED) > 0;
UInt32 offset = raw_value & ~COMPRESSED;
Console.WriteLine("Compressed={0} Offset=0x{1:X}", compressed, offset);
Output:
Compressed=True Offset=0x4000
If you just want to strip off the leading bit, perform a bitwise and (&) of the value with 0x7FFFFFFF

Compression of a very short txt file (consists of strings only) C#

I want to compress a txt file of 1.7Kb that has only strings of numbers in it.
The data is just reading of current at different voltages(100 entries)
Want to compress and write it in a smart card that has memory only 512 bits.
Could anyone help with the compression techniques available in C#.
I have tried gzip n Lzma n common techiques such as difference mechanisms n all but i could reach only upto 1kb.
Please provide some solution in C#
The reason why GZipStream gave you a larger file than you expected is that GZipStream produces whole archive files, not just the compressed equivalent of the input. Use DeflateStream instead and you will compress to a fraction of the size, using the exact same algorithm.
Edit#2: This will however save you no more than some 144 bits, and it is not good enough for you. The compressed file is so big for a small file because the Huffman table is constant size with Microsoft's flawed implementation. DotNetZip would have the same format but not the same problem. Or you can use SharpZipLib which supports one other interesting algorithm (format) as well (bzip2); use SetLevel(9) to force maximum compression level that the library can give you.
An excellent explanation of why Microsoft compression worked so badly for you and why DotNetZip or SharpZipLib can do much better even with the same format (basic algorithm), is in this answer by Mark Adler.
A solution could consist in storing data as binary => 100 entries, 4 bytes/entry => 400 bytes.
Then, maybe, you could compress the result.
List<float> myNumbers = ...
MemoryStream ms = new MemoryStream();
using(BinaryWriter bw = new BinaryWriter(stream))
{
foreach(var n in myNumbers)
bw.Write(n);
}
ms.Seek(0, SeekOrigin.Begin);
// Read the first 20 bytes from the stream.
byteArray = new byte[ms.Length];
count = memStream.Read(byteArray, 0, ms.Length);
File.WriteAllBytes(path, byteArray);
And to read:
byte[] content = File.ReadAllBytes(path);
var ms = new MemoryStream(content);
List<float> result = new List<float>()
using(BinaryReader br = new BinaryReader(ms))
{
result.Add(br.ReadSingle());
}
512 bits for 100 entries means about 5 bits per entry. The only way you're going to approach something like that losslessly (which I assume you need) is if the data has some significant predicability from sample to sample, and so the difference between the prediction and actual is small enough to be coded on average in 5 bits. Otherwise there is no hope.
I'm sure that you can compress it much smaller than 1.7KB. If it is really only digits (though I'd wonder what incredible measuring device you have that requires 17 digits per sample), then you should be able to get it down to around 700 bytes.
If you represent your samples with their actual accuracy, then you should be able to get the digits down quite a bit. Perhaps five digits per sample? Then you could get closer to 200 bytes. Still a long way though from 64 bytes (512 bits).
You can use 7ZipSharp library. It's very effective:)

Compression of small string

I have data 0f 340 bytes in string mostly consists of signs and numbers like "føàA¹º#ƒUë5§Ž§"
I want to compress into 250 or less bytes to save it on my RFID card.
As this data is related to finger print temp. I want lossless compression.
So is there any algorithm which i can implement in C# to compress it?
If the data is strictly numbers and signs, I highly recommend changing the numbers into int based values. eg:
+12939272-23923+927392
can be compress into 3 piece of 32-bit integers, which is 22 bytes => 16 bytes. Picking the right integer size (whether 32-bit, 24-bit, 16-bit) should help.
If the integer size varies greatly, you could possibly use 8-bit to begin and use the value 255 to specify that the next 8-bit becomes the 8 more significant bits of the integer, making it 15-bit.
alternatively, you could identify the most significant character and assign 0 for it. the second most significant character gets 10, and the third 110. This is a very crude compression, but if you data is very limited, this might just do the job for you.
Is there any other information you know about your string? For instance does it contain certain characters more often than others? Does it contain all 255 characters or just a subset of them?
If so, huffman encoding may help you, see this or this other link for implementations in C#.
To be honest it just depends on how your input string looks like. What I'd do is try the using rar, zip, 7zip (LZMA) with very small dictionary sizes (otherwise they'll just use up too much space for preprocessed information) and see how big the raw compressed file they produce is (will probably have to use their libraries in order to make them strip headers to conserve space). If any of them produce a file under 250b, then find the c# library for it and there you go.

How to properly read 16 byte unsigned integer with BinaryReader

I need to parse a binary stream in .NET to convert a 16 byte unsigned integer. I would like to use the BinaryReader.ReadUIntXX() functions but there isn't a BinaryReader.ReadUInt128() function available. I assume I will have to roll my own function using the ReadByte function and build an array but I don't know if this is the most efficient method?
Thanks!
I would love to take credit for this, but one quick search of the net, and viola:
http://msdn.microsoft.com/en-us/library/bb384066.aspx
Here is the code sample (which is on the same page)
byte[] bytes = { 0, 0, 0, 25 };
// If the system architecture is little-endian (that is, little end first),
// reverse the byte array.
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
int i = BitConverter.ToInt32(bytes, 0);
Console.WriteLine("int: {0}", i);
// Output: int: 25
The only thing that most developers do not know is the difference between big-endian, and little-endian. Well like most things in life the human race simply can't agree on very simple things (left and right hand cars is a good example as well). When the bits (remember 1 and 0's and binary math), are laid out the order of the bits will determine the value of the field. One byte is eigth bits.. then there is signed and unsigned.. but lets stick to the order. The number 1 (one) can be represented in one of two ways , 10000000 or 00000001 (see clarification in comments for detailed explanation) - as the comment in the code suggests, the big-endian is the one with the one in front, litte-endian is the one with zero. (see http: // en.wikipedia.org/wiki/Endianness -sorry new user and they wont' let me hyperlink more than once....) Why can't we all just agree???
I learned this lesson many years ago when dealing with embedded systems....remember linking? :) Am I showing my age??
I think the comments from 0xA3, SLaks, and Darin Dimitrov answered the question but to put it all together.
BinaryReader.ReadUInt128() is not supported in the binary reader class in .NET and the only solution I could find was to create my own function. As 0xA3 mentioned, there is a BigInt data type in .NET 4.0. I am in the process of creating my own function based upon everyone's comments.
Thanks!
a guid is exactly 16 bytes in size.
Guid guid = new Guid(byteArray);
But you cannot do maths with a Guid. If you need to, you can search for some implementations of a BigInteger for .net on the internet. You can then convert your bytearray into a BigInteger.

Categories

Resources