-
Notifications
You must be signed in to change notification settings - Fork 2
/
adma.m
158 lines (148 loc) · 5.15 KB
/
adma.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
%-----------------------------------------------------------------------
%| Function: adma
%-----------------------------------------------------------------------
%| Process the signal of the 3 channel differential
%| microphone array.
%|
%| Author: Patrick Michelson
%| Version: 0.1
%| Date: 06.09.2012
%| Library: ADMA
%|
%-----------------------------------------------------------------------
function [ out options sigVecCard ] = adma(sigVecProc,freqVec,fs,options...
,speedOfSound)
%% PARAMETER %%
d = options.d; %distance between microphones
steeringMethod = options.steeringMethod;
%Build cardioid and eight signals
[sigVecCard sigVecEight] = admaBuildCardioids(sigVecProc,freqVec,d...
,speedOfSound,options.doEqualization);
no_speaker = false;
%% Locate Speaker %%
if (options.findMax)%use adaptive alogrithm to find speaker
search_range = options.search_range;
weights = admaParams(search_range, search_range+180,steeringMethod);%weights
if (isfield(options,'speaker_range'))%use function with speaker_range TODO don't use isfield
[theta power1 no_speaker] = admaFindMax2(sigVecSearch, ...
search_range, ...
weights, ...
options.speaker_range, ...
options.last_theta);
theta1 = theta(1);
if (options.findMin)
if (isnan(theta(2)))
theta2 = theta1+180;
else
theta2 = theta(2);
end
else
theta2 = options.theta2;
end
else%use function wiouth speaker_range
[theta1 power1] = admaFindMax(sigVecSearch, search_range, weights);
if (options.findMin)
search_range = (theta1+90):15:(theta1+270);
weights = admaParams(theta1*ones(size(search_range)),search_range...
,steeringMethod);
[theta2] = admaFindMin(sigVecCard, search_range,weights);
else
theta2 = options.theta2;
end
end
%diff between theta1 & theta2 < 90deg?
%if (real(exp(j*(theta2-theta1)/180*pi))>0)
% theta1 = theta2 + 90;
%end
else%do not use adaptive algo to find speaker
theta1 = options.theta1;
if (options.findMin)
search_range = (theta1+90):15:(theta1+270);
weights = admaParams(theta1*ones(size(search_range)),search_range...
,steeringMethod);
[theta2] = admaFindMin(sigVecCard, search_range,weights)
else
theta2 = options.theta2;
end
end%findMax
%Cancel audio if no speaker is found
if (no_speaker && options.zero_noise)
out = zeros(size(sigVecProc));
out(3,:) = 1/3*sum(sigVecCard);
options.newMask = -1;
options.theta2 = NaN;
else
%% Build Pattern
if (strcmpi(options.pattern, 'cardioid'))
theta2 = theta1+180;
end
if(limitAngle(theta1) == limitAngle(theta2))
theta1 = theta2+180;
end
%calculate weights
weights1 = admaParams(theta1, theta2,steeringMethod);%best pattern
weightSphere = admaNullToSphereAndEight(theta1-theta2);%weight for adding
%sphere and eight, only used if steeringMethod = 'eights'
%calculate output signals
out(3,:) = 1/3*sum(sigVecCard);%omni directional
if(strcmpi(steeringMethod,'cardioids'))
out(1,:) = weights1' * sigVecCard;%found pattern, will be overwritten
%with binary masked signal
out(2,:) = out(1,:);%found pattern, wit not be overwritten
elseif(strcmpi(steeringMethod,'eights'))
%eight pointing in right direction
out(1,:) = weights1.' * sigVecEight;%found pattern, will be overwritten
%with binary masked signal
%weighted addition of eight and sphere to result in desired pattern
out(1,:) = weightSphere*out(3,:) + (1-weightSphere)*out(1,:);
out(2,:) = out(1,:);%found pattern, will not be overwritten
else
error(['unknown steering method: ' steeringMethod]);
end
% Apply binary mask to pattern 1
%TODO in evaluation mode, the given mask is not applied to signal properly
%instead a new mask based on the evaluation signal is calculated
if (options.Mask)
newMask = admaMask(options.mask_angle,sigVecProc,weights1,freqVec);
if (options.oldMask ~= -1)
newMask = options.mask_update * newMask...
+ (1-options.mask_update) * options.oldMask;
end
out(1,:) = newMask .* out(1,:);
options.newMask = newMask;
else
options.newMask = -1;
end
options.theta1 = theta1;
options.theta2 = theta2;
end
end %end of function
%-----------------------------------------------------------------------
%| Function: bandpass
%-----------------------------------------------------------------------
%| Limits the freqVec and sigVec to a frequency band.
%|
%| Author: Patrick Michelson
%| Version: 0.1
%| Date: 08.10.2012
%| Library: Helper
%|
%----------------------------------------------------------------------
function [ freqVec sigVec ] = bandpass(lbound, ubound, Fs, freqVec, sigVec)
%calculate indices of boundries
lidx = floor(lbound/Fs*2*(size(freqVec,2)-1)+1); %index of lower bound
uidx = ceil( ubound/Fs*2*(size(freqVec,2)-1)+1); %index of upper bound
if (lidx == 1)
lidx=2; %delete freq=0 in any case
end
if (ndims(sigVec)==2)
sigVec(:,1:lidx-1) = zeros(size(sigVec(:,1:lidx-1)));
sigVec(:,uidx:size(sigVec,2))...
= zeros(size(sigVec(:,uidx:size(sigVec,2))));
elseif (ndims(sigVec)==3)
sigVec(:,:,1:lidx-1) = zeros(size(sigVec(:,:,1:lidx-1)));
sigVec(:,:,uidx:size(sigVec,3))...
= zeros(size(sigVec(:,:,uidx:size(sigVec,3))));
end
end
%% End of file 'adma.m'