/* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) */ /* This file is part of ODR-DabMod. ODR-DabMod is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. ODR-DabMod is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ODR-DabMod. If not, see . */ #include "FrequencyInterleaver.h" #include "PcDebug.h" #include #include #include #include typedef std::complex complexf; FrequencyInterleaver::FrequencyInterleaver(size_t mode) : ModCodec() { PDEBUG("FrequencyInterleaver::FrequencyInterleaver(%zu) @ %p\n", mode, this); size_t num; size_t alpha = 13; size_t beta; switch (mode) { case 1: d_carriers = 1536; num = 2048; beta = 511; break; case 2: d_carriers = 384; num = 512; beta = 127; break; case 3: d_carriers = 192; num = 256; beta = 63; break; case 0: case 4: d_carriers = 768; num = 1024; beta = 255; break; default: PDEBUG("Carriers: %zu\n", (d_carriers >> 1) << 1); throw std::runtime_error("FrequencyInterleaver::FrequencyInterleaver " "nb of carriers invalid!"); break; } d_indexes = (size_t*)memalign(16, d_carriers * sizeof(size_t)); size_t* index = d_indexes; size_t perm = 0; PDEBUG("i: %4u, R: %4u\n", 0, 0); for (size_t j = 1; j < num; ++j) { perm = (alpha * perm + beta) & (num - 1); if (perm >= ((num - d_carriers) / 2) && perm <= (num - (num - d_carriers) / 2) && perm != (num / 2)) { PDEBUG("i: %4zu, R: %4zu, d: %4zu, n: %4zu, k: %5zi, index: %zu\n", j, perm, perm, index - d_indexes, perm - num / 2, perm > num / 2 ? perm - (1 + (num / 2)) : perm + (d_carriers - (num / 2))); *(index++) = perm > num / 2 ? perm - (1 + (num / 2)) : perm + (d_carriers - (num / 2)); } else { PDEBUG("i: %4zu, R: %4zu\n", j, perm); } } } FrequencyInterleaver::~FrequencyInterleaver() { PDEBUG("FrequencyInterleaver::~FrequencyInterleaver() @ %p\n", this); free(d_indexes); } int FrequencyInterleaver::process(Buffer* const dataIn, Buffer* dataOut) { PDEBUG("FrequencyInterleaver::process" "(dataIn: %p, sizeIn: %zu, dataOut: %p, sizeOut: %zu)\n", dataIn, dataIn->getLength(), dataOut, dataOut->getLength()); dataOut->setLength(dataIn->getLength()); const complexf* in = reinterpret_cast(dataIn->getData()); complexf* out = reinterpret_cast(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexf); if (sizeIn % d_carriers != 0) { throw std::runtime_error( "FrequencyInterleaver::process input size not valid!"); } for (size_t i = 0; i < sizeIn;) { // memset(out, 0, d_carriers * sizeof(complexf)); for (size_t j = 0; j < d_carriers; i += 4, j += 4) { out[d_indexes[j]] = in[i]; out[d_indexes[j + 1]] = in[i + 1]; out[d_indexes[j + 2]] = in[i + 2]; out[d_indexes[j + 3]] = in[i + 3]; } out += d_carriers; } return 1; }