Plotting spectrograms for multiple files

28 views (last 30 days)
I have multiple acoustic files for which I would like to plot a spectrogram on a single plot.
I know how to plot one spectrogram:
[xbit,fs]=audioread(fullfname, [nlo nup]); %read in wav
xbit=detrend(xbit); %remove DC offset
calxbit=xbit*cal; %apply calibration
%Perform FFT and plot:
[S,F,T,P] = spectrogram(calxbit,window,overlap,nfft,fs,'yaxis');
figure(2);
h = pcolor(T,F,10*log10(P));
set(h,'EdgeColor','none');
This provides one figure with time on the x axis and frequency on the y-axis, and colourplot for intensity.
However, I would like to plot multiple spectrograms and so the x-axis represents multiple files which were collected over time e.g. every 5 minutes.
I considered that I could read in the acoustic data for multiple files and concatenate it, but this would not preserve any gaps in time between the subsequent files (which may or may not be negligible). I'd like to have the x tick marks represent the start time of each separate file perhaps.

Answers (1)

Bjorn Gustavsson
Bjorn Gustavsson on 6 Oct 2021
Wouldn't you achieve the desired output by putting the different spectrograms in consecutive subplots?
Something like this perhaps:
nFiles = numel(fullfnames);
for iFile = 1:nFiles
fullfname = fullfnames{iFile};
t0 = Tstart(iFile);
[xbit,fs]=audioread(fullfname, [nlo nup]); %read in wav
xbit=detrend(xbit); %remove DC offset
calxbit=xbit*cal; %apply calibration
%Perform FFT and plot:
[S,F,T,P] = spectrogram(calxbit,window,overlap,nfft,fs,'yaxis');
sph(iFile) = subplot(1,nFiles,iFile);
h = pcolor(T,F,10*log10(P)); % Here you might want to add the start-time, t0, to T
% with proper conversion of time-format...
set(h,'EdgeColor','none');
end
Then you can adjust the spacing of the sub-plot-panels using sph (also consider using tile-nexttile)
HTH
  8 Comments
Louise Wilson
Louise Wilson on 7 Oct 2021
This works, but when I try to expand the limits of the plot to see both spectrograms (when doing 2 files only) the plot goes blank.
directory={'X:\SoundTrap\Boats\wav\Noises\LTSA test\LTSA test batch'}; %folder where wav files are
folder=char(directory);
fullfnames=dir(fullfile(folder,'*.wav')); %list all .wavs in folder
nFiles=numel(fullfnames);
%get fs of first (i.e. all) files in folder
firstfile=fullfile(folder,char(fullfnames(1,1).name));
[xbit,fs]=audioread(firstfile,[1 2]);
tlo=1.0;
thi=114.0;
nlo=fs*tlo; %multiply fs by tlo to get starting point
nup=fs*thi; %do the same for end point
nfft=16384;
window=16384;
overlap=window/2; %50% overlap
cal=176.4;
cal=power(10,cal/20); %calculate calibration value
t0=0;
dt=1;
for iFile = 1:2%nFiles
fullfname = fullfnames(iFile).name;
%format is xxxx.yyMMddHHmmss.cut.wav
% you'll have to set/get/extract start-time for each spectrogram
fname=strsplit(fullfname,{'.'});
fname_st=fname(2);
fname_st=datenum(fname_st,'yyMMddHHmmss');
tStartstrings{iFile} = fname_st;% you'll have to set/get/extract start-time for each spectrogram
[xbit,fs]=audioread(fullfile(folder,fullfname), [nlo nup]); %read in wav
xbit=detrend(xbit); %remove DC offset
calxbit=xbit*cal; %apply calibration
%Perform FFT and plot:
[S,F,T,P] = spectrogram(calxbit,window,overlap,nfft,fs,'yaxis');
T=fname_st+datenum(seconds(T)); %start time of .wav file + seconds of each chunk
%to produce informative x-axis
h = pcolor(T,F,10*log10(P)); % Here you might want to add the start-time, t0, to T
% with proper conversion of time-format...
hold on
set(h,'EdgeColor','none');
end
Bjorn Gustavsson
Bjorn Gustavsson on 8 Oct 2021
That might be because you now add the ID-time of each file to the start-time, which meand that if you have large gaps (you mentioned something like 5 minutes appart, and then each of those files were for a couple of seconds worth of data) between the spectrograms. The idea I proposed was to plot the first spectrogram at times between
0 and "10 s" the next spectrogram between "10 s"+dt and "20 s"+dt, the third spectrogram between "20 s"+2*dt and "30 s"+2*dt and so on. The next step is then to se the tick-marks to:
xTickTimes = 0:("10 s"+dt):(N*("10 s"+dt));
set(gca,'Xtick',xTickTimes)
Which should give you tickmarks at the start of each spectra, next you'll have to set the Xticklabel. For that you should have made a cell-array of the fname_st-contents, lets say you call that variable t_filestarts_all, then this should be:
set(gca,'XtickLabel',t_filestarts_all)
This way you will have an uneven time-axis, one scale for the file-start-times and between those the time-scales of the spectrograms.
HTH

Sign in to comment.

Categories

Find more on Time-Frequency Analysis in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!