Home > graphics > 3D spectrogram plots

3D spectrogram plots

April 7Hits:1
Advertisement

How can I compute and plot the spectrogram of a signal/time series/data in Mathematica? I have a WAV file, sampled at 44100 samples/second and I want to generate a spectrogram of that data. Something like this:

3D spectrogram plots

Answers

Get a sample sound:

snd = ExampleData[{"Sound", "SopranoSaxophone"}];

This gives us a Sound data structure with a SampledSoundList as first element. Extracting the data from it:

sndData = snd[[1, 1, 1]];
sndSampleRate = snd[[1, 2]];

Plotting the data:

ListPlot[sndData, DataRange -> {0, Length[sndData]/sndSampleRate },
 ImageSize -> 600, Frame -> True,
 FrameLabel -> {"Time (s)", "Amplitude", "", ""},
 BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 14}]

3D spectrogram plots

Find the lowest amplitude level (used as reference for dB calculations):

min = Min[Abs[Fourier[sndData]]];

A spectrogram is made by making a DFT of partitions of the sample. The partitions usually have some overlap.

partSize = 2500;
offset = 250;
spectroGramData =
  Take[20*Log10[Abs[Fourier[#]]/min], {2, partSize/2 // Floor}] & /@
   Partition[sndData, partSize, offset];

Note that I skip the first element of the DFT. This is the mean level. I also show only half of the frequency data. Because of the finite sampling only half of the returned coefficient list contains useful frequency information (up to the Nyquist frequency).

MatrixPlot[
  Reverse[spectroGramData\[Transpose]],
  ColorFunction -> "Rainbow",
  DataRange ->
    Round[
     {{0, Length[sndData]/sndSampleRate },
     {sndSampleRate/partSize, sndSampleRate/2 }},
     0.1
    ],
  AspectRatio -> 1/2,  ImageSize -> 800,
  Frame -> True, FrameLabel -> {"Frequency (Hz)", "Time (s)", "", ""},
  BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 12}
]

3D spectrogram plots

A 3D spectrogram (note the different offset value):

partSize = 2500;
offset = 2500;
spectroGramData =
  Take[20*Log10[Abs[Fourier[#]]/min], {2, partSize/2 // Floor}] & /@
   Partition[sndData, partSize, offset];

ListPlot3D[spectroGramData\[Transpose], ColorFunction -> "Rainbow",
 DataRange ->
  Round[{{0, Length[sndData]/sndSampleRate }, {sndSampleRate/partSize,
      sndSampleRate/2}}, 0.1], ImageSize -> 800,
 BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 12}]

3D spectrogram plots

The following is a more detailed version of a Spectrogram implementation in Mathematica and is part of a larger package that I'm writing in my spare time. I've tried to keep the functionality and output structure similar to MATLAB's (but not entirely). The code is provided at the end of this answer, and I'll jump to the examples now:

First load the package and some example data:

<<SignalProcessing`
{data, fs} = {#[[1, 1, 1]], #[[1, 2]]} &@ ExampleData[{"Sound", "Apollo11SmallStep"}];

Spectrogram takes several options such as:

  • WindowFunction — Hamming, Hanning and rectangular (default) windows are pre-defined and you can extend it to other windows or supply one of your own.
  • WindowLength — Samples in each segment (default is Floor[Length[data]])
  • OverlapLength — Samples overlapping with the previous segment (default 50%)
  • FFTLength (default: Max[256, 2^pow] where pow is the next power of 2 larger than your segment length) and SamplingFrequency are self explanatory

A sample call to Spectrogram with the above data would be:

{s, f, t} = Spectrogram[data, WindowFunction -> Hamming, WindowLength -> 200,
   SamplingFrequency -> fs];

You can then plot this like in Sjoerd's example (or you can implement a default plot style within Spectrogram) to get something like:

3D spectrogram plots

A couple of things that are on my to-do list are to implement the Goertzel algorithm so that you can easily supply a list of frequencies at which the spectrogram needs to be calculated and different plotting schemes for 2D (something like the plot above as default) and waterfall and similar for 3D plots. I'll update this post when I get around to doing that.


Spectrogram code

BeginPackage["SignalProcessing`"];
Unprotect[Spectrogram,Hamming,Hanning,Rectangular];

Begin["`Private`"];
(* Input checks *)
DoubleQ[data_List] := And @@ Function[x, MachineNumberQ[x], Listable][data];

CheckInput::sparse = "The input data must not be sparse!";
CheckInput::nodbl = "The input data must be machine precision!";
CheckInput[x_] := Which[
    Head[x] === SparseArray, Message[CheckInput::sparse],
    ! DoubleQ[x], Message[CheckInput::nodbl],
    True, True
]

(* Window functions *)
Rectangular = UnitStep[Range[#]] &;
Hanning = 0.5 (1 - Cos[2 Pi Range[0, #-1]/(#-1)]) &;
Hamming = 0.54 - 0.46 Cos[2 Pi Range[0, #-1]/(#-1)] &;

(* Spectrogram code *)
Spectrogram[data_List, opts : OptionsPattern[{
    WindowFunction -> Rectangular, WindowLength :> Floor[Length[data]/8],
    OverlapLength -> {}, FFTLength -> {}, SamplingFrequency -> 1}]] :=
    Module[{
        x = Developer`ToPackedArray[data], len = Length[data], win, seg,
        olap, nfft, fs, spectra, time, freq},
        (* parameters *)
        seg = OptionValue[WindowLength];
        olap = If[# === {}, Floor[seg/2], #] &@OptionValue[OverlapLength];
        nfft = If[# === {}, Max[2^Ceiling[Log2[seg]], 256], #] &@ OptionValue[FFTLength];
        win = OptionValue[WindowFunction];
        fs = OptionValue[SamplingFrequency];
        (* output *)
        time = Range[0, len]/fs;
        freq = fs Range[0, nfft/2]/nfft ;
        spectra = Take[Abs[Fourier[PadRight[#*win[seg], nfft], FourierParameters -> {1, -1}]] & /@
            Partition[x, seg, seg - olap, {1, -1}] // Transpose, Floor[nfft/2] + 1];

        {spectra, freq, time}
    ] /; CheckInput[data]
End[];

Protect[Spectrogram,Hamming,Hanning,Rectangular];
EndPackage[];

Version 9 has introduced several signal processing functions and Spectrogram is now a built-in function. You can simply do:

{data, fs} = {#[[1, 1, 1]], #[[1, 2]]} &@ExampleData[{"Sound", "Apollo11SmallStep"}];
Spectrogram[data, SampleRate -> fs, ColorFunction -> "Rainbow",
    FrameLabel -> {"Frequency (Hz)", "Time (s)"}]

3D spectrogram plots

Mathematica can plot spectrograms using the Spectrogram function or the SpectrogramArray function, or the Fourier function -- it is very general and powerful. Here are some examples of audio spectrograms from the Wolfram demonstration site and here is a discussion on Mathematica stackexchange of the process of taking spectrograms of audio. To use mp3s you will need to convert them to .wav files, which can be done using a program like Audacity or Quicktime (or many others). If your final goal is to plot spectrograms, Audacity (or other free software) might be more appropriate. What you would gain in Mathematica is the ability to control the analysis in complete detail -- but this would not be automatic or trivial, it would take some knowledge of how the spectral functions work.

Related Articles

  • 3D spectrogram plots

    3D spectrogram plots April 7

    How can I compute and plot the spectrogram of a signal/time series/data in Mathematica? I have a WAV file, sampled at 44100 samples/second and I want to generate a spectrogram of that data. Something like this: --------------Solutions------------- Ge

  • Python - time frequency spectrogram

    Python - time frequency spectrogramAugust 7

    I have some 64 channel EEG data sampled at 256Hz and I'm trying to conduct a time frequency analysis for each channel and plot a spectrogram. The data is stored in a numpy 3d array, where one of the dimensions has length 256, each element containing

  • Computing and plotting a spectrogram in Mathematica

    Computing and plotting a spectrogram in MathematicaApril 7

    How can I compute and plot the spectrogram of a signal/time series/data in Mathematica? I have a WAV file, sampled at 44100 samples/second and I want to generate a spectrogram of that data. Something like this: --------------Solutions------------- Ge

  • How to plot Spectrogram of SoundNote?January 4

    I try to use the expression: Spectrogram[Sound[SoundNote[{"C", "E", "G", "C5"}, 10, "Vibraphone"]]] to plot the spectrogram of a SoundNote. But Spectrogram symbol do not support SoundNote. I tried Play and

  • Why the Spectrogram can't plot correctly?

    Why the Spectrogram can't plot correctly?December 30

    The same data lead two different graph. Plot[E^(-Pi*(t - 5)^2), {t, -10, 10}, PlotRange -> All] The method to plot the spectrogram use the build-in function: Samplerate = 20;data = Table[E^(-Pi*(t - 5)^2), {t, 0, 10, 1/Samplerate}]; Spectrogram[data,

  • How to increase Spectrogram resolution?

    How to increase Spectrogram resolution?October 21

    I have a time-domain signal that I want do a time-frequency analysis on it. When I tried the Spectrogram, I always get very low resolution. For example: I have a signal like this: data = Table[ Piecewise[{{Sin[2 \[Pi] 10 t], 0 <= t < 1/4}, {Sin[2 \[

  • Plot Notes present in sound sample

    Plot Notes present in sound sampleApril 14

    I would like to visualize a sampled sound, and place the sounds as notes starting from C0 to A8 or such. I have a table of frequencies (in $[Hz]$) of these notes, and I have a sample sound. My goal is to have along the $y$ axis the possible notes, an

  • Customizing output of Spectrogram[], units of Periodogram[]?

    Customizing output of Spectrogram[], units of Periodogram[]?March 16

    I am analyzing spectrum of recorded sound. For that purpose I am using Mathematica's built in functions Spectrogram[] and Periodogram[]. I have three questions regarding those: What is the way to set desired range on frequency axis (y-axis) in Spectr

  • How can I use Mathematica to numerically compute a Wigner spectrogram of an optical pulse?

    How can I use Mathematica to numerically compute a Wigner spectrogram of an optical pulse?November 17

    This question was inspired by this question where it is necessary to numerically compute the Fourier transform of a Gaussian optical pulse with a Gaussian chirp function. $$E(t)=e^{-t^2} \cos(50 t - e^{-2 t^2} 8 π)$$. I was thinking that the Fourier

  • Matplotlib spectrogram versus STFTFebruary 5

    I'm currently computing the spectrogram with the matplotlib. I specify NFFT=512 but the resulting image has a height of 257. I then tried to just do a STFT (short time fourier transform) which gives me 512 dimensional vectors (as expected). If I plot

  • How to change the color in colormap in surf plot?

    How to change the color in colormap in surf plot?February 15

    I have the following code and I have plotted a 3D plot for the stft with respect to time, frequency and amplitude. How do I change the black color seen in the plot to white? I do not understand how to change the black color to white in colormap optio

  • Good graph plotting appOctober 14

    Does anyone know of a free graph plotting app for windows (or online) that can plot something like this? Xn+1= r sin (π * Xn) --------------Solutions------------- I'd like to suggest WolframAlpha, but it has got troubles with the "r*", the best

  • How to plot dot labeled data?November 7

    I'd like to turn a file like: Name X Y a 1 2 b 4 1 s 3 3 in a X-Y graphic with the X-Y dots labeled with Name. How can I do it? I think this can be done with gnuplot, but I wasn't able to do it yet. --------------Solutions------------- You can put la

  • Spectrogram app for the Mac

    Spectrogram app for the MacNovember 12

    Where do I find a real time spectrogram analysis application for the Mac? Freeware or Shareware if possible. --------------Solutions------------- Spectrogram is a free real-time spectrum analyzer VST plug-in for Macintosh. The spectrum may be shown i

  • Plot an area defined by a parameter range ofNovember 23

    If I have something like this: y = sin(x+z) How can I plot the values of y, as a function of x and all the possible values of z in [-0.1, +0.1]? That is, I want the area defined by those limits. So everything bounded by sin(x-0.1) and sin(x+0.1) woul

  • Excel graph plotting for large data set with datesJanuary 23

    I have a large table of data (not created by me) with more than 1500 rows. The first column of which is a list of dates, monthly, starting from 1870. Some of the columns contain data for the full rage of dates while in others data is available only i

  • Plot a line chart in Excel 2007January 23

    I have 2 columns of numbers, column A i want to be the X axis of a line graph, and column B to be the Y axis. Whenever i select the range, Excel just gives me two series instead of plotting one against the other. I am obviously missing something. Tha

  • How to easily plot graph, using (preferably) free software?

    How to easily plot graph, using (preferably) free software?February 2

    I need to plot a graph, given some data, where on X axis will be names of data and on Y axis those data, and it will be given by a table, and it will be line graph with the data connected. If there was a possibility to draw more data into one graph,

  • Free software to plot cartogramsApril 8

    Is there any free software to plot cartograms? --------------Solutions------------- MAPresso is a free Java applet for unclassed choropleth maps and cartograms.

  • How to plot survey results on Excel?

    How to plot survey results on Excel?June 1

    I would like to plot the average of these data samples: 1. Contribution to the project 2. Affiliation with project owners 3. Level of expertise 4. Learning Curve Yes No 3 2 No No 3 2 No No 4 3 No No 5 3 No No 3 3 Yes Yes 5 4 No No 4 3 No No 3 2 No Ye

Copyright (C) 2018 ceus-now.com, All Rights Reserved. webmaster#ceus-now.com 14 q. 0.339 s.