bool ChannelizerBase::initFFT()
{
	int len;
	int flags = CXVEC_FLG_FFT_ALIGN;

	if (fftInput || fftOutput || fftHandle)
		return false;

	len = chunkLen * mChanM;
	fftInput = cxvec_alloc(len, 0, NULL, flags);

	len = (chunkLen + mFiltLen) * mChanM;
	fftOutput = cxvec_alloc(len, 0, NULL, flags);

	if (!fftInput | !fftOutput) {
		LOG(ERR) << "Memory allocation error";
		return false;
	}

	cxvec_reset(fftInput);
	cxvec_reset(fftOutput);

	fftHandle = init_fft(0, mChanM, chunkLen, chunkLen + mFiltLen,
			     fftInput, fftOutput, mFiltLen);

	return true;
}
/* 
 * Setup filterbank internals
 */
bool ChannelizerBase::init()
{
	int i;

	/*
	 * Filterbank coefficients, fft plan, history, and output sample
	 * rate conversion blocks
	 */
	if (!initFilters()) {
		LOG(ERR) << "Failed to initialize channelizing filter";
		return false;
	}

	mResampler = new Resampler(mP, mQ, mFiltLen, mChanM);
	if (!mResampler->init()) {
		LOG(ERR) << "Failed to initialize resampling filter";
		return false;
	}

	history = (struct cxvec **) malloc(sizeof(struct cxvec *) * mChanM);
	for (i = 0; i < mChanM; i++) {
		history[i] =  cxvec_alloc(mFiltLen, 0, NULL, 0);
		cxvec_reset(history[i]);
	}

	if (!initFFT()) {
		LOG(ERR) << "Failed to initialize FFT";
		return false;
	}

	mapBuffers();

	return true;
}
/* Initialize I/O specific objects */
bool RadioInterface::init()
{
	int i;

	chan = new Channelizer(mChanM, CHAN_FILT_LEN, RESAMP_FILT_LEN,
			       RESAMP_INRATE, RESAMP_OUTRATE, CHUNKMUL);
	if (!chan->init(NULL)) {
		LOG(ALERT) << "Rx channelizer failed to initialize";
		return false;
	}

	synth = new Synthesis(mChanM, CHAN_FILT_LEN, RESAMP_FILT_LEN,
			      RESAMP_OUTRATE, RESAMP_INRATE, CHUNKMUL);
	if (!synth->init(NULL)) {
		LOG(ALERT) << "Tx channelizer failed to initialize";
		return false;
	}

	highRateTxBuf = cxvec_alloc(OUTBUFLEN * mChanM, 0, NULL, 0);
	highRateRxBuf = cxvec_alloc(OUTBUFLEN * mChanM, 0, NULL, 0);

	/*
	 * Setup per-channel variables. The low rate transmit vectors 
	 * feed into the resampler prior to the synthesis filter
	 * and requires headroom equivalent to the filter length. Low
	 * rate buffers are allocated in the main radio interface code.
	 */
	for (i = 0; i < mChanM; i++) {
		if (chanActive[i]) {
			chan->activateChan(i);
			synth->activateChan(i);
		}

		lowRateRxBufs[i] =
			cxvec_alloc(2 * 625, 0, (cmplx *) rcvBuffer[i], 0);
		lowRateTxBufs[i] =
			cxvec_alloc(2 * 625, RESAMP_FILT_LEN, (cmplx *) sendBuffer[i], 0);
	}

	return true;
}
示例#4
0
/*! \brief Reverse a complex vector
 *  \param[in] in Complex input vector
 *  \param[out] out Complex output vector pointers
 */
int cxvec_rvrs(struct cxvec *in, struct cxvec *out)
{
	int i;
	struct cxvec *rev = cxvec_alloc(in->len, 0, NULL, 0);

	for (i = 0; i < in->len; i++)
		rev->data[i] = in->data[in->len - 1 - i];

	memcpy(out->data, rev->data, in->len * sizeof(float complex));

	cxvec_free(rev);

	return 0;
}
/* 
 * Create polyphase filterbank
 *
 * Implementation based material found in, 
 *
 * "harris, fred, Multirate Signal Processing, Upper Saddle River, NJ,
 *     Prentice Hall, 2006."
 */
bool ChannelizerBase::initFilters()
{
	int i, n;
	int m = mChanM;
	int protoLen = m * mFiltLen;

	float *proto;
	float sum = 0.0f;
	float scale = 0.0f;
	float midpt = protoLen / 2;

	/* 
	 * Allocate 'M' partition filters and the temporary prototype
	 * filter. Coefficients are real only and must be 16-byte memory
	 * aligned for SSE usage.
	 */
	int flags = CXVEC_FLG_REAL_ONLY | CXVEC_FLG_MEM_ALIGN;

	proto = (float *) malloc(protoLen * sizeof(float));
	if (!proto)
		return false;

	subFilters = (struct cxvec **) malloc(sizeof(struct cxvec *) * m);
	if (!subFilters)
		return false;

	for (i = 0; i < m; i++) {
		subFilters[i] = cxvec_alloc(mFiltLen, 0, NULL, flags);
	}

	/* 
	 * Generate the prototype filter with a Blackman-harris window.
	 * Scale coefficients with DC filter gain set to unity divided
	 * by the number of channels.
	 */
	float a0 = 0.35875;
	float a1 = 0.48829;
	float a2 = 0.14128;
	float a3 = 0.01168;

	for (i = 0; i < protoLen; i++) {
		proto[i] = cxvec_sinc(((float) i - midpt) / m);
		proto[i] *= a0 -
			    a1 * cos(2 * M_PI * i / (protoLen - 1)) +
			    a2 * cos(4 * M_PI * i / (protoLen - 1)) -
			    a3 * cos(6 * M_PI * i / (protoLen - 1));
		sum += proto[i];
	}
	scale = mChanM / sum;

	/* 
	 * Populate partition filters and reverse the coefficients per
	 * convolution requirements.
	 */
	for (i = 0; i < mFiltLen; i++) {
		for (n = 0; n < m; n++) {
			subFilters[n]->data[i] = proto[i * m + n] * scale;
		}
	}

	for (i = 0; i < m; i++) {
		cxvec_rvrs(subFilters[i], subFilters[i]);
	}

	free(proto);

	return true;
}