diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am index 52ec995b..667217f8 100644 --- a/Transceiver52M/Makefile.am +++ b/Transceiver52M/Makefile.am @@ -67,6 +67,7 @@ libtransceiver_la_SOURCES = \ $(COMMON_SOURCES) \ Resampler.cpp \ radioInterfaceResamp.cpp \ + radioInterfaceMulti.cpp \ radioInterfaceDiversity.cpp bin_PROGRAMS = osmo-trx diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp index 5ffaa62f..af9fc988 100644 --- a/Transceiver52M/UHDDevice.cpp +++ b/Transceiver52M/UHDDevice.cpp @@ -35,6 +35,7 @@ #endif #define B2XX_CLK_RT 26e6 +#define B2XX_MCBTS_CLK_RT 3.2e6 #define E1XX_CLK_RT 52e6 #define B100_BASE_RT 400000 #define USRP2_BASE_RT 390625 @@ -61,6 +62,7 @@ enum uhd_dev_type { B100, B200, B210, + B2XX_MCBTS, E1XX, E3XX, X3XX, @@ -110,6 +112,7 @@ static struct uhd_dev_offset uhd_offsets[] = { { B200, 4, 1, B2XX_TIMING_4SPS, "B200 4/1 Tx/Rx SPS" }, { B210, 1, 1, B2XX_TIMING_1SPS, "B210 1 SPS" }, { B210, 4, 1, B2XX_TIMING_4SPS, "B210 4/1 Tx/Rx SPS" }, + { B2XX_MCBTS, 4, 4, 1.07188e-4, "B200/B210 4 SPS Multi-ARFCN" }, { E1XX, 1, 1, 9.5192e-5, "E1XX 1 SPS" }, { E1XX, 4, 1, 6.5571e-5, "E1XX 4/1 Tx/Rx SPS" }, { E3XX, 1, 1, 1.84616e-4, "E3XX 1 SPS" }, @@ -150,9 +153,20 @@ static double select_rate(uhd_dev_type type, int sps, return -9999.99; } + if ((sps != 4) && (sps != 1)) return -9999.99; + if (iface == RadioDevice::MULTI_ARFCN) { + switch (type) { + case B2XX_MCBTS: + return 4 * MCBTS_SPACING; + default: + LOG(ALERT) << "Invalid device combination"; + return -9999.99; + } + } + switch (type) { case USRP2: case X3XX: @@ -542,12 +556,15 @@ int uhd_device::set_rates(double tx_rate, double rx_rate) if ((dev_type == B200) || (dev_type == B210) || (dev_type == E3XX)) { if (set_master_clk(B2XX_CLK_RT) < 0) return -1; - } - else if (dev_type == E1XX) { + } else if (dev_type == E1XX) { if (set_master_clk(E1XX_CLK_RT) < 0) return -1; + } else if (dev_type == B2XX_MCBTS) { + if (set_master_clk(B2XX_MCBTS_CLK_RT) < 0) + return -1; } + // Set sample rates try { usrp_dev->set_tx_rate(tx_rate); @@ -574,6 +591,9 @@ int uhd_device::set_rates(double tx_rate, double rx_rate) double uhd_device::setTxGain(double db, size_t chan) { + if (iface == MULTI_ARFCN) + chan = 0; + if (chan >= tx_gains.size()) { LOG(ALERT) << "Requested non-existent channel" << chan; return 0.0f; @@ -620,6 +640,9 @@ double uhd_device::setRxGain(double db, size_t chan) double uhd_device::getRxGain(size_t chan) { + if (iface == MULTI_ARFCN) + chan = 0; + if (chan >= rx_gains.size()) { LOG(ALERT) << "Requested non-existent channel " << chan; return 0.0f; @@ -762,11 +785,24 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels) } // Verify and set channels - if ((dev_type == B210) && (chans == 2)) { - } else if ((dev_type == UMTRX) && (chans == 2)) { - uhd::usrp::subdev_spec_t subdev_spec(swap_channels?"B:0 A:0":"A:0 B:0"); - usrp_dev->set_tx_subdev_spec(subdev_spec); - usrp_dev->set_rx_subdev_spec(subdev_spec); + if (iface == MULTI_ARFCN) { + if ((dev_type != B200) && (dev_type != B210)) { + LOG(ALERT) << "Unsupported device configuration"; + return -1; + } + + dev_type = B2XX_MCBTS; + chans = 1; + } else if (chans == 2) { + if (dev_type == B210) { + } else if (dev_type == UMTRX) { + uhd::usrp::subdev_spec_t subdev_spec(swap_channels?"B:0 A:0":"A:0 B:0"); + usrp_dev->set_tx_subdev_spec(subdev_spec); + usrp_dev->set_rx_subdev_spec(subdev_spec); + } else { + LOG(ALERT) << "Invalid device configuration"; + return -1; + } } else if (chans != 1) { LOG(ALERT) << "Invalid channel combination for device"; return -1; @@ -839,6 +875,8 @@ int uhd_device::open(const std::string &args, bool extref, bool swap_channels) if (iface == DIVERSITY) return DIVERSITY; + if (iface == MULTI_ARFCN) + return MULTI_ARFCN; switch (dev_type) { case B100: @@ -1295,7 +1333,7 @@ double uhd_device::getRxFreq(size_t chan) */ TIMESTAMP uhd_device::initialWriteTimestamp() { - if (rx_sps == tx_sps) + if ((iface == MULTI_ARFCN) || (rx_sps == tx_sps)) return ts_initial; else return ts_initial * tx_sps; diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp index 9dcda5fc..ac9cc488 100644 --- a/Transceiver52M/osmo-trx.cpp +++ b/Transceiver52M/osmo-trx.cpp @@ -74,6 +74,7 @@ struct trx_config { bool extref; Transceiver::FillerType filler; bool diversity; + bool mcbts; double offset; double rssi_offset; bool swap_channels; @@ -127,7 +128,7 @@ bool testConfig() */ bool trx_setup_config(struct trx_config *config) { - std::string refstr, fillstr, divstr, edgestr; + std::string refstr, fillstr, divstr, mcstr, edgestr; if (!testConfig()) return false; @@ -163,13 +164,29 @@ bool trx_setup_config(struct trx_config *config) config->diversity = DEFAULT_DIVERSITY; } - /* Diversity only supported on 2 channels */ - if (config->diversity) + if (!config->chans) + config->chans = DEFAULT_CHANS; + + if (config->mcbts && ((config->chans < 0) || (config->chans > 5))) { + std::cout << "Unsupported number of channels" << std::endl; + return false; + } + + /* Diversity only supported on 2 channels without multi-carrier */ + if (config->diversity && config->mcbts) { + std::cout << "Multi-carrier diversity unsupported" << std::endl; + return false; + } + if (config->diversity && (config->chans != 2)) { + std::cout << "Setting channels to 2 for diversity" << std::endl; config->chans = 2; + } edgestr = config->edge ? "Enabled" : "Disabled"; refstr = config->extref ? "Enabled" : "Disabled"; divstr = config->diversity ? "Enabled" : "Disabled"; + mcstr = config->mcbts ? "Enabled" : "Disabled"; + switch (config->filler) { case Transceiver::FILLER_DUMMY: fillstr = "Dummy bursts"; @@ -200,6 +217,7 @@ bool trx_setup_config(struct trx_config *config) ost << " EDGE support............ " << edgestr << std::endl; ost << " External Reference...... " << refstr << std::endl; ost << " C0 Filler Table......... " << fillstr << std::endl; + ost << " Multi-Carrier........... " << mcstr << std::endl; ost << " Diversity............... " << divstr << std::endl; ost << " Tuning offset........... " << config->offset << std::endl; ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl; @@ -235,6 +253,10 @@ RadioInterface *makeRadioInterface(struct trx_config *config, radio = new RadioInterfaceDiversity(usrp, config->tx_sps, config->chans); break; + case RadioDevice::MULTI_ARFCN: + radio = new RadioInterfaceMulti(usrp, config->tx_sps, + config->rx_sps, config->chans); + break; default: LOG(ALERT) << "Unsupported radio interface configuration"; return NULL; @@ -309,6 +331,7 @@ static void print_help() " -p Base port number\n" " -e Enable EDGE receiver\n" " -d Enable dual channel diversity receiver\n" + " -m Enable multi-ARFCN transceiver (default=disabled)\n" " -x Enable external 10 MHz reference\n" " -s Tx samples-per-symbol (1 or 4)\n" " -b Rx samples-per-symbol (1 or 4)\n" @@ -334,13 +357,14 @@ static void handle_options(int argc, char **argv, struct trx_config *config) config->rach_delay = 0; config->extref = false; config->filler = Transceiver::FILLER_ZERO; + config->mcbts = false; config->diversity = false; config->offset = 0.0; config->rssi_offset = 0.0; config->swap_channels = false; config->edge = false; - while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:b:r:A:R:Se")) != -1) { + while ((option = getopt(argc, argv, "ha:l:i:p:c:dmxfo:s:b:r:A:R:Se")) != -1) { switch (option) { case 'h': print_help(); @@ -361,6 +385,9 @@ static void handle_options(int argc, char **argv, struct trx_config *config) case 'c': config->chans = atoi(optarg); break; + case 'm': + config->mcbts = true; + break; case 'd': config->diversity = true; break; @@ -403,8 +430,8 @@ static void handle_options(int argc, char **argv, struct trx_config *config) } } - /* Force 4 SPS for EDGE configurations */ - if (config->edge) { + /* Force 4 SPS for EDGE or multi-ARFCN configurations */ + if ((config->edge) || (config->mcbts)) { config->tx_sps = 4; config->rx_sps = 4; } @@ -412,7 +439,8 @@ static void handle_options(int argc, char **argv, struct trx_config *config) if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND)) config->filler = Transceiver::FILLER_EDGE_RAND; - if ((config->tx_sps != 1) && (config->tx_sps != 4)) { + if ((config->tx_sps != 1) && (config->tx_sps != 4) && + (config->rx_sps != 1) && (config->rx_sps != 4)) { printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps); print_help(); exit(0); @@ -455,6 +483,9 @@ int main(int argc, char *argv[]) srandom(time(NULL)); /* Create the low level device object */ + if (config.mcbts) + iface = RadioDevice::MULTI_ARFCN; + usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface, config.chans, config.offset); type = usrp->open(config.dev_args, config.extref, config.swap_channels); diff --git a/Transceiver52M/radioDevice.h b/Transceiver52M/radioDevice.h index a9924833..142fcf6b 100644 --- a/Transceiver52M/radioDevice.h +++ b/Transceiver52M/radioDevice.h @@ -23,6 +23,7 @@ #endif #define GSMRATE (1625e3/6) +#define MCBTS_SPACING 800000.0 /** a 64-bit virtual timestamp for radio data */ typedef unsigned long long TIMESTAMP; @@ -39,6 +40,7 @@ class RadioDevice { NORMAL, RESAMP_64M, RESAMP_100M, + MULTI_ARFCN, DIVERSITY, }; diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h index 1f225a22..b63cc4c2 100644 --- a/Transceiver52M/radioInterface.h +++ b/Transceiver52M/radioInterface.h @@ -22,6 +22,8 @@ #include "radioClock.h" #include "radioBuffer.h" #include "Resampler.h" +#include "Channelizer.h" +#include "Synthesis.h" static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods @@ -101,7 +103,7 @@ public: RadioClock* getClock(void) { return &mClock;}; /** set transmit frequency */ - bool tuneTx(double freq, size_t chan = 0); + virtual bool tuneTx(double freq, size_t chan = 0); /** set receive frequency */ virtual bool tuneRx(double freq, size_t chan = 0); @@ -164,6 +166,34 @@ public: void close(); }; +class RadioInterfaceMulti : public RadioInterface { +private: + bool pushBuffer(); + void pullBuffer(); + + signalVector *outerSendBuffer; + signalVector *outerRecvBuffer; + std::vector history; + std::vector active; + + Resampler *dnsampler; + Resampler *upsampler; + Channelizer *channelizer; + Synthesis *synthesis; + +public: + RadioInterfaceMulti(RadioDevice* radio, size_t tx_sps, + size_t rx_sps, size_t chans = 1); + ~RadioInterfaceMulti(); + + bool init(int type); + void close(); + + bool tuneTx(double freq, size_t chan); + bool tuneRx(double freq, size_t chan); + double setRxGain(double dB, size_t chan); +}; + class RadioInterfaceDiversity : public RadioInterface { public: RadioInterfaceDiversity(RadioDevice* wRadio, diff --git a/Transceiver52M/radioInterfaceMulti.cpp b/Transceiver52M/radioInterfaceMulti.cpp new file mode 100644 index 00000000..ba81fe15 --- /dev/null +++ b/Transceiver52M/radioInterfaceMulti.cpp @@ -0,0 +1,387 @@ +/* + * Multi-carrier radio interface + * + * Copyright (C) 2016 Ettus Research LLC + * + * Author: Tom Tsou + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * See the COPYING file in the main directory for details. + */ + +#include +#include + +#include "Resampler.h" + +extern "C" { +#include "convert.h" +} + +/* Resampling parameters for 64 MHz clocking */ +#define RESAMP_INRATE 65 +#define RESAMP_OUTRATE (96 / 2) + +/* Universal resampling parameters */ +#define NUMCHUNKS 24 + +#define MCHANS 4 + +RadioInterfaceMulti::RadioInterfaceMulti(RadioDevice *radio, size_t tx_sps, + size_t rx_sps, size_t chans) + : RadioInterface(radio, tx_sps, rx_sps, chans), + outerSendBuffer(NULL), outerRecvBuffer(NULL), + dnsampler(NULL), upsampler(NULL), channelizer(NULL), synthesis(NULL) +{ +} + +RadioInterfaceMulti::~RadioInterfaceMulti() +{ + close(); +} + +void RadioInterfaceMulti::close() +{ + delete outerSendBuffer; + delete outerRecvBuffer; + delete dnsampler; + delete upsampler; + delete channelizer; + delete synthesis; + + outerSendBuffer = NULL; + outerRecvBuffer = NULL; + dnsampler = NULL; + upsampler = NULL; + channelizer = NULL; + synthesis = NULL; + + mReceiveFIFO.resize(0); + powerScaling.resize(0); + history.resize(0); + active.resize(0); + + RadioInterface::close(); +} + +static int getLogicalChan(size_t pchan, size_t chans) +{ + switch (chans) { + case 1: + if (pchan == 0) + return 0; + else + return -1; + break; + case 2: + if (pchan == 0) + return 0; + if (pchan == 3) + return 1; + else + return -1; + break; + case 3: + if (pchan == 1) + return 0; + if (pchan == 0) + return 1; + if (pchan == 3) + return 2; + else + return -1; + break; + default: + break; + }; + + return -1; +} + +static int getFreqShift(size_t chans) +{ + switch (chans) { + case 1: + return 0; + case 2: + return 0; + case 3: + return 1; + default: + break; + }; + + return -1; +} + +/* Initialize I/O specific objects */ +bool RadioInterfaceMulti::init(int type) +{ + float cutoff = 1.0f; + size_t inchunk = 0, outchunk = 0; + + if (mChans > MCHANS - 1) { + LOG(ALERT) << "Invalid channel configuration " << mChans; + return false; + } + + close(); + + sendBuffer.resize(mChans); + recvBuffer.resize(mChans); + convertSendBuffer.resize(1); + convertRecvBuffer.resize(1); + + mReceiveFIFO.resize(mChans); + powerScaling.resize(mChans); + history.resize(mChans); + active.resize(MCHANS, false); + + inchunk = RESAMP_INRATE * 4; + outchunk = RESAMP_OUTRATE * 4; + + if (inchunk * NUMCHUNKS < 625 * 2) { + LOG(ALERT) << "Invalid inner chunk size " << inchunk; + return false; + } + + dnsampler = new Resampler(RESAMP_INRATE, RESAMP_OUTRATE); + if (!dnsampler->init(1.0)) { + LOG(ALERT) << "Rx resampler failed to initialize"; + return false; + } + + upsampler = new Resampler(RESAMP_OUTRATE, RESAMP_INRATE); + if (!upsampler->init(cutoff)) { + LOG(ALERT) << "Tx resampler failed to initialize"; + return false; + } + + channelizer = new Channelizer(MCHANS, outchunk); + if (!channelizer->init()) { + LOG(ALERT) << "Rx channelizer failed to initialize"; + return false; + } + + synthesis = new Synthesis(MCHANS, outchunk); + if (!synthesis->init()) { + LOG(ALERT) << "Tx synthesis filter failed to initialize"; + return false; + } + + /* + * Allocate high and low rate buffers. The high rate receive + * buffer and low rate transmit vectors feed into the resampler + * and requires headroom equivalent to the filter length. Low + * rate buffers are allocated in the main radio interface code. + */ + for (size_t i = 0; i < mChans; i++) { + sendBuffer[i] = new RadioBuffer(NUMCHUNKS, inchunk, + upsampler->len(), true); + recvBuffer[i] = new RadioBuffer(NUMCHUNKS, inchunk, + 0, false); + history[i] = new signalVector(dnsampler->len()); + + synthesis->resetBuffer(i); + } + + outerSendBuffer = new signalVector(synthesis->outputLen()); + outerRecvBuffer = new signalVector(channelizer->inputLen()); + + convertSendBuffer[0] = new short[2 * synthesis->outputLen()]; + convertRecvBuffer[0] = new short[2 * channelizer->inputLen()]; + + /* Configure channels */ + switch (mChans) { + case 1: + active[0] = true; + break; + case 2: + active[0] = true; + active[3] = true; + break; + case 3: + active[0] = true; + active[1] = true; + active[3] = true; + break; + default: + LOG(ALERT) << "Unsupported channel combination"; + return false; + } + + return true; +} + +/* Receive a timestamped chunk from the device */ +void RadioInterfaceMulti::pullBuffer() +{ + bool local_underrun; + size_t num; + float *buf; + + if (recvBuffer[0]->getFreeSegments() <= 0) + return; + + /* Outer buffer access size is fixed */ + num = mRadio->readSamples(convertRecvBuffer, + outerRecvBuffer->size(), + &overrun, + readTimestamp, + &local_underrun); + if (num != channelizer->inputLen()) { + LOG(ALERT) << "Receive error " << num << ", " << channelizer->inputLen(); + return; + } + + convert_short_float((float *) outerRecvBuffer->begin(), + convertRecvBuffer[0], 2 * outerRecvBuffer->size()); + + underrun |= local_underrun; + readTimestamp += num; + + channelizer->rotate((float *) outerRecvBuffer->begin(), + outerRecvBuffer->size()); + + for (size_t pchan = 0; pchan < MCHANS; pchan++) { + if (!active[pchan]) + continue; + + int lchan = getLogicalChan(pchan, mChans); + if (lchan < 0) { + LOG(ALERT) << "Invalid logical channel " << pchan; + continue; + } + + /* + * Update history by writing into the head portion of the + * channelizer output buffer. For this to work, filter length of + * the polyphase channelizer partition filter should be equal to + * or larger than the resampling filter. + */ + buf = channelizer->outputBuffer(pchan); + size_t cLen = channelizer->outputLen(); + size_t hLen = dnsampler->len(); + size_t hSize = 2 * hLen * sizeof(float); + + memcpy(&buf[2 * -hLen], history[lchan]->begin(), hSize); + memcpy(history[lchan]->begin(), &buf[2 * (cLen - hLen)], hSize); + + float *wr_segment = recvBuffer[lchan]->getWriteSegment(); + + /* Write to the end of the inner receive buffer */ + if (!dnsampler->rotate(channelizer->outputBuffer(pchan), + channelizer->outputLen(), + wr_segment, + recvBuffer[lchan]->getSegmentLen())) { + LOG(ALERT) << "Sample rate upsampling error"; + } + } +} + +/* Send a timestamped chunk to the device */ +bool RadioInterfaceMulti::pushBuffer() +{ + if (sendBuffer[0]->getAvailSegments() <= 0) + return false; + + for (size_t pchan = 0; pchan < MCHANS; pchan++) { + if (!active[pchan]) { + synthesis->resetBuffer(pchan); + continue; + } + + int lchan = getLogicalChan(pchan, mChans); + if (lchan < 0) { + LOG(ALERT) << "Invalid logical channel " << pchan; + continue; + } + + if (!upsampler->rotate(sendBuffer[lchan]->getReadSegment(), + sendBuffer[lchan]->getSegmentLen(), + synthesis->inputBuffer(pchan), + synthesis->inputLen())) { + LOG(ALERT) << "Sample rate downsampling error"; + } + } + + synthesis->rotate((float *) outerSendBuffer->begin(), + outerSendBuffer->size()); + + convert_float_short(convertSendBuffer[0], + (float *) outerSendBuffer->begin(), + 1.0 / (float) mChans, 2 * outerSendBuffer->size()); + + size_t num = mRadio->writeSamples(convertSendBuffer, + outerSendBuffer->size(), + &underrun, + writeTimestamp); + if (num != outerSendBuffer->size()) { + LOG(ALERT) << "Transmit error " << num; + } + + writeTimestamp += num; + + return true; +} + +/* Frequency comparison limit */ +#define FREQ_DELTA_LIMIT 10.0 + +static bool fltcmp(double a, double b) +{ + return fabs(a - b) < FREQ_DELTA_LIMIT ? true : false; +} + +bool RadioInterfaceMulti::tuneTx(double freq, size_t chan) +{ + if (chan >= mChans) + return false; + + double shift = (double) getFreqShift(mChans); + + if (!chan) + return mRadio->setTxFreq(freq + shift * MCBTS_SPACING); + + double center = mRadio->getTxFreq(); + if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) + return false; + + return true; +} + +bool RadioInterfaceMulti::tuneRx(double freq, size_t chan) +{ + if (chan >= mChans) + return false; + + double shift = (double) getFreqShift(mChans); + + if (!chan) + return mRadio->setRxFreq(freq + shift * MCBTS_SPACING); + + double center = mRadio->getRxFreq(); + if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) + return false; + + return true; +} + +double RadioInterfaceMulti::setRxGain(double db, size_t chan) +{ + if (!chan) + return mRadio->setRxGain(db); + else + return mRadio->getRxGain(); +} diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index 7a032b39..6495b1eb 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -80,7 +80,6 @@ static Complex psk8_table[8] = { #define DOWNSAMPLE_OUT_LEN 156 static Resampler *dnsampler = NULL; -static signalVector *dnsampler_in = NULL; /* * RACH and midamble correlation waveforms. Store the buffer separately @@ -163,7 +162,6 @@ void sigProcLibDestroy() delete GSMPulse1; delete GSMPulse4; delete dnsampler; - delete dnsampler_in; GMSKRotation1 = NULL; GMSKRotation4 = NULL; @@ -1936,13 +1934,15 @@ int detectEdgeBurst(signalVector &rxBurst, unsigned tsc, float thresh, signalVector *downsampleBurst(signalVector &burst) { - size_t ilen = DOWNSAMPLE_IN_LEN, olen = DOWNSAMPLE_OUT_LEN; + signalVector *in, *out; - signalVector *out = new signalVector(olen); - memcpy(dnsampler_in->begin(), burst.begin(), ilen * 2 * sizeof(float)); + in = new signalVector(DOWNSAMPLE_IN_LEN, dnsampler->len()); + out = new signalVector(DOWNSAMPLE_OUT_LEN); + memcpy(in->begin(), burst.begin(), DOWNSAMPLE_IN_LEN * 2 * sizeof(float)); - dnsampler->rotate((float *) dnsampler_in->begin(), ilen, - (float *) out->begin(), olen); + dnsampler->rotate((float *) in->begin(), DOWNSAMPLE_IN_LEN, + (float *) out->begin(), DOWNSAMPLE_OUT_LEN); + delete in; return out; }; @@ -2128,8 +2128,6 @@ bool sigProcLibSetup() goto fail; } - dnsampler_in = new signalVector(DOWNSAMPLE_IN_LEN, dnsampler->len()); - return true; fail: