-
Notifications
You must be signed in to change notification settings - Fork 0
/
jp_getenvelope.m
97 lines (80 loc) · 2.56 KB
/
jp_getenvelope.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function env = jp_getenvelope(s, fs, opts)
%JP_GETENVELOPE Return the envelope of a sound.
%
% JP_GETENVELOPE(S, [FS], [OPTS]) returns the envelope of signal S using
% sampling frequency FS. S can be a .wav file in which case FS can
% be left empty or ommitted. If S is not a .wav file FS must be
% specified.
%
% opts has the following fields
% rectify 'full' or 'half' (default 'half')
% freq smoothing frequency for envelope in Hz (default 30)
% edge_freqs edge frequencies for channels (see below)
%
% If opts.edge_freq is specified, the function returns one envelope
% for each of M channels, where M = length(edge_freq) - 1. The
% default is opts.edge_freq = [], in which case the envelope for
% the unfiltered signal is returned.
%
% JP_GETENVELOPE requires the signal processing toolbox.
%
%
% From https://github.com/jpeelle/jp_matlab
if nargin < 3
opts = struct();
end
if ischar(s)
[path,name,ext] = fileparts(s);
if strcmp(lower(ext),'.wav')
[s, fs] = audioread(s);
else
error('If a file, S must be a .wav file.')
end
else
% If not a .wav file, make sure fs is specified
if nargin < 2 || isempty(fs)
error('If S is not a .wav file, you must specify Fs.')
end
end
half_sample_rate = fs/2;
% set defaults -------------------------------------------
if ~isfield(opts, 'rectify') || isempty(opts.rectify)
opts.rectify = 'half';
end
if ~isfield(opts, 'freq') || isempty(opts.freq)
opts.freq = 30;
end
if isfield(opts, 'edge_freqs')
if length(opts.edge_freqs) < 2
error('If specifying edge frequencies, must specify at least 2.');
end
else
opts.edge_freqs = [];
end
if ~(strcmp(opts.rectify,'full') || strcmp(opts.rectify, 'half'))
error('opts.rectify must be ''full'' or ''half''');
end
% Create the low-pass filter
[lpB,lpA]=butter(2,opts.freq/half_sample_rate);
if isempty(opts.edge_freqs)
if strcmp(opts.rectify,'half')
env = filter(lpB,lpA,0.5*(abs(s)+s));
elseif strcmp(opts.rectify,'full')
env = filter(lpB,lpA,abs(s));
end
else
% create a matrix for holding the envelopes, one per row
env = zeros(length(opts.edge_freqs)-1, length(s));
for i=1:length(opts.edge_freqs)-1
W1 = [opts.edge_freqs(i)/half_sample_rate, opts.edge_freqs(i+1)/half_sample_rate];
[infilterB, infilterA] = butter(3,W1);
% filter the sound
yy = filter(infilterB, infilterA, s)';
% and get the envelope of the filtered sound
if strcmp(opts.rectify,'half')
env(i,:) = filter(lpB,lpA,0.5*(abs(yy)+yy));
elseif strcmp(opts.rectify,'full')
env(i,:) = filter(lpB,lpA,abs(yy));
end
end
end