forked from gilbertz/GPS_Milemeter_IMU_EKFLocation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
awgn.m
245 lines (205 loc) · 6.68 KB
/
awgn.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
function y=awgn(varargin)
%AWGN Add white Gaussian noise to a signal.
% Y = AWGN(X,SNR) adds white Gaussian noise to X. The SNR is in dB.
% The power of X is assumed to be 0 dBW. If X is complex, then
% AWGN adds complex noise.
%
% Y = AWGN(X,SNR,SIGPOWER) when SIGPOWER is numeric, it represents
% the signal power in dBW. When SIGPOWER is 'measured', AWGN measures
% the signal power before adding noise.
%
% Y = AWGN(X,SNR,SIGPOWER,STATE) resets the state of RANDN to STATE.
%
% Y = AWGN(..., POWERTYPE) specifies the units of SNR and SIGPOWER.
% POWERTYPE can be 'db' or 'linear'. If POWERTYPE is 'db', then SNR
% is measured in dB and SIGPOWER is measured in dBW. If POWERTYPE is
% 'linear', then SNR is measured as a ratio and SIGPOWER is measured
% in Watts.
%
% Example: To specify the power of X to be 0 dBW and add noise to produce
% an SNR of 10dB, use:
% X = sqrt(2)*sin(0:pi/8:6*pi);
% Y = AWGN(X,10,0);
%
% Example: To specify the power of X to be 0 dBW, set RANDN to the 1234th
% state and add noise to produce an SNR of 10dB, use:
% X = sqrt(2)*sin(0:pi/8:6*pi);
% Y = AWGN(X,10,0,1234);
%
% Example: To specify the power of X to be 3 Watts and add noise to
% produce a linear SNR of 4, use:
% X = sqrt(2)*sin(0:pi/8:6*pi);
% Y = AWGN(X,4,3,'linear');
%
% Example: To cause AWGN to measure the power of X, set RANDN to the
% 1234th state and add noise to produce a linear SNR of 4, use:
% X = sqrt(2)*sin(0:pi/8:6*pi);
% Y = AWGN(X,4,'measured',1234,'linear');
%
% See also WGN, RANDN, and BSC.
% Copyright 1996-2007 The MathWorks, Inc.
% $Revision: 1.9.4.4 $ $Date: 2007/10/05 18:33:01 $
% --- Initial checks
error(nargchk(2,5,nargin,'struct'));
% --- Value set indicators (used for the string flags)
pModeSet = 0;
measModeSet = 0;
% --- Set default values
sigPower = 0;
pMode = 'db';
measMode = 'specify';
state = [];
% --- Placeholder for the signature string
sigStr = '';
% --- Identify string and numeric arguments
for n=1:nargin
if(n>1)
sigStr(size(sigStr,2)+1) = '/';
end
% --- Assign the string and numeric flags
if(ischar(varargin{n}))
sigStr(size(sigStr,2)+1) = 's';
elseif(isnumeric(varargin{n}))
sigStr(size(sigStr,2)+1) = 'n';
else
error('comm:awgn:InvalidArg','Only string and numeric arguments are allowed.');
end
end
% --- Identify parameter signatures and assign values to variables
switch sigStr
% --- awgn(x, snr)
case 'n/n'
sig = varargin{1};
reqSNR = varargin{2};
% --- awgn(x, snr, sigPower)
case 'n/n/n'
sig = varargin{1};
reqSNR = varargin{2};
sigPower = varargin{3};
% --- awgn(x, snr, 'measured')
case 'n/n/s'
sig = varargin{1};
reqSNR = varargin{2};
measMode = lower(varargin{3});
measModeSet = 1;
% --- awgn(x, snr, sigPower, state)
case 'n/n/n/n'
sig = varargin{1};
reqSNR = varargin{2};
sigPower = varargin{3};
state = varargin{4};
% --- awgn(x, snr, 'measured', state)
case 'n/n/s/n'
sig = varargin{1};
reqSNR = varargin{2};
measMode = lower(varargin{3});
state = varargin{4};
measModeSet = 1;
% --- awgn(x, snr, sigPower, 'db|linear')
case 'n/n/n/s'
sig = varargin{1};
reqSNR = varargin{2};
sigPower = varargin{3};
pMode = lower(varargin{4});
pModeSet = 1;
% --- awgn(x, snr, 'measured', 'db|linear')
case 'n/n/s/s'
sig = varargin{1};
reqSNR = varargin{2};
measMode = lower(varargin{3});
pMode = lower(varargin{4});
measModeSet = 1;
pModeSet = 1;
% --- awgn(x, snr, sigPower, state, 'db|linear')
case 'n/n/n/n/s'
sig = varargin{1};
reqSNR = varargin{2};
sigPower = varargin{3};
state = varargin{4};
pMode = lower(varargin{5});
pModeSet = 1;
% --- awgn(x, snr, 'measured', state, 'db|linear')
case 'n/n/s/n/s'
sig = varargin{1};
reqSNR = varargin{2};
measMode = lower(varargin{3});
state = varargin{4};
pMode = lower(varargin{5});
measModeSet = 1;
pModeSet = 1;
otherwise
error('comm:awgn:InvalidSyntax','Syntax error.');
end
% --- Parameters have all been set, either to their defaults or by the values passed in,
% so perform range and type checks
% --- sig
if(isempty(sig))
error('comm:awgn:NoInput','An input signal must be given.');
end
if(ndims(sig)>2)
error('comm:awgn:InvalidSignalDims','The input signal must have 2 or fewer dimensions.');
end
% --- measMode
if(measModeSet)
if(~strcmp(measMode,'measured'))
error('comm:awgn:InvalidSigPower','The signal power parameter must be numeric or ''measured''.');
end
end
% --- pMode
if(pModeSet)
switch pMode
case {'db' 'linear'}
otherwise
error('comm:awgn:InvalidPowerType','The signal power mode must be ''db'' or ''linear''.');
end
end
% -- reqSNR
if(any([~isreal(reqSNR) (length(reqSNR)>1) (isempty(reqSNR))]))
error('comm:awgn:InvalidSNR','The signal-to-noise ratio must be a real scalar.');
end
if(strcmp(pMode,'linear'))
if(reqSNR<=0)
error('comm:awgn:InvalidSNRForLinearMode','In linear mode, the signal-to-noise ratio must be > 0.');
end
end
% --- sigPower
if(~strcmp(measMode,'measured'))
% --- If measMode is not 'measured', then the signal power must be specified
if(any([~isreal(sigPower) (length(sigPower)>1) (isempty(sigPower))]))
error('comm:awgn:InvalidSigPower','The signal power value must be a real scalar.');
end
if(strcmp(pMode,'linear'))
if(sigPower<0)
error('comm:awgn:InvalidSigPowerForLinearMode','In linear mode, the signal power must be >= 0.');
end
end
end
% --- state
if(~isempty(state))
if(any([~isreal(state) (length(state)>1) (isempty(state)) any((state-floor(state))~=0)]))
error('comm:awgn:InvaildState','The State must be a real, integer scalar.');
end
end
% --- All parameters are valid, so no extra checking is required
% --- Check the signal power. This needs to consider power measurements on matrices
if(strcmp(measMode,'measured'))
sigPower = sum(abs(sig(:)).^2)/length(sig(:));
if(strcmp(pMode,'db'))
sigPower = 10*log10(sigPower);
end
end
% --- Compute the required noise power
switch lower(pMode)
case 'linear'
noisePower = sigPower/reqSNR;
case 'db'
noisePower = sigPower-reqSNR;
pMode = 'dbw';
end
% --- Add the noise
if(isreal(sig))
opType = 'real';
else
opType = 'complex';
end
y = sig+wgn(size(sig,1), size(sig,2), noisePower, 1, state, pMode, opType);