Comparing the "Tone" of musical instruments in matlab

12 views (last 30 days)
I am trying to find a way to compare the likeness of short 500 millisecond recordings using metlab of the same note played on different instruments.
Going into detail on this specific topic: I am a music student that has been given the task to objectively determine the tone of various modern low brass instruments to determine what instrument should replace the obsolete "ophicleide" or Bass keyed bugle. I first used a visual comparison of a spectrograph of it and 6 other instruments, but that approach was too subjective.
I recorded all of the instruments with the same microphone, equipment, gain levels, and the same notes. For this reason, I believe that the signals are similar enough to use metlab tools.
I believe that comparing the fft is going to be the most accurate calculation. I tried at first a freq-domain correlation, and tested different segments of the same tone (eu, and eu2 being variables)
corr(abs(fft(eu)),abs(fft(eu2))) ans = 0.9963
Which is a step in the right direction, but I seem to get the opposite result when I compare different signals: (euphonium and ophicleide sound almost identical)
corr(abs(fft(eu)),abs(fft(ophi))) ans = 0.5242
euphonium and bass clarinet sound completely different, but this shows higher correlation
corr(abs(fft(eu)),abs(fft(basscl))) ans = 0.8506
I tried a normalized maximum cross-correlation magnitude formula that I found online, but I am getting the same results
>> norm_max_xcorr_mag = @(x,y)(max(abs(xcorr(x,y)))/(norm(x,2)*norm(y,2)));
x =eu2; y = eu;
norm_max_xcorr_mag(x,y)
ans = 0.9638
I get a similar result when comparing the other samples
>> norm_max_xcorr_mag = @(x,y)(max(abs(xcorr(x,y)))/(norm(x,2)*norm(y,2)));
x = eu; y = basscl;
ans = 0.6825
compared to
>> norm_max_xcorr_mag = @(x,y)(max(abs(xcorr(x,y)))/(norm(x,2)*norm(y,2)));
x = eu; y = ophi;
norm_max_xcorr_mag(x,y)
ans = 0.3519
The euphonium and Bass Clarinet (basscl) have a completely different sound, and completely different harmonic series, but these formulas are showing closer correlation than the Euphonium and Ophicleide, whose frequency bands look almost like an identical match.
I am worried that these correlations are showing the correlation of true pitch (I am playing the same note on all of these instruments, but the ophicleide might be out of tune by up to 1 Hz) It could also be accounting for phase, or even total amplitude.
does anyone know of a better clear cut method in comparing the proportions of the harmonic overtones of these complex waveforms?
or am I barking up the wrong tree?
  2 Comments
Star Strider
Star Strider on 2 Jun 2014
It’s MATLAB ported to Babbage’s Difference Engine. Early releases were, appropriately, called metal lab, owing to its technology.

Sign in to comment.

Answers (1)

Star Strider
Star Strider on 1 Jun 2014
Disclaimer: I love early music and am attempting to teach myself the lute (that won’t stay in tune).
I suggest knnsearch to start. I would use the magnitude ( abs ) of the fft of the signals, since they are sampled at the same time and in the same conditions, and are therefore the same length and frequency resolution. The phase information may not be necessary if you are simply comparing the spectral magnitude.
If this fails to reveal the true inheritor of the ophicleide’s place in early music, consider various Feature Transformation procedures on the magnitude spectra of the candidate instruments for dimension reduction to define the important features of the various instruments. (This is the sort of procedure used for biomedical signal analysis and classification, so it is likely valid for your application.)
  4 Comments
Euphonium
Euphonium on 2 Jun 2014
this is what I wrote: I also included the correlations of the signals as well
[x1, Fs] = wavread('baritone_01.wav');
[x2, Fs] = wavread('Bass clar 1_01.wav');
[x3, Fs] = wavread('basstubatone.wav');
[x4, Fs] = wavread('bbbtuba_01.wav');
[x5, Fs] = wavread('bucket_01.wav');
[x6, Fs] = wavread('cup_01.wav');
[x7, Fs] = wavread('euph bucket_01.wav');
[x8, Fs] = wavread('eupho 1_01.wav');
[x9, Fs] = wavread('funny wood_01.wav');
[x10, Fs] = wavread('funny1_01.wav');
[x11, Fs] = wavread('straight1_01.wav');
[x12, Fs] = wavread('trombonetone.wav');
[x, Fs] = wavread('ophi 1_01.wav');
FFTInst = [abs(fft(x1));
abs(fft(x2));
abs(fft(x3));
abs(fft(x4));
abs(fft(x5));
abs(fft(x6));
abs(fft(x7));
abs(fft(x8));
abs(fft(x9));
abs(fft(x10));
abs(fft(x11));
abs(fft(x12))];
corr((abs(fft(x))),(abs(fft(x1))))
corr((abs(fft(x))),(abs(fft(x2))))
corr((abs(fft(x))),(abs(fft(x3))))
corr((abs(fft(x))),(abs(fft(x4))))
corr((abs(fft(x))),(abs(fft(x5))))
corr((abs(fft(x))),(abs(fft(x6))))
corr((abs(fft(x))),(abs(fft(x7))))
corr((abs(fft(x))),(abs(fft(x8))))
corr((abs(fft(x))),(abs(fft(x9))))
corr((abs(fft(x))),(abs(fft(x10))))
corr((abs(fft(x))),(abs(fft(x11))))
corr((abs(fft(x))),(abs(fft(x12))))
knnsearch (abs(fft(x)), (FFTInst))
This gave me a long string, so I plotted it.
I guess it shows Nearest neighbor of every frequency. I guess I could take the mean of each system and use that to calculate a total percentage of similarity?
I normalized and did a DC offset of the audio files before running this code, but I am going to try to normalize the data itself now post fft.
by the way, the names of these files are also of mutes placed in a euphonium bell to change the sound of the instrument. That is why it is called the funny mute, or the funny wood. I am getting a little worried that if the correlation algorithem is correct, the contrabass tuba might be the second closest sound to the ophicleide, destroying my theory. However, this formula says that a bass clarinet sounds closer to a euphonium than any of the instruments do to each other. there are may high overtones, possible 3,000 more hertz that make up the bass clarinet's sound, so I wonder if the sounds are similar but 2 or 3 lower order overtones on the bass clarinet are softer, and that makes the signals look closer mathematically even if they sound extremely distinct.
Star Strider
Star Strider on 2 Jun 2014
Edited: Star Strider on 2 Jun 2014
I hope you did the baseline subtraction and normalisation before you did the knnsearch. Nonetheless, something is obviously wrong, unless I missed something in your latest comment. First, I may have gotten the argument order backwards in my suggested call to knnsearch. See what:
D = knnsearch(FFTInst, abs(fft(x)))
returns. It will be a vector of 12 indices in the ascending order of ‘distance’ from (similarity to) the magnitude of the fft of the ophicleide. Those indices will correspond to the rows in FFTInst. For instance, D(1) will be the index of the closest to the ophicleide, and so on for all 12.
The knnsearch function documentation states:
  • IDX = knnsearch(X,Y) finds the nearest neighbor in X for each point in Y . X is an mx-by-n matrix and Y is an my-by-n matrix. Rows of X and Y correspond to observations and columns correspond to variables. IDX is a column vector with my rows. Each row in IDX contains the index of nearest neighbor in X for the corresponding row in Y .
  • [IDX,D] = knnsearch(X,Y) returns an my-by-1 vector D containing the distances between each observation in Y and the corresponding closest observation in X. That is, D(i) is the distance between X(IDX(i),:) and Y(i,:).
The output of knsearch should produce a vector for the indices of the various other instruments in order of ‘nearness’ of the their fft magnitudes to that of the ophicleide. By my count you should have one column vector (or two, depending on how you called knnsearch) that has only 12 elements. What are you plotting? I have no idea what knnsearch returns without any output arguments. Usually this is simply the first output, but it seems it returned something entirely different in your call to it.
If you want the correlation coefficients, include abs(fft(x)) (the fft magnitude vector for the ophicleide), possibly as the first row in a slightly differently named FFTInst matrix (maybe FFTInstR), and then use that matrix as the argument to the corr or corrcoef functions. You need to use all the functions with output arguments to understand the information they’re giving you.
Don’t worry about your hypothesis being disproved just yet. When we get all this sorted, it may turn out that you are correct.

Sign in to comment.

Categories

Find more on Measurements and Feature Extraction in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!