Create new .wav files around findpeak outputs
4 次查看(过去 30 天)
显示 更早的评论
Hi everyone,
I would like to create short .wav files containing the audio data of each detected peak (see plot below as example). I would like the data in each .wav file to include the peak and a buffer on either side of roughly 0.02 s (e.g. black boxes around peaks would each be seperate .wav files). I have include my code so far and added a zip file with a short sample of the data to run code below.
% Read in audio file
[y,Fs] = audioread('test_MATLABAsk.wav');
info = audioinfo('test_MATLABAsk.wav');
sound(y,Fs) % Play the sound
% plot the data
% Create a time component using info
t = 0:seconds(1/Fs):seconds(info.Duration);
t = t(1:end-1);
figure(1)
plot(t,y)
xlabel('Time (s)')
ylabel('Audio Signal')
% Detect peaks from y
[pk_Fs, locs_Fs] = findpeaks(y,Fs, 'MinPeakDistance',0.03, 'MinPeakHeight',0.01); % See plot example below
0 个评论
采纳的回答
Guillaume
2019-10-8
Here's how I'd do it:
infile = 'C:\somewhere\somefolder\test_100m.wav'; %I'd recommend you use full path instead of relying on the current directory
outfolder = 'C:\somewhere\someotherfolder';
outformat = 'split%03d.wav'; %using sprintf format to insert peak number
halfwidth = seconds(0.02); %half width of signal to keep around peak
%read file, convert to timetable, find peak locations
[samples, Fs] = audioread(infile);
audiotable = timetable(samples, 'SampleRate', Fs);
[~, peaklocs] = findpeaks(samples, Fs, 'MinPeakDistance', 0.03, 'MinPeakHeight', 0.01);
%iterate over peaks, extract signal and save to file
for peakidx = 1:numel(peaklocs)
peaktime = audiotable.Time(peakloc(peakidx));
tokeep = isbetween(audiotable.Time, peaktime - halfwidth, peaktime + halfwidth);
audiowrite(fullfile(outfolder, sprintf(outformat, peakidx)), audiotable.samples(tokeep), Fs);
end
19 个评论
Guillaume
2019-10-9
Ok, so peaktime makes sense, you're using a wav file much longer than the one you originally posted. The duration of that file is at least 110 seconds.
peaktime is simply (peaklocs-1) ./ Fs
and peaktime is a plain vector. I did write in a comment that if it's a plain vector you needed to convert that to a duration vector with seconds. Otherwise, it's interpreted as days when you subtract audiotable.Time. So, correct code using Fs for findpeaks:
infile = 'C:\somewhere\somefolder\test_100m.wav'; %I'd recommend you use full path instead of relying on the current directory
outfolder = 'C:\somewhere\somefolder\OutWav';
outformat = 'split%03d.wav'; %using sprintf format to insert peak number
halfwidth = seconds(0.02); % half width of signal to keep around peak
%read file, convert to timetable, find peak locations
[samples, Fs] = audioread(infile);
audiotable = timetable(samples, 'SampleRate', Fs);
[~, peaktimes] = findpeaks(samples, Fs, 'MinPeakDistance', 0.03, 'MinPeakHeight', 0.01);
peaktimes = seconds(peaktimes);
%iterate over peaks, extract signal and save to file
for peakidx = 1:numel(peaktimes)
tokeep = abs(audiotable.Time - peaktimes(peakidx)) <= halfwidth;
audiowrite(fullfile(outfolder, sprintf(outformat, peakidx)), audiotable.samples(tokeep), Fs);
end
For what it's worth, I've raise a service request with Mathworks to get them to improve the documentation of findpeaks.
更多回答(0 个)
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!