00001 00034 #include <itpp/comm/channel.h> 00035 #include <itpp/base/stat.h> 00036 #include <itpp/base/specmat.h> 00037 #include <itpp/base/transforms.h> 00038 #include <itpp/base/bessel.h> 00039 #include <itpp/base/window.h> 00040 00041 00042 namespace itpp { 00043 00044 vec jake_filter(double NormFDopp, int order) 00045 { 00046 int i, L = (int)std::floor(double(order)/2); 00047 double t, x0; 00048 vec x_pos(L), x_neg(L), x(2*L+1), h(2*L+1); 00049 for (i=1; i<L+1; i++) { 00050 t = double(i); 00051 x_pos(i-1) = besselj(0.25, 2*pi*NormFDopp*t) / std::sqrt(std::sqrt(t)); 00052 } 00053 x0 = double(1.468813) * std::sqrt(std::sqrt(NormFDopp)); 00054 x_neg = reverse(x_pos); 00055 x = concat( concat(x_neg, x0), x_pos); 00056 h = elem_mult(hamming(2*L+1), x); 00057 h /= norm(h); 00058 return h; 00059 } 00060 00061 00062 00063 // ------------------------------------------------------------------------------------------------------------------ 00064 Fading_Generator::Fading_Generator(const double norm_doppler, const DOPPLER_SPECTRUM spectrum) 00065 { 00066 set_norm_doppler(norm_doppler); 00067 set_doppler_spectrum(spectrum); 00068 los_power = 0.0; // no LOS component 00069 los_dopp = 0.0; 00070 } 00071 00072 void Fading_Generator::set_norm_doppler(const double norm_doppler) 00073 { 00074 it_assert((norm_doppler >= 0) && (norm_doppler < 1.0), "Fading_Generator: Normalized Doppler must be >= 0 and < 1."); 00075 n_dopp = norm_doppler; 00076 init_flag = false; 00077 } 00078 00079 void Fading_Generator::set_doppler_spectrum(const DOPPLER_SPECTRUM spectrum) 00080 { 00081 dopp_spectrum = spectrum; 00082 if (spectrum != Rice) { // no LOS component 00083 los_power = 0.0; 00084 los_dopp = 0.0; 00085 } 00086 init_flag = false; 00087 } 00088 00089 void Fading_Generator::set_LOS(const double relative_power, const double relative_doppler) 00090 { 00091 it_assert((relative_doppler >= 0) && (relative_doppler <= 1.0), "Relative Doppler must be >=0 and <=1."); 00092 it_assert(relative_power >= 0.0, "Rice factor need to be >= 0.0"); 00093 it_assert(dopp_spectrum == Rice, "Can only set LOS component if Rice spectrum"); 00094 los_power = relative_power; 00095 los_dopp = relative_doppler; 00096 init_flag = false; 00097 } 00098 00099 cvec Fading_Generator::generate(const int no_samples) 00100 { 00101 cvec output; 00102 this->generate(no_samples, output); 00103 return output; 00104 } 00105 00106 cvec Fading_Generator::generate(const int no_samples, const int upsampling_factor) 00107 { 00108 cvec output; 00109 this->generate(no_samples, upsampling_factor, output); 00110 return output; 00111 } 00112 00113 void Fading_Generator::shift_time_offset(const int no_samples) 00114 { 00115 time_offset += no_samples; 00116 } 00117 00118 void Fading_Generator::generate_zero_doppler(const int no_samples, cvec &output) 00119 { 00120 output = randn_c(no_samples); 00121 if(los_power > 0.0) { 00122 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00123 double direct = diffuse*std::sqrt(los_power); 00124 for (int i=0; i<no_samples; i++) 00125 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i+time_offset))); 00126 } 00127 time_offset += no_samples; 00128 } 00129 00130 void Fading_Generator::generate_zero_doppler(const int no_samples, const int upsampling_factor, cvec &output) 00131 { 00132 output = randn_c(no_samples); 00133 if (los_power > 0.0) { 00134 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00135 double direct = diffuse*std::sqrt(los_power); 00136 for (int i=0; i<no_samples; i++) 00137 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i*upsampling_factor+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i*upsampling_factor+time_offset))); 00138 } 00139 time_offset += no_samples * upsampling_factor; 00140 } 00141 00142 00143 // ------------------------------------------------------------------------------------------------------------------ 00144 Rice_Fading_Generator::Rice_Fading_Generator(const double norm_doppler, const DOPPLER_SPECTRUM spectrum, const int no_freq, const RICE_METHOD method) 00145 : Fading_Generator(norm_doppler, spectrum) 00146 { 00147 set_no_frequencies(no_freq); 00148 set_method(method); 00149 } 00150 00151 void Rice_Fading_Generator::set_no_frequencies(const int no_freq) 00152 { 00153 it_assert(no_freq >= 7, "Rice_Fading_Generator: number of doppler frequencies should be at least 7"); 00154 Ni = no_freq; 00155 init_flag = false; 00156 } 00157 00158 void Rice_Fading_Generator::set_method(const RICE_METHOD method) 00159 { 00160 // check if this method works for the given spectrum 00161 rice_method = method; 00162 init_flag = false; 00163 } 00164 00165 int Rice_Fading_Generator::get_no_frequencies() 00166 { 00167 return Ni; 00168 } 00169 00170 RICE_METHOD Rice_Fading_Generator::get_method() 00171 { 00172 return rice_method; 00173 } 00174 00175 void Rice_Fading_Generator::init() 00176 { 00177 switch(rice_method) { 00178 case MEDS: // Method of Exact Doppler Spread (MEDS) 00179 init_MEDS(); 00180 break; 00181 00182 default: 00183 it_error("Rice_Fading_Generator: this method is not implemented"); 00184 }; 00185 00186 time_offset = 0; // state in the process 00187 init_flag = true; // generator ready to use 00188 } 00189 00190 void Rice_Fading_Generator::set_time_offset(const int offset) 00191 { 00192 it_assert(offset >= 0, "Rice_Fading_Generator: time offset need to be >=0"); 00193 time_offset = offset; 00194 } 00195 00196 double Rice_Fading_Generator::get_time_offset() 00197 { 00198 return time_offset; 00199 } 00200 00201 void Rice_Fading_Generator::generate(const int no_samples, cvec &output) 00202 { 00203 if (init_flag == false) 00204 init(); 00205 00206 if (n_dopp == 0.0) 00207 generate_zero_doppler(no_samples, output); 00208 else { 00209 output.set_size(no_samples, false); 00210 00211 for (int i=0; i<no_samples; i++) { 00212 output(i) = std::complex<double>( sum( elem_mult( c1, cos(2*pi*f1*n_dopp*(i+time_offset)+th1) ) ), 00213 sum( elem_mult( c2, cos(2*pi*f2*n_dopp*(i+time_offset)+th2) ) ) ); 00214 } 00215 00216 if(los_power > 0.0) { // LOS component exist 00217 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00218 double direct = diffuse*std::sqrt(los_power); 00219 for (int i=0; i<no_samples; i++) 00220 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i+time_offset))); 00221 } 00222 time_offset += no_samples; 00223 } 00224 } 00225 00226 00227 void Rice_Fading_Generator::generate(const int no_samples, const int upsampling_factor, cvec &output) 00228 { 00229 if (init_flag == false) 00230 init(); 00231 00232 if (n_dopp == 0.0) { 00233 generate_zero_doppler(no_samples, upsampling_factor, output); 00234 } 00235 else { 00236 output.set_size(no_samples, false); 00237 00238 for (int i=0; i<no_samples; i++) { 00239 output(i) = std::complex<double>( sum( elem_mult( c1, cos(2*pi*f1*n_dopp*(i*upsampling_factor+time_offset)+th1) ) ), 00240 sum( elem_mult( c2, cos(2*pi*f2*n_dopp*(i*upsampling_factor+time_offset)+th2) ) ) ); 00241 } 00242 00243 if(los_power > 0.0) { // LOS component exist 00244 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00245 double direct = diffuse*std::sqrt(los_power); 00246 for (int i=0; i<no_samples; i++) 00247 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i*upsampling_factor+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i*upsampling_factor+time_offset))); 00248 } 00249 time_offset += no_samples * upsampling_factor; 00250 } 00251 } 00252 00253 00254 void Rice_Fading_Generator::init_MEDS() 00255 { 00256 vec n; 00257 00258 switch(dopp_spectrum) { 00259 case Jakes: // Jakes (Clark) spectrum 00260 case Rice: // Rice also have a Jakes spectrum component 00261 n = linspace(1,Ni,Ni); 00262 f1 = sin(pi/(2*Ni)*(n-0.5)); 00263 c1 = std::sqrt(1.0/Ni)*ones(Ni); 00264 th1 = randu(Ni)*2*pi; 00265 00266 n = linspace(1,Ni+1,Ni+1); 00267 f2 = sin(pi/(2*(Ni+1))*(n-0.5)); 00268 c2 = std::sqrt(1.0/(Ni+1))*ones(Ni+1); 00269 th2 = randu(Ni+1)*2*pi; 00270 break; 00271 00272 default: 00273 it_error("Rice_Fading_Generator: this spectrum is not implemented for the MEDS Rice fading generator"); 00274 }; 00275 } 00276 00277 00278 // ------------------------------------------------------------------------------------------------------------------ 00279 00280 FIR_Fading_Generator::FIR_Fading_Generator(const double norm_doppler, const DOPPLER_SPECTRUM spectrum, const int filter_length) 00281 : Fading_Generator(norm_doppler, spectrum) 00282 { 00283 set_filter_length(filter_length); 00284 } 00285 00286 00287 void FIR_Fading_Generator::set_filter_length(const int filter_length) 00288 { 00289 it_assert(filter_length >= 50, "FIR_Fading_Generator: filter length should be at least 50"); 00290 fir_length = filter_length; 00291 init_flag = false; 00292 } 00293 00294 int FIR_Fading_Generator::get_filter_length() 00295 { 00296 return fir_length; 00297 } 00298 00299 void FIR_Fading_Generator::init() 00300 { 00301 double norm_dopp = n_dopp; 00302 if (n_dopp > 0.0) { 00303 switch(dopp_spectrum) { 00304 case Jakes: 00305 case Rice: // Rice also has a Jakes spectrum component 00306 upsample_rate = 1; // upsampling rate 00307 while (norm_dopp < 0.1) { // calculate a reasonable upsample rate so that normalized doppler is > 0.1 00308 norm_dopp *= 2; 00309 upsample_rate *= 2; 00310 } 00311 fir_filter.set_coeffs(jake_filter(norm_dopp, fir_length)); 00312 break; 00313 00314 default: 00315 it_error("FIR_Fading_Generator: doppler spectrum is not implemented"); 00316 }; 00317 00318 // fill filter with dummy data 00319 cvec dummy = fir_filter(randn_c(fir_length)); 00320 00321 left_overs.set_size(0, false); 00322 } 00323 init_flag = true; // generator ready to use 00324 } 00325 00326 void FIR_Fading_Generator::generate(const int no_samples, cvec &output) 00327 { 00328 if (init_flag == false) 00329 init(); 00330 00331 if (n_dopp == 0.0) 00332 generate_zero_doppler(no_samples, output); 00333 else { 00334 int no_upsamples = ceil_i(double(no_samples-left_overs.size())/double(upsample_rate)) + 1; // calculate number of samples before upsampling 00335 00336 // should make a smarter interpolation here!!! 00337 lininterp(fir_filter(randn_c(no_upsamples)), upsample_rate, output); 00338 output = concat(left_overs, output); // add left-overs from previous filtering 00339 left_overs = output.right(output.size()-no_samples); // save left-overs for next round of filtering 00340 output.set_size(no_samples, true); 00341 00342 if(los_power > 0.0) { // LOS component exist 00343 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00344 double direct = diffuse*std::sqrt(los_power); 00345 for (int i=0; i<no_samples; i++) 00346 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i+time_offset))); 00347 } 00348 time_offset += no_samples; 00349 } 00350 } 00351 00352 00354 void FIR_Fading_Generator::generate(const int no_samples, const int upsampling_factor, cvec &output) 00355 { 00356 this->generate(no_samples, output); 00357 } 00358 00359 00360 // ------------------------------------------------------------------------------------------------------------------ 00361 IFFT_Fading_Generator::IFFT_Fading_Generator(const double norm_doppler, const DOPPLER_SPECTRUM spectrum) 00362 : Fading_Generator(norm_doppler, spectrum) { } 00363 00364 00365 void IFFT_Fading_Generator::init() 00366 { 00367 init_flag = true; // generator ready to use 00368 } 00369 00370 00371 void IFFT_Fading_Generator::generate(const int no_samples, cvec &output) 00372 { 00373 if (init_flag == false) 00374 init(); 00375 00376 if (n_dopp == 0.0) 00377 generate_zero_doppler(no_samples, output); 00378 else { 00379 switch(dopp_spectrum) { 00380 00381 case Jakes: 00382 case Rice: // Rice also has a Jakes spectrum component 00383 generate_Jakes(no_samples, output); 00384 break; 00385 default: 00386 it_error("IFFT_Fading_Generator: doppler spectrum is not implemented"); 00387 }; 00388 00389 if(los_power > 0.0) { // LOS component exist 00390 double diffuse = std::sqrt(1.0/(1.0+los_power)); 00391 double direct = diffuse*std::sqrt(los_power); 00392 for (int i=0; i<no_samples; i++) 00393 output(i) = diffuse*output(i) + direct*std::complex<double>(std::cos(2*pi*los_dopp*n_dopp*(i+time_offset)),std::sin(2*pi*los_dopp*n_dopp*(i+time_offset))); 00394 } 00395 time_offset += no_samples; 00396 } 00397 } 00398 00399 // Is this really correct??? 00400 void IFFT_Fading_Generator::generate(const int no_samples, const int upsampling_factor, cvec &output) 00401 { 00402 this->generate(no_samples, output); 00403 } 00404 00405 00406 void IFFT_Fading_Generator::generate_Jakes(const int no_samples, cvec &output) 00407 { 00408 int Nfft = pow2i(levels2bits(no_samples)); 00409 double df = 1.0/Nfft; 00410 int noisesamp = (int)std::ceil(n_dopp/df); 00411 int no_upsample = 1; 00412 00413 while (noisesamp <= 10) { // if too few samples, increase the FFT size 00414 Nfft *= 2; 00415 no_upsample *= 2; 00416 df = 1.0/double(Nfft); 00417 noisesamp = (int)std::ceil(n_dopp/df); 00418 it_assert(no_upsample < 128, "IFFT_Fading_Generator: Too low normalized doppler or too small blocks of data. Results in inefficient algorithm with lots of zero-padding"); 00419 } 00420 00421 00422 vec Fpos = linspace(0,0.5,Nfft/2+1); 00423 vec F = concat(Fpos, reverse(-Fpos(1,Nfft/2-1))); 00424 vec S = zeros(Nfft); 00425 00426 for (int i=0; i<F.size(); i++) { 00427 if (std::abs(F(i)) < n_dopp) 00428 S(i) = std::sqrt(1.5 / ( pi*n_dopp*std::sqrt(1-std::pow(F(i)/n_dopp,2)))); 00429 else if (std::abs(F(i)) == n_dopp) 00430 S(i) = 1000000; 00431 } 00432 00433 S /= norm(S,2); S *= Nfft; 00434 00435 cvec x(Nfft); 00436 00437 // lots of zeros. Not necessary to do the multiplication for all elements!!! 00438 // S is converted. Not necessary??? 00439 x = ifft( elem_mult(to_cvec(S), concat(randn_c(noisesamp), zeros_c(Nfft-2*noisesamp), randn_c(noisesamp)) ) ); 00440 output = x.mid(0, no_samples); 00441 } 00442 00443 // ------------------------------------------------------------------------------------------------------------------ 00444 Channel_Specification::Channel_Specification(const vec &avg_power_dB, const vec &delay_prof) 00445 { 00446 set_channel_profile(avg_power_dB, delay_prof); 00447 } 00448 00449 Channel_Specification::Channel_Specification(const CHANNEL_PROFILE profile) 00450 { 00451 set_channel_profile(profile); 00452 } 00453 00454 void Channel_Specification::set_channel_profile(const vec &avg_power_dB, const vec &delay_prof) 00455 { 00456 it_assert(min(delay_prof) == 0, "Minimum relative delay must be 0."); 00457 it_assert(avg_power_dB.size() == delay_prof.size(), "Power and delay vectors must be of equal length!"); 00458 it_assert(delay_prof(0) == 0, "First tap must be at zero delay"); 00459 00460 00461 N_taps = delay_prof.size(); 00462 // taps should be sorted and unique 00463 for (int i=1; i<N_taps; i++) { 00464 it_assert(delay_prof(i) > delay_prof(i-1), "Delays should be sorted and unique"); 00465 } 00466 00467 a_prof_dB = avg_power_dB; 00468 d_prof = delay_prof; 00469 00470 // set doppler spectrum to Jakes per default 00471 tap_doppler_spectrum.set_size(N_taps, false); 00472 for (int i=0; i<N_taps; i++) 00473 tap_doppler_spectrum(i) = Jakes; 00474 00475 discrete = false; 00476 } 00477 00478 void Channel_Specification::set_channel_profile(const CHANNEL_PROFILE profile) 00479 { 00480 switch (profile) { 00481 // -------------- ITU Channel models ----------------- 00482 case ITU_Vehicular_A: 00483 set_channel_profile(vec("0 -1 -9 -10 -15 -20"), 00484 vec("0 310 710 1090 1730 2510") * 1e-9); 00485 break; 00486 00487 case ITU_Vehicular_B: 00488 set_channel_profile(vec("-2.5 0 -12.8 -10 -25.2 -16"), 00489 vec("0 300 8900 12900 17100 20000") * 1e-9); 00490 break; 00491 00492 case ITU_Pedestrian_A: 00493 set_channel_profile(vec("0 -9.7 -19.2 -22.8"), 00494 vec("0 110 190 410") * 1e-9); 00495 break; 00496 00497 case ITU_Pedestrian_B: 00498 set_channel_profile(vec("0 -0.9 -4.9 -8 -7.8 -23.9"), 00499 vec("0 200 800 1200 2300 3700") * 1e-9); 00500 break; 00501 00502 // -------------- COST259 Channel models ----------------- 00503 case COST259_TUx: 00504 set_channel_profile(vec("-5.7 -7.6 -10.1 -10.2 -10.2 -11.5 -13.4 -16.3 -16.9 -17.1 -17.4 -19 -19 -19.8 -21.5 -21.6 -22.1 -22.6 -23.5 -24.3"), 00505 vec("0 217 512 514 517 674 882 1230 1287 1311 1349 1533 1535 1622 1818 1836 1884 1943 2048 2140") * 1e-9); 00506 break; 00507 00508 case COST259_RAx: 00509 set_channel_profile(vec("-5.2 -6.4 -8.4 -9.3 -10 -13.1 -15.3 -18.5 -20.4 -22.4"), 00510 vec("0 42 101 129 149 245 312 410 469 528") * 1e-9); 00511 set_doppler_spectrum(0, Rice); 00512 set_LOS( sqr(0.91/0.41), 0.7); // What should the rice factor be??? Not sure from report! 00513 break; 00514 00515 case COST259_HTx: 00516 set_channel_profile(vec("-3.6 -8.9 -10.2 -11.5 -11.8 -12.7 -13.0 -16.2 -17.3 -17.7 -17.6 -22.7 -24.1 -25.8 -25.8 -26.2 -29 -29.9 -30 -30.7"), 00517 vec("0 356 441 528 546 609 625 842 916 941 15000 16172 16492 16876 16882 16978 17615 17827 17849 18016") * 1e-9); 00518 break; 00519 00520 // -------------- COST207 Channel models ----------------- 00521 case COST207_RA: 00522 set_channel_profile(vec("0 -2 -10 -20"), 00523 vec("0 200 400 600") * 1e-9); 00524 set_doppler_spectrum(0, Rice); 00525 set_LOS( sqr(0.91/0.41), 0.7); 00526 break; 00527 00528 case COST207_RA6: 00529 set_channel_profile(vec("0 -4 -8 -12 -16 -20"), 00530 vec("0 100 200 300 400 500") * 1e-9); 00531 set_doppler_spectrum(0, Rice); 00532 set_LOS( sqr(0.91/0.41), 0.7); 00533 break; 00534 00535 case COST207_TU: 00536 set_channel_profile(vec("-3 0 -2 -6 -8 -10"), 00537 vec("0 200 600 1600 2400 5000") * 1e-9); 00538 set_doppler_spectrum(2, GaussI); 00539 set_doppler_spectrum(3, GaussI); 00540 set_doppler_spectrum(4, GaussII); 00541 set_doppler_spectrum(5, GaussII); 00542 break; 00543 00544 case COST207_TU6alt: 00545 set_channel_profile(vec("-3 0 -2 -6 -8 -10"), 00546 vec("0 200 500 1600 2300 5000") * 1e-9); 00547 set_doppler_spectrum(3, GaussI); 00548 set_doppler_spectrum(4, GaussII); 00549 set_doppler_spectrum(5, GaussII); 00550 break; 00551 00552 case COST207_TU12: 00553 set_channel_profile(vec("-4 -3 0 -2 -3 -5 -7 -5 -6 -9 -11 -10"), 00554 vec("0 200 400 600 800 1200 1400 1800 2400 3000 3200 5000") * 1e-9); 00555 set_doppler_spectrum(3, GaussI); 00556 set_doppler_spectrum(4, GaussI); 00557 set_doppler_spectrum(5, GaussI); 00558 set_doppler_spectrum(6, GaussI); 00559 set_doppler_spectrum(7, GaussI); 00560 set_doppler_spectrum(8, GaussII); 00561 set_doppler_spectrum(9, GaussII); 00562 set_doppler_spectrum(10, GaussII); 00563 set_doppler_spectrum(11, GaussII); 00564 break; 00565 00566 case COST207_TU12alt: 00567 set_channel_profile(vec("-4 -3 0 -2.6 -3 -5 -7 -5 -6.5 -8.6 -11 -10"), 00568 vec("0 200 400 600 800 1200 1400 1800 2400 3000 3200 5000") * 1e-9); 00569 set_doppler_spectrum(4, GaussI); 00570 set_doppler_spectrum(5, GaussI); 00571 set_doppler_spectrum(6, GaussI); 00572 set_doppler_spectrum(7, GaussI); 00573 set_doppler_spectrum(8, GaussII); 00574 set_doppler_spectrum(9, GaussII); 00575 set_doppler_spectrum(10, GaussII); 00576 set_doppler_spectrum(11, GaussII); 00577 break; 00578 00579 case COST207_BU: 00580 set_channel_profile(vec("-3 0 -3 -5 -2 -4"), 00581 vec("0 400 1000 1600 5000 6600") * 1e-9); 00582 set_doppler_spectrum(2, GaussI); 00583 set_doppler_spectrum(3, GaussI); 00584 set_doppler_spectrum(4, GaussII); 00585 set_doppler_spectrum(5, GaussII); 00586 break; 00587 00588 case COST207_BU6alt: 00589 set_channel_profile(vec("-2.5 0 -3 -5 -2 -4"), 00590 vec("0 300 1000 1600 5000 6600") * 1e-9); 00591 set_doppler_spectrum(2, GaussI); 00592 set_doppler_spectrum(3, GaussI); 00593 set_doppler_spectrum(4, GaussII); 00594 set_doppler_spectrum(5, GaussII); 00595 break; 00596 00597 case COST207_BU12: 00598 set_channel_profile(vec("-7 -3 -1 0 -2 -6 -7 -1 -2 -7 -10 -15"), 00599 vec("0 200 400 800 1600 2200 3200 5000 6000 7200 8200 10000") * 1e-9); 00600 set_doppler_spectrum(3, GaussI); 00601 set_doppler_spectrum(4, GaussI); 00602 set_doppler_spectrum(5, GaussII); 00603 set_doppler_spectrum(6, GaussII); 00604 set_doppler_spectrum(7, GaussII); 00605 set_doppler_spectrum(8, GaussII); 00606 set_doppler_spectrum(9, GaussII); 00607 set_doppler_spectrum(10, GaussII); 00608 set_doppler_spectrum(11, GaussII); 00609 break; 00610 00611 case COST207_BU12alt: 00612 set_channel_profile(vec("-7.7 -3.4 -1.3 0 -2.3 -5.6 -7.4 -1.4 -1.6 -6.7 -9.8 -15.1"), 00613 vec("0 100 300 700 1600 2200 3100 5000 6000 7200 8100 10000") * 1e-9); 00614 set_doppler_spectrum(3, GaussI); 00615 set_doppler_spectrum(4, GaussI); 00616 set_doppler_spectrum(5, GaussII); 00617 set_doppler_spectrum(6, GaussII); 00618 set_doppler_spectrum(7, GaussII); 00619 set_doppler_spectrum(8, GaussII); 00620 set_doppler_spectrum(9, GaussII); 00621 set_doppler_spectrum(10, GaussII); 00622 set_doppler_spectrum(11, GaussII); 00623 break; 00624 00625 00626 case COST207_HT: 00627 set_channel_profile(vec("0 -2 -4 -7 -6 -12"), 00628 vec("0 200 400 600 15000 17200") * 1e-9); 00629 set_doppler_spectrum(4, GaussII); 00630 set_doppler_spectrum(5, GaussII); 00631 break; 00632 00633 case COST207_HT6alt: 00634 set_channel_profile(vec("0 -1.5 -4.5 -7.5 -8 -17.7"), 00635 vec("0 100 300 500 15000 17200") * 1e-9); 00636 set_doppler_spectrum(4, GaussII); 00637 set_doppler_spectrum(5, GaussII); 00638 break; 00639 00640 case COST207_HT12: 00641 set_channel_profile(vec("-10 -8 -6 -4 0 0 -4 -8 -9 -10 -12 -14"), 00642 vec("0 200 400 600 800 2000 2400 15000 15200 15800 17200 20000") * 1e-9); 00643 set_doppler_spectrum(3, GaussI); 00644 set_doppler_spectrum(4, GaussI); 00645 set_doppler_spectrum(5, GaussI); 00646 set_doppler_spectrum(6, GaussII); 00647 set_doppler_spectrum(7, GaussII); 00648 set_doppler_spectrum(8, GaussII); 00649 set_doppler_spectrum(9, GaussII); 00650 set_doppler_spectrum(10, GaussII); 00651 set_doppler_spectrum(11, GaussII); 00652 break; 00653 00654 case COST207_HT12alt: 00655 set_channel_profile(vec("-10 -8 -6 -4 0 0 -4 -8 -9 -10 -12 -14"), 00656 vec("0 100 300 500 700 1000 1300 15000 15200 15700 17200 20000") * 1e-9); 00657 set_doppler_spectrum(4, GaussI); 00658 set_doppler_spectrum(5, GaussI); 00659 set_doppler_spectrum(6, GaussI); 00660 set_doppler_spectrum(7, GaussII); 00661 set_doppler_spectrum(8, GaussII); 00662 set_doppler_spectrum(9, GaussII); 00663 set_doppler_spectrum(10, GaussII); 00664 set_doppler_spectrum(11, GaussII); 00665 break; 00666 }; 00667 } 00668 00669 00670 void Channel_Specification::set_doppler_spectrum(DOPPLER_SPECTRUM *tap_spectrum) 00671 { 00672 for (int i=0; i<N_taps; i++) 00673 tap_doppler_spectrum(i) = tap_spectrum[i]; 00674 } 00675 00676 void Channel_Specification::set_doppler_spectrum(const int tap_number, DOPPLER_SPECTRUM tap_spectrum) 00677 { 00678 tap_doppler_spectrum(tap_number) = tap_spectrum; 00679 } 00680 00681 void Channel_Specification::set_LOS(const double relative_power, const double norm_doppler) 00682 { 00683 it_assert(N_taps >= 1, "Cannot set LOS component if not set channel profile"); 00684 it_assert((norm_doppler >= 0) && (norm_doppler <= 1.0), "Normalized Doppler must be >=0 and <=1."); 00685 it_assert(relative_power >= 0.0, "Rice factor need to be >= 0.0"); 00686 it_assert(tap_doppler_spectrum(0) == Rice, "Can only set LOS component if Rice spectrum"); 00687 00688 los_power = relative_power; 00689 los_dopp = norm_doppler; 00690 } 00691 00692 void Channel_Specification::get_channel_profile(vec &avg_power_dB, vec &delay_prof) 00693 { 00694 avg_power_dB = a_prof_dB; 00695 delay_prof = d_prof; 00696 } 00697 00698 vec Channel_Specification::get_avg_power_dB() 00699 { 00700 return a_prof_dB; 00701 } 00702 00703 vec Channel_Specification::get_delay_prof() 00704 { 00705 return d_prof; 00706 } 00707 00708 DOPPLER_SPECTRUM Channel_Specification::get_doppler_spectrum(const int index) 00709 { 00710 it_assert((index >= 0) && (index < N_taps), "Channel_Specification: index of of range"); 00711 return tap_doppler_spectrum(index); 00712 } 00713 00714 double Channel_Specification::get_LOS_power() 00715 { 00716 return los_power; 00717 } 00718 00719 double Channel_Specification::get_LOS_doppler() 00720 { 00721 return los_dopp; 00722 } 00723 00724 double Channel_Specification::calc_mean_excess_delay() 00725 { 00726 vec a_prof = inv_dB(a_prof_dB); 00727 vec delay_prof = d_prof; 00728 00729 return ( a_prof*delay_prof / sum(a_prof)); 00730 } 00731 00732 double Channel_Specification::calc_rms_delay_spread() 00733 { 00734 vec a_prof = inv_dB(a_prof_dB); 00735 vec delay_prof = d_prof; 00736 00737 00738 double a = ( a_prof*delay_prof / sum(a_prof)); 00739 double b = ( a_prof*sqr(delay_prof) / sum(a_prof) ); 00740 00741 return ( std::sqrt(b-a*a) ); 00742 } 00743 00744 void Channel_Specification::discretize(const double Ts) 00745 { 00746 it_assert(N_taps > 0, "Channel_Specification::discretize: no channel profile specified"); 00747 vec delay_prof(N_taps); 00748 vec power(N_taps); 00749 Array <DOPPLER_SPECTRUM> tap_spectrum(N_taps); 00750 00751 int j = 0, no_taps, j_delay = 0; 00752 00753 vec a_prof = inv_dB(a_prof_dB); // convert power profile 00754 00755 00756 it_assert(d_prof(0) == 0, "Channel_Specification: first tap should be at zero delay"); 00757 delay_prof(0) = d_prof(0); 00758 power(0) = a_prof(0); 00759 tap_spectrum(0) = tap_doppler_spectrum(0); 00760 00761 // taps within ((j-0.5)Ts,(j+0.5)Ts] are included in the j-th tap 00762 for(int i=1; i<N_taps; i++) { 00763 if( d_prof(i) > (j_delay+0.5)*Ts ) { 00764 while( d_prof(i) > (j_delay+0.5)*Ts ) { j_delay++; } // first skip empty taps 00765 // create a new tap at (j+1)Ts 00766 j++; 00767 delay_prof(j) = j_delay; 00768 power(j) = a_prof(i); 00769 tap_spectrum(j) = tap_doppler_spectrum(i); 00770 } else { 00771 power(j) += a_prof(i); 00772 it_assert((tap_spectrum(j) == tap_doppler_spectrum(i) 00773 || (tap_spectrum(j) == Rice)), 00774 "Channel_Specification::discretize(): Sampling frequency too low. Can not discretize the channel with different Doppler spectra."); 00775 } 00776 } 00777 00778 no_taps = j+1; // number of taps found 00779 if (no_taps != N_taps) { 00780 it_warning("Channel_Specification::discretize(): Sampling frequency too low. The discretized channel profile will have less taps than expected."); 00781 power.set_size(no_taps, true); 00782 delay_prof.set_size(no_taps, true); 00783 N_taps = no_taps; 00784 tap_doppler_spectrum = tap_spectrum; 00785 tap_doppler_spectrum.set_size(no_taps, true); 00786 } 00787 00788 // write over existing channel profile with the discretized version 00789 a_prof_dB = dB(power); 00790 d_prof = delay_prof * Ts; // still store in seconds 00791 00792 discrete = true; 00793 discrete_Ts = Ts; 00794 } 00795 00796 // ------------------------------------------------------------------------------------------------------------------ 00797 TDL_Channel::TDL_Channel(const double norm_doppler, const vec &avg_power_dB, const ivec &delay_prof) 00798 { 00799 set_channel_profile(avg_power_dB, delay_prof); 00800 set_norm_doppler(norm_doppler); 00801 method = Rice_MEDS; // default generation method 00802 } 00803 00804 TDL_Channel::TDL_Channel(Channel_Specification &channel_spec) 00805 { 00806 set_channel_profile(channel_spec); 00807 set_norm_doppler(0.0); // initially set to 0 doppler. 00808 00809 // set doppler spectrum 00810 tap_doppler_spectrum.set_size(N_taps, false); 00811 for (int i=0; i<N_taps; i++) { 00812 tap_doppler_spectrum(i) = channel_spec.get_doppler_spectrum(i); 00813 } 00814 00815 if (tap_doppler_spectrum(0) == Rice) // set LOS component 00816 set_LOS(channel_spec.get_LOS_power(), channel_spec.get_LOS_doppler()); 00817 00818 method = Rice_MEDS; // default generation method 00819 } 00820 00821 TDL_Channel::~TDL_Channel() 00822 { 00823 if (fading_gen.size() > 0) { // delete all old generators 00824 for (int i = 0; i < fading_gen.size(); i++) { 00825 if (fading_gen(i) != NULL) 00826 delete fading_gen(i); 00827 fading_gen(i) = NULL; 00828 } 00829 } 00830 } 00831 00832 void TDL_Channel::set_channel_profile(const vec &avg_power_dB, const ivec &delay_prof) 00833 { 00834 it_assert(min(delay_prof) == 0, "Minimum relative delay must be 0."); 00835 it_assert(avg_power_dB.size() == delay_prof.size(), "Power and delay vectors must be of equal length!"); 00836 it_assert(delay_prof(0) == 0, "First tap must be at zero delay"); 00837 00838 N_taps = delay_prof.size(); 00839 // taps should be sorted and unique 00840 for (int i=1; i<N_taps; i++) { 00841 it_assert(delay_prof(i) > delay_prof(i-1), "Delays should be sorted and unique"); 00842 } 00843 00844 a_prof = pow(10.0,avg_power_dB/20.0); // Convert power profile to ampiltude profile 00845 a_prof /= norm(a_prof); // Normalize 00846 00847 d_prof = delay_prof; 00848 00849 init_flag = false; 00850 } 00851 00852 void TDL_Channel::set_norm_doppler(const double norm_doppler) 00853 { 00854 it_assert((norm_doppler >= 0) && (norm_doppler <= 1.0), "TDL_Channel: Normalized Doppler must be >=0 and <=1."); 00855 n_dopp = norm_doppler; 00856 init_flag = false; 00857 } 00858 00859 void TDL_Channel::set_channel_profile_uniform(const int no_taps) 00860 { 00861 it_assert(no_taps >= 1, "TDL_Channel::set_channel_profile_uniform(): Minimum number of taps is 1."); 00862 00863 vec avg_power_dB = zeros(no_taps); 00864 ivec delay_prof(no_taps); 00865 00866 for (int i=0; i<no_taps; i++) 00867 delay_prof(i) = i; 00868 00869 set_channel_profile(avg_power_dB, delay_prof); 00870 } 00871 00872 00873 // TODO: implement the exponential channel profile according to: 00874 // p(k*ts) = exp(-k*ts), k = 0...no_taps-1 00875 void TDL_Channel::set_channel_profile_exponential(int no_taps) 00876 { 00877 it_assert(no_taps >= 1, "TDL_Channel::set_channel_profile_exponential(): Minimum number of taps is 1."); 00878 it_error("TDL_Channel::set_channel_profile_exponential(): Not implemented yet"); 00879 } 00880 00881 00882 void TDL_Channel::set_channel_profile(Channel_Specification &channel_spec) 00883 { 00884 vec avg_power_dB; 00885 vec delay_profile; 00886 00887 it_assert(channel_spec.is_discrete() == true, "TDL_Channel: Channel_Specification has not been discretized"); 00888 00889 channel_spec.get_channel_profile(avg_power_dB, delay_profile); 00890 set_channel_profile(avg_power_dB, to_ivec(round(delay_profile/channel_spec.get_discrete_Ts())) ); 00891 } 00892 00893 00894 void TDL_Channel::set_doppler_spectrum(DOPPLER_SPECTRUM *tap_spectrum) 00895 { 00896 it_assert(N_taps > 0, "TDL_Channel:: set_doppler_spectrum: channel profile not defined yet"); 00897 tap_doppler_spectrum.set_size(N_taps, false); 00898 00899 for (int i=0; i<N_taps; i++) 00900 tap_doppler_spectrum(i) = tap_spectrum[i]; 00901 00902 init_flag = false; 00903 } 00904 00905 void TDL_Channel::set_generation_method(const FADING_GENERATION_METHOD generation_method) 00906 { 00907 method = generation_method; 00908 init_flag = false; 00909 } 00910 00911 void TDL_Channel::set_LOS(const double relative_power, const double norm_doppler) 00912 { 00913 it_assert(N_taps >= 1, "Cannot set LOS component if not set channel profile"); 00914 it_assert((norm_doppler >= 0) && (norm_doppler <= 1.0), "Normalized Doppler must be >=0 and <=1."); 00915 it_assert(relative_power >= 0.0, "Rice factor need to be >= 0.0"); 00916 it_assert(tap_doppler_spectrum(0) == Rice, "Can only set LOS component if Rice spectrum"); 00917 00918 los_power = relative_power; 00919 los_dopp = norm_doppler; 00920 init_flag = false; 00921 } 00922 00923 void TDL_Channel::get_channel_profile(vec &avg_power_dB, ivec &delay_prof) 00924 { 00925 avg_power_dB = 20 * log10(a_prof); 00926 delay_prof = d_prof; 00927 } 00928 00929 00930 vec TDL_Channel::get_avg_power_dB() 00931 { 00932 return ( 20 * log10(a_prof) ); 00933 } 00934 00935 ivec TDL_Channel::get_delay_prof() 00936 { 00937 return d_prof; 00938 } 00939 00940 00941 double TDL_Channel::get_norm_doppler() 00942 { 00943 return n_dopp; 00944 } 00945 00946 double TDL_Channel::get_LOS_power() 00947 { 00948 return los_power; 00949 } 00950 00951 double TDL_Channel::get_LOS_doppler() 00952 { 00953 return los_dopp; 00954 } 00955 00956 FADING_GENERATION_METHOD TDL_Channel::get_generation_method() 00957 { 00958 return method; 00959 } 00960 00961 double TDL_Channel::calc_mean_excess_delay() 00962 { 00963 return ( sqr(a_prof)*d_prof / sum_sqr(a_prof)); 00964 } 00965 00966 double TDL_Channel::calc_rms_delay_spread() 00967 { 00968 double a = ( sqr(a_prof)*d_prof / sum_sqr(a_prof)); 00969 double b = ( sqr(a_prof)*sqr(to_vec(d_prof)) / sum_sqr(a_prof) ); 00970 00971 return ( std::sqrt(b-a*a) ); 00972 } 00973 00974 void TDL_Channel::init() 00975 { 00976 it_assert(N_taps > 0, "TDL_Channel:: init: channel profile not defined yet"); 00977 00978 if (fading_gen.size() > 0) { // delete all old generators 00979 for(int i=0; i<fading_gen.size(); i++) 00980 { 00981 if (fading_gen(i) != NULL) 00982 delete fading_gen(i); 00983 00984 fading_gen(i) = NULL; 00985 } 00986 } 00987 00988 fading_gen.set_size(N_taps, false); 00989 00990 if (tap_doppler_spectrum.size() != N_taps) { // doppler-spectrum is not set. Assume Jakes 00991 tap_doppler_spectrum.set_size(N_taps); 00992 for(int i=0; i<N_taps; i++) 00993 tap_doppler_spectrum(i) = Jakes; 00994 } 00995 00996 00997 // create all generators and set the parameters 00998 switch (method) { 00999 case FIR: 01000 for(int i=0; i<N_taps; i++) { fading_gen(i) = new FIR_Fading_Generator(n_dopp, tap_doppler_spectrum(i)); } 01001 break; 01002 01003 case IFFT: 01004 for(int i=0; i<N_taps; i++) { fading_gen(i) = new IFFT_Fading_Generator(n_dopp, tap_doppler_spectrum(i)); } 01005 break; 01006 01007 case Rice_MEDS: 01008 // Ni= smallest number of doppler frequencies, increase by 2 for each tap to make taps uncorrelated 01009 for(int i=0; i<N_taps; i++) { fading_gen(i) = new Rice_Fading_Generator(n_dopp, tap_doppler_spectrum(i), 16+i*2, MEDS); } 01010 break; 01011 01012 default: 01013 it_error("TDL_Channel::init(): Generation method is not implemented"); 01014 }; 01015 01016 if (tap_doppler_spectrum(0) == Rice && los_power > 0.0) { // set LOS component 01017 fading_gen(0)->set_LOS(los_power, los_dopp); 01018 } 01019 01020 // initialize all fading generators 01021 for(int i=0; i<N_taps; i++) 01022 fading_gen(i)->init(); 01023 01024 init_flag = true; 01025 } 01026 01027 void TDL_Channel::generate(const int no_samples, Array<cvec> &channel_coeff) 01028 { 01029 if(init_flag == false) 01030 init(); 01031 01032 channel_coeff.set_size(N_taps, false); 01033 01034 for (int i=0; i<N_taps; i++) 01035 channel_coeff(i) = a_prof(i) * fading_gen(i)->generate(no_samples); 01036 } 01037 01038 void TDL_Channel::generate(const int no_samples, cmat &channel_coeff) 01039 { 01040 if(init_flag == false) 01041 init(); 01042 01043 channel_coeff.set_size(no_samples, N_taps, false); 01044 01045 for (int i=0; i<N_taps; i++) 01046 channel_coeff.set_col(i, a_prof(i) * fading_gen(i)->generate(no_samples)); 01047 } 01048 01049 01050 // no_samples is the actual number of generated samples (with upsampling factor taken into account) 01051 // time_offset will be increased by no_samples*upsampling_factor 01052 void TDL_Channel::generate(const int no_samples, const int upsampling_factor, Array<cvec> &channel_coeff) 01053 { 01054 if(init_flag == false) 01055 init(); 01056 01057 it_assert(method == Rice_MEDS, "TDL_Channel::generate: use with Rice_MEDS generation metod only"); 01058 01059 channel_coeff.set_size(N_taps, false); 01060 01061 for (int i=0; i<N_taps; i++) { 01062 channel_coeff(i) = a_prof(i) * fading_gen(i)->generate(no_samples, upsampling_factor); 01063 } 01064 } 01065 01066 void TDL_Channel::generate(const int no_samples, const int upsampling_factor, cmat &channel_coeff) 01067 { 01068 if(init_flag == false) 01069 init(); 01070 01071 it_assert(method == Rice_MEDS, "TDL_Channel::generate: use with Rice_MEDS generation metod only"); 01072 01073 channel_coeff.set_size(no_samples, N_taps, false); 01074 01075 for (int i=0; i<N_taps; i++) { 01076 channel_coeff.set_col(i, a_prof(i) * fading_gen(i)->generate(no_samples, upsampling_factor)); 01077 } 01078 } 01079 01080 void TDL_Channel::shift_time_offset(const int no_samples) 01081 { 01082 for (int i = 0; i < N_taps; i++) { 01083 fading_gen(i)->shift_time_offset(no_samples); 01084 } 01085 } 01086 01087 01088 void TDL_Channel::filter_known_channel(const cvec &input, cvec &output, const Array<cvec> &channel_coeff) 01089 { 01090 int maxdelay = max(d_prof); 01091 01092 output.set_size(input.size()+maxdelay, false); 01093 output.zeros(); 01094 01095 for (int i=0; i<N_taps; i++) 01096 output += concat( zeros_c(d_prof(i)), elem_mult(input, channel_coeff(i)), zeros_c(maxdelay-d_prof(i)) ); 01097 } 01098 01099 void TDL_Channel::filter_known_channel(const cvec &input, cvec &output, const cmat &channel_coeff) 01100 { 01101 int maxdelay = max(d_prof); 01102 01103 output.set_size(input.size()+maxdelay, false); 01104 output.zeros(); 01105 01106 for (int i=0; i<N_taps; i++) 01107 output += concat( zeros_c(d_prof(i)), elem_mult(input, channel_coeff.get_col(i)), zeros_c(maxdelay-d_prof(i)) ); 01108 } 01109 01110 void TDL_Channel::filter(const cvec &input, cvec &output, Array<cvec> &channel_coeff) 01111 { 01112 generate(input.size(), channel_coeff); 01113 filter_known_channel(input, output, channel_coeff); 01114 } 01115 01116 void TDL_Channel::filter(const cvec &input, cvec &output, cmat &channel_coeff) 01117 { 01118 generate(input.size(), channel_coeff); 01119 filter_known_channel(input, output, channel_coeff); 01120 } 01121 01122 cvec TDL_Channel::filter(const cvec &input, Array<cvec> &channel_coeff) 01123 { 01124 cvec output; 01125 filter(input, output, channel_coeff); 01126 return output; 01127 } 01128 01129 cvec TDL_Channel::filter(const cvec &input, cmat &channel_coeff) 01130 { 01131 cvec output; 01132 filter(input, output, channel_coeff); 01133 return output; 01134 } 01135 01136 void TDL_Channel::filter(const cvec &input, cvec &output) 01137 { 01138 Array<cvec> channel_coeff; 01139 filter(input, output, channel_coeff); 01140 } 01141 01142 cvec TDL_Channel::filter(const cvec &input) 01143 { 01144 cvec output; 01145 filter(input, output); 01146 return output; 01147 } 01148 01149 01150 void TDL_Channel::operator()(const cvec &input, cvec &output, Array<cvec> &channel_coeff) 01151 { 01152 filter(input, output, channel_coeff); 01153 } 01154 01155 void TDL_Channel::operator()(const cvec &input, cvec &output, cmat &channel_coeff) 01156 { 01157 filter(input, output, channel_coeff); 01158 } 01159 01160 01161 cvec TDL_Channel::operator()(const cvec &input, Array<cvec> &channel_coeff) 01162 { 01163 return filter(input, channel_coeff); 01164 } 01165 01166 cvec TDL_Channel::operator()(const cvec &input, cmat &channel_coeff) 01167 { 01168 return filter(input, channel_coeff); 01169 } 01170 01171 cvec TDL_Channel::operator()(const cvec &input) 01172 { 01173 return filter(input); 01174 } 01175 01176 01177 void TDL_Channel::calc_impulse_response(const Array<cvec> &channel_coeff, Array<cvec> &impulse_response) 01178 { 01179 it_assert(init_flag == true, "calc_impulse_response: TDL_Channel is not initialized"); 01180 it_assert(N_taps == channel_coeff.size(), "calc_impulse_response: number of channel taps do not match"); 01181 01182 int no_samples = channel_coeff(0).size(); 01183 it_assert(no_samples > 0, "calc_impulse_response: channel_coeff must contain samples"); 01184 01185 impulse_response.set_size(no_samples); 01186 01187 for (int i=0; i<no_samples; i++) { 01188 impulse_response(i).set_size(d_prof(N_taps-1)+1, false); 01189 impulse_response(i).zeros(); 01190 01191 for (int j=0; j<N_taps; j++) 01192 impulse_response(i)(d_prof(j)) = channel_coeff(j)(i); 01193 01194 } 01195 } 01196 01197 void TDL_Channel::calc_frequency_response(const Array<cvec> &channel_coeff, Array<cvec> &frequency_response, const int fft_size) 01198 { 01199 it_assert(init_flag == true, "calc_frequency_response: TDL_Channel is not initialized"); 01200 it_assert(N_taps == channel_coeff.size(), "calc_frequency_response: number of channel taps do not match"); 01201 01202 int no_samples = channel_coeff(0).size(); 01203 it_assert(no_samples > 0, "calc_frequency_response: channel_coeff must contain samples"); 01204 01205 frequency_response.set_size(no_samples); 01206 01207 it_assert(fft_size > d_prof(N_taps-1), "calc_frequency_response: fft_size must be larger than the maximum delay in samples"); 01208 cvec impulse_response(fft_size); 01209 01210 for (int i=0; i<no_samples; i++) { 01211 impulse_response.zeros(); 01212 01213 for (int j=0; j<N_taps; j++) 01214 impulse_response(d_prof(j)) = channel_coeff(j)(i); 01215 01216 fft(impulse_response, frequency_response(i)); 01217 01218 } 01219 } 01220 01221 void TDL_Channel::calc_frequency_response(const cmat &channel_coeff, cmat &frequency_response, const int fft_size) 01222 { 01223 it_assert(init_flag == true, "calc_frequency_response: TDL_Channel is not initialized"); 01224 it_assert(N_taps == channel_coeff.cols(), "calc_frequency_response: number of channel taps do not match"); 01225 01226 int no_samples = channel_coeff.rows(); 01227 it_assert(no_samples > 0, "calc_frequency_response: channel_coeff must contain samples"); 01228 01229 frequency_response.set_size(fft_size, no_samples, false); 01230 01231 it_assert(fft_size > d_prof(N_taps-1), "calc_frequency_response: fft_size must be larger than the maximum delay in samples"); 01232 cvec impulse_response(fft_size); 01233 cvec freq; 01234 01235 for (int i=0; i<no_samples; i++) { 01236 impulse_response.zeros(); 01237 01238 for (int j=0; j<N_taps; j++) 01239 impulse_response(d_prof(j)) = channel_coeff(i, j); 01240 01241 fft(impulse_response, freq); 01242 frequency_response.set_col(i, freq); 01243 } 01244 } 01245 01246 //------------------------------------------------------------------------------ 01247 // Binary Symetric Channel, BSC. 01248 //------------------------------------------------------------------------------ 01249 01250 01251 bvec BSC::operator()(const bvec &input) 01252 { 01253 int i, length = input.length(); 01254 bvec output(length); 01255 01256 for (i=0; i<length; i++) { 01257 if (u() <= p) { 01258 output(i) = input(i) + bin(1); 01259 } else { 01260 output(i) = input(i); 01261 } 01262 } 01263 return output; 01264 } 01265 01266 01267 01268 cvec AWGN_Channel::operator()(const cvec &input) 01269 { 01270 cvec output = input + sigma*randn_c(input.size()); 01271 return output; 01272 } 01273 01274 vec AWGN_Channel::operator()(const vec &input) 01275 { 01276 vec output = input + sigma*randn(input.size()); 01277 return output; 01278 } 01279 01280 01281 } // namespace itpp
Generated on Wed Mar 21 12:21:41 2007 for IT++ by Doxygen 1.4.7