1
$\begingroup$

How can I create a bar based spectrogram that updates as a .wav file is playing. This is commonly found in music players. Here is an example below: enter image description here

I am able to display a amplitude/frequency graph that updates as the .wav file is being played using this code below:

function syncPlayerDemo()
%some example music
%set up audio player
%player = audioread('test.wav');
[y,Fs] = audioread('test.wav');
player = audioplayer(y, Fs);
[samples,channels]=size(y);
%calculate timeline
t=linspace(0,1/Fs*(samples-1),samples);
%initialize full plot, update will only move the visible area using xlim
h=plot(t,y);
%set up callback to update every <TimerPeriod> s
player.TimerFcn=@timerFcn;
player.TimerPeriod=0.1;
player.playblocking()
end
function timerFcn(source,data)
%an area of length <area> s will be visible
area=1;
position=(source.CurrentSample-1)/source.SampleRate;
%move visible area, current position is in the center
set(gca,'XLim',[position-area/2,position+area/2]);
%used a waitbar for testing, might be commented in
%waitbar(source.CurrentSample/source.TotalSamples);
end

Which results in an updating graph: enter image description here

How can I get the bars like above, any suggestions?

$\endgroup$
3
  • $\begingroup$ Your "amplitude/frequency graph" is actually amplitude vs time. To get amplitude vs frequency you need to do an FFT on each chunk and then probably bin it on a log frequency scale. $\endgroup$
    – endolith
    Commented Nov 24, 2015 at 14:43
  • $\begingroup$ that's not a spectrogram, that is a frequency analysis over the whole time. Break down your signal in segments of equal length, and do this for each of them. See specgram for something that already does this. $\endgroup$ Commented Aug 20, 2016 at 17:31
  • $\begingroup$ dsp.stackexchange.com/a/2427/29 $\endgroup$
    – endolith
    Commented May 8, 2019 at 17:14

2 Answers 2

1
$\begingroup$

You can get the bar based spectrogram by decomposing the signal segments into fractional-octave subbands. Try octaveFilterBank and then compute signal power level by pow2db(sum(abs(signal))). This will result in a logarithmic frequency scale.

You can also use pwelch to estimate power spectral density, which brings you a linear frequency scale.

$\endgroup$
0
$\begingroup$

I guess you can simply change the command "plot(t,y)" to "bar(t,y)" and customize the plot more!

If you want the visual to look good, try dspSystemToolbox. This is much easier and allows frame based processing (it will process particular number of samples each time) with more smoother response.Especially "the time scope" looks much better and allows "stair plotting"(check doc dsp.TimeScope). I feel it suits more for your need, although there is no problem with the present code.

If you are not familiar with this and If you have already installed dspSystemToolbox, you can type on command line "testbenchGeneratorExampleApp", the GUI there after appears will allow you to configure sources and sinks and generate the respected MATLAB code directly for you. You can modify this code little to appear the data in bars and you can customize this bar plot also. I suggest customizing the Timescope.
Hope this helps :)

$\endgroup$
2
  • 1
    $\begingroup$ This is only half of the solution. Using bar() instead of plot() will change how the data is plotted. However, @Techno04335 asked for a spectrogram. The nomenclature does not quite match the plot he's showing. I assume the goal is a plot of some sort of power spectral density (PSD) estimate and - most preferrably - a conversion to logarithmic dB scale. Something like y = 20 * log10(abs(FFT(y))) should do the trick in this case. Furthermore, it will not be possible to shift the visible region when displaying the PSD. Better compute the PSD for each block and plot it indvidually. $\endgroup$
    – applesoup
    Commented Feb 23, 2016 at 23:41
  • $\begingroup$ dspSystemToolbox has Spectrogram and Timescope and both look visually very good with bar plot customization, which iI thought is close to what he is asking for. But yes you are correct. $\endgroup$
    – charansai
    Commented Feb 24, 2016 at 0:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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