/*
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(ModFormat(0), ModFormat(0))
{
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;
}