Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have:

music = Import["http://www.qlcoder.com/uploads/145425353234642.mp3", "mp3"]

Then I get:

enter image description here

But what I want to get is F(t)=x Hz(means in t, the frequency is x Hz). Then how to get that?

share|improve this question
2  
What if there are superimposed sounds of multiple frequencies (as is almost always the case)? Then a simple frequency(t) doesn't make sense. You may want to compute a spectrogram: mathematica.stackexchange.com/questions/4017/… – Szabolcs Feb 1 at 13:10
    
If you know for sure that there is only a single (possibly amplitude and frequency modulated) sine oscillator active (e.g. $f(t)=a(t)sin(\omega(t)),\omega(t)=\omega_0 + \int_0^t 2\pi f(s) ds$), then you can see your waveform as the real part of a complex (as in complex numbers) oscillator. You can then use a Hilbert transform (see here) to get the corresponding imaginary part of that oscillator and use this to reconstruct $a(t)$ and $f(t)$ (which is just $\frac{d\omega(t)}{dt}$). – Thies Heidecke Feb 1 at 18:03
up vote 6 down vote accepted

Duration = 9.95265 sec, frequency in Hz on x axis:

music = Import["http://www.qlcoder.com/uploads/145425353234642.mp3", "mp3"];
amps = music[[1, 1, 1, All]];
namps = Length@amps; (* namps = 438912 corresponds to 9.95265 sec *)

sr = 44100; (* your sampling rate in Hz *)
inc = sr/namps; (* increment *)
freq = Table[f, {f, 0, sr - inc, inc}] // N;

y = Abs@Fourier[amps, FourierParameters -> {-1, 1}];
data = Transpose[{freq, y}];

fmax = 3000; (* you can go up to Nyquist frequence = max frequency = 22050 Hz *)

ListLinePlot[data, Frame -> True, Joined -> True, 
 PlotStyle -> {RGBColor[0, 0, 1], Thickness[0.002]}, 
 FrameLabel -> {{"Amplitude", ""}, {"f (Hz)", ""}}, 
 BaseStyle -> {FontWeight -> "Bold", FontSize -> 20, 
   FontFamily -> "Calibri"}, PlotRange -> {{0, fmax}, All}, 
 ImageSize -> 800]

enter image description here

share|improve this answer

You can see the spectrum of the first note played, (first 40000 points)

ListLogLogPlot[
 {#, # PeakDetect[#, 5, 10^-2]} &@
  Abs@Fourier@music[[1, 1, 1, 1 ;; 40000]]
 , Joined -> {True, False}
 , PlotStyle -> {Gray, Red}
 , Filling -> Axis
 , PlotRange -> {{100, 1000}, All}
 , PlotTheme -> "Scientific"]

Mathematica graphics

But beware that the scaling is not in Hertz here To get the scaling correct use:

sft[d_, sr_] := Block[{n, ft, fy},
  n = Length[d];
  fy = Take[N@Abs[Fourier[d]], n/2];
  ft = N@Range[0, n/2 - 1] sr/n;
  SortBy[First]@Transpose[{ft, fy}]
  ]

ListLogLogPlot[
 {#, Part[#, 
     Flatten@Position[PeakDetect[#[[All, 2]], 5, 10^-2], 1]]} &@
  sft[music[[1, 1, 1, 1 ;; 40000]], music[[1, 2]]]
 , Joined -> {True, False}
 , PlotStyle -> {Gray, Red}
 , Filling -> Axis
 , PlotRange -> {{100, 1000}, All}
 , PlotTheme -> "Scientific"]

Mathematica graphics

To see the peaks of the first two notes:

Part[#, Flatten@Position[PeakDetect[#[[All, 2]], 5, 10^-2], 1]] &@
 sft[music[[1, 1, 1, 1 ;; 40000]], music[[1, 2]]]
 {{174.195, 4.61849}, {350.595, 5.65904}, {524.79, 3.73059}}
Part[#, Flatten@Position[PeakDetect[#[[All, 2]], 5, 10^-2], 1]] &@
 sft[music[[1, 1, 1, 40001 ;; 70000]], music[[1, 2]]]
{{164.64, 3.93114}, {330.75, 3.66594}, {495.39, 1.70307}, {660.03, 4.29606}, {826.14, 1.9469}}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.