aboutsummaryrefslogtreecommitdiffstats
path: root/dabplussnoop.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2016-09-02 17:43:32 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2016-09-07 21:20:24 +0200
commit4809f3c042a99a639542b1e6cd22657871113260 (patch)
treedc0ec0f256eaceb79d63daa09591d4a6ef08cb73 /dabplussnoop.cpp
parent5542c8ecff635f9abc05b6b2ff255db02c2c9c46 (diff)
downloadetisnoop-4809f3c042a99a639542b1e6cd22657871113260.tar.gz
etisnoop-4809f3c042a99a639542b1e6cd22657871113260.tar.bz2
etisnoop-4809f3c042a99a639542b1e6cd22657871113260.zip
Move all sources to src/
Diffstat (limited to 'dabplussnoop.cpp')
-rw-r--r--dabplussnoop.cpp324
1 files changed, 0 insertions, 324 deletions
diff --git a/dabplussnoop.cpp b/dabplussnoop.cpp
deleted file mode 100644
index cd91d49..0000000
--- a/dabplussnoop.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- Copyright (C) 2014, 2015 Matthias P. Braendli (http://www.opendigitalradio.org)
-
- This program 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.
-
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- dabplussnoop.cpp
- Parse DAB+ frames from a ETI file
-
- Authors:
- Matthias P. Braendli <matthias@mpb.li>
- Mathias Coinchon <coinchon@yahoo.com>
-*/
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <cassert>
-#include <sstream>
-#include <algorithm>
-#include <vector>
-#include "dabplussnoop.hpp"
-extern "C" {
-#include "firecode.h"
-#include "lib_crc.h"
-}
-#include "faad_decoder.hpp"
-#include "rsdecoder.hpp"
-
-#define DPS_INDENT "\t\t"
-#define DPS_PREFIX "DAB+ decode:"
-
-#define DPS_DEBUG 0
-
-using namespace std;
-
-void DabPlusSnoop::push(uint8_t* streamdata, size_t streamsize)
-{
- // Try to decode audio
- size_t original_size = m_data.size();
- m_data.resize(original_size + streamsize);
- memcpy(&m_data[original_size], streamdata, streamsize);
-
- if (seek_valid_firecode()) {
- // m_data now points to a valid header
-
- if (decode()) {
-
- // First dump to subchannel file (superframe+parity word)
- if (m_raw_data_stream_fd == NULL) {
- stringstream dump_filename;
- dump_filename << "stream-" << m_index << ".msc";
-
- m_raw_data_stream_fd = fopen(dump_filename.str().c_str(), "w");
-
- if (m_raw_data_stream_fd == NULL) {
- perror("File open failed");
- }
- }
-
- fwrite(&m_data[0], m_subchannel_index, 120, m_raw_data_stream_fd);
-
- // We have been able to decode the AUs, now flush vector
- m_data.clear();
- }
- }
-}
-
-// Idea and some code taken from Xpadxpert
-bool DabPlusSnoop::seek_valid_firecode()
-{
- if (m_data.size() < 10) {
- // Not enough data
- return false;
- }
-
- bool crc_ok = false;
- size_t i;
-
- for (i = 0; i < m_data.size() - 10; i++) {
- uint8_t* b = &m_data[i];
-
- // the three bytes after the firecode must not be zero
- // (simple plausibility check to avoid sync in zero byte region)
- if (b[3] != 0x00 || (b[4] & 0xF0) != 0x00) {
- uint16_t header_firecode = (b[0] << 8) | b[1];
- uint16_t calculated_firecode = firecode_crc(b+2, 9);
-
- if (header_firecode == calculated_firecode) {
- crc_ok = true;
- break;
- }
- }
- }
-
- if (crc_ok) {
-#if DPS_DEBUG
- printf(DPS_PREFIX " Found valid FireCode at %zu\n", i);
-#endif
- //erase elements before the header
- m_data.erase(m_data.begin(), m_data.begin() + i);
- return true;
- }
- else {
-#if DPS_DEBUG
- printf(DPS_PREFIX " No valid FireCode found\n");
-#endif
-
- m_data.clear();
- return false;
- }
-}
-
-bool DabPlusSnoop::decode()
-{
-#if DPS_DEBUG
- printf(DPS_PREFIX " We have %zu bytes of data\n", m_data.size());
-#endif
-
- const size_t sf_len = m_subchannel_index * 120;
- if (m_subchannel_index && m_data.size() >= sf_len) {
- std::vector<uint8_t> b(sf_len);
- std::copy(m_data.begin(), m_data.begin() + sf_len, b.begin());
-
- RSDecoder rs_dec;
- int rs_errors = rs_dec.DecodeSuperframe(b, m_subchannel_index);
-
- if (rs_errors == -1) {
- return false;
- }
-
- // -- Parse he_aac_super_frame
- // ---- Parse he_aac_super_frame_header
- // ------ Parse firecode and audio params
- uint16_t header_firecode = (b[0] << 8) | b[1];
- uint8_t audio_params = b[2];
- int rfa = (audio_params & 0x80) ? true : false;
- m_dac_rate = (audio_params & 0x40) ? true : false;
- m_sbr_flag = (audio_params & 0x20) ? true : false;
- m_aac_channel_mode = (audio_params & 0x10) ? true : false;
- m_ps_flag = (audio_params & 0x08) ? true : false;
- m_mpeg_surround_config = (audio_params & 0x07);
-
- int num_aus;
- if (!m_dac_rate && m_sbr_flag) num_aus = 2;
- // AAC core sampling rate 16 kHz
- else if (m_dac_rate && m_sbr_flag) num_aus = 3;
- // AAC core sampling rate 24 kHz
- else if (!m_dac_rate && !m_sbr_flag) num_aus = 4;
- // AAC core sampling rate 32 kHz
- else if (m_dac_rate && !m_sbr_flag) num_aus = 6;
- // AAC core sampling rate 48 kHz
-
-#if DPS_DEBUG
- printf( DPS_INDENT DPS_PREFIX "\n"
- DPS_INDENT "\tfirecode 0x%x\n"
- DPS_INDENT "\trfa %d\n"
- DPS_INDENT "\tdac_rate %d\n"
- DPS_INDENT "\tsbr_flag %d\n"
- DPS_INDENT "\taac_channel_mode %d\n"
- DPS_INDENT "\tps_flag %d\n"
- DPS_INDENT "\tmpeg_surround_config %d\n"
- DPS_INDENT "\tnum_aus %d\n",
- header_firecode, rfa, m_dac_rate, m_sbr_flag,
- m_aac_channel_mode, m_ps_flag, m_mpeg_surround_config,
- num_aus);
-#else
- // Avoid "unused variable" warning
- (void)header_firecode;
- (void)rfa;
-#endif
-
-
- // ------ Parse au_start
- auto au_starts = b.begin() + 3;
-
- vector<uint8_t> au_start_nibbles(0);
-
- /* Each AU_START is encoded in three nibbles.
- * When we have n AUs, we have n-1 au_start values. */
- for (int i = 0; i < (num_aus-1)*3; i++) {
- if (i % 2 == 0) {
- char nibble = au_starts[i/2] >> 4;
-
- au_start_nibbles.push_back( nibble );
- }
- else {
- char nibble = au_starts[i/2] & 0x0F;
-
- au_start_nibbles.push_back( nibble );
- }
-
- }
-
-
- vector<int> au_start(num_aus);
-
- if (num_aus == 2)
- au_start[0] = 5;
- else if (num_aus == 3)
- au_start[0] = 6;
- else if (num_aus == 4)
- au_start[0] = 8;
- else if (num_aus == 6)
- au_start[0] = 11;
-
-
- int nib = 0;
- for (int au = 1; au < num_aus; au++) {
- au_start[au] = au_start_nibbles[nib] << 8 | \
- au_start_nibbles[nib+1] << 4 | \
- au_start_nibbles[nib+2];
-
- nib += 3;
- }
-
-#if DPS_DEBUG
- printf(DPS_INDENT DPS_PREFIX " AU start\n");
- for (int au = 0; au < num_aus; au++) {
- printf(DPS_INDENT "\tAU[%d] %d 0x%x\n", au,
- au_start[au],
- au_start[au]);
- }
-#endif
-
- return extract_au(au_start);
- }
- else {
- return false;
- }
-}
-
-bool DabPlusSnoop::extract_au(vector<int> au_start)
-{
- vector<vector<uint8_t> > aus(au_start.size());
-
- // The last entry of au_start must the end of valid
- // AU data. We stop at m_subchannel_index * 110 because
- // what comes after is RS parity
- au_start.push_back(m_subchannel_index * 110);
-
- bool all_crc_ok = true;
-
- for (size_t au = 0; au < aus.size(); au++)
- {
-#if DPS_DEBUG
- printf(DPS_PREFIX DPS_INDENT
- "Copy au %zu of size %zu\n",
- au,
- au_start[au+1] - au_start[au]-2 );
-#endif
-
- aus[au].resize(au_start[au+1] - au_start[au]-2);
- std::copy(
- m_data.begin() + au_start[au],
- m_data.begin() + au_start[au+1]-2,
- aus[au].begin() );
-
- /* Check CRC */
- uint16_t au_crc = m_data[au_start[au+1]-2] << 8 | \
- m_data[au_start[au+1]-1];
-
- uint16_t calc_crc = 0xFFFF;
- for (vector<uint8_t>::iterator au_data = aus[au].begin();
- au_data != aus[au].end();
- ++au_data) {
- calc_crc = update_crc_ccitt(calc_crc, *au_data);
- }
- calc_crc =~ calc_crc;
-
- if (calc_crc != au_crc) {
- printf(DPS_INDENT DPS_PREFIX
- "Erroneous CRC for au %zu: 0x%04x vs 0x%04x\n",
- au, calc_crc, au_crc);
-
- all_crc_ok = false;
- }
- }
-
- if (all_crc_ok) {
- return analyse_au(aus);
- }
- else {
- //discard faulty superframe (to be improved to correct/conceal)
- m_data.clear();
- return false;
- }
-}
-
-bool DabPlusSnoop::analyse_au(vector<vector<uint8_t> >& aus)
-{
- stringstream ss_filename;
-
- ss_filename << "stream-" << m_index;
-
- if (!m_faad_decoder.is_initialised()) {
- m_faad_decoder.open(ss_filename.str(), m_ps_flag,
- m_aac_channel_mode, m_dac_rate, m_sbr_flag,
- m_mpeg_surround_config);
- }
-
- return m_faad_decoder.decode(aus);
-}
-
-void DabPlusSnoop::close()
-{
- m_faad_decoder.close();
-
- if (m_raw_data_stream_fd) {
- fclose(m_raw_data_stream_fd);
- }
-}