|
My god man. I think this is quite possibly the most helpful reply I've gotten on the internet ***ever***.
Thank you for your time. I think with this information I should be able to cook up some code now.
Many thanks,
Brandon.
|
|
|
|
|
Well, that's the longest post on forums I've ever wrote hahah , so I'm happy it's useful.
btw. My code on this is very dirty, cause it's one of that programs "Hey, i will add those few lines and see what happens, wow, it works, now I will put few lines here....", so I haven't posted it.
Good luck,
Rav
|
|
|
|
|
Ugh. Back from work late and I must be doing something wrong. (Warning, big post ahead).
I wanted to see how the code would work on recorded samples, so I recorded 3 WAV files, each one for my low string E on my guitar. Thus, the three WAV files should produce the same data, correct? By this I mean the magnitude I would assume would be roughly the same for all three files; since they are the same note & same string on the guitar. (I basically plucked the string and recorded, and repeated that 3 times).
But that is not the case. Here is how I went about it:
In code, I jump to 44 bytes into the WAV file (which is where the WAV data actually starts) and read that whole thing into a big byte array (so, byte[] arrDataToProcess).
Now, from the previous mentioned project above, I see where his FFT library processes the data in 16 bit samples (16384) - so I split arrDataToProcess into a List<byte[]> lstArraysToProcess of 16384 each; then feed each one into a method that converts the bytes to doubles, and then call the FFT on that:
public static double[] Process(ref byte[] wave)
{
double[] _fftDataToReturn;
double[] _waveDataToProcess = new double[wave.Length / 4];
int h = 0;
for (int i = 0; i < wave.Length; i+=4)
{
_waveDataToProcess[h] = (double)BitConverter.ToInt16(wave, i);
h++;
}
_fftDataToReturn = SoundCatcher.FourierTransform.FFT(ref _waveDataToProcess);
return _fftDataToReturn;
}
the SoundCatcher.FourierTransform.FFT(ref _waveDataToProcess) method as seen above looks like so (warning, large code block ahead):
static public double[] FFT(ref double[] x)
{
n = x.Length;
nu = (int)(Math.Log(n) / Math.Log(2));
int n2 = n / 2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] magnitude = new double[n2];
double[] decibel = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++)
{
xre[i] = x[i];
xim[i] = 0.0f;
}
int k = 0;
for (int l = 1; l <= nu; l++)
{
while ((k < n))
{
for (int i = 1; i <= n2; i++)
{
p = BitReverse(k >> nu1);
arg = 2 * (double)Math.PI * p / n;
c = (double)Math.Cos(arg);
s = (double)Math.Sin(arg);
tr = xre[k + n2] * c + xim[k + n2] * s;
ti = xim[k + n2] * c - xre[k + n2] * s;
xre[k + n2] = xre[k] - tr;
xim[k + n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 = n2 / 2;
}
k = 0;
int r;
while (k < n)
{
r = BitReverse(k);
if (r > k)
{
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
for (int i = 0; i < n / 2; i++)
magnitude[i] = (float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i])));
return magnitude;
}
}
I collect all the returned double[] from public static double[] Process(ref byte[] wave) into a List<double[]> lstFFTData , which I then splice back together into one huge array of double[] named arrFinalData.
Finally, I attempt to do the logic you mentioned about finding the maximum magnitude by iterating over this array (arrFinalData). This, however, keeps producing different numbers for the 3 WAV files; even though they are the same note (and I have taken much care to try and play the note at the same volume and with no background noise and the mic the same distance from the guitar each time). So, fe:
* 1st WAV file maximum magnitude: 77140.71
* 2nd WAV file maximum magnitude: 30483.56
* 3rd WAV file maximum magnitude: 79244.77
(numbers are obviously truncated)
As well, I am also a bit lost at second glance as to your suggestion about
<br />
T - array of input data (sound we've catched).<br />
F - array of output data (magnitudes of complex numbers computed by FFT)<br />
length(T) == length(F)
because if I do a comparison on the arrDataToProcess.Length versus arrFinalData.Length , this of course does not match.
Alas, I think I am way in over my head.
Am I:
* wrong in my implementation?
* wrong in using the FFT class from the above mentioned project?
* wrong about interpreting the results?
* wrong altogether about how this should work?
or am I right in all of my implementation, and possibly just have a bug somewhere else in my code?
If you think the problem lies between the keyboard and chair, that is fine too
Thanks for taking the time to read,
Brandon.
modified on Tuesday, December 30, 2008 3:08 AM
|
|
|
|
|
Hello,
Few things I can see here is:
If you record wav file, you must be sure what format it is, fe. it can be recored as stereo 16-bit, so then byte align would be:
LL RR LL RR LL RR, where L/R - left/right side byte.
Second - your FFT function does some "magic" work for you (which is not a part of FFT, it's just stuff that author of this code places there so function will return ready to use data, which are:
for (int i = 0; i < n / 2; i++)
magnitude[i] = (float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i])));
return magnitude;
First of all: return array has length equal to 1/2 of input array, 2nd of all, magnitudes are counted (that's good anyway). The reason why only 1st half of array is returned is that when you do FFT on 1D data, you will always have result data mirrored, always. So if 1st half of output array is:
1 2 4 7 5 , the 2nd half would be: 5 7 4 2 1 . So it's ok, but you have to remember, to the FreqStep from (44100.0 / length(F)) to (44100.0 / (length(F) * 2))
Ok, and now, for what I think is your error:
I collect all the returned double[] from public static double[] Process(ref byte[] wave) into a List<double[]> lstFFTData, which I then splice back together into one huge array of double[] named arrFinalData.
You don't do that! . Each of those data is an array of some length that contains data about frequency, from circa 0.0Hz up to some value (about half of sampling rate, based on Nyquist law). Each of this array, back from FFT should be counted as a whole. So:
1. Get FFT from short sample (16kBytes in your example)
2. Get highest frequecy from that short array - it's your result
3. Now you can back to step 1., iterate few times and check frequency, it should be very similiar, but you can for example count airthmetic mean.
If you want to get more accurate sample, you can't connect few results from FFT, you have to supply bigger array of data to FFT, so fe. you can use 32KBytes array, which will give you 16k shorts, which will give you 8k doubles after your FFT method, instead of 4k you have now.
|
|
|
|
|
Goodness. The more I dig into this project, the more I realize I don't know what I'm doing. Sorry for the delay in responding, been busy at work. I have today off from work for New Year's.
For the record, I am recording my samples using the regular Windows XP sound recorder (sndrec32.exe -- you can bring it up if you click Start -> Run, and type 'sndrec32') and have set the select under File -> Properties -> "Convert Now" -> to Format as "PCM" and the attributes to "44100khz at 16 bit Mono".
Since I'm recording in Mono, I didn't bother splitting the channels out as the original author did like so in his Process():
int h = 0;
for (int i = 0; i < wave.Length; i += 4)
{
_waveLeft[h] = (double)BitConverter.ToInt16(wave, i);
_waveRight[h] = (double)BitConverter.ToInt16(wave, i + 2);
h++;
}
Thanks for clarifying that I didn't need to split the arrays back together (d'oh!). I'm a bit confused on how that is supposed to work though?
If I am passing to my Process() function an array of bytes[16384] from the WAV File - isn't this data from the first few seconds of the WAV file? (Remember, I am jumping 44 bytes into the WAV file, reading from that position to the end of the file, and then splitting that array into byte[16384] each into a List<byte[]> )
The reason I ask is because as soon as I hit "Record" I don't immediately play my guitar string. Thus, wouldn't the first second or so of the WAV file be silence - so thus the first 16384 bytes be unusable to me?
If this is incorrect, forgive me - but only reason I ask is because although I've adjusted my code now to only bother with a 16kb sample, I am still getting different maximum magnitudes when I iterate over my array for each WAV file (although they are the same note & string) played on my guitar.)
Also, I am still a bit lost on your frequency formula's you had earlier. You said in your original post:
Now, if fe. your fi = 50, sample_rate = 44100 (which is standard value),
and you will catch 4096 samples (which means, your T tables has length od 4096, and that means, your F table has length of 4096),
the most significant frequency in your sound probe is:
Freq = 50 * (44100 / 4096)
which I simply translated to be in code:
double freq = _MaxFoundValue * (SampleRate / _outputSample.Length);
but I don't understand how that relates to the FreqStep you mentioned (is not FreqStep just SampleRate / _outputSample.Length)?
Is my formula
double freq = _MaxFoundValue * (SampleRate / _outputSample.Length); correct? From here, do I simply compare this result against a table for pitch for respective guitar notes (such as this http://www.vaughns-1-pagers.com/music/musical-note-frequencies.htm[^] ?)
Finally, thank you for all the information you have already provided. It has gotten me further along than I would have expected. If it makes life easier for you - is there simply just a condensed writeup that would explain all this comprehensively?
Thank you very much for all the guidance thus far,
Brandon.
modified on Wednesday, December 31, 2008 4:36 PM
|
|
|
|
|
Hello,
1. I've created sample app that could help you (it analyzes sound from mic and writes recognized freq to console if recored sound was loud enough, I can send it to you if you'll give your mail, or some other way to send zip file)
2. As for your questions:
When analyzing sound (especially sound that is recorded in real time, like getting is from mic) you do want to analyze it in small chunks. Small does not need to mean very small, it depends on what you want to do.
I'd recommend to make such solution that will be configurable, fe. if you want to stick with wav files, make this parameter configurable, and to check which sound you were playing: analyze whole wave file, divided into chunks of size X, and check what frequencies you have found. By changing chunk size you can see what happens.
And yes, first 16kB of data will be unusuable for you then.
FreqStep is SampleRate / outputSample.Length , your right (remember that FFT code you have used, returned only 1st half of array, so your length will be smaller then it should be after real FFT function).
And yes, frequency that you will get is freq. that you can compare to table from link (or generate this table with method I have gave you earlier). (Just to make sure: MaxFoundValue is NOT that value, but index of that value, right?, because if it's value, which is magnitude, then no, it won't work ).
|
|
|
|
|
Well, let me get my situation explained. Before I go any further please know I HAVE google'd, so much so that I'm posting on a forum after a few hours of searching .
Sticking to the point, I'm basically trying to aquire the current media info from windows media player and retrieve the value in a .NET application. My apologies for the amount of links.
I first found the COM refrence named wmp.dll, after a reasonable amount of time wasted, I realised that it was used for embedding WMP in a form application etc, which isn't what I wanted.
Next I hit google, nothing.
IRC followed with everyone shrugging, one individual did however suggest I look at a IM plugin source code. After that I found the following file written in what I think looks like C (http://pidgin-musictracker.googlecode.com/svn/trunk/src/wmp.c[^).
Reading through the plugin wiki revealed the following page, (http://kentie.net/article/nowplaying/index.htm[^]). I learned that the wmp live messenger plugin sent its data via WM_COPYDATA (still not too sure on how that works ), following on from that... I then landed on the following link which seemed very promising at first (http://www.codeproject.com/KB/cs/wm_copydata_use.aspx[^]).
I downloaded the source & binaries and sure enough the data was 'magically' been sent between programs, I thought to myself.. thats how WMP does it!
After reading the source, I was stumped... probably due to my lack of knowlage and experience.
Could some 'kind' individual(s) aid me in these troubles I am having.
Kind Regards
Sam
|
|
|
|
|
It would help if you kindly stated your exact question so that someone could know how to help you.
Are you trying to implement the WM_COPYDATA in your C# program?
|
|
|
|
|
My apologies :P
Yes, I'm trying to impliment WM_COPYDATA into my C# .NET program, however it needs to get the data sent by wmplayer.exe rather than another application that I have written.
Thanks
|
|
|
|
|
Hi,
It appears that you have two problems, basically.
1. How to implement the reception of the WM_COPYDATA message in your C# program - this I can help you with
2. How to make Media Player send you the information - this I have no idea.
As far as #1, you'll have to create and manage a window for the sole purpose of receiving window messages of which WM_COPYDATA is just one.
Look up this topic in MSDN "Subclassing Controls with a Managed Window Procedure" .
The idea is that you hijack the window procedure for one of your controls, and handle the low-level window messages in your C# program instead of letting the control handle them itself.
This is pretty tough stuff, but if you have further questions, I'm sure that I or someone else can answer them.
|
|
|
|
|
Looks like I'm in luck! I'll take a look at the MSDN topic later on today. Regarding #2, wmp already includes this by default to support windows messenger.
Thanks Richard
|
|
|
|
|
|
please help me
i want to design small program to lock the windows XP
but i do not know how can i start because i am beginner in c# language
so please help me
tell me what is the steps
and thank you so mach
|
|
|
|
|
|
how can play an avi format file in my project in which i am creating a media player.
|
|
|
|
|
Hi,
welcome to CodeProject.
This website holds more than 20,000 articles and it has a reasonably good search facility.
Why don't you try this[^]?
|
|
|
|
|
Here are the ways that I know of:
easiest: use WPF and make a MediaElement
2nd easiest: Use an old audio/video player class from the directX sdk. (This thing really sucks but will play an avi w/ a few lines of code)
3rd easiest: Use this AviFile C# wrapper Avi File in C#[^] And display the images (Too slow for big files)
4th easiest: Use the windows media player activeX control http://msdn.microsoft.com/en-us/library/bb262657(VS.85).aspx[^]
5th easiest: Use directshow/directx from C# and get out the VMR9. This is the best / most capable / smoothest way to play video in C#, but isn't very straight forward or easy. You'll find lots of examples out there, some are better than others.
|
|
|
|
|
I'm trying to write a questionnaire that gathers info of the user and then updates a database in Access. I've managed to write the program and everything works up to the point where it updates the database, at which point it displays the error message below:
OleDbException was unhandled
Syntax error in INSERT INTO statement
I've checked it and I can't find any syntax errors in it. Could someone help me out please? I'm very new to programming, so please try to explain in as simple terms as possible. The section of code is below. Thanks for your help.
sing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
OleDbConnection con = new OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=d:\\LO2.mdb");
OleDbDataAdapter ad;
DataTable table = new DataTable();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ad = new OleDbDataAdapter("select * from attributes ", con);
OleDbCommandBuilder cb = new OleDbCommandBuilder(ad);
ad.Fill(table);
dataGridView1.DataSource = table;
}
private void button1_Click(object sender, EventArgs e)
{
DataRow row = table.NewRow();
row["identifier"] = textBox1.Text;
row["language"] = textBox2.Text;
row["title"] = textBox3.Text;
row["description"] = textBox4.Text;
row["id"] = textBox5.Text;
table.Rows.Add(row);
ad.Update(table);
dataGridView1.DataSource = table;
}
|
|
|
|
|
hatan86 wrote: I've checked it and I can't find any syntax errors in it.
You haven't supplied an INSERT statement, your SELECT statement uses SELECT * which means that the DataAdapter probably cannot work out what columns it needs to insert.
|
|
|
|
|
Can you give me an example
|
|
|
|
|
|
Hey.
I've created a control which allows users to draw "tiles" onto a canvas, and supports multiple layers.
I've been running diagnostic time checks on each of these. The problem is, the system draws "previews" (50% transparency images of the other layers) when another layer is selected, so the person can see where the other tiles/sprites are on the canvas.
I have it set so that only the region of the canvas where a sprite has been painted is invalidated and updated when the user paints onto the canvas. But the problem is that it still requires quite a bit of rendering.
I have set DoubleBuffering to true, enabled OptimizedDoubleBuffering, AllPaintInWmPaint etc. Here are some times:
When drawing the entire map without transparency on layers: 0.23 seconds.
When drawing one layer, other layers with transparency: 0.8 seconds.
When painting a tile onto part of a layer: 0.26 seconds.
This might seem moderately fast for a drawing system, but for some reason the drawing is lagging. The painting itself isn't lagging at all, but it's the rendering the output onto the control that seems to take a while. You see, I have a selector box that's 2px wide rectangle that follows the mouse on the map to show where the sprite will be painted, and it takes a while to update the position.
Is there any way I could speed up the processing of my control? I know it's a hefty load to be drawing onto a control (especially 3~4 layers, where 2~3 of them are drawn with 50% transparency), but there are other editors which perform the same function and don't lag at all (or atleast take around 0.2 seconds to render transparent layers.
Edit
Just as a point of interest, would it speed up my processing if I split each layer into seperate controls, placed on top of each other on my main edit control, then drawing each layer seperately on each control, rather than having them all parsed in the same control?
Thanks ~ Chris.
|
|
|
|
|
Dear All :
When I put the tablelayoutpanel into usercontrol.
If this usercontrol allow developer adjust usercontrol.tablelayoutpanel row / column size into design-time
Can anyone help me teach me how to do it ?
As [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] is only work in property
Thanks
Michael
|
|
|
|
|
I'm having trouble on how am going to start this idea of mine. I have an image and I want to plot points on that image. My Idea is to get the X and Y coordinates of the mouse pointer and save it into a text file so that by the time I re-run the program again, the plotted points is still there. But it seems like this is not a good idea since everything will be messed up if I load the program to a computer with different screen size. I was thinking of placing an invisible grid, but looks like this will be tough to do.
|
|
|
|
|
Silvyster wrote: But it seems like this is not a good idea since everything will be messed up if I load the program to a computer with different screen size.
Why don't you store the coordinates in a coordinate space that is independent of the screen size, like relative to the image size?
modified 12-Sep-18 21:01pm.
|
|
|
|
|