diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-12-25 14:57:56 +0100 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-12-25 14:57:56 +0100 | 
| commit | 78c4a0b9af981dc66cb42d46dfd60fe87679d178 (patch) | |
| tree | 7da981e2ee8d8e9047c482f86ceb607e84ee1566 | |
| parent | aa63facf2c4140acef2ba6e7f1b8012eec5536bf (diff) | |
| download | dabmod-78c4a0b9af981dc66cb42d46dfd60fe87679d178.tar.gz dabmod-78c4a0b9af981dc66cb42d46dfd60fe87679d178.tar.bz2 dabmod-78c4a0b9af981dc66cb42d46dfd60fe87679d178.zip  | |
Add file output format converter
| -rw-r--r-- | src/DabMod.cpp | 50 | ||||
| -rw-r--r-- | src/FormatConverter.cpp | 96 | ||||
| -rw-r--r-- | src/FormatConverter.h | 53 | ||||
| -rw-r--r-- | src/Makefile.am | 1 | 
4 files changed, 186 insertions, 14 deletions
diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 91c0b9d..dc61ae2 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -35,6 +35,7 @@  #include "DabModulator.h"  #include "InputMemory.h"  #include "OutputFile.h" +#include "FormatConverter.h"  #if defined(HAVE_OUTPUT_UHD)  #   include "OutputUHD.h"  #endif @@ -176,6 +177,7 @@ int main(int argc, char* argv[])      std::string outputName;      int useZeroMQOutput = 0;      int useFileOutput = 0; +    std::string fileOutputFormat = "complexf";      int useUHDOutput = 0;      uint64_t frame = 0; @@ -187,6 +189,17 @@ int main(int argc, char* argv[])      GainMode gainMode = GAIN_VAR;      Buffer data; + +    /* UHD requires the input I and Q samples to be in the interval +     * [-1.0,1.0], otherwise they get truncated, which creates very +     * wide-spectrum spikes. Depending on the Transmission Mode, the +     * Gain Mode and the sample rate (and maybe other parameters), the +     * samples can have peaks up to about 48000. The value of 50000 +     * should guarantee that with a digital gain of 1.0, UHD never clips +     * our samples. +     */ +    const float normalise_factor = 50000.0f; +      std::string filterTapsFilename = "";      // Two configuration sources exist: command line and (new) INI file @@ -207,6 +220,7 @@ int main(int argc, char* argv[])      Flowgraph* flowgraph = NULL;      DabModulator* modulator = NULL;      InputMemory* input = NULL; +    FormatConverter* format_converter = NULL;      ModOutput* output = NULL;      BaseRemoteController* rc = NULL; @@ -478,6 +492,8 @@ int main(int argc, char* argv[])                  goto END_MAIN;              }              useFileOutput = 1; + +            fileOutputFormat = pt.get("fileoutput.format", fileOutputFormat);          }  #if defined(HAVE_OUTPUT_UHD)          else if (output_selected == "uhd") { @@ -741,23 +757,23 @@ int main(int argc, char* argv[])          goto END_MAIN;      } -      if (useFileOutput) { -        // Opening COFDM output file -        output = new OutputFile(outputName); +        if (fileOutputFormat == "complexf") { +            output = new OutputFile(outputName); +        } +        else if (fileOutputFormat == "s8") { +            // We must normalise the samples to the interval [-127.0; 127.0] +            normalise = 127.0f / normalise_factor; + +            format_converter = new FormatConverter(); + +            output = new OutputFile(outputName); +        }      }  #if defined(HAVE_OUTPUT_UHD)      else if (useUHDOutput) { -        /* UHD requires the input I and Q samples to be in the interval -         * [-1.0,1.0], otherwise they get truncated, which creates very -         * wide-spectrum spikes. Depending on the Transmission Mode, the -         * Gain Mode and the sample rate (and maybe other parameters), the -         * samples can have peaks up to about 48000. The value of 50000 -         * should guarantee that with a digital gain of 1.0, UHD never clips -         * our samples. -         */ -        normalise = 1.0f/50000.0f; +        normalise = 1.0f / normalise_factor;          outputuhd_conf.sampleRate = outputRate;          try { @@ -773,7 +789,7 @@ int main(int argc, char* argv[])  #if defined(HAVE_OUTPUT_ZEROMQ)      else if (useZeroMQOutput) {          /* We normalise the same way as for the UHD output */ -        normalise = 1.0f/50000.0f; +        normalise = 1.0f / normalise_factor;          output = new OutputZeroMQ(outputName);      } @@ -785,7 +801,13 @@ int main(int argc, char* argv[])      modulator = new DabModulator(modconf, rc, logger, outputRate, clockRate,              dabMode, gainMode, digitalgain, normalise, filterTapsFilename);      flowgraph->connect(input, modulator); -    flowgraph->connect(modulator, output); +    if (format_converter) { +        flowgraph->connect(modulator, format_converter); +        flowgraph->connect(format_converter, output); +    } +    else { +        flowgraph->connect(modulator, output); +    }  #if defined(HAVE_OUTPUT_UHD)      if (useUHDOutput) { diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp new file mode 100644 index 0000000..4f7d95c --- /dev/null +++ b/src/FormatConverter.cpp @@ -0,0 +1,96 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty +   the Queen in Right of Canada (Communications Research Center Canada) + +   Copyright (C) 2014 +   Matthias P. Braendli, matthias.braendli@mpb.li + +    http://opendigitalradio.org + +    This flowgraph block converts complexf to signed integer. + */ +/* +   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 <http://www.gnu.org/licenses/>. + */ + +#include "FormatConverter.h" +#include "PcDebug.h" + +#include <malloc.h> +#include <sys/types.h> +#include <string.h> +#include <stdexcept> +#include <assert.h> + + +FormatConverter::FormatConverter(void) : +    ModCodec(ModFormat(sizeof(complexf)), +            ModFormat(sizeof(int8_t))) { } + +/* Expect the input samples to be in the range [-255.0, 255.0] */ +int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) +{ +    PDEBUG("FormatConverter::process(dataIn: %p, dataOut: %p)\n", +            dataIn, dataOut); + +    size_t sizeIn = dataIn->getLength() / sizeof(float); +    dataOut->setLength(sizeIn * sizeof(int8_t)); + +    float* in = reinterpret_cast<float*>(dataIn->getData()); +    int8_t* out = reinterpret_cast<int8_t*>(dataOut->getData()); + +#if 0 +    // WARNING: Untested Code Ahead +    assert(sizeIn % 16 == 0); +    assert((uintptr_t)in % 16 == 0); +    for(int i = 0; i < sizeIn; i+=16) +    { +        __m128 a1 = _mm_load_ps(in+i+0); +        __m128 a2 = _mm_load_ps(in+i+4); +        __m128 a3 = _mm_load_ps(in+i+8); +        __m128 a4 = _mm_load_ps(in+i+12); +        __m64 b1 = _mm_cvtps_pi8(a1); +        __m64 b2 = _mm_cvtps_pi8(a2); +        __m64 b3 = _mm_cvtps_pi8(a3); +        __m64 b4 = _mm_cvtps_pi8(a4); +        _mm_store_ps(out+i+0, b1); +        _mm_store_ps(out+i+4, b2); +        _mm_store_ps(out+i+8, b3); +        _mm_store_ps(out+i+12, b4); +    } +#else +    // Slow implementation that uses _ftol() +    for (size_t i = 0; i < sizeIn; i++) { +        if (in[i] > 127.0f) { +            out[i] = 127; +        } +        else if (in[i] < -127.0f) { +            out[i] = -127; +        } +        else { +            out[i] = in[i]; +        } +    } +#endif + +    return 1; +} + +const char* FormatConverter::name() +{ +    return "FormatConverter"; +} + diff --git a/src/FormatConverter.h b/src/FormatConverter.h new file mode 100644 index 0000000..0243685 --- /dev/null +++ b/src/FormatConverter.h @@ -0,0 +1,53 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty +   the Queen in Right of Canada (Communications Research Center Canada) + +   Copyright (C) 2014 +   Matthias P. Braendli, matthias.braendli@mpb.li + +    http://opendigitalradio.org + +    This flowgraph block converts complexf to signed integer. + */ +/* +   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 <http://www.gnu.org/licenses/>. + */ + +#ifndef FORMAT_CONVERTER_H +#define FORMAT_CONVERTER_H + +#ifdef HAVE_CONFIG_H +#   include <config.h> +#endif + +#include "porting.h" +#include "ModCodec.h" +#include <complex> +#include <stdint.h> + +typedef std::complex<float> complexf; + +class FormatConverter : public ModCodec +{ +    public: +        FormatConverter(void); + +        int process(Buffer* const dataIn, Buffer* dataOut); +        const char* name(); +}; + +#endif // FORMAT_CONVERTER_H + diff --git a/src/Makefile.am b/src/Makefile.am index 922ce52..f8ba7c2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -110,6 +110,7 @@ odr_dabmod_SOURCES  = DabMod.cpp \  					  ThreadsafeQueue.h \  					  Log.cpp Log.h \  					  RemoteControl.cpp RemoteControl.h \ +					  FormatConverter.cpp FormatConverter.h \  					  zmq.hpp  nodist_odr_dabmod_SOURCES = $(FFT_SRC)  | 
