|
George_George wrote: I am confused about your solution of using IronPython
What's to be confused about?? IronPython is a .NET CLR, managed-code verison, of Python. It's not to involved .NET in Python. It is a version of the language that cannot run without .NET. No, there is no possible way to convert the code you have to work under the .NET CLR, without rewriting it, by hand.
|
|
|
|
|
Thanks Dave,
I am confused about what do you mean "IronPython is a .NET CLR, managed-code verison, of Python. It's not to involved .NET in Python". I am interested in how IronPython works, does it compiles Python code into .Net IL code and then run them under .Net Runtime?
regards,
George
|
|
|
|
|
Just like C#, VB.NET, C++/CLI, ..., yes.
|
|
|
|
|
But what do you mean "It's not to involved .NET in Python"?
regards,
George
|
|
|
|
|
He means 'Yes'.
probably.Dave Cross
|
|
|
|
|
Wow your request is on every forum possible isn't it.
Such a tool doesn't exist, you're gonna need some help on this one from someone who knows both python and c#.
|
|
|
|
|
You mean convert the code manually?
regards,
George
|
|
|
|
|
what is the .xsd file in a C# project ?
Thanks...
|
|
|
|
|
Which one? It might be a dataset schema, it might be virtually anything
Be more specific.
Regards,
Lev
|
|
|
|
|
xsd files are XML schemas for datasets
|
|
|
|
|
What if I have a xsd file in my project for some xml-html transformations? Will it make it a dataset schema?
Of course not. It is not clear which file hung1984 means, that's why I asked him to be more specific.
Regards,
Lev
|
|
|
|
|
I've been kicking around the idea now of writing a guitar tuner in C#; but I've no idea on where to begin. Specifically I've seen excellent articles such as: http://www.codeproject.com/KB/audio-video/SoundCatcher.aspx[^] which will let me plot a wav file in real time; but I need to be able to calculate (I suppose, anyway) the pitch of a sample, correct?
In other words:
1. Suppose I have a WAV file looping that is playing a guitar string, say E, that is in tune.
2. I want to take the project mentioned above, and put a mic on my guitar and play my E string over and over...
3. I'd like to be able to tell if my E string that I am playing is in tune with the recorded WAV file...
For that, I'd need to be able to calculate pitch, correct? Is there a library to be able to do this? If not, could anyone kindly give me pointers on where to begin?
Many thanks,
Brandon.
|
|
|
|
|
Hi,
I've recently wrote project that could help you (in c#).
What I did was:
1. Write library wrapper to MM, which enables me to catch sound from microphone as pure data.
2. Write functions that will do FFT on that data
3. Check what sound (frequency) is "the loudest".
4. That's all folks! .
I've tested it on my piano and some youtube piano songs and my program is able to tell what tone I am playing (not as correctly as I would like though).
Anyway:
My approach was a bit different than yours, I wasn't comparing my sound to wav file with recorded, instead I was transforming small chunks of data, fe. 8192 samples (with 44.1kHz sampling rate, you will get enough samples after 1/5 sec, so that's the shortest sound you can catch), transform it to frequency domain using DFT / FFT, get "loudest" frequency from that sample and check what sound (tune) it is. If you decide to try write your soft that way, write if you will have any questions on that.
Good luck,
Ravadre
modified on Sunday, December 28, 2008 11:57 PM
|
|
|
|
|
Thanks for the reply.
Using the above project I mentioned, I have an example to follow for capturing live mic input; however I'm lost on the FFT. In the above mentioned project, he has a FFT class (which I would happily copy and paste, except that it would make this post hard to read) that takes an array of doubles and that will spit back out an array of doubles, but I'm not sure exactly what to do with them? Plot them?
I guess where I'm currently stuck is that I don't understand at all the FFT - other than it is a method for computing a wave?? I think I may go to the local community college library and check out a few books to bring myself up to speed.
Do you have a writeup, kind sir, of your project? If not, may I ask which library you used for your FFT? Or - if you know of any excellent articles that you could refer me to in getting started (because I don't fully understand either the sampling rate, etc) would be of most help.
Thank you for your time,
Brandon.
|
|
|
|
|
Hello,
In my library I use few FFT algorithms, just for fun, the best and easiest to use and understand was FFT algorithm in AForge library (100% c#) (by Andrew Kirillov, who writes greats articles on CP.com btw ).
The mystery of DFT (Discrete Fourier Transform)is, that it simply converts data from time-domain to frequency-domain (now mathematicans will scratch simply and write few books on how hard, complicated and beatiful it is, but for now - we don't need that knowledge).
FFT is nothing more then algorithm of computing DFT efficiently, so I will use FFT term from now on.
And now quick tutorial on FFT and sound data:
What you have when capturing sound from microphone is buffer of data, this data represents how sound has changed over time, so it's in time-domain. Now, what you have to do is compute F = FFT(T), where T is your time domain data, and what you will have in result is the same data, but in frequency domain. You should get array of complex numbers (or 2 double arrays, 1st representing Re part, 2nd representing Im part), if algorithm from this program returns doubles, I assume it computes magnitude of complex numbers, which is OK for your purpose (you would have to compute it anyway from normal FFT algorithm). So, what we've got now is:
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)
Now we have to find which frequency has the highest magnitude. We iterate over our array and find index with the highest value - that's the easy part.
So now we also have
fi - Index in array of F with greatest value
Now the question is how to get frequency of that sound. The answer is:
double freqStep = sampling_rate / length(F)
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)
If you analyse this, you can see, that the longer probes you will have, the smaller freqStep will be, and that means you will analyze sound frequency better (more accurate), but you will have to catch sound longer.
Now the last part is how to convert Freq to pitch (C, C#, D ...). I don't know how does it look for guitar, but in piano 1st key has frequency of 27.5Hz, which is A sound, and piano has 88 keys, so We have to compute help table:
pitches = new double[88];
pitches[0] = 27.5;
double step = Math.Pow(2, 1.0 / 12.0);
for (int i = 1; i < 88; ++i)
{
pitches[i] = pitches[i - 1] * step;
}
Now, to get pitch, we find index that value is closest to Freq, fe. If we have Freq=445.0, the closest index will be 48 (which has value of 440). Now, because 1st value in our array is A pitch, and we have 12 pitches, we can get pitch like that:
string GetPitch(int pitchindex)
{
int rest = pitchindex % 12;
switch (rest)
{
case 0: return "A";
case 1: return "A#";
case 2: return "H";
case 3: return "C";
case 4: return "C#";
case 5: return "D";
case 6: return "D#";
case 7: return "E";
case 8: return "F";
case 9: return "F#";
case 10: return "G";
case 11: return "G#";
}
throw new Exception("?");
}
|
|
|
|
|
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.
|
|
|
|
|