/* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) Copyright (C) 2016 Matthias P. Braendli, matthias.braendli@mpb.li http://opendigitalradio.org */ /* 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 "SubchannelSource.h" #include "PcDebug.h" #include #include #include #include #define P1 0xc8888888 #define P2 0xc888c888 #define P3 0xc8c8c888 #define P4 0xc8c8c8c8 #define P5 0xccc8c8c8 #define P6 0xccc8ccc8 #define P7 0xccccccc8 #define P8 0xcccccccc #define P9 0xeccccccc #define P10 0xeccceccc #define P11 0xecececcc #define P12 0xecececec #define P13 0xeeececec #define P14 0xeeeceeec #define P15 0xeeeeeeec #define P16 0xeeeeeeee #define P17 0xfeeeeeee #define P18 0xfeeefeee #define P19 0xfefefeee #define P20 0xfefefefe #define P21 0xfffefefe #define P22 0xfffefffe #define P23 0xfffffffe #define P24 0xffffffff const std::vector& SubchannelSource::get_rules() const { return d_puncturing_rules; } SubchannelSource::SubchannelSource( uint8_t sad, uint16_t stl, uint8_t tpl ) : ModInput(), d_start_address(sad), d_framesize(stl * 8), d_protection(tpl) { PDEBUG("SubchannelSource::SubchannelSource(...) @ %p\n", this); PDEBUG(" Start address: %zu\n", d_start_address); PDEBUG(" Framesize: %zu\n", d_framesize); PDEBUG(" Protection: %zu\n", d_protection); if (protectionForm()) { if (protectionOption() == 0) { switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back( ((6 * bitrate() / 8) - 3) * 16, P24); d_puncturing_rules.emplace_back(3 * 16, P23); break; case 2: if (bitrate() == 8) { d_puncturing_rules.emplace_back(5 * 16, P13); d_puncturing_rules.emplace_back(1 * 16, P12); } else { d_puncturing_rules.emplace_back( ((2 * bitrate() / 8) - 3) * 16, P14); d_puncturing_rules.emplace_back( ((4 * bitrate() / 8) + 3) * 16, P13); } break; case 3: d_puncturing_rules.emplace_back( ((6 * bitrate() / 8) - 3) * 16, P8); d_puncturing_rules.emplace_back(3 * 16, P7); break; case 4: d_puncturing_rules.emplace_back( ((4 * bitrate() / 8) - 3) * 16, P3); d_puncturing_rules.emplace_back( ((2 * bitrate() / 8) + 3) * 16, P2); break; default: fprintf(stderr, "Protection form(%zu), option(%zu) and level(%zu)\n", protectionForm(), protectionOption(), protectionLevel()); fprintf(stderr, "Subchannel TPL: 0x%x (%u)\n", tpl, tpl); throw std::runtime_error("SubchannelSource::SubchannelSource " "unknown protection level!"); } } else if (protectionOption() == 1) { switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back( ((24 * bitrate() / 32) - 3) * 16, P10); d_puncturing_rules.emplace_back( 3 * 16, P9); break; case 2: d_puncturing_rules.emplace_back( ((24 * bitrate() / 32) - 3) * 16, P6); d_puncturing_rules.emplace_back( 3 * 16, P5); break; case 3: d_puncturing_rules.emplace_back( ((24 * bitrate() / 32) - 3) * 16, P4); d_puncturing_rules.emplace_back( 3 * 16, P3); break; case 4: d_puncturing_rules.emplace_back( ((24 * bitrate() / 32) - 3) * 16, P2); d_puncturing_rules.emplace_back( 3 * 16, P1); break; default: fprintf(stderr, "Protection form(%zu), option(%zu) and level(%zu)\n", protectionForm(), protectionOption(), protectionLevel()); fprintf(stderr, "Subchannel TPL: 0x%x (%u)\n", tpl, tpl); throw std::runtime_error("SubchannelSource::SubchannelSource " "unknown protection level!"); } } else { fprintf(stderr, "Protection form(%zu), option(%zu) and level(%zu)\n", protectionForm(), protectionOption(), protectionLevel()); fprintf(stderr, "Subchannel TPL: 0x%x (%u)\n", tpl, tpl); throw std::runtime_error("SubchannelSource::SubchannelSource " "unknown protection option!"); } } else { bool error = false; switch (bitrate()) { case 32: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(3 * 16, P24); d_puncturing_rules.emplace_back(5 * 16, P17); d_puncturing_rules.emplace_back(13 * 16, P12); d_puncturing_rules.emplace_back(3 * 16, P17); break; case 2: d_puncturing_rules.emplace_back(3 * 16, P22); d_puncturing_rules.emplace_back(4 * 16, P13); d_puncturing_rules.emplace_back(14 * 16, P8 ); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(3 * 16, P15); d_puncturing_rules.emplace_back(4 * 16, P9 ); d_puncturing_rules.emplace_back(14 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P8 ); break; case 4: d_puncturing_rules.emplace_back(3 * 16, P11); d_puncturing_rules.emplace_back(3 * 16, P6 ); d_puncturing_rules.emplace_back(18 * 16, P5 ); break; case 5: d_puncturing_rules.emplace_back(3 * 16, P5 ); d_puncturing_rules.emplace_back(4 * 16, P3 ); d_puncturing_rules.emplace_back(17 * 16, P2 ); break; default: error = true; } break; case 48: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(3 * 16, P24); d_puncturing_rules.emplace_back(5 * 16, P18); d_puncturing_rules.emplace_back(25 * 16, P13); d_puncturing_rules.emplace_back(3 * 16, P18); break; case 2: d_puncturing_rules.emplace_back(3 * 16, P24); d_puncturing_rules.emplace_back(4 * 16, P14); d_puncturing_rules.emplace_back(26 * 16, P8 ); d_puncturing_rules.emplace_back(3 * 16, P15); break; case 3: d_puncturing_rules.emplace_back(3 * 16, P15); d_puncturing_rules.emplace_back(4 * 16, P10); d_puncturing_rules.emplace_back(26 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P9 ); break; case 4: d_puncturing_rules.emplace_back(3 * 16, P9 ); d_puncturing_rules.emplace_back(4 * 16, P6 ); d_puncturing_rules.emplace_back(26 * 16, P4 ); d_puncturing_rules.emplace_back(3 * 16, P6 ); break; case 5: d_puncturing_rules.emplace_back(4 * 16, P5 ); d_puncturing_rules.emplace_back(3 * 16, P4 ); d_puncturing_rules.emplace_back(26 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: error = true; } break; case 56: switch (protectionLevel()) { case 2: d_puncturing_rules.emplace_back(6 * 16, P23); d_puncturing_rules.emplace_back(10 * 16, P13); d_puncturing_rules.emplace_back(23 * 16, P8 ); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(6 * 16, P16); d_puncturing_rules.emplace_back(12 * 16, P7 ); d_puncturing_rules.emplace_back(21 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P9 ); break; case 4: d_puncturing_rules.emplace_back(6 * 16, P9 ); d_puncturing_rules.emplace_back(10 * 16, P6 ); d_puncturing_rules.emplace_back(23 * 16, P4 ); d_puncturing_rules.emplace_back(3 * 16, P5 ); break; case 5: d_puncturing_rules.emplace_back(6 * 16, P5 ); d_puncturing_rules.emplace_back(10 * 16, P4 ); d_puncturing_rules.emplace_back(23 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: error = true; } break; case 64: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(6 * 16, P24); d_puncturing_rules.emplace_back(11 * 16, P18); d_puncturing_rules.emplace_back(28 * 16, P12); d_puncturing_rules.emplace_back(3 * 16, P18); break; case 2: d_puncturing_rules.emplace_back(6 * 16, P23); d_puncturing_rules.emplace_back(10 * 16, P13); d_puncturing_rules.emplace_back(29 * 16, P8 ); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(6 * 16, P16); d_puncturing_rules.emplace_back(12 * 16, P8 ); d_puncturing_rules.emplace_back(27 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P9 ); break; case 4: d_puncturing_rules.emplace_back(6 * 16, P11); d_puncturing_rules.emplace_back(9 * 16, P6 ); d_puncturing_rules.emplace_back(33 * 16, P5 ); break; case 5: d_puncturing_rules.emplace_back(6 * 16, P5 ); d_puncturing_rules.emplace_back(9 * 16, P3 ); d_puncturing_rules.emplace_back(31 * 16, P2 ); d_puncturing_rules.emplace_back(2 * 16, P3 ); break; default: error = true; } break; case 80: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(6 * 16, P24); d_puncturing_rules.emplace_back(10 * 16, P17); d_puncturing_rules.emplace_back(41 * 16, P12); d_puncturing_rules.emplace_back(3 * 16, P18); break; case 2: d_puncturing_rules.emplace_back(6 * 16, P23); d_puncturing_rules.emplace_back(10 * 16, P13); d_puncturing_rules.emplace_back(41 * 16, P8 ); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(6 * 16, P16); d_puncturing_rules.emplace_back(11 * 16, P8 ); d_puncturing_rules.emplace_back(40 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P7 ); break; case 4: d_puncturing_rules.emplace_back(6 * 16, P11); d_puncturing_rules.emplace_back(10 * 16, P6 ); d_puncturing_rules.emplace_back(41 * 16, P5 ); d_puncturing_rules.emplace_back(3 * 16, P6 ); break; case 5: d_puncturing_rules.emplace_back(6 * 16, P6 ); d_puncturing_rules.emplace_back(10 * 16, P3 ); d_puncturing_rules.emplace_back(41 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P3 ); break; default: error = true; } break; case 96: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(6 * 16, P24); d_puncturing_rules.emplace_back(13 * 16, P18); d_puncturing_rules.emplace_back(50 * 16, P13); d_puncturing_rules.emplace_back(3 * 16, P19); break; case 2: d_puncturing_rules.emplace_back(6 * 16, P22); d_puncturing_rules.emplace_back(10 * 16, P12); d_puncturing_rules.emplace_back(53 * 16, P9 ); d_puncturing_rules.emplace_back(3 * 16, P12); break; case 3: d_puncturing_rules.emplace_back(6 * 16, P16); d_puncturing_rules.emplace_back(12 * 16, P9 ); d_puncturing_rules.emplace_back(51 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 4: d_puncturing_rules.emplace_back(7 * 16, P9 ); d_puncturing_rules.emplace_back(10 * 16, P6 ); d_puncturing_rules.emplace_back(52 * 16, P4 ); d_puncturing_rules.emplace_back(3 * 16, P6 ); break; case 5: d_puncturing_rules.emplace_back(7 * 16, P5 ); d_puncturing_rules.emplace_back(9 * 16, P4 ); d_puncturing_rules.emplace_back(53 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: error = true; } break; case 112: switch (protectionLevel()) { case 2: d_puncturing_rules.emplace_back(11 * 16, P23); d_puncturing_rules.emplace_back(21 * 16, P12); d_puncturing_rules.emplace_back(49 * 16, P9 ); d_puncturing_rules.emplace_back(3 * 16, P14); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(23 * 16, P8 ); d_puncturing_rules.emplace_back(47 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P9 ); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P9 ); d_puncturing_rules.emplace_back(21 * 16, P6 ); d_puncturing_rules.emplace_back(49 * 16, P4 ); d_puncturing_rules.emplace_back(3 * 16, P8 ); break; case 5: d_puncturing_rules.emplace_back(14 * 16, P5 ); d_puncturing_rules.emplace_back(17 * 16, P4 ); d_puncturing_rules.emplace_back(50 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P5 ); break; default: error = true; } break; case 128: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(20 * 16, P17); d_puncturing_rules.emplace_back(62 * 16, P13); d_puncturing_rules.emplace_back(3 * 16, P19); break; case 2: d_puncturing_rules.emplace_back(11 * 16, P22); d_puncturing_rules.emplace_back(21 * 16, P12); d_puncturing_rules.emplace_back(61 * 16, P9 ); d_puncturing_rules.emplace_back(3 * 16, P14); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(22 * 16, P9 ); d_puncturing_rules.emplace_back(60 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P11); d_puncturing_rules.emplace_back(21 * 16, P6 ); d_puncturing_rules.emplace_back(61 * 16, P5 ); d_puncturing_rules.emplace_back(3 * 16, P7 ); break; case 5: d_puncturing_rules.emplace_back(12 * 16, P5 ); d_puncturing_rules.emplace_back(19 * 16, P3 ); d_puncturing_rules.emplace_back(62 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: error = true; } break; case 160: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(22 * 16, P18); d_puncturing_rules.emplace_back(84 * 16, P12); d_puncturing_rules.emplace_back(3 * 16, P19); break; case 2: d_puncturing_rules.emplace_back(11 * 16, P22); d_puncturing_rules.emplace_back(21 * 16, P11); d_puncturing_rules.emplace_back(85 * 16, P9 ); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(24 * 16, P8 ); d_puncturing_rules.emplace_back(82 * 16, P6 ); d_puncturing_rules.emplace_back(3 * 16, P11); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P11); d_puncturing_rules.emplace_back(23 * 16, P6 ); d_puncturing_rules.emplace_back(83 * 16, P5 ); d_puncturing_rules.emplace_back(3 * 16, P9 ); break; case 5: d_puncturing_rules.emplace_back(11 * 16, P5 ); d_puncturing_rules.emplace_back(19 * 16, P4 ); d_puncturing_rules.emplace_back(87 * 16, P2 ); d_puncturing_rules.emplace_back(3 * 16, P4 ); break; default: error = true; } break; case 192: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(21 * 16, P20); d_puncturing_rules.emplace_back(109 * 16, P13); d_puncturing_rules.emplace_back(3 * 16, P24); break; case 2: d_puncturing_rules.emplace_back(11 * 16, P22); d_puncturing_rules.emplace_back(20 * 16, P13); d_puncturing_rules.emplace_back(110 * 16, P9); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(24 * 16, P10); d_puncturing_rules.emplace_back(106 * 16, P6); d_puncturing_rules.emplace_back(3 * 16, P11); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P10); d_puncturing_rules.emplace_back(22 * 16, P6); d_puncturing_rules.emplace_back(108 * 16, P4); d_puncturing_rules.emplace_back(3 * 16, P9); break; case 5: d_puncturing_rules.emplace_back(11 * 16, P6); d_puncturing_rules.emplace_back(20 * 16, P4); d_puncturing_rules.emplace_back(110 * 16, P2); d_puncturing_rules.emplace_back(3 * 16, P5); break; default: error = true; } break; case 224: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(24 * 16, P20); d_puncturing_rules.emplace_back(130 * 16, P12); d_puncturing_rules.emplace_back(3 * 16, P20); break; case 2: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(22 * 16, P16); d_puncturing_rules.emplace_back(132 * 16, P10); d_puncturing_rules.emplace_back(3 * 16, P15); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(20 * 16, P10); d_puncturing_rules.emplace_back(134 * 16, P7); d_puncturing_rules.emplace_back(3 * 16, P9); break; case 4: d_puncturing_rules.emplace_back(12 * 16, P12); d_puncturing_rules.emplace_back(26 * 16, P8); d_puncturing_rules.emplace_back(127 * 16, P4); d_puncturing_rules.emplace_back(3 * 16, P11); break; case 5: d_puncturing_rules.emplace_back(12 * 16, P8); d_puncturing_rules.emplace_back(22 * 16, P6); d_puncturing_rules.emplace_back(131 * 16, P2); d_puncturing_rules.emplace_back(3 * 16, P6); break; default: error = true; } break; case 256: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(26 * 16, P19); d_puncturing_rules.emplace_back(152 * 16, P14); d_puncturing_rules.emplace_back(3 * 16, P18); break; case 2: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(22 * 16, P14); d_puncturing_rules.emplace_back(156 * 16, P10); d_puncturing_rules.emplace_back(3 * 16, P13); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(27 * 16, P10); d_puncturing_rules.emplace_back(151 * 16, P7); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P12); d_puncturing_rules.emplace_back(24 * 16, P9); d_puncturing_rules.emplace_back(154 * 16, P5); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 5: d_puncturing_rules.emplace_back(11 * 16, P6); d_puncturing_rules.emplace_back(24 * 16, P5); d_puncturing_rules.emplace_back(154 * 16, P2); d_puncturing_rules.emplace_back(3 * 16, P5); break; default: error = true; } break; case 320: switch (protectionLevel()) { case 2: d_puncturing_rules.emplace_back(11 * 16, P24); d_puncturing_rules.emplace_back(26 * 16, P17); d_puncturing_rules.emplace_back(200 * 16, P9 ); d_puncturing_rules.emplace_back(3 * 16, P17); break; case 4: d_puncturing_rules.emplace_back(11 * 16, P13); d_puncturing_rules.emplace_back(25 * 16, P9); d_puncturing_rules.emplace_back(201 * 16, P5); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 5: d_puncturing_rules.emplace_back(11 * 16, P8); d_puncturing_rules.emplace_back(26 * 16, P5); d_puncturing_rules.emplace_back(200 * 16, P2); d_puncturing_rules.emplace_back(3 * 16, P6); break; default: error = true; } break; case 384: switch (protectionLevel()) { case 1: d_puncturing_rules.emplace_back(12 * 16, P24); d_puncturing_rules.emplace_back(28 * 16, P20); d_puncturing_rules.emplace_back(245 * 16, P14); d_puncturing_rules.emplace_back(3 * 16, P23); break; case 3: d_puncturing_rules.emplace_back(11 * 16, P16); d_puncturing_rules.emplace_back(24 * 16, P9); d_puncturing_rules.emplace_back(250 * 16, P7); d_puncturing_rules.emplace_back(3 * 16, P10); break; case 5: d_puncturing_rules.emplace_back(11 * 16, P8); d_puncturing_rules.emplace_back(27 * 16, P6); d_puncturing_rules.emplace_back(247 * 16, P2); d_puncturing_rules.emplace_back(3 * 16, P7); break; default: error = true; } break; default: error = true; } if (error) { fprintf(stderr, " Protection: UEP-%zu @ %zukb/s\n", protectionLevel(), bitrate()); throw std::runtime_error("SubchannelSource::SubchannelSource " "UEP puncturing rules does not exist!"); } } } size_t SubchannelSource::startAddress() const { return d_start_address; } size_t SubchannelSource::framesize() const { return d_framesize; } size_t SubchannelSource::framesizeCu() const { size_t framesizeCu = 0; if (protectionForm()) { // Long form if ((d_protection >> 2) & 0x07) { // Option switch (d_protection & 0x03) { case 0: framesizeCu = (bitrate() / 32) * 27; break; case 1: framesizeCu = (bitrate() / 32) * 21; break; case 2: framesizeCu = (bitrate() / 32) * 18; break; case 3: framesizeCu = (bitrate() / 32) * 15; break; default: framesizeCu = 0xffff; break; } } else { switch (d_protection & 0x03) { case 0: framesizeCu = (bitrate() / 8) * 12; break; case 1: framesizeCu = (bitrate() / 8) * 8; break; case 2: framesizeCu = (bitrate() / 8) * 6; break; case 3: framesizeCu = (bitrate() / 8) * 4; break; default: framesizeCu = 0xffff; break; } } } else { // Short form switch (bitrate()) { case 32: switch (protectionLevel()) { case 1: framesizeCu = 35; break; case 2: framesizeCu = 29; break; case 3: framesizeCu = 24; break; case 4: framesizeCu = 21; break; case 5: framesizeCu = 16; break; default: framesizeCu = 0xffff; break; } break; case 48: switch (protectionLevel()) { case 1: framesizeCu = 52; break; case 2: framesizeCu = 42; break; case 3: framesizeCu = 35; break; case 4: framesizeCu = 29; break; case 5: framesizeCu = 24; break; default: framesizeCu = 0xffff; break; } break; case 56: switch (protectionLevel()) { case 2: framesizeCu = 52; break; case 3: framesizeCu = 42; break; case 4: framesizeCu = 35; break; case 5: framesizeCu = 29; break; default: framesizeCu = 0xffff; break; } break; case 64: switch (protectionLevel()) { case 1: framesizeCu = 70; break; case 2: framesizeCu = 58; break; case 3: framesizeCu = 48; break; case 4: framesizeCu = 42; break; case 5: framesizeCu = 32; break; default: framesizeCu = 0xffff; break; } break; case 80: switch (protectionLevel()) { case 1: framesizeCu = 84; break; case 2: framesizeCu = 70; break; case 3: framesizeCu = 58; break; case 4: framesizeCu = 52; break; case 5: framesizeCu = 40; break; default: framesizeCu = 0xffff; break; } break; case 96: switch (protectionLevel()) { case 1: framesizeCu = 104; break; case 2: framesizeCu = 84; break; case 3: framesizeCu = 70; break; case 4: framesizeCu = 58; break; case 5: framesizeCu = 48; break; default: framesizeCu = 0xffff; break; } break; case 112: switch (protectionLevel()) { case 2: framesizeCu = 104; break; case 3: framesizeCu = 84; break; case 4: framesizeCu = 70; break; case 5: framesizeCu = 58; break; default: framesizeCu = 0xffff; break; } break; case 128: switch (protectionLevel()) { case 1: framesizeCu = 140; break; case 2: framesizeCu = 116; break; case 3: framesizeCu = 96; break; case 4: framesizeCu = 84; break; case 5: framesizeCu = 64; break; default: framesizeCu = 0xffff; break; } break; case 160: switch (protectionLevel()) { case 1: framesizeCu = 168; break; case 2: framesizeCu = 140; break; case 3: framesizeCu = 116; break; case 4: framesizeCu = 104; break; case 5: framesizeCu = 80; break; default: framesizeCu = 0xffff; break; } break; case 192: switch (protectionLevel()) { case 1: framesizeCu = 208; break; case 2: framesizeCu = 168; break; case 3: framesizeCu = 140; break; case 4: framesizeCu = 116; break; case 5: framesizeCu = 96; break; default: framesizeCu = 0xffff; break; } break; case 224: switch (protectionLevel()) { case 1: framesizeCu = 232; break; case 2: framesizeCu = 208; break; case 3: framesizeCu = 168; break; case 4: framesizeCu = 140; break; case 5: framesizeCu = 116; break; default: framesizeCu = 0xffff; break; } break; case 256: switch (protectionLevel()) { case 1: framesizeCu = 280; break; case 2: framesizeCu = 232; break; case 3: framesizeCu = 192; break; case 4: framesizeCu = 168; break; case 5: framesizeCu = 128; break; default: framesizeCu = 0xffff; break; } break; case 320: switch (protectionLevel()) { case 2: framesizeCu = 280; break; case 4: framesizeCu = 208; break; case 5: framesizeCu = 160; break; default: framesizeCu = 0xffff; break; } break; case 384: switch (protectionLevel()) { case 1: framesizeCu = 416; break; case 3: framesizeCu = 280; break; case 5: framesizeCu = 192; break; default: framesizeCu = 0xffff; break; } break; default: framesizeCu = 0xffff; break; } } if (framesizeCu == 0) { fprintf(stderr, " Protection %zu @ %zu kb/s\n", protectionLevel(), bitrate()); throw std::runtime_error("SubchannelSource::framesizeCu protection " "not yet coded!"); } if (framesizeCu == 0xffff) { fprintf(stderr, " Protection %zu @ %zu kb/s\n", protectionLevel(), bitrate()); throw std::runtime_error("SubchannelSource::framesizeCu invalid " "protection!"); } return framesizeCu; } size_t SubchannelSource::bitrate() const { return d_framesize / 3; } size_t SubchannelSource::protection() const { return d_protection; } size_t SubchannelSource::protectionForm() const { return (d_protection >> 5) & 1; } size_t SubchannelSource::protectionLevel() const { if (protectionForm()) { // Long form return (d_protection & 0x3) + 1; } // Short form return (d_protection & 0x7) + 1; } size_t SubchannelSource::protectionOption() const { if (protectionForm()) { // Long form return (d_protection >> 2) & 0x7; } // Short form return 0; } void SubchannelSource::loadSubchannelData(const Buffer& data) { d_buffer = data; } int SubchannelSource::process(Buffer* outputData) { PDEBUG("SubchannelSource::process(outputData: %p, outputSize: %zu)\n", outputData, outputData->getLength()); if (d_buffer.getLength() != d_framesize) { throw std::runtime_error( "ERROR: Subchannel::process: d_buffer != d_framesize: " + std::to_string(d_buffer.getLength()) + " != " + std::to_string(d_framesize)); } *outputData = d_buffer; return outputData->getLength(); }