1
+ % x = generate_observation_SNR_controlled(noise,signal,fs,fsig,time_of_arrival,SNR)
2
+ %
3
+ % This fonction can be used to generate an observation with a controlled
4
+ % SNR, following this definition SNR = 10*log10(signal_power/noise_power)
5
+ % with x_power = x_energy/length(x). This fonction is build for tonals.
6
+ % Therefore, the energy term is relative to the energy in the signal's
7
+ % frequency band, define by fsig = [fmin fmax]. The noise energy is
8
+ % measured at each time_of_arrival value for the duration of the signal,
9
+ % and the signal's amplitude is ajusted by the variable coef to satisfy the
10
+ % imposed SNR. This function is based on the method proposed (Mellinger &
11
+ % Clark 2006, see Mobysound website: http://www.mobysound.org/software.html)
12
+ %
13
+ % INPUTS:
14
+ % - noise, noise vector where the signal is going to be injected
15
+ % with a controlled SNR, sampled at fs;
16
+ % - signal, the signal that is going to be injected at each time_of_arrival
17
+ % sampled at fs;
18
+ % - fs, the sampling frequency (Hz);
19
+ % - fsig, fsig = [fmin fmax], the signal's frequency band;
20
+ % - time_of_arrival, time vector containig the starting time where
21
+ % signals will be injected;
22
+ % - SNR, imposed Signal to Noise Ratio (dB);
23
+ %
24
+ % OUTPUT:
25
+ % - x, temporal observation vector of a mixture of signal and noise at
26
+ % the required SNR
27
+ % - real_SNR (optional), double-checked SNR value according
28
+
29
+
30
+ function [x ,real_SNR ] = generate_observation_SNR_controlled(noise ,signal ,fs ,fsig ,time_of_arrival ,SNR )
31
+ % pre-processing of the data
32
+ noise = noise - mean(noise ); % so the noise is centered
33
+ signal = signal - mean(signal ); signal = signal / max(abs(signal )); % the signal is normalized
34
+
35
+ %% Signal and noise mixture
36
+ % Initialize the received signal with the noise
37
+ received_signal = noise ;
38
+
39
+ % We want to measure the exact noise power at the TOA where we're going to
40
+ % inject the signal, to adjust its power and have the required SNR.
41
+ N = length(signal );
42
+ N_2 = 2 .^ nextpow2(N );
43
+
44
+ % Frequency indexes corresponding to fmin and fmax of the simulated Z-call
45
+ % +/- 1 Hz (upper and lower)
46
+ i0 = round((fsig(1 )-1 )/(fs / 2 )*N_2 / 2 ) + 1 ; % index for lower freq bound
47
+ i1 = round((fsig(2 )+1 )/(fs / 2 )*N_2 / 2 ) + 1 ; % ...and upper
48
+
49
+ % Signal Energy
50
+ Ref_Signal_energy = energy_measurement(signal ,[i0 i1 ],[N N_2 ]);
51
+
52
+ % Initialize
53
+ real_SNR = [];
54
+ % For each emission
55
+ for emmission_number = 1 : length(time_of_arrival )
56
+
57
+ % Sample where we'll start injecting the call
58
+ arrival_sample = round(time_of_arrival(emmission_number )*fs );
59
+ % Noise cut from the arrival sample and for the duration of the call
60
+ noise_short = received_signal(arrival_sample : arrival_sample + N - 1 );
61
+ % Calculation of noise_short power in the bandwidth of the Z-call
62
+ Noise_energy = energy_measurement(noise_short ,[i0 i1 ],[N N_2 ]);
63
+ % Calculation of the coefficient that will be used to set signal at
64
+ % the right amplitude
65
+ Signal_wanted_energy = Noise_energy * 10 ^(SNR / 10 ) - Noise_energy ;
66
+ coef = sqrt(Signal_wanted_energy / Ref_Signal_energy );
67
+
68
+ % Received signal
69
+ received_signal(arrival_sample : arrival_sample + N - 1 ) = received_signal(arrival_sample : arrival_sample + N - 1 ) + coef * signal ;
70
+
71
+ if nargout == 2
72
+ % SNR (to verify)
73
+ Observation_energy = energy_measurement(received_signal(arrival_sample : arrival_sample + N - 1 ),[i0 i1 ],[N N_2 ]);
74
+ real_SNR = [real_SNR 10 * log10(Observation_energy / Noise_energy )];
75
+ end
76
+
77
+ end
78
+ % Returned built simulated signal
79
+ x = received_signal ;
80
+ x = x - mean(x ); x = x / max(x );
81
+
82
+ function energy = energy_measurement(x ,I ,NN )
83
+ pad = [x zeros(1 , NN(2 )-NN(1 ))]; % zero-pad to power-of-2 length
84
+ FT = abs(fft(pad ));
85
+ energy = (1 / NN(2 )) * sum(FT(I(1 ): I(2 )).^2 )/NN(1 );
0 commit comments