1 #ifndef __SDR_AUTOCAST_HH__ 2 #define __SDR_AUTOCAST_HH__ 3 4 #include "node.hh" 5 #include "traits.hh" 6 #include "logger.hh" 7 8 namespace sdr { 9 10 /** This class performs some automatic casts to a certain buffer type if possible specified by 11 * the template argument. Currently only integer casts are supported. */ 12 template <class Scalar> 13 class AutoCast: public SinkBase, public Source 14 { 15 public: 16 /** Constructor. */ AutoCast()17 AutoCast() 18 : SinkBase(), Source(), _buffer(), _cast(0) 19 { 20 // pass... 21 } 22 23 /** Configures the auto cast node. */ config(const Config & src_cfg)24 virtual void config(const Config &src_cfg) { 25 // Requires buffer size, sample rate and type: 26 if ((Config::Type_UNDEFINED==src_cfg.type()) || (0==src_cfg.sampleRate()) || (0==src_cfg.bufferSize())) { return; } 27 28 // Check type cast combination 29 if (Config::Type_s8 == Traits<Scalar>::scalarId) { 30 switch (src_cfg.type()) { 31 case Config::Type_u8: 32 case Config::Type_s8: _cast = _identity; break; 33 case Config::Type_u16: 34 case Config::Type_s16: _cast = _int16_int8; break; 35 default: break; 36 } 37 } else if (Config::Type_cs8 == Traits<Scalar>::scalarId) { 38 switch (src_cfg.type()) { 39 case Config::Type_u8: _cast = _uint8_cint8; break; 40 case Config::Type_s8: _cast = _int8_cint8; break; 41 case Config::Type_cu8: _cast = _cuint8_cint8; break; 42 case Config::Type_cs8: _cast = _identity; break; 43 case Config::Type_u16: 44 case Config::Type_s16: _cast = _int16_cint8; break; 45 default: break; 46 } 47 } else if (Config::Type_s16 == Traits<Scalar>::scalarId) { 48 switch (src_cfg.type()) { 49 case Config::Type_u8: 50 case Config::Type_s8: _cast = _int8_int16; break; 51 case Config::Type_u16: 52 case Config::Type_s16: _cast = _identity; break; 53 default: break; 54 } 55 } else if (Config::Type_cs16 == Traits<Scalar>::scalarId) { 56 switch (src_cfg.type()) { 57 case Config::Type_u8: _cast = _uint8_cint16; break; 58 case Config::Type_s8: _cast = _int8_cint16; break; 59 case Config::Type_cu8: _cast = _cuint8_cint16; break; 60 case Config::Type_cs8: _cast = _cint8_cint16; break; 61 case Config::Type_u16: _cast = _uint16_cint16; break; 62 case Config::Type_s16: _cast = _int16_cint16; break; 63 case Config::Type_cu16: 64 case Config::Type_cs16: _cast = _identity; break; 65 default: break; 66 } 67 } 68 69 // Check if there exists a cast to the required type 70 if (0 == _cast) { 71 ConfigError err; 72 err << "AutoCast: Can not cast from type " << src_cfg.type() << " to " << Traits<Scalar>::scalarId; 73 throw err; 74 } 75 76 // Allocate buffer 77 _buffer = Buffer<Scalar>(src_cfg.bufferSize()); 78 79 LogMessage msg(LOG_DEBUG); 80 msg << "Configure AutoCast node:" << std::endl 81 << " input type: " << src_cfg.type() << std::endl 82 << " output type: " << Traits<Scalar>::scalarId; 83 Logger::get().log(msg); 84 85 // Propergate config 86 this->setConfig(Config(Config::typeId<Scalar>(), src_cfg.sampleRate(), src_cfg.bufferSize(), 1)); 87 } 88 handleBuffer(const RawBuffer & buffer,bool allow_overwrite)89 virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite) { 90 // If no conversion is selected 91 if (0 == _cast) { return; } 92 // If the identity conversion is selected -> forward buffer 93 if (_identity == _cast) { this->send(buffer, allow_overwrite); return; } 94 // Otherwise cast 95 size_t bytes = _cast(buffer, _buffer); 96 this->send(RawBuffer(_buffer, 0, bytes), false); 97 } 98 99 100 protected: 101 /** Output buffer. */ 102 Buffer<Scalar> _buffer; 103 /** Cast function. */ 104 size_t (*_cast)(const RawBuffer &in, const RawBuffer &out); 105 106 protected: 107 /** Performs no cast at all. */ _identity(const RawBuffer & in,const RawBuffer & out)108 static size_t _identity(const RawBuffer &in, const RawBuffer &out) { 109 memcpy(out.ptr(), in.data(), in.bytesLen()); 110 return in.bytesLen(); 111 } 112 113 /** int16 -> int8 */ _int16_int8(const RawBuffer & in,const RawBuffer & out)114 static size_t _int16_int8(const RawBuffer &in, const RawBuffer &out) { 115 size_t N = in.bytesLen()/2; 116 for (size_t i=0; i<N; i++) { 117 reinterpret_cast<int8_t *>(out.data())[i] = reinterpret_cast<int16_t *>(in.data())[i]>>8; 118 } 119 return N; 120 } 121 122 /** uint8 -> complex int8. */ _uint8_cint8(const RawBuffer & in,const RawBuffer & out)123 static size_t _uint8_cint8(const RawBuffer &in, const RawBuffer &out) { 124 size_t N = in.bytesLen(); 125 uint8_t *values = reinterpret_cast<uint8_t *>(in.data()); 126 for (size_t i=0; i<N; i++) { 127 reinterpret_cast<std::complex<int8_t> *>(out.data())[i] = 128 (int16_t(values[i])-127); 129 } 130 return 2*N; 131 } 132 133 /** int8 -> complex int8. */ _int8_cint8(const RawBuffer & in,const RawBuffer & out)134 static size_t _int8_cint8(const RawBuffer &in, const RawBuffer &out) { 135 size_t N = in.bytesLen(); 136 for (size_t i=0; i<N; i++) { 137 reinterpret_cast<std::complex<int8_t> *>(out.data())[i] = reinterpret_cast<int8_t *>(in.data())[i]; 138 } 139 return 2*N; 140 } 141 142 /** std::complex<uint8_t> -> std::complex<int8_t>. */ _cuint8_cint8(const RawBuffer & in,const RawBuffer & out)143 static size_t _cuint8_cint8(const RawBuffer &in, const RawBuffer &out) { 144 size_t N = in.bytesLen()/2; 145 std::complex<uint8_t> *values = reinterpret_cast<std::complex<uint8_t> *>(in.data()); 146 for (size_t i=0; i<N; i++) { 147 reinterpret_cast<std::complex<int8_t> *>(out.data())[i] = 148 std::complex<int8_t>(int16_t(values[i].real())-127, int16_t(values[i].imag())-127); 149 } 150 return 2*N; 151 } 152 153 /** int16 -> complex int 8. */ _int16_cint8(const RawBuffer & in,const RawBuffer & out)154 static size_t _int16_cint8(const RawBuffer &in, const RawBuffer &out) { 155 size_t N = in.bytesLen()/2; 156 for (size_t i=0; i<N; i++) { 157 reinterpret_cast<std::complex<int8_t> *>(out.data())[i] = reinterpret_cast<int16_t *>(in.data())[i]>>8; 158 } 159 return 2*N; 160 } 161 162 /** complex int16 -> complex int 8. */ _cint16_cint8(const RawBuffer & in,const RawBuffer & out)163 static size_t _cint16_cint8(const RawBuffer &in, const RawBuffer &out) { 164 size_t N = in.bytesLen()/4; 165 std::complex<int16_t> *values = reinterpret_cast<std::complex<int16_t> *>(in.data()); 166 for (size_t i=0; i<N; i++) { 167 reinterpret_cast<std::complex<int8_t> *>(out.data())[i] = std::complex<int8_t>(values[i].real()>>8, values[i].imag()>>8); 168 } 169 return 2*N; 170 } 171 172 /** int8 -> int16. */ _int8_int16(const RawBuffer & in,const RawBuffer & out)173 static size_t _int8_int16(const RawBuffer &in, const RawBuffer &out) { 174 size_t N = in.bytesLen(); 175 int8_t *values = reinterpret_cast<int8_t *>(in.data()); 176 for (size_t i=0; i<N; i++) { 177 reinterpret_cast<int16_t *>(out.data())[i] = int16_t(values[i])<<8; 178 } 179 return 2*N; 180 } 181 182 /** unsinged int8 -> complex int16. */ _uint8_cint16(const RawBuffer & in,const RawBuffer & out)183 static size_t _uint8_cint16(const RawBuffer &in, const RawBuffer &out) { 184 size_t N = in.bytesLen(); 185 uint8_t *values = reinterpret_cast<uint8_t *>(in.data()); 186 for (size_t i=0; i<N; i++) { 187 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] 188 = std::complex<int16_t>((int16_t(values[i])-127)<<8); 189 } 190 return 4*N; 191 } 192 193 /** int8 -> complex int16. */ _int8_cint16(const RawBuffer & in,const RawBuffer & out)194 static size_t _int8_cint16(const RawBuffer &in, const RawBuffer &out) { 195 size_t N = in.bytesLen(); 196 int8_t *values = reinterpret_cast<int8_t *>(in.data()); 197 for (size_t i=0; i<N; i++) { 198 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] 199 = std::complex<int16_t>(int16_t(values[i])*(1<<8)); 200 } 201 return 4*N; 202 } 203 204 /** complex unsigned int8 -> complex int16. */ _cuint8_cint16(const RawBuffer & in,const RawBuffer & out)205 static size_t _cuint8_cint16(const RawBuffer &in, const RawBuffer &out) { 206 size_t N = in.bytesLen()/2; 207 std::complex<uint8_t> *values = reinterpret_cast<std::complex<uint8_t> *>(in.data()); 208 for (size_t i=0; i<N; i++) { 209 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] = 210 std::complex<int16_t>((int16_t(values[i].real())-127)*(1<<8), 211 (int16_t(values[i].imag())-127)*(1<<8)); 212 } 213 return 4*N; 214 } 215 216 /** complex int8 -> complex int16. */ _cint8_cint16(const RawBuffer & in,const RawBuffer & out)217 static size_t _cint8_cint16(const RawBuffer &in, const RawBuffer &out) { 218 size_t N = in.bytesLen()/2; 219 std::complex<int8_t> *values = reinterpret_cast<std::complex<int8_t> *>(in.data()); 220 for (size_t i=0; i<N; i++) { 221 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] = 222 std::complex<int16_t>(int16_t(values[i].real())*(1<<8), 223 int16_t(values[i].imag())*(1<<8)); 224 } 225 return 4*N; 226 } 227 228 /** uint16 -> complex int16. */ _uint16_cint16(const RawBuffer & in,const RawBuffer & out)229 static size_t _uint16_cint16(const RawBuffer &in, const RawBuffer &out) { 230 size_t N = in.bytesLen()/2; 231 uint16_t *values = reinterpret_cast<uint16_t *>(in.data()); 232 for (size_t i=0; i<N; i++) { 233 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] 234 = std::complex<int16_t>(int32_t(values[i])-(1<<15)); 235 } 236 return 4*N; 237 } 238 239 /** int16 -> complex int16. */ _int16_cint16(const RawBuffer & in,const RawBuffer & out)240 static size_t _int16_cint16(const RawBuffer &in, const RawBuffer &out) { 241 size_t N = in.bytesLen()/2; 242 int16_t *values = reinterpret_cast<int16_t *>(in.data()); 243 for (size_t i=0; i<N; i++) { 244 reinterpret_cast<std::complex<int16_t> *>(out.data())[i] = std::complex<int16_t>(values[i]); 245 } 246 return 4*N; 247 } 248 }; 249 250 251 } 252 #endif // __SDR_AUTOCAST_HH__ 253