\( \def\xx{\mathbf x} \def\xX{\mathbf X} \def\yy{\mathbf y} \def\bold#1{\bf #1} \)
Download the following matlab files: [stft.m]
“stft.m” computes the complex spectrogram of a signal.
You can read a wav file into matlab as follows:
[s,fs] = audioread('filename'); s = resample(s,16000,fs);
Above, we resample the signal to a standard sampling rate for convenience. Next, we can compute the complex short-time Fourier transform of the signal, and the magnitude spectrogram from it, as follows. Here we use 2048 sample windows, which correspond to 64ms analysis windows. Adjacent frames are shifted by 256 samples, so we get 64 frames/second of signal.
To compute the spectrogram of a recording, e.g. the music, perform the following.
spectrum = stft(s',2048,256,0,hann(2048)); music = abs(spectrum); sphase = spectrum ./(abs(spectrum)+eps);
This will result in a 1025-dimensional (rows) spectrogram, with 64 frames(columns) per second of signal.
Note that we are also storing the phase of the original signal. We will need it later for reconstructing the signal. We explain how to do this later. The eps
in this formula ensures that the denominator does not go to zero.
You can compute the spectra for the notes as follows. The following script reads the directory and computes spectra for all notes in it.
notesfolder = 'notes15/'; listname = dir([notesfolder '*.wav']); notes = []; for k =1:length(listname) [s,fs] = audioread([notesfolder listname(k).name]); s = s(:,1); s = resample(s,16000,fs); spectrum = stft(s',2048,256,0,hann(2048)); % Find the central frame middle = ceil(size(spectrum,2)/2); note = abs(spectrum(:,middle)); % Clean up everything more than 40db below the peak note(find(note < max(note(:))/100)) = 0; note = note/norm(note); %normalize the note to unit length notes = [notes,note]; end
The “notes” matrix will have as many columns as there are notes (15 in our data). Each column represents a note. The notes will each be represented by a 1025 dimensional column vector.
reconstructedmagnitude
be the reconstructed magnitude spectrogram from which you want to compute a signal. In our homework we get many variants of this. To recover the signal we will use the sphase
we computed earlier from the original signal.
reconstructedsignal = stft(reconstructedmagnitude.*sphase,2048,256,0,hann(2048));