NAudio WaveFileReader.ReadNextSampleFrame() returns invalid amplitudes - c#

I recorded note D to the wav file and want to get array of it's amplitudes. I started to play this note before beginning of recording, so there is no empty interval.
Then I used NAudio.WaveFileReader.ReadNextSampleFrame() to get it's amplitudes but have output with a lot of zeros and rarely encountered non zero values, e.g:
0
0
0.1312
0
0
... a lot of zeros
0.12312
0.123123
0
0
..a lot of zeros
0
0.12312
This is not correct because Ableton shows that sound is wavy:
Here is my code:
using (var reader = new WaveFileReader("record.wav"))
{
var leftAmplitudes = new List<float>();
var rightAmplitudes = new List<float>();
for (int i = 0; i < reader.SampleCount; i++)
{
var sampleFrame = reader.ReadNextSampleFrame();
leftAmplitudes.Add(sampleFrame[0]);
rightAmplitudes.Add(sampleFrame[1]);
}
}
Do you know how can I get actual amplitudes?

Related

All indexes of string-array return null

I've been coding in C# (winforms) for a project for 2 weeks now. My goal is to build a GUI for an FFT-Analysis (frequency-realm).
my Problem:
I keep running into the same problem: i receive 1024 int values (one blocksize) separated by white spaces in one string via serial port and then terminated by \n into a buffer uart_buf. To obtain numeric values, i use uart_buf.split(' ') into a string[] parse_buf and then try to access a single value in ASCII-format like this: parse_buf[i] = val_buf. This i then try to form into a numeric via value = int.Parse(val_buf), without success: System.ArgumentNullException: value cant be NULL.
What I've tried:
value = int.Parse(parse_buf[i]); This returns a format exception
printing parse_buf[i] to a textbox shows an expected value (the received data is correct)
observing the main buffer uart_buf shows valid data like this: "41 30 2 0 0 0 0 0 0 0 3 40 500 69..."
starting from index 1 (or any other) instead of 0 changes nothing
What I don't get:
A single element (ergo a string) of parse_buf contains a value in text-form, e.g. "41". I want to save it to a regular string val_buf, which i should be able to parse to int. Why is every string accessed via parse_buf[i] null?
Code-Fragments:
private void displayData(object o, EventArgs e)
{
parse_buf = uart_buf.Split(' ');
tb_data.Text = parse_buf[0]; //this shows valid data in a tb
for (i = 1; i < parse_buf.Length; i++) //about 1024 loops
{
//problem area:
parse_buf[i] = val_buf;
fft = int.Parse(val_buf);
//ignore this:
f = i * 20;
chart1.Series[0].Points.AddXY(f, fft);
}
}
I usually work in C with embeded systems, so sorry for not seeing the problem instantly. Thanks.
private void DisplayData(object o, EventArgs e)
{
parse_buf = uart_buf.Split(' ');
tb_data.Text = parse_buf[0]; //this shows valid data in a tb
for (i = 0; i < parse_buf.Length; i++) //about 1024 loops
{
//problem area:
int.TryParse(parse_buf[i], out ftt);
//ignore this:
chart1.Series[0].Points.AddXY(i * 20, fft);
}
}

C# - Reading specific part of a File and splitting each line into an array or a list

First of all, Hi to everyone. I'm a beginner with C# and trying to do this homework. My problem is, reading a specific part of a .pdb (protein data bank) file and split that specific lines into an array or list. Then I will use it for a Forms App
So .pdb file index is looks like this;
HEADER ANTIFREEZE 17-SEP-97 7MSI
TITLE TYPE III ANTIFREEZE PROTEIN ISOFORM HPLC 12
COMPND MOL_ID: 1;
COMPND 2 MOLECULE: TYPE III ANTIFREEZE PROTEIN ISOFORM HPLC 12;
SOURCE MOL_ID: 1;
SOURCE 2 ORGANISM_SCIENTIFIC: MACROZOARCES AMERICANUS;
ATOM 1 N MET A 0 18.112 24.345 32.146 1.00 51.10 N
ATOM 2 CA MET A 0 18.302 23.436 31.020 1.00 49.06 C
ATOM 3 C MET A 0 18.079 24.312 29.799 1.00 46.75 C
ATOM 4 O MET A 0 16.928 24.678 29.560 1.00 48.24 O
ATOM 5 CB MET A 0 17.257 22.311 31.008 1.00 48.14 C
ATOM 6 N ALA A 1 19.106 24.757 29.076 1.00 43.47 N
HETATM 491 O HOH A 101 23.505 19.335 23.451 1.00 35.56 O
HETATM 492 O HOH A 102 19.193 19.013 25.418 1.00 12.73 O
HETATM 493 O HOH A 103 7.781 12.538 12.927 1.00 80.11 O
....
and goes on like this
I only need to read the lines that starts with "ATOM" keyword. Then I want to split their informations to variables and to an array or list. After that I want to print the maximum value of X Coordinate to a label.
For example;
ATOM 1 N MET A 0 18.112 24.345 32.146 1.00 51.10 N
1 stands for atom number
N stands for atom name
MET stands for amino acid name
18.112 stands for X coordinate etc.
WHAT I DID
I used the codes from a similar question that was asked here before but i couldn't implement it to my project.
First I created a Class for variables
class Atom
{
public int atom_no;
public string atom_name;
public string amino_name;
public char chain;
public int amino_no;
public float x_coordinate;
public float y_coordinate;
public float z_coordinate;
public float ratio;
public float temperature;
}
For the main class; NOTE: I should mention that there's not single whitespace beetween variables. For example between "MET" and "A" there are extra 3 or 4 whitespaces. I've tried to remove them while reading file but I don't know if that worked..
private void button1_Click(object sender, EventArgs e)
{
string filePath = #"path_of_file";
string stringToSearch = #"ATOM";
List<Atom> Atoms = new List<Atom>();
using (StreamReader sr = new StreamReader(filePath))
{
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
if (line.Contains(stringToSearch)) // i have tried to read the parts that starts with ATOM
{
while (sr.Peek() >= 0) //this while part is from the question asked before
{
string[] strArray;
string line1 = sr.ReadLine(); // i've added theese 2 lines to remove the extra whitespaces
var lineParts = line1.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
strArray = line1.Split(' ');
Atom currentAtom = new Atom();
currentAtom.atom_no = int.Parse(strArray[0]);
currentAtom.atom_name = strArray[1];
currentAtom.amino_name = strArray[2];
currentAtom.chain = char.Parse(strArray[3]);
currentAtom.amino_no = int.Parse(strArray[4]);
currentAtom.x_coordinate = float.Parse(strArray[5]);
currentAtom.y_coordinate = float.Parse(strArray[6]);
currentAtom.z_coordinate = float.Parse(strArray[7]);
currentAtom.ratio = float.Parse(strArray[8]);
currentAtom.temperature = float.Parse(strArray[9]);
Atoms.Add(currentAtom);
}
}
}
}
listBox1.DataSource = Atoms;
listBox1.ValueMember = "atom_no";
listBox1.DisplayMember = "atom_name";
}
I didn't add the part that i want to print the max value of X Coordinate to a label yet. I'm testing at this point with listbox. So when I run the code and press the button gives me "Input string was not in a correct format" error at the currentAtom.atom_no = int.Parse(strArray[0]); line.
I know that my code looks like mess and sorry If I've stolen your time with this. I would be much appreciated if you guys can help me do this Forms app for my homework. If not, still thank you for reading it. Have a nice and healhty day..
One way to do this is to just use File.ReadAllLines to read the file, then filter out any lines that don't StartWith the stringToSearch text (using the System.Linq method Where), and finally select a new Atom from each line using the Split method (and remove empty entries) as you were doing, and finally returning them all with ToList:
List<Atom> Atoms = File.ReadAllLines(filePath) // Read all the lines
.Where(line => line.StartsWith(stringToSearch)) // Filter on our string
.Select(line =>
{
// Split the line on the space character into an array
var strArray = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
// Return a new Atom for each line based on the array contents
return strArray.Length < 10 // Ensure we have at least ten elements in the array
? null // If we don't have 10, return 'null'
: new Atom // Otherwise return a new atom from the array
{
atom_no = int.Parse(strArray[0]),
atom_name = strArray[1],
amino_name = strArray[2],
chain = char.Parse(strArray[3]),
amino_no = int.Parse(strArray[4]),
x_coordinate = float.Parse(strArray[5]),
y_coordinate = float.Parse(strArray[6]),
z_coordinate = float.Parse(strArray[7]),
ratio = float.Parse(strArray[8]),
temperature = float.Parse(strArray[9])
};
})
.ToList(); // Return the items as a list

Algorithm for generating all combinations with 2 potential values in 5 variables

Apologies if this has been answered before but I can't come up with a good name to search for what I'm looking for. I have the potential for between 1-5 string variables (we'll call them A,B,C,D,E) that can have one of two values represented by 'P' and 'S'. These are for pluralized and singular word forms
The data will always be in the same order, ABCDE, so that is not a concern but it may not contain all five (could be only A, AB, ABC or ABCD). I'm looking for an algorithm that will handle that possibility while generating all potential plural/singular combinations. So in the case of a 5 variable string the results would be:
SSSSS,
SPSSS,
SPPSS,
SPSPS,
...
PPPPP
I have the logic to pluralize and to store the data it's just a question of what is the logic that will generate all those combinations. If it matters, I am working in C#. Any help would be greatly appreciated!
So there are only two possible values, 0 and 1. Wait a minute... Zeroes and ones... Why does that sound familiar...? Ah, binary to the rescue!
Let's count a little in binary, starting with 0.
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
...etc
If you look at the rightmost bit of the first two rows, we have all the possible combinations for 1 bit, 0 and 1.
If you then look at the two rightmost bits of the first four rows, you get all 2 bit combinations: 00, 01, 10 and 11.
The first eight rows have all three bit combinations, etc.
If you want all possible combinations of x bits, count all numbers from 0 to (2^x)-1 and look at the last x bits of the numbers written in binary.
(Likewise, if you instead have three possible values (0, 1 and 2), you can count between 0 and (3^x)-1 and look at the last x digits when written in ternary, and so on for all possible amounts of values.)
"Recursive permutations C#" will do the trick for a google search. But I thought I'd attempt a solution for you using simple counting and bit masking. Here is some code that will do "binary" counting and, using bitshifting, determine if the position in the words should be pluralized (you mention you have those details already):
string input = "red bag";
string[] tokens = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string[] test = new string[tokens.Length];
int size = (int)Math.Pow(tokens.Length, 2);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < tokens.Length; j++)
{
int mask = (1 << j);
if ((mask & i) != 0)
{
test[j] = Pluralize(tokens[j]);
}
else
{
test[j] = Singularize(tokens[j]);
}
}
Console.WriteLine(string.Join(" ", test));
}
Output:
red bag
reds bag
red bags
reds bags
I would advise a recursive algorithm. For example an algorithm like this could be the answer to your problem (I dont really know what returnvalues you exactly want)
public void getAllWords(ref List<string> result, string Prefix, int wordLength)
{
if(wordLength == 0)
result.add(prefix);
else
{
getAllWords(result, prefix+"0", wordLength-1);
getAllWords(result, prefix+"1", wordLength-1);
}
}
to be called with
List<string> result = new List<string>();
getAllWords(result, "", 5);
I hope this works, I'm on mobile at the moment.
You can change that as you want to account for m a different alphabet (for example values 0,1,2..) as you like.
You can enumerate all integers from 0 to 2^5-1 (i.e. from 0 to 31 ) and represent each integer as bool[]. May be this will be helpful:
static bool[][] GetCombinations(int wordCount) {
int length = (int) Math.Pow(2, wordCount);
bool[][] res = new bool[length][];
for (int i = 0; i < length; i++)
{
res [i] = new bool[wordCount];
for (int j = 0; j < wordCount; j++) {
res [i] [j] = ((i & (int)Math.Pow (2, j)) != 0);
}
}
return res;
}

How to get count of numbers in int and how to split a number without making a string

I have a number like 601511616
If all number's length is multiple of 3, how can a split the number into an array without making a string
Also, how can I count numbers in the int without making a string?
Edit: Is there a way to simply split the number, knowing it's always in a multiple of 3... good output should look like this: {616,511,601}
You can use i % 10 in order to get the last digit of integer.
Then, you can use division by 10 for removing the last digit.
1234567 % 10 = 7
1234567 / 10 = 123456
Here is the code sample:
int value = 601511616;
List<int> digits = new List<int>();
while (value > 0)
{
digits.Add(value % 10);
value /= 10;
}
// digits is [6,1,6,1,1,5,1,0,6] now
digits.Reverse(); // Values has been inserted from least significant to the most
// digits is [6,0,1,5,1,1,6,1,6] now
Console.WriteLine("Count of digits: {0}", digits.Count); // Outputs "9"
for (int i = 0; i < digits.Count; i++) // Outputs "601,511,616"
{
Console.Write("{0}", digits[i]);
if (i > 0 && i % 3 == 0) Console.Write(","); // Insert comma after every 3 digits
}
IDEOne working demonstration of List and division approach.
Actually, if you don't need to split it up but only need to output in 3-digit groups, then there is a very convenient and proper way to do this with formatting.
It will work as well :)
int value = 601511616;
Console.WriteLine("{0:N0}", value); // 601,511,616
Console.WriteLine("{0:N2}", value); // 601,511,616.00
IDEOne working demonstration of formatting approach.
I can't understand your question regarding how to split a number into an array without making a string - sorry. But I can understand the question about getting the count of numbers in an int.
Here's your answer to that question.
Math.Floor(Math.Log10(601511616) + 1) = 9
Edit:
Here's the answer to your first question..
var n = 601511616;
var nArray = new int[3];
for (int i = 0, numMod = n; i < 3; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Please keep in mind there's no safety in this operation.
Edit#3
Still not perfect, but a better example.
var n = 601511616;
var nLength = (int)Math.Floor(Math.Log10(n) + 1)/ 3;
var nArray = new int[nLength];
for (int i = 0, numMod = n; i < nLength; numMod /= 1000, i++)
nArray[i] = numMod%1000;
Edit#3:
IDEOne example http://ideone.com/SSz3Ni
the output is exactly as the edit approved by the poster suggested.
{ 616, 511, 601 }
Using Log10 to calculate the number of digits is easy, but it involves floating-point operations which is very slow and sometimes incorrect due to rounding errors. You can use this way without calculating the value size first. It doesn't care if the number of digits is a multiple of 3 or not.
int value = 601511616;
List<int> list = new List<int>();
while (value > 0) // main part to split the number
{
int t = value % 1000;
value /= 1000;
list.Add(t);
}
// Convert back to an array only if it's necessary, otherwise use List<T> directly
int[] splitted = list.ToArray();
This will store the splitted numbers in reverse order, i.e. 601511616 will become {616, 511, 601}. If you want the numbers in original order, simply iterate the array backwards. Alternatively use Array.Reverse or a Stack
Since you already know they are in multiples of 3, you can just use the extracting each digit method but use 1000 instead of 10. Here is the example
a = 601511616
b = []
while(a):
b.append(a%1000)
a = a//1000
print(b)
#[616, 511, 601]

C# read in file using hex prints FFFFFF

very confused by this, when I read in a file using the code below when it gets to the end it prints out FFFFFF, could anyone explain this to me the text file only has numbers and letters in it? Any help would be most greatful!
String fileDirectory = "C:\\t.txt";
StreamReader reader = new StreamReader(fileDirectory);
int hexIn;
for (int i = 0; (hexIn = reader.Read()) != -1; i++)
{
String s;
s = hexIn.ToString("X2");
int x = 0;
while (x < 1)
{
hexIn = reader.Read();
s = hexIn.ToString("X2");
x++;
}
hexIn = reader.Read();
s = hexIn.ToString("X2");
MessageBox.Show(s);
}
You've got three Read calls per loop iteration, which means that any one of them could return -1 to indicate the end of the file. I suspect that's then being converted to FFFFFFFF, hence your output. Why do you have more than one Read call? And why aren't you reading a block at a time?
The FFFFFF may also indicate an empty value. If you Hex editted Nintendo DS Roms you would see a whole bunch of FFFFFFFF at the end which is put there because the game is too small for the cartridge so in actual fact that file may have empty values at the end.

Categories