From 78c4a0b9af981dc66cb42d46dfd60fe87679d178 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 25 Dec 2014 14:57:56 +0100 Subject: Add file output format converter --- src/FormatConverter.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/FormatConverter.cpp (limited to 'src/FormatConverter.cpp') 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 . + */ + +#include "FormatConverter.h" +#include "PcDebug.h" + +#include +#include +#include +#include +#include + + +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(dataIn->getData()); + int8_t* out = reinterpret_cast(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"; +} + -- cgit v1.2.3 From 289ca8255ec7341530327a4b118372276cc3147e Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 25 Dec 2014 15:56:46 +0100 Subject: FormatConverter: correct SSE code --- src/FormatConverter.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'src/FormatConverter.cpp') diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index 4f7d95c..8b510bd 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -35,6 +35,9 @@ #include #include +#ifdef __SSE__ +# include +#endif FormatConverter::FormatConverter(void) : ModCodec(ModFormat(sizeof(complexf)), @@ -50,13 +53,20 @@ int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) dataOut->setLength(sizeIn * sizeof(int8_t)); float* in = reinterpret_cast(dataIn->getData()); - int8_t* out = reinterpret_cast(dataOut->getData()); -#if 0 - // WARNING: Untested Code Ahead +#ifdef __SSE__ + /* + _mm_cvtps_pi8 does: + |<----------- 128 bits ------------>| + __m128 | I1 | Q1 | I2 | Q2 | in float + __m64 |I1Q1I2Q2|00000000| in int8_t + */ + + uint32_t* out = reinterpret_cast(dataOut->getData()); + assert(sizeIn % 16 == 0); assert((uintptr_t)in % 16 == 0); - for(int i = 0; i < sizeIn; i+=16) + for(size_t i = 0, j = 0; i < sizeIn; i+=16, j+=4) { __m128 a1 = _mm_load_ps(in+i+0); __m128 a2 = _mm_load_ps(in+i+4); @@ -66,23 +76,17 @@ int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) __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); + out[j+0] = b1[0]; + out[j+1] = b2[0]; + out[j+2] = b3[0]; + out[j+3] = b4[0]; } #else + int8_t* out = reinterpret_cast(dataOut->getData()); + // 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]; - } + out[i] = in[i]; } #endif -- cgit v1.2.3 From 782bb1624b3ac9d340cb12f2ca52b549c64c23e5 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 25 Dec 2014 19:09:56 +0100 Subject: FormatConverter: disable SSE --- src/FormatConverter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/FormatConverter.cpp') diff --git a/src/FormatConverter.cpp b/src/FormatConverter.cpp index 8b510bd..766b6d8 100644 --- a/src/FormatConverter.cpp +++ b/src/FormatConverter.cpp @@ -54,7 +54,10 @@ int FormatConverter::process(Buffer* const dataIn, Buffer* dataOut) float* in = reinterpret_cast(dataIn->getData()); -#ifdef __SSE__ +#if 0 + // Disabled because subscripting a __m64 doesn't seem to work + // on all platforms. + /* _mm_cvtps_pi8 does: |<----------- 128 bits ------------>| -- cgit v1.2.3