Get/access excact peak levels -> Stuck in no mans land -> but yet so close :-/

Jan 26, 2013 at 9:22 PM

In a mix of trying to alter code fom this tutorial:  https://www.youtube.com/watch?v=ZnFoVuOVrUQ

 - and trying to get the peak values of a recorded wave I ended up with this:

while (wave.Position < wave.Length )
            {
                read = wave.Read(buffer, 0, 16384);

                for (int i = 0; i < read / 4; i++)
                {                  
                            if (i < 5000){   
                            chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, i * 4));

                            liste.Add(chart1.Series["wave"].Points[Convert.ToInt32(wave.Position/4096)].YValues[0]);
                                         }

                            if (wave.Position % 16384 == 0 && i % 4096 == 0)
                            {
                                Console.WriteLine("Values!!: "+ liste[i]);
                                Console.WriteLine("values: " + chart1.Series["wave"].Points[Convert.ToInt32(BitConverter.ToDouble(buffer, i / 4))].YValues[0]);
                            }                      
                }
                textBox1.Text = Convert.ToString(optaelPeaks);
                textBox2.Text = Convert.ToString(wp);
            }

-  but the output of this code doesn't really makes sense in the console as all the values lays between 0.027 and 0.089 (in a very looping-like pattern, that doesn't resembles the .wav I am analyzing/loading), as opposed to the chart1 that shows values from -1.0 to 1.0.

I have also been checking up on Voicerecorder and this link: http://stackoverflow.com/questions/14350790/naudio-peak-volume-meter

- without getting further (as a Dane I have trouble with more in depth math English terms like: "take the log base 10 of the maximum value") ... Hope you can help me /on before hand thx /Thomas

Coordinator
Jan 28, 2013 at 3:44 PM

what format are you recording in? ToSingle assumes you are capturing as IEEE float.

Jan 29, 2013 at 3:42 PM

Hi - thx for replying.


I tried Google/Wiki 'IEEE float' ->> I guess it is a general data-format rather than an audio format. Thereafter I went to my recording software to meet that recording standard. It turned out that the line:


  NAudio.Wave.WaveChannel32 wave = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName));


- only can open 'Windows PCM 16-bit'.

In this process (my own and early learning process of C#) I have also (- found a way to -) tried to export the data stream of the y-values, from above, into an .csv-file, which rendered (in Excel) the values into this graph: http://www.preforce.dk/DIV/NAudio_codeplex.htm
This doesn't fit with the asymmetric output of my 'Windows PCM 16-bit' wav-file in chart1.

So instead of;

  NAudio.Wave.WaveChannel32 wave = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName));

- should I then be using a different way to open the wavefile? (the goal is to make the y-values fits the peaks at the waveposittion (x-values/time) in the recorded file, of course)
All though Giawa, who made this tutorial that I am merging from, could plot out to the chart, I am having big trouble understanding whats going on value-wise. I mean; on the chart it displays very different y-values (making peaks) ->> so how to access those peak-making y-values?

Lastly; I also tried to alter the way the files ya-values are being read/gets converted in the tutorial from:

chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, i * 4));

to:

chart1.Series["wave"].Points.Add(BitConverter.ToDouble(buffer, i * 4));


(actually this action, was just to try something, as you wrote about the 'ToSingle'-approach being wrong ('IEEE float'))

'ToDouble' results in an exception, but then again, this was a wild shot from my side :-/

Coordinator
Jan 30, 2013 at 11:24 AM

your WAV file is 16 bit, but WaveChannel32 converts 16 bit into 32 bit IEEE float. So you either keep WaveChannel32. ToSingle is right if your audio is IEEE float at that point. I'm not really clear on what you are trying to graph. Do you want to draw a waveform?

Feb 9, 2013 at 7:29 PM
I got it to work with this:

while (wave.Position < wave.Length)
        {
            wPosTilSecs = Convert.ToInt32(Math.Round(Convert.ToDouble(wave.Position / 88723)));
            read = wave.Read(buffer, 0, 8192);
            for (int i = 0; i < read / 4; i++)
            {
                if (i < 5000){
                    chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, Convert.ToInt32(Math.Round(secondCounter*10))));
                    chart1.Series["wave"].Points.Add(BitConverter.ToSingle(buffer, i*4));                          
                }            
                areal += buffer[i];       
                if (buffer[i] > 4)
                     {
                    if (areal > 196000)
                         {
                             peaker +=1;
                         }
                     }
                if (i % 512 == 0) { secondCounter += 0.0057305; optaellerIbyteCycles = 0; Console.WriteLine("sec: " + secondCounter);

                }
                       if (i%32==0) {                              
                           if (BitConverter.ToSingle(buffer, i * 4) > 0.04 || BitConverter.ToSingle(buffer, i * 4)< 0.01)
                           {
                               sw.Write("Y-value PEAK?: " + BitConverter.ToSingle(buffer, i * 4));
                               sw.Write("\t\n");

                               sw.Write("sec PEAK?:: " + secondCounter.ToString());
                               sw.Write("\t");
                           }
                           else {
                               if (i % 16384 == 0)
                               {
                                   sw.Write("Y-value no-peak: " + BitConverter.ToSingle(buffer, i * 4));
                                   sw.Write("\t\n");

                                   sw.Write("sec no-peak: " + secondCounter.ToString());
                                   sw.Write("\t");
                               }
                           }
                           peaker = 0;                 
                      }                      
               }                  
            areal = 0;
            textBox1.Text = Convert.ToString(countPeaks);
            textBox2.Text = Convert.ToString(wp);               
        }

The line: if (BitConverter.ToSingle(buffer, i * 4) > 0.04 || BitConverter.ToSingle(buffer, i * 4)< 0.01)
  • is the core to the solver, as the waveform I was drawing with the MS Visual Studio standard chart showed a the confusing range og -1 to 1. The 'buffer' variable outputs values from 0.003 to 0.098 (I did not see that range from buffer earlier, and I just had to amp up the detail via a txt-stream to a notepad-file in order to discover it -> otherwise my small induvidual wave-inputs did not show over a time period of 5-6 secs.)