IT++ Logo Newcom Logo

channel.cpp

Go to the documentation of this file.
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
SourceForge Logo

Generated on Sat Aug 25 23:40:26 2007 for IT++ by Doxygen 1.5.2