From 9998c6ae08e08dd5acb32a0dc2229d099cafd775 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 11 Aug 2017 16:12:00 +0200 Subject: [PATCH 001/135] GUI: add GNU radio plots in developer mode --- include/dab/firecode_check_bb.h | 2 + include/dab/reed_solomon_decode_bb.h | 2 + lib/firecode_check_bb_impl.cc | 2 + lib/firecode_check_bb_impl.h | 4 + lib/reed_solomon_decode_bb_impl.cc | 2 + lib/reed_solomon_decode_bb_impl.h | 4 + python/GUI/main.py | 127 +++++++++++++++++++++++---- python/GUI/user_frontend.py | 31 ++++++- python/GUI/user_frontend.ui | 59 +++++++++++-- python/GUI/usrp_dab_rx.py | 20 ++++- python/dabplus_audio_decoder_ff.py | 6 ++ 11 files changed, 233 insertions(+), 26 deletions(-) diff --git a/include/dab/firecode_check_bb.h b/include/dab/firecode_check_bb.h index d1f1c5b3..e810a9af 100644 --- a/include/dab/firecode_check_bb.h +++ b/include/dab/firecode_check_bb.h @@ -46,6 +46,8 @@ namespace gr { * creating new instances. */ static sptr make(int bit_rate_n); + + virtual bool get_firecode_passed() = 0; }; } // namespace dab diff --git a/include/dab/reed_solomon_decode_bb.h b/include/dab/reed_solomon_decode_bb.h index 04d774cd..609ab79f 100644 --- a/include/dab/reed_solomon_decode_bb.h +++ b/include/dab/reed_solomon_decode_bb.h @@ -47,6 +47,8 @@ namespace gr { * creating new instances. */ static sptr make(int bit_rate_n); + + virtual int get_corrected_errors() = 0; }; } // namespace dab diff --git a/lib/firecode_check_bb_impl.cc b/lib/firecode_check_bb_impl.cc index 1a42f8ed..6a0b1f41 100644 --- a/lib/firecode_check_bb_impl.cc +++ b/lib/firecode_check_bb_impl.cc @@ -85,10 +85,12 @@ namespace gr { memcpy(out + d_nproduced * d_frame_size, in + d_nconsumed * d_frame_size, d_frame_size * 5); d_nproduced += 5; d_nconsumed += 5; + d_firecode_passed = true; } else { GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); // shift of one logical frame d_nconsumed++; + d_firecode_passed = false; } } // Tell runtime system how many input items we consumed on diff --git a/lib/firecode_check_bb_impl.h b/lib/firecode_check_bb_impl.h index 7f417a58..b7c74273 100644 --- a/lib/firecode_check_bb_impl.h +++ b/lib/firecode_check_bb_impl.h @@ -39,6 +39,7 @@ namespace gr { int d_frame_size; int d_bit_rate_n; int d_nproduced, d_nconsumed; + bool d_firecode_passed; firecode_checker fc; public: @@ -46,6 +47,9 @@ namespace gr { ~firecode_check_bb_impl(); + virtual bool get_firecode_passed() + { return d_firecode_passed; } + // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/reed_solomon_decode_bb_impl.cc b/lib/reed_solomon_decode_bb_impl.cc index 3468b5a1..bb84ac34 100644 --- a/lib/reed_solomon_decode_bb_impl.cc +++ b/lib/reed_solomon_decode_bb_impl.cc @@ -65,6 +65,7 @@ namespace gr { d_superframe_size = bit_rate_n * 120; d_superframe_size_rs = bit_rate_n * 110; set_output_multiple(d_superframe_size_rs); + d_corrected_errors = 0; } /* @@ -109,6 +110,7 @@ namespace gr { } } GR_LOG_DEBUG(d_logger, format("RS corrected %d errors in superframe") % total_corr_count); + d_corrected_errors = total_corr_count; } diff --git a/lib/reed_solomon_decode_bb_impl.h b/lib/reed_solomon_decode_bb_impl.h index 149a993e..0dcf011c 100644 --- a/lib/reed_solomon_decode_bb_impl.h +++ b/lib/reed_solomon_decode_bb_impl.h @@ -50,6 +50,7 @@ namespace gr { void *rs_handle; uint8_t rs_packet[120]; int corr_pos[10]; + int d_corrected_errors; void DecodeSuperframe(uint8_t *sf, size_t sf_len); @@ -58,6 +59,9 @@ namespace gr { ~reed_solomon_decode_bb_impl(); + virtual int get_corrected_errors() + { return d_corrected_errors; } + // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/python/GUI/main.py b/python/GUI/main.py index 20d91a79..8ae8e69d 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -1,15 +1,17 @@ #!/usr/bin/env python from PyQt4 import QtGui -from PyQt4.QtCore import QThread +from PyQt4 import QtCore from PyQt4.QtCore import QTimer import sys +import time import user_frontend import usrp_dab_rx import usrp_dab_tx import math import json import sip +import random class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def __init__(self, parent=None): @@ -58,6 +60,7 @@ def __init__(self, parent=None): # set file path self.btn_file_path.clicked.connect(self.set_file_path) # init button initializes receiver with center frequency + self.btn_init.clicked.connect(self.update_statusBar) self.btn_init.clicked.connect(self.init_receiver) # update button updates services in table self.btn_update_info.clicked.connect(self.update_service_info) @@ -72,6 +75,19 @@ def __init__(self, parent=None): # record button self.btn_record.clicked.connect(self.record_audio) + ###################################################################### + # DEVELOPER MODE + ###################################################################### + self.dev_mode_active = False + # hide close button and just show open button + self.btn_dev_mode_close.hide() + # dev mode open button pressed + self.btn_dev_mode_open.clicked.connect(self.dev_mode_open) + # dev mode close button pressed + self.btn_dev_mode_close.clicked.connect(self.dev_mode_close) + # firecode display + self.snr_timer.timeout.connect(self.update_firecode) + ###################################################################### # TAB TRANSMISSION (defining variables, signals and slots) ###################################################################### @@ -177,20 +193,29 @@ def set_file_path(self): self.label_path.setText(path) def init_receiver(self): - # set status bar message - self.statusBar.showMessage("initializing receiver ...") - self.btn_update_info.setEnabled(True) # stop any processes that access to an instance of usrp_dab_rx self.snr_timer.stop() # set up and start flowgraph self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() - self.snr_timer.start(5000) + # status bar + self.statusBar.showMessage("initialization finished!") + # init dev mode + self.dev_mode_init() + # once scan ensemble automatically (after per clicking btn) + time.sleep(1) + self.update_service_info() + self.btn_update_info.setEnabled(True) + self.snr_update() + self.snr_timer.start(1000) + + def update_statusBar(self): + self.statusBar.showMessage("initializing receiver ...") def update_service_info(self): # set status bar message - self.statusBar.showMessage("scanning ensemble...", 1000) + self.statusBar.showMessage("scanning ensemble...") # remove all old data from table at first while (self.table_mci.rowCount() > 0): self.table_mci.removeRow(0) @@ -220,21 +245,16 @@ def update_service_info(self): self.label_ensemble.setText(ensemble_data.keys()[0].strip()) self.label_country.setText(str(self.table.country_ID_ECC_E0[int(ensemble_data.values()[0]['country_ID'])])) self.lcd_number_num_subch.display(self.num_subch) + # status bar + self.statusBar.showMessage("Select a Service Component.") def selected_subch(self): # enable/disable buttons self.btn_play.setEnabled(True) self.btn_record.setEnabled(True) - - # check if selected sub-channel is different to former selected sub-channel - if self.table_mci.currentRow() is self.subch: - self.need_new_init = False - else: - # new subch was selected - self.subch = self.table_mci.currentRow() - self.need_new_init = True - self.btn_play.setText("Play") - self.slider_volume.setEnabled(False) + # new subch was selected + self.btn_play.setText("Play") + self.slider_volume.setEnabled(False) # get selected sub-channel by its ID ID = self.table_mci.item(self.table_mci.currentRow(), 0).text() @@ -259,6 +279,8 @@ def selected_subch(self): # service component (=sub-channel) info self.label_primary.setText(("primary" if service_data['primary'] == True else "secondary")) self.label_dabplus.setText(("DAB+" if service_data['DAB+'] == True else "DAB")) + # status Bar + self.statusBar.showMessage("Play/Record the selected Service Component.") def snr_update(self): print "update snr" @@ -293,13 +315,21 @@ def play_audio(self): self.slider_volume.setValue(self.volume) self.set_volume() # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver - if self.need_new_init: + if self.subch is not self.table_mci.currentRow(): + self.subch = self.table_mci.currentRow() + dev_mode_opened = False + if self.dev_mode_active: + dev_mode_opened = True + self.dev_mode_close() self.snr_timer.stop() self.my_receiver.stop() self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.frequency, self.bit_rate, self.address, self.size, self.protection, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() + self.dev_mode_init() + if dev_mode_opened: + self.dev_mode_open() self.snr_timer.start(5000) else: # mute button pressed @@ -309,9 +339,15 @@ def play_audio(self): self.slider_volume.setEnabled(False) self.set_volume() self.need_new_init = False + # start timer for snr update again self.snr_timer.start(1000) + # update dev mode def stop_reception(self): + # close dev mode + self.btn_dev_mode_close.hide() + self.btn_dev_mode_open.show() + self.btn_dev_mode_open.setEnabled(False) # stop flowgraph self.my_receiver.stop() # enable/disable buttons @@ -380,6 +416,63 @@ def get_sample_rate(self): # TODO: set rational resampler in flowgraoph with sample rate return self.my_receiver.get_sample_rate() + ################################ + # Developer Mode + ################################ + + def dev_mode_init(self): + # FFT plot + self.fft_plot = sip.wrapinstance(self.my_receiver.fft_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.fft_plot) + self.fft_plot.hide() + # Waterfall plot + self.waterfall_plot = sip.wrapinstance(self.my_receiver.waterfall_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.waterfall_plot) + self.waterfall_plot.hide() + # Time plot + # self.time_plot = sip.wrapinstance(self.my_receiver.time_plot.pyqwidget(), QtGui.QWidget) + # self.vertical_layout_dev_mode_right.addWidget(self.time_plot) + #self.time_plot.hide() + # constellation plot + self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.constellation) + self.constellation.hide() + # if dev mode is initialized, we can enable the dev mode open button + self.btn_dev_mode_open.setEnabled(True) + + def dev_mode_open(self): + self.dev_mode_active = True + # hide open button and show close button + self.btn_dev_mode_open.hide() + self.btn_dev_mode_close.show() + # show widgets + self.fft_plot.show() + self.waterfall_plot.show() + self.constellation.show() + self.label_firecode.show() + self.label_firecode.setText("") + + def dev_mode_close(self): + self.dev_mode_active = False + # hide close button and show open button + self.btn_dev_mode_close.hide() + self.btn_dev_mode_open.show() + # hide widgets + self.fft_plot.hide() + self.waterfall_plot.hide() + self.constellation.hide() + self.label_firecode.hide() + + def update_firecode(self): + if self.dev_mode_active: + if not self.my_receiver.get_firecode_passed(): + self.label_firecode.setText(self.label_firecode.text() + "X ") + else: + errors = self.my_receiver.get_corrected_errors() + self.label_firecode.setText(self.label_firecode.text() +("" + str(errors) +" ")) + self.label_firecode.setWordWrap(True) + + ################################ # Transmitter functions ################################ diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 511e33b8..f6582801 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -43,6 +43,18 @@ def setupUi(self, MainWindow): self.horizontalLayout_21.addWidget(self.label_6) spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.horizontalLayout_21.addItem(spacerItem1) + self.btn_dev_mode_close = QtGui.QPushButton(self.centralwidget) + self.btn_dev_mode_close.setEnabled(True) + icon = QtGui.QIcon.fromTheme(_fromUtf8("list-remove")) + self.btn_dev_mode_close.setIcon(icon) + self.btn_dev_mode_close.setObjectName(_fromUtf8("btn_dev_mode_close")) + self.horizontalLayout_21.addWidget(self.btn_dev_mode_close) + self.btn_dev_mode_open = QtGui.QPushButton(self.centralwidget) + self.btn_dev_mode_open.setEnabled(False) + icon = QtGui.QIcon.fromTheme(_fromUtf8("list-add")) + self.btn_dev_mode_open.setIcon(icon) + self.btn_dev_mode_open.setObjectName(_fromUtf8("btn_dev_mode_open")) + self.horizontalLayout_21.addWidget(self.btn_dev_mode_open) self.verticalLayout.addLayout(self.horizontalLayout_21) self.mode_tabs = QtGui.QTabWidget(self.centralwidget) self.mode_tabs.setEnabled(True) @@ -190,7 +202,7 @@ def setupUi(self, MainWindow): self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) self.bar_snr.setMinimum(-20) self.bar_snr.setMaximum(20) - self.bar_snr.setProperty("value", -20) + self.bar_snr.setProperty("value", 0) self.bar_snr.setFormat(_fromUtf8("")) self.bar_snr.setObjectName(_fromUtf8("bar_snr")) self.horizontalLayout_23.addWidget(self.bar_snr) @@ -313,7 +325,13 @@ def setupUi(self, MainWindow): self.horizontalLayout_4.addWidget(self.slider_volume) self.verticalLayout_7.addLayout(self.horizontalLayout_4) self.horizontalLayout_2.addLayout(self.verticalLayout_7) + self.vertical_layout_dev_mode_right = QtGui.QVBoxLayout() + self.vertical_layout_dev_mode_right.setObjectName(_fromUtf8("vertical_layout_dev_mode_right")) + self.horizontalLayout_2.addLayout(self.vertical_layout_dev_mode_right) self.verticalLayout_2.addLayout(self.horizontalLayout_2) + self.test_layout = QtGui.QVBoxLayout() + self.test_layout.setObjectName(_fromUtf8("test_layout")) + self.verticalLayout_2.addLayout(self.test_layout) self.mode_tabs.addTab(self.tab_reception, _fromUtf8("")) self.tab_transmission = QtGui.QWidget() self.tab_transmission.setObjectName(_fromUtf8("tab_transmission")) @@ -384,7 +402,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -587, 397, 954)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 397, 954)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -878,6 +896,12 @@ def setupUi(self, MainWindow): self.verticalLayout_3.addLayout(self.horizontalLayout_7) self.mode_tabs.addTab(self.tab_transmission, _fromUtf8("")) self.verticalLayout.addWidget(self.mode_tabs) + self.horizontalLayout_29 = QtGui.QHBoxLayout() + self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) + self.label_firecode = QtGui.QLabel(self.centralwidget) + self.label_firecode.setObjectName(_fromUtf8("label_firecode")) + self.horizontalLayout_29.addWidget(self.label_firecode) + self.verticalLayout.addLayout(self.horizontalLayout_29) MainWindow.setCentralWidget(self.centralwidget) self.statusBar = QtGui.QStatusBar(MainWindow) self.statusBar.setAutoFillBackground(False) @@ -892,6 +916,8 @@ def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.label_5.setText(_translate("MainWindow", "


", None)) self.label_6.setText(_translate("MainWindow", "

DABstep

", None)) + self.btn_dev_mode_close.setText(_translate("MainWindow", "Developer Mode", None)) + self.btn_dev_mode_open.setText(_translate("MainWindow", "Developer Mode", None)) self.rbtn_USRP.setText(_translate("MainWindow", "USRP", None)) self.label_frequency.setText(_translate("MainWindow", "Frequency", None)) self.label_4.setText(_translate("MainWindow", "Hz ", None)) @@ -992,4 +1018,5 @@ def retranslateUi(self, MainWindow): self.t_btn_stop.setText(_translate("MainWindow", " Stop", None)) self.label_19.setText(_translate("MainWindow", "Volume", None)) self.mode_tabs.setTabText(self.mode_tabs.indexOf(self.tab_transmission), _translate("MainWindow", "Transmitter", None)) + self.label_firecode.setText(_translate("MainWindow", "

Frames:

", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index bd184f30..0745a711 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -60,6 +60,32 @@ + + + + true + + + Developer Mode + + + + + + + + + + false + + + Developer Mode + + + + + + @@ -362,7 +388,7 @@ 20 - -20 + 0 @@ -494,7 +520,9 @@ set up receiver - + + + false @@ -510,7 +538,9 @@ scan ensemble - + + + @@ -622,8 +652,14 @@ + + + + + + @@ -773,7 +809,7 @@ 0 - -587 + 0 397 954 @@ -1621,7 +1657,9 @@ set up transmitter - + + + @@ -1770,6 +1808,17 @@ + + + + + + <html><head/><body><p>Frames:</p></body></html> + + + + + diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 0fa663ce..4cfcdb39 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -26,6 +26,7 @@ from gnuradio import gr, uhd, blocks from gnuradio import audio, digital from gnuradio import qtgui +from gnuradio import fft import dab import time, math @@ -68,6 +69,12 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src self.resample_fixed, self.verbose, self.correct_ffe, self.equalize_magnitude) + ######################## + # FFT and waterfall plot + ######################## + self.fft_plot = qtgui.freq_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "FFT") + self.waterfall_plot = qtgui.waterfall_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "Waterfall") + #self.time_plot = qtgui.time_sink_c_make(1024, 2e6, "Time") ######################## # OFDM demod @@ -79,7 +86,7 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src ######################## self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, 1536) self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) - self.null_sink_snr = blocks.null_sink_make(gr.sizeof_gr_complex) + self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) ######################## # FIC decoder @@ -95,11 +102,14 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src ######################## # Connections ######################## + self.connect(self.src, self.fft_plot) + self.connect(self.src, self.waterfall_plot) + #self.connect(self.src, self.time_plot) self.connect(self.src, self.demod, (self.fic_dec, 0)) self.connect((self.demod, 1), (self.fic_dec, 1)) self.connect((self.demod, 0), (self.dabplus, 0)) self.connect((self.demod, 1), (self.dabplus, 1)) - self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.null_sink_snr) + self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) # connect audio to sound card # left stereo channel self.connect((self.dabplus, 0), (self.audio, 0)) @@ -144,6 +154,12 @@ def get_sample_rate(self): def get_snr(self): return self.snr_measurement.snr() + def get_firecode_passed(self): + return self.dabplus.get_firecode_passed() + + def get_corrected_errors(self): + return self.dabplus.get_corrected_errors() + ######################## # setter methods ######################## diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index 80fc697c..ee1f058b 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -99,3 +99,9 @@ def set_volume(self, volume): def get_sample_rate(self): return self.mp4.get_sample_rate() + + def get_firecode_passed(self): + return self.firecode.get_firecode_passed() + + def get_corrected_errors(self): + return self.rs.get_corrected_errors() From 984565f59415dac56f4d1a48a7d4101afee760da Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 14 Aug 2017 09:57:24 +0200 Subject: [PATCH 002/135] GUI window size --- python/GUI/main.py | 2 ++ python/GUI/user_frontend.py | 4 ++-- python/GUI/user_frontend.ui | 14 +++++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 8ae8e69d..6bf55c86 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -462,6 +462,8 @@ def dev_mode_close(self): self.waterfall_plot.hide() self.constellation.hide() self.label_firecode.hide() + self.hide() + self.show() def update_firecode(self): if self.dev_mode_active: diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index f6582801..4cac4b9b 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(890, 585) + MainWindow.resize(849, 596) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -402,7 +402,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 397, 954)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 672, 1080)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 0745a711..4cfd5117 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,8 +6,8 @@ 0 0 - 890 - 585 + 849 + 596 @@ -69,7 +69,9 @@ Developer Mode - + + + @@ -82,7 +84,9 @@ Developer Mode - + + + @@ -810,7 +814,7 @@ 0 0 - 397 + 369 954 From e5d66b6d31fe2c41baccbbf57bb1b1a0f983a76c Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 14 Aug 2017 16:43:08 +0200 Subject: [PATCH 003/135] GUI: logo, superframe display flow(devMode) --- python/GUI/DAB_logo.png | Bin 0 -> 7053 bytes python/GUI/main.py | 31 +++++++++++----- python/GUI/user_frontend.py | 64 +++++++++++++++++++------------- python/GUI/user_frontend.ui | 71 ++++++++++++++++++++++++++---------- 4 files changed, 112 insertions(+), 54 deletions(-) create mode 100644 python/GUI/DAB_logo.png diff --git a/python/GUI/DAB_logo.png b/python/GUI/DAB_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b50c540e93a164ba3b432aaedbe05093bdee8688 GIT binary patch literal 7053 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�To+7|m=jAsvqcJatcn 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 literal 0 HcmV?d00001 diff --git a/python/GUI/main.py b/python/GUI/main.py index 6bf55c86..a7c20a34 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from PyQt4 import QtGui -from PyQt4 import QtCore from PyQt4.QtCore import QTimer import sys import time @@ -11,13 +10,17 @@ import math import json import sip -import random +import os class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def __init__(self, parent=None): super(DABstep, self).__init__(parent) self.setupUi(self) + # show logo if it exists + if os.path.exists("DAB_logo.png"): + self.label_logo.setText("") + # tab definitions self.modes = {"rec": 0, "trans": 1, "dev": 2} self.mode = self.modes["rec"] @@ -87,6 +90,14 @@ def __init__(self, parent=None): self.btn_dev_mode_close.clicked.connect(self.dev_mode_close) # firecode display self.snr_timer.timeout.connect(self.update_firecode) + self.label_firecode.setText("") + font = QtGui.QFont() + font.setFamily("CourierNew") + self.label_firecode.setFont(font) + self.label_firecode.hide() + self.content_count = 0 + + ###################################################################### # TAB TRANSMISSION (defining variables, signals and slots) @@ -208,7 +219,7 @@ def init_receiver(self): self.update_service_info() self.btn_update_info.setEnabled(True) self.snr_update() - self.snr_timer.start(1000) + self.snr_timer.start(500) def update_statusBar(self): self.statusBar.showMessage("initializing receiver ...") @@ -299,11 +310,11 @@ def snr_update(self): SNR = -20 self.bar_snr.setValue(SNR) self.lcd_snr.display(SNR) - self.snr_timer.start(1000) + self.snr_timer.start(500) else: self.bar_snr.setValue(-20) self.label_snr.setText("SNR: no reception") - self.snr_timer.start(4000) + self.snr_timer.start(500) def play_audio(self): if not self.slider_volume.isEnabled(): @@ -340,7 +351,7 @@ def play_audio(self): self.set_volume() self.need_new_init = False # start timer for snr update again - self.snr_timer.start(1000) + self.snr_timer.start(500) # update dev mode def stop_reception(self): @@ -451,6 +462,7 @@ def dev_mode_open(self): self.constellation.show() self.label_firecode.show() self.label_firecode.setText("") + self.content_count = 0 def dev_mode_close(self): self.dev_mode_active = False @@ -462,18 +474,19 @@ def dev_mode_close(self): self.waterfall_plot.hide() self.constellation.hide() self.label_firecode.hide() - self.hide() - self.show() def update_firecode(self): if self.dev_mode_active: + if self.content_count >=120: + self.label_firecode.setText("") + self.content_count = 0 if not self.my_receiver.get_firecode_passed(): self.label_firecode.setText(self.label_firecode.text() + "X ") else: errors = self.my_receiver.get_corrected_errors() self.label_firecode.setText(self.label_firecode.text() +("" + str(errors) +" ")) self.label_firecode.setWordWrap(True) - + self.content_count += 1 ################################ # Transmitter functions diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 4cac4b9b..ba0bbcc2 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(849, 596) + MainWindow.resize(896, 655) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -33,16 +33,14 @@ def setupUi(self, MainWindow): self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) self.horizontalLayout_21 = QtGui.QHBoxLayout() self.horizontalLayout_21.setObjectName(_fromUtf8("horizontalLayout_21")) - spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_21.addItem(spacerItem) self.label_5 = QtGui.QLabel(self.centralwidget) self.label_5.setObjectName(_fromUtf8("label_5")) self.horizontalLayout_21.addWidget(self.label_5) - self.label_6 = QtGui.QLabel(self.centralwidget) - self.label_6.setObjectName(_fromUtf8("label_6")) - self.horizontalLayout_21.addWidget(self.label_6) - spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_21.addItem(spacerItem1) + self.label_logo = QtGui.QLabel(self.centralwidget) + self.label_logo.setObjectName(_fromUtf8("label_logo")) + self.horizontalLayout_21.addWidget(self.label_logo) + spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_21.addItem(spacerItem) self.btn_dev_mode_close = QtGui.QPushButton(self.centralwidget) self.btn_dev_mode_close.setEnabled(True) icon = QtGui.QIcon.fromTheme(_fromUtf8("list-remove")) @@ -77,8 +75,8 @@ def setupUi(self, MainWindow): self.rbtn_USRP.setAutoRepeat(False) self.rbtn_USRP.setObjectName(_fromUtf8("rbtn_USRP")) self.horizontalLayout.addWidget(self.rbtn_USRP) - spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem2) + spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) self.label_frequency = QtGui.QLabel(self.tab_reception) self.label_frequency.setObjectName(_fromUtf8("label_frequency")) self.horizontalLayout.addWidget(self.label_frequency) @@ -168,8 +166,8 @@ def setupUi(self, MainWindow): self.verticalLayout_10 = QtGui.QVBoxLayout() self.verticalLayout_10.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.verticalLayout_10.setObjectName(_fromUtf8("verticalLayout_10")) - spacerItem3 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem3) + spacerItem2 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_10.addItem(spacerItem2) self.horizontalLayout_28 = QtGui.QHBoxLayout() self.horizontalLayout_28.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.horizontalLayout_28.setObjectName(_fromUtf8("horizontalLayout_28")) @@ -192,8 +190,8 @@ def setupUi(self, MainWindow): self.label_country.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_country.setObjectName(_fromUtf8("label_country")) self.verticalLayout_10.addWidget(self.label_country) - spacerItem4 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem4) + spacerItem3 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_10.addItem(spacerItem3) self.horizontalLayout_27.addLayout(self.verticalLayout_10) self.verticalLayout_7.addLayout(self.horizontalLayout_27) self.horizontalLayout_23 = QtGui.QHBoxLayout() @@ -254,8 +252,8 @@ def setupUi(self, MainWindow): self.line_7.setFrameShadow(QtGui.QFrame.Sunken) self.line_7.setObjectName(_fromUtf8("line_7")) self.verticalLayout_7.addWidget(self.line_7) - spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem5) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem4) self.horizontalLayout_26 = QtGui.QHBoxLayout() self.horizontalLayout_26.setObjectName(_fromUtf8("horizontalLayout_26")) self.btn_init = QtGui.QPushButton(self.tab_reception) @@ -348,8 +346,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem6 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem6) + spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem5) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -402,7 +400,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 672, 1080)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 400, 954)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -820,8 +818,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem7) + spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem6) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -836,8 +834,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem8) + spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem7) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -898,7 +896,21 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.mode_tabs) self.horizontalLayout_29 = QtGui.QHBoxLayout() self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) + spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_29.addItem(spacerItem8) self.label_firecode = QtGui.QLabel(self.centralwidget) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_firecode.sizePolicy().hasHeightForWidth()) + self.label_firecode.setSizePolicy(sizePolicy) + self.label_firecode.setMinimumSize(QtCore.QSize(365, 113)) + self.label_firecode.setMaximumSize(QtCore.QSize(365, 113)) + self.label_firecode.setFrameShape(QtGui.QFrame.Box) + self.label_firecode.setFrameShadow(QtGui.QFrame.Sunken) + self.label_firecode.setLineWidth(2) + self.label_firecode.setMidLineWidth(0) + self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_firecode.setObjectName(_fromUtf8("label_firecode")) self.horizontalLayout_29.addWidget(self.label_firecode) self.verticalLayout.addLayout(self.horizontalLayout_29) @@ -915,7 +927,7 @@ def setupUi(self, MainWindow): def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) self.label_5.setText(_translate("MainWindow", "


", None)) - self.label_6.setText(_translate("MainWindow", "

DABstep

", None)) + self.label_logo.setText(_translate("MainWindow", "

DABstep

", None)) self.btn_dev_mode_close.setText(_translate("MainWindow", "Developer Mode", None)) self.btn_dev_mode_open.setText(_translate("MainWindow", "Developer Mode", None)) self.rbtn_USRP.setText(_translate("MainWindow", "USRP", None)) @@ -941,7 +953,7 @@ def retranslateUi(self, MainWindow): self.label_dabplus.setText(_translate("MainWindow", "DAB", None)) self.label_bit_rate.setText(_translate("MainWindow", "bit rate", None)) self.label_primary.setText(_translate("MainWindow", "primary", None)) - self.btn_init.setText(_translate("MainWindow", "set up receiver", None)) + self.btn_init.setText(_translate("MainWindow", "start receiver", None)) self.btn_update_info.setText(_translate("MainWindow", "scan ensemble", None)) self.label_2.setText(_translate("MainWindow", "Audio Player", None)) self.btn_play.setText(_translate("MainWindow", " Play", None)) @@ -1009,7 +1021,7 @@ def retranslateUi(self, MainWindow): self.t_edit_service_label.setText(_translate("MainWindow", "Wasteland Radio", None)) self.label_17.setText(_translate("MainWindow", "Number of channels", None)) self.label_23.setText(_translate("MainWindow", "Language", None)) - self.t_btn_init.setText(_translate("MainWindow", " set up transmitter", None)) + self.t_btn_init.setText(_translate("MainWindow", "start transmitter", None)) self.label_22.setText(_translate("MainWindow", "Status:", None)) self.t_label_status.setText(_translate("MainWindow", "not running", None)) self.label_20.setText(_translate("MainWindow", "Audio Player", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 4cfd5117..c5fd7c5a 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,8 +6,8 @@ 0 0 - 849 - 596 + 896 + 655 @@ -20,19 +20,6 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -41,7 +28,7 @@ - + <html><head/><body><p><span style=" font-size:20pt; font-weight:600;">DABstep</span></p></body></html> @@ -521,7 +508,7 @@ - set up receiver + start receiver @@ -814,7 +801,7 @@ 0 0 - 369 + 400 954 @@ -1658,7 +1645,7 @@ - set up transmitter + start transmitter @@ -1814,11 +1801,57 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + 0 + 0 + + + + + 365 + 113 + + + + + 365 + 113 + + + + QFrame::Box + + + QFrame::Sunken + + + 2 + + + 0 + <html><head/><body><p>Frames:</p></body></html> + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + From 7d521bcfb5fac762024668a1a785d338b8cf67ca Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 15 Aug 2017 15:52:24 +0200 Subject: [PATCH 004/135] GUI: add DAB mode (next to DAB+) --- include/dab/mp2_decode_bs.h | 2 + lib/mp2_decode_bs_impl.cc | 3 +- lib/mp2_decode_bs_impl.h | 4 + python/GUI/main.py | 118 +++++++++++++++------- python/GUI/user_frontend.py | 86 ++++++++++++---- python/GUI/user_frontend.ui | 116 ++++++++++++++++++++-- python/GUI/usrp_dab_rx.py | 38 ++++--- python/GUI/usrp_dab_tx.py | 28 +++--- python/GUI/usrp_dabplus_rx.py | 181 ++++++++++++++++++++++++++++++++++ python/GUI/usrp_dabplus_tx.py | 131 ++++++++++++++++++++++++ 10 files changed, 604 insertions(+), 103 deletions(-) create mode 100644 python/GUI/usrp_dabplus_rx.py create mode 100644 python/GUI/usrp_dabplus_tx.py diff --git a/include/dab/mp2_decode_bs.h b/include/dab/mp2_decode_bs.h index 517b7363..fcc26c8f 100644 --- a/include/dab/mp2_decode_bs.h +++ b/include/dab/mp2_decode_bs.h @@ -47,6 +47,8 @@ namespace gr { * creating new instances. */ static sptr make(int bit_rate_n); + + virtual int32_t get_sample_rate() = 0; }; } // namespace dab diff --git a/lib/mp2_decode_bs_impl.cc b/lib/mp2_decode_bs_impl.cc index 07fbbe44..d259fbdd 100644 --- a/lib/mp2_decode_bs_impl.cc +++ b/lib/mp2_decode_bs_impl.cc @@ -293,8 +293,9 @@ namespace gr { || ((frame[1] & 0xF6) != 0xF4) // no MPEG-1/2 Audio Layer II? || ((frame[2] - 0x10) >= 0xE0)) // invalid bitrate? return 0; - return sample_rates[(((frame[1] & 0x08) >> 1) ^ 4) // MPEG-1/2 switch + d_sample_rate = sample_rates[(((frame[1] & 0x08) >> 1) ^ 4) // MPEG-1/2 switch + ((frame[2] >> 2) & 3)]; // actual rate + return d_sample_rate; } struct quantizer_spec *mp2_decode_bs_impl::read_allocation(int sb, int b2_table) diff --git a/lib/mp2_decode_bs_impl.h b/lib/mp2_decode_bs_impl.h index 52367095..62ca2b7e 100644 --- a/lib/mp2_decode_bs_impl.h +++ b/lib/mp2_decode_bs_impl.h @@ -63,6 +63,7 @@ namespace gr { int d_bit_rate; int d_nproduced; uint16_t *d_out; + int32_t d_sample_rate; int16_t d_V_offs; int32_t d_baud_rate; @@ -105,6 +106,9 @@ namespace gr { ~mp2_decode_bs_impl(); + virtual int32_t get_sample_rate() + {return d_sample_rate;} + // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/python/GUI/main.py b/python/GUI/main.py index a7c20a34..224bb79c 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -5,7 +5,9 @@ import sys import time import user_frontend +import usrp_dabplus_rx import usrp_dab_rx +import usrp_dabplus_tx import usrp_dab_tx import math import json @@ -17,6 +19,8 @@ def __init__(self, parent=None): super(DABstep, self).__init__(parent) self.setupUi(self) + # window title + self.setWindowTitle("DABstep - A DAB/DAB+ transceiver app") # show logo if it exists if os.path.exists("DAB_logo.png"): self.label_logo.setText("") @@ -33,13 +37,13 @@ def __init__(self, parent=None): # TAB RECEPTION (defining variables, signals and slots) ###################################################################### # receiver variables - self.frequency = 208.064e6 self.bit_rate = 8 self.address = 0 self.size = 6 self.protection = 2 self.volume = 80 self.subch = -1 + self.dabplus = True self.need_new_init = True self.recorder = False self.file_path = "None" @@ -53,6 +57,7 @@ def __init__(self, parent=None): header.setResizeMode(3, QtGui.QHeaderView.ResizeToContents) header.setStretchLastSection(False) self.table_mci.verticalHeader().hide() + self.table_mci.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) # timer for update of SNR self.snr_timer = QTimer() @@ -97,8 +102,6 @@ def __init__(self, parent=None): self.label_firecode.hide() self.content_count = 0 - - ###################################################################### # TAB TRANSMISSION (defining variables, signals and slots) ###################################################################### @@ -204,22 +207,26 @@ def set_file_path(self): self.label_path.setText(path) def init_receiver(self): - # stop any processes that access to an instance of usrp_dab_rx + # stop any processes that access to an instance of usrp_dabplus_rx self.snr_timer.stop() - # set up and start flowgraph - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, - self.src_is_USRP, self.file_path, self.recorder) - self.my_receiver.start() - # status bar - self.statusBar.showMessage("initialization finished!") - # init dev mode - self.dev_mode_init() - # once scan ensemble automatically (after per clicking btn) - time.sleep(1) - self.update_service_info() - self.btn_update_info.setEnabled(True) - self.snr_update() - self.snr_timer.start(500) + # check if file path is selected in case that file is the selected source + if (not self.src_is_USRP) and (self.file_path == "None"): + self.label_path.setStyleSheet('color: red') + else: + # set up and start flowgraph + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, + self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver.start() + # status bar + self.statusBar.showMessage("initialization finished!") + # init dev mode + self.dev_mode_init() + # once scan ensemble automatically (after per clicking btn) + time.sleep(1) + self.update_service_info() + self.btn_update_info.setEnabled(True) + self.snr_update() + self.snr_timer.start(500) def update_statusBar(self): self.statusBar.showMessage("initializing receiver ...") @@ -275,13 +282,14 @@ def selected_subch(self): service_data = next((item for item in self.get_service_info() if item['ID'] == int(ID)), {"reference":-1, "ID": -1, "primary": True}) service_label = next((item for item in self.get_service_labels() if item['reference'] == int(reference)), {"reference": -1, "label":"not found"}) subch_data = next((item for item in self.get_subch_info() if item['ID'] == int(ID)), {"ID":-1, "address":0, "protection":0,"size":0}) - #programme_type = next((item for item in self.get_programme_type() if item["reference"] == reference), {"programme_type":0,"language":0}) + programme_type = next((item for item in self.get_programme_type() if item["reference"] == reference), {"programme_type":0}) # update sub-channel info for receiver self.address = int(subch_data['address']) self.size = int(subch_data['size']) self.protection = int(subch_data['protection']) self.bit_rate = self.size * 8/6 + #self.dabplus = service_data['DAB+'] # display info to selected sub-channel # service info @@ -290,12 +298,17 @@ def selected_subch(self): # service component (=sub-channel) info self.label_primary.setText(("primary" if service_data['primary'] == True else "secondary")) self.label_dabplus.setText(("DAB+" if service_data['DAB+'] == True else "DAB")) + # programme type + if programme_type["programme_type"] is 0: + self.label_programme_type.setText("\n") + else: + self.label_programme_type.setText(self.table.programme_types[programme_type["programme_type"]] + "\n") # status Bar self.statusBar.showMessage("Play/Record the selected Service Component.") def snr_update(self): print "update snr" - # display snr in progress bar if an instance of usrp_dab_rx is existing + # display snr in progress bar if an instance of usrp_dabplus_rx is existing if hasattr(self, 'my_receiver'): SNR = self.my_receiver.get_snr() if SNR > 10: @@ -334,9 +347,18 @@ def play_audio(self): self.dev_mode_close() self.snr_timer.stop() self.my_receiver.stop() - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.frequency, self.bit_rate, self.address, self.size, - self.protection, - self.src_is_USRP, self.file_path, self.recorder) + if self.dabplus: + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, + self.src_is_USRP, self.file_path, self.recorder) + else: + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, + self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() self.dev_mode_init() if dev_mode_opened: @@ -379,9 +401,16 @@ def record_audio(self): self.btn_stop.setEnabled(True) self.recorder = True # start flowgraph - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.frequency, self.bit_rate, self.address, self.size, - self.protection, - self.src_is_USRP, self.file_path, self.recorder) + if self.dabplus: + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, + self.protection, + self.src_is_USRP, self.file_path, self.recorder) + else: + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, + self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() def set_volume(self): @@ -573,16 +602,33 @@ def t_init_transmitter(self): if arguments_incomplete is False: # init transmitter - self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spinbox_frequency.value(), - self.t_spin_num_subch.value(), - str(self.t_edit_ensemble_label.text()), - str(self.t_edit_service_label.text()), - self.t_combo_language.currentIndex(), - protection_array, data_rate_n_array, - audio_paths, - self.t_spin_listen_to_component.value(), - self.t_rbtn_USRP.isChecked(), - str(self.t_label_sink.text())+ "/" +str(self.t_edit_file_name.text())) + if self.t_combo_dabplus.currentIndex() is 1: + # transmitting in DAB mode + self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + str(self.t_edit_service_label.text()), + self.t_combo_language.currentIndex(), + protection_array, data_rate_n_array, 48000, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + str(self.t_label_sink.text())+ "/" +str(self.t_edit_file_name.text())) + else: + # transmitting in DAB+ mode + self.my_transmitter = usrp_dabplus_tx.usrp_dabplus_tx(self.t_spin_dab_mode.value(), + self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + str(self.t_edit_service_label.text()), + self.t_combo_language.currentIndex(), + protection_array, data_rate_n_array, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + str(self.t_label_sink.text()) + "/" + str( + self.t_edit_file_name.text())) + # enable play button self.t_btn_play.setEnabled(True) self.t_label_status.setText("ready to transmit") diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index ba0bbcc2..3d8118c9 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -116,6 +116,19 @@ def setupUi(self, MainWindow): self.btn_file_path.setObjectName(_fromUtf8("btn_file_path")) self.horizontalLayout_6.addWidget(self.btn_file_path) self.verticalLayout_6.addLayout(self.horizontalLayout_6) + self.horizontalLayout_30 = QtGui.QHBoxLayout() + self.horizontalLayout_30.setObjectName(_fromUtf8("horizontalLayout_30")) + spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_30.addItem(spacerItem2) + self.label_6 = QtGui.QLabel(self.tab_reception) + self.label_6.setObjectName(_fromUtf8("label_6")) + self.horizontalLayout_30.addWidget(self.label_6) + self.spin_dab_mode = QtGui.QSpinBox(self.tab_reception) + self.spin_dab_mode.setMinimum(1) + self.spin_dab_mode.setMaximum(4) + self.spin_dab_mode.setObjectName(_fromUtf8("spin_dab_mode")) + self.horizontalLayout_30.addWidget(self.spin_dab_mode) + self.verticalLayout_6.addLayout(self.horizontalLayout_30) self.horizontalLayout_3 = QtGui.QHBoxLayout() self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3")) self.verticalLayout_6.addLayout(self.horizontalLayout_3) @@ -166,8 +179,8 @@ def setupUi(self, MainWindow): self.verticalLayout_10 = QtGui.QVBoxLayout() self.verticalLayout_10.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.verticalLayout_10.setObjectName(_fromUtf8("verticalLayout_10")) - spacerItem2 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem2) + spacerItem3 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_10.addItem(spacerItem3) self.horizontalLayout_28 = QtGui.QHBoxLayout() self.horizontalLayout_28.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.horizontalLayout_28.setObjectName(_fromUtf8("horizontalLayout_28")) @@ -190,8 +203,8 @@ def setupUi(self, MainWindow): self.label_country.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_country.setObjectName(_fromUtf8("label_country")) self.verticalLayout_10.addWidget(self.label_country) - spacerItem3 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem3) + spacerItem4 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_10.addItem(spacerItem4) self.horizontalLayout_27.addLayout(self.verticalLayout_10) self.verticalLayout_7.addLayout(self.horizontalLayout_27) self.horizontalLayout_23 = QtGui.QHBoxLayout() @@ -232,12 +245,15 @@ def setupUi(self, MainWindow): self.label_service.setObjectName(_fromUtf8("label_service")) self.horizontalLayout_24.addWidget(self.label_service) self.verticalLayout_7.addLayout(self.horizontalLayout_24) + self.label_programme_type = QtGui.QLabel(self.tab_reception) + font = QtGui.QFont() + font.setPointSize(12) + self.label_programme_type.setFont(font) + self.label_programme_type.setAlignment(QtCore.Qt.AlignCenter) + self.label_programme_type.setObjectName(_fromUtf8("label_programme_type")) + self.verticalLayout_7.addWidget(self.label_programme_type) self.horizontalLayout_25 = QtGui.QHBoxLayout() self.horizontalLayout_25.setObjectName(_fromUtf8("horizontalLayout_25")) - self.label_dabplus = QtGui.QLabel(self.tab_reception) - self.label_dabplus.setAlignment(QtCore.Qt.AlignCenter) - self.label_dabplus.setObjectName(_fromUtf8("label_dabplus")) - self.horizontalLayout_25.addWidget(self.label_dabplus) self.label_bit_rate = QtGui.QLabel(self.tab_reception) self.label_bit_rate.setAlignment(QtCore.Qt.AlignCenter) self.label_bit_rate.setObjectName(_fromUtf8("label_bit_rate")) @@ -246,14 +262,18 @@ def setupUi(self, MainWindow): self.label_primary.setAlignment(QtCore.Qt.AlignCenter) self.label_primary.setObjectName(_fromUtf8("label_primary")) self.horizontalLayout_25.addWidget(self.label_primary) + self.label_dabplus = QtGui.QLabel(self.tab_reception) + self.label_dabplus.setAlignment(QtCore.Qt.AlignCenter) + self.label_dabplus.setObjectName(_fromUtf8("label_dabplus")) + self.horizontalLayout_25.addWidget(self.label_dabplus) self.verticalLayout_7.addLayout(self.horizontalLayout_25) self.line_7 = QtGui.QFrame(self.tab_reception) self.line_7.setFrameShape(QtGui.QFrame.HLine) self.line_7.setFrameShadow(QtGui.QFrame.Sunken) self.line_7.setObjectName(_fromUtf8("line_7")) self.verticalLayout_7.addWidget(self.line_7) - spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem4) + spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem5) self.horizontalLayout_26 = QtGui.QHBoxLayout() self.horizontalLayout_26.setObjectName(_fromUtf8("horizontalLayout_26")) self.btn_init = QtGui.QPushButton(self.tab_reception) @@ -346,8 +366,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem5) + spacerItem6 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem6) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -391,6 +411,24 @@ def setupUi(self, MainWindow): self.t_btn_file_path.setObjectName(_fromUtf8("t_btn_file_path")) self.horizontalLayout_10.addWidget(self.t_btn_file_path) self.verticalLayout_5.addLayout(self.horizontalLayout_10) + self.horizontalLayout_31 = QtGui.QHBoxLayout() + self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) + spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem7) + self.label_8 = QtGui.QLabel(self.tab_transmission) + self.label_8.setObjectName(_fromUtf8("label_8")) + self.horizontalLayout_31.addWidget(self.label_8) + self.t_spin_dab_mode = QtGui.QSpinBox(self.tab_transmission) + self.t_spin_dab_mode.setMinimum(1) + self.t_spin_dab_mode.setMaximum(4) + self.t_spin_dab_mode.setObjectName(_fromUtf8("t_spin_dab_mode")) + self.horizontalLayout_31.addWidget(self.t_spin_dab_mode) + self.t_combo_dabplus = QtGui.QComboBox(self.tab_transmission) + self.t_combo_dabplus.setObjectName(_fromUtf8("t_combo_dabplus")) + self.t_combo_dabplus.addItem(_fromUtf8("")) + self.t_combo_dabplus.addItem(_fromUtf8("")) + self.horizontalLayout_31.addWidget(self.t_combo_dabplus) + self.verticalLayout_5.addLayout(self.horizontalLayout_31) self.line_4 = QtGui.QFrame(self.tab_transmission) self.line_4.setFrameShape(QtGui.QFrame.HLine) self.line_4.setFrameShadow(QtGui.QFrame.Sunken) @@ -400,7 +438,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 400, 954)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 395, 876)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -818,8 +856,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem6) + spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem8) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -834,8 +872,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem7) + spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem9) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -896,8 +934,8 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.mode_tabs) self.horizontalLayout_29 = QtGui.QHBoxLayout() self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_29.addItem(spacerItem8) + spacerItem10 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_29.addItem(spacerItem10) self.label_firecode = QtGui.QLabel(self.centralwidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -921,7 +959,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) + self.mode_tabs.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -936,6 +974,7 @@ def retranslateUi(self, MainWindow): self.rbtn_File.setText(_translate("MainWindow", "File", None)) self.label_path.setText(_translate("MainWindow", "select path", None)) self.btn_file_path.setText(_translate("MainWindow", "...", None)) + self.label_6.setText(_translate("MainWindow", "Transmission Mode", None)) item = self.table_mci.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "ID", None)) item = self.table_mci.horizontalHeaderItem(1) @@ -950,9 +989,11 @@ def retranslateUi(self, MainWindow): self.label_snr.setText(_translate("MainWindow", "reception: ", None)) self.label_7.setText(_translate("MainWindow", "dB", None)) self.label_service.setText(_translate("MainWindow", "SERVICE", None)) - self.label_dabplus.setText(_translate("MainWindow", "DAB", None)) + self.label_programme_type.setText(_translate("MainWindow", "programme type\n" +"", None)) self.label_bit_rate.setText(_translate("MainWindow", "bit rate", None)) self.label_primary.setText(_translate("MainWindow", "primary", None)) + self.label_dabplus.setText(_translate("MainWindow", "DAB", None)) self.btn_init.setText(_translate("MainWindow", "start receiver", None)) self.btn_update_info.setText(_translate("MainWindow", "scan ensemble", None)) self.label_2.setText(_translate("MainWindow", "Audio Player", None)) @@ -968,6 +1009,9 @@ def retranslateUi(self, MainWindow): self.t_edit_file_name.setText(_translate("MainWindow", "gen_iq_dab.dat", None)) self.t_label_sink.setText(_translate("MainWindow", "select path", None)) self.t_btn_file_path.setText(_translate("MainWindow", "...", None)) + self.label_8.setText(_translate("MainWindow", "Transmission Mode", None)) + self.t_combo_dabplus.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus.setItemText(1, _translate("MainWindow", "DAB", None)) self.t_label_heading_service_comp.setText(_translate("MainWindow", "Service Components", None)) self.t_label_comp1.setText(_translate("MainWindow", "Component 1", None)) self.t_label_rate1.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index c5fd7c5a..4b238c2f 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true - 0 + 1 @@ -208,6 +208,40 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Transmission Mode + + + + + + + 1 + + + 4 + + + + + @@ -441,12 +475,28 @@ + + + + + 12 + + + + programme type + + + + Qt::AlignCenter + + + - + - DAB + bit rate Qt::AlignCenter @@ -454,9 +504,9 @@ - + - bit rate + primary Qt::AlignCenter @@ -464,9 +514,9 @@ - + - primary + DAB Qt::AlignCenter @@ -784,6 +834,54 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Transmission Mode + + + + + + + 1 + + + 4 + + + + + + + + DAB+ + + + + + DAB + + + + + + @@ -801,8 +899,8 @@ 0 0 - 400 - 954 + 395 + 876 diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 4cfcdb39..d98a35ef 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -20,7 +20,7 @@ # """ -receive DAB+ with USRP +receive DAB with USRP (for DAB+ reception see usrp_dabplus_rx.py) """ from gnuradio import gr, uhd, blocks @@ -32,10 +32,10 @@ class usrp_dab_rx(gr.top_block): - def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src_path, record_audio = False, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use_usrp, src_path, record_audio = False, sink_path = "None"): gr.top_block.__init__(self) - self.dab_mode = 1 + self.dab_mode = dab_mode self.verbose = False self.sample_rate = 2e6 self.use_usrp = use_usrp @@ -84,7 +84,7 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src ######################## # SNR measurement ######################## - self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, 1536) + self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dab_params.num_carriers) self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) @@ -96,7 +96,12 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src ######################## # MSC decoder and audio sink ######################## - self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) + self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) + self.mp2 = dab.mp2_decode_bs_make(bit_rate / 8) + self.s2f_left = blocks.short_to_float_make(1, 32767) + self.s2f_right = blocks.short_to_float_make(1, 32767) + self.gain_left = blocks.multiply_const_ff(1, 1) + self.gain_right = blocks.multiply_const_ff(1, 1) self.audio = audio.sink_make(32000) ######################## @@ -107,19 +112,16 @@ def __init__(self, frequency, bit_rate, address, size, protection, use_usrp, src #self.connect(self.src, self.time_plot) self.connect(self.src, self.demod, (self.fic_dec, 0)) self.connect((self.demod, 1), (self.fic_dec, 1)) - self.connect((self.demod, 0), (self.dabplus, 0)) - self.connect((self.demod, 1), (self.dabplus, 1)) + self.connect((self.demod, 0), (self.msc_dec, 0)) + self.connect((self.demod, 1), (self.msc_dec, 1)) + self.connect(self.msc_dec, (self.mp2, 0), self.s2f_left, self.gain_left, (self.audio, 0)) + self.connect((self.mp2, 1), self.s2f_right, self.gain_right, (self.audio, 1)) self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) - # connect audio to sound card - # left stereo channel - self.connect((self.dabplus, 0), (self.audio, 0)) - # right stereo channel - self.connect((self.dabplus, 1), (self.audio, 1)) # connect file sink if recording is selected if self.record_audio: self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) - self.connect((self.dabplus, 0), (self.sink, 0)) - self.connect((self.dabplus, 1), (self.sink, 1)) + self.connect(self.gain_left, (self.sink, 0)) + self.connect(self.gain_right, (self.sink, 1)) # tune USRP frequency if self.use_usrp: @@ -149,17 +151,11 @@ def get_programme_type(self): return self.fic_dec.get_programme_type() def get_sample_rate(self): - return self.dabplus.get_sample_rate() + return self.mp2.get_sample_rate() def get_snr(self): return self.snr_measurement.snr() - def get_firecode_passed(self): - return self.dabplus.get_firecode_passed() - - def get_corrected_errors(self): - return self.dabplus.get_corrected_errors() - ######################## # setter methods ######################## diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 764f0b1b..38a7f89b 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -20,7 +20,7 @@ # """ -receive DAB with USRP +receive DAB with USRP (for DAB+ transmission see usrp_dabplus_tx.py) """ from gnuradio import gr, uhd, blocks @@ -29,11 +29,11 @@ import numpy as np -class usrp_dab_tx(gr.top_block): - def __init__(self, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, sink_path = "dab_iq_generated.dat"): +class usrp_dabplus_tx(gr.top_block): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, audio_sample_rate, src_paths, selected_audio, use_usrp, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) - self.dab_mode = 1 + self.dab_mode = dab_mode self.frequency = frequency interp = 64 self.sample_rate = 128e6 / interp @@ -65,8 +65,7 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag self.msc_sources = [None] * self.num_subch self.f2s_left_converters = [None] * self.num_subch self.f2s_right_converters = [None] * self.num_subch - self.mp4_encoders = [None] * self.num_subch - self.rs_encoders = [None] * self.num_subch + self.mp2_encoders = [None] * self.num_subch self.msc_encoders = [None] * self.num_subch for i in range(0, self.num_subch): # source @@ -74,9 +73,8 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) - # mp4 encoder and Reed-Solomon encoder - self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) - self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) + # mp2 encoder + self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n, 2, audio_sample_rate) # encoder self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) @@ -85,12 +83,12 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag ######################## self.mux = dab.dab_transmission_frame_mux_bb_make(self.dab_mode, self.num_subch, self.subch_sizes) #self.mux = dab.dab_transmission_frame_mux_bb_make(1, 1, [84, 84]) - self.trigsrc = blocks.vector_source_b([1] + [0] * 74, True) + self.trigsrc = blocks.vector_source_b([1] + [0] * (self.dp.symbols_per_frame-2), True) ######################## # Modulator ######################## - self.s2v_mod = blocks.stream_to_vector(gr.sizeof_char, 384) + self.s2v_mod = blocks.stream_to_vector(gr.sizeof_char, self.dp.num_carriers/4) self.mod = dab.ofdm_mod(self.dp) ######################## @@ -104,7 +102,7 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag else: self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) # audio sink - self.audio = audio.sink_make(32000) + self.audio = audio.sink_make(audio_sample_rate) self.gain_left = blocks.multiply_const_ff_make(1, 1) self.gain_right = blocks.multiply_const_ff_make(1, 1) @@ -113,8 +111,8 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag ######################## self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) for i in range(0, self.num_subch): - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i+1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) self.connect(self.mod, self.sink) @@ -122,7 +120,7 @@ def __init__(self, frequency, num_subch, ensemble_label, service_label, languag self.connect((self.msc_sources[self.selected_audio - 1], 1), self.gain_right, (self.audio, 1)) def transmit(self): - tx = usrp_dab_tx() + tx = usrp_dabplus_tx() tx.run() def set_volume(self, volume): diff --git a/python/GUI/usrp_dabplus_rx.py b/python/GUI/usrp_dabplus_rx.py new file mode 100644 index 00000000..0ced68af --- /dev/null +++ b/python/GUI/usrp_dabplus_rx.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +""" +receive DAB+ with USRP +""" + +from gnuradio import gr, uhd, blocks +from gnuradio import audio, digital +from gnuradio import qtgui +from gnuradio import fft +import dab +import time, math + + +class usrp_dabplus_rx(gr.top_block): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use_usrp, src_path, record_audio = False, sink_path = "None"): + gr.top_block.__init__(self) + + self.dab_mode = dab_mode + self.verbose = False + self.sample_rate = 2e6 + self.use_usrp = use_usrp + self.src_path = src_path + self.record_audio = record_audio + self.sink_path = sink_path + + ######################## + # source + ######################## + if self.use_usrp: + self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) + self.src.set_samp_rate(self.sample_rate) + self.src.set_antenna("TX/RX") + else: + print "using file source" + self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, True) + + # set paramters to default mode + self.softbits = True + self.filter_input = True + self.autocorrect_sample_rate = False + self.resample_fixed = 1 + self.correct_ffe = True + self.equalize_magnitude = True + self.frequency = frequency + self.dab_params = dab.parameters.dab_parameters(self.dab_mode, self.sample_rate, self.verbose) + self.rx_params = dab.parameters.receiver_parameters(self.dab_mode, self.softbits, + self.filter_input, + self.autocorrect_sample_rate, + self.resample_fixed, + self.verbose, self.correct_ffe, + self.equalize_magnitude) + ######################## + # FFT and waterfall plot + ######################## + self.fft_plot = qtgui.freq_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "FFT") + self.waterfall_plot = qtgui.waterfall_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "Waterfall") + #self.time_plot = qtgui.time_sink_c_make(1024, 2e6, "Time") + + ######################## + # OFDM demod + ######################## + self.demod = dab.ofdm_demod(self.dab_params, self.rx_params, self.verbose) + + ######################## + # SNR measurement + ######################## + self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dab_params.num_carriers) + self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) + self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) + + ######################## + # FIC decoder + ######################## + self.fic_dec = dab.fic_decode(self.dab_params) + + ######################## + # MSC decoder and audio sink + ######################## + self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) + self.audio = audio.sink_make(32000) + + ######################## + # Connections + ######################## + self.connect(self.src, self.fft_plot) + self.connect(self.src, self.waterfall_plot) + #self.connect(self.src, self.time_plot) + self.connect(self.src, self.demod, (self.fic_dec, 0)) + self.connect((self.demod, 1), (self.fic_dec, 1)) + self.connect((self.demod, 0), (self.dabplus, 0)) + self.connect((self.demod, 1), (self.dabplus, 1)) + self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) + # connect audio to sound card + # left stereo channel + self.connect((self.dabplus, 0), (self.audio, 0)) + # right stereo channel + self.connect((self.dabplus, 1), (self.audio, 1)) + # connect file sink if recording is selected + if self.record_audio: + self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) + self.connect((self.dabplus, 0), (self.sink, 0)) + self.connect((self.dabplus, 1), (self.sink, 1)) + + # tune USRP frequency + if self.use_usrp: + self.set_freq(self.frequency) + # set gain + # if no gain was specified, use the mid-point in dB + g = self.src.get_gain_range() + self.rx_gain = float(g.start() + g.stop()) / 2 + self.src.set_gain(self.rx_gain) + +######################## +# getter methods +######################## + def get_ensemble_info(self): + return self.fic_dec.get_ensemble_info() + + def get_service_info(self): + return self.fic_dec.get_service_info() + + def get_service_labels(self): + return self.fic_dec.get_service_labels() + + def get_subch_info(self): + return self.fic_dec.get_subch_info() + + def get_programme_type(self): + return self.fic_dec.get_programme_type() + + def get_sample_rate(self): + return self.dabplus.get_sample_rate() + + def get_snr(self): + return self.snr_measurement.snr() + + def get_firecode_passed(self): + return self.dabplus.get_firecode_passed() + + def get_corrected_errors(self): + return self.dabplus.get_corrected_errors() + +######################## +# setter methods +######################## + def set_volume(self, volume): + self.dabplus.set_volume(volume) + + def set_freq(self, freq): + if self.src.set_center_freq(freq): + if self.verbose: + print "--> retuned to " + str(freq) + " Hz" + return True + else: + print "-> error - cannot tune to " + str(freq) + " Hz" + return False + + def receive(self): + rx = usrp_dabplus_rx() + rx.run() + diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py new file mode 100644 index 00000000..489fe232 --- /dev/null +++ b/python/GUI/usrp_dabplus_tx.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +""" +transmit DAB+ with USRP +""" + +from gnuradio import gr, uhd, blocks +from gnuradio import audio +import dab +import numpy as np + + +class usrp_dabplus_tx(gr.top_block): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, sink_path = "dab_iq_generated.dat"): + gr.top_block.__init__(self) + + self.dab_mode = dab_mode + self.frequency = frequency + interp = 64 + self.sample_rate = 128e6 / interp + self.dp = dab.parameters.dab_parameters(self.dab_mode, 2000000, False) + self.num_subch = num_subch + self.ensemble_label = ensemble_label + self.service_label = service_label + self.language = language + self.protections = protections + self.data_rates_n = data_rates_n + self.subch_sizes = np.multiply(self.data_rates_n, 6) + self.src_paths = src_paths + self.use_usrp = use_usrp + self.sink_path = sink_path + self.selected_audio = selected_audio + self.volume = 80 + + ######################## + # FIC + ######################## + # source + self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n) + # encoder + self.fic_enc = dab.fic_encode(self.dp) + + ######################## + # MSC + ######################## + self.msc_sources = [None] * self.num_subch + self.f2s_left_converters = [None] * self.num_subch + self.f2s_right_converters = [None] * self.num_subch + self.mp4_encoders = [None] * self.num_subch + self.rs_encoders = [None] * self.num_subch + self.msc_encoders = [None] * self.num_subch + for i in range(0, self.num_subch): + # source + self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) + # float to short + self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) + self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) + # mp4 encoder and Reed-Solomon encoder + self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) + self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) + # encoder + self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) + + ######################## + # MUX + ######################## + self.mux = dab.dab_transmission_frame_mux_bb_make(self.dab_mode, self.num_subch, self.subch_sizes) + #self.mux = dab.dab_transmission_frame_mux_bb_make(1, 1, [84, 84]) + self.trigsrc = blocks.vector_source_b([1] + [0] * (self.dp.symbols_per_frame-2), True) + + ######################## + # Modulator + ######################## + self.s2v_mod = blocks.stream_to_vector(gr.sizeof_char, self.dp.num_carriers/4) + self.mod = dab.ofdm_mod(self.dp) + + ######################## + # Sink + ######################## + if self.use_usrp: + self.sink = uhd.usrp_sink("", uhd.io_type.COMPLEX_FLOAT32, 1) + self.sink.set_samp_rate(self.sample_rate) + self.sink.set_antenna("TX/RX") + self.sink.set_center_freq(self.frequency) + else: + self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) + # audio sink + self.audio = audio.sink_make(32000) + self.gain_left = blocks.multiply_const_ff_make(1, 1) + self.gain_right = blocks.multiply_const_ff_make(1, 1) + + ######################## + # Connections + ######################## + self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) + for i in range(0, self.num_subch): + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) + self.connect(self.trigsrc, (self.mod, 1)) + self.connect(self.mod, self.sink) + self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) + self.connect((self.msc_sources[self.selected_audio - 1], 1), self.gain_right, (self.audio, 1)) + + def transmit(self): + tx = usrp_dabplus_tx() + tx.run() + + def set_volume(self, volume): + self.gain_left.set_k(volume) + self.gain_right.set_k(volume) + From e39cc9f9d9c816c618d81b4b7ff5790daaa431c5 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 15 Aug 2017 16:45:55 +0200 Subject: [PATCH 005/135] GUI: add case: no MCI in FIC, prevent from crashing whole programm --- python/GUI/main.py | 70 +++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 224bb79c..8bf14101 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -347,7 +347,7 @@ def play_audio(self): self.dev_mode_close() self.snr_timer.stop() self.my_receiver.stop() - if self.dabplus: + if True: self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, @@ -418,39 +418,59 @@ def set_volume(self): self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) def get_ensemble_info(self): - # load string (json) with ensemble info and convert it to dictionary - # string structure example: "{\"SWR_BW_N\":{\"country_ID\":1}}" - self.ensemble_info = json.loads(self.my_receiver.get_ensemble_info()) - json.dumps(self.ensemble_info) - return self.ensemble_info + json = self.my_receiver.get_ensemble_info() + if json is "": + return {"unknown":{"country_ID":0}} + else: + # load string (json) with ensemble info and convert it to dictionary + # string structure example: "{\"SWR_BW_N\":{\"country_ID\":1}}" + self.ensemble_info = json.loads(json) + json.dumps(self.ensemble_info) + return self.ensemble_info def get_service_info(self): - # load string (json) with MCI and convert it to array of dictionaries - self.service_info = json.loads(self.my_receiver.get_service_info()) - # string structure example: "[{\"reference\":736,\"ID\":2,\"primary\":true},{\"reference\":736,\"ID\":3,\"primary\":false},{\"reference\":234,\"ID\":5,\"primary\":true}]" - json.dumps(self.service_info) - return self.service_info + self.json = self.my_receiver.get_service_info() + if self.json is "": + return [] + else: + # load string (json) with MCI and convert it to array of dictionaries + self.service_info = json.loads(self.json) + # string structure example: "[{\"reference\":736,\"ID\":2,\"primary\":true},{\"reference\":736,\"ID\":3,\"primary\":false},{\"reference\":234,\"ID\":5,\"primary\":true}]" + json.dumps(self.service_info) + return self.service_info def get_service_labels(self): - # load string (json) with service labels and convert it to array of dictionaries - self.service_labels = json.loads(self.my_receiver.get_service_labels()) - # string structure example: "[{\"label\":\"SWR1_BW \",\"reference\":736},{\"label\":\"SWR2 \",\"reference\":234}]" - json.dumps(self.service_labels) - return self.service_labels + self.json = self.my_receiver.get_service_labels() + if self.json is "": + return [] + else: + # load string (json) with service labels and convert it to array of dictionaries + self.service_labels = json.loads(self.json) + # string structure example: "[{\"label\":\"SWR1_BW \",\"reference\":736},{\"label\":\"SWR2 \",\"reference\":234}]" + json.dumps(self.service_labels) + return self.service_labels def get_subch_info(self): - # load string (json) with sub-channel info and convert it to array of dictionaries - self.subch_info = json.loads(self.my_receiver.get_subch_info()) - # string structure example: "[{\"ID\":2, \"address\":54, \"protect\":2,\"size\":84},{\"ID\":3, \"address\":54, \"protect\":2,\"size\":84}]" - json.dumps(self.subch_info) - return self.subch_info + self.json = self.my_receiver.get_subch_info() + if self.json is "": + return [] + else: + # load string (json) with sub-channel info and convert it to array of dictionaries + self.subch_info = json.loads(self.json) + # string structure example: "[{\"ID\":2, \"address\":54, \"protect\":2,\"size\":84},{\"ID\":3, \"address\":54, \"protect\":2,\"size\":84}]" + json.dumps(self.subch_info) + return self.subch_info def get_programme_type(self): + self.json = self.my_receiver.get_programme_type() # load string (json) with service information (programme type) and convert it to array of dictionaries - self.programme_type = json.loads(self.my_receiver.get_programme_type()) - # string structure example: "[{\"reference\":736, \"programme_type\":13},{\"reference\":234, \"programme_type\":0}]" - json.dumps(self.programme_type) - return self.programme_type + if self.json == "": + return [] + else: + self.programme_type = json.loads(self.json) + # string structure example: "[{\"reference\":736, \"programme_type\":13},{\"reference\":234, \"programme_type\":0}]" + json.dumps(self.programme_type) + return self.programme_type def get_sample_rate(self): # TODO: set rational resampler in flowgraoph with sample rate From 3b735bdbdeae6a00b2845a4e4ed53d3fb3a5691a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 15 Aug 2017 19:18:44 +0200 Subject: [PATCH 006/135] GUI: bug fix JSON --- python/GUI/main.py | 14 ++++--- python/GUI/user_frontend.py | 48 +++++++++++------------ python/GUI/user_frontend.ui | 76 ++++++++++++++----------------------- 3 files changed, 62 insertions(+), 76 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 8bf14101..fbce0c5f 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -2,6 +2,7 @@ from PyQt4 import QtGui from PyQt4.QtCore import QTimer +from PyQt4 import QtCore import sys import time import user_frontend @@ -18,9 +19,9 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def __init__(self, parent=None): super(DABstep, self).__init__(parent) self.setupUi(self) - # window title self.setWindowTitle("DABstep - A DAB/DAB+ transceiver app") + self.resize(5000, 5000) # show logo if it exists if os.path.exists("DAB_logo.png"): self.label_logo.setText("") @@ -418,13 +419,13 @@ def set_volume(self): self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) def get_ensemble_info(self): - json = self.my_receiver.get_ensemble_info() - if json is "": + self.json = self.my_receiver.get_ensemble_info() + if self.json is "": return {"unknown":{"country_ID":0}} else: # load string (json) with ensemble info and convert it to dictionary # string structure example: "{\"SWR_BW_N\":{\"country_ID\":1}}" - self.ensemble_info = json.loads(json) + self.ensemble_info = json.loads(self.json) json.dumps(self.ensemble_info) return self.ensemble_info @@ -495,7 +496,7 @@ def dev_mode_init(self): #self.time_plot.hide() # constellation plot self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) - self.vertical_layout_dev_mode_right.addWidget(self.constellation) + self.horitontal_layout_dev_mode_bottom.addWidget(self.constellation) self.constellation.hide() # if dev mode is initialized, we can enable the dev mode open button self.btn_dev_mode_open.setEnabled(True) @@ -523,6 +524,9 @@ def dev_mode_close(self): self.waterfall_plot.hide() self.constellation.hide() self.label_firecode.hide() + print "key" + self.resize(2000, 2000) + def update_firecode(self): if self.dev_mode_active: diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 3d8118c9..307666bc 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -163,9 +163,10 @@ def setupUi(self, MainWindow): self.verticalLayout_7.setObjectName(_fromUtf8("verticalLayout_7")) self.horizontalLayout_27 = QtGui.QHBoxLayout() self.horizontalLayout_27.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) + self.horizontalLayout_27.setSpacing(6) self.horizontalLayout_27.setObjectName(_fromUtf8("horizontalLayout_27")) self.label_ensemble = QtGui.QLabel(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_ensemble.sizePolicy().hasHeightForWidth()) @@ -179,8 +180,6 @@ def setupUi(self, MainWindow): self.verticalLayout_10 = QtGui.QVBoxLayout() self.verticalLayout_10.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.verticalLayout_10.setObjectName(_fromUtf8("verticalLayout_10")) - spacerItem3 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem3) self.horizontalLayout_28 = QtGui.QHBoxLayout() self.horizontalLayout_28.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) self.horizontalLayout_28.setObjectName(_fromUtf8("horizontalLayout_28")) @@ -203,10 +202,13 @@ def setupUi(self, MainWindow): self.label_country.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_country.setObjectName(_fromUtf8("label_country")) self.verticalLayout_10.addWidget(self.label_country) - spacerItem4 = QtGui.QSpacerItem(20, 0, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_10.addItem(spacerItem4) self.horizontalLayout_27.addLayout(self.verticalLayout_10) self.verticalLayout_7.addLayout(self.horizontalLayout_27) + self.line_11 = QtGui.QFrame(self.tab_reception) + self.line_11.setFrameShape(QtGui.QFrame.HLine) + self.line_11.setFrameShadow(QtGui.QFrame.Sunken) + self.line_11.setObjectName(_fromUtf8("line_11")) + self.verticalLayout_7.addWidget(self.line_11) self.horizontalLayout_23 = QtGui.QHBoxLayout() self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) self.bar_snr = QtGui.QProgressBar(self.tab_reception) @@ -272,8 +274,6 @@ def setupUi(self, MainWindow): self.line_7.setFrameShadow(QtGui.QFrame.Sunken) self.line_7.setObjectName(_fromUtf8("line_7")) self.verticalLayout_7.addWidget(self.line_7) - spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem5) self.horizontalLayout_26 = QtGui.QHBoxLayout() self.horizontalLayout_26.setObjectName(_fromUtf8("horizontalLayout_26")) self.btn_init = QtGui.QPushButton(self.tab_reception) @@ -297,10 +297,10 @@ def setupUi(self, MainWindow): self.line_9.setFrameShadow(QtGui.QFrame.Sunken) self.line_9.setObjectName(_fromUtf8("line_9")) self.verticalLayout_7.addWidget(self.line_9) + spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem3) self.label_2 = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() - font.setFamily(_fromUtf8("Abyssinica SIL")) - font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_2.setFont(font) @@ -366,8 +366,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem6 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem6) + spacerItem4 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem4) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -413,8 +413,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_10) self.horizontalLayout_31 = QtGui.QHBoxLayout() self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem7) + spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem5) self.label_8 = QtGui.QLabel(self.tab_transmission) self.label_8.setObjectName(_fromUtf8("label_8")) self.horizontalLayout_31.addWidget(self.label_8) @@ -856,8 +856,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem8) + spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem6) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -872,8 +872,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem9) + spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem7) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -932,10 +932,10 @@ def setupUi(self, MainWindow): self.verticalLayout_3.addLayout(self.horizontalLayout_7) self.mode_tabs.addTab(self.tab_transmission, _fromUtf8("")) self.verticalLayout.addWidget(self.mode_tabs) - self.horizontalLayout_29 = QtGui.QHBoxLayout() - self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) - spacerItem10 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_29.addItem(spacerItem10) + self.horitontal_layout_dev_mode_bottom = QtGui.QHBoxLayout() + self.horitontal_layout_dev_mode_bottom.setObjectName(_fromUtf8("horitontal_layout_dev_mode_bottom")) + spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horitontal_layout_dev_mode_bottom.addItem(spacerItem8) self.label_firecode = QtGui.QLabel(self.centralwidget) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -950,8 +950,8 @@ def setupUi(self, MainWindow): self.label_firecode.setMidLineWidth(0) self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_firecode.setObjectName(_fromUtf8("label_firecode")) - self.horizontalLayout_29.addWidget(self.label_firecode) - self.verticalLayout.addLayout(self.horizontalLayout_29) + self.horitontal_layout_dev_mode_bottom.addWidget(self.label_firecode) + self.verticalLayout.addLayout(self.horitontal_layout_dev_mode_bottom) MainWindow.setCentralWidget(self.centralwidget) self.statusBar = QtGui.QStatusBar(MainWindow) self.statusBar.setAutoFillBackground(False) @@ -959,7 +959,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(1) + self.mode_tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 4b238c2f..53e346b0 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true - 1 + 0 @@ -297,13 +297,16 @@ + + 6 + QLayout::SetDefaultConstraint - + 0 0 @@ -326,19 +329,6 @@ QLayout::SetDefaultConstraint - - - - Qt::Vertical - - - - 20 - 0 - - - - @@ -382,23 +372,17 @@ - - - - Qt::Vertical - - - - 20 - 0 - - - - + + + + Qt::Horizontal + + + @@ -532,22 +516,6 @@ - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 40 - - - - @@ -594,12 +562,26 @@ + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + - Abyssinica SIL - 12 75 true @@ -1898,7 +1880,7 @@ - + From f5a73962c2696330193ed299247adb9fd4b5f630 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 16 Aug 2017 17:38:37 +0200 Subject: [PATCH 007/135] auto adjust sample rate + programme type support --- grc/CMakeLists.txt | 3 +- include/dab/CMakeLists.txt | 3 +- include/dab/fib_sink_vb.h | 1 + lib/CMakeLists.txt | 2 +- lib/dab_transmission_frame_mux_bb_impl.cc | 3 +- lib/fib_sink_vb_impl.cc | 16 +- lib/fib_sink_vb_impl.h | 5 + lib/mp4_decode_bs_impl.cc | 2 +- python/GUI/main.py | 98 ++++++--- python/GUI/user_frontend.py | 122 ++++++++--- python/GUI/user_frontend.ui | 238 ++++++++++++++++++---- python/GUI/usrp_dabplus_rx.py | 9 +- python/GUI/usrp_dabplus_tx.py | 8 +- python/dabplus_audio_decoder_ff.py | 16 +- python/fic.py | 5 +- swig/dab_swig.i | 1 + 16 files changed, 404 insertions(+), 128 deletions(-) diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index cf20dc65..de22f3b4 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -69,5 +69,6 @@ install(FILES dab_dabplus_audio_decoder_ff.xml dab_reed_solomon_encode_bb.xml dab_mp4_encode_sb.xml - dab_mp2_encode_sb.xml DESTINATION share/gnuradio/grc/blocks + dab_mp2_encode_sb.xml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index f850b0ac..89ba4b26 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -63,5 +63,6 @@ install(FILES reed_solomon_decode_bb.h reed_solomon_encode_bb.h mp4_encode_sb.h - mp2_encode_sb.h DESTINATION include/dab + mp2_encode_sb.h + DESTINATION include/dab ) diff --git a/include/dab/fib_sink_vb.h b/include/dab/fib_sink_vb.h index 809fa382..737e1699 100644 --- a/include/dab/fib_sink_vb.h +++ b/include/dab/fib_sink_vb.h @@ -54,6 +54,7 @@ namespace gr { virtual std::string get_service_labels() = 0; virtual std::string get_subch_info() = 0; virtual std::string get_programme_type() = 0; + virtual bool get_crc_passed() = 0; }; } // namespace dab diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 432363cc..70d46a43 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -93,7 +93,7 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/psycho_n1.c ${LIBTOOLAME-DAB_SOURCE_DIR}/encode_new.c ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c -) + ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/dab_transmission_frame_mux_bb_impl.cc b/lib/dab_transmission_frame_mux_bb_impl.cc index f05d25d9..7473d1db 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.cc +++ b/lib/dab_transmission_frame_mux_bb_impl.cc @@ -85,6 +85,7 @@ namespace gr { // generate PRBS for padding generate_prbs(d_prbs, sizeof(d_prbs)); + GR_LOG_DEBUG(d_logger, boost::format("key num_subch: %d") %d_num_subch); } /* @@ -133,7 +134,7 @@ namespace gr { gr_vector_void_star &output_items) { unsigned char *out = (unsigned char *) output_items[0]; - unsigned char *triggerout = (unsigned char *) output_items[1]; + //unsigned char *triggerout = (unsigned char *) output_items[1]; //const unsigned char *in; // create control stream for ofdm with trigger at start of frame and set zero diff --git a/lib/fib_sink_vb_impl.cc b/lib/fib_sink_vb_impl.cc index 68492062..4ef9cc16 100644 --- a/lib/fib_sink_vb_impl.cc +++ b/lib/fib_sink_vb_impl.cc @@ -57,6 +57,7 @@ namespace gr { d_service_labels_written_trigger = -1; d_subch_info_written_trigger = -1; d_programme_type_written_trigger = -1; + d_crc_passed = false; } int @@ -65,9 +66,11 @@ namespace gr { uint8_t type, length, pos; if (crc16(fib, FIB_LENGTH, FIB_CRC_POLY, FIB_CRC_INITSTATE) != 0) { GR_LOG_DEBUG(d_logger, "FIB CRC error"); + d_crc_passed = false; return 1; } GR_LOG_DEBUG(d_logger, "FIB correct"); + d_crc_passed = true; pos = 0; while (pos < FIB_LENGTH - FIB_CRC_LENGTH && (uint8_t) fib[pos] != FIB_ENDMARKER && (uint8_t) fib[pos] != 0) { //TODO correct? @@ -262,12 +265,11 @@ namespace gr { GR_LOG_DEBUG(d_logger, "programme number"); break; case FIB_SI_EXTENSION_PROGRAMME_TYPE: { - GR_LOG_DEBUG(d_logger, format("programme type, %d components") %((length-1)/6)); - for(int i = 0; i < (length-1)/6; i++) { - uint8_t programme_type = (uint8_t)(data[2 + i*6 + 4] & 0x1f); - uint8_t language = (uint8_t)(data[2 + i*6 + 3]); - uint16_t service_reference = (uint16_t)(data[2 + i*6] & 0x0f) << 8 | - (uint8_t) data[2 + i*6 + 1]; + GR_LOG_DEBUG(d_logger, format("programme type, %d components") %((length-1)/4)); + for(int i = 0; i < (length-1)/4; i++) { + uint8_t programme_type = (uint8_t)(data[2 + i*4 + 3] & 0x1f); + uint16_t service_reference = (uint16_t)(data[2 + i*4] & 0x0f) << 8 | + (uint8_t) data[2 + i*4 + 1]; GR_LOG_DEBUG(d_logger, format("reference %d, type: %d") %service_reference %(int)programme_type); // write programme type to json @@ -276,7 +278,7 @@ namespace gr { } else { std::stringstream ss; ss << d_programme_type_current << ",{" << "\"reference\":" << (int) service_reference << ",\"programme_type\":" - << (int) programme_type << ",\"language\":" << (int)language << "}\0"; + << (int) programme_type << "}\0"; d_programme_type_current = ss.str(); if ((int) service_reference == d_programme_type_written_trigger) { std::stringstream ss_json; diff --git a/lib/fib_sink_vb_impl.h b/lib/fib_sink_vb_impl.h index db615103..da621a78 100644 --- a/lib/fib_sink_vb_impl.h +++ b/lib/fib_sink_vb_impl.h @@ -35,6 +35,8 @@ namespace gr { int process_fig(uint8_t type, const char *data, uint8_t length); + bool d_crc_passed; + std::string d_json_ensemble_info; // service info std::string d_json_service_info; @@ -73,6 +75,9 @@ namespace gr { virtual std::string get_programme_type() { return d_json_programme_type;} + virtual bool get_crc_passed() + { return d_crc_passed;} + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index 5b6de084..9a74dd08 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -65,7 +65,7 @@ namespace gr { set_output_multiple(960 * 4); //TODO: right? baudRate*0.12 for output of one superframe aacHandle = NeAACDecOpen(); //memset(d_aac_frame, 0, 960); - d_sample_rate = 32000; + d_sample_rate = -1; } /* diff --git a/python/GUI/main.py b/python/GUI/main.py index fbce0c5f..6c0dcfc1 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -2,7 +2,6 @@ from PyQt4 import QtGui from PyQt4.QtCore import QTimer -from PyQt4 import QtCore import sys import time import user_frontend @@ -42,6 +41,7 @@ def __init__(self, parent=None): self.address = 0 self.size = 6 self.protection = 2 + self.audio_bit_rate = 32000 self.volume = 80 self.subch = -1 self.dabplus = True @@ -69,7 +69,6 @@ def __init__(self, parent=None): # set file path self.btn_file_path.clicked.connect(self.set_file_path) # init button initializes receiver with center frequency - self.btn_init.clicked.connect(self.update_statusBar) self.btn_init.clicked.connect(self.init_receiver) # update button updates services in table self.btn_update_info.clicked.connect(self.update_service_info) @@ -95,12 +94,22 @@ def __init__(self, parent=None): # dev mode close button pressed self.btn_dev_mode_close.clicked.connect(self.dev_mode_close) # firecode display - self.snr_timer.timeout.connect(self.update_firecode) + self.firecode_timer = QTimer() + self.firecode_timer.timeout.connect(self.update_firecode) self.label_firecode.setText("") + self.label_fic.setText("") font = QtGui.QFont() font.setFamily("CourierNew") self.label_firecode.setFont(font) self.label_firecode.hide() + self.led_msc.hide() + self.label_label_msc.hide() + self.label_fic.setFont(font) + self.label_fic.hide() + self.led_fic.hide() + self.label_label_fic.hide() + self.label_label_fic.setFont(font) + self.label_label_msc.setFont(font) self.content_count = 0 ###################################################################### @@ -208,18 +217,20 @@ def set_file_path(self): self.label_path.setText(path) def init_receiver(self): + self.statusBar.showMessage("initializing receiver ...") # stop any processes that access to an instance of usrp_dabplus_rx self.snr_timer.stop() + self.firecode_timer.stop() # check if file path is selected in case that file is the selected source if (not self.src_is_USRP) and (self.file_path == "None"): self.label_path.setStyleSheet('color: red') else: # set up and start flowgraph - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() # status bar - self.statusBar.showMessage("initialization finished!") + self.statusBar.showMessage("Reception is running.") # init dev mode self.dev_mode_init() # once scan ensemble automatically (after per clicking btn) @@ -227,14 +238,12 @@ def init_receiver(self): self.update_service_info() self.btn_update_info.setEnabled(True) self.snr_update() - self.snr_timer.start(500) - - def update_statusBar(self): - self.statusBar.showMessage("initializing receiver ...") + self.snr_timer.start(1000) + self.firecode_timer.start(120) def update_service_info(self): # set status bar message - self.statusBar.showMessage("scanning ensemble...") + self.statusBar.showMessage("Scanning ensemble...") # remove all old data from table at first while (self.table_mci.rowCount() > 0): self.table_mci.removeRow(0) @@ -289,7 +298,12 @@ def selected_subch(self): self.address = int(subch_data['address']) self.size = int(subch_data['size']) self.protection = int(subch_data['protection']) - self.bit_rate = self.size * 8/6 + conv_table = [12, 8, 6, 5] + self.bit_rate = self.size * 8/conv_table[self.protection] + if self.bit_rate < 100: + self.audio_bit_rate = 48000 + else: + self.audio_bit_rate = 32000 #self.dabplus = service_data['DAB+'] # display info to selected sub-channel @@ -305,7 +319,7 @@ def selected_subch(self): else: self.label_programme_type.setText(self.table.programme_types[programme_type["programme_type"]] + "\n") # status Bar - self.statusBar.showMessage("Play/Record the selected Service Component.") + self.statusBar.showMessage("Play/Record the selected service component.") def snr_update(self): print "update snr" @@ -324,11 +338,10 @@ def snr_update(self): SNR = -20 self.bar_snr.setValue(SNR) self.lcd_snr.display(SNR) - self.snr_timer.start(500) else: self.bar_snr.setValue(-20) self.label_snr.setText("SNR: no reception") - self.snr_timer.start(500) + self.snr_timer.start(1000) def play_audio(self): if not self.slider_volume.isEnabled(): @@ -347,12 +360,13 @@ def play_audio(self): dev_mode_opened = True self.dev_mode_close() self.snr_timer.stop() + self.firecode_timer.stop() self.my_receiver.stop() if True: self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, - self.protection, + self.protection, self.audio_bit_rate, self.src_is_USRP, self.file_path, self.recorder) else: self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), @@ -361,10 +375,10 @@ def play_audio(self): self.protection, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() + self.statusBar.showMessage("Audio playing.") self.dev_mode_init() if dev_mode_opened: self.dev_mode_open() - self.snr_timer.start(5000) else: # mute button pressed self.btn_play.setText("Play") @@ -374,7 +388,8 @@ def play_audio(self): self.set_volume() self.need_new_init = False # start timer for snr update again - self.snr_timer.start(500) + self.snr_timer.start(1000) + self.firecode_timer.start(120) # update dev mode def stop_reception(self): @@ -394,6 +409,8 @@ def stop_reception(self): self.recorder = False # stop snr updates because no flowgraph is running to measure snr self.snr_timer.stop() + self.firecode_timer.stop() + self.statusBar.showMessage("Reception stopped.") def record_audio(self): # enable/disable buttons @@ -404,7 +421,7 @@ def record_audio(self): # start flowgraph if self.dabplus: self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, - self.protection, + self.protection, self.audio_bit_rate, self.src_is_USRP, self.file_path, self.recorder) else: self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), @@ -413,6 +430,7 @@ def record_audio(self): self.protection, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() + self.statusBar.showMessage("Recording audio ...") def set_volume(self): # map volume from [0:100] to [0:1] @@ -490,13 +508,9 @@ def dev_mode_init(self): self.waterfall_plot = sip.wrapinstance(self.my_receiver.waterfall_plot.pyqwidget(), QtGui.QWidget) self.vertical_layout_dev_mode_right.addWidget(self.waterfall_plot) self.waterfall_plot.hide() - # Time plot - # self.time_plot = sip.wrapinstance(self.my_receiver.time_plot.pyqwidget(), QtGui.QWidget) - # self.vertical_layout_dev_mode_right.addWidget(self.time_plot) - #self.time_plot.hide() # constellation plot self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) - self.horitontal_layout_dev_mode_bottom.addWidget(self.constellation) + self.vertical_layout_dev_mode_right.addWidget(self.constellation) self.constellation.hide() # if dev mode is initialized, we can enable the dev mode open button self.btn_dev_mode_open.setEnabled(True) @@ -511,7 +525,13 @@ def dev_mode_open(self): self.waterfall_plot.show() self.constellation.show() self.label_firecode.show() + self.led_msc.show() + self.label_label_msc.show() self.label_firecode.setText("") + self.label_fic.show() + self.led_fic.show() + self.label_label_fic.show() + self.label_fic.setText("") self.content_count = 0 def dev_mode_close(self): @@ -524,20 +544,41 @@ def dev_mode_close(self): self.waterfall_plot.hide() self.constellation.hide() self.label_firecode.hide() + self.led_msc.hide() + self.label_label_msc.hide() + self.label_fic.hide() + self.led_fic.hide() + self.label_label_fic.hide() print "key" self.resize(2000, 2000) def update_firecode(self): if self.dev_mode_active: - if self.content_count >=120: + if self.content_count >=69: self.label_firecode.setText("") + self.label_fic.setText("") self.content_count = 0 + # write msc status if not self.my_receiver.get_firecode_passed(): self.label_firecode.setText(self.label_firecode.text() + "X ") + self.led_msc.setColor(QtGui.QColor(255, 0, 0)) else: errors = self.my_receiver.get_corrected_errors() - self.label_firecode.setText(self.label_firecode.text() +("" + str(errors) +" ")) + if errors < 10: + self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + " < /font>") + self.led_msc.setColor(QtGui.QColor(0, 255, 0)) + else: + self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + "") + self.led_msc.setColor(QtGui.QColor(0, 255, 128)) + # write fic status + if self.my_receiver.get_crc_passed(): + self.label_fic.setText(self.label_fic.text() + "0 ") + self.led_fic.setColor(QtGui.QColor(0, 255, 0)) + else: + self.label_fic.setText(self.label_fic.text() + "X ") + self.led_fic.setColor(QtGui.QColor(255, 0, 0)) + self.label_fic.setWordWrap(True) self.label_firecode.setWordWrap(True) self.content_count += 1 @@ -656,12 +697,13 @@ def t_init_transmitter(self): # enable play button self.t_btn_play.setEnabled(True) self.t_label_status.setText("ready to transmit") + self.statusBar.showMessage("ready to transmit") def t_run_transmitter(self): self.t_btn_stop.setEnabled(True) self.t_slider_volume.setEnabled(True) - self.t_label_status.setText("transmitting..") - self.statusBar.showMessage("transmitting..") + self.t_label_status.setText("transmitting...") + self.statusBar.showMessage("transmitting...") self.my_transmitter.start() def t_set_volume(self): @@ -673,7 +715,7 @@ def t_stop_transmitter(self): self.t_btn_stop.setEnabled(False) self.t_slider_volume.setEnabled(False) self.t_label_status.setText("not running") - self.statusBar.showMessage("not running") + self.statusBar.showMessage("Transmission stopped.") def t_set_file_path(self): path = QtGui.QFileDialog.getExistingDirectory(self, "Pick a folder for your file sink") diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 307666bc..102033d2 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(896, 655) + MainWindow.resize(816, 664) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -232,6 +232,76 @@ def setupUi(self, MainWindow): self.label_7.setObjectName(_fromUtf8("label_7")) self.horizontalLayout_23.addWidget(self.label_7) self.verticalLayout_7.addLayout(self.horizontalLayout_23) + self.vertical_layout_dev_mode_right_vertical = QtGui.QVBoxLayout() + self.vertical_layout_dev_mode_right_vertical.setObjectName(_fromUtf8("vertical_layout_dev_mode_right_vertical")) + self.horizontalLayout_29 = QtGui.QHBoxLayout() + self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) + self.label_label_msc = QtGui.QLabel(self.tab_reception) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_label_msc.setFont(font) + self.label_label_msc.setObjectName(_fromUtf8("label_label_msc")) + self.horizontalLayout_29.addWidget(self.label_label_msc) + self.verticalLayout_13 = QtGui.QVBoxLayout() + self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) + spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem3) + self.led_msc = KLed(self.tab_reception) + self.led_msc.setLook(KLed.Sunken) + self.led_msc.setDarkFactor(300) + self.led_msc.setObjectName(_fromUtf8("led_msc")) + self.verticalLayout_13.addWidget(self.led_msc) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem4) + self.horizontalLayout_29.addLayout(self.verticalLayout_13) + self.label_firecode = QtGui.QLabel(self.tab_reception) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_firecode.sizePolicy().hasHeightForWidth()) + self.label_firecode.setSizePolicy(sizePolicy) + self.label_firecode.setMinimumSize(QtCore.QSize(365, 55)) + self.label_firecode.setMaximumSize(QtCore.QSize(365, 55)) + self.label_firecode.setFrameShape(QtGui.QFrame.Box) + self.label_firecode.setFrameShadow(QtGui.QFrame.Sunken) + self.label_firecode.setLineWidth(2) + self.label_firecode.setMidLineWidth(0) + self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.label_firecode.setObjectName(_fromUtf8("label_firecode")) + self.horizontalLayout_29.addWidget(self.label_firecode) + self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_29) + self.horizontalLayout_32 = QtGui.QHBoxLayout() + self.horizontalLayout_32.setObjectName(_fromUtf8("horizontalLayout_32")) + self.label_label_fic = QtGui.QLabel(self.tab_reception) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_label_fic.setFont(font) + self.label_label_fic.setObjectName(_fromUtf8("label_label_fic")) + self.horizontalLayout_32.addWidget(self.label_label_fic) + self.verticalLayout_14 = QtGui.QVBoxLayout() + self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) + spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem5) + self.led_fic = KLed(self.tab_reception) + self.led_fic.setLook(KLed.Sunken) + self.led_fic.setObjectName(_fromUtf8("led_fic")) + self.verticalLayout_14.addWidget(self.led_fic) + spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem6) + self.horizontalLayout_32.addLayout(self.verticalLayout_14) + self.label_fic = QtGui.QLabel(self.tab_reception) + self.label_fic.setMinimumSize(QtCore.QSize(365, 55)) + self.label_fic.setMaximumSize(QtCore.QSize(365, 60)) + self.label_fic.setFrameShape(QtGui.QFrame.Box) + self.label_fic.setFrameShadow(QtGui.QFrame.Sunken) + self.label_fic.setLineWidth(2) + self.label_fic.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.label_fic.setObjectName(_fromUtf8("label_fic")) + self.horizontalLayout_32.addWidget(self.label_fic) + self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_32) + self.verticalLayout_7.addLayout(self.vertical_layout_dev_mode_right_vertical) self.line_6 = QtGui.QFrame(self.tab_reception) self.line_6.setFrameShape(QtGui.QFrame.HLine) self.line_6.setFrameShadow(QtGui.QFrame.Sunken) @@ -297,8 +367,8 @@ def setupUi(self, MainWindow): self.line_9.setFrameShadow(QtGui.QFrame.Sunken) self.line_9.setObjectName(_fromUtf8("line_9")) self.verticalLayout_7.addWidget(self.line_9) - spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem3) + spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem7) self.label_2 = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() font.setBold(True) @@ -366,8 +436,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem4 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem4) + spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem8) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -413,8 +483,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_10) self.horizontalLayout_31 = QtGui.QHBoxLayout() self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem5) + spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem9) self.label_8 = QtGui.QLabel(self.tab_transmission) self.label_8.setObjectName(_fromUtf8("label_8")) self.horizontalLayout_31.addWidget(self.label_8) @@ -438,7 +508,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 395, 876)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 392, 876)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -856,8 +926,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem6) + spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem10) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -872,8 +942,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem7) + spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem11) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -934,23 +1004,11 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.mode_tabs) self.horitontal_layout_dev_mode_bottom = QtGui.QHBoxLayout() self.horitontal_layout_dev_mode_bottom.setObjectName(_fromUtf8("horitontal_layout_dev_mode_bottom")) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horitontal_layout_dev_mode_bottom.addItem(spacerItem8) - self.label_firecode = QtGui.QLabel(self.centralwidget) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_firecode.sizePolicy().hasHeightForWidth()) - self.label_firecode.setSizePolicy(sizePolicy) - self.label_firecode.setMinimumSize(QtCore.QSize(365, 113)) - self.label_firecode.setMaximumSize(QtCore.QSize(365, 113)) - self.label_firecode.setFrameShape(QtGui.QFrame.Box) - self.label_firecode.setFrameShadow(QtGui.QFrame.Sunken) - self.label_firecode.setLineWidth(2) - self.label_firecode.setMidLineWidth(0) - self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) - self.label_firecode.setObjectName(_fromUtf8("label_firecode")) - self.horitontal_layout_dev_mode_bottom.addWidget(self.label_firecode) + spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horitontal_layout_dev_mode_bottom.addItem(spacerItem12) + self.verticalLayout_11 = QtGui.QVBoxLayout() + self.verticalLayout_11.setObjectName(_fromUtf8("verticalLayout_11")) + self.horitontal_layout_dev_mode_bottom.addLayout(self.verticalLayout_11) self.verticalLayout.addLayout(self.horitontal_layout_dev_mode_bottom) MainWindow.setCentralWidget(self.centralwidget) self.statusBar = QtGui.QStatusBar(MainWindow) @@ -988,6 +1046,10 @@ def retranslateUi(self, MainWindow): self.label_country.setText(_translate("MainWindow", "Country", None)) self.label_snr.setText(_translate("MainWindow", "reception: ", None)) self.label_7.setText(_translate("MainWindow", "dB", None)) + self.label_label_msc.setText(_translate("MainWindow", "MSC", None)) + self.label_firecode.setText(_translate("MainWindow", "

Superframes:

", None)) + self.label_label_fic.setText(_translate("MainWindow", "FIC", None)) + self.label_fic.setText(_translate("MainWindow", "

FIC:

", None)) self.label_service.setText(_translate("MainWindow", "SERVICE", None)) self.label_programme_type.setText(_translate("MainWindow", "programme type\n" "", None)) @@ -1074,5 +1136,5 @@ def retranslateUi(self, MainWindow): self.t_btn_stop.setText(_translate("MainWindow", " Stop", None)) self.label_19.setText(_translate("MainWindow", "Volume", None)) self.mode_tabs.setTabText(self.mode_tabs.indexOf(self.tab_transmission), _translate("MainWindow", "Transmitter", None)) - self.label_firecode.setText(_translate("MainWindow", "

Frames:

", None)) +from PyKDE4.kdeui import KLed diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 53e346b0..2102a0da 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,8 +6,8 @@ 0 0 - 896 - 655 + 816 + 664
@@ -433,6 +433,192 @@
+ + + + + + + + + 75 + true + + + + MSC + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + KLed::Sunken + + + 300 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + + 365 + 55 + + + + + 365 + 55 + + + + QFrame::Box + + + QFrame::Sunken + + + 2 + + + 0 + + + <html><head/><body><p>Superframes:</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + + 75 + true + + + + FIC + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + KLed::Sunken + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 365 + 55 + + + + + 365 + 55 + + + + QFrame::Box + + + QFrame::Sunken + + + 2 + + + <html><head/><body><p>FIC:</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + @@ -881,7 +1067,7 @@ 0 0 - 395 + 392 876 @@ -1895,44 +2081,7 @@ - - - - 0 - 0 - - - - - 365 - 113 - - - - - 365 - 113 - - - - QFrame::Box - - - QFrame::Sunken - - - 2 - - - 0 - - - <html><head/><body><p>Frames:</p></body></html> - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - +
@@ -1944,6 +2093,13 @@ + + + KLed + QWidget +
kled.h
+
+
diff --git a/python/GUI/usrp_dabplus_rx.py b/python/GUI/usrp_dabplus_rx.py index 0ced68af..7fe1ef04 100644 --- a/python/GUI/usrp_dabplus_rx.py +++ b/python/GUI/usrp_dabplus_rx.py @@ -32,7 +32,7 @@ class usrp_dabplus_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use_usrp, src_path, record_audio = False, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, use_usrp, src_path, record_audio = False, sink_path = "None"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -52,7 +52,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use self.src.set_antenna("TX/RX") else: print "using file source" - self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, True) + self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, False) # set paramters to default mode self.softbits = True @@ -97,7 +97,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use # MSC decoder and audio sink ######################## self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) - self.audio = audio.sink_make(32000) + self.audio = audio.sink_make(audio_bit_rate) ######################## # Connections @@ -160,6 +160,9 @@ def get_firecode_passed(self): def get_corrected_errors(self): return self.dabplus.get_corrected_errors() + def get_crc_passed(self): + return self.fic_dec.get_crc_passed() + ######################## # setter methods ######################## diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py index 489fe232..557bed0a 100644 --- a/python/GUI/usrp_dabplus_tx.py +++ b/python/GUI/usrp_dabplus_tx.py @@ -104,7 +104,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label else: self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) # audio sink - self.audio = audio.sink_make(32000) + #self.audio = audio.sink_make(32000) self.gain_left = blocks.multiply_const_ff_make(1, 1) self.gain_right = blocks.multiply_const_ff_make(1, 1) @@ -117,9 +117,9 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) - self.connect(self.mod, self.sink) - self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) - self.connect((self.msc_sources[self.selected_audio - 1], 1), self.gain_right, (self.audio, 1)) + self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) + #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) + #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) def transmit(self): tx = usrp_dabplus_tx() diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index ee1f058b..b6da1ae8 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -60,11 +60,11 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output self.debug = debug # sanity check - if self.bit_rate_n*6 != self.size: - log = gr.logger("log") - log.debug("bit rate and subchannel size are not fitting") - log.set_level("ERROR") - raise ValueError + # if self.bit_rate_n*6 != self.size: + # log = gr.logger("log") + # log.debug("bit rate and subchannel size are not fitting") + # log.set_level("ERROR") + # raise ValueError # MSC decoder extracts logical frames out of transmission frame and decodes it self.msc_decoder = dab.msc_decode(self.dp, self.address, self.size, self.protection, self.verbose, self.debug) @@ -84,10 +84,8 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output self.s2f_right = blocks.short_to_float_make(1, 32767) self.gain_left = blocks.multiply_const_ff(1, 1) self.gain_right = blocks.multiply_const_ff(1, 1) - self.resample_left = filter.rational_resampler_base_fff_make(2, self.get_sample_rate()/16000, [1]) - self.resample_right = filter.rational_resampler_base_fff_make(2, self.get_sample_rate()/16000, [1]) - self.connect((self.mp4, 0), self.s2f_left, self.gain_left, self.resample_left, (self, 0)) - self.connect((self.mp4, 1), self.s2f_right, self.gain_right, self.resample_right, (self, 1)) + self.connect((self.mp4, 0), self.s2f_left, self.gain_left, (self, 0)) + self.connect((self.mp4, 1), self.s2f_right, self.gain_right, (self, 1)) else: # output signed 16 bit integers (directly from decoder) self.connect((self.mp4, 0), (self, 0)) diff --git a/python/fic.py b/python/fic.py index 0b297cee..6a9524c6 100644 --- a/python/fic.py +++ b/python/fic.py @@ -155,4 +155,7 @@ def get_subch_info(self): return self.fibsink.get_subch_info() def get_programme_type(self): - return self.fibsink.get_programme_type() \ No newline at end of file + return self.fibsink.get_programme_type() + + def get_crc_passed(self): + return self.fibsink.get_crc_passed() \ No newline at end of file diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 08b9b151..2a579272 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -139,3 +139,4 @@ GR_SWIG_BLOCK_MAGIC2(dab, reed_solomon_encode_bb); GR_SWIG_BLOCK_MAGIC2(dab, mp4_encode_sb); %include "dab/mp2_encode_sb.h" GR_SWIG_BLOCK_MAGIC2(dab, mp2_encode_sb); + From 260543cfb9edb564fa62752d63de20785eda9fe0 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 16 Aug 2017 20:30:28 +0200 Subject: [PATCH 008/135] FIB_source: change structure to one subchannel per service and multiple services --- lib/fib_source_b_impl.cc | 46 ++++++++++++++++++---------------------- lib/fib_source_b_impl.h | 8 +++---- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index b6152a6a..4445c8d9 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -45,14 +45,13 @@ namespace gr { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 000 00110 000 00000 0100000000000000 00 0 0000000000000 00000000 - //service orga with number of service components (last 4 bits have to be modified) and without service component descrition (only 1 service with numSubCh of SubChannels) - const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - //000 00110 000 00010 0100000000000000 0 000 0001 + //service orga header + const char fib_source_b_impl::d_service_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; + //000 00100 000 00010 - //d_service_comp_description, has to be added for each service comp to d_service_orga (with change of Sub_channel ID!!) - const char fib_source_b_impl::d_service_comp_description[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; - //00 000000 000000 1 0 + //service orga for one service containing one subchannel + const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + // 0100000000000000 0 000 0001 00 000000 000000 00 //subchannel orga header, length has to be changed according to the number of subchannel-orga fields const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; @@ -230,7 +229,7 @@ namespace gr { if ((d_nFIBs_written % 3 == 0 && d_transmission_mode != 3) || (d_nFIBs_written % 4 == 0 && d_transmission_mode == 3)) { //////////////////////////////////////////////// -/// add first FIB with only MCI (max numSubCh = 7) +/// add first FIB with only MCI (max numSubCh = 5) //////////////////////////////////////////////// //ensemble info std::memcpy(out + d_offset, d_ensemble_info, d_size_ensemble_info); @@ -240,27 +239,24 @@ namespace gr { else CIF_counter(out + d_offset, d_nFIBs_written / 4); //service orga - std::memcpy(out + d_offset, d_service_orga, d_size_service_orga); - d_offset += d_size_service_orga; - //change number of service components in d_service_orga (bit manipulation) - bit_adaption(out + d_offset, d_num_subch, 4); - //service component description (numSubCh times; for every sub_channel different, belongs to d_service_orga) - for (int subch_count = 0; subch_count < d_num_subch; subch_count++) { - std::memcpy(out + d_offset, - d_service_comp_description, - d_size_service_comp_description); //add numSubCh with default values - d_offset += d_size_service_comp_description; - //change SubChID and priority for all not-primary channels - if (subch_count >= 1) { //is it not the first (=secondary) subchannel? - out[d_offset - 2] = 0; //all additional subchannels are secondary - //the SubChannel ID has to increase, to be different (count up from zero) - bit_adaption(out + d_offset - 2, subch_count, 6); - } + //header + std::memcpy(out + d_offset, d_service_orga_header, d_size_service_orga_header); + d_offset += d_size_service_orga_header; + //change FIG length depending on number of services + bit_adaption(out + d_offset - 8, 1 + 5*d_num_subch, 5); + //data field for every service (each containing one service component) + for (int service_count = 0; service_count < d_num_subch; service_count++) { + std::memcpy(out + d_offset, d_service_orga, d_size_service_orga); + d_offset += d_size_service_orga; + //change service Identifier + bit_adaption(out + d_offset - 24, service_count, 8); + //change subchannel ID + bit_adaption(out + d_offset - 2, service_count, 6); } //MCI is set, set EndMarker and padding if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) - for (int i = 0; i < 8; i++) { //find:: binde FIC.h ein und verwende die konstaten statt FIB_size + for (int i = 0; i < 8; i++) { out[i + d_offset] = 1; } } diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index cd02347f..5c684eab 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -32,7 +32,7 @@ namespace gr { * produces Fast Information Blocks (FIBs) according to the DAB standard and the input parameters * * @param transmission_mode transmission mode - * @param num_subch number of subchannels to be transmitted + * @param num_subch number of subchannels to be transmitted, each in a speparated service * @param ensemble_label string label of the DAB ensemble (max 16 characters) * @param programme_service_label string label of the DAB service (max 16 characters) * @param service_comp_label string label of the DAB service component (max 16 characters) @@ -54,10 +54,10 @@ namespace gr { const static int d_size_ensemble_info = 56; void CIF_counter(char *out_ptr, int counter);//implementation of the mod 20 and mod 250 counter - const static char d_service_orga[40]; //const + const static char d_service_orga_header[16]; //*const + const static int d_size_service_orga_header = 16; + const static char d_service_orga[40]; //*services const static int d_size_service_orga = 40; - const static char d_service_comp_description[16]; //*numSubCh - const static int d_size_service_comp_description = 16; const static char d_subchannel_orga_header[16]; //const const static int d_size_subchannel_orga_header = 16; const static char d_subchannel_orga_field[32]; //*numSubCh From 5ae9b92be90004b1dbc9ea7b1f3695d88477c44a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 16 Aug 2017 23:15:36 +0200 Subject: [PATCH 009/135] transmission mux bug fix --- lib/dab_transmission_frame_mux_bb_impl.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/dab_transmission_frame_mux_bb_impl.cc b/lib/dab_transmission_frame_mux_bb_impl.cc index 7473d1db..b33e3b54 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.cc +++ b/lib/dab_transmission_frame_mux_bb_impl.cc @@ -100,11 +100,9 @@ namespace gr { { // the first input is always the FIC ninput_items_required[0] = d_fic_len * (noutput_items / d_vlen_out); - // the second input is always the PRBS source - ninput_items_required[1] = d_cif_len * 8; for (int i = 0; i < d_num_subch; ++i) { // the amount of consumed data of each sub-channel depends on its size - ninput_items_required[i + 2] = d_subch_size[i] * d_cu_len * (noutput_items / d_vlen_out); + ninput_items_required[i + 1] = d_subch_size[i] * d_cu_len * d_num_cifs * (noutput_items / d_vlen_out); } } From 87641b082fda19597d4b580ded026d5e10a46f14 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 17 Aug 2017 09:47:02 +0200 Subject: [PATCH 010/135] FIB_source: add individual labels for each service --- grc/dab_fib_source_b.xml | 4 +- include/dab/fib_source_b.h | 2 +- lib/fib_source_b_impl.cc | 88 ++++++++++++++------------------------ lib/fib_source_b_impl.h | 16 ++----- 4 files changed, 38 insertions(+), 72 deletions(-) diff --git a/grc/dab_fib_source_b.xml b/grc/dab_fib_source_b.xml index 7beae2bb..ba7470f0 100644 --- a/grc/dab_fib_source_b.xml +++ b/grc/dab_fib_source_b.xml @@ -3,7 +3,7 @@ dab_fib_source_b DAB import dab - dab.fib_source_b($dab_mode, $num_subch, $ensemble_label, $programme_service_label, $service_comp_label, $service_comp_lang, $protection_mode, $data_rate_n) + dab.fib_source_b($dab_mode, $num_subch, $ensemble_label, $programme_service_labels, $service_comp_label, $service_comp_lang, $protection_mode, $data_rate_n) DAB Mode dab_mode @@ -38,7 +38,7 @@ Service label - programme_service_label + programme_service_labels string diff --git a/include/dab/fib_source_b.h b/include/dab/fib_source_b.h index 2d736e98..73c3e1ce 100644 --- a/include/dab/fib_source_b.h +++ b/include/dab/fib_source_b.h @@ -43,7 +43,7 @@ namespace gr { * class. dab::fib_source_b::make is the public interface for * creating new instances. */ - static sptr make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_label, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n); + static sptr make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n); }; } // namespace dab diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index 4445c8d9..9e557f71 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -98,40 +98,14 @@ namespace gr { 1, 0, 0}; //001 10101 0000 0 001 0100000000000000 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01010010 01100001 01100100 01101001 01101111 00110001 01011111 01011111 0111000111100100 - //Programme Service Component label - char fib_source_b_impl::d_service_comp_label[184] = {0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, - 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, - 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, - 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, - 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, - 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}; - //001 10110 0000 0 100 0 000 0000 0100000000000000 01000001 01110111 01100101 01110011 01101111 01101101 01100101 01011111 01001101 01101001 01111000 01011111 01010110 01101111 01101100 00110001 0000000011111111 - - //service component language - char fib_source_b_impl::d_service_comp_language[32] = {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0}; - //"000 00011 000 00101 0 0 000000 00001000"; - - /// d_SI_pointer array contains all SI for transmission. - const char *fib_source_b_impl::d_SI_pointer[ - d_num_SI_basic + d_num_SI_subch] = {d_ensemble_label, d_programme_service_label, d_service_comp_language, - d_service_comp_label}; - /// contains the lengths of the SI FIGs for transmission - const int fib_source_b_impl::d_SI_size[d_num_SI_basic + d_num_SI_subch] = {176, 176, 32, 184}; - fib_source_b::sptr fib_source_b::make(int transmission_mode, int num_subch, std::string ensemble_label, - std::string programme_service_label, std::string service_comp_label, uint8_t service_comp_lang, + std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n) { return gnuradio::get_initial_sptr (new fib_source_b_impl(transmission_mode, num_subch, ensemble_label, - programme_service_label, service_comp_label, service_comp_lang, protection_mode, + programme_service_labels, service_comp_label, service_comp_lang, protection_mode, data_rate_n)); } @@ -139,29 +113,32 @@ namespace gr { * The private constructor */ fib_source_b_impl::fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, - std::string programme_service_label, std::string service_comp_label, + std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n) : gr::sync_block("fib_source_b", gr::io_signature::make(0, 0, 0), gr::io_signature::make(1, 1, sizeof(char))), - d_transmission_mode(transmission_mode), d_num_subch(num_subch), d_nFIBs_written(0), d_nSI_written(0), - d_subch_iterate(0), d_protection_mode(protection_mode), d_data_rate_n(data_rate_n) + d_transmission_mode(transmission_mode), d_num_subch(num_subch), d_nFIBs_written(0), + d_protection_mode(protection_mode), d_data_rate_n(data_rate_n) { if (d_transmission_mode != 3) set_output_multiple((8 * FIB_LENGTH) * 3); else set_output_multiple((8 * FIB_LENGTH) * 4); - //write the labels with input strings once at beginning + //write the ensemble label with input string once at beginning write_label(d_ensemble_label + 32, ensemble_label); - write_label(d_programme_service_label + 32, programme_service_label); - write_label(d_service_comp_label + 40, service_comp_label); - //change service comp language - bit_adaption(d_service_comp_language + d_size_service_comp_language, service_comp_lang, 8); if (protection_mode.size() != num_subch) { throw std::invalid_argument((boost::format("size of vector protection_mode (%d) does not fit with number of subchannels (%d)") % protection_mode.size() % num_subch).str()); } if (data_rate_n.size() != num_subch) { throw std::invalid_argument((boost::format("size of vector data_rate_n (%d) does not fit with number of subchannels (%d)") % data_rate_n.size() % num_subch).str()); } + // init counter for iterating over the services + d_label_counter = 0; + d_service_labels = programme_service_labels; + // the string programme_service_labels containts num_subch * 16 chars, appended. Note that every subchannel is strutured in a different service in this implementation. + if (programme_service_labels.size() != 16*num_subch){ + throw std::invalid_argument((boost::format("size of service label strings is (%d) but should be %d * 16 = %d") % programme_service_labels.size() % num_subch % (16*num_subch)).str()); + } } /* @@ -338,29 +315,26 @@ namespace gr { /// write a not primary FIB with SI ///////////////////////////////////////////////// do { //fill FIB with FIGs - //write one SI-FIG in FIB - std::memcpy(out + d_offset, d_SI_pointer[d_nSI_written], d_SI_size[d_nSI_written]); - //change content if subchannel specific SI - d_offset += d_SI_size[d_nSI_written]; - - //SI for each subchannel? - if (d_nSI_written + 1 >= d_num_SI_basic) //a subchannel specific FIG has to be written d_num_subch times - { - if (++d_subch_iterate >= d_num_subch) //all subchannels were written; go on with next SI - { - d_nSI_written++; - d_subch_iterate = 0; - } - } else //basic SI -> just write once - { - d_nSI_written++; + if(d_label_counter == 0){ + // write ensemble label + std::memcpy(out + d_offset, d_ensemble_label, d_size_label); + d_offset += d_size_label; + ++d_label_counter; } - //start from first FIG when all FIGs are written - if (d_nSI_written >= d_num_SI_basic + d_num_SI_subch) { - d_nSI_written = 0; + else{ + // write service label + std::memcpy(out + d_offset, d_programme_service_label, d_size_label); + // change label + std::string label = d_service_labels.substr((d_label_counter-1)*16, 16); + write_label(out + d_offset + 32, label); + d_offset += d_size_label; + bit_adaption(out + d_offset - 144, d_label_counter-1, 8); + if(++d_label_counter > d_num_subch){ + d_label_counter = 0; + } + } - } while ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= - d_SI_size[d_nSI_written]); //check if there is enough space for next FIG + } while ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= 176); //check if there is enough space for next FIG //FIB is filled, set endmarker and padding if ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index 5c684eab..6a743b40 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -66,27 +66,19 @@ namespace gr { std::vector d_protection_mode, d_data_rate_n; //Service Information + int d_label_counter; + const static int d_size_label = 176; static char d_ensemble_label[176]; //21*8+8, ensemble label (FIG 1/0) const static int d_size_ensemble_label = 176; static char d_programme_service_label[176]; //21*8+8, service label (FIG 1/0) const static int d_size_service_label = 176; - static char d_service_comp_label[184]; //21*8+8, service component label (FIG 1/0) - const static int d_size_service_comp_label = 184; - static char d_service_comp_language[32]; //3*8+8, service component language; short form (FIG 0/5) - const static int d_size_service_comp_language = 32; - - const static int d_num_SI_basic = 4; //no subchannel specific SI - const static int d_num_SI_subch = 0; //SI for a specific subchannel - const static char *d_SI_pointer[d_num_SI_basic + - d_num_SI_subch]; //pointer to iterate the SI data in non-primary FIBs, saves the start adress from each SI_Array - const static int d_SI_size[d_num_SI_basic + d_num_SI_subch]; //Saves the lengths of the SI_Arrays - int d_nSI_written, d_subch_iterate; + std::string d_service_labels; int write_label(char *out_ptr, std::string label, int num_chars = 16);//default for 16 characters (16 byte) public: fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, - std::string programme_service_label, std::string service_comp_label, uint8_t service_comp_lang, + std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n); ~fib_source_b_impl(); From 3f6896ca5ef99e95fccf646ff8c4ae5e7c22f01c Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 17 Aug 2017 12:10:56 +0200 Subject: [PATCH 011/135] GUI transmitter: add dab/dab+ selection for each service individually --- grc/dab_fib_source_b.xml | 5 + include/dab/fib_source_b.h | 2 +- lib/fib_source_b_impl.cc | 16 +- lib/fib_source_b_impl.h | 3 +- python/GUI/main.py | 76 ++--- python/GUI/user_frontend.py | 313 ++++++++++++++++---- python/GUI/user_frontend.ui | 539 +++++++++++++++++++++++++++++----- python/GUI/usrp_dabplus_tx.py | 25 +- 8 files changed, 797 insertions(+), 182 deletions(-) diff --git a/grc/dab_fib_source_b.xml b/grc/dab_fib_source_b.xml index ba7470f0..287d458b 100644 --- a/grc/dab_fib_source_b.xml +++ b/grc/dab_fib_source_b.xml @@ -61,6 +61,11 @@ data_rate_n raw + + DAB+ + dabplus + raw + out byte diff --git a/include/dab/fib_source_b.h b/include/dab/fib_source_b.h index 73c3e1ce..653c3c16 100644 --- a/include/dab/fib_source_b.h +++ b/include/dab/fib_source_b.h @@ -43,7 +43,7 @@ namespace gr { * class. dab::fib_source_b::make is the public interface for * creating new instances. */ - static sptr make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n); + static sptr make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); }; } // namespace dab diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index 9e557f71..27e135ab 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -50,8 +50,8 @@ namespace gr { //000 00100 000 00010 //service orga for one service containing one subchannel - const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - // 0100000000000000 0 000 0001 00 000000 000000 00 + const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; + // 0100000000000000 0 000 0001 00 111111 000000 00 //subchannel orga header, length has to be changed according to the number of subchannel-orga fields const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; @@ -101,12 +101,12 @@ namespace gr { fib_source_b::sptr fib_source_b::make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, - const std::vector &protection_mode, const std::vector &data_rate_n) + const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus) { return gnuradio::get_initial_sptr (new fib_source_b_impl(transmission_mode, num_subch, ensemble_label, programme_service_labels, service_comp_label, service_comp_lang, protection_mode, - data_rate_n)); + data_rate_n, dabplus)); } /* @@ -115,12 +115,12 @@ namespace gr { fib_source_b_impl::fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, - const std::vector &data_rate_n) + const std::vector &data_rate_n, const std::vector &dabplus) : gr::sync_block("fib_source_b", gr::io_signature::make(0, 0, 0), gr::io_signature::make(1, 1, sizeof(char))), d_transmission_mode(transmission_mode), d_num_subch(num_subch), d_nFIBs_written(0), - d_protection_mode(protection_mode), d_data_rate_n(data_rate_n) + d_protection_mode(protection_mode), d_data_rate_n(data_rate_n), d_dabplus(dabplus) { if (d_transmission_mode != 3) set_output_multiple((8 * FIB_LENGTH) * 3); else set_output_multiple((8 * FIB_LENGTH) * 4); @@ -229,6 +229,10 @@ namespace gr { bit_adaption(out + d_offset - 24, service_count, 8); //change subchannel ID bit_adaption(out + d_offset - 2, service_count, 6); + //change DAB+ mode if not DAB+ but DAB + if(d_dabplus[service_count] != 1){ + bit_adaption(out + d_offset -8, 0, 6); + } } //MCI is set, set EndMarker and padding if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index 6a743b40..edbe727e 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -43,6 +43,7 @@ namespace gr { class fib_source_b_impl : public fib_source_b { private: int d_transmission_mode; //transmission mode + std::vector d_dabplus; int d_offset; uint16_t d_nFIBs_written; //counts totally written FIBs void bit_adaption(char *out_ptr, int number, @@ -79,7 +80,7 @@ namespace gr { public: fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, - const std::vector &protection_mode, const std::vector &data_rate_n); + const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); ~fib_source_b_impl(); diff --git a/python/GUI/main.py b/python/GUI/main.py index 6c0dcfc1..64610e21 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -123,31 +123,31 @@ def __init__(self, parent=None): {"label": self.t_label_comp1, "data_rate_label": self.t_label_rate1, "data_rate": self.t_spin_rate1, "protection_label": self.t_label_prot1, "protection": self.t_spin_prot1, "enabled": True, "src_label": self.t_label_comp_src1, "src_path_disp": self.t_label_path_src1, - "src_btn": self.t_btn_path_src1, "src_path":"None"}, + "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1}, {"label": self.t_label_comp2, "data_rate_label": self.t_label_rate2, "data_rate": self.t_spin_rate2, "protection_label": self.t_label_prot2, "protection": self.t_spin_prot2, "enabled": False, "src_label": self.t_label_comp_src2, "src_path_disp": self.t_label_path_src2, - "src_btn": self.t_btn_path_src2, "src_path":"None"}, + "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2}, {"label": self.t_label_comp3, "data_rate_label": self.t_label_rate3, "data_rate": self.t_spin_rate3, "protection_label": self.t_label_prot3, "protection": self.t_spin_prot3, "enabled": False, "src_label": self.t_label_comp_src3, "src_path_disp": self.t_label_path_src3, - "src_btn": self.t_btn_path_src3, "src_path":"None"}, + "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3}, {"label": self.t_label_comp4, "data_rate_label": self.t_label_rate4, "data_rate": self.t_spin_rate4, "protection_label": self.t_label_prot4, "protection": self.t_spin_prot4, "enabled": False, "src_label": self.t_label_comp_src4, "src_path_disp": self.t_label_path_src4, - "src_btn": self.t_btn_path_src4, "src_path":"None"}, + "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4}, {"label": self.t_label_comp5, "data_rate_label": self.t_label_rate5, "data_rate": self.t_spin_rate5, "protection_label": self.t_label_prot5, "protection": self.t_spin_prot5, "enabled": False, "src_label": self.t_label_comp_src5, "src_path_disp": self.t_label_path_src5, - "src_btn": self.t_btn_path_src5, "src_path":"None"}, + "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5}, {"label": self.t_label_comp6, "data_rate_label": self.t_label_rate6, "data_rate": self.t_spin_rate6, "protection_label": self.t_label_prot6, "protection": self.t_spin_prot6, "enabled": False, "src_label": self.t_label_comp_src6, "src_path_disp": self.t_label_path_src6, - "src_btn": self.t_btn_path_src6, "src_path":"None"}, + "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6}, {"label": self.t_label_comp7, "data_rate_label": self.t_label_rate7, "data_rate": self.t_spin_rate7, "protection_label": self.t_label_prot7, "protection": self.t_spin_prot7, "enabled": False, "src_label": self.t_label_comp_src7, "src_path_disp": self.t_label_path_src7, - "src_btn": self.t_btn_path_src7, "src_path":"None"}] + "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7}] # update service components initially to hide the service components 2-7 self.t_update_service_components() # provide suggestions for language combo box @@ -631,6 +631,10 @@ def t_update_service_components(self): component["src_label"].hide() component["src_path_disp"].hide() component["src_btn"].hide() + component["label_label"].hide() + component["edit_label"].hide() + component["combo_dabplus"].hide() + component["btn_record"].hide() else: component["label"].show() component["data_rate_label"].show() @@ -640,6 +644,10 @@ def t_update_service_components(self): component["src_label"].show() component["src_path_disp"].show() component["src_btn"].show() + component["label_label"].show() + component["edit_label"].show() + component["combo_dabplus"].show() + component["btn_record"].show() def t_init_transmitter(self): self.statusBar.showMessage("initializing transmitter...") @@ -649,16 +657,29 @@ def t_init_transmitter(self): protection_array = [None] * self.t_spin_num_subch.value() data_rate_n_array = [None] * self.t_spin_num_subch.value() audio_paths = ["None"] * self.t_spin_num_subch.value() + merged_service_string = "" + dabplus_types = [True] * self.t_spin_num_subch.value() + record_states = [False] * self.t_spin_num_subch.value() for i in range(0, self.t_spin_num_subch.value()): + # write array with protection modes protection_array[i] = self.components[i]["protection"].value() + # write array with data rates data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # check audio paths if self.components[i]["src_path"] is "None": # highlight the path which is not selected self.components[i]["src_path_disp"].setStyleSheet('color: red') arguments_incomplete = True - print "path " + str(i+1) + " not selected" + self.statusBar.showMessage("path " + str(i+1) + " not selected") else: audio_paths[i] = self.components[i]["src_path"] + # write service labels + merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) + # write dabplus types + dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) + # write record states + record_states[i] = (True if self.components[i]["btn_record"].isDefault() else False) + print merged_service_string # check if File path for sink is chosen if option enabled if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): @@ -667,32 +688,19 @@ def t_init_transmitter(self): if arguments_incomplete is False: # init transmitter - if self.t_combo_dabplus.currentIndex() is 1: - # transmitting in DAB mode - self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), self.t_spinbox_frequency.value(), - self.t_spin_num_subch.value(), - str(self.t_edit_ensemble_label.text()), - str(self.t_edit_service_label.text()), - self.t_combo_language.currentIndex(), - protection_array, data_rate_n_array, 48000, - audio_paths, - self.t_spin_listen_to_component.value(), - self.t_rbtn_USRP.isChecked(), - str(self.t_label_sink.text())+ "/" +str(self.t_edit_file_name.text())) - else: - # transmitting in DAB+ mode - self.my_transmitter = usrp_dabplus_tx.usrp_dabplus_tx(self.t_spin_dab_mode.value(), - self.t_spinbox_frequency.value(), - self.t_spin_num_subch.value(), - str(self.t_edit_ensemble_label.text()), - str(self.t_edit_service_label.text()), - self.t_combo_language.currentIndex(), - protection_array, data_rate_n_array, - audio_paths, - self.t_spin_listen_to_component.value(), - self.t_rbtn_USRP.isChecked(), - str(self.t_label_sink.text()) + "/" + str( - self.t_edit_file_name.text())) + self.my_transmitter = usrp_dabplus_tx.usrp_dabplus_tx(self.t_spin_dab_mode.value(), + self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + merged_service_string, + self.t_combo_language.currentIndex(), + protection_array, data_rate_n_array, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + dabplus_types, record_states, + str(self.t_label_sink.text()) + "/" + str( + self.t_edit_file_name.text())) # enable play button self.t_btn_play.setEnabled(True) diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 102033d2..840fd1e9 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(816, 664) + MainWindow.resize(1051, 737) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -293,7 +293,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_32.addLayout(self.verticalLayout_14) self.label_fic = QtGui.QLabel(self.tab_reception) self.label_fic.setMinimumSize(QtCore.QSize(365, 55)) - self.label_fic.setMaximumSize(QtCore.QSize(365, 60)) + self.label_fic.setMaximumSize(QtCore.QSize(365, 55)) self.label_fic.setFrameShape(QtGui.QFrame.Box) self.label_fic.setFrameShadow(QtGui.QFrame.Sunken) self.label_fic.setLineWidth(2) @@ -493,11 +493,6 @@ def setupUi(self, MainWindow): self.t_spin_dab_mode.setMaximum(4) self.t_spin_dab_mode.setObjectName(_fromUtf8("t_spin_dab_mode")) self.horizontalLayout_31.addWidget(self.t_spin_dab_mode) - self.t_combo_dabplus = QtGui.QComboBox(self.tab_transmission) - self.t_combo_dabplus.setObjectName(_fromUtf8("t_combo_dabplus")) - self.t_combo_dabplus.addItem(_fromUtf8("")) - self.t_combo_dabplus.addItem(_fromUtf8("")) - self.horizontalLayout_31.addWidget(self.t_combo_dabplus) self.verticalLayout_5.addLayout(self.horizontalLayout_31) self.line_4 = QtGui.QFrame(self.tab_transmission) self.line_4.setFrameShape(QtGui.QFrame.HLine) @@ -508,7 +503,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 392, 876)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -811, 477, 1269)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -540,25 +535,40 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(2, QtGui.QFormLayout.LabelRole, self.t_label_comp1) self.t_label_rate1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate1.setObjectName(_fromUtf8("t_label_rate1")) - self.formLayout_3.setWidget(3, QtGui.QFormLayout.LabelRole, self.t_label_rate1) + self.formLayout_3.setWidget(4, QtGui.QFormLayout.LabelRole, self.t_label_rate1) self.t_spin_rate1 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate1.setMaximum(999) self.t_spin_rate1.setProperty("value", 112) self.t_spin_rate1.setObjectName(_fromUtf8("t_spin_rate1")) - self.formLayout_3.setWidget(3, QtGui.QFormLayout.FieldRole, self.t_spin_rate1) + self.formLayout_3.setWidget(4, QtGui.QFormLayout.FieldRole, self.t_spin_rate1) self.t_label_prot1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot1.setObjectName(_fromUtf8("t_label_prot1")) - self.formLayout_3.setWidget(4, QtGui.QFormLayout.LabelRole, self.t_label_prot1) + self.formLayout_3.setWidget(5, QtGui.QFormLayout.LabelRole, self.t_label_prot1) self.t_spin_prot1 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot1.setMaximum(3) self.t_spin_prot1.setProperty("value", 2) self.t_spin_prot1.setObjectName(_fromUtf8("t_spin_prot1")) - self.formLayout_3.setWidget(4, QtGui.QFormLayout.FieldRole, self.t_spin_prot1) + self.formLayout_3.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_spin_prot1) self.t_label_comp_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src1.setObjectName(_fromUtf8("t_label_comp_src1")) - self.formLayout_3.setWidget(5, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) + self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) self.horizontalLayout_13 = QtGui.QHBoxLayout() self.horizontalLayout_13.setObjectName(_fromUtf8("horizontalLayout_13")) + self.t_btn_record1 = QtGui.QPushButton(self.scrollAreaWidgetContents) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.t_btn_record1.sizePolicy().hasHeightForWidth()) + self.t_btn_record1.setSizePolicy(sizePolicy) + self.t_btn_record1.setMinimumSize(QtCore.QSize(27, 27)) + self.t_btn_record1.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record1.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record1.setIcon(icon) + self.t_btn_record1.setDefault(False) + self.t_btn_record1.setFlat(False) + self.t_btn_record1.setObjectName(_fromUtf8("t_btn_record1")) + self.horizontalLayout_13.addWidget(self.t_btn_record1) self.t_label_path_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -578,7 +588,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src1 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src1.setObjectName(_fromUtf8("t_btn_path_src1")) self.horizontalLayout_13.addWidget(self.t_btn_path_src1) - self.formLayout_3.setLayout(5, QtGui.QFormLayout.FieldRole, self.horizontalLayout_13) + self.formLayout_3.setLayout(6, QtGui.QFormLayout.FieldRole, self.horizontalLayout_13) self.t_label_comp2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp2.setEnabled(True) font = QtGui.QFont() @@ -587,27 +597,34 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp2.setFont(font) self.t_label_comp2.setObjectName(_fromUtf8("t_label_comp2")) - self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_comp2) + self.formLayout_3.setWidget(7, QtGui.QFormLayout.LabelRole, self.t_label_comp2) self.t_label_rate2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate2.setObjectName(_fromUtf8("t_label_rate2")) - self.formLayout_3.setWidget(7, QtGui.QFormLayout.LabelRole, self.t_label_rate2) + self.formLayout_3.setWidget(9, QtGui.QFormLayout.LabelRole, self.t_label_rate2) self.t_spin_rate2 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate2.setMaximum(999) self.t_spin_rate2.setProperty("value", 112) self.t_spin_rate2.setObjectName(_fromUtf8("t_spin_rate2")) - self.formLayout_3.setWidget(7, QtGui.QFormLayout.FieldRole, self.t_spin_rate2) + self.formLayout_3.setWidget(9, QtGui.QFormLayout.FieldRole, self.t_spin_rate2) self.t_label_prot2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot2.setObjectName(_fromUtf8("t_label_prot2")) - self.formLayout_3.setWidget(8, QtGui.QFormLayout.LabelRole, self.t_label_prot2) + self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_prot2) self.t_spin_prot2 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot2.setProperty("value", 2) self.t_spin_prot2.setObjectName(_fromUtf8("t_spin_prot2")) - self.formLayout_3.setWidget(8, QtGui.QFormLayout.FieldRole, self.t_spin_prot2) + self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_spin_prot2) self.t_label_comp_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src2.setObjectName(_fromUtf8("t_label_comp_src2")) - self.formLayout_3.setWidget(9, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) + self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) self.horizontalLayout_14 = QtGui.QHBoxLayout() self.horizontalLayout_14.setObjectName(_fromUtf8("horizontalLayout_14")) + self.t_btn_record2 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record2.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record2.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record2.setIcon(icon) + self.t_btn_record2.setObjectName(_fromUtf8("t_btn_record2")) + self.horizontalLayout_14.addWidget(self.t_btn_record2) self.t_label_path_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -622,7 +639,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src2 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src2.setObjectName(_fromUtf8("t_btn_path_src2")) self.horizontalLayout_14.addWidget(self.t_btn_path_src2) - self.formLayout_3.setLayout(9, QtGui.QFormLayout.FieldRole, self.horizontalLayout_14) + self.formLayout_3.setLayout(11, QtGui.QFormLayout.FieldRole, self.horizontalLayout_14) self.t_label_comp3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp3.setEnabled(True) font = QtGui.QFont() @@ -631,27 +648,34 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp3.setFont(font) self.t_label_comp3.setObjectName(_fromUtf8("t_label_comp3")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_comp3) + self.formLayout_3.setWidget(12, QtGui.QFormLayout.LabelRole, self.t_label_comp3) self.t_label_rate3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate3.setObjectName(_fromUtf8("t_label_rate3")) - self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_rate3) + self.formLayout_3.setWidget(14, QtGui.QFormLayout.LabelRole, self.t_label_rate3) self.t_spin_rate3 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate3.setMaximum(999) self.t_spin_rate3.setProperty("value", 112) self.t_spin_rate3.setObjectName(_fromUtf8("t_spin_rate3")) - self.formLayout_3.setWidget(11, QtGui.QFormLayout.FieldRole, self.t_spin_rate3) + self.formLayout_3.setWidget(14, QtGui.QFormLayout.FieldRole, self.t_spin_rate3) self.t_label_prot3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot3.setObjectName(_fromUtf8("t_label_prot3")) - self.formLayout_3.setWidget(12, QtGui.QFormLayout.LabelRole, self.t_label_prot3) + self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_prot3) self.t_spin_prot3 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot3.setProperty("value", 2) self.t_spin_prot3.setObjectName(_fromUtf8("t_spin_prot3")) - self.formLayout_3.setWidget(12, QtGui.QFormLayout.FieldRole, self.t_spin_prot3) + self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_spin_prot3) self.t_label_comp_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src3.setObjectName(_fromUtf8("t_label_comp_src3")) - self.formLayout_3.setWidget(13, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) + self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) self.horizontalLayout_15 = QtGui.QHBoxLayout() self.horizontalLayout_15.setObjectName(_fromUtf8("horizontalLayout_15")) + self.t_btn_record3 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record3.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record3.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record3.setIcon(icon) + self.t_btn_record3.setObjectName(_fromUtf8("t_btn_record3")) + self.horizontalLayout_15.addWidget(self.t_btn_record3) self.t_label_path_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -666,7 +690,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src3 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src3.setObjectName(_fromUtf8("t_btn_path_src3")) self.horizontalLayout_15.addWidget(self.t_btn_path_src3) - self.formLayout_3.setLayout(13, QtGui.QFormLayout.FieldRole, self.horizontalLayout_15) + self.formLayout_3.setLayout(16, QtGui.QFormLayout.FieldRole, self.horizontalLayout_15) self.t_label_comp4 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -674,27 +698,34 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp4.setFont(font) self.t_label_comp4.setObjectName(_fromUtf8("t_label_comp4")) - self.formLayout_3.setWidget(14, QtGui.QFormLayout.LabelRole, self.t_label_comp4) + self.formLayout_3.setWidget(17, QtGui.QFormLayout.LabelRole, self.t_label_comp4) self.t_label_rate4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate4.setObjectName(_fromUtf8("t_label_rate4")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_rate4) + self.formLayout_3.setWidget(19, QtGui.QFormLayout.LabelRole, self.t_label_rate4) self.t_spin_rate4 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate4.setMaximum(999) self.t_spin_rate4.setProperty("value", 112) self.t_spin_rate4.setObjectName(_fromUtf8("t_spin_rate4")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_spin_rate4) + self.formLayout_3.setWidget(19, QtGui.QFormLayout.FieldRole, self.t_spin_rate4) self.t_label_prot4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot4.setObjectName(_fromUtf8("t_label_prot4")) - self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_prot4) + self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_prot4) self.t_spin_prot4 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot4.setProperty("value", 2) self.t_spin_prot4.setObjectName(_fromUtf8("t_spin_prot4")) - self.formLayout_3.setWidget(16, QtGui.QFormLayout.FieldRole, self.t_spin_prot4) + self.formLayout_3.setWidget(20, QtGui.QFormLayout.FieldRole, self.t_spin_prot4) self.t_label_comp_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src4.setObjectName(_fromUtf8("t_label_comp_src4")) - self.formLayout_3.setWidget(17, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) + self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) self.horizontalLayout_16 = QtGui.QHBoxLayout() self.horizontalLayout_16.setObjectName(_fromUtf8("horizontalLayout_16")) + self.t_btn_record4 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record4.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record4.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record4.setIcon(icon) + self.t_btn_record4.setObjectName(_fromUtf8("t_btn_record4")) + self.horizontalLayout_16.addWidget(self.t_btn_record4) self.t_label_path_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -709,7 +740,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src4 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src4.setObjectName(_fromUtf8("t_btn_path_src4")) self.horizontalLayout_16.addWidget(self.t_btn_path_src4) - self.formLayout_3.setLayout(17, QtGui.QFormLayout.FieldRole, self.horizontalLayout_16) + self.formLayout_3.setLayout(21, QtGui.QFormLayout.FieldRole, self.horizontalLayout_16) self.t_label_comp5 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -717,27 +748,34 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp5.setFont(font) self.t_label_comp5.setObjectName(_fromUtf8("t_label_comp5")) - self.formLayout_3.setWidget(18, QtGui.QFormLayout.LabelRole, self.t_label_comp5) + self.formLayout_3.setWidget(22, QtGui.QFormLayout.LabelRole, self.t_label_comp5) self.t_label_rate5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate5.setObjectName(_fromUtf8("t_label_rate5")) - self.formLayout_3.setWidget(19, QtGui.QFormLayout.LabelRole, self.t_label_rate5) + self.formLayout_3.setWidget(24, QtGui.QFormLayout.LabelRole, self.t_label_rate5) self.t_spin_rate5 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate5.setMaximum(999) self.t_spin_rate5.setProperty("value", 112) self.t_spin_rate5.setObjectName(_fromUtf8("t_spin_rate5")) - self.formLayout_3.setWidget(19, QtGui.QFormLayout.FieldRole, self.t_spin_rate5) + self.formLayout_3.setWidget(24, QtGui.QFormLayout.FieldRole, self.t_spin_rate5) self.t_label_prot5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot5.setObjectName(_fromUtf8("t_label_prot5")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_prot5) + self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_prot5) self.t_spin_prot5 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot5.setProperty("value", 2) self.t_spin_prot5.setObjectName(_fromUtf8("t_spin_prot5")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.FieldRole, self.t_spin_prot5) + self.formLayout_3.setWidget(25, QtGui.QFormLayout.FieldRole, self.t_spin_prot5) self.t_label_comp_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src5.setObjectName(_fromUtf8("t_label_comp_src5")) - self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) + self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) self.horizontalLayout_17 = QtGui.QHBoxLayout() self.horizontalLayout_17.setObjectName(_fromUtf8("horizontalLayout_17")) + self.t_btn_record5 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record5.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record5.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record5.setIcon(icon) + self.t_btn_record5.setObjectName(_fromUtf8("t_btn_record5")) + self.horizontalLayout_17.addWidget(self.t_btn_record5) self.t_label_path_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -752,7 +790,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src5 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src5.setObjectName(_fromUtf8("t_btn_path_src5")) self.horizontalLayout_17.addWidget(self.t_btn_path_src5) - self.formLayout_3.setLayout(21, QtGui.QFormLayout.FieldRole, self.horizontalLayout_17) + self.formLayout_3.setLayout(26, QtGui.QFormLayout.FieldRole, self.horizontalLayout_17) self.t_label_comp6 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -760,27 +798,34 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp6.setFont(font) self.t_label_comp6.setObjectName(_fromUtf8("t_label_comp6")) - self.formLayout_3.setWidget(22, QtGui.QFormLayout.LabelRole, self.t_label_comp6) + self.formLayout_3.setWidget(27, QtGui.QFormLayout.LabelRole, self.t_label_comp6) self.t_label_rate6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate6.setObjectName(_fromUtf8("t_label_rate6")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.LabelRole, self.t_label_rate6) + self.formLayout_3.setWidget(29, QtGui.QFormLayout.LabelRole, self.t_label_rate6) self.t_spin_rate6 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate6.setMaximum(999) self.t_spin_rate6.setProperty("value", 112) self.t_spin_rate6.setObjectName(_fromUtf8("t_spin_rate6")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.FieldRole, self.t_spin_rate6) + self.formLayout_3.setWidget(29, QtGui.QFormLayout.FieldRole, self.t_spin_rate6) self.t_label_prot6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot6.setObjectName(_fromUtf8("t_label_prot6")) - self.formLayout_3.setWidget(24, QtGui.QFormLayout.LabelRole, self.t_label_prot6) + self.formLayout_3.setWidget(30, QtGui.QFormLayout.LabelRole, self.t_label_prot6) self.t_spin_prot6 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot6.setProperty("value", 2) self.t_spin_prot6.setObjectName(_fromUtf8("t_spin_prot6")) - self.formLayout_3.setWidget(24, QtGui.QFormLayout.FieldRole, self.t_spin_prot6) + self.formLayout_3.setWidget(30, QtGui.QFormLayout.FieldRole, self.t_spin_prot6) self.t_label_comp_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src6.setObjectName(_fromUtf8("t_label_comp_src6")) - self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) + self.formLayout_3.setWidget(31, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) self.horizontalLayout_18 = QtGui.QHBoxLayout() self.horizontalLayout_18.setObjectName(_fromUtf8("horizontalLayout_18")) + self.t_btn_record6 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record6.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record6.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record6.setIcon(icon) + self.t_btn_record6.setObjectName(_fromUtf8("t_btn_record6")) + self.horizontalLayout_18.addWidget(self.t_btn_record6) self.t_label_path_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -795,7 +840,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src6 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src6.setObjectName(_fromUtf8("t_btn_path_src6")) self.horizontalLayout_18.addWidget(self.t_btn_path_src6) - self.formLayout_3.setLayout(25, QtGui.QFormLayout.FieldRole, self.horizontalLayout_18) + self.formLayout_3.setLayout(31, QtGui.QFormLayout.FieldRole, self.horizontalLayout_18) self.t_label_comp7 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -803,28 +848,35 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp7.setFont(font) self.t_label_comp7.setObjectName(_fromUtf8("t_label_comp7")) - self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp7) + self.formLayout_3.setWidget(32, QtGui.QFormLayout.LabelRole, self.t_label_comp7) self.t_label_rate7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate7.setObjectName(_fromUtf8("t_label_rate7")) - self.formLayout_3.setWidget(27, QtGui.QFormLayout.LabelRole, self.t_label_rate7) + self.formLayout_3.setWidget(34, QtGui.QFormLayout.LabelRole, self.t_label_rate7) self.t_spin_rate7 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate7.setMaximum(999) self.t_spin_rate7.setProperty("value", 112) self.t_spin_rate7.setObjectName(_fromUtf8("t_spin_rate7")) - self.formLayout_3.setWidget(27, QtGui.QFormLayout.FieldRole, self.t_spin_rate7) + self.formLayout_3.setWidget(34, QtGui.QFormLayout.FieldRole, self.t_spin_rate7) self.t_label_prot7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot7.setObjectName(_fromUtf8("t_label_prot7")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.LabelRole, self.t_label_prot7) + self.formLayout_3.setWidget(35, QtGui.QFormLayout.LabelRole, self.t_label_prot7) self.t_spin_prot7 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_prot7.setEnabled(True) self.t_spin_prot7.setProperty("value", 2) self.t_spin_prot7.setObjectName(_fromUtf8("t_spin_prot7")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.FieldRole, self.t_spin_prot7) + self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_spin_prot7) self.t_label_comp_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src7.setObjectName(_fromUtf8("t_label_comp_src7")) - self.formLayout_3.setWidget(29, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) + self.formLayout_3.setWidget(36, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) self.horizontalLayout_19 = QtGui.QHBoxLayout() self.horizontalLayout_19.setObjectName(_fromUtf8("horizontalLayout_19")) + self.t_btn_record7 = QtGui.QPushButton(self.scrollAreaWidgetContents) + self.t_btn_record7.setMaximumSize(QtCore.QSize(27, 27)) + self.t_btn_record7.setText(_fromUtf8("")) + icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) + self.t_btn_record7.setIcon(icon) + self.t_btn_record7.setObjectName(_fromUtf8("t_btn_record7")) + self.horizontalLayout_19.addWidget(self.t_btn_record7) self.t_label_path_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) @@ -839,7 +891,119 @@ def setupUi(self, MainWindow): self.t_btn_path_src7 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src7.setObjectName(_fromUtf8("t_btn_path_src7")) self.horizontalLayout_19.addWidget(self.t_btn_path_src7) - self.formLayout_3.setLayout(29, QtGui.QFormLayout.FieldRole, self.horizontalLayout_19) + self.formLayout_3.setLayout(36, QtGui.QFormLayout.FieldRole, self.horizontalLayout_19) + self.t_label_label1 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label1.setObjectName(_fromUtf8("t_label_label1")) + self.formLayout_3.setWidget(3, QtGui.QFormLayout.LabelRole, self.t_label_label1) + self.t_label_label2 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label2.setObjectName(_fromUtf8("t_label_label2")) + self.formLayout_3.setWidget(8, QtGui.QFormLayout.LabelRole, self.t_label_label2) + self.t_label_label3 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label3.setObjectName(_fromUtf8("t_label_label3")) + self.formLayout_3.setWidget(13, QtGui.QFormLayout.LabelRole, self.t_label_label3) + self.t_label_label4 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label4.setObjectName(_fromUtf8("t_label_label4")) + self.formLayout_3.setWidget(18, QtGui.QFormLayout.LabelRole, self.t_label_label4) + self.t_label_label5 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label5.setObjectName(_fromUtf8("t_label_label5")) + self.formLayout_3.setWidget(23, QtGui.QFormLayout.LabelRole, self.t_label_label5) + self.t_label_label6 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label6.setObjectName(_fromUtf8("t_label_label6")) + self.formLayout_3.setWidget(28, QtGui.QFormLayout.LabelRole, self.t_label_label6) + self.t_label_label7 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_label7.setObjectName(_fromUtf8("t_label_label7")) + self.formLayout_3.setWidget(33, QtGui.QFormLayout.LabelRole, self.t_label_label7) + self.t_edit_service_label1 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label1.setObjectName(_fromUtf8("t_edit_service_label1")) + self.formLayout_3.setWidget(3, QtGui.QFormLayout.FieldRole, self.t_edit_service_label1) + self.t_edit_service_label2 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label2.setObjectName(_fromUtf8("t_edit_service_label2")) + self.formLayout_3.setWidget(8, QtGui.QFormLayout.FieldRole, self.t_edit_service_label2) + self.t_edit_service_label3 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label3.setObjectName(_fromUtf8("t_edit_service_label3")) + self.formLayout_3.setWidget(13, QtGui.QFormLayout.FieldRole, self.t_edit_service_label3) + self.t_edit_service_label4 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label4.setObjectName(_fromUtf8("t_edit_service_label4")) + self.formLayout_3.setWidget(18, QtGui.QFormLayout.FieldRole, self.t_edit_service_label4) + self.t_edit_service_label5 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label5.setObjectName(_fromUtf8("t_edit_service_label5")) + self.formLayout_3.setWidget(23, QtGui.QFormLayout.FieldRole, self.t_edit_service_label5) + self.t_edit_service_label6 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label6.setObjectName(_fromUtf8("t_edit_service_label6")) + self.formLayout_3.setWidget(28, QtGui.QFormLayout.FieldRole, self.t_edit_service_label6) + self.t_edit_service_label7 = QtGui.QLineEdit(self.scrollAreaWidgetContents) + self.t_edit_service_label7.setObjectName(_fromUtf8("t_edit_service_label7")) + self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) + self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) + spacerItem10 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus1.addItem(spacerItem10) + self.t_combo_dabplus1 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus1.setObjectName(_fromUtf8("t_combo_dabplus1")) + self.t_combo_dabplus1.addItem(_fromUtf8("")) + self.t_combo_dabplus1.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus1.addWidget(self.t_combo_dabplus1) + self.formLayout_3.setLayout(2, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus1) + self.t_layout_combo_dabplus2 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus2.setObjectName(_fromUtf8("t_layout_combo_dabplus2")) + spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus2.addItem(spacerItem11) + self.t_combo_dabplus2 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus2.setObjectName(_fromUtf8("t_combo_dabplus2")) + self.t_combo_dabplus2.addItem(_fromUtf8("")) + self.t_combo_dabplus2.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus2.addWidget(self.t_combo_dabplus2) + self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) + self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) + spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus3.addItem(spacerItem12) + self.t_combo_dabplus3 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus3.setObjectName(_fromUtf8("t_combo_dabplus3")) + self.t_combo_dabplus3.addItem(_fromUtf8("")) + self.t_combo_dabplus3.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus3.addWidget(self.t_combo_dabplus3) + self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) + self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) + spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus4.addItem(spacerItem13) + self.t_combo_dabplus4 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus4.setObjectName(_fromUtf8("t_combo_dabplus4")) + self.t_combo_dabplus4.addItem(_fromUtf8("")) + self.t_combo_dabplus4.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus4.addWidget(self.t_combo_dabplus4) + self.formLayout_3.setLayout(17, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) + self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) + spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus5.addItem(spacerItem14) + self.t_combo_dabplus5 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus5.setObjectName(_fromUtf8("t_combo_dabplus5")) + self.t_combo_dabplus5.addItem(_fromUtf8("")) + self.t_combo_dabplus5.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus5.addWidget(self.t_combo_dabplus5) + self.formLayout_3.setLayout(22, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) + self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) + spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus6.addItem(spacerItem15) + self.t_combo_dabplus6 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus6.setObjectName(_fromUtf8("t_combo_dabplus6")) + self.t_combo_dabplus6.addItem(_fromUtf8("")) + self.t_combo_dabplus6.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus6.addWidget(self.t_combo_dabplus6) + self.formLayout_3.setLayout(27, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) + self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() + self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) + spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus7.addItem(spacerItem16) + self.t_combo_dabplus7 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_dabplus7.setObjectName(_fromUtf8("t_combo_dabplus7")) + self.t_combo_dabplus7.addItem(_fromUtf8("")) + self.t_combo_dabplus7.addItem(_fromUtf8("")) + self.t_layout_combo_dabplus7.addWidget(self.t_combo_dabplus7) + self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus7) self.verticalLayout_4.addLayout(self.formLayout_3) self.line_15 = QtGui.QFrame(self.scrollAreaWidgetContents) self.line_15.setFrameShape(QtGui.QFrame.HLine) @@ -926,8 +1090,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem10) + spacerItem17 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem17) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -942,8 +1106,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem11) + spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem18) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -1004,8 +1168,8 @@ def setupUi(self, MainWindow): self.verticalLayout.addWidget(self.mode_tabs) self.horitontal_layout_dev_mode_bottom = QtGui.QHBoxLayout() self.horitontal_layout_dev_mode_bottom.setObjectName(_fromUtf8("horitontal_layout_dev_mode_bottom")) - spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horitontal_layout_dev_mode_bottom.addItem(spacerItem12) + spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horitontal_layout_dev_mode_bottom.addItem(spacerItem19) self.verticalLayout_11 = QtGui.QVBoxLayout() self.verticalLayout_11.setObjectName(_fromUtf8("verticalLayout_11")) self.horitontal_layout_dev_mode_bottom.addLayout(self.verticalLayout_11) @@ -1017,7 +1181,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) + self.mode_tabs.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1072,8 +1236,6 @@ def retranslateUi(self, MainWindow): self.t_label_sink.setText(_translate("MainWindow", "select path", None)) self.t_btn_file_path.setText(_translate("MainWindow", "...", None)) self.label_8.setText(_translate("MainWindow", "Transmission Mode", None)) - self.t_combo_dabplus.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus.setItemText(1, _translate("MainWindow", "DAB", None)) self.t_label_heading_service_comp.setText(_translate("MainWindow", "Service Components", None)) self.t_label_comp1.setText(_translate("MainWindow", "Component 1", None)) self.t_label_rate1.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) @@ -1117,6 +1279,27 @@ def retranslateUi(self, MainWindow): self.t_label_comp_src7.setText(_translate("MainWindow", "Audio Source", None)) self.t_label_path_src7.setText(_translate("MainWindow", "select audio", None)) self.t_btn_path_src7.setText(_translate("MainWindow", "...", None)) + self.t_label_label1.setText(_translate("MainWindow", "Name", None)) + self.t_label_label2.setText(_translate("MainWindow", "Name", None)) + self.t_label_label3.setText(_translate("MainWindow", "Name", None)) + self.t_label_label4.setText(_translate("MainWindow", "Name", None)) + self.t_label_label5.setText(_translate("MainWindow", "Name", None)) + self.t_label_label6.setText(_translate("MainWindow", "Name", None)) + self.t_label_label7.setText(_translate("MainWindow", "Name", None)) + self.t_combo_dabplus1.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus1.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus2.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus2.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus3.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus3.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus4.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus4.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus5.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus5.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus6.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus6.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_dabplus7.setItemText(0, _translate("MainWindow", "DAB+", None)) + self.t_combo_dabplus7.setItemText(1, _translate("MainWindow", "DAB", None)) self.t_label_increase_num_subch_info.setText(_translate("MainWindow", "increase \"Number of channels\" for more components", None)) self.label_12.setText(_translate("MainWindow", "Ensemble info", None)) self.label_13.setText(_translate("MainWindow", "Label", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 2102a0da..3bf53661 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,8 +6,8 @@ 0 0 - 816 - 664 + 1051 + 737 @@ -85,7 +85,7 @@ true - 0 + 1 @@ -1034,20 +1034,6 @@
- - - - - DAB+ - - - - - DAB - - - - @@ -1066,9 +1052,9 @@ 0 - 0 - 392 - 876 + -811 + 477 + 1269 @@ -1114,14 +1100,14 @@ - + Data rate [kbit/s] - + 999 @@ -1131,14 +1117,14 @@ - + Protection Mode - + 3 @@ -1148,15 +1134,49 @@ - + Audio Source - + + + + + + 0 + 0 + + + + + 27 + 27 + + + + + 27 + 27 + + + + + + + + + + false + + + false + + + @@ -1200,7 +1220,7 @@ - + true @@ -1217,14 +1237,14 @@ - + Data rate [kbit/s] - + 999 @@ -1234,29 +1254,45 @@ - + Protection Mode - + 2 - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1291,7 +1327,7 @@ - + true @@ -1308,14 +1344,14 @@ - + Data rate [kbit/s] - + 999 @@ -1325,29 +1361,45 @@ - + Protection Mode - + 2 - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1382,7 +1434,7 @@ - + @@ -1396,14 +1448,14 @@ - + Data rate [kbit/s] - + 999 @@ -1413,29 +1465,45 @@ - + Protection Mode - + 2 - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1470,7 +1538,7 @@ - + @@ -1484,14 +1552,14 @@ - + Data rate [kbit/s] - + 999 @@ -1501,29 +1569,45 @@ - + Protection Mode - + 2 - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1558,7 +1642,7 @@ - + @@ -1572,14 +1656,14 @@ - + Data rate [kbit/s] - + 999 @@ -1589,29 +1673,45 @@ - + Protection Mode - + 2 - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1646,7 +1746,7 @@ - + @@ -1660,14 +1760,14 @@ - + Data rate [kbit/s] - + 999 @@ -1677,14 +1777,14 @@ - + Protection Mode - + true @@ -1694,15 +1794,31 @@ - + Audio Source - + + + + + + 27 + 27 + + + + + + + + + + @@ -1737,6 +1853,293 @@ + + + + Name + + + + + + + Name + + + + + + + Name + + + + + + + Name + + + + + + + Name + + + + + + + Name + + + + + + + Name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + DAB+ + + + + + DAB + + + + + + diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py index 557bed0a..70357a21 100644 --- a/python/GUI/usrp_dabplus_tx.py +++ b/python/GUI/usrp_dabplus_tx.py @@ -30,7 +30,7 @@ class usrp_dabplus_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, sink_path = "dab_iq_generated.dat"): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, record_states, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -47,6 +47,8 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.subch_sizes = np.multiply(self.data_rates_n, 6) self.src_paths = src_paths self.use_usrp = use_usrp + self.dabplus_types = dabplus_types + self.record_sates = record_states self.sink_path = sink_path self.selected_audio = selected_audio self.volume = 80 @@ -55,7 +57,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label # FIC ######################## # source - self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n) + self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n, self.dabplus_types) # encoder self.fic_enc = dab.fic_encode(self.dp) @@ -66,6 +68,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.f2s_left_converters = [None] * self.num_subch self.f2s_right_converters = [None] * self.num_subch self.mp4_encoders = [None] * self.num_subch + self.mp2_encoders = [None] * self.num_subch self.rs_encoders = [None] * self.num_subch self.msc_encoders = [None] * self.num_subch for i in range(0, self.num_subch): @@ -74,9 +77,13 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) - # mp4 encoder and Reed-Solomon encoder - self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) - self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) + if self.dabplus_types[i] is 1: + # mp4 encoder and Reed-Solomon encoder + self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) + self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) + else: + # mp2 encoder + self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n[i], 2, 48000) # encoder self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) @@ -113,8 +120,12 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label ######################## self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) for i in range(0, self.num_subch): - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + if self.dabplus_types[i] is 1: + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i + 1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) From f6962450a0e619770de71994a3446b74d5ef5158 Mon Sep 17 00:00:00 2001 From: Felix Wunsch Date: Thu, 17 Aug 2017 16:40:35 +0200 Subject: [PATCH 012/135] add a std::runtime_error if aac enc init fails. --- lib/mp4_encode_sb_impl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mp4_encode_sb_impl.cc b/lib/mp4_encode_sb_impl.cc index a75a68cc..4d6f1834 100644 --- a/lib/mp4_encode_sb_impl.cc +++ b/lib/mp4_encode_sb_impl.cc @@ -69,6 +69,7 @@ namespace gr { GR_LOG_INFO(d_logger, "AAC enc init succeeded"); } else { GR_LOG_ERROR(d_logger, "AAC enc init failed"); + throw std::runtime_error("AAC enc init failed"); } // check encoder status if (aacEncInfo(d_aac_encoder, &info) != AACENC_OK) { From c34c68c7e37e2188bfa642adf6e930f4fb70930f Mon Sep 17 00:00:00 2001 From: Felix Wunsch Date: Thu, 17 Aug 2017 16:56:09 +0200 Subject: [PATCH 013/135] add another throw statement --- lib/mp4_encode_sb_impl.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/mp4_encode_sb_impl.cc b/lib/mp4_encode_sb_impl.cc index 4d6f1834..927eba15 100644 --- a/lib/mp4_encode_sb_impl.cc +++ b/lib/mp4_encode_sb_impl.cc @@ -74,7 +74,9 @@ namespace gr { // check encoder status if (aacEncInfo(d_aac_encoder, &info) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to get the encoder info"); + throw std::runtime_error("AAC enc init failed"); } + // set input size (number of items per channel(in this case one item is a int16_t)) d_input_size = info.frameLength; GR_LOG_INFO(d_logger, format("AAC Encoding: framelen = %d") % info.frameLength); From 0b5e672786f4ae396cca2fc5c16ca822d6ba722b Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 17 Aug 2017 20:06:04 +0200 Subject: [PATCH 014/135] GUI: enable physical audio source (e.g. microphone) as msc audio source --- python/GUI/main.py | 117 ++++++++++----- python/GUI/user_frontend.py | 195 +++++++++++++----------- python/GUI/user_frontend.ui | 272 ++++++++++++++++++++++------------ python/GUI/usrp_dabplus_rx.py | 41 +++-- python/GUI/usrp_dabplus_tx.py | 26 ++-- 5 files changed, 410 insertions(+), 241 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 64610e21..3660d6b6 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -14,13 +14,18 @@ import sip import os +resolution_width = 0 +resolution_height = 0 + class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def __init__(self, parent=None): super(DABstep, self).__init__(parent) self.setupUi(self) + self.resize(800, 600) # window title self.setWindowTitle("DABstep - A DAB/DAB+ transceiver app") - self.resize(5000, 5000) + self.screen_width = resolution_width + self.screen_height = resolution_height # show logo if it exists if os.path.exists("DAB_logo.png"): self.label_logo.setText("") @@ -87,6 +92,8 @@ def __init__(self, parent=None): # DEVELOPER MODE ###################################################################### self.dev_mode_active = False + # hide scroll area + self.dev_scroll_area.hide() # hide close button and just show open button self.btn_dev_mode_close.hide() # dev mode open button pressed @@ -108,8 +115,6 @@ def __init__(self, parent=None): self.label_fic.hide() self.led_fic.hide() self.label_label_fic.hide() - self.label_label_fic.setFont(font) - self.label_label_msc.setFont(font) self.content_count = 0 ###################################################################### @@ -174,6 +179,13 @@ def __init__(self, parent=None): self.t_btn_path_src5.pressed.connect(self.t_set_subch_path5) self.t_btn_path_src6.pressed.connect(self.t_set_subch_path6) self.t_btn_path_src7.pressed.connect(self.t_set_subch_path7) + self.t_btn_record1.pressed.connect(self.t_toggle_record1) + self.t_btn_record2.pressed.connect(self.t_toggle_record2) + self.t_btn_record3.pressed.connect(self.t_toggle_record3) + self.t_btn_record4.pressed.connect(self.t_toggle_record4) + self.t_btn_record5.pressed.connect(self.t_toggle_record5) + self.t_btn_record6.pressed.connect(self.t_toggle_record6) + self.t_btn_record7.pressed.connect(self.t_toggle_record7) # set volume if volume slider is changed self.t_slider_volume.valueChanged.connect(self.t_set_volume) @@ -226,7 +238,7 @@ def init_receiver(self): self.label_path.setStyleSheet('color: red') else: # set up and start flowgraph - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() # status bar @@ -304,7 +316,7 @@ def selected_subch(self): self.audio_bit_rate = 48000 else: self.audio_bit_rate = 32000 - #self.dabplus = service_data['DAB+'] + self.dabplus = service_data['DAB+'] # display info to selected sub-channel # service info @@ -362,18 +374,12 @@ def play_audio(self): self.snr_timer.stop() self.firecode_timer.stop() self.my_receiver.stop() - if True: - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), - self.spinbox_frequency.value(), self.bit_rate, - self.address, self.size, - self.protection, self.audio_bit_rate, - self.src_is_USRP, self.file_path, self.recorder) - else: - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), - self.spinbox_frequency.value(), self.bit_rate, - self.address, self.size, - self.protection, - self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver.start() self.statusBar.showMessage("Audio playing.") self.dev_mode_init() @@ -419,16 +425,10 @@ def record_audio(self): self.btn_stop.setEnabled(True) self.recorder = True # start flowgraph - if self.dabplus: - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, - self.protection, self.audio_bit_rate, - self.src_is_USRP, self.file_path, self.recorder) - else: - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), - self.spinbox_frequency.value(), self.bit_rate, - self.address, self.size, - self.protection, - self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver.start() self.statusBar.showMessage("Recording audio ...") @@ -500,23 +500,31 @@ def get_sample_rate(self): ################################ def dev_mode_init(self): + available_height = self.screen_height-200 + # constellation plot + self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.constellation) + self.constellation.setMaximumHeight(available_height/3) + self.constellation.setMaximumWidth(available_height/3*2) + self.constellation.hide() # FFT plot self.fft_plot = sip.wrapinstance(self.my_receiver.fft_plot.pyqwidget(), QtGui.QWidget) self.vertical_layout_dev_mode_right.addWidget(self.fft_plot) + self.fft_plot.setMaximumHeight(available_height/3) + self.fft_plot.setMaximumWidth(available_height/3*2) self.fft_plot.hide() # Waterfall plot self.waterfall_plot = sip.wrapinstance(self.my_receiver.waterfall_plot.pyqwidget(), QtGui.QWidget) self.vertical_layout_dev_mode_right.addWidget(self.waterfall_plot) + self.waterfall_plot.setMaximumHeight(available_height/3) + self.waterfall_plot.setMaximumWidth(available_height/3*2) self.waterfall_plot.hide() - # constellation plot - self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) - self.vertical_layout_dev_mode_right.addWidget(self.constellation) - self.constellation.hide() # if dev mode is initialized, we can enable the dev mode open button self.btn_dev_mode_open.setEnabled(True) def dev_mode_open(self): self.dev_mode_active = True + self.dev_scroll_area.show() # hide open button and show close button self.btn_dev_mode_open.hide() self.btn_dev_mode_close.show() @@ -533,9 +541,12 @@ def dev_mode_open(self): self.label_label_fic.show() self.label_fic.setText("") self.content_count = 0 + # resize window width + self.showMaximized() def dev_mode_close(self): self.dev_mode_active = False + self.dev_scroll_area.hide() # hide close button and show open button self.btn_dev_mode_close.hide() self.btn_dev_mode_open.show() @@ -549,13 +560,11 @@ def dev_mode_close(self): self.label_fic.hide() self.led_fic.hide() self.label_label_fic.hide() - print "key" - self.resize(2000, 2000) - + self.resize(800, 600) def update_firecode(self): if self.dev_mode_active: - if self.content_count >=69: + if self.content_count >=80: self.label_firecode.setText("") self.label_fic.setText("") self.content_count = 0 @@ -677,8 +686,6 @@ def t_init_transmitter(self): merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) # write dabplus types dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) - # write record states - record_states[i] = (True if self.components[i]["btn_record"].isDefault() else False) print merged_service_string # check if File path for sink is chosen if option enabled @@ -698,7 +705,7 @@ def t_init_transmitter(self): audio_paths, self.t_spin_listen_to_component.value(), self.t_rbtn_USRP.isChecked(), - dabplus_types, record_states, + dabplus_types, str(self.t_label_sink.text()) + "/" + str( self.t_edit_file_name.text())) @@ -740,6 +747,7 @@ def t_set_subch_path1(self): # display path in path label self.components[0]["src_path_disp"].setText(path) self.components[0]["src_path_disp"].setStyleSheet('color: black') + self.t_btn_record1.setFlat(False) def t_set_subch_path2(self): path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") @@ -795,6 +803,34 @@ def t_set_subch_path7(self): self.components[6]["src_path_disp"].setText(path) self.components[7]["src_path_disp"].setStyleSheet('color: black') + def t_toggle_record1(self): + self.t_label_path_src1.setText("microphone") + self.components[0]["src_path"] = "mic" + + def t_toggle_record2(self): + self.t_label_path_src2.setText("microphone") + self.components[1]["src_path"] = "mic" + + def t_toggle_record3(self): + self.t_label_path_src3.setText("microphone") + self.components[2]["src_path"] = "mic" + + def t_toggle_record4(self): + self.t_label_path_src4.setText("microphone") + self.components[3]["src_path"] = "mic" + + def t_toggle_record5(self): + self.t_label_path_src5.setText("microphone") + self.components[4]["src_path"] = "mic" + + def t_toggle_record6(self): + self.t_label_path_src6.setText("microphone") + self.components[5]["src_path"] = "mic" + + def t_toggle_record7(self): + self.t_label_path_src7.setText("microphone") + self.components[6]["src_path"] = "mic" + class lookup_tables: languages = [ @@ -904,6 +940,11 @@ class lookup_tables: def main(): app = QtGui.QApplication(sys.argv) + global resolution_width + resolution_width = app.desktop().screenGeometry().width() + global resolution_height + resolution_height = app.desktop().screenGeometry().height() + form = DABstep() form.show() app.exec_() diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 840fd1e9..a1318ba1 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(1051, 737) + MainWindow.resize(992, 739) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -61,8 +61,8 @@ def setupUi(self, MainWindow): self.tab_reception.setObjectName(_fromUtf8("tab_reception")) self.verticalLayout_2 = QtGui.QVBoxLayout(self.tab_reception) self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) - self.horizontalLayout_2 = QtGui.QHBoxLayout() - self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) + self.horizontal_layout_reception = QtGui.QHBoxLayout() + self.horizontal_layout_reception.setObjectName(_fromUtf8("horizontal_layout_reception")) self.verticalLayout_6 = QtGui.QVBoxLayout() self.verticalLayout_6.setObjectName(_fromUtf8("verticalLayout_6")) self.horizontalLayout_8 = QtGui.QHBoxLayout() @@ -153,12 +153,12 @@ def setupUi(self, MainWindow): self.table_mci.horizontalHeader().setDefaultSectionSize(100) self.table_mci.horizontalHeader().setStretchLastSection(True) self.verticalLayout_6.addWidget(self.table_mci) - self.horizontalLayout_2.addLayout(self.verticalLayout_6) + self.horizontal_layout_reception.addLayout(self.verticalLayout_6) self.line_8 = QtGui.QFrame(self.tab_reception) self.line_8.setFrameShape(QtGui.QFrame.VLine) self.line_8.setFrameShadow(QtGui.QFrame.Sunken) self.line_8.setObjectName(_fromUtf8("line_8")) - self.horizontalLayout_2.addWidget(self.line_8) + self.horizontal_layout_reception.addWidget(self.line_8) self.verticalLayout_7 = QtGui.QVBoxLayout() self.verticalLayout_7.setObjectName(_fromUtf8("verticalLayout_7")) self.horizontalLayout_27 = QtGui.QHBoxLayout() @@ -236,33 +236,14 @@ def setupUi(self, MainWindow): self.vertical_layout_dev_mode_right_vertical.setObjectName(_fromUtf8("vertical_layout_dev_mode_right_vertical")) self.horizontalLayout_29 = QtGui.QHBoxLayout() self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) - self.label_label_msc = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_label_msc.setFont(font) - self.label_label_msc.setObjectName(_fromUtf8("label_label_msc")) - self.horizontalLayout_29.addWidget(self.label_label_msc) - self.verticalLayout_13 = QtGui.QVBoxLayout() - self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) - spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem3) - self.led_msc = KLed(self.tab_reception) - self.led_msc.setLook(KLed.Sunken) - self.led_msc.setDarkFactor(300) - self.led_msc.setObjectName(_fromUtf8("led_msc")) - self.verticalLayout_13.addWidget(self.led_msc) - spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem4) - self.horizontalLayout_29.addLayout(self.verticalLayout_13) self.label_firecode = QtGui.QLabel(self.tab_reception) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_firecode.sizePolicy().hasHeightForWidth()) self.label_firecode.setSizePolicy(sizePolicy) - self.label_firecode.setMinimumSize(QtCore.QSize(365, 55)) - self.label_firecode.setMaximumSize(QtCore.QSize(365, 55)) + self.label_firecode.setMinimumSize(QtCore.QSize(365, 80)) + self.label_firecode.setMaximumSize(QtCore.QSize(365, 80)) self.label_firecode.setFrameShape(QtGui.QFrame.Box) self.label_firecode.setFrameShadow(QtGui.QFrame.Sunken) self.label_firecode.setLineWidth(2) @@ -270,38 +251,65 @@ def setupUi(self, MainWindow): self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_firecode.setObjectName(_fromUtf8("label_firecode")) self.horizontalLayout_29.addWidget(self.label_firecode) - self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_29) - self.horizontalLayout_32 = QtGui.QHBoxLayout() - self.horizontalLayout_32.setObjectName(_fromUtf8("horizontalLayout_32")) - self.label_label_fic = QtGui.QLabel(self.tab_reception) + self.verticalLayout_13 = QtGui.QVBoxLayout() + self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) + spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem3) + self.led_msc = KLed(self.tab_reception) + self.led_msc.setLook(KLed.Sunken) + self.led_msc.setDarkFactor(300) + self.led_msc.setObjectName(_fromUtf8("led_msc")) + self.verticalLayout_13.addWidget(self.led_msc) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem4) + self.horizontalLayout_29.addLayout(self.verticalLayout_13) + self.label_label_msc = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() font.setBold(True) font.setWeight(75) - self.label_label_fic.setFont(font) - self.label_label_fic.setObjectName(_fromUtf8("label_label_fic")) - self.horizontalLayout_32.addWidget(self.label_label_fic) - self.verticalLayout_14 = QtGui.QVBoxLayout() - self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) - spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem5) - self.led_fic = KLed(self.tab_reception) - self.led_fic.setLook(KLed.Sunken) - self.led_fic.setObjectName(_fromUtf8("led_fic")) - self.verticalLayout_14.addWidget(self.led_fic) - spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem6) - self.horizontalLayout_32.addLayout(self.verticalLayout_14) + self.label_label_msc.setFont(font) + self.label_label_msc.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) + self.label_label_msc.setObjectName(_fromUtf8("label_label_msc")) + self.horizontalLayout_29.addWidget(self.label_label_msc) + spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_29.addItem(spacerItem5) + self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_29) + self.horizontalLayout_32 = QtGui.QHBoxLayout() + self.horizontalLayout_32.setObjectName(_fromUtf8("horizontalLayout_32")) self.label_fic = QtGui.QLabel(self.tab_reception) - self.label_fic.setMinimumSize(QtCore.QSize(365, 55)) - self.label_fic.setMaximumSize(QtCore.QSize(365, 55)) + self.label_fic.setMinimumSize(QtCore.QSize(365, 80)) + self.label_fic.setMaximumSize(QtCore.QSize(365, 80)) self.label_fic.setFrameShape(QtGui.QFrame.Box) self.label_fic.setFrameShadow(QtGui.QFrame.Sunken) self.label_fic.setLineWidth(2) self.label_fic.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_fic.setObjectName(_fromUtf8("label_fic")) self.horizontalLayout_32.addWidget(self.label_fic) + self.verticalLayout_14 = QtGui.QVBoxLayout() + self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) + spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem6) + self.led_fic = KLed(self.tab_reception) + self.led_fic.setLook(KLed.Sunken) + self.led_fic.setObjectName(_fromUtf8("led_fic")) + self.verticalLayout_14.addWidget(self.led_fic) + spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem7) + self.horizontalLayout_32.addLayout(self.verticalLayout_14) + self.label_label_fic = QtGui.QLabel(self.tab_reception) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_label_fic.setFont(font) + self.label_label_fic.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_label_fic.setObjectName(_fromUtf8("label_label_fic")) + self.horizontalLayout_32.addWidget(self.label_label_fic) + spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_32.addItem(spacerItem8) self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_32) self.verticalLayout_7.addLayout(self.vertical_layout_dev_mode_right_vertical) + spacerItem9 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem9) self.line_6 = QtGui.QFrame(self.tab_reception) self.line_6.setFrameShape(QtGui.QFrame.HLine) self.line_6.setFrameShadow(QtGui.QFrame.Sunken) @@ -367,8 +375,8 @@ def setupUi(self, MainWindow): self.line_9.setFrameShadow(QtGui.QFrame.Sunken) self.line_9.setObjectName(_fromUtf8("line_9")) self.verticalLayout_7.addWidget(self.line_9) - spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem7) + spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem10) self.label_2 = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() font.setBold(True) @@ -412,14 +420,33 @@ def setupUi(self, MainWindow): self.slider_volume.setObjectName(_fromUtf8("slider_volume")) self.horizontalLayout_4.addWidget(self.slider_volume) self.verticalLayout_7.addLayout(self.horizontalLayout_4) - self.horizontalLayout_2.addLayout(self.verticalLayout_7) + self.horizontal_layout_reception.addLayout(self.verticalLayout_7) + self.line_12 = QtGui.QFrame(self.tab_reception) + self.line_12.setFrameShape(QtGui.QFrame.VLine) + self.line_12.setFrameShadow(QtGui.QFrame.Sunken) + self.line_12.setObjectName(_fromUtf8("line_12")) + self.horizontal_layout_reception.addWidget(self.line_12) + self.dev_scroll_area = QtGui.QScrollArea(self.tab_reception) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.dev_scroll_area.sizePolicy().hasHeightForWidth()) + self.dev_scroll_area.setSizePolicy(sizePolicy) + self.dev_scroll_area.setMinimumSize(QtCore.QSize(0, 0)) + self.dev_scroll_area.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.dev_scroll_area.setWidgetResizable(True) + self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) + self.dev_scroll_area_content = QtGui.QWidget() + self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 87, 602)) + self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) + self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) + self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) self.vertical_layout_dev_mode_right = QtGui.QVBoxLayout() self.vertical_layout_dev_mode_right.setObjectName(_fromUtf8("vertical_layout_dev_mode_right")) - self.horizontalLayout_2.addLayout(self.vertical_layout_dev_mode_right) - self.verticalLayout_2.addLayout(self.horizontalLayout_2) - self.test_layout = QtGui.QVBoxLayout() - self.test_layout.setObjectName(_fromUtf8("test_layout")) - self.verticalLayout_2.addLayout(self.test_layout) + self.verticalLayout_12.addLayout(self.vertical_layout_dev_mode_right) + self.dev_scroll_area.setWidget(self.dev_scroll_area_content) + self.horizontal_layout_reception.addWidget(self.dev_scroll_area) + self.verticalLayout_2.addLayout(self.horizontal_layout_reception) self.mode_tabs.addTab(self.tab_reception, _fromUtf8("")) self.tab_transmission = QtGui.QWidget() self.tab_transmission.setObjectName(_fromUtf8("tab_transmission")) @@ -436,8 +463,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem8) + spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem11) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -483,8 +510,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_10) self.horizontalLayout_31 = QtGui.QHBoxLayout() self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem9) + spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem12) self.label_8 = QtGui.QLabel(self.tab_transmission) self.label_8.setObjectName(_fromUtf8("label_8")) self.horizontalLayout_31.addWidget(self.label_8) @@ -503,7 +530,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -811, 477, 1269)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 448, 1269)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -936,8 +963,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) - spacerItem10 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus1.addItem(spacerItem10) + spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus1.addItem(spacerItem13) self.t_combo_dabplus1 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus1.setObjectName(_fromUtf8("t_combo_dabplus1")) self.t_combo_dabplus1.addItem(_fromUtf8("")) @@ -946,8 +973,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(2, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus1) self.t_layout_combo_dabplus2 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus2.setObjectName(_fromUtf8("t_layout_combo_dabplus2")) - spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus2.addItem(spacerItem11) + spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus2.addItem(spacerItem14) self.t_combo_dabplus2 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus2.setObjectName(_fromUtf8("t_combo_dabplus2")) self.t_combo_dabplus2.addItem(_fromUtf8("")) @@ -956,8 +983,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) - spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus3.addItem(spacerItem12) + spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus3.addItem(spacerItem15) self.t_combo_dabplus3 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus3.setObjectName(_fromUtf8("t_combo_dabplus3")) self.t_combo_dabplus3.addItem(_fromUtf8("")) @@ -966,8 +993,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) - spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus4.addItem(spacerItem13) + spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus4.addItem(spacerItem16) self.t_combo_dabplus4 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus4.setObjectName(_fromUtf8("t_combo_dabplus4")) self.t_combo_dabplus4.addItem(_fromUtf8("")) @@ -976,8 +1003,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(17, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) - spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus5.addItem(spacerItem14) + spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus5.addItem(spacerItem17) self.t_combo_dabplus5 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus5.setObjectName(_fromUtf8("t_combo_dabplus5")) self.t_combo_dabplus5.addItem(_fromUtf8("")) @@ -986,8 +1013,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(22, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) - spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus6.addItem(spacerItem15) + spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus6.addItem(spacerItem18) self.t_combo_dabplus6 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus6.setObjectName(_fromUtf8("t_combo_dabplus6")) self.t_combo_dabplus6.addItem(_fromUtf8("")) @@ -996,8 +1023,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(27, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) - spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus7.addItem(spacerItem16) + spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus7.addItem(spacerItem19) self.t_combo_dabplus7 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus7.setObjectName(_fromUtf8("t_combo_dabplus7")) self.t_combo_dabplus7.addItem(_fromUtf8("")) @@ -1090,8 +1117,8 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem17 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem17) + spacerItem20 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem20) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -1106,8 +1133,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem18) + spacerItem21 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem21) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -1166,14 +1193,6 @@ def setupUi(self, MainWindow): self.verticalLayout_3.addLayout(self.horizontalLayout_7) self.mode_tabs.addTab(self.tab_transmission, _fromUtf8("")) self.verticalLayout.addWidget(self.mode_tabs) - self.horitontal_layout_dev_mode_bottom = QtGui.QHBoxLayout() - self.horitontal_layout_dev_mode_bottom.setObjectName(_fromUtf8("horitontal_layout_dev_mode_bottom")) - spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horitontal_layout_dev_mode_bottom.addItem(spacerItem19) - self.verticalLayout_11 = QtGui.QVBoxLayout() - self.verticalLayout_11.setObjectName(_fromUtf8("verticalLayout_11")) - self.horitontal_layout_dev_mode_bottom.addLayout(self.verticalLayout_11) - self.verticalLayout.addLayout(self.horitontal_layout_dev_mode_bottom) MainWindow.setCentralWidget(self.centralwidget) self.statusBar = QtGui.QStatusBar(MainWindow) self.statusBar.setAutoFillBackground(False) @@ -1181,7 +1200,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(1) + self.mode_tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1210,10 +1229,10 @@ def retranslateUi(self, MainWindow): self.label_country.setText(_translate("MainWindow", "Country", None)) self.label_snr.setText(_translate("MainWindow", "reception: ", None)) self.label_7.setText(_translate("MainWindow", "dB", None)) - self.label_label_msc.setText(_translate("MainWindow", "MSC", None)) self.label_firecode.setText(_translate("MainWindow", "

Superframes:

", None)) - self.label_label_fic.setText(_translate("MainWindow", "FIC", None)) + self.label_label_msc.setText(_translate("MainWindow", "MSC", None)) self.label_fic.setText(_translate("MainWindow", "

FIC:

", None)) + self.label_label_fic.setText(_translate("MainWindow", "FIC", None)) self.label_service.setText(_translate("MainWindow", "SERVICE", None)) self.label_programme_type.setText(_translate("MainWindow", "programme type\n" "", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 3bf53661..12b31c4f 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,8 +6,8 @@ 0 0 - 1051 - 737 + 992 + 739 @@ -85,7 +85,7 @@ true - 1 + 0 @@ -93,7 +93,7 @@ - + @@ -438,15 +438,42 @@ - - - - 75 - true - + + + + 0 + 0 + + + + + 365 + 80 + + + + + 365 + 80 + + + + QFrame::Box + + + QFrame::Sunken + + + 2 + + + 0 - MSC + <html><head/><body><p>Superframes:</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -491,23 +518,50 @@ - - - - 0 - 0 - + + + + 75 + true + + + + MSC + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 365 - 55 + 80 365 - 55 + 80 @@ -519,34 +573,14 @@ 2 - - 0 - - <html><head/><body><p>Superframes:</p></body></html> + <html><head/><body><p>FIC:</p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 75 - true - - - - FIC - - - @@ -585,40 +619,51 @@ - - - - 365 - 55 - - - - - 365 - 55 - - - - QFrame::Box - - - QFrame::Sunken - - - 2 + + + + 75 + true + - <html><head/><body><p>FIC:</p></body></html> + FIC - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -862,13 +907,54 @@
- + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + true + + + + + 0 + 0 + 87 + 602 + + + + + + + + +
- - - @@ -1052,8 +1138,8 @@ 0 - -811 - 477 + 0 + 448 1269 @@ -1167,7 +1253,9 @@ - + + + false @@ -1289,7 +1377,9 @@ - + + +
@@ -1396,7 +1486,9 @@ - + + +
@@ -1500,7 +1592,9 @@ - + + +
@@ -1604,7 +1698,9 @@ - + + +
@@ -1708,7 +1804,9 @@ - + + +
@@ -1815,7 +1913,9 @@ - + + +
@@ -2468,26 +2568,6 @@
- - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - diff --git a/python/GUI/usrp_dabplus_rx.py b/python/GUI/usrp_dabplus_rx.py index 7fe1ef04..86a8fa22 100644 --- a/python/GUI/usrp_dabplus_rx.py +++ b/python/GUI/usrp_dabplus_rx.py @@ -32,16 +32,18 @@ class usrp_dabplus_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, use_usrp, src_path, record_audio = False, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, record_audio = False, sink_path = "None"): gr.top_block.__init__(self) self.dab_mode = dab_mode self.verbose = False self.sample_rate = 2e6 + self.dabplus = dabplus self.use_usrp = use_usrp self.src_path = src_path self.record_audio = record_audio self.sink_path = sink_path + gr.log.set_level("warn") ######################## # source @@ -96,7 +98,15 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## # MSC decoder and audio sink ######################## - self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) + if self.dabplus: + self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) + else: + self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) + self.mp2_dec = dab.mp2_decode_bs_make(bit_rate) + self.s2f_left = blocks.short_to_float_make(1, 32767) + self.s2f_right = blocks.short_to_float_make(1, 32767) + self.gain_left = blocks.multiply_const_ff(1, 1) + self.gain_right = blocks.multiply_const_ff(1, 1) self.audio = audio.sink_make(audio_bit_rate) ######################## @@ -104,17 +114,24 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## self.connect(self.src, self.fft_plot) self.connect(self.src, self.waterfall_plot) - #self.connect(self.src, self.time_plot) self.connect(self.src, self.demod, (self.fic_dec, 0)) self.connect((self.demod, 1), (self.fic_dec, 1)) - self.connect((self.demod, 0), (self.dabplus, 0)) - self.connect((self.demod, 1), (self.dabplus, 1)) + if self.dabplus: + self.connect((self.demod, 0), (self.dabplus, 0)) + self.connect((self.demod, 1), (self.dabplus, 1)) + else: + self.connect((self.demod, 0), (self.msc_dec, 0), self.mp2_dec) + self.connect((self.demod, 1), (self.msc_dec, 1)) + self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) + self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) # connect audio to sound card - # left stereo channel - self.connect((self.dabplus, 0), (self.audio, 0)) - # right stereo channel - self.connect((self.dabplus, 1), (self.audio, 1)) + if self.dabplus: + self.connect((self.dabplus, 0), (self.audio, 0)) + self.connect((self.dabplus, 1), (self.audio, 1)) + else: + self.connect(self.gain_left, (self.audio, 0)) + self.connect(self.gain_right, (self.audio, 1)) # connect file sink if recording is selected if self.record_audio: self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) @@ -167,7 +184,11 @@ def get_crc_passed(self): # setter methods ######################## def set_volume(self, volume): - self.dabplus.set_volume(volume) + if self.dabplus: + self.dabplus.set_volume(volume) + else: + self.gain_left.set_k(volume) + self.gain_right.set_k(volume) def set_freq(self, freq): if self.src.set_center_freq(freq): diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py index 70357a21..cb465c3c 100644 --- a/python/GUI/usrp_dabplus_tx.py +++ b/python/GUI/usrp_dabplus_tx.py @@ -30,7 +30,7 @@ class usrp_dabplus_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, record_states, sink_path = "dab_iq_generated.dat"): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -48,7 +48,6 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.src_paths = src_paths self.use_usrp = use_usrp self.dabplus_types = dabplus_types - self.record_sates = record_states self.sink_path = sink_path self.selected_audio = selected_audio self.volume = 80 @@ -64,6 +63,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label ######################## # MSC ######################## + self.recorder = audio.source_make(32000) self.msc_sources = [None] * self.num_subch self.f2s_left_converters = [None] * self.num_subch self.f2s_right_converters = [None] * self.num_subch @@ -72,8 +72,9 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.rs_encoders = [None] * self.num_subch self.msc_encoders = [None] * self.num_subch for i in range(0, self.num_subch): - # source - self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) + if not self.src_paths[i] is "mic": + # source + self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) @@ -111,9 +112,12 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label else: self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) # audio sink - #self.audio = audio.sink_make(32000) + self.audio = audio.sink_make(32000) + self.gain_left = blocks.multiply_const_ff_make(1, 1) self.gain_right = blocks.multiply_const_ff_make(1, 1) + self.s2f_left = blocks.short_to_float_make(1, 32767) + self.s2f_right = blocks.short_to_float_make(1, 32767) ######################## # Connections @@ -121,16 +125,20 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) for i in range(0, self.num_subch): if self.dabplus_types[i] is 1: - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + if self.src_paths[i] is "mic": + self.connect((self.recorder, 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i + 1)) + self.connect((self.recorder, 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) else: self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i + 1)) self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) - #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) - #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) + self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) + self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) def transmit(self): tx = usrp_dabplus_tx() From d96cec313fa0a8f5ecd2847f030307b7ba98d87e Mon Sep 17 00:00:00 2001 From: Felix Wunsch Date: Fri, 18 Aug 2017 12:59:16 +0200 Subject: [PATCH 015/135] grc: fixed category naming --- grc/dab_complex_to_interleaved_float_vcf.xml | 2 +- grc/dab_conv_encoder_bb.xml | 2 +- grc/dab_crc16_bb.xml | 2 +- grc/dab_dab_transmission_frame_mux_bb.xml | 2 +- grc/dab_dabplus_audio_decoder_ff.xml | 2 +- grc/dab_detect_null.xml | 2 +- grc/dab_diff_phasor_vcc.xml | 2 +- grc/dab_estimate_sample_rate_bf.xml | 2 +- grc/dab_fib_source_b.xml | 2 +- grc/dab_fic_decode.xml | 2 +- grc/dab_fic_encode.xml | 2 +- grc/dab_firecode_check_bb.xml | 2 +- grc/dab_fractional_interpolator_triggered_update_cc.xml | 2 +- grc/dab_frequency_interleaver_vcc.xml | 2 +- grc/dab_magnitude_equalizer_vcc.xml | 2 +- grc/dab_mapper_bc.xml | 2 +- grc/dab_measure_processing_rate.xml | 2 +- grc/dab_modulo_ff.xml | 2 +- grc/dab_moving_sum_ff.xml | 2 +- grc/dab_mp2_decode_bs.xml | 2 +- grc/dab_mp2_encode_sb.xml | 2 +- grc/dab_mp4_decode_bs.xml | 2 +- grc/dab_mp4_encode_sb.xml | 2 +- grc/dab_msc_decode.xml | 2 +- grc/dab_msc_encode.xml | 2 +- grc/dab_ofdm_coarse_frequency_correct.xml | 2 +- grc/dab_ofdm_demod.xml | 2 +- grc/dab_ofdm_ffe_all_in_one.xml | 2 +- grc/dab_ofdm_mod.xml | 2 +- grc/dab_ofdm_remove_first_symbol_vcc.xml | 2 +- grc/dab_ofdm_sampler.xml | 2 +- grc/dab_ofdm_sync_dab2.xml | 2 +- grc/dab_prune.xml | 2 +- grc/dab_puncture_bb.xml | 2 +- grc/dab_reed_solomon_decode_bb.xml | 2 +- grc/dab_reed_solomon_encode_bb.xml | 2 +- grc/dab_select_subch_vfvf.xml | 2 +- grc/dab_time_deinterleave_ff.xml | 2 +- grc/dab_time_interleave_bb.xml | 2 +- grc/dab_transmitter_c.xml | 2 +- grc/dab_unpuncture_ff.xml | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/grc/dab_complex_to_interleaved_float_vcf.xml b/grc/dab_complex_to_interleaved_float_vcf.xml index 04abe70c..a4674f63 100644 --- a/grc/dab_complex_to_interleaved_float_vcf.xml +++ b/grc/dab_complex_to_interleaved_float_vcf.xml @@ -1,7 +1,7 @@ Complex to interleaved float dab_complex_to_interleaved_float_vcf - DAB + [DAB] import dab dab.complex_to_interleaved_float_vcf($length) diff --git a/grc/dab_conv_encoder_bb.xml b/grc/dab_conv_encoder_bb.xml index 521641e9..1616cd0a 100644 --- a/grc/dab_conv_encoder_bb.xml +++ b/grc/dab_conv_encoder_bb.xml @@ -1,7 +1,7 @@ DAB: Convolutional encoder dab_conv_encoder_bb - DAB + [DAB] import dab dab.conv_encoder_bb($framesize) diff --git a/grc/dab_crc16_bb.xml b/grc/dab_crc16_bb.xml index caf898df..04f3c181 100644 --- a/grc/dab_crc16_bb.xml +++ b/grc/dab_crc16_bb.xml @@ -2,7 +2,7 @@ CRC16 dab_crc16_bb - DAB + [DAB] import dab dab.crc16_bb($length, $generator, $initial_state) diff --git a/grc/dab_dab_transmission_frame_mux_bb.xml b/grc/dab_dab_transmission_frame_mux_bb.xml index ac9f0f5c..1424325b 100644 --- a/grc/dab_dab_transmission_frame_mux_bb.xml +++ b/grc/dab_dab_transmission_frame_mux_bb.xml @@ -2,7 +2,7 @@ DAB: Transmission Frame MUX dab_dab_transmission_frame_mux_bb - DAB + [DAB] import dab dab.dab_transmission_frame_mux_bb($dab_mode, $num_subch, $subch_size) diff --git a/grc/dab_dabplus_audio_decoder_ff.xml b/grc/dab_dabplus_audio_decoder_ff.xml index 3511ed49..f87d34f9 100644 --- a/grc/dab_dabplus_audio_decoder_ff.xml +++ b/grc/dab_dabplus_audio_decoder_ff.xml @@ -2,7 +2,7 @@ DAB: DAB+ Decoder dab_dabplus_audio_decoder_ff - DAB + [DAB] import dab dab.dabplus_audio_decoder_ff(dab.parameters.dab_parameters(mode=$dab_mode, sample_rate=$samp_rate, verbose=False), $bit_rate, $address, $subch_size, $protection, $output_float) diff --git a/grc/dab_detect_null.xml b/grc/dab_detect_null.xml index 3112f836..adf206ef 100644 --- a/grc/dab_detect_null.xml +++ b/grc/dab_detect_null.xml @@ -2,7 +2,7 @@ Detect NULL dab_detect_null - DAB + [DAB] import dab dab.detect_null($length, False) diff --git a/grc/dab_diff_phasor_vcc.xml b/grc/dab_diff_phasor_vcc.xml index 2e7b0508..0ac63c1a 100644 --- a/grc/dab_diff_phasor_vcc.xml +++ b/grc/dab_diff_phasor_vcc.xml @@ -2,7 +2,7 @@ Diff Phasor VCC dab_diff_phasor_vcc - DAB + [DAB] import dab dab.diff_phasor_vcc($num_carriers) diff --git a/grc/dab_estimate_sample_rate_bf.xml b/grc/dab_estimate_sample_rate_bf.xml index eaf170bf..52cb8281 100644 --- a/grc/dab_estimate_sample_rate_bf.xml +++ b/grc/dab_estimate_sample_rate_bf.xml @@ -2,7 +2,7 @@ DAB Est Samp Rate estimate_sample_rate_bf - DAB + [DAB] import dab dab.estimate_sample_rate_bf($exp_samp_rate, $frame_length) diff --git a/grc/dab_fib_source_b.xml b/grc/dab_fib_source_b.xml index 7beae2bb..2102c7f2 100644 --- a/grc/dab_fib_source_b.xml +++ b/grc/dab_fib_source_b.xml @@ -1,7 +1,7 @@ DAB: FIB source dab_fib_source_b - DAB + [DAB] import dab dab.fib_source_b($dab_mode, $num_subch, $ensemble_label, $programme_service_label, $service_comp_label, $service_comp_lang, $protection_mode, $data_rate_n) diff --git a/grc/dab_fic_decode.xml b/grc/dab_fic_decode.xml index c9829c76..46c4ce45 100644 --- a/grc/dab_fic_decode.xml +++ b/grc/dab_fic_decode.xml @@ -2,7 +2,7 @@ DAB: FIC decoder dab_fic_decode - DAB + [DAB] import dab dab.fic_decode( dab.parameters.dab_parameters( diff --git a/grc/dab_fic_encode.xml b/grc/dab_fic_encode.xml index 02b7debc..c5585d84 100644 --- a/grc/dab_fic_encode.xml +++ b/grc/dab_fic_encode.xml @@ -2,7 +2,7 @@ DAB: FIC encoder dab_fic_encode - DAB + [DAB] import dab dab.fic_encode(dab.parameters.dab_parameters(mode=$dab_mode, sample_rate=$samp_rate, verbose=False)) diff --git a/grc/dab_firecode_check_bb.xml b/grc/dab_firecode_check_bb.xml index 2b96d53c..1a66cd15 100644 --- a/grc/dab_firecode_check_bb.xml +++ b/grc/dab_firecode_check_bb.xml @@ -1,7 +1,7 @@ Firecode checker dab_firecode_check_bb - DAB + [DAB] import dab dab.firecode_check_bb($bit_rate_n) diff --git a/grc/dab_fractional_interpolator_triggered_update_cc.xml b/grc/dab_fractional_interpolator_triggered_update_cc.xml index 4ec58359..66f46162 100644 --- a/grc/dab_fractional_interpolator_triggered_update_cc.xml +++ b/grc/dab_fractional_interpolator_triggered_update_cc.xml @@ -2,7 +2,7 @@ Frac. Interp. Trig. Update dab_fractional_interpolator_triggered_update_cc - DAB + [DAB] import dab dab.fractional_interpolator_triggered_update_cc($phase_shift, $interp_ratio) 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�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�yD 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%0AN5M+ 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 z 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

&!=`8%;CL;+HB>?79j<0ug+>+k`;~fkzM;SL zRXP758espYnJ^CK|K@c3?>(O*O%2B_QCOc`y?!y-bs=ZA%+DA>~v{!a_DAs$&ZM25i906 zdhHPRh4UYQNU|TQA9j*|zwLjLje_S$B3m(Tt-f{0USu9gf)0E&OVBYbX>#-Fd1;Ev zBgQb3fySe~`8QIa-ta+~LVxCB@4rc0YGYLo%uj?m-*jnxx)O+%eIhAC@e+wVZ$imP zy>!fMM#(pIM!AVBHw|f)%JdMJXxeCGq`JpnOYB>e1F>zNP-~r7FRo~4x=kk2C4boR znkpsB>@>lctDupAby`2VD=dplaJg!9Ok4apA(6PRV5UWxk(8u^1nNK}i1Ka?2(*`~ z+A0Bkn$`epXsV9t6)*;r4A`7y`Kk=-f##%52tvnVHR)N9F0u z4~*v_0^MCPpDZ104u`f=tIc&E@~%(vwhr?Hyo1OB^-ijhy646HD-GU`_+axAzO^+Yq00>`nWUrG6j2Q#?&+=XvRq$E* zuSKLb44+Si)>g{&#`R+3^s6&qs!RfyOT{32*KBW2lOr&>?)1*YD;3U?r-Mp9yx5LZ zKWYlP^schXKf-v|-XrBQJZf$6850ZBw6k-IY7iubw2wn2lplok-@psUwCgOg00S#e zbw018ft0C%l&#r1kqC>(%vD>)MV6Zp?wETY@+>m4eNJ%FhN-;R8m4=eub3YhPFNeX zLhoQVi1jn96ixxKgI0q#b@SEXJIXAM{mLS?;9kn1zn}~1(ancB2_~M!y}nwci@l<| ztb48l>2_1NqMo-ebb8idZ0WY$t{wKE9>QP;7*8AB+;lgY&GV*>ldoD1zwKN4E>dSq zhBJAJ(6#&Egj%aKOEz$Ja3~&;YfwQJ(u56l_5BE9yTnZC=Z69LG7k3Tmrvyjy@mDg zn>%#k0SkUBI!6Wf>B z`Hg95#=;ame}_CqJQDRJlj`uV7!^~{;GY!>K1C^in1Z*ls>M&eSYc;%^Vq0+XE#?< zFbEs(w%W~Q@sk;gla?Qw>-vj9LvvT&5bQ)SRYpOw9k61ANpjQzkE=I0nfP}WR`tp z%*I>seL_ME`99MkEb|_pdlF^f(V5jXI}^TLOp0S20bnxFuMGV$1&(v$H2UGocYxl% z@2&EkWu=)vVFT~-2fC-z%{`_r%p#qbqE@9Dc*1Emi7GuRJkR9p96Ntc`f@x%0Avug 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%0DRjIhct+Yp?K41h>_I~ufO_$0Oh7K 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%0DU@mM#8Y58!ix! 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\U7G~h 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

)um$wYWKH#Xhp@{4#DoUr*!D%gyI^;6FBwle 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�Gs& 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 l^H;NFu8Kk}s7qmmoAlG%ne=>;nw&}IriXJlM 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 jQ{_0S|NLs^;c4OS=?n9Rqr<$xyzh9?VOea{ 2048 +\f] + +tpdec_lib.h and TRANSPORTDEC_INBUF_SIZE are not part of the decoder's library interface. Therefore +only source-code clients may change this setting. If you received a library release, please ask us and +we can change this in order to meet your memory requirements. + +\page OutputFormat Decoder audio output + +\section OutputFormatObtaining Obtaining channel mapping information + +The decoded audio output format is indicated by a set of variables of the CStreamInfo structure. +While the members sampleRate, frameSize and numChannels might be quite self explaining, +pChannelType and pChannelIndices might require some more detailed explanation. + +These two arrays indicate what is each output channel supposed to be. Both array have +CStreamInfo::numChannels cells. Each cell of pChannelType indicates the channel type, described in +the enum ::AUDIO_CHANNEL_TYPE defined in FDK_audio.h. The cells of pChannelIndices indicate the sub index +among the channels starting with 0 among all channels of the same audio channel type. + +The indexing scheme is the same as for MPEG-2/4. Thus indices are counted upwards starting from the front +direction (thus a center channel if any, will always be index 0). Then the indices count up, starting always +with the left side, pairwise from front toward back. For detailed explanation, please refer to +ISO/IEC 13818-7:2005(E), chapter 8.5.3.2. + +In case a Program Config is included in the audio configuration, the channel mapping described within +it will be adopted. + +In case of MPEG-D Surround the channel mapping will follow the same criteria described in ISO/IEC 13818-7:2005(E), +but adding corresponding top channels to the channel types front, side and back, in order to avoid any +loss of information. + +\section OutputFormatChange Changing the audio output format + +The channel interleaving scheme and the actual channel order can be changed at runtime through the +parameters ::AAC_PCM_OUTPUT_INTERLEAVED and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING. See the description of those +parameters and the decoder library function aacDecoder_SetParam() for more detail. + +\section OutputFormatExample Channel mapping examples + +The following examples illustrate the location of individual audio samples in the audio buffer that +is passed to aacDecoder_DecodeFrame() and the expected data in the CStreamInfo structure which can be obtained +by calling aacDecoder_GetStreamInfo(). + +\subsection ExamplesStereo Stereo + +In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 0 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 2 in its audio specific config would lead +to the following values in CStreamInfo: + +CStreamInfo::numChannels = 2 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT } + +CStreamInfo::pChannelIndices = { 0, 1 } + +Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 0, the audio channels will be located as contiguous blocks +in the output buffer as follows: + +\verbatim + ... + ... +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesSurround Surround 5.1 + +In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 6 in its audio specific config, would lead +to the following values in CStreamInfo: + +CStreamInfo::numChannels = 6 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_FRONT, ::ACT_LFE, ::ACT_BACK, ::ACT_BACK } + +CStreamInfo::pChannelIndices = { 1, 2, 0, 0, 0, 1 } + +Since ::AAC_PCM_OUTPUT_CHANNEL_MAPPING is 1, WAV file channel ordering will be used. For a 5.1 channel +scheme, thus the channels would be: front left, front right, center, LFE, surround left, surround right. +Thus the third channel is the center channel, receiving the index 0. The other front channels are +front left, front right being placed as first and second channels with indices 1 and 2 correspondingly. +There is only one LFE, placed as the fourth channel and index 0. Finally both surround +channels get the type definition ACT_BACK, and the indices 0 and 1. + +Since ::AAC_PCM_OUTPUT_INTERLEAVED is set to 1, the audio channels will be placed in the output buffer +as follows: + +\verbatim + +
+ + + +
+ + +... + + +
+ +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesArib ARIB coding mode 2/1 + +In case of ::AAC_PCM_OUTPUT_INTERLEAVED set to 1 and ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +in case of a ARIB bit stream using coding mode 2/1 as described in ARIB STD-B32 Part 2 Version 2.1-E1, page 61, +would lead to the following values in CStreamInfo: + +CStreamInfo::numChannels = 3 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT,:: ACT_BACK } + +CStreamInfo::pChannelIndices = { 0, 1, 0 } + +The audio channels will be placed as follows in the audio output buffer: + +\verbatim + + + + +... + + + +Where N equals to CStreamInfo::frameSize . + +\endverbatim + +*/ + +#ifndef AACDECODER_LIB_H +#define AACDECODER_LIB_H + +#include "machine_type.h" +#include "FDK_audio.h" + +#include "genericStds.h" + +#define AACDECODER_LIB_VL0 2 +#define AACDECODER_LIB_VL1 5 +#define AACDECODER_LIB_VL2 17 + +/** + * \brief AAC decoder error codes. + */ +typedef enum { + AAC_DEC_OK = 0x0000, /*!< No error occured. Output buffer is valid and error free. */ + AAC_DEC_OUT_OF_MEMORY = 0x0002, /*!< Heap returned NULL pointer. Output buffer is invalid. */ + AAC_DEC_UNKNOWN = 0x0005, /*!< Error condition is of unknown reason, or from a another module. Output buffer is invalid. */ + + /* Synchronization errors. Output buffer is invalid. */ + aac_dec_sync_error_start = 0x1000, + AAC_DEC_TRANSPORT_SYNC_ERROR = 0x1001, /*!< The transport decoder had syncronisation problems. Do not exit decoding. Just feed new + bitstream data. */ + AAC_DEC_NOT_ENOUGH_BITS = 0x1002, /*!< The input buffer ran out of bits. */ + aac_dec_sync_error_end = 0x1FFF, + + /* Initialization errors. Output buffer is invalid. */ + aac_dec_init_error_start = 0x2000, + AAC_DEC_INVALID_HANDLE = 0x2001, /*!< The handle passed to the function call was invalid (NULL). */ + AAC_DEC_UNSUPPORTED_AOT = 0x2002, /*!< The AOT found in the configuration is not supported. */ + AAC_DEC_UNSUPPORTED_FORMAT = 0x2003, /*!< The bitstream format is not supported. */ + AAC_DEC_UNSUPPORTED_ER_FORMAT = 0x2004, /*!< The error resilience tool format is not supported. */ + AAC_DEC_UNSUPPORTED_EPCONFIG = 0x2005, /*!< The error protection format is not supported. */ + AAC_DEC_UNSUPPORTED_MULTILAYER = 0x2006, /*!< More than one layer for AAC scalable is not supported. */ + AAC_DEC_UNSUPPORTED_CHANNELCONFIG = 0x2007, /*!< The channel configuration (either number or arrangement) is not supported. */ + AAC_DEC_UNSUPPORTED_SAMPLINGRATE = 0x2008, /*!< The sample rate specified in the configuration is not supported. */ + AAC_DEC_INVALID_SBR_CONFIG = 0x2009, /*!< The SBR configuration is not supported. */ + AAC_DEC_SET_PARAM_FAIL = 0x200A, /*!< The parameter could not be set. Either the value was out of range or the parameter does + not exist. */ + AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, since the requiered configuration change cannot be + performed. */ + AAC_DEC_OUTPUT_BUFFER_TOO_SMALL = 0x200C, /*!< The provided output buffer is too small. */ + aac_dec_init_error_end = 0x2FFF, + + /* Decode errors. Output buffer is valid but concealed. */ + aac_dec_decode_error_start = 0x4000, + AAC_DEC_TRANSPORT_ERROR = 0x4001, /*!< The transport decoder encountered an unexpected error. */ + AAC_DEC_PARSE_ERROR = 0x4002, /*!< Error while parsing the bitstream. Most probably it is corrupted, or the system crashed. */ + AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD = 0x4003, /*!< Error while parsing the extension payload of the bitstream. The extension payload type + found is not supported. */ + AAC_DEC_DECODE_FRAME_ERROR = 0x4004, /*!< The parsed bitstream value is out of range. Most probably the bitstream is corrupt, or + the system crashed. */ + AAC_DEC_CRC_ERROR = 0x4005, /*!< The embedded CRC did not match. */ + AAC_DEC_INVALID_CODE_BOOK = 0x4006, /*!< An invalid codebook was signalled. Most probably the bitstream is corrupt, or the system + crashed. */ + AAC_DEC_UNSUPPORTED_PREDICTION = 0x4007, /*!< Predictor found, but not supported in the AAC Low Complexity profile. Most probably the + bitstream is corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_CCE = 0x4008, /*!< A CCE element was found which is not supported. Most probably the bitstream is corrupt, or + has a wrong format. */ + AAC_DEC_UNSUPPORTED_LFE = 0x4009, /*!< A LFE element was found which is not supported. Most probably the bitstream is corrupt, or + has a wrong format. */ + AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA = 0x400A, /*!< Gain control data found but not supported. Most probably the bitstream is corrupt, or has + a wrong format. */ + AAC_DEC_UNSUPPORTED_SBA = 0x400B, /*!< SBA found, but currently not supported in the BSAC profile. */ + AAC_DEC_TNS_READ_ERROR = 0x400C, /*!< Error while reading TNS data. Most probably the bitstream is corrupt or the system + crashed. */ + AAC_DEC_RVLC_ERROR = 0x400D, /*!< Error while decoding error resillient data. */ + aac_dec_decode_error_end = 0x4FFF, + + /* Ancillary data errors. Output buffer is valid. */ + aac_dec_anc_data_error_start = 0x8000, + AAC_DEC_ANC_DATA_ERROR = 0x8001, /*!< Non severe error concerning the ancillary data handling. */ + AAC_DEC_TOO_SMALL_ANC_BUFFER = 0x8002, /*!< The registered ancillary data buffer is too small to receive the parsed data. */ + AAC_DEC_TOO_MANY_ANC_ELEMENTS = 0x8003, /*!< More than the allowed number of ancillary data elements should be written to buffer. */ + aac_dec_anc_data_error_end = 0x8FFF + + +} AAC_DECODER_ERROR; + + +/** Macro to identify initialization errors. */ +#define IS_INIT_ERROR(err) ( (((err)>=aac_dec_init_error_start) && ((err)<=aac_dec_init_error_end)) ? 1 : 0) +/** Macro to identify decode errors. */ +#define IS_DECODE_ERROR(err) ( (((err)>=aac_dec_decode_error_start) && ((err)<=aac_dec_decode_error_end)) ? 1 : 0) +/** Macro to identify if the audio output buffer contains valid samples after calling aacDecoder_DecodeFrame(). */ +#define IS_OUTPUT_VALID(err) ( ((err) == AAC_DEC_OK) || IS_DECODE_ERROR(err) ) + +/** + * \brief AAC decoder setting parameters + */ +typedef enum +{ + AAC_PCM_OUTPUT_INTERLEAVED = 0x0000, /*!< PCM output mode (1: interleaved (default); 0: not interleaved). */ + AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = 0x0002, /*!< Defines how the decoder processes two channel signals: \n + 0: Leave both signals as they are (default). \n + 1: Create a dual mono output signal from channel 1. \n + 2: Create a dual mono output signal from channel 2. \n + 3: Create a dual mono output signal by mixing both channels (L' = R' = 0.5*Ch1 + 0.5*Ch2). */ + AAC_PCM_OUTPUT_CHANNEL_MAPPING = 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: WAV file channel order (default). */ + AAC_PCM_LIMITER_ENABLE = 0x0004, /*!< Enable signal level limiting. \n + -1: Auto-config. Enable limiter for all non-lowdelay configurations by default. \n + 0: Disable limiter in general. \n + 1: Enable limiter always. + It is recommended to call the decoder with a AACDEC_CLRHIST flag to reset all states when + the limiter switch is changed explicitly. */ + AAC_PCM_LIMITER_ATTACK_TIME = 0x0005, /*!< Signal level limiting attack time in ms. + Default confguration is 15 ms. Adjustable range from 1 ms to 15 ms. */ + AAC_PCM_LIMITER_RELEAS_TIME = 0x0006, /*!< Signal level limiting release time in ms. + Default configuration is 50 ms. Adjustable time must be larger than 0 ms. */ + AAC_PCM_MIN_OUTPUT_CHANNELS = 0x0011, /*!< Minimum number of PCM output channels. If higher than the number of encoded audio channels, + a simple channel extension is applied. \n + -1, 0: Disable channel extenstion feature. The decoder output contains the same number of + channels as the encoded bitstream. \n + 1: This value is currently needed only together with the mix-down feature. See + ::AAC_PCM_MAX_OUTPUT_CHANNELS and note 2 below. \n + 2: Encoded mono signals will be duplicated to achieve a 2/0/0.0 channel output + configuration. \n + 6: The decoder trys to reorder encoded signals with less than six channels to achieve + a 3/0/2.1 channel output signal. Missing channels will be filled with a zero signal. + If reordering is not possible the empty channels will simply be appended. Only + available if instance is configured to support multichannel output. \n + 8: The decoder trys to reorder encoded signals with less than eight channels to + achieve a 3/0/4.1 channel output signal. Missing channels will be filled with a + zero signal. If reordering is not possible the empty channels will simply be + appended. Only available if instance is configured to support multichannel output.\n + NOTE: \n + 1. The channel signalling (CStreamInfo::pChannelType and CStreamInfo::pChannelIndices) + will not be modified. Added empty channels will be signalled with channel type + AUDIO_CHANNEL_TYPE::ACT_NONE. \n + 2. If the parameter value is greater than that of ::AAC_PCM_MAX_OUTPUT_CHANNELS both will + be set to the same value. \n + 3. This parameter does not affect MPEG Surround processing. */ + AAC_PCM_MAX_OUTPUT_CHANNELS = 0x0012, /*!< Maximum number of PCM output channels. If lower than the number of encoded audio channels, + downmixing is applied accordingly. If dedicated metadata is available in the stream it + will be used to achieve better mixing results. \n + -1, 0: Disable downmixing feature. The decoder output contains the same number of channels + as the encoded bitstream. \n + 1: All encoded audio configurations with more than one channel will be mixed down to + one mono output signal. \n + 2: The decoder performs a stereo mix-down if the number encoded audio channels is + greater than two. \n + 6: If the number of encoded audio channels is greater than six the decoder performs a + mix-down to meet the target output configuration of 3/0/2.1 channels. Only + available if instance is configured to support multichannel output. \n + 8: This value is currently needed only together with the channel extension feature. + See ::AAC_PCM_MIN_OUTPUT_CHANNELS and note 2 below. Only available if instance is + configured to support multichannel output. \n + NOTE: \n + 1. Down-mixing of any seven or eight channel configuration not defined in ISO/IEC 14496-3 + PDAM 4 is not supported by this software version. \n + 2. If the parameter value is greater than zero but smaller than ::AAC_PCM_MIN_OUTPUT_CHANNELS + both will be set to same value. \n + 3. The operating mode of the MPEG Surround module will be set accordingly. \n + 4. Setting this param with any value will disable the binaural processing of the MPEG + Surround module (::AAC_MPEGS_BINAURAL_ENABLE=0). */ + + AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n + 0: Spectral muting. \n + 1: Noise substitution (see ::CONCEAL_NOISE). \n + 2: Energy interpolation (adds additional signal delay of one frame, see ::CONCEAL_INTER). \n */ + + AAC_DRC_BOOST_FACTOR = 0x0200, /*!< Dynamic Range Control: Scaling factor for boosting gain values. + Defines how the boosting DRC factors (conveyed in the bitstream) will be applied to the + decoded signal. The valid values range from 0 (don't apply boost factors) to 127 (fully + apply all boosting factors). */ + AAC_DRC_ATTENUATION_FACTOR = 0x0201, /*!< Dynamic Range Control: Scaling factor for attenuating gain values. Same as + AAC_DRC_BOOST_FACTOR but for attenuating DRC factors. */ + AAC_DRC_REFERENCE_LEVEL = 0x0202, /*!< Dynamic Range Control: Target reference level. Defines the level below full-scale + (quantized in steps of 0.25dB) to which the output audio signal will be normalized to by + the DRC module. The valid values range from 0 (full-scale) to 127 (31.75 dB below + full-scale). The value smaller than 0 switches off normalization. */ + AAC_DRC_HEAVY_COMPRESSION = 0x0203, /*!< Dynamic Range Control: En-/Disable DVB specific heavy compression (aka RF mode). + If set to 1, the decoder will apply the compression values from the DVB specific ancillary + data field. At the same time the MPEG-4 Dynamic Range Control tool will be disabled. By + default heavy compression is disabled. */ + + AAC_QMF_LOWPOWER = 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing mode. \n + -1: Use internal default. Implies MPEG Surround partially complex accordingly. \n + 0: Use complex QMF data mode. \n + 1: Use real (low power) QMF data mode. \n */ + + AAC_MPEGS_ENABLE = 0x0500, /*!< MPEG Surround: Allow/Disable decoding of MPS content. Available only for decoders with MPEG + Surround support. */ + + AAC_TPDEC_CLEAR_BUFFER = 0x0603 /*!< Clear internal bit stream buffer of transport layers. The decoder will start decoding + at new data passed after this event and any previous data is discarded. */ + +} AACDEC_PARAM; + +/** + * \brief This structure gives information about the currently decoded audio data. + * All fields are read-only. + */ +typedef struct +{ + /* These five members are the only really relevant ones for the user. */ + INT sampleRate; /*!< The samplerate in Hz of the fully decoded PCM audio signal (after SBR processing). */ + INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n + 1024 or 960 for AAC-LC \n + 2048 or 1920 for HE-AAC (v2) \n + 512 or 480 for AAC-LD and AAC-ELD */ + INT numChannels; /*!< The number of output audio channels in the decoded and interleaved PCM audio signal. */ + AUDIO_CHANNEL_TYPE *pChannelType; /*!< Audio channel type of each output audio channel. */ + UCHAR *pChannelIndices; /*!< Audio channel index for each output audio channel. + See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */ + /* Decoder internal members. */ + INT aacSampleRate; /*!< Sampling rate in Hz without SBR (from configuration info). */ + INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. MPEG-4)). */ + AUDIO_OBJECT_TYPE aot; /*!< Audio Object Type (from ASC): is set to the appropriate value for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */ + INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: stereo, ... */ + INT bitRate; /*!< Instantaneous bit rate. */ + INT aacSamplesPerFrame; /*!< Samples per frame for the AAC core (from ASC). \n + 1024 or 960 for AAC-LC \n + 512 or 480 for AAC-LD and AAC-ELD */ + INT aacNumChannels; /*!< The number of audio channels after AAC core processing (before PS or MPS processing). + CAUTION: This are not the final number of output channels! */ + AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */ + INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) */ + + UINT outputDelay; /*!< The number of samples the output is additionally delayed by the decoder. */ + + UINT flags; /*!< Copy of internal flags. Only to be written by the decoder, and only to be read externally. */ + + SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */ + + /* Statistics */ + INT numLostAccessUnits; /*!< This integer will reflect the estimated amount of lost access units in case aacDecoder_DecodeFrame() + returns AAC_DEC_TRANSPORT_SYNC_ERROR. It will be < 0 if the estimation failed. */ + + UINT numTotalBytes; /*!< This is the number of total bytes that have passed through the decoder. */ + UINT numBadBytes; /*!< This is the number of total bytes that were considered with errors from numTotalBytes. */ + UINT numTotalAccessUnits; /*!< This is the number of total access units that have passed through the decoder. */ + UINT numBadAccessUnits; /*!< This is the number of total access units that were considered with errors from numTotalBytes. */ + + /* Metadata */ + SCHAR drcProgRefLev; /*!< DRC program reference level. Defines the reference level below full-scale. + It is quantized in steps of 0.25dB. The valid values range from 0 (0 dBFS) to 127 (-31.75 dBFS). + It is used to reflect the average loudness of the audio in LKFS accoring to ITU-R BS 1770. + If no level has been found in the bitstream the value is -1. */ + SCHAR drcPresMode; /*!< DRC presentation mode. According to ETSI TS 101 154, this field indicates whether + light (MPEG-4 Dynamic Range Control tool) or heavy compression (DVB heavy compression) + dynamic range control shall take priority on the outputs. + For details, see ETSI TS 101 154, table C.33. Possible values are: \n + -1: No corresponding metadata found in the bitstream \n + 0: DRC presentation mode not indicated \n + 1: DRC presentation mode 1 \n + 2: DRC presentation mode 2 \n + 3: Reserved */ + +} CStreamInfo; + + +typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER; /*!< Pointer to a AAC decoder instance. */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \brief Initialize ancillary data buffer. + * + * \param self AAC decoder handle. + * \param buffer Pointer to (external) ancillary data buffer. + * \param size Size of the buffer pointed to by buffer. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_AncDataInit ( HANDLE_AACDECODER self, + UCHAR *buffer, + int size ); + +/** + * \brief Get one ancillary data element. + * + * \param self AAC decoder handle. + * \param index Index of the ancillary data element to get. + * \param ptr Pointer to a buffer receiving a pointer to the requested ancillary data element. + * \param size Pointer to a buffer receiving the length of the requested ancillary data element. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_AncDataGet ( HANDLE_AACDECODER self, + int index, + UCHAR **ptr, + int *size ); + +/** + * \brief Set one single decoder parameter. + * + * \param self AAC decoder handle. + * \param param Parameter to be set. + * \param value Parameter value. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_SetParam ( const HANDLE_AACDECODER self, + const AACDEC_PARAM param, + const INT value ); + + +/** + * \brief Get free bytes inside decoder internal buffer + * \param self Handle of AAC decoder instance + * \param pFreeBytes Pointer to variable receving amount of free bytes inside decoder internal buffer + * \return Error code + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self, + UINT *pFreeBytes); + +/** + * \brief Open an AAC decoder instance + * \param transportFmt The transport type to be used + * \return AAC decoder handle + */ +LINKSPEC_H HANDLE_AACDECODER +aacDecoder_Open ( TRANSPORT_TYPE transportFmt, UINT nrOfLayers ); + +/** + * \brief Explicitly configure the decoder by passing a raw AudioSpecificConfig (ASC) or a StreamMuxConfig (SMC), + * contained in a binary buffer. This is required for MPEG-4 and Raw Packets file format bitstreams + * as well as for LATM bitstreams with no in-band SMC. If the transport format is LATM with or without + * LOAS, configuration is assumed to be an SMC, for all other file formats an ASC. + * + * \param self AAC decoder handle. + * \param conf Pointer to an unsigned char buffer containing the binary configuration buffer (either ASC or SMC). + * \param length Length of the configuration buffer in bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_ConfigRaw ( HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[] ); + + +/** + * \brief Fill AAC decoder's internal input buffer with bitstream data from the external input buffer. + * The function only copies such data as long as the decoder-internal input buffer is not full. + * So it grabs whatever it can from pBuffer and returns information (bytesValid) so that at a + * subsequent call of %aacDecoder_Fill(), the right position in pBuffer can be determined to + * grab the next data. + * + * \param self AAC decoder handle. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required because decoder-internally + * we need the information to calculate the offset to pBuffer, where the next + * available data is, which is then fed into the decoder-internal buffer (as much + * as possible). Our example framework implementation fills the buffer at pBuffer + * again, once it contains no available valid bytes anymore (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer that have not yet been + * copied into the decoder's internal bitstream buffer by calling this function. + * The value is updated according to the amount of newly copied bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_Fill ( HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *bytesValid ); + +#define AACDEC_CONCEAL 1 /*!< Flag for aacDecoder_DecodeFrame(): Trigger the built-in error concealment module \ + to generate a substitute signal for one lost frame. New input data will not be + considered. */ +#define AACDEC_FLUSH 2 /*!< Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all delayed audio \ + without having new input data. Thus new input data will not be considered.*/ +#define AACDEC_INTR 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data discontinuity. \ + Resync any internals as necessary. */ +#define AACDEC_CLRHIST 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and history buffers.\ + CAUTION: This can cause discontinuities in the output signal. */ + +/** + * \brief Decode one audio frame + * + * \param self AAC decoder handle. + * \param pTimeData Pointer to external output buffer where the decoded PCM samples will be stored into. + * \param flags Bit field with flags for the decoder: \n + * (flags & AACDEC_CONCEAL) == 1: Do concealment. \n + * (flags & AACDEC_FLUSH) == 2: Discard input data. Flush filter banks (output delayed audio). \n + * (flags & AACDEC_INTR) == 4: Input data is discontinuous. Resynchronize any internals as necessary. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_DecodeFrame ( HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags ); + +/** + * \brief De-allocate all resources of an AAC decoder instance. + * + * \param self AAC decoder handle. + * \return void + */ +LINKSPEC_H void aacDecoder_Close ( HANDLE_AACDECODER self ); + +/** + * \brief Get CStreamInfo handle from decoder. + * + * \param self AAC decoder handle. + * \return Reference to requested CStreamInfo. + */ +LINKSPEC_H CStreamInfo* aacDecoder_GetStreamInfo( HANDLE_AACDECODER self ); + +/** + * \brief Get decoder library info. + * + * \param info Pointer to an allocated LIB_INFO structure. + * \return 0 on success + */ +LINKSPEC_H INT aacDecoder_GetLibInfo( LIB_INFO *info ); + + +#ifdef __cplusplus +} +#endif + +#endif /* AACDECODER_LIB_H */ diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp new file mode 100644 index 00000000..1ff289b9 --- /dev/null +++ b/libAACdec/src/aac_ram.cpp @@ -0,0 +1,142 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + +******************************************************************************/ + +#include "aac_ram.h" +#include "aac_rom.h" + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER2_TAG 1 + +/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all decoder configurations, + handles and structs. + */ +C_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE, 1) + +/*! + \name StaticAacData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo which is needed + for the decoding of one aac channel.
+ Dimension: #AacDecoderChannels */ +C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8)) + +/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is needed + for the decoding of one aac channel.
+ Dimension: #AacDecoderChannels */ +C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8)) + +/*! Overlap buffer */ +C_ALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8)) + +C_ALLOC_MEM(DrcInfo, CDrcInfo, 1) + +/* @} */ + +/*! + \name DynamicAacData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the sbr decoder +*/ +C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8)*1024), SECT_DATA_L2, WORKBUFFER2_TAG) + + +C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, WORKBUFFER1_TAG) + +/* @{ */ + + +/* @} */ + + + diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h new file mode 100644 index 00000000..4527e278 --- /dev/null +++ b/libAACdec/src/aac_ram.h @@ -0,0 +1,120 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + +#ifndef AAC_RAM_H +#define AAC_RAM_H + +#include "common_fix.h" + +#include "aacdecoder.h" + +#include "channel.h" + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr.h" + +/* End of formal fix.h */ + +#define MAX_SYNCHS 10 +#define SAMPL_FREQS 12 + +H_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE) + +H_ALLOC_MEM(DrcInfo, CDrcInfo) + +H_ALLOC_MEM(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo) +H_ALLOC_MEM(AacDecoderChannelInfo, CAacDecoderChannelInfo) +H_ALLOC_MEM(OverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1) +H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL) + + +#endif /* #ifndef AAC_RAM_H */ diff --git a/libAACdec/src/aac_rom.cpp b/libAACdec/src/aac_rom.cpp new file mode 100644 index 00000000..f3c9b5a8 --- /dev/null +++ b/libAACdec/src/aac_rom.cpp @@ -0,0 +1,1937 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: Definition of constant tables + +******************************************************************************/ + +#include "aac_rom.h" + + +/* Prescale InverseQuantTable by 4 to save + redundant shifts in invers quantization + */ +#define SCL_TAB(a) (a>>4) +const FIXP_DBL InverseQuantTable [INV_QUANT_TABLESIZE + 1] = +{ + SCL_TAB(0x32CBFD40), SCL_TAB(0x330FC340), SCL_TAB(0x33539FC0), SCL_TAB(0x33979280), SCL_TAB(0x33DB9BC0), SCL_TAB(0x341FBB80), SCL_TAB(0x3463F180), SCL_TAB(0x34A83DC0), + SCL_TAB(0x34ECA000), SCL_TAB(0x35311880), SCL_TAB(0x3575A700), SCL_TAB(0x35BA4B80), SCL_TAB(0x35FF0600), SCL_TAB(0x3643D680), SCL_TAB(0x3688BCC0), SCL_TAB(0x36CDB880), + SCL_TAB(0x3712CA40), SCL_TAB(0x3757F1C0), SCL_TAB(0x379D2F00), SCL_TAB(0x37E28180), SCL_TAB(0x3827E9C0), SCL_TAB(0x386D6740), SCL_TAB(0x38B2FA40), SCL_TAB(0x38F8A2C0), + SCL_TAB(0x393E6080), SCL_TAB(0x39843380), SCL_TAB(0x39CA1BC0), SCL_TAB(0x3A101940), SCL_TAB(0x3A562BC0), SCL_TAB(0x3A9C5340), SCL_TAB(0x3AE28FC0), SCL_TAB(0x3B28E180), + SCL_TAB(0x3B6F4800), SCL_TAB(0x3BB5C340), SCL_TAB(0x3BFC5380), SCL_TAB(0x3C42F880), SCL_TAB(0x3C89B200), SCL_TAB(0x3CD08080), SCL_TAB(0x3D176340), SCL_TAB(0x3D5E5B00), + SCL_TAB(0x3DA56700), SCL_TAB(0x3DEC87C0), SCL_TAB(0x3E33BCC0), SCL_TAB(0x3E7B0640), SCL_TAB(0x3EC26400), SCL_TAB(0x3F09D640), SCL_TAB(0x3F515C80), SCL_TAB(0x3F98F740), + SCL_TAB(0x3FE0A600), SCL_TAB(0x40286900), SCL_TAB(0x40704000), SCL_TAB(0x40B82B00), SCL_TAB(0x41002A00), SCL_TAB(0x41483D00), SCL_TAB(0x41906400), SCL_TAB(0x41D89F00), + SCL_TAB(0x4220ED80), SCL_TAB(0x42695000), SCL_TAB(0x42B1C600), SCL_TAB(0x42FA5000), SCL_TAB(0x4342ED80), SCL_TAB(0x438B9E80), SCL_TAB(0x43D46380), SCL_TAB(0x441D3B80), + SCL_TAB(0x44662780), SCL_TAB(0x44AF2680), SCL_TAB(0x44F83900), SCL_TAB(0x45415F00), SCL_TAB(0x458A9880), SCL_TAB(0x45D3E500), SCL_TAB(0x461D4500), SCL_TAB(0x4666B800), + SCL_TAB(0x46B03E80), SCL_TAB(0x46F9D800), SCL_TAB(0x47438480), SCL_TAB(0x478D4400), SCL_TAB(0x47D71680), SCL_TAB(0x4820FC00), SCL_TAB(0x486AF500), SCL_TAB(0x48B50000), + SCL_TAB(0x48FF1E80), SCL_TAB(0x49494F80), SCL_TAB(0x49939380), SCL_TAB(0x49DDEA80), SCL_TAB(0x4A285400), SCL_TAB(0x4A72D000), SCL_TAB(0x4ABD5E80), SCL_TAB(0x4B080000), + SCL_TAB(0x4B52B400), SCL_TAB(0x4B9D7A80), SCL_TAB(0x4BE85380), SCL_TAB(0x4C333F00), SCL_TAB(0x4C7E3D00), SCL_TAB(0x4CC94D00), SCL_TAB(0x4D146F80), SCL_TAB(0x4D5FA500), + SCL_TAB(0x4DAAEC00), SCL_TAB(0x4DF64580), SCL_TAB(0x4E41B180), SCL_TAB(0x4E8D2F00), SCL_TAB(0x4ED8BF80), SCL_TAB(0x4F246180), SCL_TAB(0x4F701600), SCL_TAB(0x4FBBDC00), + SCL_TAB(0x5007B480), SCL_TAB(0x50539F00), SCL_TAB(0x509F9B80), SCL_TAB(0x50EBA980), SCL_TAB(0x5137C980), SCL_TAB(0x5183FB80), SCL_TAB(0x51D03F80), SCL_TAB(0x521C9500), + SCL_TAB(0x5268FC80), SCL_TAB(0x52B57580), SCL_TAB(0x53020000), SCL_TAB(0x534E9C80), SCL_TAB(0x539B4A80), SCL_TAB(0x53E80A80), SCL_TAB(0x5434DB80), SCL_TAB(0x5481BE80), + SCL_TAB(0x54CEB280), SCL_TAB(0x551BB880), SCL_TAB(0x5568CF80), SCL_TAB(0x55B5F800), SCL_TAB(0x56033200), SCL_TAB(0x56507D80), SCL_TAB(0x569DDA00), SCL_TAB(0x56EB4800), + SCL_TAB(0x5738C700), SCL_TAB(0x57865780), SCL_TAB(0x57D3F900), SCL_TAB(0x5821AC00), SCL_TAB(0x586F7000), SCL_TAB(0x58BD4500), SCL_TAB(0x590B2B00), SCL_TAB(0x59592200), + SCL_TAB(0x59A72A80), SCL_TAB(0x59F54380), SCL_TAB(0x5A436D80), SCL_TAB(0x5A91A900), SCL_TAB(0x5ADFF500), SCL_TAB(0x5B2E5180), SCL_TAB(0x5B7CBF80), SCL_TAB(0x5BCB3E00), + SCL_TAB(0x5C19CD00), SCL_TAB(0x5C686D80), SCL_TAB(0x5CB71E00), SCL_TAB(0x5D05DF80), SCL_TAB(0x5D54B200), SCL_TAB(0x5DA39500), SCL_TAB(0x5DF28880), SCL_TAB(0x5E418C80), + SCL_TAB(0x5E90A100), SCL_TAB(0x5EDFC680), SCL_TAB(0x5F2EFC00), SCL_TAB(0x5F7E4280), SCL_TAB(0x5FCD9900), SCL_TAB(0x601D0080), SCL_TAB(0x606C7800), SCL_TAB(0x60BC0000), + SCL_TAB(0x610B9800), SCL_TAB(0x615B4100), SCL_TAB(0x61AAF980), SCL_TAB(0x61FAC300), SCL_TAB(0x624A9C80), SCL_TAB(0x629A8600), SCL_TAB(0x62EA8000), SCL_TAB(0x633A8A00), + SCL_TAB(0x638AA480), SCL_TAB(0x63DACF00), SCL_TAB(0x642B0980), SCL_TAB(0x647B5400), SCL_TAB(0x64CBAE80), SCL_TAB(0x651C1900), SCL_TAB(0x656C9400), SCL_TAB(0x65BD1E80), + SCL_TAB(0x660DB900), SCL_TAB(0x665E6380), SCL_TAB(0x66AF1E00), SCL_TAB(0x66FFE880), SCL_TAB(0x6750C280), SCL_TAB(0x67A1AC80), SCL_TAB(0x67F2A600), SCL_TAB(0x6843B000), + SCL_TAB(0x6894C900), SCL_TAB(0x68E5F200), SCL_TAB(0x69372B00), SCL_TAB(0x69887380), SCL_TAB(0x69D9CB80), SCL_TAB(0x6A2B3300), SCL_TAB(0x6A7CAA80), SCL_TAB(0x6ACE3180), + SCL_TAB(0x6B1FC800), SCL_TAB(0x6B716E00), SCL_TAB(0x6BC32400), SCL_TAB(0x6C14E900), SCL_TAB(0x6C66BD80), SCL_TAB(0x6CB8A180), SCL_TAB(0x6D0A9500), SCL_TAB(0x6D5C9800), + SCL_TAB(0x6DAEAA00), SCL_TAB(0x6E00CB80), SCL_TAB(0x6E52FC80), SCL_TAB(0x6EA53D00), SCL_TAB(0x6EF78C80), SCL_TAB(0x6F49EB80), SCL_TAB(0x6F9C5980), SCL_TAB(0x6FEED700), + SCL_TAB(0x70416380), SCL_TAB(0x7093FF00), SCL_TAB(0x70E6AA00), SCL_TAB(0x71396400), SCL_TAB(0x718C2D00), SCL_TAB(0x71DF0580), SCL_TAB(0x7231ED00), SCL_TAB(0x7284E300), + SCL_TAB(0x72D7E880), SCL_TAB(0x732AFD00), SCL_TAB(0x737E2080), SCL_TAB(0x73D15300), SCL_TAB(0x74249480), SCL_TAB(0x7477E480), SCL_TAB(0x74CB4400), SCL_TAB(0x751EB200), + SCL_TAB(0x75722F00), SCL_TAB(0x75C5BB00), SCL_TAB(0x76195580), SCL_TAB(0x766CFF00), SCL_TAB(0x76C0B700), SCL_TAB(0x77147E00), SCL_TAB(0x77685400), SCL_TAB(0x77BC3880), + SCL_TAB(0x78102B80), SCL_TAB(0x78642D80), SCL_TAB(0x78B83E00), SCL_TAB(0x790C5D00), SCL_TAB(0x79608B00), SCL_TAB(0x79B4C780), SCL_TAB(0x7A091280), SCL_TAB(0x7A5D6C00), + SCL_TAB(0x7AB1D400), SCL_TAB(0x7B064A80), SCL_TAB(0x7B5ACF80), SCL_TAB(0x7BAF6380), SCL_TAB(0x7C040580), SCL_TAB(0x7C58B600), SCL_TAB(0x7CAD7500), SCL_TAB(0x7D024200), + SCL_TAB(0x7D571E00), SCL_TAB(0x7DAC0800), SCL_TAB(0x7E010080), SCL_TAB(0x7E560780), SCL_TAB(0x7EAB1C80), SCL_TAB(0x7F004000), SCL_TAB(0x7F557200), SCL_TAB(0x7FAAB200), + SCL_TAB(0x7FFFFFFF) +} ; + +/** + * \brief Table representing scale factor gains. Given a scale factor sf, and a value pSpec[i] the + * gain is given by: MantissaTable[sf % 4][msb] = 2^(sf % 4) / (1<> 2)) + * The corresponding exponents for the values in this tables are stored in ExponentTable[sf % 4][msb] below. + */ +const FIXP_DBL MantissaTable [4][14] = +{ + { + 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, + 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00 + }, + { + 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, + 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380 + }, + { + 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, + 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800 + }, + { + 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, + 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80 + } +} ; + +const SCHAR ExponentTable [4][14] = +{ + { 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18 }, + { 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18 }, + { 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18 }, + { 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19 } +} ; + + +/* 41 scfbands */ +static const SHORT sfb_96_1024[42] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, + 156, 172, 188, 212, 240, 276, 320, 384, 448, 512, 576, 640, + 704, 768, 832, 896, 960, 1024 +}; +/* 12 scfbands */ +static const SHORT sfb_96_128[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, + 128 +}; + +/* 47 scfbands*/ +static const SHORT sfb_64_1024[48] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, + 268, 304, 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, + 824, 864, 904, 944, 984,1024 +}; + +/* 12 scfbands */ +static const SHORT sfb_64_128[13] = +{ + 0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128 +}; + +/* 49 scfbands */ +static const SHORT sfb_48_1024[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, + 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, + 736, 768, 800, 832, 864, 896, 928, 1024 +}; +/* 14 scfbands */ +static const SHORT sfb_48_128[15] = +{ + 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, + 128 +}; + +/* 51 scfbands */ +static const SHORT sfb_32_1024[52] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, + 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, 672, 704, + 736, 768, 800, 832, 864, 896, 928, 960, 992,1024 +}; + +/* 47 scfbands */ +static const SHORT sfb_24_1024[48] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, + 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, + 220, 240, 260, 284, 308, 336, 364, 396, 432, 468, 508, 552, 600, 652, + 704, 768, 832, 896, 960,1024 +}; + +/* 15 scfbands */ +static const SHORT sfb_24_128[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, + 108, 128 +}; + +/* 43 scfbands */ +static const SHORT sfb_16_1024[44] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, + 124, 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, + 344, 368, 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, + 960,1024 +}; + +/* 15 scfbands */ +static const SHORT sfb_16_128[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, + 108, 128 +}; + +/* 40 scfbands */ +static const SHORT sfb_8_1024[41] = +{ + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, + 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, + 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944,1024 +}; + +/* 15 scfbands */ +static const SHORT sfb_8_128[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, + 108, 128 +}; + + +static const SHORT sfb_96_960[42] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 156, 172, 188, 212, 240, 276, + 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, + 960 +}; /* 40 scfbands */ + +static const SHORT sfb_96_120[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, + 64, 92, 120 +}; /* 12 scfbands */ + +static const SHORT sfb_64_960[47] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 100, + 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, + 344, 384, 424, 464, 504, 544, 584, 624, 664, 704, + 744, 784, 824, 864, 904, 944, 960 +}; /* 46 scfbands */ + +static const SHORT sfb_64_120[13] = +{ + 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, + 64, 92, 120 +}; /* 12 scfbands */ + +static const SHORT sfb_48_960[50] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 48, 56, 64, 72, 80, 88, 96, 108, 120, + 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, + 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, + 672, 704, 736, 768, 800, 832, 864, 896, 928, 960 +}; /* 49 scfbands */ +static const SHORT sfb_48_120[15] = +{ + 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, + 68, 80, 96, 112, 120 +}; /* 14 scfbands */ + +static const SHORT sfb_32_960[50] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 48, 56, 64, 72, 80, 88, 96, 108, 120, + 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, + 352, 384, 416, 448, 480, 512, 544, 576, 608, 640, + 672, 704, 736, 768, 800, 832, 864, 896, 928, 960 +}; /* 49 scfbands */ + +static const SHORT sfb_24_960[47] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 52, 60, 68, 76, 84, 92, 100, 108, + 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, + 260, 284, 308, 336, 364, 396, 432, 468, 508, 552, + 600, 652, 704, 768, 832, 896, 960 +}; /* 46 scfbands */ + +static const SHORT sfb_24_120[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, + 52, 64, 76, 92, 108, 120 +}; /* 15 scfbands */ + +static const SHORT sfb_16_960[43] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, + 80, 88, 100, 112, 124, 136, 148, 160, 172, 184, + 196, 212, 228, 244, 260, 280, 300, 320, 344, 368, + 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, + 832, 896, 960 +}; /* 42 scfbands */ + +static const SHORT sfb_16_120[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, + 48, 60, 72, 88, 108, 120 +}; /* 15 scfbands */ + +static const SHORT sfb_8_960[41] = +{ + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, + 120, 132, 144, 156, 172, 188, 204, 220, 236, 252, + 268, 288, 308, 328, 348, 372, 396, 420, 448, 476, + 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, + 960 +}; /* 40 scfbands */ + +static const SHORT sfb_8_120[16] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, + 52, 60, 72, 88, 108, 120 +}; /* 15 scfbands */ + + + + +static const SHORT sfb_48_512[37] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 68, 76, 84, 92, + 100, 112, 124, 136, 148, 164, 184, 208, 236, 268, + 300, 332, 364, 396, 428, 460, 512 +}; /* 36 scfbands */ +static const SHORT sfb_32_512[38] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 160, 176, 192, 212, 236, 260, + 288, 320, 352, 384, 416, 448, 480, 512 +}; /* 37 scfbands */ +static const SHORT sfb_24_512[32] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 52, 60, 68, 80, 92, 104, 120, 140, + 164, 192, 224, 256, 288, 320, 352, 384, 416, 448, + 480, 512 +}; /* 31 scfbands */ + +static const SHORT sfb_48_480[36] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 156, 172, 188, 212, 240, 272, + 304, 336, 368, 400, 432, 480 +}; /* 35 scfbands */ +static const SHORT sfb_32_480[38] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, + 96, 104, 112, 124, 136, 148, 164, 180, 200, 224, + 256, 288, 320, 352, 384, 416, 448, 480 +}; /* 37 scfbands */ +static const SHORT sfb_24_480[31] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 52, 60, 68, 80, 92, 104, 120, 140, + 164, 192, 224, 256, 288, 320, 352, 384, 416, 448, + 480 +}; /* 30 scfbands */ + +const SFB_INFO sfbOffsetTables[5][16] = +{ + { + { sfb_96_1024, sfb_96_128, 41, 12 }, + { sfb_96_1024, sfb_96_128, 41, 12 }, + { sfb_64_1024, sfb_64_128, 47, 12 }, + { sfb_48_1024, sfb_48_128, 49, 14 }, + { sfb_48_1024, sfb_48_128, 49, 14 }, + { sfb_32_1024, sfb_48_128, 51, 14 }, + { sfb_24_1024, sfb_24_128, 47, 15 }, + { sfb_24_1024, sfb_24_128, 47, 15 }, + { sfb_16_1024, sfb_16_128, 43, 15 }, + { sfb_16_1024, sfb_16_128, 43, 15 }, + { sfb_16_1024, sfb_16_128, 43, 15 }, + { sfb_8_1024, sfb_8_128, 40, 15 }, + { sfb_8_1024, sfb_8_128, 40, 15 }, + }, { + { sfb_96_960, sfb_96_120, 40, 12 }, + { sfb_96_960, sfb_96_120, 40, 12 }, + { sfb_64_960, sfb_64_120, 46, 12 }, + { sfb_48_960, sfb_48_120, 49, 14 }, + { sfb_48_960, sfb_48_120, 49, 14 }, + { sfb_32_960, sfb_48_120, 49, 14 }, + { sfb_24_960, sfb_24_120, 46, 15 }, + { sfb_24_960, sfb_24_120, 46, 15 }, + { sfb_16_960, sfb_16_120, 42, 15 }, + { sfb_16_960, sfb_16_120, 42, 15 }, + { sfb_16_960, sfb_16_120, 42, 15 }, + { sfb_8_960, sfb_8_120, 40, 15 }, + { sfb_8_960, sfb_8_120, 40, 15 }, + }, { + { NULL, NULL, 0, 0 }, + }, { + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0 }, + { sfb_48_512, NULL, 36, 0}, + { sfb_32_512, NULL, 37, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + { sfb_24_512, NULL, 31, 0 }, + }, { + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_48_480, NULL, 35, 0 }, + { sfb_32_480, NULL, 37, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + { sfb_24_480, NULL, 30, 0 }, + } +}; + + +/*# don't use 1 bit hufman tables */ +/* + MPEG-2 AAC 2 BITS parallel Hufman Tables + + Bit 0: = 1=ENDNODE, 0=INDEX + Bit 1: = CODEWORD LEN MOD 2 + Bit 2..9: = VALUE/REF Tables 1..10,SCL + Bit 2..11: = VALUE/REF Table 11 +*/ + const USHORT HuffmanCodeBook_1[51][4] = +{ + {0x0157,0x0157,0x0004,0x0018}, {0x0008,0x000c,0x0010,0x0014}, {0x015b,0x015b,0x0153,0x0153}, {0x0057,0x0057,0x0167,0x0167}, + {0x0257,0x0257,0x0117,0x0117}, {0x0197,0x0197,0x0147,0x0147}, {0x001c,0x0030,0x0044,0x0058}, {0x0020,0x0024,0x0028,0x002c}, + {0x014b,0x014b,0x0163,0x0163}, {0x0217,0x0217,0x0127,0x0127}, {0x0187,0x0187,0x0097,0x0097}, {0x016b,0x016b,0x0017,0x0017}, + {0x0034,0x0038,0x003c,0x0040}, {0x0143,0x0143,0x0107,0x0107}, {0x011b,0x011b,0x0067,0x0067}, {0x0193,0x0193,0x0297,0x0297}, + {0x019b,0x019b,0x0247,0x0247}, {0x0048,0x004c,0x0050,0x0054}, {0x01a7,0x01a7,0x0267,0x0267}, {0x0113,0x0113,0x025b,0x025b}, + {0x0053,0x0053,0x005b,0x005b}, {0x0253,0x0253,0x0047,0x0047}, {0x005c,0x0070,0x0084,0x0098}, {0x0060,0x0064,0x0068,0x006c}, + {0x012b,0x012b,0x0123,0x0123}, {0x018b,0x018b,0x00a7,0x00a7}, {0x0227,0x0227,0x0287,0x0287}, {0x0087,0x0087,0x010b,0x010b}, + {0x0074,0x0078,0x007c,0x0080}, {0x021b,0x021b,0x0027,0x0027}, {0x01a3,0x01a3,0x0093,0x0093}, {0x0183,0x0183,0x0207,0x0207}, + {0x024b,0x024b,0x004b,0x004b}, {0x0088,0x008c,0x0090,0x0094}, {0x0063,0x0063,0x0103,0x0103}, {0x0007,0x0007,0x02a7,0x02a7}, + {0x009b,0x009b,0x026b,0x026b}, {0x0263,0x0263,0x01ab,0x01ab}, {0x009c,0x00a0,0x00a4,0x00b8}, {0x0241,0x0011,0x0069,0x0019}, + {0x0211,0x0041,0x0291,0x0299}, {0x00a8,0x00ac,0x00b0,0x00b4}, {0x008b,0x008b,0x0223,0x0223}, {0x00a3,0x00a3,0x020b,0x020b}, + {0x02ab,0x02ab,0x0283,0x0283}, {0x002b,0x002b,0x0083,0x0083}, {0x00bc,0x00c0,0x00c4,0x00c8}, {0x0003,0x0003,0x022b,0x022b}, + {0x028b,0x028b,0x02a3,0x02a3}, {0x0023,0x0023,0x0203,0x0203}, {0x000b,0x000b,0x00ab,0x00ab} +}; + +const USHORT HuffmanCodeBook_2[39][4] = +{ + {0x0004,0x000c,0x0020,0x0034}, {0x0157,0x0157,0x0159,0x0008}, {0x0153,0x0153,0x0257,0x0257}, {0x0010,0x0014,0x0018,0x001c}, + {0x0117,0x0117,0x0057,0x0057}, {0x0147,0x0147,0x0197,0x0197}, {0x0167,0x0167,0x0185,0x0161}, {0x0125,0x0095,0x0065,0x0215}, + {0x0024,0x0028,0x002c,0x0030}, {0x0051,0x0149,0x0119,0x0141}, {0x0015,0x0199,0x0259,0x0245}, {0x0191,0x0265,0x0105,0x0251}, + {0x0045,0x0111,0x0169,0x01a5}, {0x0038,0x0044,0x0058,0x006c}, {0x0295,0x0059,0x003c,0x0040}, {0x0227,0x0227,0x021b,0x021b}, + {0x0123,0x0123,0x0087,0x0087}, {0x0048,0x004c,0x0050,0x0054}, {0x018b,0x018b,0x006b,0x006b}, {0x029b,0x029b,0x01a3,0x01a3}, + {0x0207,0x0207,0x01ab,0x01ab}, {0x0093,0x0093,0x0103,0x0103}, {0x005c,0x0060,0x0064,0x0068}, {0x0213,0x0213,0x010b,0x010b}, + {0x012b,0x012b,0x0249,0x0061}, {0x0181,0x0291,0x0241,0x0041}, {0x0005,0x0099,0x0019,0x0025}, {0x0070,0x0074,0x0078,0x0088}, + {0x02a5,0x0261,0x0011,0x00a5}, {0x0049,0x0285,0x0269,0x0089}, {0x0221,0x007c,0x0080,0x0084}, {0x020b,0x020b,0x0003,0x0003}, + {0x00a3,0x00a3,0x02a3,0x02a3}, {0x02ab,0x02ab,0x0083,0x0083}, {0x008c,0x0090,0x0094,0x0098}, {0x028b,0x028b,0x0023,0x0023}, + {0x0283,0x0283,0x002b,0x002b}, {0x000b,0x000b,0x0203,0x0203}, {0x022b,0x022b,0x00ab,0x00ab} +}; + +const USHORT HuffmanCodeBook_3[39][4] = +{ + {0x0003,0x0003,0x0004,0x0008}, {0x0005,0x0101,0x0011,0x0041}, {0x000c,0x0010,0x0014,0x0020}, {0x0017,0x0017,0x0143,0x0143}, + {0x0051,0x0111,0x0045,0x0151}, {0x0105,0x0055,0x0018,0x001c}, {0x0157,0x0157,0x0147,0x0147}, {0x0117,0x0117,0x0009,0x0201}, + {0x0024,0x002c,0x0040,0x0054}, {0x0241,0x0019,0x0065,0x0028}, {0x0183,0x0183,0x0193,0x0193}, {0x0030,0x0034,0x0038,0x003c}, + {0x0027,0x0027,0x0253,0x0253}, {0x005b,0x005b,0x0083,0x0083}, {0x0063,0x0063,0x0093,0x0093}, {0x0023,0x0023,0x0213,0x0213}, + {0x0044,0x0048,0x004c,0x0050}, {0x004b,0x004b,0x0167,0x0167}, {0x0163,0x0163,0x0097,0x0097}, {0x0197,0x0197,0x0125,0x0085}, + {0x0185,0x0121,0x0159,0x0255}, {0x0058,0x005c,0x0060,0x0070}, {0x0119,0x0245,0x0281,0x0291}, {0x0069,0x00a5,0x0205,0x0109}, + {0x01a1,0x0064,0x0068,0x006c}, {0x002b,0x002b,0x01a7,0x01a7}, {0x0217,0x0217,0x014b,0x014b}, {0x0297,0x0297,0x016b,0x016b}, + {0x0074,0x0078,0x007c,0x0080}, {0x00a3,0x00a3,0x0263,0x0263}, {0x0285,0x0129,0x0099,0x00a9}, {0x02a1,0x01a9,0x0199,0x0265}, + {0x02a5,0x0084,0x0088,0x008c}, {0x0223,0x0223,0x008b,0x008b}, {0x0227,0x0227,0x0189,0x0259}, {0x0219,0x0090,0x0094,0x0098}, + {0x02ab,0x02ab,0x026b,0x026b}, {0x029b,0x029b,0x024b,0x024b}, {0x020b,0x020b,0x0229,0x0289} +}; + +const USHORT HuffmanCodeBook_4[38][4] = +{ + {0x0004,0x0008,0x000c,0x0018}, {0x0155,0x0151,0x0115,0x0055}, {0x0145,0x0005,0x0015,0x0001}, {0x0141,0x0045,0x0010,0x0014}, + {0x0107,0x0107,0x0053,0x0053}, {0x0103,0x0103,0x0113,0x0113}, {0x001c,0x0020,0x0034,0x0048}, {0x0043,0x0043,0x0013,0x0013}, + {0x0024,0x0028,0x002c,0x0030}, {0x015b,0x015b,0x0197,0x0197}, {0x0167,0x0167,0x0257,0x0257}, {0x005b,0x005b,0x011b,0x011b}, + {0x0067,0x0067,0x014b,0x014b}, {0x0038,0x003c,0x0040,0x0044}, {0x0193,0x0193,0x0251,0x0095}, {0x0161,0x0245,0x0125,0x0215}, + {0x0185,0x0019,0x0049,0x0025}, {0x0109,0x0211,0x0061,0x0241}, {0x004c,0x0050,0x0058,0x006c}, {0x0091,0x0121,0x0205,0x0181}, + {0x0085,0x0009,0x0201,0x0054}, {0x0023,0x0023,0x0083,0x0083}, {0x005c,0x0060,0x0064,0x0068}, {0x01a7,0x01a7,0x016b,0x016b}, + {0x019b,0x019b,0x0297,0x0297}, {0x0267,0x0267,0x025b,0x025b}, {0x00a5,0x0069,0x0099,0x01a1}, {0x0070,0x0074,0x0078,0x0084}, + {0x0291,0x0129,0x0261,0x0189}, {0x0285,0x01a9,0x0225,0x0249}, {0x0219,0x02a5,0x007c,0x0080}, {0x029b,0x029b,0x026b,0x026b}, + {0x00a3,0x00a3,0x002b,0x002b}, {0x0088,0x008c,0x0090,0x0094}, {0x0283,0x0283,0x008b,0x008b}, {0x0223,0x0223,0x020b,0x020b}, + {0x02ab,0x02ab,0x02a3,0x02a3}, {0x00ab,0x00ab,0x0229,0x0289} +}; + +const USHORT HuffmanCodeBook_5[41][4] = +{ + {0x0113,0x0113,0x0004,0x0008}, {0x010d,0x0115,0x0151,0x00d1}, {0x000c,0x0010,0x0014,0x0028}, {0x00d7,0x00d7,0x014f,0x014f}, + {0x00cf,0x00cf,0x0157,0x0157}, {0x0018,0x001c,0x0020,0x0024}, {0x010b,0x010b,0x0193,0x0193}, {0x011b,0x011b,0x0093,0x0093}, + {0x00c9,0x0159,0x008d,0x0195}, {0x0149,0x00d9,0x018d,0x0095}, {0x002c,0x0030,0x0044,0x0058}, {0x0105,0x011d,0x0051,0x01d1}, + {0x0034,0x0038,0x003c,0x0040}, {0x00c7,0x00c7,0x01d7,0x01d7}, {0x015f,0x015f,0x004f,0x004f}, {0x0147,0x0147,0x00df,0x00df}, + {0x0057,0x0057,0x01cf,0x01cf}, {0x0048,0x004c,0x0050,0x0054}, {0x018b,0x018b,0x019b,0x019b}, {0x008b,0x008b,0x009b,0x009b}, + {0x0085,0x009d,0x01c9,0x0059}, {0x019d,0x01d9,0x0185,0x0049}, {0x005c,0x0060,0x0074,0x0088}, {0x0011,0x0101,0x0161,0x0121}, + {0x0064,0x0068,0x006c,0x0070}, {0x00c3,0x00c3,0x0213,0x0213}, {0x00e3,0x00e3,0x000f,0x000f}, {0x0217,0x0217,0x020f,0x020f}, + {0x0143,0x0143,0x0017,0x0017}, {0x0078,0x007c,0x0080,0x0084}, {0x005f,0x005f,0x0047,0x0047}, {0x01c7,0x01c7,0x020b,0x020b}, + {0x0083,0x0083,0x01a3,0x01a3}, {0x001b,0x001b,0x021b,0x021b}, {0x008c,0x0090,0x0094,0x0098}, {0x01df,0x01df,0x0183,0x0183}, + {0x0009,0x00a1,0x001d,0x0041}, {0x01c1,0x021d,0x0205,0x01e1}, {0x0061,0x0005,0x009c,0x00a0}, {0x0023,0x0023,0x0203,0x0203}, + {0x0223,0x0223,0x0003,0x0003} +}; + +const USHORT HuffmanCodeBook_6[40][4] = +{ + {0x0004,0x0008,0x000c,0x001c}, {0x0111,0x0115,0x00d1,0x0151}, {0x010d,0x0155,0x014d,0x00d5}, {0x00cd,0x0010,0x0014,0x0018}, + {0x00d9,0x0159,0x0149,0x00c9}, {0x0109,0x018d,0x0119,0x0095}, {0x0195,0x0091,0x008d,0x0191}, {0x0020,0x0024,0x0038,0x004c}, + {0x0099,0x0189,0x0089,0x0199}, {0x0028,0x002c,0x0030,0x0034}, {0x0147,0x0147,0x015f,0x015f}, {0x00df,0x00df,0x01cf,0x01cf}, + {0x00c7,0x00c7,0x01d7,0x01d7}, {0x0057,0x0057,0x004f,0x004f}, {0x003c,0x0040,0x0044,0x0048}, {0x011f,0x011f,0x0107,0x0107}, + {0x0053,0x0053,0x01d3,0x01d3}, {0x019f,0x019f,0x0085,0x01c9}, {0x01d9,0x009d,0x0059,0x0049}, {0x0050,0x005c,0x0070,0x0084}, + {0x0185,0x01dd,0x0054,0x0058}, {0x005f,0x005f,0x0047,0x0047}, {0x01c7,0x01c7,0x0017,0x0017}, {0x0060,0x0064,0x0068,0x006c}, + {0x000f,0x000f,0x0163,0x0163}, {0x0143,0x0143,0x00c3,0x00c3}, {0x0217,0x0217,0x00e3,0x00e3}, {0x020f,0x020f,0x0013,0x0013}, + {0x0074,0x0078,0x007c,0x0080}, {0x0183,0x0183,0x0083,0x0083}, {0x021b,0x021b,0x000b,0x000b}, {0x0103,0x0103,0x01a3,0x01a3}, + {0x00a3,0x00a3,0x020b,0x020b}, {0x0088,0x008c,0x0090,0x0094}, {0x0123,0x0123,0x001b,0x001b}, {0x0213,0x0213,0x0005,0x0205}, + {0x001d,0x0061,0x021d,0x01e1}, {0x01c1,0x0041,0x0098,0x009c}, {0x0223,0x0223,0x0203,0x0203}, {0x0003,0x0003,0x0023,0x0023} +}; + +const USHORT HuffmanCodeBook_7[31][4] = +{ + {0x0003,0x0003,0x0004,0x0008}, {0x0007,0x0007,0x0043,0x0043}, {0x0045,0x000c,0x0010,0x0024}, {0x0049,0x0085,0x0009,0x0081}, + {0x0014,0x0018,0x001c,0x0020}, {0x004f,0x004f,0x00c7,0x00c7}, {0x008b,0x008b,0x000f,0x000f}, {0x00c3,0x00c3,0x00c9,0x008d}, + {0x0105,0x0051,0x0145,0x0055}, {0x0028,0x002c,0x0040,0x0054}, {0x00cd,0x0109,0x0101,0x0011}, {0x0030,0x0034,0x0038,0x003c}, + {0x0093,0x0093,0x014b,0x014b}, {0x0097,0x0097,0x0143,0x0143}, {0x005b,0x005b,0x0017,0x0017}, {0x0187,0x0187,0x00d3,0x00d3}, + {0x0044,0x0048,0x004c,0x0050}, {0x014f,0x014f,0x010f,0x010f}, {0x00d7,0x00d7,0x018b,0x018b}, {0x009b,0x009b,0x01c7,0x01c7}, + {0x018d,0x0181,0x0019,0x0111}, {0x0058,0x005c,0x0060,0x0068}, {0x005d,0x0151,0x009d,0x0115}, {0x00d9,0x01c9,0x00dd,0x0119}, + {0x0155,0x0191,0x01cd,0x0064}, {0x001f,0x001f,0x01c3,0x01c3}, {0x006c,0x0070,0x0074,0x0078}, {0x015b,0x015b,0x0197,0x0197}, + {0x011f,0x011f,0x01d3,0x01d3}, {0x01d7,0x01d7,0x015f,0x015f}, {0x019d,0x0199,0x01d9,0x01dd} +}; + +const USHORT HuffmanCodeBook_8[31][4] = +{ + {0x0004,0x0008,0x0010,0x0024}, {0x0047,0x0047,0x0049,0x0005}, {0x0085,0x0041,0x0089,0x000c}, {0x0003,0x0003,0x000b,0x000b}, + {0x0014,0x0018,0x001c,0x0020}, {0x0083,0x0083,0x004f,0x004f}, {0x00c7,0x00c7,0x008f,0x008f}, {0x00cb,0x00cb,0x00cd,0x0051}, + {0x0105,0x0091,0x0109,0x000d}, {0x0028,0x002c,0x0040,0x0054}, {0x00c1,0x00d1,0x010d,0x0095}, {0x0030,0x0034,0x0038,0x003c}, + {0x0057,0x0057,0x014b,0x014b}, {0x0147,0x0147,0x00d7,0x00d7}, {0x014f,0x014f,0x0113,0x0113}, {0x0117,0x0117,0x0103,0x0103}, + {0x0044,0x0048,0x004c,0x0050}, {0x0153,0x0153,0x0013,0x0013}, {0x018b,0x018b,0x009b,0x009b}, {0x005b,0x005b,0x0187,0x0187}, + {0x018d,0x00d9,0x0155,0x0015}, {0x0058,0x005c,0x0060,0x0068}, {0x0119,0x0141,0x0191,0x005d}, {0x009d,0x01c9,0x0159,0x00dd}, + {0x01c5,0x0195,0x01cd,0x0064}, {0x019b,0x019b,0x011f,0x011f}, {0x006c,0x0070,0x0074,0x0078}, {0x001b,0x001b,0x01d3,0x01d3}, + {0x0183,0x0183,0x015f,0x015f}, {0x019f,0x019f,0x01db,0x01db}, {0x01d5,0x001d,0x01c1,0x01dd} +}; + +const USHORT HuffmanCodeBook_9[84][4] = +{ + {0x0003,0x0003,0x0004,0x0008}, {0x0007,0x0007,0x0043,0x0043}, {0x0045,0x000c,0x0010,0x002c}, {0x0049,0x0085,0x0009,0x0081}, + {0x0014,0x0018,0x001c,0x0020}, {0x004f,0x004f,0x008b,0x008b}, {0x00c7,0x00c7,0x000d,0x00c1}, {0x00c9,0x008d,0x0105,0x0051}, + {0x0109,0x0145,0x0024,0x0028}, {0x0093,0x0093,0x00cf,0x00cf}, {0x0103,0x0103,0x0013,0x0013}, {0x0030,0x0044,0x0058,0x00a4}, + {0x0034,0x0038,0x003c,0x0040}, {0x0057,0x0057,0x014b,0x014b}, {0x0187,0x0187,0x010f,0x010f}, {0x0097,0x0097,0x005b,0x005b}, + {0x00d3,0x00d3,0x0141,0x0189}, {0x0048,0x004c,0x0050,0x0054}, {0x0015,0x01c5,0x014d,0x0205}, {0x0061,0x0111,0x00d5,0x0099}, + {0x005d,0x0181,0x00a1,0x0209}, {0x018d,0x01c9,0x0151,0x0065}, {0x005c,0x0068,0x007c,0x0090}, {0x0245,0x009d,0x0060,0x0064}, + {0x001b,0x001b,0x0117,0x0117}, {0x00db,0x00db,0x00e3,0x00e3}, {0x006c,0x0070,0x0074,0x0078}, {0x01c3,0x01c3,0x00a7,0x00a7}, + {0x020f,0x020f,0x0193,0x0193}, {0x01cf,0x01cf,0x0203,0x0203}, {0x006b,0x006b,0x011b,0x011b}, {0x0080,0x0084,0x0088,0x008c}, + {0x024b,0x024b,0x0157,0x0157}, {0x0023,0x0023,0x001f,0x001f}, {0x00df,0x00df,0x00ab,0x00ab}, {0x00e7,0x00e7,0x0123,0x0123}, + {0x0094,0x0098,0x009c,0x00a0}, {0x0287,0x0287,0x011f,0x011f}, {0x015b,0x015b,0x0197,0x0197}, {0x0213,0x0213,0x01d3,0x01d3}, + {0x024f,0x024f,0x006f,0x006f}, {0x00a8,0x00bc,0x00d0,0x00f4}, {0x00ac,0x00b0,0x00b4,0x00b8}, {0x0217,0x0217,0x0027,0x0027}, + {0x0163,0x0163,0x00e9,0x0289}, {0x0241,0x00ad,0x0125,0x0199}, {0x0071,0x0251,0x01a1,0x02c5}, {0x00c0,0x00c4,0x00c8,0x00cc}, + {0x0165,0x0129,0x01d5,0x015d}, {0x02c9,0x0305,0x00b1,0x00ed}, {0x028d,0x0255,0x01d9,0x01e1}, {0x012d,0x0281,0x019d,0x00f1}, + {0x00d4,0x00d8,0x00dc,0x00e0}, {0x0029,0x0169,0x0291,0x0219}, {0x0309,0x01a5,0x01e5,0x02d1}, {0x002d,0x0259,0x02cd,0x0295}, + {0x00e4,0x00e8,0x00ec,0x00f0}, {0x0223,0x0223,0x021f,0x021f}, {0x0173,0x0173,0x030f,0x030f}, {0x016f,0x016f,0x01df,0x01df}, + {0x0133,0x0133,0x01af,0x01af}, {0x00f8,0x010c,0x0120,0x0134}, {0x00fc,0x0100,0x0104,0x0108}, {0x01ab,0x01ab,0x0313,0x0313}, + {0x025f,0x025f,0x02d7,0x02d7}, {0x02c3,0x02c3,0x01b3,0x01b3}, {0x029b,0x029b,0x0033,0x0033}, {0x0110,0x0114,0x0118,0x011c}, + {0x01eb,0x01eb,0x0317,0x0317}, {0x029f,0x029f,0x0227,0x0227}, {0x0303,0x0303,0x01ef,0x01ef}, {0x0263,0x0263,0x0267,0x0267}, + {0x0124,0x0128,0x012c,0x0130}, {0x022b,0x022b,0x02df,0x02df}, {0x01f3,0x01f3,0x02db,0x02db}, {0x02e3,0x02e3,0x022f,0x022f}, + {0x031f,0x031f,0x031b,0x031b}, {0x0138,0x013c,0x0140,0x0144}, {0x02a1,0x0269,0x0321,0x02a5}, {0x02e5,0x0325,0x02e9,0x0271}, + {0x02a9,0x026d,0x0231,0x02ad}, {0x02b1,0x02f1,0x0148,0x014c}, {0x032b,0x032b,0x02ef,0x02ef}, {0x032f,0x032f,0x0333,0x0333} +}; + +const USHORT HuffmanCodeBook_10[82][4] = +{ + {0x0004,0x000c,0x0020,0x004c}, {0x0045,0x0085,0x0049,0x0008}, {0x008b,0x008b,0x0007,0x0007}, {0x0010,0x0014,0x0018,0x001c}, + {0x0043,0x0043,0x00c7,0x00c7}, {0x008f,0x008f,0x004f,0x004f}, {0x00cb,0x00cb,0x00cf,0x00cf}, {0x0009,0x0081,0x0109,0x0091}, + {0x0024,0x0028,0x002c,0x0038}, {0x0105,0x0051,0x0001,0x00d1}, {0x010d,0x000d,0x00c1,0x0111}, {0x0149,0x0095,0x0030,0x0034}, + {0x0147,0x0147,0x0057,0x0057}, {0x00d7,0x00d7,0x014f,0x014f}, {0x003c,0x0040,0x0044,0x0048}, {0x0117,0x0117,0x0153,0x0153}, + {0x009b,0x009b,0x018b,0x018b}, {0x00db,0x00db,0x0013,0x0013}, {0x005b,0x005b,0x0103,0x0103}, {0x0050,0x0064,0x0078,0x00c0}, + {0x0054,0x0058,0x005c,0x0060}, {0x0187,0x0187,0x018f,0x018f}, {0x0157,0x0157,0x011b,0x011b}, {0x0193,0x0193,0x0159,0x009d}, + {0x01cd,0x01c9,0x0195,0x00a1}, {0x0068,0x006c,0x0070,0x0074}, {0x00dd,0x0015,0x005d,0x0141}, {0x0061,0x01c5,0x00e1,0x011d}, + {0x01d1,0x0209,0x0199,0x015d}, {0x0205,0x020d,0x0121,0x0211}, {0x007c,0x0084,0x0098,0x00ac}, {0x01d5,0x0161,0x0215,0x0080}, + {0x019f,0x019f,0x01db,0x01db}, {0x0088,0x008c,0x0090,0x0094}, {0x00a7,0x00a7,0x001b,0x001b}, {0x021b,0x021b,0x00e7,0x00e7}, + {0x024f,0x024f,0x0067,0x0067}, {0x024b,0x024b,0x0183,0x0183}, {0x009c,0x00a0,0x00a4,0x00a8}, {0x01a3,0x01a3,0x0127,0x0127}, + {0x0253,0x0253,0x00ab,0x00ab}, {0x0247,0x0247,0x01df,0x01df}, {0x01e3,0x01e3,0x0167,0x0167}, {0x00b0,0x00b4,0x00b8,0x00bc}, + {0x021f,0x021f,0x00eb,0x00eb}, {0x0257,0x0257,0x012b,0x012b}, {0x028b,0x028b,0x006b,0x006b}, {0x028f,0x028f,0x01a7,0x01a7}, + {0x00c4,0x00d8,0x00ec,0x0100}, {0x00c8,0x00cc,0x00d0,0x00d4}, {0x025b,0x025b,0x0023,0x0023}, {0x0293,0x0293,0x001f,0x001f}, + {0x00af,0x00af,0x025d,0x00ed}, {0x01a9,0x0285,0x006d,0x01e5}, {0x00dc,0x00e0,0x00e4,0x00e8}, {0x01c1,0x0221,0x0169,0x02cd}, + {0x0295,0x0261,0x016d,0x0201}, {0x012d,0x02c9,0x029d,0x0299}, {0x01e9,0x02d1,0x02c5,0x00b1}, {0x00f0,0x00f4,0x00f8,0x00fc}, + {0x0225,0x00f1,0x01ad,0x02d5}, {0x0131,0x01ed,0x0171,0x030d}, {0x02d9,0x0025,0x0229,0x0029}, {0x0071,0x0241,0x0311,0x0265}, + {0x0104,0x010c,0x0120,0x0134}, {0x01b1,0x0309,0x02a1,0x0108}, {0x02a7,0x02a7,0x0307,0x0307}, {0x0110,0x0114,0x0118,0x011c}, + {0x022f,0x022f,0x01f3,0x01f3}, {0x02df,0x02df,0x0317,0x0317}, {0x031b,0x031b,0x026b,0x026b}, {0x02e3,0x02e3,0x0233,0x0233}, + {0x0124,0x0128,0x012c,0x0130}, {0x0283,0x0283,0x031f,0x031f}, {0x002f,0x002f,0x02ab,0x02ab}, {0x026f,0x026f,0x02af,0x02af}, + {0x02c3,0x02c3,0x02ef,0x02ef}, {0x0138,0x013c,0x0140,0x0144}, {0x02e7,0x02e7,0x02eb,0x02eb}, {0x0033,0x0033,0x0323,0x0323}, + {0x0271,0x0329,0x0325,0x032d}, {0x02f1,0x0301,0x02b1,0x0331} +}; + +const USHORT HuffmanCodeBook_11[152][4] = +{ + {0x0004,0x0010,0x0038,0x008c}, {0x0001,0x0085,0x0008,0x000c}, {0x0843,0x0843,0x0007,0x0007}, {0x0083,0x0083,0x008b,0x008b}, + {0x0014,0x0018,0x001c,0x0024}, {0x0107,0x0107,0x010b,0x010b}, {0x0185,0x008d,0x010d,0x0009}, {0x0189,0x0101,0x018d,0x0020}, + {0x0093,0x0093,0x0207,0x0207}, {0x0028,0x002c,0x0030,0x0034}, {0x0113,0x0113,0x020b,0x020b}, {0x0193,0x0193,0x020f,0x020f}, + {0x000f,0x000f,0x0183,0x0183}, {0x0097,0x0097,0x0117,0x0117}, {0x003c,0x0050,0x0064,0x0078}, {0x0040,0x0044,0x0048,0x004c}, + {0x028b,0x028b,0x0213,0x0213}, {0x0287,0x0287,0x0197,0x0197}, {0x028f,0x028f,0x0217,0x0217}, {0x0291,0x0119,0x0309,0x0099}, + {0x0054,0x0058,0x005c,0x0060}, {0x0199,0x030d,0x0305,0x0811}, {0x080d,0x02c1,0x01c1,0x0241}, {0x0219,0x0341,0x0011,0x0311}, + {0x0201,0x0809,0x0295,0x0815}, {0x0068,0x006c,0x0070,0x0074}, {0x03c1,0x0141,0x0441,0x0389}, {0x011d,0x038d,0x0299,0x0315}, + {0x0819,0x0541,0x019d,0x009d}, {0x04c1,0x081d,0x0805,0x0385}, {0x007c,0x0080,0x0084,0x0088}, {0x0391,0x05c1,0x021d,0x0641}, + {0x0821,0x00c1,0x0319,0x0825}, {0x0409,0x0395,0x0829,0x06c1}, {0x01a1,0x0121,0x040d,0x0015}, {0x0090,0x00c8,0x011c,0x0170}, + {0x0094,0x0098,0x00a0,0x00b4}, {0x0741,0x082d,0x029d,0x0411}, {0x0399,0x031d,0x0281,0x009c}, {0x0223,0x0223,0x07c3,0x07c3}, + {0x00a4,0x00a8,0x00ac,0x00b0}, {0x0833,0x0833,0x0407,0x0407}, {0x00a3,0x00a3,0x083b,0x083b}, {0x0417,0x0417,0x0837,0x0837}, + {0x048f,0x048f,0x02a3,0x02a3}, {0x00b8,0x00bc,0x00c0,0x00c4}, {0x039f,0x039f,0x048b,0x048b}, {0x0323,0x0323,0x0127,0x0127}, + {0x01a7,0x01a7,0x083f,0x083f}, {0x0493,0x0493,0x041b,0x041b}, {0x00cc,0x00e0,0x00f4,0x0108}, {0x00d0,0x00d4,0x00d8,0x00dc}, + {0x001b,0x001b,0x0227,0x0227}, {0x0497,0x0497,0x03a3,0x03a3}, {0x041f,0x041f,0x0487,0x0487}, {0x01ab,0x01ab,0x0303,0x0303}, + {0x00e4,0x00e8,0x00ec,0x00f0}, {0x012b,0x012b,0x00a7,0x00a7}, {0x02a7,0x02a7,0x0513,0x0513}, {0x050b,0x050b,0x0327,0x0327}, + {0x050f,0x050f,0x049b,0x049b}, {0x00f8,0x00fc,0x0100,0x0104}, {0x022b,0x022b,0x0423,0x0423}, {0x02ab,0x02ab,0x03a7,0x03a7}, + {0x01af,0x01af,0x0507,0x0507}, {0x001f,0x001f,0x032b,0x032b}, {0x010c,0x0110,0x0114,0x0118}, {0x049f,0x049f,0x058f,0x058f}, + {0x0517,0x0517,0x00ab,0x00ab}, {0x0593,0x0593,0x012f,0x012f}, {0x0137,0x0137,0x051b,0x051b}, {0x0120,0x0134,0x0148,0x015c}, + {0x0124,0x0128,0x012c,0x0130}, {0x01b7,0x01b7,0x058b,0x058b}, {0x0043,0x0043,0x0597,0x0597}, {0x02af,0x02af,0x022d,0x0425}, + {0x051d,0x04a1,0x0801,0x0691}, {0x0138,0x013c,0x0140,0x0144}, {0x0381,0x068d,0x032d,0x00b5}, {0x0235,0x01b1,0x0689,0x02b5}, + {0x0521,0x0599,0x0429,0x03a9}, {0x0139,0x0231,0x0585,0x0611}, {0x014c,0x0150,0x0154,0x0158}, {0x00ad,0x060d,0x0685,0x0131}, + {0x059d,0x070d,0x0615,0x0695}, {0x0239,0x0711,0x03ad,0x01b9}, {0x02b1,0x0335,0x0331,0x0021}, {0x0160,0x0164,0x0168,0x016c}, + {0x042d,0x0609,0x04a5,0x02b9}, {0x0699,0x0529,0x013d,0x05a1}, {0x0525,0x0339,0x04a9,0x0715}, {0x04ad,0x00b9,0x0709,0x0619}, + {0x0174,0x0188,0x019c,0x01cc}, {0x0178,0x017c,0x0180,0x0184}, {0x0605,0x0435,0x0401,0x03b5}, {0x061d,0x03b1,0x069d,0x01bd}, + {0x00b1,0x0719,0x0789,0x02bd}, {0x023d,0x0705,0x05a5,0x0791}, {0x018c,0x0190,0x0194,0x0198}, {0x03b9,0x06a1,0x04b5,0x0621}, + {0x0795,0x078d,0x05a9,0x052d}, {0x0431,0x033d,0x03bd,0x0721}, {0x00bd,0x071d,0x0025,0x0481}, {0x01a0,0x01a4,0x01a8,0x01b8}, + {0x06a5,0x0625,0x04b1,0x0439}, {0x06a9,0x04b9,0x0531,0x0799}, {0x079d,0x01ac,0x01b0,0x01b4}, {0x0727,0x0727,0x043f,0x043f}, + {0x05af,0x05af,0x072f,0x072f}, {0x0787,0x0787,0x062b,0x062b}, {0x01bc,0x01c0,0x01c4,0x01c8}, {0x072b,0x072b,0x05b7,0x05b7}, + {0x0537,0x0537,0x06af,0x06af}, {0x062f,0x062f,0x07a3,0x07a3}, {0x05bb,0x05bb,0x0637,0x0637}, {0x01d0,0x01e4,0x01f8,0x020c}, + {0x01d4,0x01d8,0x01dc,0x01e0}, {0x06b3,0x06b3,0x04bf,0x04bf}, {0x053b,0x053b,0x002b,0x002b}, {0x05b3,0x05b3,0x07a7,0x07a7}, + {0x0503,0x0503,0x0633,0x0633}, {0x01e8,0x01ec,0x01f0,0x01f4}, {0x002f,0x002f,0x0733,0x0733}, {0x07ab,0x07ab,0x06b7,0x06b7}, + {0x0683,0x0683,0x063b,0x063b}, {0x053f,0x053f,0x05bf,0x05bf}, {0x01fc,0x0200,0x0204,0x0208}, {0x07af,0x07af,0x06bb,0x06bb}, + {0x0037,0x0037,0x0583,0x0583}, {0x0737,0x0737,0x063f,0x063f}, {0x06bf,0x06bf,0x07b3,0x07b3}, {0x0210,0x0214,0x0218,0x021c}, + {0x003b,0x003b,0x073b,0x073b}, {0x07b7,0x07b7,0x0033,0x0033}, {0x07bb,0x07bb,0x0701,0x0601}, {0x073d,0x003d,0x0781,0x07bd}, + {0x0118,0x0117,0x0100,0x0109}, {0x05a5,0x05a1,0x05b7,0x0513}, {0x08f9,0x08ff,0x0821,0x08ff}, {0x084f,0x08ff,0x08bc,0x08ff}, + {0x0815,0x08ff,0x0837,0x08ff}, {0x080d,0x08ff,0x085f,0x08ff}, {0x084a,0x08ff,0x087d,0x08ff}, {0x08ff,0x08ff,0x08a8,0x08ff}, + {0x0815,0x08ff,0x083f,0x08ff}, {0x0830,0x08ff,0x0894,0x08ff}, {0x08d4,0x08ff,0x0825,0x08ff}, {0x08ef,0x08ff,0x083f,0x08ff}, + {0x0809,0x08ff,0x08fc,0x08ff}, {0x0842,0x08ff,0x08b3,0x08ff}, {0x070d,0x07a9,0x060e,0x06e2}, {0x06c7,0x06d0,0x04b2,0x0407} +}; + + +const USHORT HuffmanCodeBook_SCL[65][4] = +{ + {0x00f3,0x00f3,0x0004,0x0008}, {0x00ef,0x00ef,0x00f5,0x00e9}, {0x00f9,0x000c,0x0010,0x0014}, {0x00e7,0x00e7,0x00ff,0x00ff}, + {0x00e1,0x0101,0x00dd,0x0105}, {0x0018,0x001c,0x0020,0x0028}, {0x010b,0x010b,0x00db,0x00db}, {0x010f,0x010f,0x00d5,0x0111}, + {0x00d1,0x0115,0x00cd,0x0024}, {0x011b,0x011b,0x00cb,0x00cb}, {0x002c,0x0030,0x0034,0x0040}, {0x00c7,0x00c7,0x011f,0x011f}, + {0x0121,0x00c1,0x0125,0x00bd}, {0x0129,0x00b9,0x0038,0x003c}, {0x0133,0x0133,0x012f,0x012f}, {0x0137,0x0137,0x013b,0x013b}, + {0x0044,0x0048,0x004c,0x0058}, {0x00b7,0x00b7,0x00af,0x00af}, {0x00b1,0x013d,0x00a9,0x00a5}, {0x0141,0x00a1,0x0050,0x0054}, + {0x0147,0x0147,0x009f,0x009f}, {0x014b,0x014b,0x009b,0x009b}, {0x005c,0x0060,0x0064,0x0070}, {0x014f,0x014f,0x0095,0x008d}, + {0x0155,0x0085,0x0091,0x0089}, {0x0151,0x0081,0x0068,0x006c}, {0x015f,0x015f,0x0167,0x0167}, {0x007b,0x007b,0x007f,0x007f}, + {0x0074,0x0078,0x0080,0x00b0}, {0x0159,0x0075,0x0069,0x006d}, {0x0071,0x0061,0x0161,0x007c}, {0x0067,0x0067,0x005b,0x005b}, + {0x0084,0x0088,0x008c,0x009c}, {0x005f,0x005f,0x0169,0x0055}, {0x004d,0x000d,0x0005,0x0009}, {0x0001,0x0090,0x0094,0x0098}, + {0x018b,0x018b,0x018f,0x018f}, {0x0193,0x0193,0x0197,0x0197}, {0x019b,0x019b,0x01d7,0x01d7}, {0x00a0,0x00a4,0x00a8,0x00ac}, + {0x0187,0x0187,0x016f,0x016f}, {0x0173,0x0173,0x0177,0x0177}, {0x017b,0x017b,0x017f,0x017f}, {0x0183,0x0183,0x01a3,0x01a3}, + {0x00b4,0x00c8,0x00dc,0x00f0}, {0x00b8,0x00bc,0x00c0,0x00c4}, {0x01bf,0x01bf,0x01c3,0x01c3}, {0x01c7,0x01c7,0x01cb,0x01cb}, + {0x01cf,0x01cf,0x01d3,0x01d3}, {0x01bb,0x01bb,0x01a7,0x01a7}, {0x00cc,0x00d0,0x00d4,0x00d8}, {0x01ab,0x01ab,0x01af,0x01af}, + {0x01b3,0x01b3,0x01b7,0x01b7}, {0x01db,0x01db,0x001b,0x001b}, {0x0023,0x0023,0x0027,0x0027}, {0x00e0,0x00e4,0x00e8,0x00ec}, + {0x002b,0x002b,0x0017,0x0017}, {0x019f,0x019f,0x01e3,0x01e3}, {0x01df,0x01df,0x0013,0x0013}, {0x001f,0x001f,0x003f,0x003f}, + {0x00f4,0x00f8,0x00fc,0x0100}, {0x0043,0x0043,0x004b,0x004b}, {0x0053,0x0053,0x0047,0x0047}, {0x002f,0x002f,0x0033,0x0033}, + {0x003b,0x003b,0x0037,0x0037} +}; + + + +/* .CodeBook = HuffmanCodeBook_x, .Dimension = 4, .numBits = 2, .Offset = 0 */ +const CodeBookDescription AACcodeBookDescriptionTable[13] = { + { NULL, 0, 0, 0 }, + { HuffmanCodeBook_1, 4, 2, 1 }, + { HuffmanCodeBook_2, 4, 2, 1 }, + { HuffmanCodeBook_3, 4, 2, 0 }, + { HuffmanCodeBook_4, 4, 2, 0 }, + { HuffmanCodeBook_5, 2, 4, 4 }, + { HuffmanCodeBook_6, 2, 4, 4 }, + { HuffmanCodeBook_7, 2, 4, 0 }, + { HuffmanCodeBook_8, 2, 4, 0 }, + { HuffmanCodeBook_9, 2, 4, 0 }, + { HuffmanCodeBook_10, 2, 4, 0 }, + { HuffmanCodeBook_11, 2, 5, 0 }, + { HuffmanCodeBook_SCL, 1, 8, 60 } +}; + +const CodeBookDescription AACcodeBookDescriptionSCL = { HuffmanCodeBook_SCL, 1, 8, 60 }; + + + +/* ********************************************************************************************* */ +/* Table: HuffTree41 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 1). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- */ +/* HuffTree */ +const UINT aHuffTree41[80] = {0x4a0001,0x026002,0x013003,0x021004,0x01c005,0x00b006,0x010007,0x019008, + 0x00900e,0x00a03a,0x400528,0x00c037,0x00d03b,0x454404,0x00f04c,0x448408, + 0x017011,0x01202e,0x42c40c,0x034014,0x01502c,0x016049,0x410470,0x01804e, + 0x414424,0x03201a,0x02001b,0x520418,0x02f01d,0x02a01e,0x01f04d,0x41c474, + 0x540420,0x022024,0x04a023,0x428510,0x025029,0x430508,0x02703c,0x028047, + 0x50c434,0x438478,0x04802b,0x46443c,0x02d03e,0x4404b0,0x44451c,0x03003f, + 0x03104b,0x52444c,0x033039,0x4f0450,0x035041,0x036046,0x4e8458,0x04f038, + 0x45c53c,0x4604e0,0x4f8468,0x46c4d4,0x04503d,0x4ac47c,0x518480,0x043040, + 0x4844dc,0x042044,0x4884a8,0x4bc48c,0x530490,0x4a4494,0x4984b8,0x49c4c4, + 0x5044b4,0x5004c0,0x4d04c8,0x4f44cc,0x4d8538,0x4ec4e4,0x52c4fc,0x514534}; + +/* ********************************************************************************************* */ +/* Table: HuffTree42 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 2). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree42[80] = {0x026001,0x014002,0x009003,0x010004,0x01d005,0x00600d,0x007018,0x450008, + 0x4e0400,0x02e00a,0x03900b,0x03d00c,0x43c404,0x01b00e,0x00f04f,0x4d8408, + 0x023011,0x01203b,0x01a013,0x41440c,0x015020,0x016040,0x025017,0x500410, + 0x038019,0x540418,0x41c444,0x02d01c,0x420520,0x01e042,0x03701f,0x4244cc, + 0x02a021,0x02204c,0x478428,0x024031,0x42c4dc,0x4304e8,0x027033,0x4a0028, + 0x50c029,0x4344a4,0x02c02b,0x470438,0x4404c8,0x4f8448,0x04902f,0x04b030, + 0x44c484,0x524032,0x4ec454,0x03e034,0x035046,0x4c4036,0x488458,0x4d445c, + 0x460468,0x04e03a,0x51c464,0x03c04a,0x46c514,0x47453c,0x04503f,0x47c4ac, + 0x044041,0x510480,0x04304d,0x4e448c,0x490518,0x49449c,0x048047,0x4c0498, + 0x4b84a8,0x4b0508,0x4fc4b4,0x4bc504,0x5304d0,0x5344f0,0x4f452c,0x528538}; + +/* ********************************************************************************************* */ +/* Table: HuffTree43 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 3). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree43[80] = {0x400001,0x002004,0x00300a,0x46c404,0x00b005,0x00600d,0x034007,0x037008, + 0x494009,0x4d8408,0x42440c,0x00c01b,0x490410,0x00e016,0x00f011,0x010014, + 0x4144fc,0x01201d,0x020013,0x508418,0x4c0015,0x41c440,0x022017,0x018026, + 0x019035,0x03801a,0x420444,0x01c01f,0x430428,0x02101e,0x44842c,0x478434, + 0x4b4438,0x45443c,0x02c023,0x039024,0x02503f,0x48844c,0x030027,0x02e028, + 0x032029,0x02a041,0x4d402b,0x4504f0,0x04302d,0x4584a8,0x02f03b,0x46045c, + 0x03103d,0x464046,0x033044,0x46853c,0x47049c,0x045036,0x4744dc,0x4a047c, + 0x500480,0x4ac03a,0x4b8484,0x03c04e,0x48c524,0x03e040,0x4984e8,0x50c4a4, + 0x4b0530,0x042047,0x4bc04b,0x4e44c4,0x5184c8,0x52c4cc,0x5204d0,0x04d048, + 0x04a049,0x4e004c,0x51c4ec,0x4f4510,0x5284f8,0x50404f,0x514538,0x540534}; + +/* ********************************************************************************************* */ +/* Table: HuffTree44 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 4). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 4) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree44[80] = {0x001004,0x020002,0x036003,0x490400,0x005008,0x010006,0x01f007,0x404428, + 0x00e009,0x01100a,0x00b018,0x01600c,0x03700d,0x408015,0x00f03e,0x40c424, + 0x410478,0x022012,0x038013,0x01e014,0x454414,0x448418,0x025017,0x47441c, + 0x030019,0x02601a,0x02d01b,0x01c034,0x01d029,0x4204f0,0x4dc42c,0x470430, + 0x02103c,0x4a0434,0x02302a,0x440024,0x4384a8,0x43c44c,0x02703a,0x02802c, + 0x444524,0x4504e0,0x02b03d,0x458480,0x45c4f4,0x04b02e,0x04f02f,0x460520, + 0x042031,0x048032,0x049033,0x514464,0x03504c,0x540468,0x47c46c,0x4844d8, + 0x039044,0x4884fc,0x03b045,0x48c53c,0x49449c,0x4b8498,0x03f046,0x041040, + 0x4c44a4,0x50c4ac,0x04a043,0x5184b0,0x4e44b4,0x4bc4ec,0x04e047,0x4c04e8, + 0x4c8510,0x4cc52c,0x4d0530,0x5044d4,0x53804d,0x5284f8,0x508500,0x51c534}; + +/* ********************************************************************************************* */ +/* Table: HuffTree21 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 5). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree21[80] = {0x450001,0x044002,0x042003,0x035004,0x026005,0x022006,0x013007,0x010008, + 0x00d009,0x01c00a,0x01f00b,0x01e00c,0x4a0400,0x01b00e,0x03200f,0x47e402, + 0x020011,0x01204d,0x40449c,0x017014,0x015019,0x01603f,0x406458,0x01804f, + 0x448408,0x04901a,0x40a45a,0x48c40c,0x01d031,0x40e48e,0x490410,0x492412, + 0x021030,0x480414,0x033023,0x02402e,0x02503e,0x416482,0x02a027,0x02802c, + 0x029040,0x418468,0x02b04a,0x41a486,0x02d048,0x41c484,0x04e02f,0x41e426, + 0x420434,0x42249e,0x424494,0x03d034,0x428470,0x039036,0x03703b,0x038041, + 0x42a476,0x03a04b,0x42c454,0x03c047,0x42e472,0x430478,0x43246e,0x496436, + 0x488438,0x43a466,0x046043,0x43c464,0x04504c,0x43e462,0x460440,0x44245e, + 0x45c444,0x46a446,0x44a456,0x47444c,0x45244e,0x46c47c,0x48a47a,0x49a498}; + +/* ********************************************************************************************* */ +/* Table: HuffTree22 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 6). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree22[80] = {0x03c001,0x02f002,0x020003,0x01c004,0x00f005,0x00c006,0x016007,0x04d008, + 0x00b009,0x01500a,0x400490,0x40e402,0x00d013,0x00e02a,0x40c404,0x019010, + 0x011041,0x038012,0x40a406,0x014037,0x40849c,0x4a0410,0x04a017,0x458018, + 0x412422,0x02801a,0x01b029,0x480414,0x02401d,0x01e02b,0x48a01f,0x416432, + 0x02d021,0x026022,0x023039,0x418468,0x025043,0x48641a,0x027040,0x41c488, + 0x41e48c,0x42045a,0x47c424,0x04c02c,0x46e426,0x03602e,0x428478,0x030033, + 0x43c031,0x04b032,0x42e42a,0x03403a,0x035048,0x42c442,0x470430,0x494434, + 0x43649a,0x45c438,0x04403b,0x43a454,0x04503d,0x03e03f,0x43e464,0x440460, + 0x484444,0x049042,0x446448,0x44a456,0x46644c,0x047046,0x44e452,0x450462, + 0x47445e,0x46a496,0x49846c,0x472476,0x47a482,0x04e04f,0x47e492,0x48e49e}; + +/* ********************************************************************************************* */ +/* Table: HuffTree23 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 7). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree23[63] = {0x400001,0x002003,0x410402,0x004007,0x412005,0x01c006,0x420404,0x00800b, + 0x01d009,0x00a01f,0x406026,0x00c012,0x00d00f,0x02700e,0x408440,0x010022, + 0x028011,0x45440a,0x013017,0x029014,0x024015,0x01602f,0x43c40c,0x02b018, + 0x019033,0x03201a,0x43e01b,0x47040e,0x422414,0x01e025,0x432416,0x020021, + 0x418442,0x41a452,0x036023,0x41c446,0x46441e,0x424430,0x426434,0x436428, + 0x44442a,0x02e02a,0x45642c,0x03002c,0x02d03b,0x46642e,0x43a438,0x460448, + 0x031037,0x47244a,0x45a44c,0x034039,0x038035,0x47844e,0x462450,0x474458, + 0x46a45c,0x03a03c,0x45e47a,0x476468,0x03d03e,0x47c46c,0x46e47e}; + +/* ********************************************************************************************* */ +/* Table: HuffTree24 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 8). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree24[63] = {0x001006,0x01d002,0x005003,0x424004,0x400420,0x414402,0x00700a,0x008020, + 0x00901f,0x404432,0x00b011,0x00c00e,0x00d032,0x406446,0x02300f,0x033010, + 0x458408,0x025012,0x013016,0x01402f,0x015038,0x46840a,0x028017,0x01801a, + 0x039019,0x40c47a,0x03e01b,0x03b01c,0x40e47e,0x41201e,0x422410,0x416434, + 0x02a021,0x02202b,0x418444,0x02c024,0x41a456,0x02d026,0x027034,0x46241c, + 0x029036,0x41e45c,0x426031,0x428430,0x45242a,0x03702e,0x42c464,0x03003c, + 0x47442e,0x436442,0x438454,0x43a448,0x03503a,0x43c466,0x43e03d,0x44a440, + 0x44c472,0x46044e,0x45a450,0x45e470,0x46a476,0x46c478,0x47c46e}; + +/* ********************************************************************************************* */ +/* Table: HuffTree25 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 9). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree25[168] = {0x400001,0x002003,0x41a402,0x004007,0x41c005,0x035006,0x434404,0x008010, + 0x00900c,0x04a00a,0x42000b,0x44e406,0x03600d,0x03800e,0x05a00f,0x408468, + 0x01101a,0x012016,0x039013,0x070014,0x46e015,0x40a440,0x03b017,0x01804d, + 0x01904f,0x4b840c,0x01b022,0x01c041,0x03f01d,0x01e020,0x01f05b,0x40e4ee, + 0x02107c,0x45c410,0x02302c,0x024028,0x053025,0x026045,0x02707d,0x412522, + 0x047029,0x05e02a,0x02b08a,0x526414,0x05602d,0x02e081,0x02f032,0x06e030, + 0x031080,0x416544,0x079033,0x034091,0x41852c,0x43641e,0x04b037,0x42246a, + 0x43c424,0x04c03a,0x426456,0x03c066,0x03d03e,0x482428,0x45842a,0x040072, + 0x42c4ba,0x050042,0x04305c,0x044074,0x42e4be,0x06a046,0x4dc430,0x075048, + 0x0490a3,0x44a432,0x450438,0x43a452,0x48443e,0x04e068,0x45a442,0x4d4444, + 0x051088,0x052087,0x44648c,0x077054,0x4da055,0x50a448,0x057060,0x06b058, + 0x05906d,0x44c4f6,0x46c454,0x45e474,0x06905d,0x460520,0x05f07e,0x462494, + 0x061063,0x07f062,0x464496,0x06408b,0x08d065,0x542466,0x067071,0x4d2470, + 0x4724ec,0x478476,0x53a47a,0x09b06c,0x47c4ac,0x4f847e,0x06f078,0x510480, + 0x48649e,0x4884a0,0x07307b,0x49c48a,0x4a648e,0x098076,0x4904c0,0x4924ea, + 0x4c8498,0x07a08e,0x51249a,0x4a24d6,0x5064a4,0x4f24a8,0x4aa4de,0x51e4ae, + 0x4b0538,0x082092,0x083085,0x08f084,0x5464b2,0x096086,0x4ce4b4,0x4d04b6, + 0x089090,0x4bc508,0x4c253e,0x08c0a4,0x5284c4,0x4e04c6,0x4ca4fa,0x5144cc, + 0x4f04d8,0x4e24fc,0x09309c,0x094099,0x095097,0x4e4516,0x4e652e,0x4e84fe, + 0x4f450c,0x09a09f,0x500502,0x50450e,0x09d0a0,0x09e0a5,0x518530,0x51a54a, + 0x0a70a1,0x0a20a6,0x51c534,0x53c524,0x54052a,0x548532,0x536550,0x54c54e}; + +/* ********************************************************************************************* */ +/* Table: HuffTree26 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 10). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree26[168] = {0x006001,0x002013,0x00300f,0x00400d,0x03b005,0x40046e,0x037007,0x00800a, + 0x009067,0x402420,0x05600b,0x00c057,0x434404,0x06600e,0x406470,0x03c010, + 0x059011,0x06f012,0x49e408,0x014019,0x03f015,0x016044,0x017042,0x079018, + 0x4b840a,0x01a01f,0x01b047,0x07c01c,0x08701d,0x06901e,0x44640c,0x020027, + 0x04b021,0x02204f,0x023025,0x02406b,0x40e4e0,0x081026,0x528410,0x02802c, + 0x06c029,0x08f02a,0x02b078,0x53a412,0x05202d,0x02e033,0x02f031,0x0300a2, + 0x4144ce,0x0a6032,0x416534,0x09a034,0x09f035,0x0360a7,0x54e418,0x03a038, + 0x436039,0x43841a,0x41c41e,0x42246a,0x05803d,0x03e068,0x424484,0x04005b, + 0x04107a,0x42645a,0x043093,0x4d2428,0x05e045,0x046072,0x42a45e,0x048060, + 0x073049,0x04a098,0x42c4c4,0x07504c,0x09504d,0x04e09c,0x51042e,0x063050, + 0x077051,0x43053c,0x053084,0x065054,0x4e4055,0x4fe432,0x43a454,0x43c46c, + 0x43e486,0x07005a,0x4a0440,0x07105c,0x05d07b,0x45c442,0x05f08a,0x476444, + 0x07f061,0x06206a,0x448506,0x06408e,0x52644a,0x54444c,0x45644e,0x452450, + 0x488458,0x4604ec,0x4624f6,0x50e464,0x08206d,0x0a406e,0x542466,0x4a2468, + 0x48a472,0x474089,0x4d8478,0x097074,0x47a508,0x08d076,0x47c4b6,0x51247e, + 0x4804fc,0x4bc482,0x48c4a4,0x48e4d4,0x07d07e,0x4904da,0x49208b,0x094080, + 0x49450c,0x4964e2,0x09d083,0x52a498,0x085091,0x0a5086,0x4cc49a,0x08808c, + 0x4ee49c,0x4a64ba,0x4a84c0,0x4c24aa,0x4ac4f0,0x4ae4d0,0x4ca4b0,0x0900a1, + 0x4b24ea,0x092099,0x4b4516,0x4d64be,0x4c650a,0x522096,0x4c8524,0x4dc4f2, + 0x4de4f4,0x4e6548,0x09e09b,0x5384e8,0x5204f8,0x4fa53e,0x50051a,0x0a30a0, + 0x502536,0x514504,0x51e518,0x54a51c,0x54052c,0x52e546,0x530532,0x54c550}; + +/* ********************************************************************************************* */ +/* Table: HuffTree27 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the decode tree for spectral data (Codebook 11). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * 2) */ +/* --------------------------------------------------------------------------------------------- */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- */ +const UINT aHuffTree27[288] = {0x00100d,0x002006,0x003004,0x400424,0x047005,0x402446,0x048007,0x00800a, + 0x00904c,0x44a404,0x07400b,0x00c0bb,0x466406,0x00e014,0x00f054,0x04e010, + 0x051011,0x0a9012,0x0130bc,0x408464,0x01501f,0x01601a,0x017059,0x0af018, + 0x0ca019,0x40a0e4,0x01b05e,0x01c084,0x0bf01d,0x05d01e,0x55a40c,0x020026, + 0x021066,0x043022,0x023062,0x02408d,0x025108,0x40e480,0x027030,0x02802c, + 0x02906b,0x02a0da,0x06502b,0x4105c8,0x0a402d,0x0ec02e,0x0dd02f,0x532412, + 0x06e031,0x032036,0x03303e,0x0fd034,0x0fc035,0x4145b0,0x03703a,0x038117, + 0x10d039,0x5ba416,0x10f03b,0x03c041,0x5fa03d,0x41c418,0x10403f,0x04011d, + 0x41a5f4,0x11c042,0x41e61c,0x087044,0x0f5045,0x0d9046,0x4204a2,0x640422, + 0x04904a,0x426448,0x04b073,0x428468,0x46c04d,0x48a42a,0x04f077,0x076050, + 0x42c4b0,0x0520a7,0x096053,0x42e4a8,0x05507d,0x07a056,0x0d4057,0x0df058, + 0x442430,0x05a081,0x05b09b,0x05c0e2,0x5b8432,0x4fe434,0x05f09e,0x0e6060, + 0x0610d6,0x57c436,0x0cc063,0x112064,0x4384a0,0x43a5ca,0x067089,0x0680b7, + 0x0690a2,0x0a106a,0x43c59c,0x09206c,0x06d0ba,0x60643e,0x0d106f,0x0700ee, + 0x0de071,0x10b072,0x44056c,0x46a444,0x075094,0x48c44c,0x44e490,0x095078, + 0x0ab079,0x4504ce,0x07b097,0x11e07c,0x630452,0x0ac07e,0x07f099,0x080106, + 0x4544b8,0x0820b1,0x0830e5,0x4fc456,0x0b3085,0x08609d,0x45853e,0x0880c2, + 0x5c045a,0x08a08f,0x08b0ce,0x08c0f7,0x58645c,0x11108e,0x45e5c4,0x0c4090, + 0x10a091,0x4604e4,0x0d0093,0x462608,0x48e46e,0x4704b2,0x4d2472,0x0980bd, + 0x4f2474,0x0e309a,0x4764aa,0x0be09c,0x47851a,0x47a4de,0x09f0b5,0x0a00c1, + 0x50047c,0x57847e,0x0a30c3,0x504482,0x0e90a5,0x0a6100,0x4c8484,0x0a811f, + 0x48662a,0x0c70aa,0x488494,0x4924d0,0x0ad0c8,0x0ae0d8,0x496636,0x10e0b0, + 0x4f8498,0x0f30b2,0x49a4dc,0x0f20b4,0x53c49c,0x0b60cb,0x49e57a,0x0b80e0, + 0x0b9109,0x5e44a4,0x5484a6,0x4ac4ae,0x4b44ca,0x4d64b6,0x4ba5da,0x0c60c0, + 0x4bc51e,0x4be556,0x6204c0,0x4c24c4,0x0f80c5,0x5664c6,0x4cc53a,0x4d462c, + 0x0f10c9,0x4d8552,0x4da4fa,0x5be4e0,0x0cd0ff,0x5244e2,0x0cf0e8,0x4e6568, + 0x59a4e8,0x0f90d2,0x1010d3,0x5ac4ea,0x0d50d7,0x4ec634,0x4ee560,0x4f44f0, + 0x4f6638,0x502522,0x0db0dc,0x5065a6,0x508604,0x60050a,0x50c0fb,0x63250e, + 0x1130e1,0x5a4510,0x5125fc,0x516514,0x51863e,0x51c536,0x0e70f4,0x55c520, + 0x602526,0x0eb0ea,0x5cc528,0x5ea52a,0x1140ed,0x60c52c,0x1020ef,0x0f0119, + 0x58e52e,0x530622,0x558534,0x53861e,0x55e540,0x5800f6,0x57e542,0x5445e6, + 0x5465e8,0x0fa115,0x54c54a,0x54e60e,0x5ae550,0x1160fe,0x5f0554,0x564562, + 0x56a58a,0x56e5ee,0x10310c,0x5705d0,0x107105,0x5725d4,0x57463a,0x5765b4, + 0x5825bc,0x5845e2,0x5885de,0x58c592,0x5ce590,0x5945f6,0x63c596,0x11b110, + 0x5d8598,0x5c259e,0x5e05a0,0x5a25c6,0x5a860a,0x5aa5ec,0x5b2610,0x11a118, + 0x6185b6,0x5f25d2,0x5d6616,0x5dc5f8,0x61a5fe,0x612614,0x62e624,0x626628}; + +/* get starting addresses of huffman tables into an array [convert codebook into starting address] */ + /* cb tree */ +const UINT *aHuffTable[MAX_CB] = {aHuffTree41, /* 0 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 1 1 */ + aHuffTree42, /* 2 2 */ + aHuffTree43, /* 3 3 */ + aHuffTree44, /* 4 4 */ + aHuffTree21, /* 5 5 */ + aHuffTree22, /* 6 6 */ + aHuffTree23, /* 7 7 */ + aHuffTree24, /* 8 8 */ + aHuffTree25, /* 9 9 */ + aHuffTree26, /* 10 10 */ + aHuffTree27, /* 11 11 */ + aHuffTree41, /* 12 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 13 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 14 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 15 - */ /* use tree 1 as dummy here */ + aHuffTree27, /* 16 11 */ + aHuffTree27, /* 17 11 */ + aHuffTree27, /* 18 11 */ + aHuffTree27, /* 19 11 */ + aHuffTree27, /* 20 11 */ + aHuffTree27, /* 21 11 */ + aHuffTree27, /* 22 11 */ + aHuffTree27, /* 23 11 */ + aHuffTree27, /* 24 11 */ + aHuffTree27, /* 25 11 */ + aHuffTree27, /* 26 11 */ + aHuffTree27, /* 27 11 */ + aHuffTree27, /* 28 11 */ + aHuffTree27, /* 29 11 */ + aHuffTree27, /* 30 11 */ + aHuffTree27}; /* 31 11 */ + +/*--------------------------------------------------------------------------------------------- + data-description: + The following tables contain the quantized values. Two or four of the quantized values are + indexed by the result of the decoding in the decoding tree (see tables above). + -------------------------------------------------------------------------------------------- */ + +/* ********************************************************************************************* */ +/* Table: ValTab41 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 1-2. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab41[324]={-1,-1,-1,-1,-1,-1,-1,0,-1,-1,-1,1,-1,-1,0,-1, + -1,-1,0,0,-1,-1,0,1,-1,-1,1,-1,-1,-1,1,0, + -1,-1,1,1,-1,0,-1,-1,-1,0,-1,0,-1,0,-1,1, + -1,0,0,-1,-1,0,0,0,-1,0,0,1,-1,0,1,-1, + -1,0,1,0,-1,0,1,1,-1,1,-1,-1,-1,1,-1,0, + -1,1,-1,1,-1,1,0,-1,-1,1,0,0,-1,1,0,1, + -1,1,1,-1,-1,1,1,0,-1,1,1,1,0,-1,-1,-1, + 0,-1,-1,0,0,-1,-1,1,0,-1,0,-1,0,-1,0,0, + 0,-1,0,1,0,-1,1,-1,0,-1,1,0,0,-1,1,1, + 0,0,-1,-1,0,0,-1,0,0,0,-1,1,0,0,0,-1, + 0,0,0,0,0,0,0,1,0,0,1,-1,0,0,1,0, + 0,0,1,1,0,1,-1,-1,0,1,-1,0,0,1,-1,1, + 0,1,0,-1,0,1,0,0,0,1,0,1,0,1,1,-1, + 0,1,1,0,0,1,1,1,1,-1,-1,-1,1,-1,-1,0, + 1,-1,-1,1,1,-1,0,-1,1,-1,0,0,1,-1,0,1, + 1,-1,1,-1,1,-1,1,0,1,-1,1,1,1,0,-1,-1, + 1,0,-1,0,1,0,-1,1,1,0,0,-1,1,0,0,0, + 1,0,0,1,1,0,1,-1,1,0,1,0,1,0,1,1, + 1,1,-1,-1,1,1,-1,0,1,1,-1,1,1,1,0,-1, + 1,1,0,0,1,1,0,1,1,1,1,-1,1,1,1,0, + 1,1,1,1}; + +/* ********************************************************************************************* */ +/* Table: ValTab42 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 3-4. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab42[324]={0,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, + 0,0,1,1,0,0,1,2,0,0,2,0,0,0,2,1, + 0,0,2,2,0,1,0,0,0,1,0,1,0,1,0,2, + 0,1,1,0,0,1,1,1,0,1,1,2,0,1,2,0, + 0,1,2,1,0,1,2,2,0,2,0,0,0,2,0,1, + 0,2,0,2,0,2,1,0,0,2,1,1,0,2,1,2, + 0,2,2,0,0,2,2,1,0,2,2,2,1,0,0,0, + 1,0,0,1,1,0,0,2,1,0,1,0,1,0,1,1, + 1,0,1,2,1,0,2,0,1,0,2,1,1,0,2,2, + 1,1,0,0,1,1,0,1,1,1,0,2,1,1,1,0, + 1,1,1,1,1,1,1,2,1,1,2,0,1,1,2,1, + 1,1,2,2,1,2,0,0,1,2,0,1,1,2,0,2, + 1,2,1,0,1,2,1,1,1,2,1,2,1,2,2,0, + 1,2,2,1,1,2,2,2,2,0,0,0,2,0,0,1, + 2,0,0,2,2,0,1,0,2,0,1,1,2,0,1,2, + 2,0,2,0,2,0,2,1,2,0,2,2,2,1,0,0, + 2,1,0,1,2,1,0,2,2,1,1,0,2,1,1,1, + 2,1,1,2,2,1,2,0,2,1,2,1,2,1,2,2, + 2,2,0,0,2,2,0,1,2,2,0,2,2,2,1,0, + 2,2,1,1,2,2,1,2,2,2,2,0,2,2,2,1, + 2,2,2,2}; + +/* ********************************************************************************************* */ +/* Table: ValTab21 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 5-6. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab21[162]={-4,-4,-4,-3,-4,-2,-4,-1,-4,0,-4,1,-4,2,-4,3, + -4,4,-3,-4,-3,-3,-3,-2,-3,-1,-3,0,-3,1,-3,2, + -3,3,-3,4,-2,-4,-2,-3,-2,-2,-2,-1,-2,0,-2,1, + -2,2,-2,3,-2,4,-1,-4,-1,-3,-1,-2,-1,-1,-1,0, + -1,1,-1,2,-1,3,-1,4,0,-4,0,-3,0,-2,0,-1, + 0,0,0,1,0,2,0,3,0,4,1,-4,1,-3,1,-2, + 1,-1,1,0,1,1,1,2,1,3,1,4,2,-4,2,-3, + 2,-2,2,-1,2,0,2,1,2,2,2,3,2,4,3,-4, + 3,-3,3,-2,3,-1,3,0,3,1,3,2,3,3,3,4, + 4,-4,4,-3,4,-2,4,-1,4,0,4,1,4,2,4,3, + 4,4}; + +/* ********************************************************************************************* */ +/* Table: ValTab22 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 7-8. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab22[128]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7, + 1,0,1,1,1,2,1,3,1,4,1,5,1,6,1,7, + 2,0,2,1,2,2,2,3,2,4,2,5,2,6,2,7, + 3,0,3,1,3,2,3,3,3,4,3,5,3,6,3,7, + 4,0,4,1,4,2,4,3,4,4,4,5,4,6,4,7, + 5,0,5,1,5,2,5,3,5,4,5,5,5,6,5,7, + 6,0,6,1,6,2,6,3,6,4,6,5,6,6,6,7, + 7,0,7,1,7,2,7,3,7,4,7,5,7,6,7,7}; + +/* ********************************************************************************************* */ +/* Table: ValTab23 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 9-10. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab23[338]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7, + 0,8,0,9,0,10,0,11,0,12,1,0,1,1,1,2, + 1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10, + 1,11,1,12,2,0,2,1,2,2,2,3,2,4,2,5, + 2,6,2,7,2,8,2,9,2,10,2,11,2,12,3,0, + 3,1,3,2,3,3,3,4,3,5,3,6,3,7,3,8, + 3,9,3,10,3,11,3,12,4,0,4,1,4,2,4,3, + 4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11, + 4,12,5,0,5,1,5,2,5,3,5,4,5,5,5,6, + 5,7,5,8,5,9,5,10,5,11,5,12,6,0,6,1, + 6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9, + 6,10,6,11,6,12,7,0,7,1,7,2,7,3,7,4, + 7,5,7,6,7,7,7,8,7,9,7,10,7,11,7,12, + 8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7, + 8,8,8,9,8,10,8,11,8,12,9,0,9,1,9,2, + 9,3,9,4,9,5,9,6,9,7,9,8,9,9,9,10, + 9,11,9,12,10,0,10,1,10,2,10,3,10,4,10,5, + 10,6,10,7,10,8,10,9,10,10,10,11,10,12,11,0, + 11,1,11,2,11,3,11,4,11,5,11,6,11,7,11,8, + 11,9,11,10,11,11,11,12,12,0,12,1,12,2,12,3, + 12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11, + 12,12}; + +/* ********************************************************************************************* */ +/* Table: ValTab24 */ +/* --------------------------------------------------------------------------------------------- */ +/* description: This table contains the quantized values for codebooks 11. */ +/* --------------------------------------------------------------------------------------------- */ +const SCHAR aValTab24[578]={0,0,0,1,0,2,0,3,0,4,0,5,0,6,0,7, + 0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15, + 0,16,1,0,1,1,1,2,1,3,1,4,1,5,1,6, + 1,7,1,8,1,9,1,10,1,11,1,12,1,13,1,14, + 1,15,1,16,2,0,2,1,2,2,2,3,2,4,2,5, + 2,6,2,7,2,8,2,9,2,10,2,11,2,12,2,13, + 2,14,2,15,2,16,3,0,3,1,3,2,3,3,3,4, + 3,5,3,6,3,7,3,8,3,9,3,10,3,11,3,12, + 3,13,3,14,3,15,3,16,4,0,4,1,4,2,4,3, + 4,4,4,5,4,6,4,7,4,8,4,9,4,10,4,11, + 4,12,4,13,4,14,4,15,4,16,5,0,5,1,5,2, + 5,3,5,4,5,5,5,6,5,7,5,8,5,9,5,10, + 5,11,5,12,5,13,5,14,5,15,5,16,6,0,6,1, + 6,2,6,3,6,4,6,5,6,6,6,7,6,8,6,9, + 6,10,6,11,6,12,6,13,6,14,6,15,6,16,7,0, + 7,1,7,2,7,3,7,4,7,5,7,6,7,7,7,8, + 7,9,7,10,7,11,7,12,7,13,7,14,7,15,7,16, + 8,0,8,1,8,2,8,3,8,4,8,5,8,6,8,7, + 8,8,8,9,8,10,8,11,8,12,8,13,8,14,8,15, + 8,16,9,0,9,1,9,2,9,3,9,4,9,5,9,6, + 9,7,9,8,9,9,9,10,9,11,9,12,9,13,9,14, + 9,15,9,16,10,0,10,1,10,2,10,3,10,4,10,5, + 10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13, + 10,14,10,15,10,16,11,0,11,1,11,2,11,3,11,4, + 11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12, + 11,13,11,14,11,15,11,16,12,0,12,1,12,2,12,3, + 12,4,12,5,12,6,12,7,12,8,12,9,12,10,12,11, + 12,12,12,13,12,14,12,15,12,16,13,0,13,1,13,2, + 13,3,13,4,13,5,13,6,13,7,13,8,13,9,13,10, + 13,11,13,12,13,13,13,14,13,15,13,16,14,0,14,1, + 14,2,14,3,14,4,14,5,14,6,14,7,14,8,14,9, + 14,10,14,11,14,12,14,13,14,14,14,15,14,16,15,0, + 15,1,15,2,15,3,15,4,15,5,15,6,15,7,15,8, + 15,9,15,10,15,11,15,12,15,13,15,14,15,15,15,16, + 16,0,16,1,16,2,16,3,16,4,16,5,16,6,16,7, + 16,8,16,9,16,10,16,11,16,12,16,13,16,14,16,15, + 16,16}; + + /* cb quant. val table */ +const SCHAR *aQuantTable[] = {aValTab41, /* 0 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 1 1 */ + aValTab41, /* 2 1 */ + aValTab42, /* 3 2 */ + aValTab42, /* 4 2 */ + aValTab21, /* 5 3 */ + aValTab21, /* 6 3 */ + aValTab22, /* 7 4 */ + aValTab22, /* 8 4 */ + aValTab23, /* 9 5 */ + aValTab23, /* 10 5 */ + aValTab24, /* 11 6 */ + aValTab41, /* 12 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 13 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 14 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 15 - */ /* use quant. val talble 1 as dummy here */ + aValTab24, /* 16 6 */ + aValTab24, /* 17 6 */ + aValTab24, /* 18 6 */ + aValTab24, /* 19 6 */ + aValTab24, /* 20 6 */ + aValTab24, /* 21 6 */ + aValTab24, /* 22 6 */ + aValTab24, /* 23 6 */ + aValTab24, /* 24 6 */ + aValTab24, /* 25 6 */ + aValTab24, /* 26 6 */ + aValTab24, /* 27 6 */ + aValTab24, /* 28 6 */ + aValTab24, /* 29 6 */ + aValTab24, /* 30 6 */ + aValTab24}; /* 31 6 */ + +/* arrays for HCR_TABLE_INFO structures */ +/* maximum length of codeword in each codebook */ +/* codebook: 0,1, 2,3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 */ +const UCHAR aMaxCwLen[MAX_CB]={0,11,9,20,16,13,11,14,12,17,14,49,0, 0, 0, 0, 14,17,21,21,25,25,29,29,29,29,33,33,33,37,37,41}; + +/* 11 13 15 17 19 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */ +const UCHAR aDimCb[MAX_CB] = {2,4,4,4,4,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}; /* codebook dimension - zero cb got a dimension of 2 */ + +/* 11 13 15 17 19 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */ +const UCHAR aDimCbShift[MAX_CB]={1,2,2,2,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; /* codebook dimension */ + +/* 1 -> decode sign bits */ +/* 0 -> decode no sign bits 11 13 15 17 19 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */ +const UCHAR aSignCb[MAX_CB]={0,0,0,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + +/* arrays for HCR_CB_PAIRS structures */ +const UCHAR aMinOfCbPair[MAX_CB_PAIRS]={0,1,3,5,7, 9,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,11}; +const UCHAR aMaxOfCbPair[MAX_CB_PAIRS]={0,2,4,6,8,10,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,11}; + +/* priorities of codebooks */ +const UCHAR aCbPriority[MAX_CB]={0,1,1,2,2,3,3,4,4,5,5,22,0,0,0,0,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21}; + +const SCHAR aCodebook2StartInt[] = {STOP_THIS_STATE , /* cb 0 */ + BODY_ONLY , /* cb 1 */ + BODY_ONLY , /* cb 2 */ + BODY_SIGN__BODY , /* cb 3 */ + BODY_SIGN__BODY , /* cb 4 */ + BODY_ONLY , /* cb 5 */ + BODY_ONLY , /* cb 6 */ + BODY_SIGN__BODY , /* cb 7 */ + BODY_SIGN__BODY , /* cb 8 */ + BODY_SIGN__BODY , /* cb 9 */ + BODY_SIGN__BODY , /* cb 10 */ + BODY_SIGN_ESC__BODY, /* cb 11 */ + STOP_THIS_STATE , /* cb 12 */ + STOP_THIS_STATE , /* cb 13 */ + STOP_THIS_STATE , /* cb 14 */ + STOP_THIS_STATE , /* cb 15 */ + BODY_SIGN_ESC__BODY, /* cb 16 */ + BODY_SIGN_ESC__BODY, /* cb 17 */ + BODY_SIGN_ESC__BODY, /* cb 18 */ + BODY_SIGN_ESC__BODY, /* cb 19 */ + BODY_SIGN_ESC__BODY, /* cb 20 */ + BODY_SIGN_ESC__BODY, /* cb 21 */ + BODY_SIGN_ESC__BODY, /* cb 22 */ + BODY_SIGN_ESC__BODY, /* cb 23 */ + BODY_SIGN_ESC__BODY, /* cb 24 */ + BODY_SIGN_ESC__BODY, /* cb 25 */ + BODY_SIGN_ESC__BODY, /* cb 26 */ + BODY_SIGN_ESC__BODY, /* cb 27 */ + BODY_SIGN_ESC__BODY, /* cb 28 */ + BODY_SIGN_ESC__BODY, /* cb 29 */ + BODY_SIGN_ESC__BODY, /* cb 30 */ + BODY_SIGN_ESC__BODY}; /* cb 31 */ + +const STATEFUNC aStateConstant2State[] = {NULL , /* 0 = STOP_THIS_STATE */ + Hcr_State_BODY_ONLY , /* 1 = BODY_ONLY */ + Hcr_State_BODY_SIGN__BODY , /* 2 = BODY_SIGN__BODY */ + Hcr_State_BODY_SIGN__SIGN , /* 3 = BODY_SIGN__SIGN */ + Hcr_State_BODY_SIGN_ESC__BODY , /* 4 = BODY_SIGN_ESC__BODY */ + Hcr_State_BODY_SIGN_ESC__SIGN , /* 5 = BODY_SIGN_ESC__SIGN */ + Hcr_State_BODY_SIGN_ESC__ESC_PREFIX, /* 6 = BODY_SIGN_ESC__ESC_PREFIX */ + Hcr_State_BODY_SIGN_ESC__ESC_WORD }; /* 7 = BODY_SIGN_ESC__ESC_WORD */ + +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 */ +const USHORT aLargestAbsoluteValue[MAX_CB]={0,1,1,2,2,4,4,7,7,12,12,8191, 0, 0, 0, 0,15,31,47,63,95,127,159,191,223,255,319,383,511,767,1023,2047}; /* lav */ +/* CB: 11 13 15 17 19 21 23 25 27 39 31 */ + + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlcEscape' contains the decode tree for the rvlc + escape sequences. + bit 23 and 11 not used + bit 22 and 10 determine end value --> if set codeword is decoded + bit 21-12 and 9-0 (offset to next node) or (index value) + The escape sequence is the index value. + + input: codeword + output: index +------------------------------------------------------------------------------------------ */ +const UINT aHuffTreeRvlcEscape[53] = { 0x002001,0x400003,0x401004,0x402005,0x403007,0x404006,0x00a405,0x009008, + 0x00b406,0x00c407,0x00d408,0x00e409,0x40b40a,0x40c00f,0x40d010,0x40e011, + 0x40f012,0x410013,0x411014,0x412015,0x016413,0x414415,0x017416,0x417018, + 0x419019,0x01a418,0x01b41a,0x01c023,0x03201d,0x01e020,0x43501f,0x41b41c, + 0x021022,0x41d41e,0x41f420,0x02402b,0x025028,0x026027,0x421422,0x423424, + 0x02902a,0x425426,0x427428,0x02c02f,0x02d02e,0x42942a,0x42b42c,0x030031, + 0x42d42e,0x42f430,0x033034,0x431432,0x433434 }; + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlc' contains the huffman decoding tree for the RVLC + scale factors. The table contains 15 allowed, symmetric codewords and 8 + forbidden codewords, which are used for error detection. + + usage of bits: bit 23 and 11 not used + bit 22 and 10 determine end value --> if set codeword is decoded + bit 21-12 and 9-0 (offset to next node within the table) or (index+7). + The decoded (index+7) is in the range from 0,1,..,22. If the (index+7) + is in the range 15,16,..,22, then a forbidden codeword is decoded. + + input: A single bit from a RVLC scalefactor codeword + output: [if codeword is not completely decoded:] offset to next node within table or + [if codeword is decoded:] A dpcm value i.e. (index+7) in range from 0,1,..,22. + The differential scalefactor (DPCM value) named 'index' is calculated by + subtracting 7 from the decoded value (index+7). +------------------------------------------------------------------------------------------ */ +const UINT aHuffTreeRvlCodewds[22] = { 0x407001,0x002009,0x003406,0x004405,0x005404,0x006403,0x007400,0x008402, + 0x411401,0x00a408,0x00c00b,0x00e409,0x01000d,0x40f40a,0x41400f,0x01340b, + 0x011015,0x410012,0x41240c,0x416014,0x41540d,0x41340e }; + + + +const FIXP_WTB LowDelaySynthesis512[1536] = { +/* part 0 */ +WTC(0xdac984c0), WTC(0xdb100080), WTC(0xdb56cd00), WTC(0xdb9dec40), WTC(0xdbe55fc0), WTC(0xdc2d2880), WTC(0xdc754780), WTC(0xdcbdbd80), +WTC(0xdd068a80), WTC(0xdd4fae80), WTC(0xdd992940), WTC(0xdde2f9c0), WTC(0xde2d1fc0), WTC(0xde779a80), WTC(0xdec26a00), WTC(0xdf0d8e00), +WTC(0xdf590680), WTC(0xdfa4d540), WTC(0xdff0fc80), WTC(0xe03d7e20), WTC(0xe08a5900), WTC(0xe0d78a20), WTC(0xe1250cc0), WTC(0xe172dcc0), +WTC(0xe1c0f7a0), WTC(0xe20f59a0), WTC(0xe25dfea0), WTC(0xe2ace400), WTC(0xe2fc0be0), WTC(0xe34b7bc0), WTC(0xe39b3c80), WTC(0xe3eb5260), +WTC(0xe43bbac0), WTC(0xe48c7160), WTC(0xe4dd7140), WTC(0xe52eb600), WTC(0xe5803c00), WTC(0xe5d1fda0), WTC(0xe623f360), WTC(0xe6761700), +WTC(0xe6c86400), WTC(0xe71ad500), WTC(0xe76d63e0), WTC(0xe7c00ba0), WTC(0xe812c8e0), WTC(0xe86598e0), WTC(0xe8b878e0), WTC(0xe90b68a0), +WTC(0xe95e6c40), WTC(0xe9b18ae0), WTC(0xea04ce80), WTC(0xea583ba0), WTC(0xeaabcda0), WTC(0xeaff7ee0), WTC(0xeb5348e0), WTC(0xeba722c0), +WTC(0xebfb0060), WTC(0xec4ed240), WTC(0xeca28540), WTC(0xecf60c20), WTC(0xed496120), WTC(0xed9c7e80), WTC(0xedef5e40), WTC(0xee41fc00), +WTC(0xee945600), WTC(0xeee66ac0), WTC(0xef3839a0), WTC(0xef89c0e0), WTC(0xefdafda0), WTC(0xf02bed60), WTC(0xf07c8e80), WTC(0xf0cce000), +WTC(0xf11ce220), WTC(0xf16c9620), WTC(0xf1bbfe30), WTC(0xf20b19e0), WTC(0xf259e5a0), WTC(0xf2a85dc0), WTC(0xf2f67ed0), WTC(0xf34445b0), +WTC(0xf391aed0), WTC(0xf3deb590), WTC(0xf42b53e0), WTC(0xf4778140), WTC(0xf4c33190), WTC(0xf50e5660), WTC(0xf558df30), WTC(0xf5a2be50), +WTC(0xf5ebea10), WTC(0xf6345780), WTC(0xf67bfab0), WTC(0xf6c2cee0), WTC(0xf708d7b0), WTC(0xf74e19c0), WTC(0xf7929a70), WTC(0xf7d66630), +WTC(0xf8199268), WTC(0xf85c3860), WTC(0xf89e7480), WTC(0xf8e058c0), WTC(0xf921ec08), WTC(0xf9633800), WTC(0xf9a44980), WTC(0xf9e53158), +WTC(0xfa260158), WTC(0xfa66ca18), WTC(0xfaa79ac0), WTC(0xfae87920), WTC(0xfb295fa0), WTC(0xfb6a42b8), WTC(0xfbab1240), WTC(0xfbebd1c0), +WTC(0xfc2c9c24), WTC(0xfc6d8d90), WTC(0xfcaec240), WTC(0xfcf05684), WTC(0xfd326a98), WTC(0xfd75254c), WTC(0xfdb8afd4), WTC(0xfdfccdfc), +WTC(0xfe40d694), WTC(0xfe84161c), WTC(0xfec5cf5a), WTC(0xff04e7fc), WTC(0xff3fdfe3), WTC(0xff751ddf), WTC(0xffa2fb0f), WTC(0xffc87c42), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0xbffb6081), WTC(0xbff22f81), WTC(0xbfe8fc01), WTC(0xbfdfc781), WTC(0xbfd69101), WTC(0xbfcd5a01), WTC(0xbfc42201), WTC(0xbfbae981), +WTC(0xbfb1b101), WTC(0xbfa87901), WTC(0xbf9f4181), WTC(0xbf960b01), WTC(0xbf8cd481), WTC(0xbf839d81), WTC(0xbf7a6681), WTC(0xbf712f01), +WTC(0xbf67f801), WTC(0xbf5ec101), WTC(0xbf558b01), WTC(0xbf4c5681), WTC(0xbf432281), WTC(0xbf39ee81), WTC(0xbf30bb01), WTC(0xbf278801), +WTC(0xbf1e5501), WTC(0xbf152381), WTC(0xbf0bf381), WTC(0xbf02c581), WTC(0xbef99901), WTC(0xbef06d01), WTC(0xbee74281), WTC(0xbede1901), +WTC(0xbed4f081), WTC(0xbecbca81), WTC(0xbec2a781), WTC(0xbeb98681), WTC(0xbeb06881), WTC(0xbea74c81), WTC(0xbe9e3281), WTC(0xbe951a81), +WTC(0xbe8c0501), WTC(0xbe82f301), WTC(0xbe79e481), WTC(0xbe70da01), WTC(0xbe67d381), WTC(0xbe5ed081), WTC(0xbe55d001), WTC(0xbe4cd381), +WTC(0xbe43da81), WTC(0xbe3ae601), WTC(0xbe31f701), WTC(0xbe290d01), WTC(0xbe202801), WTC(0xbe174781), WTC(0xbe0e6c01), WTC(0xbe059481), +WTC(0xbdfcc301), WTC(0xbdf3f701), WTC(0xbdeb3101), WTC(0xbde27201), WTC(0xbdd9b981), WTC(0xbdd10681), WTC(0xbdc85981), WTC(0xbdbfb281), +WTC(0xbdb71201), WTC(0xbdae7881), WTC(0xbda5e601), WTC(0xbd9d5b81), WTC(0xbd94d801), WTC(0xbd8c5c01), WTC(0xbd83e681), WTC(0xbd7b7781), +WTC(0xbd731081), WTC(0xbd6ab101), WTC(0xbd625981), WTC(0xbd5a0b01), WTC(0xbd51c481), WTC(0xbd498601), WTC(0xbd414f01), WTC(0xbd391f81), +WTC(0xbd30f881), WTC(0xbd28d981), WTC(0xbd20c401), WTC(0xbd18b781), WTC(0xbd10b381), WTC(0xbd08b781), WTC(0xbd00c381), WTC(0xbcf8d781), +WTC(0xbcf0f381), WTC(0xbce91801), WTC(0xbce14601), WTC(0xbcd97c81), WTC(0xbcd1bb81), WTC(0xbcca0301), WTC(0xbcc25181), WTC(0xbcbaa801), +WTC(0xbcb30601), WTC(0xbcab6c01), WTC(0xbca3db01), WTC(0xbc9c5281), WTC(0xbc94d201), WTC(0xbc8d5901), WTC(0xbc85e801), WTC(0xbc7e7e01), +WTC(0xbc771c01), WTC(0xbc6fc101), WTC(0xbc686e01), WTC(0xbc612301), WTC(0xbc59df81), WTC(0xbc52a381), WTC(0xbc4b6e81), WTC(0xbc444081), +WTC(0xbc3d1801), WTC(0xbc35f501), WTC(0xbc2ed681), WTC(0xbc27bd81), WTC(0xbc20ae01), WTC(0xbc19ab01), WTC(0xbc12b801), WTC(0xbc0bcf81), +WTC(0xbc04e381), WTC(0xbbfde481), WTC(0xbbf6c601), WTC(0xbbef9b81), WTC(0xbbe89901), WTC(0xbbe1f401), WTC(0xbbdbe201), WTC(0xbbd68c81), +WTC(0xbbd21281), WTC(0xbbce9181), WTC(0xbbcc2681), WTC(0xbbcaca01), WTC(0xbbca5081), WTC(0xbbca8d01), WTC(0xbbcb5301), WTC(0xbbcc8201), +WTC(0xbbce0601), WTC(0xbbcfca81), WTC(0xbbd1bd81), WTC(0xbbd3e101), WTC(0xbbd64d01), WTC(0xbbd91b81), WTC(0xbbdc6481), WTC(0xbbe03801), +WTC(0xbbe49d01), WTC(0xbbe99981), WTC(0xbbef3301), WTC(0xbbf56181), WTC(0xbbfc0f81), WTC(0xbc032601), WTC(0xbc0a8f01), WTC(0xbc123b81), +WTC(0xbc1a2401), WTC(0xbc224181), WTC(0xbc2a8c81), WTC(0xbc330781), WTC(0xbc3bbc01), WTC(0xbc44b481), WTC(0xbc4dfb81), WTC(0xbc57a301), +WTC(0xbc61c401), WTC(0xbc6c7781), WTC(0xbc77d601), WTC(0xbc83f201), WTC(0xbc90d481), WTC(0xbc9e8801), WTC(0xbcad1501), WTC(0xbcbc7e01), +WTC(0xbcccbd01), WTC(0xbcddcc81), WTC(0xbcefa601), WTC(0xbd023f01), WTC(0xbd158801), WTC(0xbd297181), WTC(0xbd3deb81), WTC(0xbd52eb01), +WTC(0xbd686681), WTC(0xbd7e5581), WTC(0xbd94b001), WTC(0xbdab7181), WTC(0xbdc29a81), WTC(0xbdda2a01), WTC(0xbdf22181), WTC(0xbe0a8581), +WTC(0xbe236001), WTC(0xbe3cbc01), WTC(0xbe56a381), WTC(0xbe712001), WTC(0xbe8c3781), WTC(0xbea7f301), WTC(0xbec45881), WTC(0xbee17201), +WTC(0xbeff4801), WTC(0xbf1de601), WTC(0xbf3d5501), WTC(0xbf5d9a81), WTC(0xbf7eb581), WTC(0xbfa0a581), WTC(0xbfc36a01), WTC(0xbfe6ed01), +WTC(0xc00b04c0), WTC(0xc02f86c0), WTC(0xc0544940), WTC(0xc0792ec0), WTC(0xc09e2640), WTC(0xc0c31f00), WTC(0xc0e80a00), WTC(0xc10cf480), +WTC(0xc1320940), WTC(0xc15773c0), WTC(0xc17d5f00), WTC(0xc1a3e340), WTC(0xc1cb05c0), WTC(0xc1f2cbc0), WTC(0xc21b3940), WTC(0xc2444b00), +WTC(0xc26df5c0), WTC(0xc2982d80), WTC(0xc2c2e640), WTC(0xc2ee0a00), WTC(0xc3197940), WTC(0xc34513c0), WTC(0xc370b9c0), WTC(0xc39c4f00), +WTC(0xc3c7bc00), WTC(0xc3f2e940), WTC(0xc41dc140), WTC(0xc44856c0), WTC(0xc472e640), WTC(0xc49dad80), WTC(0xc4c8e880), WTC(0xc4f4acc0), +WTC(0xc520e840), WTC(0xc54d8780), WTC(0xc57a76c0), WTC(0xc5a79640), WTC(0xc5d4bac0), WTC(0xc601b880), WTC(0xc62e6580), WTC(0xc65ab600), +WTC(0xc686bd40), WTC(0xc6b28fc0), WTC(0xc6de41c0), WTC(0xc709de40), WTC(0xc7356640), WTC(0xc760da80), WTC(0xc78c3c40), WTC(0xc7b78640), +WTC(0xc7e2afc0), WTC(0xc80dae80), WTC(0xc83878c0), WTC(0xc86304c0), WTC(0xc88d4900), WTC(0xc8b73b80), WTC(0xc8e0d280), WTC(0xc90a0440), +/* part 1 */ +WTC(0xb5212e81), WTC(0xb4959501), WTC(0xb40ab501), WTC(0xb3808d81), WTC(0xb2f71f01), WTC(0xb26e6881), WTC(0xb1e66a01), WTC(0xb15f2381), +WTC(0xb0d89401), WTC(0xb052bc01), WTC(0xafcd9a81), WTC(0xaf492f01), WTC(0xaec57801), WTC(0xae427481), WTC(0xadc02281), WTC(0xad3e8101), +WTC(0xacbd9081), WTC(0xac3d5001), WTC(0xabbdc001), WTC(0xab3edf01), WTC(0xaac0ad01), WTC(0xaa432981), WTC(0xa9c65401), WTC(0xa94a2c01), +WTC(0xa8ceb201), WTC(0xa853e501), WTC(0xa7d9c681), WTC(0xa7605601), WTC(0xa6e79401), WTC(0xa66f8201), WTC(0xa5f81f81), WTC(0xa5816e81), +WTC(0xa50b6e81), WTC(0xa4962181), WTC(0xa4218801), WTC(0xa3ada281), WTC(0xa33a7201), WTC(0xa2c7f801), WTC(0xa2563501), WTC(0xa1e52a81), +WTC(0xa174da81), WTC(0xa1054701), WTC(0xa0967201), WTC(0xa0285d81), WTC(0x9fbb0981), WTC(0x9f4e7801), WTC(0x9ee2a901), WTC(0x9e779f81), +WTC(0x9e0d5e01), WTC(0x9da3e601), WTC(0x9d3b3b81), WTC(0x9cd35f81), WTC(0x9c6c5481), WTC(0x9c061b81), WTC(0x9ba0b701), WTC(0x9b3c2801), +WTC(0x9ad87081), WTC(0x9a759301), WTC(0x9a139101), WTC(0x99b26c81), WTC(0x99522801), WTC(0x98f2c601), WTC(0x98944901), WTC(0x9836b201), +WTC(0x97da0481), WTC(0x977e4181), WTC(0x97236b01), WTC(0x96c98381), WTC(0x96708b81), WTC(0x96188501), WTC(0x95c17081), WTC(0x956b4f81), +WTC(0x95162381), WTC(0x94c1ee01), WTC(0x946eaf81), WTC(0x941c6901), WTC(0x93cb1c81), WTC(0x937acb01), WTC(0x932b7501), WTC(0x92dd1b01), +WTC(0x928fbe01), WTC(0x92435d01), WTC(0x91f7f981), WTC(0x91ad9281), WTC(0x91642781), WTC(0x911bb981), WTC(0x90d44781), WTC(0x908dd101), +WTC(0x90485401), WTC(0x9003ce81), WTC(0x8fc03f01), WTC(0x8f7da401), WTC(0x8f3bfb01), WTC(0x8efb4181), WTC(0x8ebb7581), WTC(0x8e7c9301), +WTC(0x8e3e9481), WTC(0x8e017581), WTC(0x8dc53001), WTC(0x8d89be81), WTC(0x8d4f1b01), WTC(0x8d154081), WTC(0x8cdc2901), WTC(0x8ca3cb01), +WTC(0x8c6c1b01), WTC(0x8c350d01), WTC(0x8bfe9401), WTC(0x8bc8a401), WTC(0x8b933001), WTC(0x8b5e2c81), WTC(0x8b298b81), WTC(0x8af53e81), +WTC(0x8ac13381), WTC(0x8a8d5801), WTC(0x8a599a81), WTC(0x8a25f301), WTC(0x89f26101), WTC(0x89bee581), WTC(0x898b8301), WTC(0x89586901), +WTC(0x8925f101), WTC(0x88f47901), WTC(0x88c45e81), WTC(0x88962981), WTC(0x886a8a81), WTC(0x88423301), WTC(0x881dd301), WTC(0x87fdd781), +WTC(0x87d0ca81), WTC(0x87c76201), WTC(0x87bcab81), WTC(0x87b0ef01), WTC(0x87a48b01), WTC(0x8797dd81), WTC(0x878b4301), WTC(0x877ede01), +WTC(0x87729701), WTC(0x87665481), WTC(0x8759fd01), WTC(0x874d8681), WTC(0x8740f681), WTC(0x87345381), WTC(0x8727a381), WTC(0x871ae981), +WTC(0x870e2301), WTC(0x87014f81), WTC(0x86f46d81), WTC(0x86e77b81), WTC(0x86da7901), WTC(0x86cd6681), WTC(0x86c04381), WTC(0x86b30f01), +WTC(0x86a5ca81), WTC(0x86987581), WTC(0x868b1001), WTC(0x867d9a81), WTC(0x86701381), WTC(0x86627b01), WTC(0x8654d001), WTC(0x86471281), +WTC(0x86394301), WTC(0x862b6201), WTC(0x861d7081), WTC(0x860f6e01), WTC(0x86015981), WTC(0x85f33281), WTC(0x85e4f801), WTC(0x85d6a981), +WTC(0x85c84801), WTC(0x85b9d481), WTC(0x85ab4f01), WTC(0x859cb781), WTC(0x858e0e01), WTC(0x857f5101), WTC(0x85707f81), WTC(0x85619a01), +WTC(0x8552a181), WTC(0x85439601), WTC(0x85347901), WTC(0x85254a81), WTC(0x85160981), WTC(0x8506b581), WTC(0x84f74e01), WTC(0x84e7d381), +WTC(0x84d84601), WTC(0x84c8a701), WTC(0x84b8f801), WTC(0x84a93801), WTC(0x84996701), WTC(0x84898481), WTC(0x84798f81), WTC(0x84698881), +WTC(0x84597081), WTC(0x84494881), WTC(0x84391081), WTC(0x8428ca01), WTC(0x84187401), WTC(0x84080d81), WTC(0x83f79681), WTC(0x83e70f01), +WTC(0x83d67881), WTC(0x83c5d381), WTC(0x83b52101), WTC(0x83a46181), WTC(0x83939501), WTC(0x8382ba01), WTC(0x8371d081), WTC(0x8360d901), +WTC(0x834fd481), WTC(0x833ec381), WTC(0x832da781), WTC(0x831c8101), WTC(0x830b4f81), WTC(0x82fa1181), WTC(0x82e8c801), WTC(0x82d77201), +WTC(0x82c61101), WTC(0x82b4a601), WTC(0x82a33281), WTC(0x8291b601), WTC(0x82803101), WTC(0x826ea201), WTC(0x825d0901), WTC(0x824b6601), +WTC(0x8239b981), WTC(0x82280581), WTC(0x82164a81), WTC(0x82048881), WTC(0x81f2bf81), WTC(0x81e0ee81), WTC(0x81cf1581), WTC(0x81bd3401), +WTC(0x81ab4b01), WTC(0x81995c01), WTC(0x81876781), WTC(0x81756d81), WTC(0x81636d81), WTC(0x81516701), WTC(0x813f5981), WTC(0x812d4481), +WTC(0x811b2981), WTC(0x81090981), WTC(0x80f6e481), WTC(0x80e4bb81), WTC(0x80d28d81), WTC(0x80c05a01), WTC(0x80ae1f81), WTC(0x809bdf01), +WTC(0x80899881), WTC(0x80774c81), WTC(0x8064fc81), WTC(0x8052a881), WTC(0x80405101), WTC(0x802df701), WTC(0x801b9b01), WTC(0x80093e01), +WTC(0x0a74b120), WTC(0x0aa08a90), WTC(0x0acd2b80), WTC(0x0afa8860), WTC(0x0b289590), WTC(0x0b574790), WTC(0x0b8692d0), WTC(0x0bb66bb0), +WTC(0x0be6c6b0), WTC(0x0c179830), WTC(0x0c48d500), WTC(0x0c7a7ad0), WTC(0x0cac9000), WTC(0x0cdf1b60), WTC(0x0d122390), WTC(0x0d45a8f0), +WTC(0x0d79a5e0), WTC(0x0dae1480), WTC(0x0de2ef30), WTC(0x0e183800), WTC(0x0e4df8c0), WTC(0x0e843b90), WTC(0x0ebb0a20), WTC(0x0ef26430), +WTC(0x0f2a3fc0), WTC(0x0f629280), WTC(0x0f9b5210), WTC(0x0fd47690), WTC(0x100dfa80), WTC(0x1047d8a0), WTC(0x10820b40), WTC(0x10bc8b80), +WTC(0x10f75080), WTC(0x11325100), WTC(0x116d84e0), WTC(0x11a8ece0), WTC(0x11e49420), WTC(0x122085a0), WTC(0x125ccbc0), WTC(0x12995a40), +WTC(0x12d60e80), WTC(0x1312c4c0), WTC(0x134f59e0), WTC(0x138bae60), WTC(0x13c7a740), WTC(0x140329e0), WTC(0x143e1b60), WTC(0x147862a0), +WTC(0x14b1e840), WTC(0x14ea94c0), WTC(0x152250a0), WTC(0x15590380), WTC(0x158e93e0), WTC(0x15c2e820), WTC(0x15f5e6e0), WTC(0x162779a0), +WTC(0x16578ca0), WTC(0x16860ca0), WTC(0x16b2e640), WTC(0x16de0b00), WTC(0x17077140), WTC(0x172f0fa0), WTC(0x1754e200), WTC(0x17796080), +WTC(0x179d7f20), WTC(0x17c23760), WTC(0x17e87da0), WTC(0x1810cc80), WTC(0x183b25a0), WTC(0x18678520), WTC(0x1895e700), WTC(0x18c64540), +WTC(0x18f89780), WTC(0x192cd560), WTC(0x1962f680), WTC(0x199af2a0), WTC(0x19d4c1e0), WTC(0x1a105ca0), WTC(0x1a4dbae0), WTC(0x1a8cd660), +WTC(0x1acdaa60), WTC(0x1b103260), WTC(0x1b546940), WTC(0x1b9a4600), WTC(0x1be1bb80), WTC(0x1c2abc60), WTC(0x1c753b80), WTC(0x1cc13860), +WTC(0x1d0ebe20), WTC(0x1d5dd8c0), WTC(0x1dae9480), WTC(0x1e010060), WTC(0x1e552f40), WTC(0x1eab33e0), WTC(0x1f032060), WTC(0x1f5cfce0), +WTC(0x1fb8c660), WTC(0x201679c0), WTC(0x207611c0), WTC(0x20d75f00), WTC(0x213a0640), WTC(0x219dab80), WTC(0x2201f480), WTC(0x2266ba80), +WTC(0x22cc0ac0), WTC(0x2331f4c0), WTC(0x23988940), WTC(0x23ffff40), WTC(0x2468b340), WTC(0x24d30300), WTC(0x253f4900), WTC(0x25ad8980), +WTC(0x261d72c0), WTC(0x268eaec0), WTC(0x2700e880), WTC(0x2773db40), WTC(0x27e751c0), WTC(0x285b1780), WTC(0x28cefbc0), WTC(0x29431f80), +WTC(0x29b7f680), WTC(0x2a2df780), WTC(0x2aa59880), WTC(0x2b1f3280), WTC(0x2b9b0140), WTC(0x2c194000), WTC(0x2c9a2540), WTC(0x2d1d8dc0), +WTC(0x2da2fc40), WTC(0x2e29ee80), WTC(0x2eb1e340), WTC(0x2f3a4e40), WTC(0x2fc29980), WTC(0x304a2ec0), WTC(0x30d07cc0), WTC(0x315566c0), +WTC(0x31d94480), WTC(0x325c72c0), WTC(0x32df51c0), WTC(0x33628c80), WTC(0x33e71a00), WTC(0x346df400), WTC(0x34f80dc0), WTC(0x3585c640), +WTC(0x3616e700), WTC(0x36ab3380), WTC(0x37426ac0), WTC(0x37dbe840), WTC(0x3876a340), WTC(0x39118f40), WTC(0x39aba2c0), WTC(0x3a4422c0), +WTC(0x3adaa200), WTC(0x3b6eb6c0), WTC(0x3bfffd80), WTC(0x3c8e9380), WTC(0x3d1b1780), WTC(0x3da62e00), WTC(0x3e307b00), WTC(0x3eba97c0), +WTC(0x3f451280), WTC(0x3fd07940), WTC(0x405d577f), WTC(0x40ebf57f), WTC(0x417c59ff), WTC(0x420e897f), WTC(0x42a2857f), WTC(0x4338307f), +WTC(0x43cf4d7f), WTC(0x44679cff), WTC(0x4500dfff), WTC(0x459ac2ff), WTC(0x4634e2ff), WTC(0x46ced9ff), WTC(0x4768437f), WTC(0x4800d27f), +WTC(0x489850ff), WTC(0x492e88ff), WTC(0x49c346ff), WTC(0x4a5678ff), WTC(0x4ae82f7f), WTC(0x4b787c7f), WTC(0x4c07717f), WTC(0x4c95337f), +WTC(0x4d21f77f), WTC(0x4dadf3ff), WTC(0x4e395eff), WTC(0x4ec4657f), WTC(0x4f4f297f), WTC(0x4fd9cd7f), WTC(0x5064737f), WTC(0x50ef3cff), +WTC(0x517a46ff), WTC(0x5205b0ff), WTC(0x529197ff), WTC(0x531e04ff), WTC(0x53aaeb7f), WTC(0x54383eff), WTC(0x54c5ef7f), WTC(0x5553a8ff), +WTC(0x55e0d57f), WTC(0x566cda7f), WTC(0x56f720ff), WTC(0x577f4aff), WTC(0x580534ff), WTC(0x5888bd7f), WTC(0x5909c6ff), WTC(0x598890ff), +WTC(0x5a05b7ff), WTC(0x5a81db7f), WTC(0x5afd99ff), WTC(0x5b794a7f), WTC(0x5bf5007f), WTC(0x5c70cbff), WTC(0x5cecbb7f), WTC(0x5d68c47f), +WTC(0x5de4c3ff), WTC(0x5e6094ff), WTC(0x5edc127f), WTC(0x5f56fdff), WTC(0x5fd1017f), WTC(0x6049c67f), WTC(0x60c0f67f), WTC(0x613650ff), +WTC(0x61a9a9ff), WTC(0x621ad77f), WTC(0x6289b37f), WTC(0x62f67fff), WTC(0x6361e87f), WTC(0x63cc9bff), WTC(0x6437457f), WTC(0x64a2247f), +WTC(0x650d0c7f), WTC(0x6577cc7f), WTC(0x65e2327f), WTC(0x664bf57f), WTC(0x66b4b5ff), WTC(0x671c137f), WTC(0x6781afff), WTC(0x67e579ff), +WTC(0x6847abff), WTC(0x68a882ff), WTC(0x69083bff), WTC(0x6966fbff), WTC(0x69c4cfff), WTC(0x6a21c57f), WTC(0x6a7de87f), WTC(0x6ad9377f), +WTC(0x6b33a5ff), WTC(0x6b8d257f), WTC(0x6be5a8ff), WTC(0x6c3d20ff), WTC(0x6c9380ff), WTC(0x6ce8ba7f), WTC(0x6d3cbfff), WTC(0x6d8f827f), +/* part 2 */ +WTC(0xad98b481), WTC(0xaead9d01), WTC(0xafbfc381), WTC(0xb0cf4d01), WTC(0xb1dc5f81), WTC(0xb2e72081), WTC(0xb3efb501), WTC(0xb4f64381), +WTC(0xb5faf101), WTC(0xb6fde401), WTC(0xb7ff4001), WTC(0xb8ff1601), WTC(0xb9fd6181), WTC(0xbafa1d01), WTC(0xbbf54401), WTC(0xbceed101), +WTC(0xbde6c081), WTC(0xbedd0e81), WTC(0xbfd1b701), WTC(0xc0c4b440), WTC(0xc1b5ffc0), WTC(0xc2a59340), WTC(0xc3936780), WTC(0xc47f78c0), +WTC(0xc569c600), WTC(0xc6524d40), WTC(0xc7390dc0), WTC(0xc81e04c0), WTC(0xc9012e00), WTC(0xc9e28540), WTC(0xcac20700), WTC(0xcb9fb1c0), +WTC(0xcc7b8640), WTC(0xcd558600), WTC(0xce2db200), WTC(0xcf0409c0), WTC(0xcfd88a40), WTC(0xd0ab3080), WTC(0xd17bfa00), WTC(0xd24ae640), +WTC(0xd317f7c0), WTC(0xd3e33080), WTC(0xd4ac9340), WTC(0xd5741f40), WTC(0xd639d2c0), WTC(0xd6fdab00), WTC(0xd7bfa5c0), WTC(0xd87fc300), +WTC(0xd93e0600), WTC(0xd9fa7180), WTC(0xdab50900), WTC(0xdb6dccc0), WTC(0xdc24ba80), WTC(0xdcd9d000), WTC(0xdd8d0b80), WTC(0xde3e6dc0), +WTC(0xdeedf9c0), WTC(0xdf9bb340), WTC(0xe0479e20), WTC(0xe0f1bac0), WTC(0xe19a07e0), WTC(0xe2408380), WTC(0xe2e52c00), WTC(0xe38802e0), +WTC(0xe4290c00), WTC(0xe4c84c20), WTC(0xe565c760), WTC(0xe6017f20), WTC(0xe69b7240), WTC(0xe7339f60), WTC(0xe7ca0500), WTC(0xe85ea480), +WTC(0xe8f18180), WTC(0xe9829fc0), WTC(0xea1202e0), WTC(0xea9fab80), WTC(0xeb2b9700), WTC(0xebb5c2a0), WTC(0xec3e2bc0), WTC(0xecc4d300), +WTC(0xed49bc80), WTC(0xedccec60), WTC(0xee4e66a0), WTC(0xeece2d80), WTC(0xef4c41e0), WTC(0xefc8a480), WTC(0xf0435610), WTC(0xf0bc5c60), +WTC(0xf133c230), WTC(0xf1a99270), WTC(0xf21dd7b0), WTC(0xf29097e0), WTC(0xf301d3d0), WTC(0xf3718c20), WTC(0xf3dfc180), WTC(0xf44c7100), +WTC(0xf4b79480), WTC(0xf52125b0), WTC(0xf5891df0), WTC(0xf5ef6fe0), WTC(0xf6540730), WTC(0xf6b6cf50), WTC(0xf717b490), WTC(0xf776b9a0), +WTC(0xf7d3f720), WTC(0xf82f86e8), WTC(0xf8898260), WTC(0xf8e1fc50), WTC(0xf93900f0), WTC(0xf98e9c28), WTC(0xf9e2d940), WTC(0xfa35b4a0), +WTC(0xfa871bd8), WTC(0xfad6fbd0), WTC(0xfb254250), WTC(0xfb71f0c0), WTC(0xfbbd1c28), WTC(0xfc06da60), WTC(0xfc4f40a4), WTC(0xfc965500), +WTC(0xfcdc0e5c), WTC(0xfd2062f4), WTC(0xfd6348d0), WTC(0xfda4b1b8), WTC(0xfde48b2c), WTC(0xfe22c280), WTC(0xfe5f462a), WTC(0xfe9a1f2e), +WTC(0xfed3711c), WTC(0xff0b60ac), WTC(0xff4212dd), WTC(0xff77b344), WTC(0xffac7407), WTC(0xffe08796), WTC(0x00141e37), WTC(0x00473665), +WTC(0x00799cd0), WTC(0x00ab1bff), WTC(0x00db7d8b), WTC(0x010a75ea), WTC(0x0137a46e), WTC(0x0162a77a), WTC(0x018b20ac), WTC(0x01b0fb7a), +WTC(0x01d46d3c), WTC(0x01f5ae7c), WTC(0x0214f91c), WTC(0x0232a5cc), WTC(0x024f2c04), WTC(0x026b048c), WTC(0x0286a628), WTC(0x02a25808), +WTC(0x02be31c0), WTC(0x02da48e0), WTC(0x02f6b09c), WTC(0x031345dc), WTC(0x032faf50), WTC(0x034b9148), WTC(0x036690e8), WTC(0x0380658c), +WTC(0x0398d8e4), WTC(0x03afb568), WTC(0x03c4c6e0), WTC(0x03d7f770), WTC(0x03e94f9c), WTC(0x03f8d938), WTC(0x04069ee8), WTC(0x0412bef8), +WTC(0x041d6b30), WTC(0x0426d638), WTC(0x042f3288), WTC(0x0436ad98), WTC(0x043d6fd0), WTC(0x0443a170), WTC(0x04496a40), WTC(0x044ee728), +WTC(0x04542a40), WTC(0x04594520), WTC(0x045e4890), WTC(0x04633210), WTC(0x0467ebe8), WTC(0x046c5f80), WTC(0x04707630), WTC(0x047417f0), +WTC(0x04772b58), WTC(0x047996e8), WTC(0x047b4140), WTC(0x047c12a0), WTC(0x047bf520), WTC(0x047ad2e0), WTC(0x04789690), WTC(0x047539c8), +WTC(0x0470c4b8), WTC(0x046b4058), WTC(0x0464b600), WTC(0x045d3a08), WTC(0x0454ebc8), WTC(0x044beb00), WTC(0x04425798), WTC(0x043853b0), +WTC(0x042e0398), WTC(0x04238bd8), WTC(0x04190f98), WTC(0x040e9670), WTC(0x04040c18), WTC(0x03f95b30), WTC(0x03ee6e20), WTC(0x03e32b64), +WTC(0x03d77598), WTC(0x03cb2f24), WTC(0x03be3b18), WTC(0x03b08b18), WTC(0x03a21f64), WTC(0x0392f8d4), WTC(0x038318e0), WTC(0x03728e94), +WTC(0x03617694), WTC(0x034fee18), WTC(0x033e11f4), WTC(0x032bf530), WTC(0x0319a114), WTC(0x03071e80), WTC(0x02f475f4), WTC(0x02e1a7c0), +WTC(0x02ceac04), WTC(0x02bb7a84), WTC(0x02a80af0), WTC(0x029452b0), WTC(0x028044e0), WTC(0x026bd488), WTC(0x0256f558), WTC(0x0241a940), +WTC(0x022c0084), WTC(0x02160c08), WTC(0x01ffdc5a), WTC(0x01e97ad2), WTC(0x01d2e982), WTC(0x01bc2a2a), WTC(0x01a53e8c), WTC(0x018e2860), +WTC(0x0176e94c), WTC(0x015f82fa), WTC(0x0147f70e), WTC(0x013046c2), WTC(0x011872e8), WTC(0x01007c4a), WTC(0x00e863cf), WTC(0x00d02c81), +WTC(0x00b7db94), WTC(0x009f7651), WTC(0x00870204), WTC(0x006e83f8), WTC(0x00560176), WTC(0x003d7fcb), WTC(0x0025043f), WTC(0x000c941f), +WTC(0xd65574c0), WTC(0xd5ebc100), WTC(0xd582d080), WTC(0xd51a9cc0), WTC(0xd4b31f80), WTC(0xd44c5280), WTC(0xd3e62f80), WTC(0xd380b040), +WTC(0xd31bce40), WTC(0xd2b78380), WTC(0xd253ca40), WTC(0xd1f0acc0), WTC(0xd18e4580), WTC(0xd12caf40), WTC(0xd0cc0400), WTC(0xd06c40c0), +WTC(0xd00d4740), WTC(0xcfaef6c0), WTC(0xcf513140), WTC(0xcef3fa80), WTC(0xce977a40), WTC(0xce3bd980), WTC(0xcde13f40), WTC(0xcd87a880), +WTC(0xcd2ee800), WTC(0xccd6cf00), WTC(0xcc7f2f40), WTC(0xcc27e880), WTC(0xcbd0ea00), WTC(0xcb7a2380), WTC(0xcb238380), WTC(0xcaccee80), +WTC(0xca763ec0), WTC(0xca1f4d00), WTC(0xc9c7f480), WTC(0xc9703b40), WTC(0xc9185200), WTC(0xc8c06b00), WTC(0xc868b4c0), WTC(0xc81100c0), +WTC(0xc7b8c280), WTC(0xc75f6a40), WTC(0xc7046900), WTC(0xc6a74340), WTC(0xc6479300), WTC(0xc5e4f200), WTC(0xc57efac0), WTC(0xc5154880), +WTC(0xc4a77780), WTC(0xc4352440), WTC(0xc3bdeac0), WTC(0xc3416740), WTC(0xc2bf33c0), WTC(0xc236eb40), WTC(0xc1a82900), WTC(0xc11290c0), +WTC(0xc075cf00), WTC(0xbfd19081), WTC(0xbf258401), WTC(0xbe716d81), WTC(0xbdb52b81), WTC(0xbcf09a81), WTC(0xbc23af81), WTC(0xbb505c01), +WTC(0xba7a9081), WTC(0xb9a65281), WTC(0xb8d79301), WTC(0xb8104c01), WTC(0xb7508181), WTC(0xb6982201), WTC(0xb5e71b01), WTC(0xb53d5b01), +WTC(0xb49ad081), WTC(0xb3ff6901), WTC(0xb36b1301), WTC(0xb2ddbd01), WTC(0xb2575481), WTC(0xb1d7c801), WTC(0xb15f0601), WTC(0xb0ecfc01), +WTC(0xb0819881), WTC(0xb01cca01), WTC(0xafbe7e01), WTC(0xaf66a301), WTC(0xaf152701), WTC(0xaec9f881), WTC(0xae850601), WTC(0xae463c81), +WTC(0xae0d8b01), WTC(0xaddae001), WTC(0xadae2881), WTC(0xad875381), WTC(0xad664f81), WTC(0xad4b0981), WTC(0xad357081), WTC(0xad257301), +WTC(0xad1afe01), WTC(0xad160081), WTC(0xad166901), WTC(0xad1c2481), WTC(0xad272201), WTC(0xad374f81), WTC(0xad4c9b01), WTC(0xad66f381), +WTC(0xad864601), WTC(0xadaa8101), WTC(0xadd39301), WTC(0xae016a01), WTC(0xae33f481), WTC(0xae6b2001), WTC(0xaea6db01), WTC(0xaee71381), +WTC(0xaf2bb801), WTC(0xaf74b681), WTC(0xafc1fd01), WTC(0xb0137a01), WTC(0xb0691b81), WTC(0xb0c2cf81), WTC(0xb1208481), WTC(0xb1822881), +WTC(0xb1e7a981), WTC(0xb250f601), WTC(0xb2bdfc01), WTC(0xb32eaa01), WTC(0xb3a2ed01), WTC(0xb41ab481), WTC(0xb495ee01), WTC(0xb5148801), +WTC(0xb5967081), WTC(0xb61b9581), WTC(0xb6a3e581), WTC(0xb72f4e01), WTC(0xb7bdbe01), WTC(0xb84f2381), WTC(0xb8e36c81), WTC(0xb97a8701), +WTC(0xba146101), WTC(0xbab0e981), WTC(0xbb500d81), WTC(0xbbf1bc81), WTC(0xbc95e381), WTC(0xbd3c7181), WTC(0xbde55481), WTC(0xbe907a01), +WTC(0xbf3dd101), WTC(0xbfed4701), WTC(0xc09ecac0), WTC(0xc1524a00), WTC(0xc207b300), WTC(0xc2bef440), WTC(0xc377fb80), WTC(0xc432b700), +WTC(0xc4ef1500), WTC(0xc5ad03c0), WTC(0xc66c7140), WTC(0xc72d4bc0), WTC(0xc7ef8180), WTC(0xc8b30080), WTC(0xc977b700), WTC(0xca3d9340), +WTC(0xcb048340), WTC(0xcbcc7540), WTC(0xcc955740), WTC(0xcd5f17c0), WTC(0xce29a480), WTC(0xcef4ec00), WTC(0xcfc0dc80), WTC(0xd08d63c0), +WTC(0xd15a7040), WTC(0xd227f000), WTC(0xd2f5d140), WTC(0xd3c40240), WTC(0xd4927100), WTC(0xd5610b80), WTC(0xd62fc080), WTC(0xd6fe7dc0), +WTC(0xd7cd3140), WTC(0xd89bc980), WTC(0xd96a34c0), WTC(0xda3860c0), WTC(0xdb063c00), WTC(0xdbd3b480), WTC(0xdca0b880), WTC(0xdd6d3640), +WTC(0xde391bc0), WTC(0xdf045740), WTC(0xdfced6c0), WTC(0xe09888c0), WTC(0xe1615b20), WTC(0xe2293c20), WTC(0xe2f01a00), WTC(0xe3b5e2c0), +WTC(0xe47a84c0), WTC(0xe53dee00), WTC(0xe6000cc0), WTC(0xe6c0cf20), WTC(0xe7802360), WTC(0xe83df7a0), WTC(0xe8fa39e0), WTC(0xe9b4d880), +WTC(0xea6dc1a0), WTC(0xeb24e360), WTC(0xebda2be0), WTC(0xec8d8960), WTC(0xed3eea20), WTC(0xedee3c00), WTC(0xee9b6d80), WTC(0xef466ca0), +WTC(0xefef2780), WTC(0xf0958c50), WTC(0xf1398950), WTC(0xf1db0ca0), WTC(0xf27a0470), WTC(0xf3165ed0), WTC(0xf3b00a10), WTC(0xf446f440), +WTC(0xf4db0b90), WTC(0xf56c3e30), WTC(0xf5fa7a50), WTC(0xf685ae10), WTC(0xf70dc7a0), WTC(0xf792b520), WTC(0xf81464c8), WTC(0xf892c4c0), +WTC(0xf90dc330), WTC(0xf9854e40), WTC(0xf9f95418), WTC(0xfa69c2f0), WTC(0xfad688e8), WTC(0xfb3f9428), WTC(0xfba4d2e8), WTC(0xfc063344), +WTC(0xfc63a370), WTC(0xfcbd1194), WTC(0xfd126bdc), WTC(0xfd63a06c), WTC(0xfdb09d78), WTC(0xfdf95124), WTC(0xfe3da99e), WTC(0xfe7d950e), +WTC(0xfeb901a2), WTC(0xfeefdd80), WTC(0xff2216d7), WTC(0xff4f9bcf), WTC(0xff785a93), WTC(0xff9c414e), WTC(0xffbb3e2b), WTC(0xffd53f54), +WTC(0xffea32f4), WTC(0xfffa0735), WTC(0x0004aa43), WTC(0x000a0a47), WTC(0x000a156c), WTC(0x0004b9de), WTC(0xfff9e5c5), WTC(0xffe9874e) +}; + + +const FIXP_WTB LowDelaySynthesis480[1440] = { + +WTC(0xdad2e6c0), WTC(0xdb1da900), WTC(0xdb68ce40), WTC(0xdbb45840), WTC(0xdc004940), WTC(0xdc4ca280), WTC(0xdc996500), WTC(0xdce69140), +WTC(0xdd342780), WTC(0xdd822700), WTC(0xddd08a80), WTC(0xde1f4d00), WTC(0xde6e6ec0), WTC(0xdebdec40), WTC(0xdf0dba80), WTC(0xdf5dd540), +WTC(0xdfae3cc0), WTC(0xdfff0500), WTC(0xe0505140), WTC(0xe0a22980), WTC(0xe0f488e0), WTC(0xe1476180), WTC(0xe19aa480), WTC(0xe1ee4d80), +WTC(0xe2425400), WTC(0xe29689a0), WTC(0xe2eacd60), WTC(0xe33f2420), WTC(0xe393a300), WTC(0xe3e87f20), WTC(0xe43dcee0), WTC(0xe4938a80), +WTC(0xe4e9b0a0), WTC(0xe5404300), WTC(0xe5973e60), WTC(0xe5ee9b80), WTC(0xe64649e0), WTC(0xe69e37e0), WTC(0xe6f65ec0), WTC(0xe74eb6c0), +WTC(0xe7a73000), WTC(0xe7ffbe40), WTC(0xe8585ee0), WTC(0xe8b10740), WTC(0xe9099c40), WTC(0xe96214e0), WTC(0xe9ba79a0), WTC(0xea12e7c0), +WTC(0xea6b89c0), WTC(0xeac46580), WTC(0xeb1d7260), WTC(0xeb76b620), WTC(0xebd036c0), WTC(0xec29e520), WTC(0xec83aa60), WTC(0xecdd5a00), +WTC(0xed36d500), WTC(0xed901540), WTC(0xede91160), WTC(0xee41bc20), WTC(0xee9a0ee0), WTC(0xeef20860), WTC(0xef49a7e0), WTC(0xefa0ec00), +WTC(0xeff7d1c0), WTC(0xf04e56b0), WTC(0xf0a476e0), WTC(0xf0fa2f60), WTC(0xf14f80e0), WTC(0xf1a46e10), WTC(0xf1f8fe80), WTC(0xf24d34a0), +WTC(0xf2a10bb0), WTC(0xf2f48210), WTC(0xf3479cc0), WTC(0xf39a5be0), WTC(0xf3ecb8f0), WTC(0xf43eafa0), WTC(0xf4903b50), WTC(0xf4e14e80), +WTC(0xf531d6a0), WTC(0xf581bc10), WTC(0xf5d0e9c0), WTC(0xf61f5250), WTC(0xf66ce6e0), WTC(0xf6b99330), WTC(0xf7054eb0), WTC(0xf7501f20), +WTC(0xf79a0750), WTC(0xf7e30700), WTC(0xf82b2fc0), WTC(0xf872a138), WTC(0xf8b97f18), WTC(0xf8ffe668), WTC(0xf945e538), WTC(0xf98b8860), +WTC(0xf9d0f380), WTC(0xfa165148), WTC(0xfa5bb8a8), WTC(0xfaa13df8), WTC(0xfae6fb00), WTC(0xfb2cf8c8), WTC(0xfb732a80), WTC(0xfbb97910), +WTC(0xfbffcd10), WTC(0xfc463478), WTC(0xfc8cd3fc), WTC(0xfcd3be5c), WTC(0xfd1afa90), WTC(0xfd62aa84), WTC(0xfdab0288), WTC(0xfdf404b4), +WTC(0xfe3d3006), WTC(0xfe85b20e), WTC(0xfecca4cc), WTC(0xff10d559), WTC(0xff50579b), WTC(0xff8a40d2), WTC(0xffb7d86e), WTC(0xffef6bbb), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), +WTC(0xbff67a01), WTC(0xbfecaa81), WTC(0xbfe2d901), WTC(0xbfd90601), WTC(0xbfcf3181), WTC(0xbfc55c81), WTC(0xbfbb8701), WTC(0xbfb1b101), +WTC(0xbfa7dc01), WTC(0xbf9e0701), WTC(0xbf943301), WTC(0xbf8a5f81), WTC(0xbf808b81), WTC(0xbf76b701), WTC(0xbf6ce201), WTC(0xbf630d81), +WTC(0xbf593a01), WTC(0xbf4f6801), WTC(0xbf459681), WTC(0xbf3bc601), WTC(0xbf31f501), WTC(0xbf282501), WTC(0xbf1e5501), WTC(0xbf148681), +WTC(0xbf0aba01), WTC(0xbf00ef81), WTC(0xbef72681), WTC(0xbeed5f01), WTC(0xbee39801), WTC(0xbed9d281), WTC(0xbed00f81), WTC(0xbec64e81), +WTC(0xbebc9181), WTC(0xbeb2d681), WTC(0xbea91f01), WTC(0xbe9f6901), WTC(0xbe95b581), WTC(0xbe8c0501), WTC(0xbe825801), WTC(0xbe78b001), +WTC(0xbe6f0c01), WTC(0xbe656c01), WTC(0xbe5bd001), WTC(0xbe523781), WTC(0xbe48a301), WTC(0xbe3f1381), WTC(0xbe358901), WTC(0xbe2c0501), +WTC(0xbe228681), WTC(0xbe190d81), WTC(0xbe0f9a01), WTC(0xbe062b81), WTC(0xbdfcc301), WTC(0xbdf36101), WTC(0xbdea0681), WTC(0xbde0b301), +WTC(0xbdd76701), WTC(0xbdce2181), WTC(0xbdc4e301), WTC(0xbdbbab01), WTC(0xbdb27b01), WTC(0xbda95301), WTC(0xbda03381), WTC(0xbd971c81), +WTC(0xbd8e0e01), WTC(0xbd850701), WTC(0xbd7c0781), WTC(0xbd731081), WTC(0xbd6a2201), WTC(0xbd613d81), WTC(0xbd586281), WTC(0xbd4f9101), +WTC(0xbd46c801), WTC(0xbd3e0801), WTC(0xbd355081), WTC(0xbd2ca281), WTC(0xbd23ff01), WTC(0xbd1b6501), WTC(0xbd12d581), WTC(0xbd0a4f81), +WTC(0xbd01d281), WTC(0xbcf95e81), WTC(0xbcf0f381), WTC(0xbce89281), WTC(0xbce03b81), WTC(0xbcd7ef01), WTC(0xbccfac01), WTC(0xbcc77181), +WTC(0xbcbf4001), WTC(0xbcb71701), WTC(0xbcaef701), WTC(0xbca6e101), WTC(0xbc9ed481), WTC(0xbc96d101), WTC(0xbc8ed701), WTC(0xbc86e581), +WTC(0xbc7efc81), WTC(0xbc771c01), WTC(0xbc6f4401), WTC(0xbc677501), WTC(0xbc5fae81), WTC(0xbc57f101), WTC(0xbc503b81), WTC(0xbc488e81), +WTC(0xbc40e881), WTC(0xbc394901), WTC(0xbc31af01), WTC(0xbc2a1a81), WTC(0xbc228f01), WTC(0xbc1b1081), WTC(0xbc13a481), WTC(0xbc0c4581), +WTC(0xbc04e381), WTC(0xbbfd6c01), WTC(0xbbf5d181), WTC(0xbbee2f81), WTC(0xbbe6c801), WTC(0xbbdfdb81), WTC(0xbbd9a781), WTC(0xbbd45881), +WTC(0xbbd01301), WTC(0xbbccfc81), WTC(0xbbcb2281), WTC(0xbbca5d01), WTC(0xbbca7481), WTC(0xbbcb3201), WTC(0xbbcc6b01), WTC(0xbbce0601), +WTC(0xbbcfea81), WTC(0xbbd20301), WTC(0xbbd45601), WTC(0xbbd70201), WTC(0xbbda2501), WTC(0xbbdddb01), WTC(0xbbe23281), WTC(0xbbe73201), +WTC(0xbbece281), WTC(0xbbf34281), WTC(0xbbfa3c01), WTC(0xbc01b381), WTC(0xbc098d81), WTC(0xbc11b681), WTC(0xbc1a2401), WTC(0xbc22cd81), +WTC(0xbc2bab01), WTC(0xbc34c081), WTC(0xbc3e1981), WTC(0xbc47c281), WTC(0xbc51cb01), WTC(0xbc5c4c81), WTC(0xbc676501), WTC(0xbc733401), +WTC(0xbc7fd301), WTC(0xbc8d5101), WTC(0xbc9bb901), WTC(0xbcab1781), WTC(0xbcbb7001), WTC(0xbcccbd01), WTC(0xbcdef701), WTC(0xbcf21601), +WTC(0xbd060c81), WTC(0xbd1ac801), WTC(0xbd303581), WTC(0xbd464281), WTC(0xbd5ce281), WTC(0xbd740b81), WTC(0xbd8bb281), WTC(0xbda3d081), +WTC(0xbdbc6381), WTC(0xbdd56b81), WTC(0xbdeee981), WTC(0xbe08e181), WTC(0xbe236001), WTC(0xbe3e7201), WTC(0xbe5a2301), WTC(0xbe767e81), +WTC(0xbe938c81), WTC(0xbeb15701), WTC(0xbecfe601), WTC(0xbeef4601), WTC(0xbf0f8301), WTC(0xbf30a901), WTC(0xbf52c101), WTC(0xbf75cc81), +WTC(0xbf99cb01), WTC(0xbfbebb81), WTC(0xbfe48981), WTC(0xc00b04c0), WTC(0xc031f880), WTC(0xc0593340), WTC(0xc0809280), WTC(0xc0a802c0), +WTC(0xc0cf6ec0), WTC(0xc0f6cc00), WTC(0xc11e3a80), WTC(0xc145f040), WTC(0xc16e22c0), WTC(0xc196fb00), WTC(0xc1c08680), WTC(0xc1eaca00), +WTC(0xc215cbc0), WTC(0xc2418940), WTC(0xc26df5c0), WTC(0xc29b02c0), WTC(0xc2c8a140), WTC(0xc2f6b500), WTC(0xc3251740), WTC(0xc353a0c0), +WTC(0xc3822c00), WTC(0xc3b09940), WTC(0xc3deccc0), WTC(0xc40ca800), WTC(0xc43a28c0), WTC(0xc4678a00), WTC(0xc4951780), WTC(0xc4c31d00), +WTC(0xc4f1bdc0), WTC(0xc520e840), WTC(0xc5508440), WTC(0xc5807900), WTC(0xc5b09e80), WTC(0xc5e0bfc0), WTC(0xc610a740), WTC(0xc64029c0), +WTC(0xc66f49c0), WTC(0xc69e2180), WTC(0xc6ccca40), WTC(0xc6fb5700), WTC(0xc729cc80), WTC(0xc7582b40), WTC(0xc7867480), WTC(0xc7b4a480), +WTC(0xc7e2afc0), WTC(0xc8108a80), WTC(0xc83e28c0), WTC(0xc86b7f00), WTC(0xc8988100), WTC(0xc8c52340), WTC(0xc8f15980), WTC(0xc91d1840), +WTC(0xb4d6a381), WTC(0xb4422b81), WTC(0xb3ae8601), WTC(0xb31bb301), WTC(0xb289b181), WTC(0xb1f88181), WTC(0xb1682281), WTC(0xb0d89401), +WTC(0xb049d601), WTC(0xafbbe801), WTC(0xaf2ec901), WTC(0xaea27681), WTC(0xae16f001), WTC(0xad8c3301), WTC(0xad023f01), WTC(0xac791401), +WTC(0xabf0b181), WTC(0xab691681), WTC(0xaae24301), WTC(0xaa5c3601), WTC(0xa9d6ef01), WTC(0xa9526d81), WTC(0xa8ceb201), WTC(0xa84bbb81), +WTC(0xa7c98b01), WTC(0xa7482101), WTC(0xa6c77e01), WTC(0xa647a301), WTC(0xa5c89001), WTC(0xa54a4701), WTC(0xa4ccc901), WTC(0xa4501601), +WTC(0xa3d43001), WTC(0xa3591801), WTC(0xa2dece81), WTC(0xa2655581), WTC(0xa1ecae01), WTC(0xa174da81), WTC(0xa0fddd81), WTC(0xa087b981), +WTC(0xa0127081), WTC(0x9f9e0301), WTC(0x9f2a7281), WTC(0x9eb7c101), WTC(0x9e45f081), WTC(0x9dd50481), WTC(0x9d650081), WTC(0x9cf5e701), +WTC(0x9c87ba81), WTC(0x9c1a7c81), WTC(0x9bae2f81), WTC(0x9b42d581), WTC(0x9ad87081), WTC(0x9a6f0381), WTC(0x9a069001), WTC(0x999f1981), +WTC(0x9938a281), WTC(0x98d32d81), WTC(0x986ebd81), WTC(0x980b5501), WTC(0x97a8f681), WTC(0x9747a481), WTC(0x96e76101), WTC(0x96882e01), +WTC(0x962a0c81), WTC(0x95ccff01), WTC(0x95710601), WTC(0x95162381), WTC(0x94bc5981), WTC(0x9463a881), WTC(0x940c1281), WTC(0x93b59901), +WTC(0x93603d01), WTC(0x930bff81), WTC(0x92b8e101), WTC(0x9266e281), WTC(0x92160301), WTC(0x91c64301), WTC(0x9177a301), WTC(0x912a2201), +WTC(0x90ddc001), WTC(0x90927b81), WTC(0x90485401), WTC(0x8fff4601), WTC(0x8fb74f81), WTC(0x8f706f01), WTC(0x8f2aa101), WTC(0x8ee5e301), +WTC(0x8ea23201), WTC(0x8e5f8881), WTC(0x8e1de001), WTC(0x8ddd3201), WTC(0x8d9d7781), WTC(0x8d5eaa01), WTC(0x8d20c301), WTC(0x8ce3ba81), +WTC(0x8ca78781), WTC(0x8c6c1b01), WTC(0x8c316681), WTC(0x8bf75b01), WTC(0x8bbde981), WTC(0x8b850281), WTC(0x8b4c9701), WTC(0x8b149701), +WTC(0x8adcee01), WTC(0x8aa58681), WTC(0x8a6e4a01), WTC(0x8a372881), WTC(0x8a001f01), WTC(0x89c92f81), WTC(0x89925a81), WTC(0x895bcd01), +WTC(0x8925f101), WTC(0x88f13801), WTC(0x88be1681), WTC(0x888d3181), WTC(0x885f8481), WTC(0x88353501), WTC(0x88124281), WTC(0x87e73d81), +WTC(0x87d4ac81), WTC(0x87cb5101), WTC(0x87c05e81), WTC(0x87b42481), WTC(0x87a70e81), WTC(0x87998f01), WTC(0x878c1881), WTC(0x877ede01), +WTC(0x8771c601), WTC(0x8764b101), WTC(0x87578181), WTC(0x874a2f01), WTC(0x873cc201), WTC(0x872f4201), WTC(0x8721b481), WTC(0x87141b01), +WTC(0x87067281), WTC(0x86f8ba81), WTC(0x86eaf081), WTC(0x86dd1481), WTC(0x86cf2601), WTC(0x86c12401), WTC(0x86b30f01), WTC(0x86a4e781), +WTC(0x8696ad01), WTC(0x86886001), WTC(0x867a0081), WTC(0x866b8d81), WTC(0x865d0581), WTC(0x864e6901), WTC(0x863fb701), WTC(0x8630f181), +WTC(0x86221801), WTC(0x86132c01), WTC(0x86042c01), WTC(0x85f51681), WTC(0x85e5eb81), WTC(0x85d6a981), WTC(0x85c75201), WTC(0x85b7e601), +WTC(0x85a86581), WTC(0x8598d081), WTC(0x85892681), WTC(0x85796601), WTC(0x85698e81), WTC(0x8559a081), WTC(0x85499d01), WTC(0x85398481), +WTC(0x85295881), WTC(0x85191801), WTC(0x8508c181), WTC(0x84f85581), WTC(0x84e7d381), WTC(0x84d73c01), WTC(0x84c69101), WTC(0x84b5d301), +WTC(0x84a50201), WTC(0x84941d81), WTC(0x84832481), WTC(0x84721701), WTC(0x8460f581), WTC(0x844fc081), WTC(0x843e7a81), WTC(0x842d2281), +WTC(0x841bb981), WTC(0x840a3e81), WTC(0x83f8b001), WTC(0x83e70f01), WTC(0x83d55d01), WTC(0x83c39a81), WTC(0x83b1c881), WTC(0x839fe801), +WTC(0x838df801), WTC(0x837bf801), WTC(0x8369e781), WTC(0x8357c701), WTC(0x83459881), WTC(0x83335c81), WTC(0x83211501), WTC(0x830ec081), +WTC(0x82fc5f01), WTC(0x82e9ef01), WTC(0x82d77201), WTC(0x82c4e801), WTC(0x82b25301), WTC(0x829fb401), WTC(0x828d0b01), WTC(0x827a5801), +WTC(0x82679901), WTC(0x8254cf01), WTC(0x8241fa01), WTC(0x822f1b01), WTC(0x821c3401), WTC(0x82094581), WTC(0x81f64f01), WTC(0x81e34f81), +WTC(0x81d04681), WTC(0x81bd3401), WTC(0x81aa1981), WTC(0x8196f781), WTC(0x8183cf81), WTC(0x8170a181), WTC(0x815d6c01), WTC(0x814a2f81), +WTC(0x8136ea01), WTC(0x81239d81), WTC(0x81104a01), WTC(0x80fcf181), WTC(0x80e99401), WTC(0x80d63101), WTC(0x80c2c781), WTC(0x80af5701), +WTC(0x809bdf01), WTC(0x80886081), WTC(0x8074dc01), WTC(0x80615281), WTC(0x804dc481), WTC(0x803a3381), WTC(0x80269f81), WTC(0x80130981), +WTC(0x0a608220), WTC(0x0a8ee7d0), WTC(0x0abe35c0), WTC(0x0aee5de0), WTC(0x0b1f5230), WTC(0x0b5104a0), WTC(0x0b836720), WTC(0x0bb66bb0), +WTC(0x0bea0440), WTC(0x0c1e22c0), WTC(0x0c52ba70), WTC(0x0c87ca90), WTC(0x0cbd5ba0), WTC(0x0cf375e0), WTC(0x0d2a1f50), WTC(0x0d615480), +WTC(0x0d990e40), WTC(0x0dd14500), WTC(0x0e09f730), WTC(0x0e432e90), WTC(0x0e7cf790), WTC(0x0eb75e50), WTC(0x0ef26430), WTC(0x0f2dfd70), +WTC(0x0f6a1d70), WTC(0x0fa6b7e0), WTC(0x0fe3c3d0), WTC(0x10213ac0), WTC(0x105f1640), WTC(0x109d4f20), WTC(0x10dbdb80), WTC(0x111ab0c0), +WTC(0x1159c360), WTC(0x11990fc0), WTC(0x11d8a060), WTC(0x121882c0), WTC(0x1258c480), WTC(0x12995a40), WTC(0x12da1b00), WTC(0x131adb60), +WTC(0x135b70c0), WTC(0x139bb680), WTC(0x13db8c00), WTC(0x141ad080), WTC(0x14596460), WTC(0x149729e0), WTC(0x14d404e0), WTC(0x150fd8e0), +WTC(0x154a88c0), WTC(0x1583f5e0), WTC(0x15bc0120), WTC(0x15f28ba0), WTC(0x162779a0), WTC(0x165ab300), WTC(0x168c2040), WTC(0x16bbaa80), +WTC(0x16e94120), WTC(0x1714d9e0), WTC(0x173e6440), WTC(0x17660680), WTC(0x178ca020), WTC(0x17b36400), WTC(0x17db84e0), WTC(0x1805d920), +WTC(0x18328400), WTC(0x18617cc0), WTC(0x1892bfa0), WTC(0x18c64540), WTC(0x18fc0400), WTC(0x1933f140), WTC(0x196e0320), WTC(0x19aa2fc0), +WTC(0x19e86d80), WTC(0x1a28b2e0), WTC(0x1a6af700), WTC(0x1aaf3320), WTC(0x1af56180), WTC(0x1b3d7ce0), WTC(0x1b877c40), WTC(0x1bd350c0), +WTC(0x1c20ea40), WTC(0x1c703840), WTC(0x1cc13860), WTC(0x1d13f760), WTC(0x1d688420), WTC(0x1dbeed40), WTC(0x1e174660), WTC(0x1e71a640), +WTC(0x1ece2400), WTC(0x1f2cd220), WTC(0x1f8db3c0), WTC(0x1ff0c3e0), WTC(0x20560080), WTC(0x20bd46c0), WTC(0x21263400), WTC(0x21905740), +WTC(0x21fb4100), WTC(0x2266ba80), WTC(0x22d2d140), WTC(0x233f9780), WTC(0x23ad25c0), WTC(0x241bc800), WTC(0x248bf040), WTC(0x24fe1380), +WTC(0x25728180), WTC(0x25e90a00), WTC(0x26614080), WTC(0x26dabdc0), WTC(0x27552540), WTC(0x27d03200), WTC(0x284ba580), WTC(0x28c740c0), +WTC(0x29431f80), WTC(0x29bfc9c0), WTC(0x2a3dd080), WTC(0x2abdc000), WTC(0x2b3ffd00), WTC(0x2bc4cd80), WTC(0x2c4c7d40), WTC(0x2cd72ec0), +WTC(0x2d647f80), WTC(0x2df3cd80), WTC(0x2e847d80), WTC(0x2f15ea40), WTC(0x2fa760c0), WTC(0x30382b80), WTC(0x30c79440), WTC(0x315566c0), +WTC(0x31e20800), WTC(0x326de7c0), WTC(0x32f98200), WTC(0x3385ba00), WTC(0x3413bec0), WTC(0x34a4c480), WTC(0x3539bf00), WTC(0x35d2c4c0), +WTC(0x366f8340), WTC(0x370fb800), WTC(0x37b2cf80), WTC(0x3857a480), WTC(0x38fcee80), WTC(0x39a16840), WTC(0x3a4422c0), WTC(0x3ae495c0), +WTC(0x3b824000), WTC(0x3c1cb500), WTC(0x3cb438c0), WTC(0x3d4994c0), WTC(0x3ddd8f40), WTC(0x3e70ec00), WTC(0x3f045e40), WTC(0x3f989080), +WTC(0x402e32ff), WTC(0x40c5c07f), WTC(0x415f547f), WTC(0x41faf07f), WTC(0x4298997f), WTC(0x4338307f), WTC(0x43d96bff), WTC(0x447bffff), +WTC(0x451f9cff), WTC(0x45c3daff), WTC(0x46683eff), WTC(0x470c4cff), WTC(0x47af93ff), WTC(0x4851c3ff), WTC(0x48f29d7f), WTC(0x4991de7f), +WTC(0x4a2f5e7f), WTC(0x4acb287f), WTC(0x4b65537f), WTC(0x4bfdf37f), WTC(0x4c95337f), WTC(0x4d2b51ff), WTC(0x4dc091ff), WTC(0x4e5533ff), +WTC(0x4ee96b7f), WTC(0x4f7d61ff), WTC(0x501140ff), WTC(0x50a5317f), WTC(0x51395a7f), WTC(0x51cddf7f), WTC(0x5262e6ff), WTC(0x52f885ff), +WTC(0x538eb47f), WTC(0x542560ff), WTC(0x54bc7b7f), WTC(0x5553a8ff), WTC(0x55ea35ff), WTC(0x567f66ff), WTC(0x5712897f), WTC(0x57a33a7f), +WTC(0x583152ff), WTC(0x58bca5ff), WTC(0x594530ff), WTC(0x59cb79ff), WTC(0x5a5047ff), WTC(0x5ad45eff), WTC(0x5b584e7f), WTC(0x5bdc417f), +WTC(0x5c60487f), WTC(0x5ce476ff), WTC(0x5d68c47f), WTC(0x5ded06ff), WTC(0x5e7111ff), WTC(0x5ef4b5ff), WTC(0x5f77a17f), WTC(0x5ff96aff), +WTC(0x6079a7ff), WTC(0x60f7f7ff), WTC(0x617417ff), WTC(0x61edd87f), WTC(0x6264ffff), WTC(0x62d9a6ff), WTC(0x634c817f), WTC(0x63be657f), +WTC(0x6430277f), WTC(0x64a2247f), WTC(0x65142bff), WTC(0x6586027f), WTC(0x65f7697f), WTC(0x666801ff), WTC(0x66d756ff), WTC(0x6744f0ff), +WTC(0x67b0787f), WTC(0x681a077f), WTC(0x6881ebff), WTC(0x68e8707f), WTC(0x694dceff), WTC(0x69b21e7f), WTC(0x6a156cff), WTC(0x6a77ca7f), +WTC(0x6ad9377f), WTC(0x6b39a4ff), WTC(0x6b9901ff), WTC(0x6bf73cff), WTC(0x6c54457f), WTC(0x6cb00aff), WTC(0x6d0a7bff), WTC(0x6d6387ff), +WTC(0xae2cbe01), WTC(0xaf526d01), WTC(0xb0751201), WTC(0xb194da81), WTC(0xb2b1f401), WTC(0xb3cc8d01), WTC(0xb4e4d201), WTC(0xb5faf101), +WTC(0xb70f1881), WTC(0xb8217301), WTC(0xb9321181), WTC(0xba40ee01), WTC(0xbb4e0201), WTC(0xbc594781), WTC(0xbd62b881), WTC(0xbe6a5181), +WTC(0xbf700d01), WTC(0xc073e4c0), WTC(0xc175d240), WTC(0xc275cc80), WTC(0xc373cb80), WTC(0xc46fca00), WTC(0xc569c600), WTC(0xc661bdc0), +WTC(0xc757af80), WTC(0xc84b9840), WTC(0xc93d7300), WTC(0xca2d3a40), WTC(0xcb1aea40), WTC(0xcc068280), WTC(0xccf00480), WTC(0xcdd77200), +WTC(0xcebccb40), WTC(0xcfa00d80), WTC(0xd0813540), WTC(0xd1603f00), WTC(0xd23d2980), WTC(0xd317f7c0), WTC(0xd3f0ac40), WTC(0xd4c74980), +WTC(0xd59bcf80), WTC(0xd66e3b00), WTC(0xd73e8900), WTC(0xd80cb740), WTC(0xd8d8c7c0), WTC(0xd9a2be00), WTC(0xda6a9e40), WTC(0xdb306a40), +WTC(0xdbf42080), WTC(0xdcb5be80), WTC(0xdd754140), WTC(0xde32a900), WTC(0xdeedf9c0), WTC(0xdfa737c0), WTC(0xe05e6740), WTC(0xe1138900), +WTC(0xe1c69ac0), WTC(0xe2779a40), WTC(0xe3268680), WTC(0xe3d36260), WTC(0xe47e33a0), WTC(0xe526ff80), WTC(0xe5cdc960), WTC(0xe6729100), +WTC(0xe7155460), WTC(0xe7b611c0), WTC(0xe854ca20), WTC(0xe8f18180), WTC(0xe98c3ca0), WTC(0xea24ffe0), WTC(0xeabbcb20), WTC(0xeb509b60), +WTC(0xebe36d00), WTC(0xec743e00), WTC(0xed0310e0), WTC(0xed8feaa0), WTC(0xee1ad060), WTC(0xeea3c640), WTC(0xef2acd60), WTC(0xefafe6a0), +WTC(0xf03312f0), WTC(0xf0b45800), WTC(0xf133c230), WTC(0xf1b15ef0), WTC(0xf22d3af0), WTC(0xf2a75c80), WTC(0xf31fc460), WTC(0xf39673b0), +WTC(0xf40b6a00), WTC(0xf47ea230), WTC(0xf4f01450), WTC(0xf55fb930), WTC(0xf5cd84c0), WTC(0xf6396090), WTC(0xf6a333e0), WTC(0xf70ae540), +WTC(0xf7707260), WTC(0xf7d3f720), WTC(0xf83592f0), WTC(0xf8956450), WTC(0xf8f38120), WTC(0xf94ff7c8), WTC(0xf9aad740), WTC(0xfa042920), +WTC(0xfa5be110), WTC(0xfab1e778), WTC(0xfb062478), WTC(0xfb588d78), WTC(0xfba93530), WTC(0xfbf836c8), WTC(0xfc45ace0), WTC(0xfc91a294), +WTC(0xfcdc0e5c), WTC(0xfd24e438), WTC(0xfd6c17dc), WTC(0xfdb19758), WTC(0xfdf54c3c), WTC(0xfe371ef8), WTC(0xfe7701aa), WTC(0xfeb50d62), +WTC(0xfef1700a), WTC(0xff2c5574), WTC(0xff65ee7b), WTC(0xff9e75de), WTC(0xffd62863), WTC(0x000d4401), WTC(0x0043d345), WTC(0x00799cd0), +WTC(0x00ae5f49), WTC(0x00e1d7a4), WTC(0x0113a6f2), WTC(0x0143575c), WTC(0x01707024), WTC(0x019a9346), WTC(0x01c1cf08), WTC(0x01e66c12), +WTC(0x0208ac48), WTC(0x0228e868), WTC(0x0247a6c8), WTC(0x02657aa0), WTC(0x0282f710), WTC(0x02a07e50), WTC(0x02be31c0), WTC(0x02dc2b30), +WTC(0x02fa7f34), WTC(0x0318fb10), WTC(0x03372fdc), WTC(0x0354ae54), WTC(0x03710d18), WTC(0x038bfdb4), WTC(0x03a54084), WTC(0x03bc92b8), +WTC(0x03d1c710), WTC(0x03e4dd20), WTC(0x03f5e25c), WTC(0x0404e218), WTC(0x0411fc30), WTC(0x041d6b30), WTC(0x04276cd0), WTC(0x04303e00), +WTC(0x04381528), WTC(0x043f2310), WTC(0x04459908), WTC(0x044ba430), WTC(0x045161f8), WTC(0x0456e6f8), WTC(0x045c49a8), WTC(0x046192f8), +WTC(0x0466af40), WTC(0x046b8240), WTC(0x046ff0d8), WTC(0x0473de18), WTC(0x04772b58), WTC(0x0479b9a0), WTC(0x047b6a30), WTC(0x047c2088), +WTC(0x047bc230), WTC(0x047a3418), WTC(0x04776098), WTC(0x04734790), WTC(0x046df4c0), WTC(0x04677220), WTC(0x045fd1b0), WTC(0x04573588), +WTC(0x044dc4b8), WTC(0x0443a5b8), WTC(0x04390160), WTC(0x042e0398), WTC(0x0422d8c0), WTC(0x0417aa30), WTC(0x040c7ce0), WTC(0x040136e0), +WTC(0x03f5beb0), WTC(0x03e9f8ec), WTC(0x03ddc484), WTC(0x03d0fd9c), WTC(0x03c37fa0), WTC(0x03b53014), WTC(0x03a60a18), WTC(0x03960f88), +WTC(0x03854110), WTC(0x0373ad9c), WTC(0x03617694), WTC(0x034ebf9c), WTC(0x033bab30), WTC(0x03284ef0), WTC(0x0314b598), WTC(0x0300ea54), +WTC(0x02ecf524), WTC(0x02d8d210), WTC(0x02c476ac), WTC(0x02afd940), WTC(0x029aee4c), WTC(0x0285a6f4), WTC(0x026ff398), WTC(0x0259c448), +WTC(0x024317cc), WTC(0x022c0084), WTC(0x02149310), WTC(0x01fce334), WTC(0x01e4fb24), WTC(0x01ccdd0a), WTC(0x01b48b20), WTC(0x019c077e), +WTC(0x01835432), WTC(0x016a733c), WTC(0x015166a6), WTC(0x0138302e), WTC(0x011ed0f6), WTC(0x010549f8), WTC(0x00eb9c25), WTC(0x00d1caa6), +WTC(0x00b7db94), WTC(0x009dd560), WTC(0x0083be75), WTC(0x00699d41), WTC(0x004f782f), WTC(0x003555ab), WTC(0x001b3c21), WTC(0x000131fe), +WTC(0xd61cfc40), WTC(0xd5acb340), WTC(0xd53d4400), WTC(0xd4cea6c0), WTC(0xd460d440), WTC(0xd3f3c440), WTC(0xd3876f80), WTC(0xd31bce40), +WTC(0xd2b0d900), WTC(0xd2468980), WTC(0xd1dcef00), WTC(0xd17429c0), WTC(0xd10c5b80), WTC(0xd0a59b80), WTC(0xd03fd780), WTC(0xcfdae780), +WTC(0xcf76a380), WTC(0xcf12fac0), WTC(0xceb01100), WTC(0xce4e18c0), WTC(0xcded4440), WTC(0xcd8d9a40), WTC(0xcd2ee800), WTC(0xccd0f440), +WTC(0xcc738780), WTC(0xcc167d40), WTC(0xcbb9c180), WTC(0xcb5d4040), WTC(0xcb00e240), WTC(0xcaa48000), WTC(0xca47eac0), WTC(0xc9eaf1c0), +WTC(0xc98d8100), WTC(0xc92fc580), WTC(0xc8d1fc80), WTC(0xc8746480), WTC(0xc816dc40), WTC(0xc7b8c280), WTC(0xc7596800), WTC(0xc6f81f80), +WTC(0xc6945740), WTC(0xc62d93c0), WTC(0xc5c358c0), WTC(0xc5552b80), WTC(0xc4e29240), WTC(0xc46b1440), WTC(0xc3ee3840), WTC(0xc36b8500), +WTC(0xc2e28040), WTC(0xc252ae80), WTC(0xc1bb9540), WTC(0xc11cc200), WTC(0xc075cf00), WTC(0xbfc65781), WTC(0xbf0df881), WTC(0xbe4c6f01), +WTC(0xbd819401), WTC(0xbcad2d01), WTC(0xbbcfb981), WTC(0xbaeca681), WTC(0xba08e781), WTC(0xb9297081), WTC(0xb851e081), WTC(0xb782ed01), +WTC(0xb6bc6a81), WTC(0xb5fe4981), WTC(0xb5487281), WTC(0xb49ad081), WTC(0xb3f54d81), WTC(0xb357d401), WTC(0xb2c24e01), WTC(0xb234a681), +WTC(0xb1aec701), WTC(0xb1309b01), WTC(0xb0ba0c01), WTC(0xb04b0481), WTC(0xafe36f01), WTC(0xaf833601), WTC(0xaf2a4381), WTC(0xaed88201), +WTC(0xae8ddb81), WTC(0xae4a3b81), WTC(0xae0d8b01), WTC(0xadd7b581), WTC(0xada8a481), WTC(0xad804281), WTC(0xad5e7a81), WTC(0xad433601), +WTC(0xad2e6001), WTC(0xad1fe281), WTC(0xad17a801), WTC(0xad159a81), WTC(0xad19a501), WTC(0xad23b101), WTC(0xad33aa01), WTC(0xad497981), +WTC(0xad650a01), WTC(0xad864601), WTC(0xadad1781), WTC(0xadd96981), WTC(0xae0b2601), WTC(0xae423781), WTC(0xae7e8801), WTC(0xaec00201), +WTC(0xaf069081), WTC(0xaf521c81), WTC(0xafa29201), WTC(0xaff7da01), WTC(0xb051df01), WTC(0xb0b08c81), WTC(0xb113cb81), WTC(0xb17b8701), +WTC(0xb1e7a981), WTC(0xb2581d81), WTC(0xb2cccc81), WTC(0xb345a181), WTC(0xb3c28701), WTC(0xb4436681), WTC(0xb4c82b81), WTC(0xb550bf81), +WTC(0xb5dd0d01), WTC(0xb66cff01), WTC(0xb7007f01), WTC(0xb7977781), WTC(0xb831d381), WTC(0xb8cf7d01), WTC(0xb9705e01), WTC(0xba146101), +WTC(0xbabb7081), WTC(0xbb657781), WTC(0xbc125f01), WTC(0xbcc21281), WTC(0xbd747b81), WTC(0xbe298581), WTC(0xbee11981), WTC(0xbf9b2301), +WTC(0xc0578b80), WTC(0xc1163dc0), WTC(0xc1d72400), WTC(0xc29a28c0), WTC(0xc35f3640), WTC(0xc42636c0), WTC(0xc4ef1500), WTC(0xc5b9bb00), +WTC(0xc6861340), WTC(0xc7540840), WTC(0xc8238400), WTC(0xc8f47100), WTC(0xc9c6b9c0), WTC(0xca9a4840), WTC(0xcb6f0780), WTC(0xcc44e140), +WTC(0xcd1bc000), WTC(0xcdf38e00), WTC(0xcecc3600), WTC(0xcfa5a240), WTC(0xd07fbcc0), WTC(0xd15a7040), WTC(0xd235a6c0), WTC(0xd3114b00), +WTC(0xd3ed4740), WTC(0xd4c98580), WTC(0xd5a5f080), WTC(0xd6827280), WTC(0xd75ef600), WTC(0xd83b6500), WTC(0xd917aa00), WTC(0xd9f3af80), +WTC(0xdacf5fc0), WTC(0xdbaaa540), WTC(0xdc856a00), WTC(0xdd5f98c0), WTC(0xde391bc0), WTC(0xdf11dd40), WTC(0xdfe9c780), WTC(0xe0c0c540), +WTC(0xe196c080), WTC(0xe26ba3c0), WTC(0xe33f5960), WTC(0xe411cba0), WTC(0xe4e2e500), WTC(0xe5b28fc0), WTC(0xe680b640), WTC(0xe74d42e0), +WTC(0xe8181fe0), WTC(0xe8e137e0), WTC(0xe9a87500), WTC(0xea6dc1a0), WTC(0xeb310820), WTC(0xebf23300), WTC(0xecb12c60), WTC(0xed6ddee0), +WTC(0xee2834a0), WTC(0xeee01800), WTC(0xef957380), WTC(0xf0483160), WTC(0xf0f83c00), WTC(0xf1a57db0), WTC(0xf24fe0f0), WTC(0xf2f74ff0), +WTC(0xf39bb530), WTC(0xf43cfaf0), WTC(0xf4db0b90), WTC(0xf575d180), WTC(0xf60d3700), WTC(0xf6a12680), WTC(0xf7318a50), WTC(0xf7be4cc0), +WTC(0xf8475850), WTC(0xf8cc9738), WTC(0xf94df3e0), WTC(0xf9cb58a8), WTC(0xfa44afe0), WTC(0xfab9e3e8), WTC(0xfb2adf20), WTC(0xfb978be8), +WTC(0xfbffd488), WTC(0xfc63a370), WTC(0xfcc2e2f0), WTC(0xfd1d7d64), WTC(0xfd735d2c), WTC(0xfdc46c9c), WTC(0xfe109618), WTC(0xfe57c3f4), +WTC(0xfe99e090), WTC(0xfed6d644), WTC(0xff0e8f6e), WTC(0xff40f667), WTC(0xff6df58c), WTC(0xff957738), WTC(0xffb765c5), WTC(0xffd3ab90), +WTC(0xffea32f4), WTC(0xfffae64c), WTC(0x0005aff3), WTC(0x000a7a44), WTC(0x00092f9c), WTC(0x0001ba54), WTC(0xfff404ca), WTC(0xffdff957) +}; + + + + +/* + * TNS_MAX_BANDS + * entry for each sampling rate + * 1 long window + * 2 SHORT window +*/ +const UCHAR tns_max_bands_tbl[13][2] = +{ + { 31, 9 }, /* 96000 */ + { 31, 9 }, /* 88200 */ + { 34, 10 }, /* 64000 */ + { 40, 14 }, /* 48000 */ + { 42, 14 }, /* 44100 */ + { 51, 14 }, /* 32000 */ + { 46, 14 }, /* 24000 */ + { 46, 14 }, /* 22050 */ + { 42, 14 }, /* 16000 */ + { 42, 14 }, /* 12000 */ + { 42, 14 }, /* 11025 */ + { 39, 14 }, /* 8000 */ + { 39, 14 }, /* 7350 */ +}; + +/* TNS_MAX_BANDS for low delay. The array index is the sampleRateIndex */ +const UCHAR tns_max_bands_tbl_480[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 30, /* 24000 */ + 30, /* 22050 */ + 30, /* 16000 */ + 30, /* 12000 */ + 30, /* 11025 */ + 30, /* 8000 */ + 30 /* 7350 */ +}; +const UCHAR tns_max_bands_tbl_512[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 31, /* 24000 */ + 31, /* 22050 */ + 31, /* 16000 */ + 31, /* 12000 */ + 31, /* 11025 */ + 31, /* 8000 */ + 31 /* 7350 */ +}; + +#define TCC(x) (FIXP_DBL(x)) + +const FIXP_TCC FDKaacDec_tnsCoeff3 [8] = +{ + TCC(0x81f1d1d4), TCC(0x9126146c), TCC(0xadb922c4), TCC(0xd438af1f), + TCC(0x00000000), TCC(0x3789809b), TCC(0x64130dd4), TCC(0x7cca7016) +}; +const FIXP_TCC FDKaacDec_tnsCoeff4 [16] = +{ + TCC(0x808bc842), TCC(0x84e2e58c), TCC(0x8d6b49d1), TCC(0x99da920a), + TCC(0xa9c45713), TCC(0xbc9ddeb9), TCC(0xd1c2d51b), TCC(0xe87ae53d), + TCC(0x00000000), TCC(0x1a9cd9b6), TCC(0x340ff254), TCC(0x4b3c8c29), + TCC(0x5f1f5ebb), TCC(0x6ed9ebba), TCC(0x79bc385f), TCC(0x7f4c7e5b) +}; + +/* MPEG like mapping (no change). */ +const UCHAR channelMappingTablePassthrough[15][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */ + { 0, 1,255,255,255,255,255,255}, /* mono / PS */ + { 0, 1,255,255,255,255,255,255}, /* stereo */ + { 0, 1, 2,255,255,255,255,255}, /* 3ch */ + { 0, 1, 2, 3,255,255,255,255}, /* 4ch */ + { 0, 1, 2, 3, 4,255,255,255}, /* 5ch */ + { 0, 1, 2, 3, 4, 5,255,255}, /* 5.1ch */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 front */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6,255}, /* 6.1ch */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* 7.1 rear */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6, 7} /* 7.1 top */ +}; + +/* WAV file like mapping (from MPEG mapping). */ +const UCHAR channelMappingTableWAV[15][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* fallback */ + { 0, 1,255,255,255,255,255,255}, /* mono / PS */ + { 0, 1,255,255,255,255,255,255}, /* stereo */ + { 2, 0, 1,255,255,255,255,255}, /* 3ch */ + { 2, 0, 1, 3,255,255,255,255}, /* 4ch */ + { 2, 0, 1, 3, 4,255,255,255}, /* 5ch */ + { 2, 0, 1, 4, 5, 3,255,255}, /* 5.1ch */ + { 2, 6, 7, 0, 1, 4, 5, 3}, /* 7.1 front */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 2, 0, 1, 4, 5, 6, 3,255}, /* 6.1ch */ + { 2, 0, 1, 6, 7, 4, 5, 3}, /* 7.1 rear */ + { 0, 1, 2, 3, 4, 5, 6, 7}, /* reserved */ + { 2, 0, 1, 4, 5, 3, 6, 7} /* 7.1 top */ +}; + +/* Lookup tables for elements in ER bitstream */ +const MP4_ELEMENT_ID elementsTab[15][7] = +{ + /* 1 */ { ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* 1 channel */ + /* 2 */ { ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, ID_NONE } /* 2 channels */ + /* 3 */ ,{ ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE }, /* 3 channels */ + /* 4 */ { ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 4 channels */ + /* 5 */ { ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE }, /* 5 channels */ + /* 6 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, ID_NONE } /* 6 channels */ + /* 7 */ ,{ ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */ + /* 8 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */ + /* 9 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */ + /* 10 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */ + /* 11 */ { ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, ID_END }, /* 7 channels */ + /* 12 */ { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END }, /* 8 channels */ + /* 13 */ { ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE }, /* reserved */ + /* 14 */ { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, ID_END } /* 8 channels */ +}; + +/*! Random sign bit used for concealment +*/ +const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16] = { +/* + sign bits of FDK_sbrDecoder_sbr_randomPhase[] entries: + LSB ........... MSB -> MSB ... LSB +*/ +/* 1001 0111 0011 1100 -> */ 0x3ce9, +/* 0100 0111 0111 1011 -> */ 0xdee2, +/* 0001 1100 1110 1011 -> */ 0xd738, +/* 0001 0011 0110 1001 -> */ 0x96c8, +/* 0101 0011 1101 0000 -> */ 0x0bca, +/* 0001 0001 1111 0100 -> */ 0x2f88, +/* 1110 1100 1110 1101 -> */ 0xb737, +/* 0010 1010 1011 1001 -> */ 0x9d54, +/* 0111 1100 0110 1010 -> */ 0x563e, +/* 1101 0111 0010 0101 -> */ 0xa4eb, +/* 0001 0101 1011 1100 -> */ 0x3da8, +/* 0101 0111 1001 1011 -> */ 0xd9ea, +/* 1101 0100 0101 0101 -> */ 0xaa2b, +/* 1000 1001 0100 0011 -> */ 0xc291, +/* 1100 1111 1010 1100 -> */ 0x35f3, +/* 1100 1010 1110 0010 -> */ 0x4753, +/* 0110 0001 1010 1000 -> */ 0x1586, +/* 0011 0101 1111 1100 -> */ 0x3fac, +/* 0001 0110 1010 0001 -> */ 0x8568, +/* 0010 1101 0111 0010 -> */ 0x4eb4, +/* 1101 1010 0100 1001 -> */ 0x925b, +/* 1100 1001 0000 1110 -> */ 0x7093, +/* 1000 1100 0110 1010 -> */ 0x5631, +/* 0000 1000 0110 1101 -> */ 0xb610, +/* 1000 0001 1111 1011 -> */ 0xdf81, +/* 1111 0011 0100 0111 -> */ 0xe2cf, +/* 1000 0001 0010 1010 -> */ 0x5481, +/* 1101 0101 1100 1111 -> */ 0xf3ab, +/* 0110 0001 0110 1000 -> */ 0x1686, +/* 0011 0011 1100 0110 -> */ 0x63cc, +/* 0011 0111 0101 0110 -> */ 0x6aec, +/* 1011 0001 1010 0010 -> */ 0x458d +}; + diff --git a/libAACdec/src/aac_rom.h b/libAACdec/src/aac_rom.h new file mode 100644 index 00000000..f314a2d5 --- /dev/null +++ b/libAACdec/src/aac_rom.h @@ -0,0 +1,188 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: Definition of constant tables + +******************************************************************************/ + +#ifndef AAC_ROM_H +#define AAC_ROM_H + +#include "common_fix.h" +#include "FDK_audio.h" +#include "aacdec_hcr_types.h" +#include "aacdec_hcrs.h" + +#define AAC_NF_NO_RANDOM_VAL 512 /*!< Size of random number array for noise floor */ + +#define INV_QUANT_TABLESIZE 256 + +extern const FIXP_DBL InverseQuantTable [INV_QUANT_TABLESIZE + 1] ; +extern const FIXP_DBL MantissaTable [4][14] ; +extern const SCHAR ExponentTable [4][14] ; + +#define NUM_LD_COEF_512 1536 +#define NUM_LD_COEF_480 1440 +/* Window table partition exponents. */ +#define WTS0 (1) +#define WTS1 (0) +#define WTS2 (-2) +extern const FIXP_WTB LowDelaySynthesis512[1536]; +extern const FIXP_WTB LowDelaySynthesis480[1440]; + +typedef struct { + const SHORT *sfbOffsetLong; + const SHORT *sfbOffsetShort; + UCHAR numberOfSfbLong; + UCHAR numberOfSfbShort; +} SFB_INFO; + +extern const SFB_INFO sfbOffsetTables[5][16]; + +/* Huffman tables */ +enum { + HuffmanBits = 2, + HuffmanEntries = (1 << HuffmanBits) +}; + +typedef struct +{ + const USHORT (*CodeBook)[HuffmanEntries]; + UCHAR Dimension; + UCHAR numBits; + UCHAR Offset; +} CodeBookDescription; + +extern const CodeBookDescription AACcodeBookDescriptionTable[13]; +extern const CodeBookDescription AACcodeBookDescriptionSCL; + + +extern const STATEFUNC aStateConstant2State[]; + +extern const SCHAR aCodebook2StartInt[]; + +extern const UCHAR aMinOfCbPair[]; +extern const UCHAR aMaxOfCbPair[]; + +extern const UCHAR aMaxCwLen[]; +extern const UCHAR aDimCb[]; +extern const UCHAR aDimCbShift[]; +extern const UCHAR aSignCb[]; +extern const UCHAR aCbPriority[]; + +extern const UINT *aHuffTable[]; +extern const SCHAR *aQuantTable[]; + +extern const USHORT aLargestAbsoluteValue[]; + +extern const UINT aHuffTreeRvlcEscape[]; +extern const UINT aHuffTreeRvlCodewds[]; + + +extern const UCHAR tns_max_bands_tbl[13][2]; + +extern const UCHAR tns_max_bands_tbl_480[13]; +extern const UCHAR tns_max_bands_tbl_512[13]; + +#define FIXP_TCC FIXP_DBL + +extern const FIXP_TCC FDKaacDec_tnsCoeff3[8]; +extern const FIXP_TCC FDKaacDec_tnsCoeff4[16]; + +extern const USHORT randomSign[AAC_NF_NO_RANDOM_VAL/16]; + +extern const FIXP_DBL pow2_div24minus1[47]; +extern const int offsetTab[2][16]; + +/* Channel mapping indices for time domain I/O. + The first dimension is the channel configuration index. */ +extern const UCHAR channelMappingTablePassthrough[15][8]; +extern const UCHAR channelMappingTableWAV[15][8]; + +/* Lookup tables for elements in ER bitstream */ +extern const MP4_ELEMENT_ID elementsTab[15][7]; + +#endif /* #ifndef AAC_ROM_H */ diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp new file mode 100644 index 00000000..eb8e4107 --- /dev/null +++ b/libAACdec/src/aacdec_drc.cpp @@ -0,0 +1,1188 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for AAC + +******************************************************************************/ + +#include "aacdec_drc.h" + + +#include "channelinfo.h" +#include "aac_rom.h" + + #include "sbrdecoder.h" + +/* + * Dynamic Range Control + */ + +/* For parameter conversion */ +#define DRC_PARAMETER_BITS ( 7 ) +#define DRC_MAX_QUANT_STEPS ( 1<enable = 0; + self->numThreads = 0; + + /* init params */ + pParams = &self->params; + pParams->bsDelayEnable = 0; + pParams->cut = FL2FXCONST_DBL(0.0f); + pParams->usrCut = FL2FXCONST_DBL(0.0f); + pParams->boost = FL2FXCONST_DBL(0.0f); + pParams->usrBoost = FL2FXCONST_DBL(0.0f); + pParams->targetRefLevel = -1; + pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES; + pParams->applyDigitalNorm = 0; + pParams->applyHeavyCompression = 0; + + /* initial program ref level = target ref level */ + self->progRefLevel = pParams->targetRefLevel; + self->progRefLevelPresent = 0; + self->presMode = -1; +} + + +/*! + \brief Initialize DRC control data for one channel + + \self Handle of DRC info + + \return none +*/ +void aacDecoder_drcInitChannelData ( + CDrcChannelData *pDrcChData ) +{ + if (pDrcChData != NULL) { + pDrcChData->expiryCount = 0; + pDrcChData->numBands = 1; + pDrcChData->bandTop[0] = (1024 >> 2) - 1; + pDrcChData->drcValue[0] = 0; + pDrcChData->drcInterpolationScheme = 0; + pDrcChData->drcDataType = UNKNOWN_PAYLOAD; + } +} + + +/*! + \brief Set one single DRC parameter + + \self Handle of DRC info. + \param Parameter to be set. + \value Value to be set. + + \return an error code. +*/ +AAC_DECODER_ERROR aacDecoder_drcSetParam ( + HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, + INT value ) +{ + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + switch (param) + { + case DRC_CUT_SCALE: + /* set attenuation scale factor */ + if ( (value < 0) + || (value > DRC_MAX_QUANT_FACTOR) ) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrCut = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value); + if (self->params.applyHeavyCompression == 0) + self->params.cut = self->params.usrCut; + break; + case DRC_BOOST_SCALE: + /* set boost factor */ + if ( (value < 0) + || (value > DRC_MAX_QUANT_FACTOR) ) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrBoost = (FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP>>DRC_PARAM_SCALE) * (INT)value); + if (self->params.applyHeavyCompression == 0) + self->params.boost = self->params.usrBoost; + break; + case TARGET_REF_LEVEL: + if ( value > MAX_REFERENCE_LEVEL + || value < -MAX_REFERENCE_LEVEL ) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + if (value < 0) { + self->params.applyDigitalNorm = 0; + self->params.targetRefLevel = -1; + } + else { + /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */ + self->params.applyDigitalNorm = 1; + if (self->params.targetRefLevel != (SCHAR)value) { + self->params.targetRefLevel = (SCHAR)value; + self->progRefLevel = (SCHAR)value; /* Always set the program reference level equal to the + target level according to 4.5.2.7.3 of ISO/IEC 14496-3. */ + } + } + break; + case APPLY_NORMALIZATION: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + /* Store new parameter value */ + self->params.applyDigitalNorm = (UCHAR)value; + break; + case APPLY_HEAVY_COMPRESSION: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + if (self->params.applyHeavyCompression != (UCHAR)value) { + if (value == 1) { + /* Disable scaling of DRC values by setting the max values */ + self->params.boost = FL2FXCONST_DBL(1.0f/(float)(1<params.cut = FL2FXCONST_DBL(1.0f/(float)(1<params.boost = self->params.usrBoost; + self->params.cut = self->params.usrCut; + } + /* Store new parameter value */ + self->params.applyHeavyCompression = (UCHAR)value; + } + break; + case DRC_BS_DELAY: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.bsDelayEnable = value; + break; + case DRC_DATA_EXPIRY_FRAME: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.expiryFrame = (UINT)value; + break; + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + + /* switch on/off processing */ + self->enable = ( (self->params.boost > (FIXP_DBL)0) + || (self->params.cut > (FIXP_DBL)0) + || (self->params.applyHeavyCompression != 0) + || (self->params.targetRefLevel >= 0) ); + + + return ErrorStatus; +} + + +static int parseExcludedChannels( UINT *excludedChnsMask, + HANDLE_FDK_BITSTREAM bs ) +{ + UINT excludeMask = 0; + UINT i, j; + int bitCnt = 9; + + for (i = 0, j = 1; i < 7; i++, j<<=1) { + if (FDKreadBits(bs,1)) { + excludeMask |= j; + } + } + + /* additional_excluded_chns */ + while (FDKreadBits(bs,1)) { + for (i = 0; i < 7; i++, j<<=1) { + if (FDKreadBits(bs,1)) { + excludeMask |= j; + } + } + bitCnt += 9; + FDK_ASSERT(j < (UINT)-1); + } + + *excludedChnsMask = excludeMask; + + return (bitCnt); +} + + +/*! + \brief Save DRC payload bitstream position + + \self Handle of DRC info + \bs Handle of FDK bitstream + + \return The number of DRC payload bits +*/ +int aacDecoder_drcMarkPayload ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM bs, + AACDEC_DRC_PAYLOAD_TYPE type ) +{ + UINT bsStartPos; + int i, numBands = 1, bitCnt = 0; + + if (self == NULL) { + return 0; + } + + bsStartPos = FDKgetValidBits(bs); + + switch (type) { + case MPEG_DRC_EXT_DATA: + { + bitCnt = 4; + + if (FDKreadBits(bs,1)) { /* pce_tag_present */ + FDKreadBits(bs,8); /* pce_instance_tag + drc_tag_reserved_bits */ + bitCnt+=8; + } + + if (FDKreadBits(bs,1)) { /* excluded_chns_present */ + FDKreadBits(bs,7); /* exclude mask [0..7] */ + bitCnt+=8; + while (FDKreadBits(bs,1)) { /* additional_excluded_chns */ + FDKreadBits(bs,7); /* exclude mask [x..y] */ + bitCnt+=8; + } + } + + if (FDKreadBits(bs,1)) { /* drc_bands_present */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + FDKreadBits(bs,4); /* reserved */ + bitCnt+=8; + for (i = 0; i < numBands; i++) { + FDKreadBits(bs,8); /* drc_band_top[i] */ + bitCnt+=8; + } + } + + if (FDKreadBits(bs,1)) { /* prog_ref_level_present */ + FDKreadBits(bs,8); /* prog_ref_level + prog_ref_level_reserved_bits */ + bitCnt+=8; + } + + for (i = 0; i < numBands; i++) { + FDKreadBits(bs,8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */ + bitCnt+=8; + } + + if ( (self->numPayloads < MAX_DRC_THREADS) + && ((INT)FDKgetValidBits(bs) >= 0) ) + { + self->drcPayloadPosition[self->numPayloads++] = bsStartPos; + } + } + break; + + case DVB_DRC_ANC_DATA: + bitCnt += 8; + /* check sync word */ + if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE) + { + int dmxLevelsPresent, compressionPresent; + int coarseGrainTcPresent, fineGrainTcPresent; + + /* bs_info field */ + FDKreadBits(bs, 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */ + bitCnt+=8; + + /* Evaluate ancillary_data_status */ + FDKreadBits(bs, 3); /* reserved, set to 0 */ + dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + FDKreadBits(bs, 1); /* reserved, set to 0 */ + compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */ + fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + bitCnt+=8; + + /* MPEG4 downmixing levels */ + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + bitCnt+=8; + } + /* audio coding mode and compression status */ + if (compressionPresent) { + FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */ + bitCnt+=16; + } + /* coarse grain timecode */ + if (coarseGrainTcPresent) { + FDKreadBits(bs, 16); /* coarse_grain_timecode */ + bitCnt+=16; + } + /* fine grain timecode */ + if (fineGrainTcPresent) { + FDKreadBits(bs, 16); /* fine_grain_timecode */ + bitCnt+=16; + } + if ( !self->dvbAncDataAvailable + && ((INT)FDKgetValidBits(bs) >= 0) ) + { + self->dvbAncDataPosition = bsStartPos; + self->dvbAncDataAvailable = 1; + } + } + break; + + default: + break; + } + + return (bitCnt); +} + + +/*! + \brief Parse DRC parameters from bitstream + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of MPEG DRC data junk (in) + + \return Number of bits read (0 in case of a parse error) +*/ +static int aacDecoder_drcParse ( + HANDLE_FDK_BITSTREAM bs, + CDrcPayload *pDrcBs, + UINT payloadPosition ) +{ + int i, numBands, bitCnt = 4; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition); + + /* pce_tag_present */ + if (FDKreadBits(bs,1)) + { + pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */ + /* only one program supported */ + FDKreadBits(bs, 4); /* drc_tag_reserved_bits */ + bitCnt += 8; + } else { + pDrcBs->pceInstanceTag = -1; /* not present */ + } + + if (FDKreadBits(bs,1)) { /* excluded_chns_present */ + /* get excluded_chn_mask */ + bitCnt += parseExcludedChannels(&pDrcBs->excludedChnsMask, bs); + } else { + pDrcBs->excludedChnsMask = 0; + } + + numBands = 1; + if (FDKreadBits(bs,1)) /* drc_bands_present */ + { + /* get band_incr */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + pDrcBs->channelData.drcInterpolationScheme = FDKreadBits(bs, 4); /* drc_interpolation_scheme */ + bitCnt += 8; + /* band_top */ + for (i = 0; i < numBands; i++) + { + pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */ + bitCnt += 8; + } + } + else { + pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */; + } + + pDrcBs->channelData.numBands = numBands; + + if (FDKreadBits(bs,1)) /* prog_ref_level_present */ + { + pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */ + FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */ + bitCnt += 8; + } else { + pDrcBs->progRefLevel = -1; + } + + for (i = 0; i < numBands; i++) + { + pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) << 7; /* dyn_rng_sgn[i] */ + pDrcBs->channelData.drcValue[i] |= FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */ + bitCnt += 8; + } + + /* Set DRC payload type */ + pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA; + + return (bitCnt); +} + + +/*! + \brief Parse heavy compression value transported in DSEs of DVB streams with MPEG-4 content. + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of DVB ancillary data junk + + \return Number of bits read (0 in case of a parse error) +*/ +#define DVB_COMPRESSION_SCALE ( 8 ) /* 48,164 dB */ + +static int aacDecoder_drcReadCompression ( + HANDLE_FDK_BITSTREAM bs, + CDrcPayload *pDrcBs, + UINT payloadPosition ) +{ + int bitCnt = 0; + int dmxLevelsPresent, extensionPresent, compressionPresent; + int coarseGrainTcPresent, fineGrainTcPresent; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, FDKgetValidBits(bs)-payloadPosition); + + /* Sanity checks */ + if ( FDKgetValidBits(bs) < 24 ) { + return 0; + } + + /* Check sync word */ + if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) { + return 0; + } + + /* Evaluate bs_info field */ + if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */ + /* No MPEG-4 audio data */ + return 0; + } + FDKreadBits(bs, 2); /* dolby_surround_mode */ + pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */ + FDKreadBits(bs, 1); /* stereo_downmix_mode */ + if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */ + return 0; + } + + /* Evaluate ancillary_data_status */ + if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */ + return 0; + } + dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + extensionPresent = FDKreadBits(bs, 1); /* ancillary_data_extension_status; */ + compressionPresent = FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + coarseGrainTcPresent = FDKreadBits(bs, 1); /* coarse_grain_timecode_status */ + fineGrainTcPresent = FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + bitCnt += 24; + + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + bitCnt += 8; + } + + /* audio_coding_mode_and_compression_status */ + if (compressionPresent) + { + UCHAR compressionOn, compressionValue; + + /* audio_coding_mode */ + if ( FDKreadBits(bs, 7) != 0 ) { /* The reserved bits shall be set to "0". */ + return 0; + } + compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */ + compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */ + bitCnt += 16; + + if ( compressionOn ) { + /* A compression value is available so store the data just like MPEG DRC data */ + pDrcBs->channelData.numBands = 1; /* One band ... */ + pDrcBs->channelData.drcValue[0] = compressionValue; /* ... with one value ... */ + pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */ + pDrcBs->pceInstanceTag = -1; /* Not present */ + pDrcBs->progRefLevel = -1; /* Not present */ + pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */ + } else { + /* No compression value available */ + /* CAUTION: It is not clearly defined by standard how to react in this situation. */ + /* Turn down the compression value to aprox. 0dB */ + pDrcBs->channelData.numBands = 1; /* One band ... */ + pDrcBs->channelData.drcValue[0] = 0x80; /* ... with aprox. 0dB ... */ + pDrcBs->channelData.bandTop[0] = (1024 >> 2) - 1; /* ... comprising the whole spectrum. */ + pDrcBs->channelData.drcDataType = DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */ + + /* If compression_on field is set to "0" the compression_value field shall be "0000 0000". */ + if (compressionValue != 0) { + return 0; + } + } + } + + /* Read timecodes if available just to get the right amount of bits. */ + if (coarseGrainTcPresent) { + FDKreadBits(bs, 16); /* coarse_grain_timecode */ + bitCnt += 16; + } + if (fineGrainTcPresent) { + FDKreadBits(bs, 16); /* fine_grain_timecode */ + bitCnt += 16; + } + + /* Read extension just to get the right amount of bits. */ + if (extensionPresent) { + int extBits = 8; + + FDKreadBits(bs, 1); /* reserved, set to 0 */ + if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_levels_status */ + if (FDKreadBits(bs, 1)) extBits += 16; /* ext_downmixing_global_gains_status */ + if (FDKreadBits(bs, 1)) extBits += 8; /* ext_downmixing_lfe_level_status */ + + FDKpushFor(bs, extBits - 4); /* skip the extension payload remainder. */ + bitCnt += extBits; + } + + return (bitCnt); +} + + +/* + * Prepare DRC processing + */ +static int aacDecoder_drcExtractAndMap ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */ + int validChannels ) +{ + CDrcPayload threadBs[MAX_DRC_THREADS]; + CDrcPayload *validThreadBs[MAX_DRC_THREADS]; + CDrcParams *pParams; + UINT backupBsPosition; + int i, thread, validThreads = 0; + int numExcludedChns[MAX_DRC_THREADS]; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(hBs != NULL); + FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL); + + pParams = &self->params; + + self->numThreads = 0; + backupBsPosition = FDKgetValidBits(hBs); + + for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; i++) { + int bitsParsed; + + /* Init payload data chunk. The memclear is very important because it initializes + the most values. Without it the module wouldn't work properly or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1; + + /* Extract payload */ + bitsParsed = aacDecoder_drcParse( hBs, + &threadBs[self->numThreads], + self->drcPayloadPosition[i] ); + if (bitsParsed > 0) { + self->numThreads++; + } + } + self->numPayloads = 0; + + if (self->dvbAncDataAvailable && self->numThreads < MAX_DRC_THREADS) + { /* Append a DVB heavy compression payload thread if available. */ + int bitsParsed; + + /* Init payload data chunk. The memclear is very important because it initializes + the most values. Without it the module wouldn't work properly or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = (1024 >> 2) - 1; + + /* Extract payload */ + bitsParsed = aacDecoder_drcReadCompression( hBs, + &threadBs[self->numThreads], + self->dvbAncDataPosition ); + if (bitsParsed > 0) { + self->numThreads++; + } + } + self->dvbAncDataAvailable = 0; + + /* Reset the bitbufffer */ + FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - backupBsPosition); + + /* calculate number of valid bits in excl_chn_mask */ + + /* coupling channels not supported */ + + /* check for valid threads */ + for (thread = 0; thread < self->numThreads; thread++) { + CDrcPayload *pThreadBs = &threadBs[thread]; + int numExclChns = 0; + + switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) { + default: + continue; + case MPEG_DRC_EXT_DATA: + case DVB_DRC_ANC_DATA: + break; + } + + if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */ + if (pThreadBs->pceInstanceTag != pceInstanceTag) { + continue; /* don't accept */ + } + } + + /* calculate number of excluded channels */ + if (pThreadBs->excludedChnsMask > 0) { + INT exclMask = pThreadBs->excludedChnsMask; + int ch; + for (ch = 0; ch < validChannels; ch++) { + numExclChns += exclMask & 0x1; + exclMask >>= 1; + } + } + if (numExclChns < validChannels) { + validThreadBs[validThreads] = pThreadBs; + numExcludedChns[validThreads] = numExclChns; + validThreads++; + } + } + + if (validThreads > 1) { + int ch; + + /* check consistency of excl_chn_mask amongst valid DRC threads */ + for (ch = 0; ch < validChannels; ch++) { + int present = 0; + + for (thread = 0; thread < validThreads; thread++) { + CDrcPayload *pThreadBs = validThreadBs[thread]; + + + /* thread applies to this channel */ + if ( (pThreadBs->channelData.drcDataType == MPEG_DRC_EXT_DATA) + && ( (numExcludedChns[thread] == 0) + || (!(pThreadBs->excludedChnsMask & (1< 1) { + return -1; + } + } + } + + /* map DRC bitstream information onto DRC channel information */ + for (thread = 0; thread < validThreads; thread++) + { + CDrcPayload *pThreadBs = validThreadBs[thread]; + INT exclMask = pThreadBs->excludedChnsMask; + AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType; + int ch; + + /* last progRefLevel transmitted is the one that is used + * (but it should really only be transmitted once per block!) + */ + if (pThreadBs->progRefLevel >= 0) { + self->progRefLevel = pThreadBs->progRefLevel; + self->progRefLevelPresent = 1; + self->prlExpiryCount = 0; /* Got a new value -> Reset counter */ + } + + if (drcPayloadType == DVB_DRC_ANC_DATA) { + /* Announce the presentation mode of this valid thread. */ + self->presMode = pThreadBs->presMode; + } + + /* SCE, CPE and LFE */ + for (ch = 0; ch < validChannels; ch++) { + int mapedChannel = channelMapping[ch]; + + if ( ((exclMask & (1<params.applyHeavyCompression) + ) ) { + /* copy thread to channel */ + pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData; + } + } + /* CCEs not supported by now */ + } + + /* Increment and check expiry counter for the program reference level: */ + if ( (pParams->expiryFrame > 0) + && (self->prlExpiryCount++ > pParams->expiryFrame) ) + { /* The program reference level is too old, so set it back to the target level. */ + self->progRefLevelPresent = 0; + self->progRefLevel = pParams->targetRefLevel; + self->prlExpiryCount = 0; + } + + return 0; +} + + +void aacDecoder_drcApply ( + HANDLE_AAC_DRC self, + void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcChData, + FIXP_DBL *extGain, + int ch, /* needed only for SBR */ + int aacFrameSize, + int bSbrPresent ) +{ + int band, top, bin, numBands; + int bottom = 0; + int modifyBins = 0; + + FIXP_DBL max_mantissa; + INT max_exponent; + + FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f); + INT norm_exponent = 1; + + FIXP_DBL fact_mantissa[MAX_DRC_BANDS]; + INT fact_exponent[MAX_DRC_BANDS]; + + CDrcParams *pParams = &self->params; + + FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + int winSeq = pIcsInfo->WindowSequence; + + /* Increment and check expiry counter */ + if ( (pParams->expiryFrame > 0) + && (++pDrcChData->expiryCount > pParams->expiryFrame) ) + { /* The DRC data is too old, so delete it. */ + aacDecoder_drcInitChannelData( pDrcChData ); + } + + if (!self->enable) { + sbrDecoder_drcDisable( (HANDLE_SBRDECODER)pSbrDec, ch ); + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale); + } else { + FDK_ASSERT(0); + } + } + return; + } + + numBands = pDrcChData->numBands; + top = FDKmax(0, numBands-1); + + pDrcChData->bandTop[0] = fixMin(pDrcChData->bandTop[0], (aacFrameSize >> 2) - 1); + + /* If program reference normalization is done in the digital domain, + modify factor to perform normalization. prog_ref_level can + alternatively be passed to the system for modification of the level in + the analog domain. Analog level modification avoids problems with + reduced DAC SNR (if signal is attenuated) or clipping (if signal is + boosted) */ + + if (pParams->targetRefLevel >= 0) + { + /* 0.5^((targetRefLevel - progRefLevel)/24) */ + norm_mantissa = fLdPow( + FL2FXCONST_DBL(-1.0), /* log2(0.5) */ + 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f/24.0)>>3) * (INT)(pParams->targetRefLevel-self->progRefLevel)), + 3, + &norm_exponent ); + } + /* Always export the normalization gain (if possible). */ + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed on by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent-gainScale); + } else { + FDK_ASSERT(0); + } + } + if (self->params.applyDigitalNorm == 0) { + /* Reset normalization gain since this module must not apply it */ + norm_mantissa = FL2FXCONST_DBL(0.5f); + norm_exponent = 1; + } + + + /* calc scale factors */ + for (band = 0; band < numBands; band++) + { + UCHAR drcVal = pDrcChData->drcValue[band]; + top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize); + + fact_mantissa[band] = FL2FXCONST_DBL(0.5f); + fact_exponent[band] = 1; + + if ( pParams->applyHeavyCompression + && ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == DVB_DRC_ANC_DATA) ) + { + INT compressionFactorVal_e; + int valX, valY; + + valX = drcVal >> 4; + valY = drcVal & 0x0F; + + /* calculate the unscaled heavy compression factor. + compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB + range: -48.166 dB to 48.164 dB */ + if ( drcVal != 0x7F ) { + fact_mantissa[band] = + fPowInt( FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */ + 0, + valY, + &compressionFactorVal_e ); + + /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */ + fact_mantissa[band] = fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]); + + fact_exponent[band] = DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e; + } + } else + if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == MPEG_DRC_EXT_DATA) + { + /* apply the scaled dynamic range control words to factor. + * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0 + * then there is no dynamic range compression + * + * if pDrcChData->drcSgn[band] is + * 1 then gain is < 1 : factor = 2^(-self->cut * pDrcChData->drcMag[band] / 24) + * 0 then gain is > 1 : factor = 2^( self->boost * pDrcChData->drcMag[band] / 24) + */ + + if ((drcVal&0x7F) > 0) { + FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost; + + fact_mantissa[band] = + f2Pow( (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f/192.0f), tParamVal) * (drcVal&0x7F)), + 3+DRC_PARAM_SCALE, + &fact_exponent[band] ); + } + } + + fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa); + fact_exponent[band] += norm_exponent; + + + bottom = top; + + } /* end loop over bands */ + + + /* normalizations */ + { + int res; + + max_mantissa = FL2FXCONST_DBL(0.0f); + max_exponent = 0; + for (band = 0; band < numBands; band++) { + max_mantissa = fixMax(max_mantissa, fact_mantissa[band]); + max_exponent = fixMax(max_exponent, fact_exponent[band]); + } + + /* left shift factors to gain accurancy */ + res = CntLeadingZeros(max_mantissa) - 1; + + /* above topmost DRC band gain factor is 1 */ + if (((pDrcChData->bandTop[numBands-1]+1)<<2) < aacFrameSize) res = 0; + + if (res > 0) { + res = fixMin(res, max_exponent); + max_exponent -= res; + + for (band = 0; band < numBands; band++) { + fact_mantissa[band] <<= res; + fact_exponent[band] -= res; + } + } + + /* normalize magnitudes to one scale factor */ + for (band = 0; band < numBands; band++) { + if (fact_exponent[band] < max_exponent) { + fact_mantissa[band] >>= max_exponent - fact_exponent[band]; + } + if (fact_mantissa[band] != FL2FXCONST_DBL(0.5f)) { + modifyBins = 1; + } + } + if (max_exponent != 1) { + modifyBins = 1; + } + } + + /* apply factor to spectral lines + * short blocks must take care that bands fall on + * block boundaries! + */ + if (!bSbrPresent) + { + bottom = 0; + + if (!modifyBins) { + /* We don't have to modify the spectral bins because the fractional part of all factors is 0.5. + In order to keep accurancy we don't apply the factor but decrease the exponent instead. */ + max_exponent -= 1; + } else + { + for (band = 0; band < numBands; band++) + { + top = fixMin((int)( (pDrcChData->bandTop[band]+1)<<2 ), aacFrameSize); /* ... * DRC_BAND_MULT; */ + + for (bin = bottom; bin < top; bin++) { + pSpectralCoefficient[bin] = fMult(pSpectralCoefficient[bin], fact_mantissa[band]); + } + + bottom = top; + } + } + + /* above topmost DRC band gain factor is 1 */ + if (max_exponent > 0) { + for (bin = bottom; bin < aacFrameSize; bin+=1) { + pSpectralCoefficient[bin] >>= max_exponent; + } + } + + /* adjust scaling */ + pSpecScale[0] += max_exponent; + + if (winSeq == EightShortSequence) { + int win; + for (win = 1; win < 8; win++) { + pSpecScale[win] += max_exponent; + } + } + } + else { + HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec; + UINT numBands = pDrcChData->numBands; + + /* feed factors into SBR decoder for application in QMF domain. */ + sbrDecoder_drcFeedChannel ( + hSbrDecoder, + ch, + numBands, + fact_mantissa, + max_exponent, + pDrcChData->drcInterpolationScheme, + winSeq, + pDrcChData->bandTop + ); + } + + return; +} + + +/* + * Prepare DRC processing + */ +int aacDecoder_drcProlog ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */ + int validChannels ) +{ + int err = 0; + + if (self == NULL) { + return -1; + } + + if (!self->params.bsDelayEnable) + { + err = aacDecoder_drcExtractAndMap ( + self, + hBs, + pAacDecoderStaticChannelInfo, + pceInstanceTag, + channelMapping, + validChannels ); + } + + return err; +} + + +/* + * Finalize DRC processing + */ +int aacDecoder_drcEpilog ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to canonical channel index */ + int validChannels ) +{ + int err = 0; + + if (self == NULL) { + return -1; + } + + if (self->params.bsDelayEnable) + { + err = aacDecoder_drcExtractAndMap ( + self, + hBs, + pAacDecoderStaticChannelInfo, + pceInstanceTag, + channelMapping, + validChannels ); + } + + return err; +} + +/* + * Export relevant metadata info from bitstream payload. + */ +void aacDecoder_drcGetInfo ( + HANDLE_AAC_DRC self, + SCHAR *pPresMode, + SCHAR *pProgRefLevel ) +{ + if (self != NULL) { + if (pPresMode != NULL) { + *pPresMode = self->presMode; + } + if (pProgRefLevel != NULL) { + if (self->progRefLevelPresent) { + *pProgRefLevel = self->progRefLevel; + } else { + *pProgRefLevel = -1; + } + } + } +} diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h new file mode 100644 index 00000000..c850aa50 --- /dev/null +++ b/libAACdec/src/aacdec_drc.h @@ -0,0 +1,189 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for AAC + +******************************************************************************/ + +#ifndef AACDEC_DRC_H +#define AACDEC_DRC_H + +#include "tp_data.h" /* for program config element support */ + + +#include "aacdec_drc_types.h" +#include "channel.h" +#include "FDK_bitstream.h" + +#define AACDEC_DRC_DFLT_EXPIRY_FRAMES ( 50 ) /* Default DRC data expiry time in AAC frames */ + +/** + * \brief DRC module setting parameters + */ +typedef enum +{ + DRC_CUT_SCALE = 0, + DRC_BOOST_SCALE, + TARGET_REF_LEVEL, + DRC_BS_DELAY, + DRC_DATA_EXPIRY_FRAME, + APPLY_NORMALIZATION, + APPLY_HEAVY_COMPRESSION + +} AACDEC_DRC_PARAM; + + +/** + * \brief DRC module interface functions + */ +void aacDecoder_drcInit ( + HANDLE_AAC_DRC self ); + +void aacDecoder_drcInitChannelData ( + CDrcChannelData *pDrcChannel ); + +AAC_DECODER_ERROR aacDecoder_drcSetParam ( + HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, + INT value ); + +int aacDecoder_drcMarkPayload ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + AACDEC_DRC_PAYLOAD_TYPE type ); + +int aacDecoder_drcProlog ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], + int numChannels ); + +/** + * \brief Apply DRC. If SBR is present, DRC data is handed over to the SBR decoder. + * \param self AAC decoder instance + * \param pSbrDec pointer to SBR decoder instance + * \param pAacDecoderChannelInfo AAC decoder channel instance to be processed + * \param pDrcDat DRC channel data + * \param extGain Pointer to a FIXP_DBL where a externally applyable gain will be stored into (independently on whether it will be apply internally or not). + * At function call the buffer must hold the scale (0 >= scale < DFRACT_BITS) to be applied on the gain value. + * \param ch channel index + * \param aacFrameSize AAC frame size + * \param bSbrPresent flag indicating that SBR is present, in which case DRC is handed over to the SBR instance pSbrDec + */ +void aacDecoder_drcApply ( + HANDLE_AAC_DRC self, + void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcDat, + FIXP_DBL *extGain, + int ch, + int aacFrameSize, + int bSbrPresent ); + +int aacDecoder_drcEpilog ( + HANDLE_AAC_DRC self, + HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], + int validChannels ); + +/** + * \brief Get metadata information found in bitstream. + * \param self DRC module instance handle. + * \param pPresMode Pointer to field where the presentation mode will be written to. + * \param pProgRefLevel Pointer to field where the program reference level will be written to. + * \return Nothing. + */ +void aacDecoder_drcGetInfo ( + HANDLE_AAC_DRC self, + SCHAR *pPresMode, + SCHAR *pProgRefLevel ); + + +#endif /* AACDEC_DRC_H */ diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h new file mode 100644 index 00000000..4c6d163a --- /dev/null +++ b/libAACdec/src/aacdec_drc_types.h @@ -0,0 +1,174 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Dynamic range control (DRC) global data types + +******************************************************************************/ + +#ifndef AACDEC_DRC_TYPES_H +#define AACDEC_DRC_TYPES_H + + + +#include "common_fix.h" + + #define MAX_DRC_THREADS ( 3 ) /* Heavy compression value is handled just like MPEG DRC data */ +#define MAX_DRC_BANDS ( 16 ) /* 2^LEN_DRC_BAND_INCR (LEN_DRC_BAND_INCR = 4) */ + +/** + * \brief DRC module global data types + */ +typedef enum +{ + UNKNOWN_PAYLOAD = 0, + MPEG_DRC_EXT_DATA = 1, + DVB_DRC_ANC_DATA = 2 + +} AACDEC_DRC_PAYLOAD_TYPE; + +typedef struct +{ + UINT expiryCount; + UINT numBands; + USHORT bandTop[MAX_DRC_BANDS]; + SHORT drcInterpolationScheme; + UCHAR drcValue[MAX_DRC_BANDS]; + SCHAR drcDataType; + +} CDrcChannelData; + +typedef struct +{ + UINT excludedChnsMask; + SCHAR progRefLevel; + SCHAR presMode; /* Presentation mode: 0 (not indicated), 1, 2, and 3 (reserved). */ + SCHAR pceInstanceTag; + + CDrcChannelData channelData; + +} CDrcPayload; + +typedef struct +{ + FIXP_DBL cut; /* The attenuation scale factor currently used. */ + FIXP_DBL usrCut; /* The latest attenuation scale factor set by user. */ + FIXP_DBL boost; /* The boost scale factor currently used. */ + FIXP_DBL usrBoost; /* The latest boost scale factor set by user. */ + + UINT expiryFrame; + SCHAR targetRefLevel; + UCHAR bsDelayEnable; + UCHAR applyDigitalNorm; + UCHAR applyHeavyCompression; + +} CDrcParams; + + +typedef struct +{ + CDrcParams params; /* Module parameters that can be set by user (via SetParam API function) */ + + UCHAR enable; /* Switch that controls dynamic range processing */ + UCHAR digitalNorm; /* Switch to en-/disable reference level normalization in digital domain */ + + USHORT numPayloads; /* The number of DRC data payload elements found within frame */ + USHORT numThreads; /* The number of DRC data threads extracted from the found payload elements */ + SCHAR progRefLevel; /* Program reference level for all channels */ + UCHAR progRefLevelPresent; /* Program reference level found in bitstream */ + + UINT prlExpiryCount; /* Counter that can be used to monitor the life time of the program reference level. */ + + SCHAR presMode; /* Presentation mode as defined in ETSI TS 101 154 */ + UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data is present or not */ + UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload position in the bitstream (only one per frame) */ + UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload positions in the bitstream */ + +} CDrcInfo; + +typedef CDrcInfo *HANDLE_AAC_DRC; + +#endif /* AACDEC_DRC_TYPES_H */ + diff --git a/libAACdec/src/aacdec_hcr.cpp b/libAACdec/src/aacdec_hcr.cpp new file mode 100644 index 00000000..e314e277 --- /dev/null +++ b/libAACdec/src/aacdec_hcr.cpp @@ -0,0 +1,1591 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo, + decode priority codewords (PCWs) + +*******************************************************************************/ + +#include "aacdec_hcr.h" + + + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr_bit.h" +#include "aacdec_hcrs.h" +#include "aac_ram.h" +#include "aac_rom.h" +#include "channel.h" +#include "block.h" + +#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */ +#include "FDK_bitstream.h" + +extern int mlFileChCurr; + +static void errDetectorInHcrSideinfoShrt(SCHAR cb, + SHORT numLine, + UINT *errorWord); + +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord); + +static void HcrCalcNumCodeword (H_HCR_INFO pHcr); +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr); +static void HcrPrepareSegmentationGrid (H_HCR_INFO pHcr); +static void HcrExtendedSectionInfo (H_HCR_INFO pHcr); + +static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment, + USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx); + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, + INT quantSpecCoef, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, + UINT codebookDim, + const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, + int *quantSpecCoefIdx, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ); + +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr); + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo + ); + + +#if CHECK_SEGMENTATION_IMMEDIATELY +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, + PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension); +#endif + +#if CHECK_SEGMENTATION_FINAL +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr); +#endif + +/*--------------------------------------------------------------------------------------------- + description: Check if codebook and numSect are within allowed range (short only) +-------------------------------------------------------------------------------------------- */ +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine,UINT* errorWord) +{ + + + + if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) { + *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK; + } + if ( numLine < 0 || numLine > 1024 ) { + *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Check both HCR lengths +-------------------------------------------------------------------------------------------- */ +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord) +{ + if ( lengthOfReorderedSpectralData < lengthOfLongestCodeword ) { + *errorWord |= HCR_SI_LENGTHS_FAILURE; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Decode (and adapt if necessary) the two HCR sideinfo components: + 'reordered_spectral_data_length' and 'longest_codeword_length' +-------------------------------------------------------------------------------------------- */ + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + INT globalHcrType = getHcrType(&pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo); + SHORT lengOfReorderedSpectralData; + SCHAR lengOfLongestCodeword; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = 0; + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0; + + + + /* ------- SI-Value No 1 ------- */ + lengOfReorderedSpectralData = FDKreadBits(bs,14) + ERROR_LORSD; + if ( globalHcrType == ID_CPE ) { + if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */ + } + else { + if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = CPE_TOP_LENGTH; /* use valid maximum */ + } + } + } + else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE || globalHcrType == ID_CCE ) { + if ((lengOfReorderedSpectralData >= 0) && (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = lengOfReorderedSpectralData; /* the decoded value is within range */ + } + else { + if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = SCE_TOP_LENGTH; /* use valid maximum */ + } + } + } + + /* ------- SI-Value No 2 ------- */ + lengOfLongestCodeword = FDKreadBits(bs,6) + ERROR_LOLC; + if ((lengOfLongestCodeword >= 0) && (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = lengOfLongestCodeword; /* the decoded value is within range */ + } + else { + if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */ + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Sets up HCR ROM-Tables +-------------------------------------------------------------------------------------------- */ + +void HcrInitRom(H_HCR_INFO pHcr) +{ + pHcr->cbPairs.pMinOfCbPair = aMinOfCbPair; + pHcr->cbPairs.pMaxOfCbPair = aMaxOfCbPair; + + pHcr->tableInfo.pMaxCwLength = aMaxCwLen; + pHcr->tableInfo.pCbDimension = aDimCb; + pHcr->tableInfo.pCbDimShift = aDimCbShift; + pHcr->tableInfo.pCbSign = aSignCb; + pHcr->tableInfo.pCbPriority = aCbPriority; + pHcr->tableInfo.pLargestAbsVal = aLargestAbsoluteValue; +} + +/*--------------------------------------------------------------------------------------------- + description: Set up HCR - must be called before every call to HcrDecoder(). + For short block a sorting algorithm is applied to get the SI in the order + that HCR could assemble the qsc's as if it is a long block. +----------------------------------------------------------------------------------------------- + return: error log +-------------------------------------------------------------------------------------------- */ + +UINT HcrInit(H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) +{ + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pNumLinesInSec; + UCHAR *pCodeBk; + SHORT numSection; + SCHAR cb; + int numLine; + int i; + + pHcr->decInOut.lengthOfReorderedSpectralData = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData; + pHcr->decInOut.lengthOfLongestCodeword = pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword; + pHcr->decInOut.pQuantizedSpectralCoefficientsBase = pAacDecoderChannelInfo->pSpectralCoefficient; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0; + pHcr->decInOut.pCodebook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + pHcr->decInOut.pNumLineInSect = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + pHcr->decInOut.numSection = pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection; + pHcr->decInOut.errorLog = 0; + pHcr->nonPcwSideinfo.pResultBase = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + + FDKsyncCache(bs); + pHcr->decInOut.bitstreamIndex = FDKgetBitCnt(bs); + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */ + { + SHORT band; + SHORT maxBand; + SCHAR group; + SCHAR winGroupLen; + SCHAR window; + SCHAR numUnitInBand; + SCHAR cntUnitInBand; + SCHAR groupWin; + SCHAR cb_prev; + + UCHAR *pCodeBook; + const SHORT *BandOffsets; + SCHAR numOfGroups; + + + pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */ + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */ + pCodeBk = pHcr->decInOut.pCodebook; /* out */ + BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */ + numOfGroups = GetWindowGroups(pIcsInfo); + + numLine = 0; + numSection = 0; + cb = pCodeBook[0]; + cb_prev = pCodeBook[0]; + + /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new section starts */ + + *pCodeBk++ = cb_prev; + + maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (band = 0; band < maxBand; band++) { /* from low to high sfbs i.e. from low to high frequencies */ + numUnitInBand = ((BandOffsets[band+1] - BandOffsets[band]) >> FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */ + for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0; cntUnitInBand-- ) { /* for every unit in the band */ + for (window = 0, group = 0; group < numOfGroups; group++) { + winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) { + cb = pCodeBook[group * 16 + band]; + if (cb != cb_prev) { +#if CHECK_VALID_HCR_INPUT /* short-block 1 of 2 */ + errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog ); + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif + *pCodeBk++ = cb; + *pNumLinesInSec++ = numLine; + numSection++; + + cb_prev = cb; + numLine = LINES_PER_UNIT; + } + else { + numLine += LINES_PER_UNIT; + } + } + } + } + } + + numSection++; + +#if CHECK_VALID_HCR_INPUT /* short-block 2 of 2 */ + errDetectorInHcrSideinfoShrt(cb,numLine,&pHcr->decInOut.errorLog ); + if ( numSection <= 0 || numSection > 1024/2 ) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif + + *pCodeBk = cb; + *pNumLinesInSec = numLine; + pHcr->decInOut.numSection = numSection; + + } else /* end short block prepare SI */ + { /* long block */ +#if CHECK_VALID_HCR_INPUT /* long-block 1 of 1 */ + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + numSection = pHcr->decInOut.numSection; + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; + pCodeBk = pHcr->decInOut.pCodebook; + if ( numSection <= 0 || numSection > 64 ) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK; + numSection = 0; + } + + for ( i = numSection; i != 0; i-- ) + { + cb = *pCodeBk++; + + if ( cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL ) { + pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK; + } + + numLine = *pNumLinesInSec++; + /* FDK_ASSERT(numLine > 0); */ + + if ( (numLine <= 0) || (numLine > 1024) ) { + pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK; + } + } + if (pHcr->decInOut.errorLog != 0 ) { + return ( pHcr->decInOut.errorLog ); + } +#endif /* CHECK_VALID_HCR_INPUT */ + } + + pCodeBk = pHcr->decInOut.pCodebook; + for ( i = 0; i < numSection; i++ ) { + if ( + (*pCodeBk == NOISE_HCB) || + (*pCodeBk == INTENSITY_HCB2) || + (*pCodeBk == INTENSITY_HCB)) + { + *pCodeBk = 0; + } + pCodeBk++; + } + + /* HCR-sideinfo-input is complete and seems to be valid */ + + + + return ( pHcr->decInOut.errorLog ); +} + + + + +#if USE_HCR_DUMMY + +/*--------------------------------------------------------------------------------------------- + + description: This HCR - dummy - function writes only a dirac-sequence in output buffer + +-------------------------------------------------------------------------------------------- */ +UINT HcrDecoder(H_HCR_INFO pHcr, + const CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + for (SHORT i=0; i < 1024; i++ ) { + pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = FL2FXCONST_DBL(0.0f); + if ( i % 30 == 0) { + pHcr->decInOut.pQuantizedSpectralCoefficients->Long[i] = (FIXP_DBL)HCR_DIRAC; + } + } + return 0; +} + +#else /* USE_HCR_DUMMY */ + +/*--------------------------------------------------------------------------------------------- + description: This function decodes the codewords of the spectral coefficients from the + bitstream according to the HCR algorithm and stores the quantized spectral + coefficients in correct order in the output buffer. +-------------------------------------------------------------------------------------------- */ + +UINT HcrDecoder(H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) +{ + int pTmp1, pTmp2, pTmp3, pTmp4; +#if DETECT_TOO_LONG_CW_READS + int pTmp5; +#endif + + INT bitCntOffst; + UINT saveBitCnt = FDKgetBitCnt(bs); /* save bitstream position */ + + HcrCalcNumCodeword(pHcr); + + HcrSortCodebookAndNumCodewordInSection(pHcr); + + HcrPrepareSegmentationGrid(pHcr); + + HcrExtendedSectionInfo(pHcr); + + if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) != 0 ) { + return ( pHcr->decInOut.errorLog ); /* sideinfo is massively corrupt, return from HCR without having decoded anything */ + } + + DeriveNumberOfExtendedSortedSectionsInSets(pHcr->segmentInfo.numSegment, + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection, + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx, + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets, + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx); + + /* store */ + pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx; + pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx; +#if DETECT_TOO_LONG_CW_READS + pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; +#endif + + /* ------- decode meaningful PCWs ------ */ + DecodePCWs(bs, pHcr); + + if (( pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK ) == 0 ) { + /* ------ decode the non-PCWs -------- */ + DecodeNonPCWs(bs, pHcr); + } + + +#if CHECK_SEGMENTATION_FINAL + errDetectWithinSegmentationFinal(pHcr); +#endif + + /* restore */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1; + pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4; +#if DETECT_TOO_LONG_CW_READS + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5; +#endif + + HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, pSamplingRateInfo); + + /* restore bitstream position */ + bitCntOffst = saveBitCnt - FDKgetBitCnt(bs); + if( bitCntOffst ) { + FDKpushBiDirectional(bs, bitCntOffst); + } + + return ( pHcr->decInOut.errorLog ); +} + + +#endif /* USE_HCR_DUMMY */ + + + + +/*--------------------------------------------------------------------------------------------- + description: This function reorders the quantized spectral coefficients sectionwise for + long- and short-blocks and compares to the LAV (Largest Absolute Value of + the current codebook) -- a counter is incremented if there is an error + detected. + Additional for short-blocks a unit-based-deinterleaving is applied. + Moreover (for short blocks) the scaling is derived (compare plain huffman + decoder). +-------------------------------------------------------------------------------------------- */ + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo + ) +{ + INT qsc; + UINT abs_qsc; + UINT i,j; + USHORT numSpectralValuesInSection; + FIXP_DBL *pTeVa; + USHORT lavErrorCnt = 0; + + UINT numSection = pHcr->decInOut.numSection; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase = pHcr->decInOut.pQuantizedSpectralCoefficientsBase; + FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + const USHORT *pLargestAbsVal = pHcr->tableInfo.pLargestAbsVal; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + FIXP_DBL *pTempValues = pHcr->segmentInfo.pTempValues; + FIXP_DBL *pBak = pHcr->segmentInfo.pTempValues; + + FDKmemclear(pTempValues,1024*sizeof(FIXP_DBL)); + + /* long and short: check if decoded huffman-values (quantized spectral coefficients) are within range */ + for ( i=numSection; i != 0; i-- ) { + numSpectralValuesInSection = *pNumSortedCodewordInSection++ << pCbDimShift[*pSortedCodebook]; + pTeVa = &pTempValues[*pReorderOffset++]; + for( j = numSpectralValuesInSection; j != 0; j-- ) { + qsc = *pQuantizedSpectralCoefficients++; + abs_qsc = FDKabs(qsc); +#if VALID_LAV_ERROR_TRIGGER + if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) { + *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */ + } + else { /* line is too high .. */ + if ( abs_qsc == Q_VALUE_INVALID ) { /* .. because of previous marking --> dont set LAV flag (would be confusing), just copy out the already marked value */ + *pTeVa++ = (FIXP_DBL) qsc; + } + else { /* .. because a too high value was decoded for this cb --> set LAV flag */ + *pTeVa++ = (FIXP_DBL) Q_VALUE_INVALID; + lavErrorCnt += 1; + } + } +#else + if ( abs_qsc <= pLargestAbsVal[*pSortedCodebook] ) { + *pTeVa++ = qsc; + } + else { + *pTeVa++ = Q_VALUE_INVALID; + lavErrorCnt += 1; + } +#endif + } + pSortedCodebook++; + } + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) + { + FIXP_DBL *pOut; + FIXP_DBL locMax; + FIXP_DBL tmp; + SCHAR groupoffset; + SCHAR group; + SCHAR band; + SCHAR groupwin; + SCHAR window; + SCHAR numWinGroup; + SHORT interm; + SCHAR numSfbTransm; + SCHAR winGroupLen; + SHORT index; + INT msb; + INT lsb; + + SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor; + SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale; + const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + pBak = pHcr->segmentInfo.pTempValues; + /* deinterleave unitwise for short blocks */ + for ( window = 0; window < (8); window++ ) { + pOut = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength); + for ( i=0; i < (LINES_PER_UNIT_GROUP); i++ ) { + pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) + i * 32; /* distance of lines between unit groups has to be constant for every framelength (32)! */ + for ( j=(LINES_PER_UNIT); j != 0; j-- ) { + *pOut++ = *pTeVa++; + } + } + } + + /* short blocks only */ + /* derive global scaling-value for every sfb and every window (as it is done in plain-huffman-decoder at short blocks) */ + groupoffset = 0; + + numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + numSfbTransm = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < numWinGroup; group++) { + winGroupLen = GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + for (band = 0; band < numSfbTransm; band++) { + interm = group * 16 + band; + msb = pScaleFacHcr[interm] >> 2; + lsb = pScaleFacHcr[interm] & 3; + for (groupwin = 0; groupwin < winGroupLen; groupwin++) { + window = groupoffset + groupwin; + pBak = SPEC(pQuantizedSpectralCoefficientsBase, window, pAacDecoderChannelInfo->granuleLength); + locMax = FL2FXCONST_DBL(0.0f); + for (index = BandOffsets[band]; index < BandOffsets[band+1]; index += LINES_PER_UNIT) { + pTeVa = &pBak[index]; + for ( i = LINES_PER_UNIT; i != 0; i --) { + tmp = (*pTeVa < FL2FXCONST_DBL(0.0f))? -*pTeVa++ : *pTeVa++; + locMax = fixMax(tmp,locMax); + } + } + if ( fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE ) { + locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE; + } + pSfbSclHcr[window*16+band] = msb - GetScaleFromValue(locMax, lsb); /* save global scale maxima in this sfb */ + } + } + groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + } + } else + { + /* copy straight for long-blocks */ + pQuantizedSpectralCoefficients = SPEC_LONG(pQuantizedSpectralCoefficientsBase); + for ( i = 1024; i != 0; i-- ) { + *pQuantizedSpectralCoefficients++ = *pBak++; + } + } + + if ( lavErrorCnt != 0 ) { + pHcr->decInOut.errorLog |= LAV_VIOLATION; + } +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of codewords + for each section (numCodewordInSection) and the number of codewords + for all sections (numCodeword). + For zero and intensity codebooks a entry is also done in the variable + numCodewordInSection. It is assumed that the codebook is a two tuples + codebook. This is needed later for the calculation of the base addresses + for the reordering of the quantize spectral coefficients at the end of the + hcr tool. + The variable numCodeword contain the number of codewords which are really + in the bitstream. Zero or intensity codebooks does not increase the + variable numCodewords. +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr) +{ + int hcrSection; + UINT numCodeword; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect; + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + + numCodeword = 0; + for ( hcrSection = numSection; hcrSection != 0; hcrSection-- ) { + *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook]; + if ( *pCodebook != 0 ) { + numCodeword += *pNumCodewordInSection; + } + pNumCodewordInSection++; + pCodebook++; + } + pHcr->sectionInfo.numCodeword = numCodeword; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number + of sorted codebooks and sorts the codebooks and the numCodewordInSection + according to the priority. +-------------------------------------------------------------------------------------------- */ + +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr) +{ + + UINT i,j,k; + UCHAR temp; + UINT counter; + UINT startOffset; + UINT numZeroSection; + UCHAR *pDest; + UINT numSectionDec; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + const UCHAR *pCbPriority = pHcr->tableInfo.pCbPriority; + const UCHAR *pMinOfCbPair = pHcr->cbPairs.pMinOfCbPair; + const UCHAR *pMaxOfCbPair = pHcr->cbPairs.pMaxOfCbPair; + const UCHAR *pCbDimShift = pHcr->tableInfo.pCbDimShift; + + UINT searchStart = 0; + + /* calculate *pNumSortedSection and store the priorities in array pSortedCdebook */ + pDest = pSortedCodebook; + numZeroSection = 0; + for ( i=numSection; i != 0; i-- ) { + if ( pCbPriority[*pCodebook] == 0 ) { + numZeroSection += 1; + } + *pDest++ = pCbPriority[*pCodebook++]; + } + pHcr->sectionInfo.numSortedSection = numSection - numZeroSection; /* numSortedSection contains no zero or intensity section */ + pCodebook = pHcr->decInOut.pCodebook; + + /* sort priorities of the codebooks in array pSortedCdebook[] */ + numSectionDec = numSection - 1; + if ( numSectionDec > 0 ) { + counter = numSectionDec; + for ( j=numSectionDec; j != 0; j-- ) { + for ( i=0; i < counter; i++ ) { + /* swap priorities */ + if ( pSortedCodebook[i+1] > pSortedCodebook[i] ) { + temp = pSortedCodebook[i]; + pSortedCodebook[i] = pSortedCodebook[i+1]; + pSortedCodebook[i+1] = temp; + } + } + counter -= 1; + } + } + + /* clear codebookSwitch array */ + for ( i = numSection; i != 0; i--) { + *pCodebookSwitch++ = 0; + } + pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + + /* sort sectionCodebooks and numCodwordsInSection and calculate pReorderOffst[j] */ + for ( j = 0; j < numSection; j++ ) { + for ( i = searchStart; i < numSection; i++ ) { + if ( pCodebookSwitch[i] == 0 && ( pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] || pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i] )) { + pCodebookSwitch[i] = 1; + pSortedCodebook[j] = pCodebook[i]; /* sort codebook */ + pNumSortedCodewordInSection[j] = pNumCodewordInSection[i]; /* sort NumCodewordInSection */ + + startOffset = 0; + for ( k = 0; k < i; k++ ) { /* make entry in pReorderOffst */ + startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]]; + } + pReorderOffset[j] = startOffset; /* offset for reordering the codewords */ + + if(i == searchStart) { + UINT k = i; + while(pCodebookSwitch[k++] == 1) searchStart++; + } + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the segmentation, which includes numSegment, + leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment. + The segmentation could be visualized a as kind of 'overlay-grid' for the + bitstream-block holding the HCR-encoded quantized-spectral-coefficients. +-------------------------------------------------------------------------------------------- */ + +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr) +{ + USHORT i,j; + USHORT numSegment = 0; + USHORT segmentStart = 0; + UCHAR segmentWidth; + UCHAR lastSegmentWidth; + UCHAR sortedCodebook; + UCHAR endFlag = 0; + USHORT intermediateResult; + + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + SHORT lengthOfReorderedSpectralData = pHcr->decInOut.lengthOfReorderedSpectralData; + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + USHORT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + USHORT bitstreamIndex = pHcr->decInOut.bitstreamIndex; + const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength; + + for ( i=numSortedSection; i != 0; i-- ) { + sortedCodebook = *pSortedCodebook++; + segmentWidth = FDKmin(pMaxCwLength[sortedCodebook],lengthOfLongestCodeword); + + for ( j = *pNumSortedCodewordInSection; j != 0 ; j-- ) { + /* width allows a new segment */ + intermediateResult = bitstreamIndex + segmentStart; + if ( (segmentStart + segmentWidth) <= lengthOfReorderedSpectralData ) { + /* store segment start, segment length and increment the number of segments */ + *pLeftStartOfSegment++ = intermediateResult; + *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1; + *pRemainingBitsInSegment++ = segmentWidth; + segmentStart += segmentWidth; + numSegment += 1; + } + /* width does not allow a new segment */ + else { + /* correct the last segment length */ + pLeftStartOfSegment--; + pRightStartOfSegment--; + pRemainingBitsInSegment--; + segmentStart = *pLeftStartOfSegment - bitstreamIndex; + + lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart; + *pRemainingBitsInSegment = lastSegmentWidth; + *pRightStartOfSegment = bitstreamIndex + segmentStart + lastSegmentWidth - 1; + endFlag = 1; + break; + } + } + pNumSortedCodewordInSection++; + if (endFlag != 0) { + break; + } + } + pHcr->segmentInfo.numSegment = numSegment; + +} + + +/*--------------------------------------------------------------------------------------------- + description: This function adapts the sorted section boundaries to the boundaries of + segmentation. If the section lengths does not fit completely into the + current segment, the section is spitted into two so called 'extended + sections'. The extended-section-info (pNumExtendedSortedCodewordInSectin + and pExtendedSortedCodebook) is updated in this case. + +-------------------------------------------------------------------------------------------- */ + +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr) +{ + UINT srtSecCnt = 0; /* counter for sorted sections */ + UINT xSrtScCnt = 0; /* counter for extended sorted sections */ + UINT remainNumCwInSortSec; + UINT inSegmentRemainNumCW; + + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook; + USHORT *pNumExtSortCwInSect = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + UINT numSegment = pHcr->segmentInfo.numSegment; +#if DETECT_TOO_LONG_CW_READS + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + const UCHAR *pMaxCwLength = pHcr->tableInfo.pMaxCwLength; +#endif + + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + + while (srtSecCnt < numSortedSection) { + if (inSegmentRemainNumCW < remainNumCwInSortSec) { + + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + remainNumCwInSortSec -= inSegmentRemainNumCW; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was not integrated in extended sorted section */ + } + else if (inSegmentRemainNumCW == remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was integrated in extended sorted section */ + } + else { /* inSegmentRemainNumCW > remainNumCwInSortSec */ + pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + + inSegmentRemainNumCW -= remainNumCwInSortSec; + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + /* data of a sorted section was integrated in extended sorted section */ + } +#if DETECT_TOO_LONG_CW_READS + pMaxLenOfCbInExtSrtSec[xSrtScCnt] = FDKmin(pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]],lengthOfLongestCodeword); +#endif + + + + xSrtScCnt += 1; + + if ( xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS) ) { + pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW; + return; + } + + } + pNumExtSortCwInSect[xSrtScCnt] = 0; + +} + + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of extended sorted sections which + belong to the sets. Each set from set 0 (one and only set for the PCWs) + till to the last set gets a entry in the array to which + 'pNumExtendedSortedSectinsInSets' points to. + + Calculation: The entrys in pNumExtendedSortedCodewordInSectin are added + untill the value numSegment is reached. Then the sum_variable is cleared + and the calculation starts from the beginning. As much extended sorted + Sections are summed up to reach the value numSegment, as much is the + current entry in *pNumExtendedSortedCodewordInSectin. +-------------------------------------------------------------------------------------------- */ +static void DeriveNumberOfExtendedSortedSectionsInSets(UINT numSegment, + USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx) +{ + USHORT counter = 0; + UINT cwSum = 0; + USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection; + USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets; + + while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0) + { + cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx]; + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + if (cwSum > numSegment) { + return; + } + counter++; + if (counter > 1024/4) { + return; + } + if ( cwSum == numSegment ) { + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + counter = 0; + cwSum = 0; + } + } + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; /* save last entry for the last - probably shorter - set */ +} + + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all priority codewords (PCWs) in a spectrum (within + set 0). The calculation of the PCWs is managed in two loops. The + loopcounter of the outer loop is set to the first value pointer + pNumExtendedSortedSectionsInSets points to. This value represents the + number of extended sorted sections within set 0. + The loopcounter of the inner loop is set to the first value pointer + pNumExtendedSortedCodewordInSectin points to. The value represents the + number of extended sorted codewords in sections (the original sections have + been splitted to go along with the borders of the sets). + Each time the number of the extended sorted codewords in sections are de- + coded, the pointer 'pNumExtendedSortedCodewordInSectin' is incremented by + one. +-------------------------------------------------------------------------------------------- */ +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) +{ + UINT i; + USHORT extSortSec; + USHORT curExtSortCwInSec; + UCHAR codebook; + UCHAR dimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + USHORT *pNumExtendedSortedCodewordInSection = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + int quantizedSpectralCoefficientsIdx = pHcr->decInOut.quantizedSpectralCoefficientsIdx; + USHORT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; +#if DETECT_TOO_LONG_CW_READS + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + UCHAR maxAllowedCwLen; + int numDecodedBits; +#endif + const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension; + const UCHAR *pCbSign = pHcr->tableInfo.pCbSign; + + /* clear result array */ + //pQSC = &pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]; + //pQSC = *pQuantizedSpectralCoefficients; + + FDKmemclear(pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx,1024*sizeof(FIXP_DBL)); + + /* decode all PCWs in the extended sorted section(s) belonging to set 0 */ + for ( extSortSec = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; extSortSec != 0; extSortSec-- ) { + + codebook = pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for this extended sorted section and increment ptr to cb of next ext. sort sec */ + extendedSortedCodebookIdx++; + if (extendedSortedCodebookIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + dimension = pCbDimension[codebook]; /* get dimension of codebook of this extended sort. sec. */ + pCurrentTree = aHuffTable [codebook]; /* convert codebook to pointer to QSCs */ + pQuantValBase = aQuantTable [codebook]; /* convert codebook to index to table of QSCs */ +#if DETECT_TOO_LONG_CW_READS + maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx]; + maxLenOfCbInExtSrtSecIdx++; + if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } +#endif + + /* switch for decoding with different codebooks: */ + if ( pCbSign[codebook] == 0 ) { /* no sign bits follow after the codeword-body */ + /* PCW_BodyONLY */ + /*==============*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) { + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + /* result is written out here because NO sign bits follow the body */ + for( i=dimension; i != 0 ; i-- ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) *pQuantVal++; /* write quant. spec. coef. into spectrum; sign is already valid */ + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY,pHcr,PCW_BODY,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) { + return; + } +#endif + pLeftStartOfSegment++; /* update pointer for decoding the next PCW */ + pRemainingBitsInSegment++; /* update pointer for decoding the next PCW */ + } + } + else if (( pCbSign[codebook] == 1 ) && ( codebook < 11 )) { /* possibly there follow 1,2,3 or 4 sign bits after the codeword-body */ + /* PCW_Body and PCW_Sign */ + /*=======================*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) + { + int err; + numDecodedBits = 0; + + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + err = DecodePCW_Sign( bs, + dimension, + pQuantVal, + pQuantizedSpectralCoefficients, + &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + if (err != 0) { + return; + } + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN,pHcr,PCW_BODY_SIGN, pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-dimension,dimension)) { + return; + } +#endif + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + else if (( pCbSign[codebook] == 1 ) && ( codebook >= 11 )) { /* possibly there follow some sign bits and maybe one or two escape sequences after the cw-body */ + /* PCW_Body, PCW_Sign and maybe PCW_Escape */ + /*=========================================*/ + + for ( curExtSortCwInSec = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx] ; curExtSortCwInSec != 0; curExtSortCwInSec--) + { + int err; + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body(bs, + pCurrentTree, + pQuantValBase, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + + err = DecodePCW_Sign( bs, + dimension, + pQuantVal, + pQuantizedSpectralCoefficients, + &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + if (err != 0) { + return; + } + + /* decode PCW_ESCAPE if present */ + quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK; + + if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs, + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + if ( fixp_abs(pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx]) == (FIXP_DBL)ESCAPE_VALUE ) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = (FIXP_DBL) DecodeEscapeSequence( bs, + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, + pRemainingBitsInSegment, + &numDecodedBits + ); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + /* one more PCW should be decoded */ + +#if DETECT_TOO_LONG_CW_READS + if ( maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG) ) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED; + } +#endif + +#if CHECK_SEGMENTATION_IMMEDIATELY + if (1 == errDetectPcwSegmentation(*pRemainingBitsInSegment-ERROR_PCW_BODY_SIGN_ESC,pHcr,PCW_BODY_SIGN_ESC,pQuantizedSpectralCoefficients+quantizedSpectralCoefficientsIdx-DIMENSION_OF_ESCAPE_CODEBOOK,DIMENSION_OF_ESCAPE_CODEBOOK)) { + return; + } +#endif + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + + /* all PCWs belonging to this extended section should be decoded */ + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR+MAX_HCR_SETS) { + return; + } + } + /* all PCWs should be decoded */ + + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + + /* Write back indexes into structure */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = numExtendedSortedSectionsInSetsIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = quantizedSpectralCoefficientsIdx; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx; +} + +#if CHECK_SEGMENTATION_IMMEDIATELY +/*--------------------------------------------------------------------------------------------- + description: This function checks immediately after every decoded PCW, whether out of + the current segment too many bits have been read or not. If an error occurrs, + probably the sideinfo or the HCR-bitstream block holding the huffman + encoded quantized spectral coefficients is distorted. In this case the two + or four quantized spectral coefficients belonging to the current codeword + are marked (for being detected by concealment later). +-------------------------------------------------------------------------------------------- */ +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, + PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension) +{ + SCHAR i; + if ( remainingBitsInSegment < 0 ) { + /* log the error */ + switch (kind) { + case PCW_BODY: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY; + break; + case PCW_BODY_SIGN: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN; + break; + case PCW_BODY_SIGN_ESC: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC; + break; + } + /* mark the erred lines */ + for ( i = dimension; i != 0; i-- ) { + *qsc_base_of_cw++ = (FIXP_DBL) Q_VALUE_INVALID; + } + return 1; + } + return 0; +} +#endif + +#if CHECK_SEGMENTATION_FINAL +/*--------------------------------------------------------------------------------------------- + description: This function checks if all segments are empty after decoding. There + are _no lines markded_ as invalid because it could not be traced back + where from the remaining bits are. +-------------------------------------------------------------------------------------------- */ +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr) +{ + UCHAR segmentationErrorFlag = 0; + USHORT i; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UINT numSegment = pHcr->segmentInfo.numSegment; + + for ( i=numSegment; i != 0 ; i--) { + if (*pRemainingBitsInSegment++ != 0) { + segmentationErrorFlag = 1; + } + } + if (segmentationErrorFlag == 1) { + pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR; + } +} +#endif + +/*--------------------------------------------------------------------------------------------- + description: This function walks one step within the decoding tree. Which branch is + taken depends on the decoded carryBit input parameter. +-------------------------------------------------------------------------------------------- */ +void CarryBitToBranchValue(UCHAR carryBit, + UINT treeNode, + UINT *branchValue, + UINT *branchNode) +{ + if (carryBit == 0) { + *branchNode = (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */ + } + else { + *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */ + } + + *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */ +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a priority codeword (PCW) +----------------------------------------------------------------------------------------------- + return: - return value is pointer to first of two or four quantized spectral + coefficients +-------------------------------------------------------------------------------------------- */ +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UCHAR carryBit; + UINT branchNode; + UINT treeNode; + UINT branchValue; + const SCHAR *pQuantVal; + + /* decode PCW_BODY */ + treeNode = *pCurrentTree; /* get first node of current tree belonging to current codebook */ + + /* decode whole PCW-codeword-body */ + while (1) { + + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + CarryBitToBranchValue(carryBit, + treeNode, + &branchValue, + &branchNode); + + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */ + break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded */ + } + else { + treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */ + } + + } + + pQuantVal = pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4 quantized values */ + + return pQuantVal; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function decodes one escape sequence. In case of a escape codebook + and in case of the absolute value of the quantized spectral value == 16, + a escapeSequence is decoded in two steps: + 1. escape prefix + 2. escape word +-------------------------------------------------------------------------------------------- */ + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, + INT quantSpecCoef, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UINT i; + INT sign; + UINT escapeOnesCounter = 0; + UINT carryBit; + INT escape_word = 0; + + /* decode escape prefix */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + if (carryBit != 0) { + escapeOnesCounter += 1; + } + else { + escapeOnesCounter += 4; + break; + } + } + + /* decode escape word */ + for( i=escapeOnesCounter; i != 0 ; i-- ) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + escape_word <<= 1; + escape_word = escape_word | carryBit; + } + + sign = (quantSpecCoef >= 0) ? 1 : -1; + + quantSpecCoef = sign * (((INT ) 1 << escapeOnesCounter) + escape_word); + + return quantSpecCoef; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the Signbits of a priority codeword (PCW) and writes out the + resulting quantized spectral values into unsorted sections +----------------------------------------------------------------------------------------------- + output: - two or four lines at position in corresponding section (which are not + located at the desired position, i.e. they must be reordered in the last + of eight function of HCR) +----------------------------------------------------------------------------------------------- + return: - updated pQuantSpecCoef pointer (to next empty storage for a line) +-------------------------------------------------------------------------------------------- */ +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, + UINT codebookDim, + const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, + int *quantSpecCoefIdx, + USHORT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits + ) +{ + UINT i; + UINT carryBit; + INT quantSpecCoef; + + for( i=codebookDim; i != 0 ; i-- ) { + quantSpecCoef = *pQuantVal++; + if (quantSpecCoef != 0) { + carryBit = HcrGetABitFromBitstream(bs, + pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024>>1)) { + return -1; + } + + /* adapt sign of values according to the decoded sign bit */ + if (carryBit != 0) { + pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef; + } + else { + pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef; + } + } + else { + pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f); + } + *quantSpecCoefIdx += 1 ; + if (*quantSpecCoefIdx >= 1024) { + return -1; + } + } + return 0; +} + + +/*--------------------------------------------------------------------------------------------- + description: Mutes spectral lines which have been marked as erroneous (Q_VALUE_INVALID) +-------------------------------------------------------------------------------------------- */ +void HcrMuteErroneousLines(H_HCR_INFO hHcr) +{ + int c; + FIXP_DBL *RESTRICT pLong = SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase); + + /* if there is a line with value Q_VALUE_INVALID mute it */ + for (c = 0; c < 1024; c++) { + if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) { +#if HCR_LISTEN_TO_MUTED_LINES + pLong[c] = (FIXP_DBL)HCR_DIRAC; /* marking */ +#else + pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */ +#endif + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Sets global HCR type +-------------------------------------------------------------------------------------------- */ +void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type) +{ + switch (type) { + case ID_SCE: + hHcr->globalHcrType = 0; + break; + case ID_CPE: + hHcr->globalHcrType = 1; + break; + default: + break; + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Gets HCR type from the HCR data structure +----------------------------------------------------------------------------------------------- + return: - global HCR type +-------------------------------------------------------------------------------------------- */ +INT getHcrType(H_HCR_INFO hHcr) +{ + return hHcr->globalHcrType; +} + + + + diff --git a/libAACdec/src/aacdec_hcr.h b/libAACdec/src/aacdec_hcr.h new file mode 100644 index 00000000..6fc527bc --- /dev/null +++ b/libAACdec/src/aacdec_hcr.h @@ -0,0 +1,126 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Interface function declaration; common defines + and structures; defines for switching error-generator, + -detector, and -concealment + +*******************************************************************************/ + +#ifndef _AACDEC_HCR_H_ +#define _AACDEC_HCR_H_ + + + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +void HcrInitRom (H_HCR_INFO hHcr); +UINT HcrInit(H_HCR_INFO pHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +UINT HcrDecoder (H_HCR_INFO hHcr, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +void CarryBitToBranchValue( + UCHAR carryBit, + UINT treeNode, + UINT *branchValue, + UINT *branchNode + ); + +void CHcr_Read (HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo); +void HcrMuteErroneousLines(H_HCR_INFO hHcr); + +void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type); +INT getHcrType(H_HCR_INFO hHcr); + + + +#endif /* _AACDEC_HCR_H_ */ diff --git a/libAACdec/src/aacdec_hcr_bit.cpp b/libAACdec/src/aacdec_hcr_bit.cpp new file mode 100644 index 00000000..df2685bb --- /dev/null +++ b/libAACdec/src/aacdec_hcr_bit.cpp @@ -0,0 +1,165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Bitstream reading + +*******************************************************************************/ + +#include "aacdec_hcr_bit.h" + + +/*--------------------------------------------------------------------------------------------- + description: This function toggles the read direction. +----------------------------------------------------------------------------------------------- + input: current read direction +----------------------------------------------------------------------------------------------- + return: new read direction +-------------------------------------------------------------------------------------------- */ +UCHAR ToggleReadDirection(UCHAR readDirection) +{ + if ( readDirection == FROM_LEFT_TO_RIGHT ) { + return FROM_RIGHT_TO_LEFT; + } + else { + return FROM_LEFT_TO_RIGHT; + } +} + + +/*--------------------------------------------------------------------------------------------- + description: This function returns a bit from the bitstream according to read direction. + It is called very often, therefore it makes sense to inline it (runtime). +----------------------------------------------------------------------------------------------- + input: - handle to FDK bitstream + - reference value marking start of bitfield + - pLeftStartOfSegment + - pRightStartOfSegment + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- */ +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, + USHORT *pLeftStartOfSegment, + USHORT *pRightStartOfSegment, + UCHAR readDirection) +{ + UINT bit; + INT readBitOffset; + + if (readDirection == FROM_LEFT_TO_RIGHT) { + readBitOffset = *pLeftStartOfSegment-FDKgetBitCnt(bs); + if( readBitOffset ) { + FDKpushBiDirectional(bs, readBitOffset); + } + + bit = FDKreadBits(bs, 1); + + *pLeftStartOfSegment += 1; + } + else { + readBitOffset = *pRightStartOfSegment-FDKgetBitCnt(bs); + if( readBitOffset ) { + FDKpushBiDirectional(bs, readBitOffset); + } + + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pRightStartOfSegment -= 1; + } + + +#if ERROR_GENERATOR_BIT_STREAM_HCR + static int a; + if ((++a % MODULO_DIVISOR_HCR) == 0) { + bit = (bit == 0) ? 1 : 0; + } +#endif + + return (bit); +} + diff --git a/libAACdec/src/aacdec_hcr_bit.h b/libAACdec/src/aacdec_hcr_bit.h new file mode 100644 index 00000000..8994ff11 --- /dev/null +++ b/libAACdec/src/aacdec_hcr_bit.h @@ -0,0 +1,106 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Bitstream reading prototypes + +*******************************************************************************/ + +#ifndef _AACDEC_HCR_BIT_H_ +#define _AACDEC_HCR_BIT_H_ + + + +#include "aacdec_hcr.h" + +UCHAR ToggleReadDirection(UCHAR readDirection); + +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, + USHORT *pLeftStartOfSegment, + USHORT *pRightStartOfSegment, + UCHAR readDirection); + + +#endif /* _AACDEC_HCR_BIT_H_ */ diff --git a/libAACdec/src/aacdec_hcr_types.h b/libAACdec/src/aacdec_hcr_types.h new file mode 100644 index 00000000..323ec4e9 --- /dev/null +++ b/libAACdec/src/aacdec_hcr_types.h @@ -0,0 +1,366 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Common defines and structures; defines for + switching error-generator, -detector, and -concealment; + +*******************************************************************************/ + +#ifndef _AACDEC_HCR_TYPES_H_ +#define _AACDEC_HCR_TYPES_H_ + + + +#include "FDK_bitstream.h" +#include "overlapadd.h" + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define LINES_PER_UNIT 4 + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ----------- basic HCR configuration ------------ */ + + + #define MAX_SFB_HCR (((1024/8) / LINES_PER_UNIT) * 8) /* (8 * 16) is not enough because sfbs are split in units for blocktype short */ + #define NUMBER_OF_UNIT_GROUPS (LINES_PER_UNIT * 8) + #define LINES_PER_UNIT_GROUP (1024 / NUMBER_OF_UNIT_GROUPS) /* 15 16 30 32 */ + + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define FROM_LEFT_TO_RIGHT 0 +#define FROM_RIGHT_TO_LEFT 1 + +#define MAX_CB_PAIRS 23 +#define MAX_HCR_SETS 14 + +#define ESCAPE_VALUE 16 +#define POSITION_OF_FLAG_A 21 +#define POSITION_OF_FLAG_B 20 + +#define MAX_CB 32 /* last used CB is cb #31 when VCB11 is used */ + +#define MAX_CB_CHECK 32 /* support for VCB11 available -- is more general, could therefore used in both cases */ + +#define NUMBER_OF_BIT_IN_WORD 32 + +/* log */ +#define THIRTYTWO_LOG_DIV_TWO_LOG 5 +#define EIGHT_LOG_DIV_TWO_LOG 3 +#define FOUR_LOG_DIV_TWO_LOG 2 + +/* borders */ +#define CPE_TOP_LENGTH 12288 +#define SCE_TOP_LENGTH 6144 +#define LEN_OF_LONGEST_CW_TOP_LENGTH 49 + +/* qsc's of high level */ +#define Q_VALUE_INVALID 8192 /* mark a invalid line with this value (to be concealed later on) */ +#define HCR_DIRAC 500 /* a line of high level */ + +/* masks */ +#define MASK_LEFT 0xFFF000 +#define MASK_RIGHT 0xFFF +#define CLR_BIT_10 0x3FF +#define TEST_BIT_10 0x400 + +#define LEFT_OFFSET 12 + +/* when set HCR is replaced by a dummy-module which just fills the outputbuffer with a dirac sequence */ +/* use this if HCR is suspected to write in other modules -- if error is stell there, HCR is innocent */ +#define USE_HCR_DUMMY 0 + + +/* ------------------------------ */ +/* - insert HCR errors - */ +/* ------------------------------ */ + + /* modify input lengths -- high protected */ +#define ERROR_LORSD 0 /* offset: error if different from zero */ +#define ERROR_LOLC 0 /* offset: error if different from zero */ + + /* segments are earlier empty as expected when decoding PCWs */ +#define ERROR_PCW_BODY 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */ +#define ERROR_PCW_BODY_SIGN 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */ +#define ERROR_PCW_BODY_SIGN_ESC 0 /* set a positive values to trigger the error (make segments earlyer appear to be empty) */ + + /* pretend there are too many bits decoded (enlarge length of codeword) at PCWs -- use a positive value */ +#define ERROR_PCW_BODY_ONLY_TOO_LONG 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_TOO_LONG 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_ESC_TOO_LONG 0 /* set a positive values to trigger the error */ + + /* modify HCR bitstream block */ +#define ERROR_GENERATOR_BIT_STREAM_HCR 0 /* modify every -bit when reading from bitstream */ /* !!! BEWARE!!! if RVLC is active, also RVLC data at ESC2 will be modified !!! */ +#define MODULO_DIVISOR_HCR 30 + + +/* ------------------------------ */ +/* - detect HCR errors - */ +/* ------------------------------ */ + /* check input data */ +#define CHECK_VALID_HCR_INPUT 1 /* it is highly recommended to check input data */ + + /* during decoding */ +#define CHECK_SEGMENTATION_IMMEDIATELY 1 /* the 2 or 4 lines of a detected PCW-decoding-error is marked */ + +#define CHECK_SEGMENTATION_FINAL 1 /* all the segments are checked -- therefore -- if this check passes, its a kind of evidence that the + decoded PCWs and non-PCWs are fine */ + +#define DETECT_TOO_LONG_CW_READS 1 /* if a codeword is decoded there exists a border for the number of bits, which are allowed to read for this + codeword. This border is the minimum of the length of the longest codeword (for the currently used + codebook) and the separately transmitted 'lengthOfLongestCodeword' in this frame and channel. The number + of decoded bits is counted (for PCWs only -- there it makes really sense in my opinion). If this number + exceeds the border (derived as minimum -- see above), a error is detected. */ + +#define STATE_MACHINE_ERROR_CHECK 1 /* test if the number of remaining bits in a segment is _below_ zero. If there are no errors the lowest + allowed value for remainingBitsInSegment is zero. This check also could be set to zero (save runtime) */ + /* other */ +#define VALID_LAV_ERROR_TRIGGER 1 /* when set to '1', avoid setting the LAV-Flag in errorLog due to a previous-line-marking (at PCW decoder). A little + more runtime is needed then when writing values out into output-buffer. */ + +#define HCR_LISTEN_TO_MUTED_LINES 0 /* listen to the "error-concealment" for testing */ + +/* ------------------------------ */ +/* - conceal HCR errors - */ +/* ------------------------------ */ + +#define HCR_ERROR_CONCEALMENT 1 /* if set to '1', HCR _mutes_ the erred quantized spectral coefficients */ + + +// ------------------------------------------------------------------------------------------------------------------ +// errorLog: A word of 32 bits used for logging possible errors within HCR +// in case of distorted bitstreams. Table of all known errors: +// ------------------------------------------------------------------------------------------------------------------------ + // bit fatal location meaning + // ----+-----+-----------+-------------------------------------- +#define SEGMENT_OVERRIDE_ERR_PCW_BODY 0x80000000 // 31 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN 0x40000000 // 30 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC 0x20000000 // 29 no PCW-Dec During PCW decoding it is checked after every PCW if there are too many bits decoded (immediate check). +#define EXTENDED_SORTED_COUNTER_OVERFLOW 0x10000000 // 28 yes Init-Dec Error during extending sideinfo (neither a PCW nor a nonPCW was decoded so far) + // 0x08000000 // 27 reserved + // 0x04000000 // 26 reserved + // 0x02000000 // 25 reserved + // 0x01000000 // 24 reserved + // 0x00800000 // 23 reserved + // 0x00400000 // 22 reserved + // 0x00200000 // 21 reserved + // 0x00100000 // 20 reserved + + /* special errors */ +#define TOO_MANY_PCW_BODY_BITS_DECODED 0x00080000 // 19 yes PCW-Dec During PCW-body-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding +#define TOO_MANY_PCW_BODY_SIGN_BITS_DECODED 0x00040000 // 18 yes PCW-Dec During PCW-body-sign-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding +#define TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED 0x00020000 // 17 yes PCW-Dec During PCW-body-sign-esc-decoding too many bits have been read from bitstream -- advice: skip non-PCW decoding + + + // 0x00010000 // 16 reserved +#define STATE_ERROR_BODY_ONLY 0x00008000 // 15 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__BODY 0x00004000 // 14 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__SIGN 0x00002000 // 13 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__BODY 0x00001000 // 12 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__SIGN 0x00000800 // 11 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX 0x00000400 // 10 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_WORD 0x00000200 // 9 no NonPCW-Dec State machine returned with error +#define HCR_SI_LENGTHS_FAILURE 0x00000100 // 8 yes Init-Dec LengthOfLongestCodeword must not be less than lenghtOfReorderedSpectralData +#define NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000080 // 7 yes Init-Dec The number of sections is not within the allowed range (short block) +#define NUM_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000040 // 6 yes Init-Dec The number of sections is not within the allowed range (long block) +#define LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK 0x00000020 // 5 yes Init-Dec The number of lines per section is not within the allowed range (short block) +#define CB_OUT_OF_RANGE_SHORT_BLOCK 0x00000010 // 4 yes Init-Dec The codebook is not within the allowed range (short block) +#define LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK 0x00000008 // 3 yes Init-Dec The number of lines per section is not within the allowed range (long block) +#define CB_OUT_OF_RANGE_LONG_BLOCK 0x00000004 // 2 yes Init-Dec The codebook is not within the allowed range (long block) +#define LAV_VIOLATION 0x00000002 // 1 no Final The absolute value of at least one decoded line was too high for the according codebook. +#define BIT_IN_SEGMENTATION_ERROR 0x00000001 // 0 no Final After PCW and non-PWC-decoding at least one segment is not zero (global check). + + /*----------*/ +#define HCR_FATAL_PCW_ERROR_MASK 0x100E01FC + + +typedef enum { + PCW_BODY, + PCW_BODY_SIGN, + PCW_BODY_SIGN_ESC +} PCW_TYPE; + + +/* interface Decoder <---> HCR */ +typedef struct { + UINT errorLog; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase; + int quantizedSpectralCoefficientsIdx; + SHORT lengthOfReorderedSpectralData; + SHORT numSection; + SHORT *pNumLineInSect; + USHORT bitstreamIndex; + SCHAR lengthOfLongestCodeword; + UCHAR *pCodebook; +} HCR_INPUT_OUTPUT; + +typedef struct { + const UCHAR *pMinOfCbPair; + const UCHAR *pMaxOfCbPair; +} HCR_CB_PAIRS; + +typedef struct{ + const USHORT *pLargestAbsVal; + const UCHAR *pMaxCwLength; + const UCHAR *pCbDimension; + const UCHAR *pCbDimShift; + const UCHAR *pCbSign; + const UCHAR *pCbPriority; +} HCR_TABLE_INFO; + +typedef struct{ + UINT numSegment; + UINT pSegmentBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)]; + UINT pCodewordBitfield[((1024>>1)/NUMBER_OF_BIT_IN_WORD+1)]; + UINT segmentOffset; + FIXP_DBL pTempValues[1024]; + USHORT pLeftStartOfSegment[1024>>1]; + USHORT pRightStartOfSegment[1024>>1]; + SCHAR pRemainingBitsInSegment[1024>>1]; + UCHAR readDirection; + UCHAR numWordForBitfield; + USHORT pNumBitValidInLastWord; +} HCR_SEGMENT_INFO; + +typedef struct{ + + UINT numCodeword; + UINT numSortedSection; + USHORT pNumCodewordInSection[MAX_SFB_HCR]; + USHORT pNumSortedCodewordInSection[MAX_SFB_HCR]; + USHORT pNumExtendedSortedCodewordInSection[MAX_SFB_HCR+MAX_HCR_SETS]; + int numExtendedSortedCodewordInSectionIdx; + USHORT pNumExtendedSortedSectionsInSets[MAX_HCR_SETS]; + int numExtendedSortedSectionsInSetsIdx; + USHORT pReorderOffset[MAX_SFB_HCR]; + UCHAR pSortedCodebook[MAX_SFB_HCR]; + + UCHAR pExtendedSortedCodebook[MAX_SFB_HCR+MAX_HCR_SETS]; + int extendedSortedCodebookIdx; +#if DETECT_TOO_LONG_CW_READS + UCHAR pMaxLenOfCbInExtSrtSec[MAX_SFB_HCR+MAX_HCR_SETS]; + int maxLenOfCbInExtSrtSecIdx; +#endif + UCHAR pCodebookSwitch[MAX_SFB_HCR]; +} HCR_SECTION_INFO; + +typedef UINT (*STATEFUNC)(HANDLE_FDK_BITSTREAM, void*); + +typedef struct{ + /* worst-case and 1024/4 non-PCWs exist in worst-case */ + FIXP_DBL *pResultBase; /* Base address for spectral data output target buffer */ + UINT iNode[1024>>2]; /* Helper indices for code books */ + USHORT iResultPointer[1024>>2]; /* Helper indices for accessing pResultBase */ + UINT pEscapeSequenceInfo[1024>>2]; + UINT codewordOffset; + STATEFUNC pState; + UCHAR pCodebook[1024>>2]; + UCHAR pCntSign[1024>>2]; + /* this array holds the states coded as integer values within the range [0,1,..,7] */ + SCHAR pSta[1024>>2]; +} HCR_NON_PCW_SIDEINFO; + +typedef struct{ + HCR_INPUT_OUTPUT decInOut; + HCR_CB_PAIRS cbPairs; + HCR_TABLE_INFO tableInfo; + HCR_SEGMENT_INFO segmentInfo; + HCR_SECTION_INFO sectionInfo; + HCR_NON_PCW_SIDEINFO nonPcwSideinfo; + + INT globalHcrType; +} CErHcrInfo; + + +typedef CErHcrInfo *H_HCR_INFO; + + +#endif /* _AACDEC_HCR_TYPES_H_ */ diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp new file mode 100644 index 00000000..c0b2173f --- /dev/null +++ b/libAACdec/src/aacdec_hcrs.cpp @@ -0,0 +1,1409 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Prepare decoding of non-PCWs, segmentation- and + bitfield-handling, HCR-Statemachine + +*******************************************************************************/ + +#include "aacdec_hcrs.h" + + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_bit.h" +#include "aac_rom.h" +#include "aac_ram.h" + + +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord); + +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr); + +static INT ModuloValue(INT input, INT bufferlength); + +static void ClearBitFromBitfield(STATEFUNC *ptrState, + UINT offset, + UINT *pBitfield); + + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all non-priority codewords (non-PCWs) by using a + state-machine. +-------------------------------------------------------------------------------------------- */ +void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) +{ + UINT numValidSegment; + INT segmentOffset; + INT codewordOffsetBase; + INT codewordOffset; + UINT trial; + + UINT *pNumSegment; + SCHAR *pRemainingBitsInSegment; + UINT *pSegmentBitfield; + UCHAR *pNumWordForBitfield; + USHORT *pNumBitValidInLastWord; + UINT *pCodewordBitfield; + INT bitfieldWord; + INT bitInWord; + UINT tempWord; + UINT interMediateWord; + INT tempBit; + INT carry; + + UINT numCodeword; + UCHAR numSet; + UCHAR currentSet; + UINT codewordInSet; + UINT remainingCodewordsInSet; + SCHAR *pSta; + UINT ret; + + pNumSegment = &(pHcr->segmentInfo.numSegment); + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield); + pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord); + pSta = pHcr->nonPcwSideinfo.pSta; + + numValidSegment = InitSegmentBitfield(pNumSegment, + pRemainingBitsInSegment, + pSegmentBitfield, + pNumWordForBitfield, + pNumBitValidInLastWord); + + if ( numValidSegment != 0 ) { + numCodeword = pHcr->sectionInfo.numCodeword; + numSet = ((numCodeword - 1) / *pNumSegment) + 1; + + + pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT; + + /* Process sets subsequently */ + for ( currentSet = 1; currentSet < numSet ; currentSet++ ) { + + + + /* step 1 */ + numCodeword -= *pNumSegment; /* number of remaining non PCWs [for all sets] */ + if ( numCodeword < *pNumSegment ) { + codewordInSet = numCodeword; /* for last set */ + } + else { + codewordInSet = *pNumSegment; /* for all sets except last set */ + } + + /* step 2 */ + /* prepare array 'CodewordBitfield'; as much ones are written from left in all words, as much decodedCodewordInSetCounter nonPCWs exist in this set */ + tempWord = 0xFFFFFFFF; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + for ( bitfieldWord = *pNumWordForBitfield; bitfieldWord !=0; bitfieldWord-- ) { /* loop over all used words */ + if ( codewordInSet > NUMBER_OF_BIT_IN_WORD ) { /* more codewords than number of bits => fill ones */ + /* fill a whole word with ones */ + *pCodewordBitfield++ = tempWord; + codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */ + } + else { + /* prepare last tempWord */ + for (remainingCodewordsInSet = codewordInSet; remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD ; remainingCodewordsInSet++ ) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-remainingCodewordsInSet)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */ + } + *pCodewordBitfield++ = tempWord; + tempWord = 0x00000000; + } + } + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + /* step 3 */ + /* build non-PCW sideinfo for each non-PCW of the current set */ + InitNonPCWSideInformationForCurrentSet(pHcr); + + /* step 4 */ + /* decode all non-PCWs belonging to this set */ + + /* loop over trials */ + codewordOffsetBase = 0; + for ( trial = *pNumSegment; trial > 0; trial-- ) { + + /* loop over number of words in bitfields */ + segmentOffset = 0; /* start at zero in every segment */ + pHcr->segmentInfo.segmentOffset = segmentOffset; /* store in structure for states */ + codewordOffset = codewordOffsetBase; + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; /* store in structure for states */ + + for ( bitfieldWord=0; bitfieldWord < *pNumWordForBitfield; bitfieldWord++ ) { + + /* derive tempWord with bitwise and */ + tempWord = pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord]; + + /* if tempWord is not zero, decode something */ + if ( tempWord != 0 ) { + + + /* loop over all bits in tempWord; start state machine if & is true */ + for ( bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; bitInWord-- ) { + + interMediateWord = ((UINT)1 << (bitInWord-1) ); + if ( ( tempWord & interMediateWord ) == interMediateWord ) { + + /* get state and start state machine */ + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; + + while(pHcr->nonPcwSideinfo.pState) { + ret = ((STATEFUNC) pHcr->nonPcwSideinfo.pState)(bs, pHcr); +#if STATE_MACHINE_ERROR_CHECK + if ( ret != 0 ) { + return; + } +#endif + } + } + + /* update both offsets */ + segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + codewordOffset = ModuloValue(codewordOffset,*pNumSegment); /* index of the current codeword lies within modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } + else { + segmentOffset += NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + codewordOffset = ModuloValue(codewordOffset,*pNumSegment); /* index of the current codeword lies within modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } /* end of bitfield word loop */ + + /* decrement codeword - pointer */ + codewordOffsetBase -= 1; + codewordOffsetBase = ModuloValue(codewordOffsetBase,*pNumSegment); /* index of the current codeword base lies within modulo range */ + + /* rotate numSegment bits in codewordBitfield */ + /* rotation of *numSegment bits in bitfield of codewords (circle-rotation) */ + /* get last valid bit */ + tempBit = pCodewordBitfield[*pNumWordForBitfield-1] & (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); + + /* write zero into place where tempBit was fetched from */ + pCodewordBitfield[*pNumWordForBitfield-1] = pCodewordBitfield[*pNumWordForBitfield-1] & ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + + /* rotate last valid word */ + pCodewordBitfield[*pNumWordForBitfield-1] = pCodewordBitfield[*pNumWordForBitfield-1] >> 1; + + /* transfare carry bit 0 from current word into bitposition 31 from next word and rotate current word */ + for ( bitfieldWord = *pNumWordForBitfield-2; bitfieldWord > -1 ; bitfieldWord-- ) { + /* get carry (=bit at position 0) from current word */ + carry = pCodewordBitfield[bitfieldWord] & 1; + + /* put the carry bit at position 31 into word right from current word */ + pCodewordBitfield[bitfieldWord+1] = pCodewordBitfield[bitfieldWord+1] | (carry << (NUMBER_OF_BIT_IN_WORD-1)); + + /* shift current word */ + pCodewordBitfield[bitfieldWord] = pCodewordBitfield[bitfieldWord] >> 1; + } + + /* put tempBit into free bit-position 31 from first word */ + pCodewordBitfield[0] = pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD-1)); + + } /* end of trial loop */ + + /* toggle read direction */ + pHcr->segmentInfo.readDirection = ToggleReadDirection(pHcr->segmentInfo.readDirection); + + } + /* end of set loop */ + + /* all non-PCWs of this spectrum are decoded */ + } + + /* all PCWs and all non PCWs are decoded. They are unbacksorted in output buffer. Here is the Interface with comparing QSCs to asm decoding */ +} + + +/*--------------------------------------------------------------------------------------------- + description: This function prepares the bitfield used for the + segments. The list is set up once to be used in all following sets. If a + segment is decoded empty, the according bit from the Bitfield is removed. +----------------------------------------------------------------------------------------------- + return: numValidSegment = the number of valid segments +-------------------------------------------------------------------------------------------- */ +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord) +{ + SHORT i; + USHORT r; + UCHAR bitfieldWord; + UINT tempWord; + USHORT numValidSegment; + + *pNumWordForBitfield = ((*pNumSegment-1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1; + + /* loop over all words, which are completely used or only partial */ + /* bit in pSegmentBitfield is zero if segment is empty; bit in pSegmentBitfield is one if segment is not empty */ + numValidSegment = 0; + *pNumBitValidInLastWord = *pNumSegment; + + /* loop over words */ + for ( bitfieldWord=0; bitfieldWord < *pNumWordForBitfield - 1; bitfieldWord++ ) { + tempWord = 0xFFFFFFFF; /* set ones */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for ( i=0; i < NUMBER_OF_BIT_IN_WORD; i++) { + if ( pRemainingBitsInSegment[r + i] == 0 ) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-i)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */ + } + else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of zeros on LSB side in the last word */ + } + + + /* calculate last word: prepare special tempWord */ + tempWord = 0xFFFFFFFF; + for ( i=0; i < ( NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord ); i++ ) { + tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */ + } + + /* calculate last word */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for ( i=0; i<*pNumBitValidInLastWord; i++) { + if ( pRemainingBitsInSegment[r + i] == 0 ) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD-1-i)); /* set a zero at bit number (NUMBER_OF_BIT_IN_WORD-1-i) in tempWord */ + } + else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + + + + return numValidSegment; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function sets up sideinfo for the non-PCW decoder (for the current set). +---------------------------------------------------------------------------------------------*/ +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr) +{ + USHORT i,k; + UCHAR codebookDim; + UINT startNode; + + UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook; + UINT *iNode = pHcr->nonPcwSideinfo.iNode; + UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign; + USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + SCHAR *pSta = pHcr->nonPcwSideinfo.pSta; + USHORT *pNumExtendedSortedCodewordInSection = pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + FIXP_DBL *pQuantizedSpectralCoefficients = SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + int quantizedSpectralCoefficientsIdx = pHcr->decInOut.quantizedSpectralCoefficientsIdx; + const UCHAR *pCbDimension = pHcr->tableInfo.pCbDimension; + int iterationCounter = 0; + + /* loop over number of extended sorted sections in the current set so all codewords sideinfo variables within this set can be prepared for decoding */ + for ( i=pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; i != 0; i-- ) { + + codebookDim = pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + + for ( k = pNumExtendedSortedCodewordInSection[numExtendedSortedCodewordInSectionIdx]; k != 0; k-- ) { + iterationCounter++; + if (iterationCounter > (1024>>2)) { + return; + } + *pSta++ = aCodebook2StartInt[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx]; + *iNode++ = startNode; + *pCntSign++ = 0; + *iResultPointer++ = quantizedSpectralCoefficientsIdx; + *pEscapeSequenceInfo++ = 0; + quantizedSpectralCoefficientsIdx += codebookDim; /* update pointer by codebookDim --> point to next starting value for writing out */ + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in current set */ + extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS) || extendedSortedCodebookIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + } + numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR+MAX_HCR_SETS)) { + return; + } + + /* Write back indexes */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = numExtendedSortedSectionsInSetsIdx; + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = numExtendedSortedCodewordInSectionIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = quantizedSpectralCoefficientsIdx; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function returns the input value if the value is in the + range of bufferlength. If is smaller, one bufferlength is added, + if is bigger one bufferlength is subtracted. +----------------------------------------------------------------------------------------------- + return: modulo result +-------------------------------------------------------------------------------------------- */ +static INT ModuloValue(INT input, INT bufferlength) +{ + if ( input > (bufferlength - 1) ) { + return (input - bufferlength); + } + if ( input < 0 ) { + return (input + bufferlength); + } + return input; +} + + +/*--------------------------------------------------------------------------------------------- + description: This function clears a bit from current bitfield and + switches off the statemachine. + + A bit is cleared in two cases: + a) a codeword is decoded, then a bit is cleared in codeword bitfield + b) a segment is decoded empty, then a bit is cleared in segment bitfield +-------------------------------------------------------------------------------------------- */ +static void ClearBitFromBitfield(STATEFUNC *ptrState, + UINT offset, + UINT *pBitfield) +{ + UINT numBitfieldWord; + UINT numBitfieldBit; + + /* get both values needed for clearing the bit */ + numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */ + numBitfieldBit = offset - (numBitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */ + + /* clear a bit in bitfield */ + pBitfield[numBitfieldWord] = pBitfield[numBitfieldWord] & ~(1 << (NUMBER_OF_BIT_IN_WORD-1 - numBitfieldBit)); + + /* switch off state machine because codeword is decoded and/or because segment is empty */ + *ptrState = NULL; +} + + + +/* ========================================================================================= + the states of the statemachine + ========================================================================================= */ + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a codeword. This State is used for codebooks 1,2,5 and 6. + No sign bits are decoded, because the table of the quantized spectral values + has got a valid sign at the quantized spectral lines. +----------------------------------------------------------------------------------------------- + output: Two or four quantizes spectral values written at position where pResultPointr + points to +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + FIXP_DBL *pResultBase; + UINT *iNode; + USHORT *iResultPointer; + UINT codewordOffset; + UINT branchNode; + UINT branchValue; + UINT iQSC; + UINT treeNode; + UCHAR carryBit; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment; + UCHAR readDirection; + UCHAR *pCodebook; + UCHAR dimCntr; + const UINT *pCurrentTree; + const UCHAR *pCbDimension; + const SCHAR *pQuantVal; + const SCHAR *pQuantValBase; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + pCbDimension = pHcr->tableInfo.pCbDimension; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, + &branchValue, + &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; ==> body is complete */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base address of quantized values belonging to current codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for writing out result */ + + for ( dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; dimCntr-- ) { + pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into spectrum; no Sign bits available in this state */ + } + + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */ + } + else { /* body is not decoded completely: */ + treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe decoding of codeword body not finished yet */ + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY; + return BODY_ONLY; + } +#endif + } + + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body, writes out result and counts the number of quantized + spectral values, which are different form zero. For those values sign bits are + needed. + + If sign bit counter cntSign is different from zero, switch to next state to + decode sign Bits there. + If sign bit counter cntSign is zero, no sign bits are needed and codeword is + decoded. +----------------------------------------------------------------------------------------------- + output: Two or four written quantizes spectral values written at position where + pResultPointr points to. The signs of those lines may be wrong. If the signs + [on just one signle sign] is wrong, the next state will correct it. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCodebook; + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UINT iQSC; + UINT cntSign; + UCHAR dimCntr; + UCHAR carryBit; + SCHAR *pSta; + UINT treeNode; + UINT branchValue; + UINT branchNode; + const UCHAR *pCbDimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + pCbDimension = pHcr->tableInfo.pCbDimension; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, + &branchValue, + &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set body complete */ + /* body completely decoded; branchValue is valid, set pQuantVal to first (of two or four) quantized spectral coefficients */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base address of quantized values belonging to current codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for writing result */ + + /* codeword decoding result is written out here: Write out 2 or 4 quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for sign bit decoding [which happens in next state] */ + cntSign = 0; + for ( dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; dimCntr-- ) { + pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if ( *pQuantVal++ != 0 ) { + cntSign += 1; + } + } + + if ( cntSign == 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + } + else { + pCntSign[codewordOffset] = cntSign; /* write sign count result into codewordsideinfo of current codeword */ + pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */ + } + else {/* body is not decoded completely: */ + treeNode = *(pCurrentTree + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe decoding of codeword body not finished yet */ + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY; + return BODY_SIGN__BODY; + } +#endif + } + + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits belonging to a codeword. The state is called + as often in different "trials" until pCntSgn[codewordOffset] is zero. +----------------------------------------------------------------------------------------------- + output: The two or four quantizes spectral values (written in previous state) have + now the correct sign. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + UCHAR carryBit; + UINT iQSC; + UCHAR cntSign; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + + + /* loop for sign bit decoding */ + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + cntSign -= 1; /* decrement sign counter because one sign bit has been read */ + + /* search for a line (which was decoded in previous state) which is not zero. [This value will get a sign] */ + while ( pResultBase[iQSC] == (FIXP_DBL)0 ) { + iQSC++; /* points to current value different from zero */ + if (iQSC >= 1024) { + return BODY_SIGN__SIGN; + } + } + + /* put sign together with line; if carryBit is zero, the sign is ok already; no write operation necessary in this case */ + if ( carryBit != 0 ) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + + iQSC++; /* update pointer to next (maybe valid) value */ + + if ( cntSign == 0 ) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */ + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + break; /* whole nonPCW-Body and according sign bits are decoded */ + } + } + pCntSign[codewordOffset] = cntSign; + iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */ + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN; + return BODY_SIGN__SIGN; + } +#endif + } + + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body in case of codebook is 11. Writes out resulting + two or four lines [with probably wrong sign] and counts the number of + lines, which are different form zero. This information is needed in next + state where sign bits will be decoded, if necessary. + If sign bit counter cntSign is zero, no sign bits are needed and codeword is + decoded completely. +----------------------------------------------------------------------------------------------- + output: Two lines (quantizes spectral coefficients) which are probably wrong. The + sign may be wrong and if one or two values is/are 16, the following states + will decode the escape sequence to correct the values which are wirtten here. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UINT cntSign; + UINT dimCntr; + UINT treeNode; + SCHAR *pSta; + UINT branchNode; + UINT branchValue; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[ESCAPE_CODEBOOK]; + + + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + /* make a step in tree */ + CarryBitToBranchValue(carryBit, + treeNode, + &branchValue, + &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set body complete */ + + /* body completely decoded; branchValue is valid */ + /* set pQuantVol to first (of two or four) quantized spectral coefficients */ + pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of quantized values belonging to current codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid line [of 2 or 4 quantized values] */ + + /* make backup from original resultPointer in node storage for state BODY_SIGN_ESC__SIGN */ + iNode[codewordOffset] = iResultPointer[codewordOffset]; + + /* get position of first line for writing result */ + iQSC = iResultPointer[codewordOffset]; + + /* codeword decoding result is written out here: Write out 2 or 4 quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for sign bit decoding [which happens in next state] */ + cntSign = 0; + + for ( dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr-- ) { + pResultBase[iQSC++] = (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if ( *pQuantVal++ != 0 ) { + cntSign += 1; + } + } + + if ( cntSign == 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + /* codeword decoded */ + } + else { + /* write sign count result into codewordsideinfo of current codeword */ + pCntSign[codewordOffset] = cntSign; + pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation of for loop counter (see above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is decoded */ + } + else { /* body is not decoded completely: */ + /* update treeNode for further step in decoding tree and store updated treeNode because maybe no more bits left in segment */ + treeNode = *(pCurrentTree + branchValue); + iNode[codewordOffset] = treeNode; + } + } + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY; + return BODY_SIGN_ESC__BODY; + } +#endif + } + + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits, if a codeword of codebook 11 needs some. + A flag named 'flagB' in codeword sideinfo is set, if the second line of + quantized spectral values is 16. The 'flagB' is used in case of decoding + of a escape sequence is necessary as far as the second line is concerned. + + If only the first line needs an escape sequence, the flagB is cleared. + If only the second line needs an escape sequence, the flagB is not used. + + For storing sideinfo in case of escape sequence decoding one single word + can be used for both escape sequences because they are decoded not at the + same time: + + + bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + ===== == == =========== =========== =================================== + ^ ^ ^ ^ ^ ^ + | | | | | | + res. flagA flagB escapePrefixUp escapePrefixDown escapeWord + +----------------------------------------------------------------------------------------------- + output: Two lines with correct sign. If one or two values is/are 16, the lines are + not valid, otherwise they are. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT iQSC; + UCHAR cntSign; + UINT flagA; + UINT flagB; + UINT flags; + UCHAR carryBit; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + + /* loop for sign bit decoding */ + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + /* decrement sign counter because one sign bit has been read */ + cntSign -= 1; + pCntSign[codewordOffset] = cntSign; + + /* get a quantized spectral value (which was decoded in previous state) which is not zero. [This value will get a sign] */ + while ( pResultBase[iQSC] == (FIXP_DBL)0 ) { + iQSC++; + } + iResultPointer[codewordOffset] = iQSC; + + /* put negative sign together with quantized spectral value; if carryBit is zero, the sign is ok already; no write operation necessary in this case */ + if ( carryBit != 0 ) { + pResultBase[iQSC] = - pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + iQSC++; /* update index to next (maybe valid) value */ + iResultPointer[codewordOffset] = iQSC; + + if ( cntSign == 0 ) { + /* all sign bits are decoded now */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + + /* check decoded values if codeword is decoded: Check if one or two escape sequences 16 follow */ + + /* step 0 */ + /* restore pointer to first decoded quantized value [ = original pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY */ + iQSC = iNode[codewordOffset]; + + /* step 1 */ + /* test first value if escape sequence follows */ + flagA = 0; /* for first possible escape sequence */ + if ( fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE ) { + flagA = 1; + } + + /* step 2 */ + /* test second value if escape sequence follows */ + flagB = 0; /* for second possible escape sequence */ + if ( fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE ) { + flagB = 1; + } + + + /* step 3 */ + /* evaluate flag result and go on if necessary */ + if ( !flagA && !flagB ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + } + else { + /* at least one of two lines is 16 */ + /* store both flags at correct positions in non PCW codeword sideinfo pEscapeSequenceInfo[codewordOffset] */ + flags = 0; + flags = flagA << POSITION_OF_FLAG_A; + flags |= (flagB << POSITION_OF_FLAG_B); + pEscapeSequenceInfo[codewordOffset] = flags; + + + /* set next state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */ + + /* set result pointer to the first line of the two decoded lines */ + iResultPointer[codewordOffset] = iNode[codewordOffset]; + + if ( !flagA && flagB ) { + /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes to correct position. Second value is the one and only escape value */ + iQSC = iResultPointer[codewordOffset]; + iQSC++; + iResultPointer[codewordOffset] = iQSC; + } + + } /* at least one of two lines is 16 */ + break; /* nonPCW-Body at cb 11 and according sign bits are decoded */ + + } /* if ( cntSign == 0 ) */ + } /* loop over remaining Bits in segment */ + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN; + return BODY_SIGN_ESC__SIGN; + } +#endif + + } + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decode escape prefix of first or second escape sequence. The escape prefix + consists of ones. The following zero is also decoded here. +----------------------------------------------------------------------------------------------- + output: If the single separator-zero which follows the escape-prefix-ones is not yet decoded: + The value 'escapePrefixUp' in word pEscapeSequenceInfo[codewordOffset] is updated. + + If the single separator-zero which follows the escape-prefix-ones is decoded: + Two updated values 'escapePrefixUp' and 'escapePrefixDown' in word + pEscapeSequenceInfo[codewordOffset]. This State is finished. Switch to next state. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT segmentOffset; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + UCHAR carryBit; + UINT escapePrefixUp; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapePrefixUp = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> LSB_ESCAPE_PREFIX_UP; + + + /* decode escape prefix */ + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + /* count ones and store sum in escapePrefixUp */ + if ( carryBit == 1 ) { + escapePrefixUp += 1; /* update conter for ones */ + + /* store updated counter in sideinfo of current codeword */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + } + else { /* separator [zero] reached */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + escapePrefixUp += 4; /* if escape_separator '0' appears, add 4 and ==> break */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit position escapePrefixUp */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit position escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= escapePrefixUp; /* insert new escapePrefixDown */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back down */ + + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */ + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */ + break; + } + } + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; + return BODY_SIGN_ESC__ESC_PREFIX; + } +#endif + } + + return STOP_THIS_STATE; +} + + +/*--------------------------------------------------------------------------------------------- + description: Decode escapeWord of escape sequence. If the escape sequence is decoded + completely, assemble quantized-spectral-escape-coefficient and replace the + previous decoded 16 by the new value. + Test flagB. If flagB is set, the second escape sequence must be decoded. If + flagB is not set, the codeword is decoded and the state machine is switched + off. +----------------------------------------------------------------------------------------------- + output: Two lines with valid sign. At least one of both lines has got the correct + value. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- */ +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr) +{ + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + USHORT *pLeftStartOfSegment; + USHORT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT escapeWord; + UINT escapePrefixDown; + UINT escapePrefixUp; + UCHAR carryBit; + UINT iQSC; + INT sign; + UINT flagA; + UINT flagB; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD; + escapePrefixDown = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> LSB_ESCAPE_PREFIX_DOWN; + + + /* decode escape word */ + for ( ; pRemainingBitsInSegment[segmentOffset] > 0 ; pRemainingBitsInSegment[segmentOffset] -= 1 ) { + + carryBit = HcrGetABitFromBitstream( bs, + &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], + readDirection); + + /* build escape word */ + escapeWord <<= 1; /* left shift previous decoded part of escapeWord by on bit */ + escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */ + + /* decrement counter for length of escape word because one more bit was decoded */ + escapePrefixDown -= 1; + + /* store updated escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= escapePrefixDown; /* insert new escapePrefixDown */ + escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */ + + + /* store updated escapeWord */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_ESCAPE_WORD; /* delete old escapeWord */ + pEscapeSequenceInfo[codewordOffset] |= escapeWord; /* insert new escapeWord */ + + + if ( escapePrefixDown == 0 ) { + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of for loop counter (see above) is done here */ + + /* escape sequence decoded. Assemble escape-line and replace original line */ + + /* step 0 */ + /* derive sign */ + iQSC = iResultPointer[codewordOffset]; + sign = (pResultBase[iQSC] >= (FIXP_DBL)0) ? 1 : -1; /* get sign of escape value 16 */ + + /* step 1 */ + /* get escapePrefixUp */ + escapePrefixUp = (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> LSB_ESCAPE_PREFIX_UP; + + /* step 2 */ + /* calculate escape value */ + pResultBase[iQSC] = (FIXP_DBL)(sign * (((INT) 1 << escapePrefixUp) + escapeWord)); + + /* get both flags from sideinfo (flags are not shifted to the lsb-position) */ + flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A; + flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B; + + /* step 3 */ + /* clear the whole escape sideinfo word */ + pEscapeSequenceInfo[codewordOffset] = 0; + + /* change state in dependence of flag flagB */ + if ( flagA != 0 ) { + /* first escape sequence decoded; previous decoded 16 has been replaced by valid line */ + + /* clear flagA in sideinfo word because this escape sequence has already beed decoded */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A; + + if ( flagB == 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + } + else { + /* updated pointer to next and last 16 */ + iQSC++; + iResultPointer[codewordOffset] = iQSC; + + /* change state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = aStateConstant2State[pSta[codewordOffset]]; /* get state from separate array of cw-sideinfo */ + } + } + else { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off statemachine */ + } + break; + } + } + + if ( pRemainingBitsInSegment[segmentOffset] <= 0 ) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), + segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and switch off statemachine */ + +#if STATE_MACHINE_ERROR_CHECK + if ( pRemainingBitsInSegment[segmentOffset] < 0 ) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD; + return BODY_SIGN_ESC__ESC_WORD; + } +#endif + } + + return STOP_THIS_STATE; +} + diff --git a/libAACdec/src/aacdec_hcrs.h b/libAACdec/src/aacdec_hcrs.h new file mode 100644 index 00000000..678ba26b --- /dev/null +++ b/libAACdec/src/aacdec_hcrs.h @@ -0,0 +1,153 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: HCR Decoder: Defines of state-constants, masks and + state-prototypes + +*******************************************************************************/ + +#ifndef _AACDEC_HCRS_H_ +#define _AACDEC_HCRS_H_ + + + +#include "FDK_bitstream.h" +#include "aacdec_hcr_types.h" + /* The four different kinds of types of states are: */ +/* different states are defined as constants */ /* start middle=self next stop */ +#define STOP_THIS_STATE 0 /* */ +#define BODY_ONLY 1 /* X X X */ +#define BODY_SIGN__BODY 2 /* X X X X [stop if no sign] */ +#define BODY_SIGN__SIGN 3 /* X X [stop if sign bits decoded] */ +#define BODY_SIGN_ESC__BODY 4 /* X X X X [stop if no sign] */ +#define BODY_SIGN_ESC__SIGN 5 /* X X X [stop if no escape sequence] */ +#define BODY_SIGN_ESC__ESC_PREFIX 6 /* X X */ +#define BODY_SIGN_ESC__ESC_WORD 7 /* X X X [stop if abs(second qsc) != 16] */ + +/* examples: */ + +/* BODY_ONLY means only the codeword body will be decoded; no sign bits will follow and no escapesequence will follow */ + +/* BODY_SIGN__BODY means that the codeword consists of two parts; body and sign part. The part '__BODY' after the two underscores shows */ +/* that the bits which are currently decoded belong to the '__BODY' of the codeword and not to the sign part. */ + +/* BODY_SIGN_ESC__ESC_PB means that the codeword consists of three parts; body, sign and (here: two) escape sequences; */ +/* P = Prefix = ones */ +/* W = Escape Word */ +/* A = first possible (of two) Escape sequeces */ +/* B = second possible (of two) Escape sequeces */ +/* The part after the two underscores shows that the current bits which are decoded belong to the '__ESC_PB' - part of the */ +/* codeword. That means the body and the sign bits are decoded completely and the bits which are decoded now belong to */ +/* the escape sequence [P = prefix; B=second possible escape sequence] */ + + +#define MSB_31_MASK 0x80000000 /* masks MSB (= Bit 31) in a 32 bit word */ +#define DIMENSION_OF_ESCAPE_CODEBOOK 2 /* for cb >= 11 is dimension 2 */ +#define ESCAPE_CODEBOOK 11 + +#define MASK_ESCAPE_PREFIX_UP 0x000F0000 +#define LSB_ESCAPE_PREFIX_UP 16 + +#define MASK_ESCAPE_PREFIX_DOWN 0x0000F000 +#define LSB_ESCAPE_PREFIX_DOWN 12 + +#define MASK_ESCAPE_WORD 0x00000FFF +#define MASK_FLAG_A 0x00200000 +#define MASK_FLAG_B 0x00100000 + + +extern void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO hHcr); + +UINT Hcr_State_BODY_ONLY (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__BODY (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__SIGN (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__BODY (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__SIGN (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX (HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD (HANDLE_FDK_BITSTREAM, void*); + +#endif /* _AACDEC_HCRS_H_ */ + diff --git a/libAACdec/src/aacdec_pns.cpp b/libAACdec/src/aacdec_pns.cpp new file mode 100644 index 00000000..541ef07c --- /dev/null +++ b/libAACdec/src/aacdec_pns.cpp @@ -0,0 +1,382 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: perceptual noise substitution tool + +******************************************************************************/ + +#include "aacdec_pns.h" + + +#include "aac_ram.h" +#include "aac_rom.h" +#include "channelinfo.h" +#include "block.h" +#include "FDK_bitstream.h" + +#include "genericStds.h" + + +#define NOISE_OFFSET 90 /* cf. ISO 14496-3 p. 175 */ + +/*! + \brief Reset InterChannel and PNS data + + The function resets the InterChannel and PNS data +*/ +void CPns_ResetData( + CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData + ) +{ + /* Assign pointer always, since pPnsData is not persistent data */ + pPnsData->pPnsInterChannelData = pPnsInterChannelData; + pPnsData->PnsActive = 0; + pPnsData->CurrentEnergy = 0; + + FDKmemclear(pPnsData->pnsUsed,(8*16)*sizeof(UCHAR)); + FDKmemclear(pPnsInterChannelData->correlated,(8*16)*sizeof(UCHAR)); +} + +/*! + \brief Initialize PNS data + + The function initializes the PNS data +*/ +void CPns_InitPns( + CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData, + INT* currentSeed, INT* randomSeed) +{ + /* save pointer to inter channel data */ + pPnsData->pPnsInterChannelData = pPnsInterChannelData; + + /* use pointer because seed has to be + same, left and right channel ! */ + pPnsData->currentSeed = currentSeed; + pPnsData->randomSeed = randomSeed; +} + +/*! + \brief Indicates if PNS is used + + The function returns a value indicating whether PNS is used or not + acordding to the noise energy + + \return PNS used +*/ +int CPns_IsPnsUsed (const CPnsData *pPnsData, + const int group, + const int band) +{ + unsigned pns_band = group*16+band; + + return pPnsData->pnsUsed[pns_band] & (UCHAR)1; +} + +/*! + \brief Set correlation + + The function activates the noise correlation between the channel pair +*/ +void CPns_SetCorrelation(CPnsData *pPnsData, + const int group, + const int band, + const int outofphase) +{ + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group*16+band; + + pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1; +} + +/*! + \brief Indicates if correlation is used + + The function indicates if the noise correlation between the channel pair + is activated + + \return PNS is correlated +*/ +static +int CPns_IsCorrelated(const CPnsData *pPnsData, + const int group, + const int band) +{ + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group*16+band; + + return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0; +} + +/*! + \brief Indicates if correlated out of phase mode is used. + + The function indicates if the noise correlation between the channel pair + is activated in out-of-phase mode. + + \return PNS is out-of-phase +*/ +static +int CPns_IsOutOfPhase(const CPnsData *pPnsData, + const int group, + const int band) +{ + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group*16+band; + + return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0; +} + +/*! + \brief Read PNS information + + The function reads the PNS information from the bitstream +*/ +void CPns_Read (CPnsData *pPnsData, + HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, + SHORT *pScaleFactor, + UCHAR global_gain, + int band, + int group /* = 0 */) +{ + int delta ; + UINT pns_band = group*16+band; + + if (pPnsData->PnsActive) { + /* Next PNS band case */ + delta = CBlock_DecodeHuffmanWord (bs, hcb) - 60; + } else { + /* First PNS band case */ + int noiseStartValue = FDKreadBits(bs,9); + + delta = noiseStartValue - 256 ; + pPnsData->PnsActive = 1; + pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET; + } + + pPnsData->CurrentEnergy += delta ; + pScaleFactor[pns_band] = pPnsData->CurrentEnergy; + + pPnsData->pnsUsed[pns_band] = 1; +} + + +/** + * \brief Generate a vector of noise of given length. The noise values are + * scaled in order to yield a noise energy of 1.0 + * \param spec pointer to were the noise values will be written to. + * \param size amount of noise values to be generated. + * \param pRandomState pointer to the state of the random generator being used. + * \return exponent of generated noise vector. + */ +static int GenerateRandomVector (FIXP_DBL *RESTRICT spec, + int size, + int *pRandomState) +{ + int i, invNrg_e = 0, nrg_e = 0; + FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f) ; + FIXP_DBL *RESTRICT ptr = spec; + int randomState = *pRandomState; + +#define GEN_NOISE_NRG_SCALE 7 + + /* Generate noise and calculate energy. */ + for (i=0; i>GEN_NOISE_NRG_SCALE); + *ptr++ = (FIXP_DBL)randomState; + } + nrg_e = GEN_NOISE_NRG_SCALE*2 + 1; + + /* weight noise with = 1 / sqrt_nrg; */ + invNrg_m = invSqrtNorm2(nrg_m<<1, &invNrg_e); + invNrg_e += -((nrg_e-1)>>1); + + for (i=size; i--; ) + { + spec[i] = fMult(spec[i], invNrg_m); + } + + /* Store random state */ + *pRandomState = randomState; + + return invNrg_e; +} + +static void ScaleBand (FIXP_DBL *RESTRICT spec, int size, int scaleFactor, int specScale, int noise_e, int out_of_phase) +{ + int i, shift, sfExponent; + FIXP_DBL sfMatissa; + + /* Get gain from scale factor value = 2^(scaleFactor * 0.25) */ + sfMatissa = MantissaTable[scaleFactor & 0x03][0]; + /* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */ + /* Note: ExponentTable[scaleFactor & 0x03][0] is always 1. */ + sfExponent = (scaleFactor >> 2) + 1; + + if (out_of_phase != 0) { + sfMatissa = -sfMatissa; + } + + /* +1 because of fMultDiv2 below. */ + shift = sfExponent - specScale + 1 + noise_e; + + /* Apply gain to noise values */ + if (shift>=0) { + shift = fixMin( shift, DFRACT_BITS-1 ); + for (i = size ; i-- != 0; ) { + spec [i] = fMultDiv2 (spec [i], sfMatissa) << shift; + } + } else { + shift = fixMin( -shift, DFRACT_BITS-1 ); + for (i = size ; i-- != 0; ) { + spec [i] = fMultDiv2 (spec [i], sfMatissa) >> shift; + } + } +} + + +/*! + \brief Apply PNS + + The function applies PNS (i.e. it generates noise) on the bands + flagged as noisy bands + +*/ +void CPns_Apply (const CPnsData *pPnsData, + const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, + const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, + const int channel) +{ + if (pPnsData->PnsActive) { + const short *BandOffsets = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); + + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo); + + for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); group++) { + for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); groupwin++, window++) { + FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength); + + for (int band = 0 ; band < ScaleFactorBandsTransmitted; band++) { + if (CPns_IsPnsUsed (pPnsData, group, band)) { + UINT pns_band = group*16+band; + + int bandWidth = BandOffsets [band + 1] - BandOffsets [band] ; + int noise_e; + + FDK_ASSERT(bandWidth >= 0); + + if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band)) + { + noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth, + &pPnsData->randomSeed [pns_band]) ; + } + else + { + pPnsData->randomSeed [pns_band] = *pPnsData->currentSeed ; + + noise_e = GenerateRandomVector (spectrum + BandOffsets [band], bandWidth, + pPnsData->currentSeed) ; + } + + int outOfPhase = CPns_IsOutOfPhase (pPnsData, group, band); + + ScaleBand (spectrum + BandOffsets [band], bandWidth, + pScaleFactor[pns_band], + pSpecScale[window], noise_e, outOfPhase) ; + } + } + } + } + } +} diff --git a/libAACdec/src/aacdec_pns.h b/libAACdec/src/aacdec_pns.h new file mode 100644 index 00000000..fc9bdcba --- /dev/null +++ b/libAACdec/src/aacdec_pns.h @@ -0,0 +1,120 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: perceptual noise substitution tool + +******************************************************************************/ + +#ifndef PNS_H +#define PNS_H + +#include "common_fix.h" + + +#define NO_OFBANDS ((8*16)) + +typedef struct { + UCHAR correlated[NO_OFBANDS]; +} CPnsInterChannelData; + +typedef struct { + CPnsInterChannelData *pPnsInterChannelData; + UCHAR pnsUsed[NO_OFBANDS]; + int CurrentEnergy; + UCHAR PnsActive; + INT *currentSeed; + INT *randomSeed; +} CPnsData; + +void CPns_InitPns ( CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData, + INT* currentSeed, + INT* randomSeed ); + +void CPns_ResetData ( CPnsData *pPnsData, CPnsInterChannelData *pPnsInterChannelData ); + + +#endif /* #ifndef PNS_H */ diff --git a/libAACdec/src/aacdec_tns.cpp b/libAACdec/src/aacdec_tns.cpp new file mode 100644 index 00000000..352f04ab --- /dev/null +++ b/libAACdec/src/aacdec_tns.cpp @@ -0,0 +1,412 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: temporal noise shaping tool + +******************************************************************************/ + +#include "aacdec_tns.h" +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" + + + +/*! + \brief Reset tns data + + The function resets the tns data + + \return none +*/ +void CTns_Reset(CTnsData *pTnsData) +{ + /* Note: the following FDKmemclear should not be required. */ + FDKmemclear(pTnsData->Filter, TNS_MAX_WINDOWS*TNS_MAXIMUM_FILTERS*sizeof(CFilter)); + FDKmemclear(pTnsData->NumberOfFilters, TNS_MAX_WINDOWS*sizeof(UCHAR)); + pTnsData->DataPresent = 0; + pTnsData->Active = 0; +} + +void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + CTnsData *pTnsData) /*!< pointer to aac decoder channel info */ +{ + pTnsData->DataPresent = (UCHAR) FDKreadBits(bs,1); +} + +/*! + \brief Read tns data from bitstream + + The function reads the elements for tns from + the bitstream. + + \return none +*/ +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, + CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, + const UINT flags) +{ + UCHAR n_filt,order; + UCHAR length,coef_res,coef_compress; + UCHAR window; + UCHAR wins_per_frame = GetWindowsPerFrame(pIcsInfo); + UCHAR isLongFlag = IsLongBlock(pIcsInfo); + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + if (!pTnsData->DataPresent) { + return ErrorStatus; + } + + for (window = 0; window < wins_per_frame; window++) + { + pTnsData->NumberOfFilters[window] = n_filt = (UCHAR) FDKreadBits(bs, isLongFlag ? 2 : 1); + + if (pTnsData->NumberOfFilters[window] > TNS_MAXIMUM_FILTERS){ + pTnsData->NumberOfFilters[window] = n_filt = TNS_MAXIMUM_FILTERS; + } + + if (n_filt) + { + int index; + UCHAR nextstopband; + + coef_res = (UCHAR) FDKreadBits(bs,1); + + nextstopband = GetScaleFactorBandsTotal(pIcsInfo); + + for (index=0; index < n_filt; index++) + { + CFilter *filter = &pTnsData->Filter[window][index]; + + length = (UCHAR)FDKreadBits(bs, isLongFlag ? 6 : 4); + + if (length > nextstopband){ + length = nextstopband; + } + + filter->StartBand = nextstopband - length; + filter->StopBand = nextstopband; + nextstopband = filter->StartBand; + + { + filter->Order = order = (UCHAR) FDKreadBits(bs, isLongFlag ? 5 : 3); + } + + if (filter->Order > TNS_MAXIMUM_ORDER){ + filter->Order = order = TNS_MAXIMUM_ORDER; + } + + if (order) + { + UCHAR coef,s_mask; + UCHAR i; + SCHAR n_mask; + static const UCHAR sgn_mask[] = { 0x2, 0x4, 0x8 }; + static const SCHAR neg_mask[] = { ~0x3, ~0x7, ~0xF }; + + filter->Direction = FDKreadBits(bs,1) ? -1 : 1; + + coef_compress = (UCHAR) FDKreadBits(bs,1); + + filter->Resolution = coef_res + 3; + + s_mask = sgn_mask[coef_res + 1 - coef_compress]; + n_mask = neg_mask[coef_res + 1 - coef_compress]; + + for (i=0; i < order; i++) + { + coef = (UCHAR) FDKreadBits(bs,filter->Resolution - coef_compress); + filter->Coeff[i] = (coef & s_mask) ? (coef | n_mask) : coef; + } + } + } + } + } + + pTnsData->Active = 1; + + return ErrorStatus; +} + + +static void CTns_Filter (FIXP_DBL *spec, int size, int inc, FIXP_TCC coeff [], int order) +{ + // - Simple all-pole filter of order "order" defined by + // y(n) = x(n) - a(2)*y(n-1) - ... - a(order+1)*y(n-order) + // + // - The state variables of the filter are initialized to zero every time + // + // - The output data is written over the input data ("in-place operation") + // + // - An input vector of "size" samples is processed and the index increment + // to the next data sample is given by "inc" + + int i,j,N; + FIXP_DBL *pSpec; + FIXP_DBL maxVal=FL2FXCONST_DBL(0.0); + INT s; + + FDK_ASSERT(order <= TNS_MAXIMUM_ORDER); + C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER); + FDKmemclear(state, order*sizeof(FIXP_DBL)); + + for (i=0; i FL2FXCONST_DBL(0.03125*0.70710678118) ) + s = fixMax(CntLeadingZeros(maxVal)-6,0); + else + s = fixMax(CntLeadingZeros(maxVal)-5,0); + + s = fixMin(s,2); + s = s-1; + + if (inc == -1) + pSpec = &spec[size - 1]; + else + pSpec = &spec[0]; + + FIXP_TCC *pCoeff; + +#define FIRST_PART_FLTR \ + FIXP_DBL x, *pState = state; \ + pCoeff = coeff; \ + \ + if (s < 0) \ + x = (pSpec [0]>>1) + fMultDiv2 (*pCoeff++, pState [0]) ; \ + else \ + x = (pSpec [0]<> s; \ + *pState =(-x) << 1; \ + pSpec += inc ; + + + if (order>8) + { + N = (order-1)&7; + + for (i = size ; i != 0 ; i--) + { + FIRST_PART_FLTR + + for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE } + + INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE + INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE + + LAST_PART_FLTR + } + + } else if (order>4) { + + N = (order-1)&3; + + for (i = size ; i != 0 ; i--) + { + FIRST_PART_FLTR + for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE } + + INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE INNER_FLTR_INLINE + + LAST_PART_FLTR + } + + } else { + + N = order-1; + + for (i = size ; i != 0 ; i--) + { + FIRST_PART_FLTR + + for (j = N; j > 0 ; j--) { INNER_FLTR_INLINE } + + LAST_PART_FLTR + } + } + + C_ALLOC_SCRATCH_END(state, FIXP_DBL, TNS_MAXIMUM_ORDER); +} + +/*! + \brief Apply tns to spectral lines + + The function applies the tns to the spectrum, + + \return none +*/ +void CTns_Apply ( + CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength + ) +{ + int window,index,start,stop,size; + + + if (pTnsData->Active) + { + C_AALLOC_SCRATCH_START(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER); + + for (window=0; window < GetWindowsPerFrame(pIcsInfo); window++) + { + FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, granuleLength); + + for (index=0; index < pTnsData->NumberOfFilters[window]; index++) + { + CFilter *RESTRICT filter = &pTnsData->Filter[window][index]; + + if (filter->Order > 0) + { + FIXP_TCC *pCoeff; + int tns_max_bands; + + pCoeff = &coeff[filter->Order-1]; + if (filter->Resolution == 3) + { + int i; + for (i=0; i < filter->Order; i++) + *pCoeff-- = FDKaacDec_tnsCoeff3[filter->Coeff[i]+4]; + } + else + { + int i; + for (i=0; i < filter->Order; i++) + *pCoeff-- = FDKaacDec_tnsCoeff4[filter->Coeff[i]+8]; + } + + switch (granuleLength) { + case 480: + tns_max_bands = tns_max_bands_tbl_480[pSamplingRateInfo->samplingRateIndex]; + break; + case 512: + tns_max_bands = tns_max_bands_tbl_512[pSamplingRateInfo->samplingRateIndex]; + break; + default: + tns_max_bands = GetMaximumTnsBands(pIcsInfo, pSamplingRateInfo->samplingRateIndex); + break; + } + + start = fixMin( fixMin(filter->StartBand, tns_max_bands), + GetScaleFactorBandsTransmitted(pIcsInfo) ); + + start = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[start]; + + stop = fixMin( fixMin(filter->StopBand, tns_max_bands), + GetScaleFactorBandsTransmitted(pIcsInfo) ); + + stop = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[stop]; + + size = stop - start; + + if (size > 0) { + CTns_Filter(&pSpectrum[start], + size, + filter->Direction, + coeff, + filter->Order ); + } + } + } + } + C_AALLOC_SCRATCH_END(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER); + } + +} diff --git a/libAACdec/src/aacdec_tns.h b/libAACdec/src/aacdec_tns.h new file mode 100644 index 00000000..f029d963 --- /dev/null +++ b/libAACdec/src/aacdec_tns.h @@ -0,0 +1,126 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: temporal noise shaping tool + +******************************************************************************/ + +#ifndef TNS_H +#define TNS_H + +#include "common_fix.h" + +enum +{ + TNS_MAX_WINDOWS = 8, /* 8 */ + TNS_MAXIMUM_ORDER = 20, /* 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken encoders also do order 20 for AAC-LC :( */ + TNS_MAXIMUM_FILTERS = 3 +}; + +typedef struct +{ + SCHAR Coeff[TNS_MAXIMUM_ORDER]; + + UCHAR StartBand; + UCHAR StopBand; + + SCHAR Direction; + SCHAR Resolution; + + UCHAR Order; +} CFilter; + +typedef struct +{ + CFilter Filter[TNS_MAX_WINDOWS][TNS_MAXIMUM_FILTERS]; + UCHAR NumberOfFilters[TNS_MAX_WINDOWS]; + UCHAR DataPresent; + UCHAR Active; +} CTnsData; + +void CTns_Reset(CTnsData *pTnsData); + +#endif /* #ifndef TNS_H */ diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp new file mode 100644 index 00000000..579e4703 --- /dev/null +++ b/libAACdec/src/aacdecoder.cpp @@ -0,0 +1,1851 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + + +/*! + \page default General Overview of the AAC Decoder Implementation + + The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It handles the different + transport multiplexes and bitstream formats supported by this implementation. It extracts the + AAC_raw_data_blocks from these bitstreams to further process then in the actual decoding stages. + + Note: Click on a function of file in the above image to see details about the function. Also note, that + this is just an overview of the most important functions and not a complete call graph. + +

1 Bitstream deformatter

+ The basic bit stream parser function CChannelElement_Read() is called. It uses other subcalls in order + to parse and unpack the bitstreams. Note, that this includes huffmann decoding of the coded spectral data. + This operation can be computational significant specifically at higher bitrates. Optimization is likely in + CBlock_ReadSpectralData(). + + The bitstream deformatter also includes many bitfield operations. Profiling on the target will determine + required optimizations. + +

2 Actual decoding to retain the time domain output

+ The basic bitstream deformatter function CChannelElement_Decode() for CPE elements and SCE elements are called. + Except for the stereo processing (2.1) which is only used for CPE elements, the function calls for CPE or SCE + are similar, except that CPE always processes to independent channels while SCE only processes one channel. + + Often there is the distinction between long blocks and short blocks. However, computational expensive functions + that ususally require optimization are being shared by these two groups, + +

2.1 Stereo processing for CPE elements

+ CChannelPairElement_Decode() first calles the joint stereo tools in stereo.cpp when required. + +

2.2 Scaling of spectral data

+ CBlock_ScaleSpectralData(). + +

2.3 Apply additional coding tools

+ ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams. + The function TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some optimization. + +

3 Frequency-To-Time conversion

+ The filterbank is called using CBlock_FrequencyToTime() using the MDCT module from the FDK Tools + +*/ + + + +#include "aacdecoder.h" + +#include "aac_rom.h" +#include "aac_ram.h" +#include "channel.h" +#include "FDK_audio.h" + +#include "FDK_tools_rom.h" + + #include "aacdec_pns.h" + + #include "sbrdecoder.h" + + + + + #include "aacdec_hcr.h" + #include "rvlc.h" + + +#include "tpdec_lib.h" + +#include "conceal.h" + + #include "FDK_crc.h" + + +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) +{ + + /* Assign user requested mode */ + self->qmfModeCurr = self->qmfModeUser; + + if ( self->qmfModeCurr == NOT_DEFINED ) + { + if ( (IS_LOWDELAY(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) + || ( (self->streamInfo.aacNumChannels == 1) + && ( (CAN_DO_PS(self->streamInfo.aot) && !(self->flags & AC_MPS_PRESENT)) + || ( IS_USAC(self->streamInfo.aot) && (self->flags & AC_MPS_PRESENT)) ) ) ) + { + self->qmfModeCurr = MODE_HQ; + } else { + self->qmfModeCurr = MODE_LP; + } + } + + + /* Set SBR to current QMF mode. Error does not matter. */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE, (self->qmfModeCurr == MODE_LP)); + self->psPossible = ((CAN_DO_PS(self->streamInfo.aot) && self->streamInfo.aacNumChannels == 1 && ! (self->flags & AC_MPS_PRESENT))) && self->qmfModeCurr == MODE_HQ ; + FDK_ASSERT( ! ( (self->flags & AC_MPS_PRESENT) && self->psPossible ) ); +} + +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) +{ +} + +/*! + \brief Reset ancillary data struct. Call before parsing a new frame. + + \ancData Pointer to ancillary data structure + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) +{ + int i; + for (i=0; i<8; i++) + { + ancData->offset[i] = 0; + } + ancData->nrElements = 0; + + return AAC_DEC_OK; +} + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size) +{ + if (size >= 0) { + ancData->buffer = buffer; + ancData->bufferSize = size; + + CAacDecoder_AncDataReset(ancData); + + return AAC_DEC_OK; + } + + return AAC_DEC_ANC_DATA_ERROR; +} + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data element in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + + *ptr = NULL; + *size = 0; + + if (index >= 0 && index < 8 && index < ancData->nrElements) + { + *ptr = &ancData->buffer[ancData->offset[index]]; + *size = ancData->offset[index+1] - ancData->offset[index]; + } + + return error; +} + + +/*! + \brief Parse ancillary data + + \ancData Pointer to ancillary data structure + \hBs Handle to FDK bitstream + \ancBytes Length of ancillary data to read from the bitstream + + \return Error code +*/ +static +AAC_DECODER_ERROR CAacDecoder_AncDataParse ( + CAncData *ancData, + HANDLE_FDK_BITSTREAM hBs, + const int ancBytes ) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + int readBytes = 0; + + if (ancData->buffer != NULL) + { + if (ancBytes > 0) { + /* write ancillary data to external buffer */ + int offset = ancData->offset[ancData->nrElements]; + + if ((offset + ancBytes) > ancData->bufferSize) + { + error = AAC_DEC_TOO_SMALL_ANC_BUFFER; + } + else if (ancData->nrElements >= 8-1) + { + error = AAC_DEC_TOO_MANY_ANC_ELEMENTS; + } + else + { + int i; + + for (i = 0; i < ancBytes; i++) { + ancData->buffer[i+offset] = FDKreadBits(hBs, 8); + readBytes++; + } + + ancData->nrElements++; + ancData->offset[ancData->nrElements] = ancBytes + ancData->offset[ancData->nrElements-1]; + } + } + } + + readBytes = ancBytes - readBytes; + + if (readBytes > 0) { + /* skip data */ + FDKpushFor(hBs, readBytes<<3); + } + + return error; +} + +/*! + \brief Read Stream Data Element + + \bs Bitstream Handle + + \return Error code +*/ +static AAC_DECODER_ERROR CDataStreamElement_Read ( + HANDLE_AACDECODER self, + HANDLE_FDK_BITSTREAM bs, + UCHAR *elementInstanceTag, + UINT alignmentAnchor ) +{ + HANDLE_TRANSPORTDEC pTp; + CAncData *ancData; + AAC_DECODER_ERROR error = AAC_DEC_OK; + UINT dataStart, dseBits; + int dataByteAlignFlag, count; + + FDK_ASSERT(self != NULL); + + ancData = &self->ancData; + pTp = self->hInput; + + int crcReg = transportDec_CrcStartReg(pTp, 0); + + /* Element Instance Tag */ + *elementInstanceTag = FDKreadBits(bs,4); + /* Data Byte Align Flag */ + dataByteAlignFlag = FDKreadBits(bs,1); + + count = FDKreadBits(bs,8); + + if (count == 255) { + count += FDKreadBits(bs,8); /* EscCount */ + } + dseBits = count*8; + + if (dataByteAlignFlag) { + FDKbyteAlign(bs, alignmentAnchor); + } + + dataStart = FDKgetValidBits(bs); + + error = CAacDecoder_AncDataParse(ancData, bs, count); + transportDec_CrcEndReg(pTp, crcReg); + + { + /* Move to the beginning of the data junk */ + FDKpushBack(bs, dataStart-FDKgetValidBits(bs)); + + /* Read Anc data if available */ + aacDecoder_drcMarkPayload( self->hDrcInfo, bs, DVB_DRC_ANC_DATA ); + } + + { + PCMDMX_ERROR dmxErr = PCMDMX_OK; + + /* Move to the beginning of the data junk */ + FDKpushBack(bs, dataStart-FDKgetValidBits(bs)); + + /* Read DMX meta-data */ + dmxErr = pcmDmx_Parse ( + self->hPcmUtils, + bs, + dseBits, + 0 /* not mpeg2 */ ); + } + + /* Move to the very end of the element. */ + FDKpushBiDirectional(bs, FDKgetValidBits(bs)-dataStart+dseBits); + + return error; +} + +#ifdef TP_PCE_ENABLE +/*! + \brief Read Program Config Element + + \bs Bitstream Handle + \pTp Transport decoder handle for CRC handling + \pce Pointer to PCE buffer + \channelConfig Current channel configuration + \alignAnchor Anchor for byte alignment + + \return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated need re-config). +*/ +static int CProgramConfigElement_Read ( + HANDLE_FDK_BITSTREAM bs, + HANDLE_TRANSPORTDEC pTp, + CProgramConfig *pce, + const UINT channelConfig, + const UINT alignAnchor ) +{ + int pceStatus = 0; + int crcReg; + + /* read PCE to temporal buffer first */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_Init(tmpPce); + CProgramConfig_Reset(tmpPce); + + crcReg = transportDec_CrcStartReg(pTp, 0); + + CProgramConfig_Read(tmpPce, bs, alignAnchor); + + transportDec_CrcEndReg(pTp, crcReg); + + if ( CProgramConfig_IsValid(tmpPce) + && (tmpPce->Profile == 1) ) + { + if ( !pce->isValid && (channelConfig > 0) ) { + /* Create a standard channel config PCE to compare with */ + CProgramConfig_GetDefault( pce, channelConfig ); + } + + if (pce->isValid) { + /* Compare the new and the old PCE (tags ignored) */ + switch ( CProgramConfig_Compare( pce, tmpPce ) ) + { + case 1: /* Channel configuration not changed. Just new metadata. */ + FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */ + pceStatus = 1; /* New PCE but no change of config */ + break; + case 2: /* The number of channels are identical but not the config */ + if (channelConfig == 0) { + FDKmemcpy(pce, tmpPce, sizeof(CProgramConfig)); /* Store the complete PCE */ + pceStatus = 2; /* Decoder needs re-configuration */ + } + break; + case -1: /* The channel configuration is completely different */ + pceStatus = -1; /* Not supported! */ + break; + case 0: /* Nothing to do because PCE matches the old one exactly. */ + default: + /* pceStatus = 0; */ + break; + } + } + } + + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + + return pceStatus; +} +#endif /* TP_PCE_ENABLE */ + +/*! + \brief Parse Extension Payload + + \self Handle of AAC decoder + \count Pointer to bit counter. + \previous_element ID of previous element (required by some extension payloads) + + \return Error code +*/ +static +AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse (HANDLE_AACDECODER self, + HANDLE_FDK_BITSTREAM hBs, + int *count, + MP4_ELEMENT_ID previous_element, + int elIndex, + int fIsFillElement) +{ + AAC_DECODER_ERROR error = AAC_DEC_OK; + EXT_PAYLOAD_TYPE extension_type; + int bytes = (*count) >> 3; + int crcFlag = 0; + + if (*count < 4) { + return AAC_DEC_PARSE_ERROR; + } else if ((INT)FDKgetValidBits(hBs) < *count) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + extension_type = (EXT_PAYLOAD_TYPE) FDKreadBits(hBs, 4); /* bs_extension_type */ + *count -= 4; + + switch (extension_type) + { + case EXT_DYNAMIC_RANGE: + { + INT readBits = aacDecoder_drcMarkPayload( self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA ); + + if (readBits > *count) + { /* Read too much. Something went wrong! */ + error = AAC_DEC_PARSE_ERROR; + } + *count -= readBits; + } + break; + + + case EXT_SBR_DATA_CRC: + crcFlag = 1; + case EXT_SBR_DATA: + if (IS_CHANNEL_ELEMENT(previous_element)) { + SBR_ERROR sbrError; + + CAacDecoder_SyncQmfMode(self); + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, + self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, + self->streamInfo.aot, + previous_element, + elIndex + ); + + if (sbrError == SBRDEC_OK) { + sbrError = sbrDecoder_Parse ( + self->hSbrDecoder, + hBs, + count, + *count, + crcFlag, + previous_element, + elIndex, + self->flags & AC_INDEP ); + /* Enable SBR for implicit SBR signalling but only if no severe error happend. */ + if ( (sbrError == SBRDEC_OK) + || (sbrError == SBRDEC_PARSE_ERROR) ) { + self->sbrEnabled = 1; + } + } else { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2 + Fill elements containing an extension_payload() with an extension_type of EXT_SBR_DATA + or EXT_SBR_DATA_CRC shall not contain any other extension_payload of any other extension_type. + */ + if (fIsFillElement) { + FDKpushBiDirectional(hBs, *count); + *count = 0; + } else { + /* If this is not a fill element with a known length, we are screwed and further parsing makes no sense. */ + if (sbrError != SBRDEC_OK) { + self->frameOK = 0; + } + } + } else { + error = AAC_DEC_PARSE_ERROR; + } + break; + + case EXT_FILL_DATA: + { + int temp; + + temp = FDKreadBits(hBs,4); + bytes--; + if (temp != 0) { + error = AAC_DEC_PARSE_ERROR; + break; + } + while (bytes > 0) { + temp = FDKreadBits(hBs,8); + bytes--; + if (temp != 0xa5) { + error = AAC_DEC_PARSE_ERROR; + break; + } + } + *count = bytes<<3; + } + break; + + case EXT_DATA_ELEMENT: + { + int dataElementVersion; + + dataElementVersion = FDKreadBits(hBs,4); + *count -= 4; + if (dataElementVersion == 0) /* ANC_DATA */ + { + int temp, dataElementLength = 0; + do { + temp = FDKreadBits(hBs,8); + *count -= 8; + dataElementLength += temp; + } while (temp == 255 ); + + CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength); + *count -= (dataElementLength<<3); + } else { + /* align = 0 */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + break; + + case EXT_DATA_LENGTH: + if ( !fIsFillElement /* Makes no sens to have an additional length in a fill ... */ + && (self->flags & AC_ER) ) /* ... element because this extension payload type was ... */ + { /* ... created to circumvent the missing length in ER-Syntax. */ + int bitCnt, len = FDKreadBits(hBs, 4); + *count -= 4; + + if (len == 15) { + int add_len = FDKreadBits(hBs, 8); + *count -= 8; + len += add_len; + + if (add_len == 255) { + len += FDKreadBits(hBs, 16); + *count -= 16; + } + } + len <<= 3; + bitCnt = len; + + if ( (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH ) { + /* Check NOTE 2: The extension_payload() included here must + not have extension_type == EXT_DATA_LENGTH. */ + error = AAC_DEC_PARSE_ERROR; + } else { + /* rewind and call myself again. */ + FDKpushBack(hBs, 4); + + error = + CAacDecoder_ExtPayloadParse ( + self, + hBs, + &bitCnt, + previous_element, + elIndex, + 0 ); + + *count -= len - bitCnt; + } + /* Note: the fall through in case the if statement above is not taken is intentional. */ + break; + } + + case EXT_FIL: + + default: + /* align = 4 */ + FDKpushFor(hBs, *count); + *count = 0; + break; + } + +bail: + if ( (error != AAC_DEC_OK) + && fIsFillElement ) + { /* Skip the remaining extension bytes */ + FDKpushBiDirectional(hBs, *count); + *count = 0; + /* Patch error code because decoding can go on. */ + error = AAC_DEC_OK; + /* Be sure that parsing errors have been stored. */ + } + return error; +} + +/* Stream Configuration and Information. + + This class holds configuration and information data for a stream to be decoded. It + provides the calling application as well as the decoder with substantial information, + e.g. profile, sampling rate, number of channels found in the bitstream etc. +*/ +static +void CStreamInfoInit(CStreamInfo *pStreamInfo) +{ + pStreamInfo->aacSampleRate = 0; + pStreamInfo->profile = -1; + pStreamInfo->aot = AOT_NONE; + + pStreamInfo->channelConfig = -1; + pStreamInfo->bitRate = 0; + pStreamInfo->aacSamplesPerFrame = 0; + + pStreamInfo->extAot = AOT_NONE; + pStreamInfo->extSamplingRate = 0; + + pStreamInfo->flags = 0; + + pStreamInfo->epConfig = -1; /* default is no ER */ + + pStreamInfo->numChannels = 0; + pStreamInfo->sampleRate = 0; + pStreamInfo->frameSize = 0; + + pStreamInfo->outputDelay = 0; + + /* DRC */ + pStreamInfo->drcProgRefLev = -1; /* set program reference level to not indicated */ + pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */ +} + +/*! + \brief Initialization of AacDecoderChannelInfo + + The function initializes the pointers to AacDecoderChannelInfo for each channel, + set the start values for window shape and window sequence of overlap&add to zero, + set the overlap buffer to zero and initializes the pointers to the window coefficients. + \param bsFormat is the format of the AAC bitstream + + \return AACDECODER instance +*/ +LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */ +{ + HANDLE_AACDECODER self; + + self = GetAacDecoder(); + if (self == NULL) { + goto bail; + } + + /* Assign channel mapping info arrays (doing so removes dependency of settings header in API header). */ + self->streamInfo.pChannelIndices = self->channelIndices; + self->streamInfo.pChannelType = self->channelType; + + /* set default output mode */ + self->outputInterleaved = 1; /* interleaved */ + + /* initialize anc data */ + CAacDecoder_AncDataInit(&self->ancData, NULL, 0); + + /* initialize stream info */ + CStreamInfoInit(&self->streamInfo); + + /* initialize error concealment common data */ + CConcealment_InitCommonData(&self->concealCommonData); + + self->hDrcInfo = GetDrcInfo(); + if (self->hDrcInfo == NULL) { + goto bail; + } + /* Init common DRC structure */ + aacDecoder_drcInit( self->hDrcInfo ); + /* Set default frame delay */ + aacDecoder_drcSetParam ( + self->hDrcInfo, + DRC_BS_DELAY, + CConcealment_GetDelay(&self->concealCommonData) + ); + + + self->aacCommonData.workBufferCore1 = GetWorkBufferCore1(); + self->aacCommonData.workBufferCore2 = GetWorkBufferCore2(); + if (self->aacCommonData.workBufferCore1 == NULL + ||self->aacCommonData.workBufferCore2 == NULL ) + goto bail; + + return self; + +bail: + CAacDecoder_Close( self ); + + return NULL; +} + +/* Destroy aac decoder */ +LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) +{ + int ch; + + if (self == NULL) + return; + + for (ch=0; ch<(8); ch++) { + if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) { + FreeOverlapBuffer (&self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer); + } + if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { + FreeAacDecoderStaticChannelInfo (&self->pAacDecoderStaticChannelInfo[ch]); + } + } + if (self->pAacDecoderChannelInfo[ch] != NULL) { + FreeAacDecoderChannelInfo (&self->pAacDecoderChannelInfo[ch]); + } + } + + self->aacChannels = 0; + + if (self->hDrcInfo) { + FreeDrcInfo(&self->hDrcInfo); + } + + if (self->aacCommonData.workBufferCore1 != NULL) { + FreeWorkBufferCore1 (&self->aacCommonData.workBufferCore1); + } + if (self->aacCommonData.workBufferCore2 != NULL) { + FreeWorkBufferCore2 (&self->aacCommonData.workBufferCore2); + } + + FreeAacDecoder ( &self); +} + + +/*! + \brief Initialization of decoder instance + + The function initializes the decoder. + + \return error status: 0 for success, <>0 for unsupported configurations +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc) +{ + AAC_DECODER_ERROR err = AAC_DEC_OK; + INT ascChannels, ch, ascChanged = 0; + + if (!self) + return AAC_DEC_INVALID_HANDLE; + + // set profile and check for supported aot + // leave profile on default (=-1) for all other supported MPEG-4 aot's except aot=2 (=AAC-LC) + switch (asc->m_aot) { + case AOT_AAC_LC: + self->streamInfo.profile = 1; + + case AOT_ER_AAC_SCAL: + if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) { + /* aac_scalable_extension_element() currently not supported. */ + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: + break; + + default: + return AAC_DEC_UNSUPPORTED_AOT; + } + + CProgramConfig_Init(&self->pce); + + /* set channels */ + switch (asc->m_channelConfiguration) { + case 0: +#ifdef TP_PCE_ENABLE + /* get channels from program config (ASC) */ + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + ascChannels = asc->m_progrConfigElement.NumChannels; + if (ascChannels > 0) { + int el; + /* valid number of channels -> copy program config element (PCE) from ASC */ + FDKmemcpy(&self->pce, &asc->m_progrConfigElement, sizeof(CProgramConfig)); + /* Built element table */ + el = CProgramConfig_GetElementTable(&asc->m_progrConfigElement, self->elements, (8), &self->chMapIndex); + for (; el<(8); el++) { + self->elements[el] = ID_NONE; + } + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } else { + self->chMapIndex = 0; + if (transportDec_GetFormat(self->hInput) == TT_MP4_ADTS) { + /* set default max_channels for memory allocation because in implicit channel mapping mode + we don't know the actual number of channels until we processed at least one raw_data_block(). */ + ascChannels = (8); + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } +#else /* TP_PCE_ENABLE */ + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; +#endif /* TP_PCE_ENABLE */ + break; + case 1: case 2: case 3: case 4: case 5: case 6: + ascChannels = asc->m_channelConfiguration; + break; + case 11: + ascChannels = 7; + break; + case 7: case 12: case 14: + ascChannels = 8; + break; + default: + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + if (ascChannels > (8)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Initialize constant mappings for channel config 1-7 */ + if (asc->m_channelConfiguration > 0) { + int el; + FDKmemcpy(self->elements, elementsTab[asc->m_channelConfiguration-1], sizeof(MP4_ELEMENT_ID)*FDKmin(7,(8))); + for (el=7; el<(8); el++) { + self->elements[el] = ID_NONE; + } + for (ch=0; chchMapping[ch] = ch; + } + for (; ch<(8); ch++) { + self->chMapping[ch] = 255; + } + self->chMapIndex = asc->m_channelConfiguration; + } + #ifdef TP_PCE_ENABLE + else { + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils, + asc->m_progrConfigElement.MatrixMixdownIndexPresent, + asc->m_progrConfigElement.MatrixMixdownIndex, + asc->m_progrConfigElement.PseudoSurroundEnable ); + } + } + #endif + + self->streamInfo.channelConfig = asc->m_channelConfiguration; + + if (self->streamInfo.aot != asc->m_aot) { + self->streamInfo.aot = asc->m_aot; + ascChanged = 1; + } + + if (self->streamInfo.aacSamplesPerFrame != (INT)asc->m_samplesPerFrame) { + self->streamInfo.aacSamplesPerFrame = asc->m_samplesPerFrame; + ascChanged = 1; + } + + self->streamInfo.bitRate = 0; + + /* Set syntax flags */ + self->flags = 0; + + self->streamInfo.extAot = asc->m_extensionAudioObjectType; + self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency; + self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; + self->flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0; + self->sbrEnabled = 0; + + /* --------- vcb11 ------------ */ + self->flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0; + + /* ---------- rvlc ------------ */ + self->flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0; + + /* ----------- hcr ------------ */ + self->flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + self->flags |= AC_ELD; + self->flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; /* Need to set the SBR flag for backward-compatibility + reasons. Even if SBR is not supported. */ + self->flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0; + self->flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_LD_MPS : 0; + } + self->flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0; + self->flags |= (asc->m_epConfig >= 0) ? AC_ER : 0; + if ( asc->m_aot == AOT_DRM_AAC ) { + self->flags |= AC_DRM|AC_SBRCRC|AC_SCALABLE; + } + if ( (asc->m_aot == AOT_AAC_SCAL) + || (asc->m_aot == AOT_ER_AAC_SCAL) ) { + self->flags |= AC_SCALABLE; + } + + + if (asc->m_sbrPresentFlag) { + self->sbrEnabled = 1; + self->sbrEnabledPrev = 1; + } + if (asc->m_psPresentFlag) { + self->flags |= AC_PS_PRESENT; + } + + if ( (asc->m_epConfig >= 0) + && (asc->m_channelConfiguration <= 0) ) { + /* we have to know the number of channels otherwise no decoding is possible */ + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + } + + self->streamInfo.epConfig = asc->m_epConfig; + /* self->hInput->asc.m_epConfig = asc->m_epConfig; */ + + if (asc->m_epConfig > 1) + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + + /* Check if samplerate changed. */ + if (self->streamInfo.aacSampleRate != (INT)asc->m_samplingFrequency) { + AAC_DECODER_ERROR error; + + ascChanged = 1; + + /* Update samplerate info. */ + error = getSamplingRateInfo(&self->samplingRateInfo, asc->m_samplesPerFrame, asc->m_samplingFrequencyIndex, asc->m_samplingFrequency); + if (error != AAC_DEC_OK) { + return error; + } + self->streamInfo.aacSampleRate = self->samplingRateInfo.samplingRate; + } + + /* Check if amount of channels has changed. */ + if (self->ascChannels != ascChannels) + { + ascChanged = 1; + + /* Allocate all memory structures for each channel */ + { + for (ch = 0; ch < ascChannels; ch++) { + CAacDecoderDynamicData *aacDecoderDynamicData = &self->aacCommonData.workBufferCore1->pAacDecoderDynamicData[ch%2]; + + /* initialize pointer to CAacDecoderChannelInfo */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch); + /* This is temporary until the DynamicData is split into two or more regions! + The memory could be reused after completed core decoding. */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + goto bail; + } + /* Hook shared work memory into channel data structure */ + self->pAacDecoderChannelInfo[ch]->pDynData = aacDecoderDynamicData; + self->pAacDecoderChannelInfo[ch]->pComData = &self->aacCommonData; + } + + /* Allocate persistent channel memory */ + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + self->pAacDecoderStaticChannelInfo[ch] = GetAacDecoderStaticChannelInfo(ch); + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + goto bail; + } + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer = GetOverlapBuffer(ch); /* This area size depends on the AOT */ + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) { + goto bail; + } + self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient = (SPECTRAL_PTR) &self->aacCommonData.workBufferCore2[ch*1024]; + + } + CPns_InitPns(&self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, &self->aacCommonData.pnsInterChannelData, &self->aacCommonData.pnsCurrentSeed, self->aacCommonData.pnsRandomSeed); + } + + if (ascChannels > self->aacChannels) + { + /* Make allocated channel count persistent in decoder context. */ + self->aacChannels = ascChannels; + } + + HcrInitRom(&self->aacCommonData.overlay.aac.erHcrInfo); + setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, ID_SCE); + } + + /* Make amount of signalled channels persistent in decoder context. */ + self->ascChannels = ascChannels; + } + + /* Update structures */ + if (ascChanged) { + + /* Things to be done for each channel, which do not involve allocating memory. + Doing these things only on the channels needed for the current configuration + (ascChannels) could lead to memory access violation later (error concealment). */ + for (ch = 0; ch < self->aacChannels; ch++) { + switch (self->streamInfo.aot) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame; + break; + default: + self->pAacDecoderChannelInfo[ch]->granuleLength = self->streamInfo.aacSamplesPerFrame / 8; + break; + } + mdct_init( &self->pAacDecoderStaticChannelInfo[ch]->IMdct, + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize ); + + + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[ch]->drcData ); + + /* Reset concealment only if ASC changed. Otherwise it will be done with any config callback. + E.g. every time the LATM SMC is present. */ + CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->streamInfo.aacSamplesPerFrame ); + } + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags; + + return err; + +bail: + aacDecoder_Close( self ); + return AAC_DEC_OUT_OF_MEMORY; +} + + +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, + const UINT flags, + INT_PCM *pTimeData, + const INT timeDataSize, + const INT interleaved + ) +{ + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + CProgramConfig *pce; + HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0); + + MP4_ELEMENT_ID type = ID_NONE; /* Current element type */ + INT aacChannels=0; /* Channel counter for channels found in the bitstream */ + int chOutMapIdx; /* Output channel mapping index (see comment below) */ + + INT auStartAnchor = (INT)FDKgetValidBits(bs); /* AU start bit buffer position for AU byte alignment */ + + self->frameOK = 1; + + /* Any supported base layer valid AU will require more than 16 bits. */ + if ( (transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) && (flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) == 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + + /* Reset Program Config structure */ + pce = &self->pce; + CProgramConfig_Reset(pce); + + CAacDecoder_AncDataReset(&self->ancData); + + { + int ch; + + if (self->streamInfo.channelConfig == 0) { + /* Init Channel/Element mapping table */ + for (ch=0; ch<(8); ch++) { + self->chMapping[ch] = 255; + } + if (!CProgramConfig_IsValid(pce)) { + int el; + for (el=0; el<(8); el++) { + self->elements[el] = ID_NONE; + } + } + } + } + + /* Check sampling frequency */ + switch ( self->streamInfo.aacSampleRate ) { + case 96000: + case 88200: + case 64000: + case 16000: + case 12000: + case 11025: + case 8000: + case 7350: + case 48000: + case 44100: + case 32000: + case 24000: + case 22050: + break; + default: + if ( ! (self->flags & (AC_USAC|AC_RSVD50)) ) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + break; + } + + + if ( flags & AACDEC_CLRHIST ) + { + int ch; + /* Clear history */ + for (ch = 0; ch < self->aacChannels; ch++) { + /* Reset concealment */ + CConcealment_InitChannelData(&self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->streamInfo.aacSamplesPerFrame ); + /* Clear overlap-add buffers to avoid clicks. */ + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL)); + } + } + + + +#ifdef TP_PCE_ENABLE + int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */ +#endif + + + INT hdaacDecoded = 0; + MP4_ELEMENT_ID previous_element = ID_END; /* Last element ID (required for extension payload mapping */ + UCHAR previous_element_index = 0; /* Canonical index of last element */ + int element_count = 0; /* Element counter for elements found in the bitstream */ + int el_cnt[ID_LAST] = { 0 }; /* element counter ( robustness ) */ + + while ( (type != ID_END) && (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) && self->frameOK ) + { + int el_channels; + + if (! (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_SCALABLE|AC_ER))) + type = (MP4_ELEMENT_ID) FDKreadBits(bs,3); + else + type = self->elements[element_count]; + + setHcrType(&self->aacCommonData.overlay.aac.erHcrInfo, type); + + + if ((INT)FDKgetValidBits(bs) < 0) + self->frameOK = 0; + + switch (type) + { + case ID_SCE: + case ID_CPE: + case ID_LFE: + /* + Consistency check + */ + + if (type == ID_CPE) { + el_channels = 2; + } else { + el_channels = 1; + } + + if ( (el_cnt[type] >= (self->ascChannels>>(el_channels-1))) || (aacChannels > (self->ascChannels-el_channels)) ) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if ( !(self->flags & (AC_USAC|AC_RSVD50)) ) { + int ch; + for (ch=0; ch < el_channels; ch+=1) { + CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels+ch]->data.aac.PnsData, + &self->pAacDecoderChannelInfo[aacChannels+ch]->pComData->pnsInterChannelData); + } + } + + if(self->frameOK) { + ErrorStatus = CChannelElement_Read( bs, + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + self->streamInfo.aot, + &self->samplingRateInfo, + self->flags, + self->streamInfo.aacSamplesPerFrame, + el_channels, + self->streamInfo.epConfig, + self->hInput + ); + if (ErrorStatus) { + self->frameOK = 0; + } + } + + + if ( self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current program */ + if ( CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag, + aacChannels, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + if ( !hdaacDecoded ) { + CChannelElement_Decode( + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + &self->samplingRateInfo, + self->flags, + el_channels + ); + } + aacChannels += 1; + if (type == ID_CPE) { + aacChannels += 1; + } + } + else { + self->frameOK = 0; + } + /* Create SBR element for SBR for upsampling for LFE elements, + and if SBR was explicitly signaled, because the first frame(s) + may not contain SBR payload (broken encoder, bit errors). */ + if ( (self->flags & AC_SBR_PRESENT) || (self->sbrEnabled == 1) ) + { + SBR_ERROR sbrError; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, + self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, + self->streamInfo.aot, + type, + previous_element_index + ); + if (sbrError != SBRDEC_OK) { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + } + } + + el_cnt[type]++; + break; + + case ID_CCE: + /* + Consistency check + */ + if ( el_cnt[type] > self->ascChannels ) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if (self->frameOK) + { + /* memory for spectral lines temporal on scratch */ + C_ALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024); + + /* create dummy channel for CCE parsing on stack */ + CAacDecoderChannelInfo tmpAacDecoderChannelInfo, *pTmpAacDecoderChannelInfo; + + FDKmemclear(mdctSpec, 1024*sizeof(FIXP_DBL)); + + tmpAacDecoderChannelInfo.pDynData = self->aacCommonData.workBufferCore1->pAacDecoderDynamicData; + tmpAacDecoderChannelInfo.pComData = &self->aacCommonData; + tmpAacDecoderChannelInfo.pSpectralCoefficient = (SPECTRAL_PTR)mdctSpec; + /* Assume AAC-LC */ + tmpAacDecoderChannelInfo.granuleLength = self->streamInfo.aacSamplesPerFrame / 8; + + /* Reset PNS data. */ + CPns_ResetData(&tmpAacDecoderChannelInfo.data.aac.PnsData, &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData); + + pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo; + /* do CCE parsing */ + ErrorStatus = CChannelElement_Read( bs, + &pTmpAacDecoderChannelInfo, + NULL, + self->streamInfo.aot, + &self->samplingRateInfo, + self->flags, + self->streamInfo.aacSamplesPerFrame, + 1, + self->streamInfo.epConfig, + self->hInput + ); + + C_ALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024); + + if (ErrorStatus) { + self->frameOK = 0; + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current program */ + if (CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + pTmpAacDecoderChannelInfo->ElementInstanceTag, + 0, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + /* decoding of CCE not supported */ + } + else { + self->frameOK = 0; + } + } + } + el_cnt[type]++; + break; + + case ID_DSE: + { + UCHAR element_instance_tag; + + CDataStreamElement_Read( self, + bs, + &element_instance_tag, + auStartAnchor ); + + if (!CProgramConfig_LookupElement( + pce, + self->streamInfo.channelConfig, + element_instance_tag, + 0, + self->chMapping, + self->channelType, + self->channelIndices, + &previous_element_index, + self->elements, + type) ) + { + /* most likely an error in bitstream occured */ + //self->frameOK = 0; + } + } + break; + +#ifdef TP_PCE_ENABLE + case ID_PCE: + { + int result = CProgramConfigElement_Read( + bs, + self->hInput, + pce, + self->streamInfo.channelConfig, + auStartAnchor ); + if ( result < 0 ) { + /* Something went wrong */ + ErrorStatus = AAC_DEC_PARSE_ERROR; + self->frameOK = 0; + } + else if ( result > 1 ) { + /* Built element table */ + int elIdx = CProgramConfig_GetElementTable(pce, self->elements, (8), &self->chMapIndex); + /* Reset the remaining tabs */ + for ( ; elIdx<(8); elIdx++) { + self->elements[elIdx] = ID_NONE; + } + /* Make new number of channel persistant */ + self->ascChannels = pce->NumChannels; + /* If PCE is not first element conceal this frame to avoid inconsistencies */ + if ( element_count != 0 ) { + self->frameOK = 0; + } + } + pceRead = (result>=0) ? 1 : 0; + } + break; +#endif /* TP_PCE_ENABLE */ + + case ID_FIL: + { + int bitCnt = FDKreadBits(bs,4); /* bs_count */ + + if (bitCnt == 15) + { + int esc_count = FDKreadBits(bs,8); /* bs_esc_count */ + bitCnt = esc_count + 14; + } + + /* Convert to bits */ + bitCnt <<= 3; + + while (bitCnt > 0) { + ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 1); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + break; + } + } + } + break; + + case ID_EXT: + { + INT bitCnt = 0; + + /* get the remaining bits of this frame */ + bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); + + if ( (bitCnt > 0) && (self->flags & AC_SBR_PRESENT) && (self->flags & (AC_USAC|AC_RSVD50|AC_ELD|AC_DRM)) ) + { + SBR_ERROR err = SBRDEC_OK; + int elIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE]; + + for (elIdx = 0; elIdx < numChElements; elIdx += 1) + { + err = sbrDecoder_Parse ( + self->hSbrDecoder, + bs, + &bitCnt, + -1, + self->flags & AC_SBRCRC, + self->elements[elIdx], + elIdx, + self->flags & AC_INDEP ); + + if (err != SBRDEC_OK) { + break; + } + } + switch (err) { + case SBRDEC_PARSE_ERROR: + /* Can not go on parsing because we do not + know the length of the SBR extension data. */ + FDKpushFor(bs, bitCnt); + bitCnt = 0; + break; + case SBRDEC_OK: + self->sbrEnabled = 1; + break; + default: + self->frameOK = 0; + break; + } + } + + + if (self->flags & AC_DRM) + { + if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) { + FDKpushBiDirectional(bs, bitCnt); + } + } + + if ( ! (self->flags & (AC_USAC|AC_RSVD50|AC_DRM)) ) + { + while ( bitCnt > 7 ) { + ErrorStatus = CAacDecoder_ExtPayloadParse(self, bs, &bitCnt, previous_element, previous_element_index, 0); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + } + } + } + break; + + case ID_END: + break; + + default: + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + previous_element = type; + element_count++; + + } /* while ( (type != ID_END) ... ) */ + + if ( !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) ) + { + /* Byte alignment with respect to the first bit of the raw_data_block(). */ + { + FDKbyteAlign(bs, auStartAnchor); + } + + /* Check if all bits of the raw_data_block() have been read. */ + if ( transportDec_GetAuBitsTotal(self->hInput, 0) > 0 ) { + INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0); + if ( unreadBits != 0 ) { + + self->frameOK = 0; + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + /* Always put the bitbuffer at the right position after the current Access Unit. */ + FDKpushBiDirectional(bs, unreadBits); + } + } + + /* Check the last element. The terminator (ID_END) has to be the last one (even if ER syntax is used). */ + if ( self->frameOK && type != ID_END ) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + self->frameOK = 0; + } + } + + /* More AAC channels than specified by the ASC not allowed. */ + if ( (aacChannels == 0 || aacChannels > self->aacChannels) && !(flags & (AACDEC_CONCEAL|AACDEC_FLUSH)) ) { + { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + self->frameOK = 0; + } + aacChannels = 0; + } + else if ( aacChannels > self->ascChannels ) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + } + self->frameOK = 0; + aacChannels = 0; + } + + if ( TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput) ) + { + self->frameOK=0; + } + + /* store or restore the number of channels and the corresponding info */ + if ( self->frameOK && !(flags &(AACDEC_CONCEAL|AACDEC_FLUSH)) ) { + self->aacChannelsPrev = aacChannels; /* store */ + FDKmemcpy(self->channelTypePrev, self->channelType, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* store */ + FDKmemcpy(self->channelIndicesPrev, self->channelIndices, (8)*sizeof(UCHAR)); /* store */ + self->sbrEnabledPrev = self->sbrEnabled; + } else { + if (self->aacChannels > 0) { + aacChannels = self->aacChannelsPrev; /* restore */ + FDKmemcpy(self->channelType, self->channelTypePrev, (8)*sizeof(AUDIO_CHANNEL_TYPE)); /* restore */ + FDKmemcpy(self->channelIndices, self->channelIndicesPrev, (8)*sizeof(UCHAR)); /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } + } + + /* Update number of output channels */ + self->streamInfo.aacNumChannels = aacChannels; + + #ifdef TP_PCE_ENABLE + if (pceRead == 1 && CProgramConfig_IsValid(pce)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce ( self->hPcmUtils, + pce->MatrixMixdownIndexPresent, + pce->MatrixMixdownIndex, + pce->PseudoSurroundEnable ); + } + #endif + + /* If there is no valid data to transfrom into time domain, return. */ + if ( ! IS_OUTPUT_VALID(ErrorStatus) ) { + return ErrorStatus; + } + + /* Setup the output channel mapping. The table below shows the four possibilities: + * # | chCfg | PCE | cChCfg | chOutMapIdx + * ---+-------+-----+--------+------------------ + * 1 | > 0 | no | - | chCfg + * 2 | 0 | yes | > 0 | cChCfg + * 3 | 0 | yes | 0 | aacChannels || 0 + * 4 | 0 | no | - | aacChannels || 0 + * ---+-------+-----+--------+------------------ + * Where chCfg is the channel configuration index from ASC and cChCfg is a corresponding chCfg + * derived from a given PCE. The variable aacChannels represents the number of channel found + * during bitstream decoding. Due to the structure of the mapping table it can only be used for + * mapping if its value is smaller than 7. Otherwise we use the fallback (0) which is a simple + * pass-through. The possibility #4 should appear only with MPEG-2 (ADTS) streams. This is + * mode is called "implicit channel mapping". + */ + chOutMapIdx = ((self->chMapIndex==0) && (aacChannels<7)) ? aacChannels : self->chMapIndex; + + /* + Inverse transform + */ + { + int stride, offset, c; + + /* Turn on/off DRC modules level normalization in digital domain depending on the limiter status. */ + aacDecoder_drcSetParam( self->hDrcInfo, APPLY_NORMALIZATION, (self->limiterEnableCurr) ? 0 : 1 ); + /* Extract DRC control data and map it to channels (without bitstream delay) */ + aacDecoder_drcProlog ( + self->hDrcInfo, + bs, + self->pAacDecoderStaticChannelInfo, + self->pce.ElementInstanceTag, + self->chMapping, + aacChannels + ); + + /* "c" iterates in canonical MPEG channel order */ + for (c=0; c < aacChannels; c++) + { + CAacDecoderChannelInfo *pAacDecoderChannelInfo; + + /* Select correct pAacDecoderChannelInfo for current channel */ + if (self->chMapping[c] >= aacChannels) { + pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[c]; + } else { + pAacDecoderChannelInfo = self->pAacDecoderChannelInfo[self->chMapping[c]]; + } + + /* Setup offset and stride for time buffer traversal. */ + if (interleaved) { + stride = aacChannels; + offset = self->channelOutputMapping[chOutMapIdx][c]; + } else { + stride = 1; + offset = self->channelOutputMapping[chOutMapIdx][c] * self->streamInfo.aacSamplesPerFrame; + } + + + if ( flags&AACDEC_FLUSH ) { + /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with AACDEC_FLUSH set it contains undefined data. */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame); + } + + /* + Conceal defective spectral data + */ + CConcealment_Apply(&self->pAacDecoderStaticChannelInfo[c]->concealmentInfo, + pAacDecoderChannelInfo, + self->pAacDecoderStaticChannelInfo[c], + &self->samplingRateInfo, + self->streamInfo.aacSamplesPerFrame, + 0, + (self->frameOK && !(flags&AACDEC_CONCEAL)), + self->flags + ); + + + if (flags & (AACDEC_INTR|AACDEC_CLRHIST)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData ( &self->pAacDecoderStaticChannelInfo[c]->drcData ); + } + /* The DRC module demands to be called with the gain field holding the gain scale. */ + self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING; + /* DRC processing */ + aacDecoder_drcApply ( + self->hDrcInfo, + self->hSbrDecoder, + pAacDecoderChannelInfo, + &self->pAacDecoderStaticChannelInfo[c]->drcData, + self->extGain, + c, + self->streamInfo.aacSamplesPerFrame, + self->sbrEnabled + ); + + switch (pAacDecoderChannelInfo->renderMode) + { + case AACDEC_RENDER_IMDCT: + CBlock_FrequencyToTime( + self->pAacDecoderStaticChannelInfo[c], + pAacDecoderChannelInfo, + pTimeData + offset, + self->streamInfo.aacSamplesPerFrame, + stride, + (self->frameOK && !(flags&AACDEC_CONCEAL)), + self->aacCommonData.workBufferCore1->mdctOutTemp + ); + self->extGainDelay = self->streamInfo.aacSamplesPerFrame; + break; + case AACDEC_RENDER_ELDFB: + CBlock_FrequencyToTimeLowDelay( + self->pAacDecoderStaticChannelInfo[c], + pAacDecoderChannelInfo, + pTimeData + offset, + self->streamInfo.aacSamplesPerFrame, + stride + ); + self->extGainDelay = (self->streamInfo.aacSamplesPerFrame*2 - self->streamInfo.aacSamplesPerFrame/2 - 1)/2; + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + break; + } + if ( flags&AACDEC_FLUSH ) { + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, sizeof(FIXP_DBL)*self->streamInfo.aacSamplesPerFrame); + FDKmemclear(self->pAacDecoderStaticChannelInfo[c]->pOverlapBuffer, OverlapBufferSize*sizeof(FIXP_DBL)); + } + } + + + /* Extract DRC control data and map it to channels (with bitstream delay) */ + aacDecoder_drcEpilog ( + self->hDrcInfo, + bs, + self->pAacDecoderStaticChannelInfo, + self->pce.ElementInstanceTag, + self->chMapping, + aacChannels + ); + } + + /* Add additional concealment delay */ + self->streamInfo.outputDelay += CConcealment_GetDelay(&self->concealCommonData) * self->streamInfo.aacSamplesPerFrame; + + /* Map DRC data to StreamInfo structure */ + aacDecoder_drcGetInfo ( + self->hDrcInfo, + &self->streamInfo.drcPresMode, + &self->streamInfo.drcProgRefLev + ); + + /* Reorder channel type information tables. */ + { + AUDIO_CHANNEL_TYPE types[(8)]; + UCHAR idx[(8)]; + int c; + + FDK_ASSERT(sizeof(self->channelType) == sizeof(types)); + FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx)); + + FDKmemcpy(types, self->channelType, sizeof(types)); + FDKmemcpy(idx, self->channelIndices, sizeof(idx)); + + for (c=0; cchannelType[self->channelOutputMapping[chOutMapIdx][c]] = types[c]; + self->channelIndices[self->channelOutputMapping[chOutMapIdx][c]] = idx[c]; + } + } + + self->blockNumber++; + + return ErrorStatus; +} + +/*! + \brief returns the streaminfo pointer + + The function hands back a pointer to the streaminfo structure + + \return pointer to the struct +*/ +LINKSPEC_CPP CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self ) +{ + if (!self) { + return NULL; + } + return &self->streamInfo; +} + + + + diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h new file mode 100644 index 00000000..25bc35dd --- /dev/null +++ b/libAACdec/src/aacdecoder.h @@ -0,0 +1,325 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + +#ifndef AACDECODER_H +#define AACDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" + +#include "channel.h" + +#include "tpdec_lib.h" +#include "FDK_audio.h" + +#include "block.h" + +#include "genericStds.h" + + +#include "sbrdecoder.h" + + +#include "aacdec_drc.h" + + #include "pcmutils_lib.h" + #include "limiter.h" + + +/* Capabilities flags */ +#define CAPF_AAC_LC 0x00000001 +#define CAPF_AAC_LD 0x00000002 +#define CAPF_AAC_SCAL 0x00000004 +#define CAPF_AAC_ER 0x00000008 +#define CAPF_AAC_480 0x00000010 +#define CAPF_AAC_512 0x00000020 +#define CAPF_AAC_960 0x00000040 +#define CAPF_AAC_1024 0x00000080 +#define CAPF_AAC_HCR 0x00000100 +#define CAPF_AAC_VCB11 0x00000200 +#define CAPF_AAC_RVLC 0x00000400 +#define CAPF_AAC_MPEG4 0x00000800 /* PNS */ +#define CAPF_AAC_DRC 0x00001000 +#define CAPF_AAC_CONCEAL 0x00002000 +#define CAPF_AAC_DRM_BSFORMAT 0x00004000 +#define CAPF_AAC_BSAC 0x00008000 + +typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER; + + +enum +{ + L = 0, + R = 1 +}; + +typedef struct { + unsigned char *buffer; + int bufferSize; + int offset[8]; + int nrElements; +} CAncData; + +typedef enum { + NOT_DEFINED = -1, + MODE_HQ = 0, + MODE_LP = 1 +} QMF_MODE; + +typedef struct { + int bsDelay; +} SBR_PARAMS; + + +/* AAC decoder (opaque toward userland) struct declaration */ +struct AAC_DECODER_INSTANCE { + INT aacChannels; /*!< Amount of AAC decoder channels allocated. */ + INT ascChannels; /*!< Amount of AAC decoder channels signalled in ASC. */ + INT blockNumber; /*!< frame counter */ + + INT nrOfLayers; + + INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). */ + + HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */ + + SamplingRateInfo samplingRateInfo; /*!< Sampling Rate information table */ + + UCHAR frameOK; /*!< Will be unset if a consistency check, e.g. CRC etc. fails */ + + UINT flags; /*!< Flags for internal decoder use. DO NOT USE self::streaminfo::flags ! */ + + MP4_ELEMENT_ID elements[(8)]; /*!< Table where the element Id's are listed */ + UCHAR elTags[(8)]; /*!< Table where the elements id Tags are listed */ + UCHAR chMapping[(8)]; /*!< Table of MPEG canonical order to bitstream channel order mapping. */ + + AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output audio channel (from 0 upto numChannels). */ + UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio channel (from 0 upto numChannels). */ + /* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a program_config_element() */ + + + const UCHAR (*channelOutputMapping)[8]; /*!< Table for MPEG canonical order to output channel order mapping. */ + UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping table. This is required + because not all 8 channel configurations have the same output mapping. */ + + CProgramConfig pce; + CStreamInfo streamInfo; /*!< pointer to StreamInfo data (read from the bitstream) */ + CAacDecoderChannelInfo *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */ + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */ + + CAacDecoderCommonData aacCommonData; /*!< Temporal shared data for all channels hooked into pAacDecoderChannelInfo */ + + CConcealParams concealCommonData; + + INT aacChannelsPrev; /*!< The amount of AAC core channels of the last successful decode call. */ + AUDIO_CHANNEL_TYPE channelTypePrev[(8)]; /*!< Array holding the channelType values of the last successful decode call. */ + UCHAR channelIndicesPrev[(8)]; /*!< Array holding the channelIndices values of the last successful decode call. */ + + + HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */ + UCHAR sbrEnabled; /*!< flag to store if SBR has been detected */ + UCHAR sbrEnabledPrev; /*!< flag to store if SBR has been detected from previous frame */ + UCHAR psPossible; /*!< flag to store if PS is possible */ + SBR_PARAMS sbrParams; /*!< struct to store all sbr parameters */ + + QMF_MODE qmfModeCurr; /*!< The current QMF mode */ + QMF_MODE qmfModeUser; /*!< The QMF mode requested by the library user */ + + HANDLE_AAC_DRC hDrcInfo; /*!< handle to DRC data structure */ + + + CAncData ancData; /*!< structure to handle ancillary data */ + + HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */ + TDLimiterPtr hLimiter; /*!< Handle of time domain limiter. */ + UCHAR limiterEnableUser; /*!< The limiter configuration requested by the library user */ + UCHAR limiterEnableCurr; /*!< The current limiter configuration. */ + + FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ + UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ + + INT_PCM pcmOutputBuffer[(8)*(2048)]; + +}; + + +#define AAC_DEBUG_EXTHLP "\ +--- AAC-Core ---\n\ + 0x00010000 Header data\n\ + 0x00020000 CRC data\n\ + 0x00040000 Channel info\n\ + 0x00080000 Section data\n\ + 0x00100000 Scalefactor data\n\ + 0x00200000 Pulse data\n\ + 0x00400000 Tns data\n\ + 0x00800000 Quantized spectrum\n\ + 0x01000000 Requantized spectrum\n\ + 0x02000000 Time output\n\ + 0x04000000 Fatal errors\n\ + 0x08000000 Buffer fullness\n\ + 0x10000000 Average bitrate\n\ + 0x20000000 Synchronization\n\ + 0x40000000 Concealment\n\ + 0x7FFF0000 all AAC-Core-Info\n\ +" + +/** + * \brief Synchronise QMF mode for all modules using QMF data. + * \param self decoder handle + */ +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self); + +/** + * \brief Signal a bit stream interruption to the decoder + * \param self decoder handle + */ +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self); + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, unsigned char *buffer, int size); + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data element + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, unsigned char **ptr, int *size); + + +/* initialization of aac decoder */ +LINKSPEC_H HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat); + +/* Initialization of stream-info elements */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, + const CSAudioSpecificConfig *asc); + +/*! + \brief Decodes one aac frame + + The function decodes one aac frame. The decoding of coupling channel + elements are not supported. The transport layer might signal, that the + data of the current frame is invalid, e.g. as a result of a packet + loss in streaming mode. + The bitstream position of transportDec_GetBitstream(self->hInput) must + be exactly the end of the access unit, including all byte alignment bits. + For this purpose, the variable auStartAnchor is used. + + \return error status +*/ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, + const UINT flags, + INT_PCM *pTimeData, + const INT timeDataSize, + const INT interleaved + ); + +/* Destroy aac decoder */ +LINKSPEC_H void CAacDecoder_Close ( HANDLE_AACDECODER self ); + +/* get streaminfo handle from decoder */ +LINKSPEC_H CStreamInfo* CAacDecoder_GetStreamInfo ( HANDLE_AACDECODER self ); + + +#endif /* #ifndef AACDECODER_H */ diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp new file mode 100644 index 00000000..50efb0fd --- /dev/null +++ b/libAACdec/src/aacdecoder_lib.cpp @@ -0,0 +1,1165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Manuel Jander + Description: + +******************************************************************************/ + +#include "aacdecoder_lib.h" + +#include "aac_ram.h" +#include "aacdecoder.h" +#include "tpdec_lib.h" +#include "FDK_core.h" /* FDK_tools version info */ + + + #include "sbrdecoder.h" + + + + +#include "conceal.h" + + #include "aacdec_drc.h" + + + +/* Decoder library info */ +#define AACDECODER_LIB_VL0 2 +#define AACDECODER_LIB_VL1 5 +#define AACDECODER_LIB_VL2 17 +#define AACDECODER_LIB_TITLE "AAC Decoder Lib" +#ifdef __ANDROID__ +#define AACDECODER_LIB_BUILD_DATE "" +#define AACDECODER_LIB_BUILD_TIME "" +#else +#define AACDECODER_LIB_BUILD_DATE __DATE__ +#define AACDECODER_LIB_BUILD_TIME __TIME__ +#endif + +static AAC_DECODER_ERROR +setConcealMethod ( const HANDLE_AACDECODER self, + const INT method ); + + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_GetFreeBytes ( const HANDLE_AACDECODER self, UINT *pFreeBytes){ + + /* reset free bytes */ + *pFreeBytes = 0; + + /* check handle */ + if(!self) + return AAC_DEC_INVALID_HANDLE; + + /* return nr of free bytes */ + HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0); + *pFreeBytes = FDKgetFreeBits(hBs) >> 3; + + /* success */ + return AAC_DEC_OK; +} + +/** + * Config Decoder using a CSAudioSpecificConfig struct. + */ +static +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config(HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct) +{ + AAC_DECODER_ERROR err; + + /* Initialize AAC core decoder, and update self->streaminfo */ + err = CAacDecoder_Init(self, pAscStruct); + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw ( + HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[] ) +{ + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + UINT layer, nrOfLayers = self->nrOfLayers; + + for(layer = 0; layer < nrOfLayers; layer++){ + if(length[layer] > 0){ + errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], length[layer], layer); + if (errTp != TRANSPORTDEC_OK) { + switch (errTp) { + case TRANSPORTDEC_NEED_TO_RESTART: + err = AAC_DEC_NEED_TO_RESTART; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + err = AAC_DEC_UNSUPPORTED_FORMAT; + break; + default: + err = AAC_DEC_UNKNOWN; + break; + } + /* if baselayer is OK we continue decoding */ + if(layer >= 1){ + self->nrOfLayers = layer; + err = AAC_DEC_OK; + } + break; + } + } + } + + return err; +} + + + +static INT aacDecoder_ConfigCallback(void *handle, const CSAudioSpecificConfig *pAscStruct) +{ + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + + { + { + err = aacDecoder_Config(self, pAscStruct); + } + } + if (err == AAC_DEC_OK) { + if ( self->flags & (AC_USAC|AC_RSVD50|AC_LD|AC_ELD) + && CConcealment_GetDelay(&self->concealCommonData) > 0 ) + { + /* Revert to error concealment method Noise Substitution. + Because interpolation is not implemented for USAC/RSVD50 or + the additional delay is unwanted for low delay codecs. */ + setConcealMethod(self, 1); +#ifdef DEBUG + FDKprintf(" Concealment method was reverted to 1 !\n"); +#endif + } + errTp = TRANSPORTDEC_OK; + } else { + if (IS_INIT_ERROR(err)) { + errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } /* Fatal errors */ + else if (err == AAC_DEC_NEED_TO_RESTART) { + errTp = TRANSPORTDEC_NEED_TO_RESTART; + } else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + return errTp; +} + + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_AncDataInit ( HANDLE_AACDECODER self, + UCHAR *buffer, + int size ) +{ + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataInit(ancData, buffer, size); +} + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_AncDataGet ( HANDLE_AACDECODER self, + int index, + UCHAR **ptr, + int *size ) +{ + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataGet(ancData, index, ptr, size); +} + + +static AAC_DECODER_ERROR +setConcealMethod ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const INT method ) +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + HANDLE_SBRDECODER hSbrDec = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + CConcealmentMethod backupMethod = ConcealMethodNone; + int backupDelay = 0; + int bsDelay = 0; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hSbrDec = self->hSbrDecoder; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + } + + + /* Get current method/delay */ + backupMethod = CConcealment_GetMethod(pConcealData); + backupDelay = CConcealment_GetDelay(pConcealData); + + /* Be sure to set AAC and SBR concealment method simultaneously! */ + errorStatus = + CConcealment_SetParams( + pConcealData, + (int)method, // concealMethod + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel + ); + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) { + goto bail; + } + + /* Get new delay */ + bsDelay = CConcealment_GetDelay(pConcealData); + + { + SBR_ERROR sbrErr = SBRDEC_OK; + + /* set SBR bitstream delay */ + sbrErr = sbrDecoder_SetParam ( + hSbrDec, + SBR_SYSTEM_BITSTREAM_DELAY, + bsDelay + ); + + switch (sbrErr) { + case SBRDEC_OK: + case SBRDEC_NOT_INITIALIZED: + if (self != NULL) { + /* save the param value and set later + (when SBR has been initialized) */ + self->sbrParams.bsDelay = bsDelay; + } + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BS_DELAY, + bsDelay + ); + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) { + goto bail; + } + + if (errorStatus == AAC_DEC_OK) { + PCMDMX_ERROR err = + pcmDmx_SetParam ( + hPcmDmx, + DMX_BS_DATA_DELAY, + bsDelay + ); + switch (err) { + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + case PCMDMX_OK: + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + +bail: + if ( (errorStatus != AAC_DEC_OK) + && (errorStatus != AAC_DEC_INVALID_HANDLE) ) + { + /* Revert to the initial state */ + CConcealment_SetParams ( + pConcealData, + (int)backupMethod, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED + ); + /* Revert SBR bitstream delay */ + sbrDecoder_SetParam ( + hSbrDec, + SBR_SYSTEM_BITSTREAM_DELAY, + backupDelay + ); + /* Revert DRC bitstream delay */ + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BS_DELAY, + backupDelay + ); + /* Revert PCM mixdown bitstream delay */ + pcmDmx_SetParam ( + hPcmDmx, + DMX_BS_DATA_DELAY, + backupDelay + ); + } + + return errorStatus; +} + + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_SetParam ( const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const AACDEC_PARAM param, /*!< Parameter to set */ + const INT value) /*!< Parameter valued */ +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + TDLimiterPtr hPcmTdl = NULL; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + hPcmTdl = self->hLimiter; + } else { + errorStatus = AAC_DEC_INVALID_HANDLE; + } + + /* configure the subsystems */ + switch (param) + { + case AAC_PCM_OUTPUT_INTERLEAVED: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->outputInterleaved = value; + break; + + case AAC_PCM_MIN_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + { + PCMDMX_ERROR err; + + err = pcmDmx_SetParam ( + hPcmDmx, + MIN_NUMBER_OF_OUTPUT_CHANNELS, + value ); + + switch (err) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + break; + + case AAC_PCM_MAX_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + { + PCMDMX_ERROR err; + + err = pcmDmx_SetParam ( + hPcmDmx, + MAX_NUMBER_OF_OUTPUT_CHANNELS, + value ); + + switch (err) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + break; + + case AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE: + { + PCMDMX_ERROR err; + + err = pcmDmx_SetParam ( + hPcmDmx, + DMX_DUAL_CHANNEL_MODE, + value ); + + switch (err) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + break; + + + case AAC_PCM_LIMITER_ENABLE: + if (value < -1 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->limiterEnableUser = value; + break; + + case AAC_PCM_LIMITER_ATTACK_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (setLimiterAttack(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_PCM_LIMITER_RELEAS_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (setLimiterRelease(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_PCM_OUTPUT_CHANNEL_MAPPING: + switch (value) { + case 0: + if (self != NULL) { + self->channelOutputMapping = channelMappingTablePassthrough; + } + break; + case 1: + if (self != NULL) { + self->channelOutputMapping = channelMappingTableWAV; + } + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + break; + } + break; + + + case AAC_QMF_LOWPOWER: + if (value < -1 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /** + * Set QMF mode (might be overriden) + * 0:HQ (complex) + * 1:LP (partially complex) + */ + self->qmfModeUser = (QMF_MODE)value; + break; + + + case AAC_DRC_ATTENUATION_FACTOR: + /* DRC compression factor (where 0 is no and 127 is max compression) */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_CUT_SCALE, + value + ); + break; + + case AAC_DRC_BOOST_FACTOR: + /* DRC boost factor (where 0 is no and 127 is max boost) */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + DRC_BOOST_SCALE, + value + ); + break; + + case AAC_DRC_REFERENCE_LEVEL: + /* DRC reference level quantized in 0.25dB steps using values [0..127] it is '-' for analog scaling */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + TARGET_REF_LEVEL, + value + ); + break; + + case AAC_DRC_HEAVY_COMPRESSION: + /* Don't need to overwrite cut/boost values */ + errorStatus = + aacDecoder_drcSetParam ( + hDrcInfo, + APPLY_HEAVY_COMPRESSION, + value + ); + break; + + + case AAC_TPDEC_CLEAR_BUFFER: + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + /* aacDecoder_SignalInterruption(self); */ + break; + + case AAC_CONCEAL_METHOD: + /* Changing the concealment method can introduce additional bitstream delay. And + that in turn affects sub libraries and modules which makes the whole thing quite + complex. So the complete changing routine is packed into a helper function which + keeps all modules and libs in a consistent state even in the case an error occures. */ + errorStatus = setConcealMethod ( self, value ); + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + + return (errorStatus); +} + + +LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, UINT nrOfLayers) +{ + AAC_DECODER_INSTANCE *aacDec = NULL; + HANDLE_TRANSPORTDEC pIn; + int err = 0; + + /* Allocate transport layer struct. */ + pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4); + if (pIn == NULL) { + return NULL; + } + + transportDec_SetParam(pIn, TPDEC_PARAM_IGNORE_BUFFERFULLNESS, 1); + + /* Allocate AAC decoder core struct. */ + aacDec = CAacDecoder_Open(transportFmt); + + if (aacDec == NULL) { + transportDec_Close(&pIn); + goto bail; + } + aacDec->hInput = pIn; + + aacDec->nrOfLayers = nrOfLayers; + + aacDec->channelOutputMapping = channelMappingTableWAV; + + /* Register Config Update callback. */ + transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, (void*)aacDec); + + /* open SBR decoder */ + if ( SBRDEC_OK != sbrDecoder_Open ( &aacDec->hSbrDecoder )) { + err = -1; + goto bail; + } + aacDec->qmfModeUser = NOT_DEFINED; + transportDec_RegisterSbrCallback(aacDec->hInput, (cbSbr_t)sbrDecoder_Header, (void*)aacDec->hSbrDecoder); + + + pcmDmx_Open( &aacDec->hPcmUtils ); + if (aacDec->hPcmUtils == NULL) { + err = -1; + goto bail; + } + + aacDec->hLimiter = createLimiter(TDL_ATTACK_DEFAULT_MS, TDL_RELEASE_DEFAULT_MS, SAMPLE_MAX, (8), 96000); + if (NULL == aacDec->hLimiter) { + err = -1; + goto bail; + } + aacDec->limiterEnableUser = (UCHAR)-1; + aacDec->limiterEnableCurr = 0; + + + + /* Assure that all modules have same delay */ + if ( setConcealMethod(aacDec, CConcealment_GetMethod(&aacDec->concealCommonData)) ) { + err = -1; + goto bail; + } + +bail: + if (err == -1) { + aacDecoder_Close(aacDec); + aacDec = NULL; + } + return aacDec; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill( + HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *pBytesValid + ) +{ + TRANSPORTDEC_ERROR tpErr; + /* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only + available layer */ + INT layer = 0; + INT nrOfLayers = self->nrOfLayers; + + { + for (layer = 0; layer < nrOfLayers; layer++){ + { + tpErr = transportDec_FillData( self->hInput, pBuffer[layer], bufferSize[layer], &pBytesValid[layer], layer ); + if (tpErr != TRANSPORTDEC_OK) { + return AAC_DEC_UNKNOWN; /* Must be an internal error */ + } + } + } + } + + return AAC_DEC_OK; +} + + +static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self) +{ + CAacDecoder_SignalInterruption(self); + + if ( self->hSbrDecoder != NULL ) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 0); + } +} + +static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, HANDLE_FDK_BITSTREAM hBs, int nBits, AAC_DECODER_ERROR ErrorStatus) +{ + /* calculate bit difference (amount of bits moved forward) */ + nBits = nBits - FDKgetValidBits(hBs); + + /* Note: The amount of bits consumed might become negative when parsing a + bit stream with several sub frames, and we find out at the last sub frame + that the total frame length does not match the sum of sub frame length. + If this happens, the transport decoder might want to rewind to the supposed + ending of the transport frame, and this position might be before the last + access unit beginning. */ + + /* Calc bitrate. */ + if (pSi->frameSize > 0) { + pSi->bitRate = (nBits * pSi->sampleRate)/pSi->frameSize; + } + + /* bit/byte counters */ + { + int nBytes; + + nBytes = nBits>>3; + pSi->numTotalBytes += nBytes; + if (IS_OUTPUT_VALID(ErrorStatus)) { + pSi->numTotalAccessUnits++; + } + if (IS_DECODE_ERROR(ErrorStatus)) { + pSi->numBadBytes += nBytes; + pSi->numBadAccessUnits++; + } + } +} + +static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) +{ + INT n; + + transportDec_GetMissingAccessUnitCount( &n, self->hInput); + + return n; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame( + HANDLE_AACDECODER self, + INT_PCM *pTimeData_extern, + const INT timeDataSize_extern, + const UINT flags) +{ + AAC_DECODER_ERROR ErrorStatus; + int fTpInterruption = 0; /* Transport originated interruption detection. */ + int fTpConceal = 0; /* Transport originated concealment. */ + + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + INT interleaved = self->outputInterleaved; + INT_PCM *pTimeData = self->pcmOutputBuffer; + INT timeDataSize = sizeof(self->pcmOutputBuffer)/sizeof(*self->pcmOutputBuffer); + + if (flags & AACDEC_INTR) { + self->streamInfo.numLostAccessUnits = 0; + } + + HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0); + + /* Get current bits position for bitrate calculation. */ + INT nBits = FDKgetValidBits(hBs); + if (! (flags & (AACDEC_CONCEAL | AACDEC_FLUSH) ) ) + { + TRANSPORTDEC_ERROR err; + + for(INT layer = 0; layer < self->nrOfLayers; layer++) + { + err = transportDec_ReadAccessUnit(self->hInput, layer); + if (err != TRANSPORTDEC_OK) { + switch (err) { + case TRANSPORTDEC_NOT_ENOUGH_BITS: + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + case TRANSPORTDEC_SYNC_ERROR: + self->streamInfo.numLostAccessUnits = aacDecoder_EstimateNumberOfLostFrames(self); + fTpInterruption = 1; + break; + case TRANSPORTDEC_NEED_TO_RESTART: + ErrorStatus = AAC_DEC_NEED_TO_RESTART; + goto bail; + case TRANSPORTDEC_CRC_ERROR: + fTpConceal = 1; + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + } else { + if (self->streamInfo.numLostAccessUnits > 0) { + self->streamInfo.numLostAccessUnits--; + } + } + + /* Signal bit stream interruption to other modules if required. */ + if ( fTpInterruption || (flags & (AACDEC_INTR|AACDEC_CLRHIST)) ) + { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_CLEAR_HISTORY, (flags&AACDEC_CLRHIST)); + aacDecoder_SignalInterruption(self); + if ( ! (flags & AACDEC_INTR) ) { + ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR; + goto bail; + } + } + + /* Empty bit buffer in case of flush request. */ + if (flags & AACDEC_FLUSH) + { + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + } + /* Reset the output delay field. The modules will add their figures one after another. */ + self->streamInfo.outputDelay = 0; + + if (self->limiterEnableUser==(UCHAR)-1) { + /* Enbale limiter for all non-lowdelay AOT's. */ + self->limiterEnableCurr = ( self->flags & (AC_LD|AC_ELD) ) ? 0 : 1; + } + else { + /* Use limiter configuration as requested. */ + self->limiterEnableCurr = self->limiterEnableUser; + } + /* reset limiter gain on a per frame basis */ + self->extGain[0] = FL2FXCONST_DBL(1.0f/(float)(1<hInput); + if (tpErr != TRANSPORTDEC_OK) { + self->frameOK = 0; + } + } + + /* If the current pTimeData does not contain a valid signal, there nothing else we can do, so bail. */ + if ( ! IS_OUTPUT_VALID(ErrorStatus) ) { + goto bail; + } + + { + /* Export data into streaminfo structure */ + self->streamInfo.sampleRate = self->streamInfo.aacSampleRate; + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + } + self->streamInfo.numChannels = self->streamInfo.aacNumChannels; + + + + CAacDecoder_SyncQmfMode(self); + +/* sbr decoder */ + + if (ErrorStatus || (flags & AACDEC_CONCEAL) || self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > ConcealState_FadeIn) + { + self->frameOK = 0; /* if an error has occured do concealment in the SBR decoder too */ + } + + if (self->sbrEnabled) + { + SBR_ERROR sbrError = SBRDEC_OK; + int chIdx, numCoreChannel = self->streamInfo.numChannels; + int chOutMapIdx = ((self->chMapIndex==0) && (numCoreChannel<7)) ? numCoreChannel : self->chMapIndex; + + /* set params */ + sbrDecoder_SetParam ( self->hSbrDecoder, + SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + sbrDecoder_SetParam ( self->hSbrDecoder, + SBR_FLUSH_DATA, + (flags & AACDEC_FLUSH) ); + + if ( self->streamInfo.aot == AOT_ER_AAC_ELD ) { + /* Configure QMF */ + sbrDecoder_SetParam ( self->hSbrDecoder, + SBR_LD_QMF_TIME_ALIGN, + (self->flags & AC_LD_MPS) ? 1 : 0 ); + } + + { + PCMDMX_ERROR dmxErr; + INT maxOutCh = 0; + + dmxErr = pcmDmx_GetParam(self->hPcmUtils, MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh); + if ( (dmxErr == PCMDMX_OK) && (maxOutCh == 1) ) { + /* Disable PS processing if we have to create a mono output signal. */ + self->psPossible = 0; + } + } + + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply ( self->hSbrDecoder, + pTimeData, + &self->streamInfo.numChannels, + &self->streamInfo.sampleRate, + self->channelOutputMapping[chOutMapIdx], + interleaved, + self->frameOK, + &self->psPossible); + + + if (sbrError == SBRDEC_OK) { + #define UPS_SCALE 2 /* Maximum upsampling factor is 4 (CELP+SBR) */ + FIXP_DBL upsampleFactor = FL2FXCONST_DBL(1.0f/(1<flags |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.frameSize == 768) { + upsampleFactor = FL2FXCONST_DBL(8.0f/(3<streamInfo.frameSize = (INT)fMult((FIXP_DBL)self->streamInfo.aacSamplesPerFrame<streamInfo.outputDelay = (UINT)(INT)fMult((FIXP_DBL)self->streamInfo.outputDelay<streamInfo.outputDelay += sbrDecoder_GetDelay( self->hSbrDecoder ); + + if (self->psPossible) { + self->flags |= AC_PS_PRESENT; + } + for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; chIdx+=1) { + self->channelType[chIdx] = ACT_FRONT; + self->channelIndices[chIdx] = chIdx; + } + } + } + + + { + INT pcmLimiterScale = 0; + PCMDMX_ERROR dmxErr = PCMDMX_OK; + if ( flags & (AACDEC_INTR | AACDEC_CLRHIST) ) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset( self->hPcmUtils, PCMDMX_RESET_BS_DATA ); + } + /* do PCM post processing */ + dmxErr = pcmDmx_ApplyFrame ( + self->hPcmUtils, + pTimeData, + self->streamInfo.frameSize, + &self->streamInfo.numChannels, + interleaved, + self->channelType, + self->channelIndices, + self->channelOutputMapping, + (self->limiterEnableCurr) ? &pcmLimiterScale : NULL + ); + if ( (ErrorStatus == AAC_DEC_OK) + && (dmxErr == PCMDMX_INVALID_MODE) ) { + /* Announce the framework that the current combination of channel configuration and downmix + * settings are not know to produce a predictable behavior and thus maybe produce strange output. */ + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + if ( flags & AACDEC_CLRHIST ) { + /* Delete the delayed signal. */ + resetLimiter(self->hLimiter); + } + if (self->limiterEnableCurr) + { + /* Set actual signal parameters */ + setLimiterNChannels(self->hLimiter, self->streamInfo.numChannels); + setLimiterSampleRate(self->hLimiter, self->streamInfo.sampleRate); + + applyLimiter( + self->hLimiter, + pTimeData, + self->extGain, + &pcmLimiterScale, + 1, + self->extGainDelay, + self->streamInfo.frameSize + ); + + /* Announce the additional limiter output delay */ + self->streamInfo.outputDelay += getLimiterDelay(self->hLimiter); + } + } + + + /* Signal interruption to take effect in next frame. */ + if ( flags & AACDEC_FLUSH ) { + aacDecoder_SignalInterruption(self); + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags; + +bail: + + /* Update Statistics */ + aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, ErrorStatus); + + /* Check whether external output buffer is large enough. */ + if (timeDataSize_extern < self->streamInfo.numChannels*self->streamInfo.frameSize) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + } + + /* Update external output buffer. */ + if ( IS_OUTPUT_VALID(ErrorStatus) ) { + FDKmemcpy(pTimeData_extern, pTimeData, self->streamInfo.numChannels*self->streamInfo.frameSize*sizeof(*pTimeData)); + } + else { + FDKmemclear(pTimeData_extern, timeDataSize_extern*sizeof(*pTimeData_extern)); + } + + return ErrorStatus; +} + +LINKSPEC_CPP void aacDecoder_Close ( HANDLE_AACDECODER self ) +{ + if (self == NULL) + return; + + + if (self->hLimiter != NULL) { + destroyLimiter(self->hLimiter); + } + + if (self->hPcmUtils != NULL) { + pcmDmx_Close( &self->hPcmUtils ); + } + + + + if (self->hSbrDecoder != NULL) { + sbrDecoder_Close(&self->hSbrDecoder); + } + + if (self->hInput != NULL) { + transportDec_Close(&self->hInput); + } + + CAacDecoder_Close(self); +} + + +LINKSPEC_CPP CStreamInfo* aacDecoder_GetStreamInfo ( HANDLE_AACDECODER self ) +{ + return CAacDecoder_GetStreamInfo(self); +} + +LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return -1; + } + + sbrDecoder_GetLibInfo( info ); + transportDec_GetLibInfo( info ); + FDK_toolsGetLibInfo( info ); + pcmDmx_GetLibInfo( info ); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_AACDEC; + /* build own library info */ + info->version = LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = AACDECODER_LIB_BUILD_DATE; + info->build_time = AACDECODER_LIB_BUILD_TIME; + info->title = AACDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 + | CAPF_AAC_LC + | CAPF_ER_AAC_SCAL + | CAPF_AAC_VCB11 + | CAPF_AAC_HCR + | CAPF_AAC_RVLC + | CAPF_ER_AAC_LD + | CAPF_ER_AAC_ELD + | CAPF_AAC_CONCEALMENT + | CAPF_AAC_DRC + + | CAPF_AAC_MPEG4 + + | CAPF_AAC_DRM_BSFORMAT + + | CAPF_AAC_1024 + | CAPF_AAC_960 + + | CAPF_AAC_512 + + | CAPF_AAC_480 + + ; + /* End of flags */ + + return 0; +} + + + + diff --git a/libAACdec/src/arm/block_arm.cpp b/libAACdec/src/arm/block_arm.cpp new file mode 100644 index 00000000..fbc1bf3e --- /dev/null +++ b/libAACdec/src/arm/block_arm.cpp @@ -0,0 +1,140 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + + +/******************************** Fraunhofer IIS *************************** + + Author(s): Arthur Tritthart + Description: (ARM optimised) Scaling of spectral data + +******************************************************************************/ + + +#define FUNCTION_CBlock_ScaleSpectralData_func1 + +/* Note: This loop is only separated for ARM in order to save cycles + by loop unrolling. The ARM core provides by default a 5-cycle + loop overhead per sample, that goes down to 1-cycle per sample + with an optimal 4x-loop construct (do - 4x - while). +*/ + +FDK_INLINE static void CBlock_ScaleSpectralData_func1( + FIXP_DBL *pSpectrum, + int max_band, + const SHORT * RESTRICT BandOffsets, + int SpecScale_window, + const SHORT * RESTRICT pSfbScale, + int window) +{ + int band_offset = 0; + for (int band=0; band < max_band; band++) + { + int runs = band_offset; + band_offset = BandOffsets[band+1]; + runs = band_offset - runs; /* is always a multiple of 4 */ + int scale = SpecScale_window-pSfbScale[window*16+band]; + if (scale) + { + do + { + FIXP_DBL tmp0, tmp1, tmp2, tmp3; + tmp0 = pSpectrum[0]; + tmp1 = pSpectrum[1]; + tmp2 = pSpectrum[2]; + tmp3 = pSpectrum[3]; + tmp0 >>= scale; + tmp1 >>= scale; + tmp2 >>= scale; + tmp3 >>= scale; + *pSpectrum++ = tmp0; + *pSpectrum++ = tmp1; + *pSpectrum++ = tmp2; + *pSpectrum++ = tmp3; + } while ((runs = runs-4) != 0); + } + else + { + pSpectrum+= runs; + } + } +} diff --git a/libAACdec/src/block.cpp b/libAACdec/src/block.cpp new file mode 100644 index 00000000..bda565c5 --- /dev/null +++ b/libAACdec/src/block.cpp @@ -0,0 +1,761 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: long/short-block decoding + +******************************************************************************/ + +#include "block.h" + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "FDK_tools_rom.h" + + + + +#include "aacdec_hcr.h" +#include "rvlc.h" + + +#if defined(__arm__) +#include "arm/block_arm.cpp" +#endif + +/*! + \brief Read escape sequence of codeword + + The function reads the escape sequence from the bitstream, + if the absolute value of the quantized coefficient has the + value 16. + + \return quantized coefficient +*/ +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const LONG q) /*!< quantized coefficient */ +{ + LONG i, off, neg ; + + if (q < 0) + { + if (q != -16) return q; + neg = 1; + } + else + { + if (q != +16) return q; + neg = 0; + } + + for (i=4; ; i++) + { + if (FDKreadBits(bs,1) == 0) + break; + } + + if (i > 16) + { + if (i - 16 > CACHE_BITS) { /* cannot read more than "CACHE_BITS" bits at once in the function FDKreadBits() */ + return (MAX_QUANTIZED_VALUE + 1); /* returning invalid value that will be captured later */ + } + + off = FDKreadBits(bs,i-16) << 16; + off |= FDKreadBits(bs,16); + } + else + { + off = FDKreadBits(bs,i); + } + + i = off + (1 << i); + + if (neg) i = -i; + + return i; +} + +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs, + UINT flags + ) +{ + int temp; + int band; + int group; + int position = 0; /* accu for intensity delta coding */ + int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain; /* accu for scale factor delta coding */ + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const CodeBookDescription *hcb =&AACcodeBookDescriptionTable[BOOKSCL]; + + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) + { + for (band=0; band < ScaleFactorBandsTransmitted; band++) + { + switch (pCodeBook[group*16+band]) { + + case ZERO_HCB: /* zero book */ + pScaleFactor[group*16+band] = 0; + break; + + default: /* decode scale factor */ + { + temp = CBlock_DecodeHuffmanWord(bs,hcb); + factor += temp - 60; /* MIDFAC 1.5 dB */ + } + pScaleFactor[group*16+band] = factor - 100; + break; + + case INTENSITY_HCB: /* intensity steering */ + case INTENSITY_HCB2: + temp = CBlock_DecodeHuffmanWord(bs,hcb); + position += temp - 60; + pScaleFactor[group*16+band] = position - 100; + break; + + case NOISE_HCB: /* PNS */ + if (flags & (AC_MPS_RES|AC_USAC|AC_RSVD50)) { + return AAC_DEC_PARSE_ERROR; + } + CPns_Read( &pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb, pAacDecoderChannelInfo->pDynData->aScaleFactor, pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain, band, group); + break; + } + } + } + + return AAC_DEC_OK; +} + +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo) +{ + int band; + int window; + const SHORT * RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT * RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale; + int groupwin,group; + const SHORT * RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + SPECTRAL_PTR RESTRICT pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient; + + + FDKmemclear(pSpecScale, 8*sizeof(SHORT)); + + int max_band = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) + { + for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++) + { + int SpecScale_window = pSpecScale[window]; + FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength); + + /* find scaling for current window */ + for (band=0; band < max_band; band++) + { + SpecScale_window = fMax(SpecScale_window, (int)pSfbScale[window*16+band]); + } + + if (pAacDecoderChannelInfo->pDynData->TnsData.Active) { + SpecScale_window += TNS_SCALE; + } + + /* store scaling of current window */ + pSpecScale[window] = SpecScale_window; + +#ifdef FUNCTION_CBlock_ScaleSpectralData_func1 + + CBlock_ScaleSpectralData_func1(pSpectrum, max_band, BandOffsets, SpecScale_window, pSfbScale, window); + +#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + for (band=0; band < max_band; band++) + { + int scale = SpecScale_window - pSfbScale[window*16+band]; + if (scale) + { + /* following relation can be used for optimizations: (BandOffsets[i]%4) == 0 for all i */ + int max_index = BandOffsets[band+1]; + for (int index = BandOffsets[band]; index < max_index; index++) + { + pSpectrum[index] >>= scale; + } + } + } +#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + } + } + +} + +AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags) +{ + int top, band; + int sect_len, sect_len_incr; + int group; + UCHAR sect_cb; + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + /* HCR input (long) */ + SHORT *pNumLinesInSec = pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + int numLinesInSecIdx = 0; + UCHAR *pHcrCodeBook = pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + const SHORT *BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0; + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + FDKmemclear(pCodeBook, sizeof(UCHAR)*(8*16)); + + const int nbits = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3; + + int sect_esc_val = (1 << nbits) - 1 ; + + UCHAR ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group=0; groupicsInfo); group++) + { + for (band=0; band < ScaleFactorBandsTransmitted; ) + { + sect_len = 0; + if ( flags & AC_ER_VCB11 ) { + sect_cb = (UCHAR) FDKreadBits(bs,5); + } + else + sect_cb = (UCHAR) FDKreadBits(bs,4); + + if ( ((flags & AC_ER_VCB11) == 0) || ( sect_cb < 11 ) || ((sect_cb > 11) && (sect_cb < 16)) ) { + sect_len_incr = FDKreadBits(bs, nbits); + while (sect_len_incr == sect_esc_val) + { + sect_len += sect_esc_val; + sect_len_incr = FDKreadBits(bs, nbits); + } + } + else { + sect_len_incr = 1; + } + + sect_len += sect_len_incr; + if (sect_len <= 0) { + return AAC_DEC_PARSE_ERROR; + } + + + top = band + sect_len; + + if (flags & AC_ER_HCR) { + /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */ + if (numLinesInSecIdx >= MAX_SFB_HCR) { + return AAC_DEC_PARSE_ERROR; + } + pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band]; + numLinesInSecIdx++; + if (sect_cb == BOOKSCL) + { + return AAC_DEC_INVALID_CODE_BOOK; + } else { + *pHcrCodeBook++ = sect_cb; + } + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++; + } + + /* Check spectral line limits */ + if (IsLongBlock( &(pAacDecoderChannelInfo->icsInfo) )) + { + if (top > 64) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } else { /* short block */ + if (top + group*16 > (8 * 16)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + /* Check if decoded codebook index is feasible */ + if ( (sect_cb == BOOKSCL) + || ( (sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) && pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0) + ) + { + return AAC_DEC_INVALID_CODE_BOOK; + } + + /* Store codebook index */ + for (; band < top; band++) + { + pCodeBook[group*16+band] = sect_cb; + } + } + } + + + return ErrorStatus; +} + +/* mso: provides a faster way to i-quantize a whole band in one go */ + +/** + * \brief inverse quantize one sfb. Each value of the sfb is processed according to the + * formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3) * 2^(lsb/4). + * \param spectrum pointer to first line of the sfb to be inverse quantized. + * \param noLines number of lines belonging to the sfb. + * \param lsb last 2 bits of the scale factor of the sfb. + * \param scale max allowed shift scale for the sfb. + */ +static +void InverseQuantizeBand( FIXP_DBL * RESTRICT spectrum, + INT noLines, + INT lsb, + INT scale ) +{ + const FIXP_DBL * RESTRICT InverseQuantTabler=(FIXP_DBL *)InverseQuantTable; + const FIXP_DBL * RESTRICT MantissaTabler=(FIXP_DBL *)MantissaTable[lsb]; + const SCHAR* RESTRICT ExponentTabler=(SCHAR*)ExponentTable[lsb]; + + FIXP_DBL *ptr = spectrum; + FIXP_DBL signedValue; + + FDK_ASSERT(noLines>2); + for (INT i=noLines; i--; ) + { + if ((signedValue = *ptr++) != FL2FXCONST_DBL(0)) + { + FIXP_DBL value = fAbs(signedValue); + UINT freeBits = CntLeadingZeros(value); + UINT exponent = 32 - freeBits; + + UINT x = (UINT) (LONG)value << (INT) freeBits; + x <<= 1; /* shift out sign bit to avoid masking later on */ + UINT tableIndex = x >> 24; + x = (x >> 20) & 0x0F; + + UINT r0=(UINT)(LONG)InverseQuantTabler[tableIndex+0]; + UINT r1=(UINT)(LONG)InverseQuantTabler[tableIndex+1]; + UINT temp= (r1 - r0)*x + (r0 << 4); + + value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]); + + /* + 1 compensates fMultDiv2() */ + scaleValueInPlace(&value, scale + ExponentTabler[exponent] + 1); + + signedValue = (signedValue < (FIXP_DBL)0) ? -value : value; + ptr[-1] = signedValue; + } + } +} + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo) +{ + int window, group, groupwin, band; + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale, (8*16)*sizeof(SHORT)); + + for (window=0, group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) + { + for (groupwin=0; groupwin < GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); groupwin++, window++) + { + /* inverse quantization */ + for (band=0; band < ScaleFactorBandsTransmitted; band++) + { + FIXP_DBL *pSpectralCoefficient = SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength) + BandOffsets[band]; + + int noLines = BandOffsets[band+1] - BandOffsets[band]; + int bnds = group*16+band; + int i; + + if ((pCodeBook[bnds] == ZERO_HCB) + || (pCodeBook[bnds] == INTENSITY_HCB) + || (pCodeBook[bnds] == INTENSITY_HCB2) + ) + continue; + + if (pCodeBook[bnds] == NOISE_HCB) + { + /* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) = 1, + worst case of additional headroom required because of the scalefactor. */ + pSfbScale[window*16+band] = (pScaleFactor [bnds] >> 2) + 1 ; + continue; + } + + /* Find max spectral line value of the current sfb */ + FIXP_DBL locMax = (FIXP_DBL)0; + + for (i = noLines; i-- ; ) { + /* Expensive memory access */ + locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax); + } + + /* Cheap robustness improvement - Do not remove!!! */ + if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + /* + The inverse quantized spectral lines are defined by: + pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * 2^(0.25*pScaleFactor[bnds]) * pSpectralCoefficient[i]^(4/3) + This is equivalent to: + pSpectralCoefficient[i] = Sign(pSpectralCoefficient[i]) * (2^(pScaleFactor[bnds] % 4) * pSpectralCoefficient[i]^(4/3)) + pSpectralCoefficient_e[i] += pScaleFactor[bnds]/4 + */ + { + int msb = pScaleFactor [bnds] >> 2 ; + int lsb = pScaleFactor [bnds] & 0x03 ; + + int scale = GetScaleFromValue(locMax, lsb); + + pSfbScale[window*16+band] = msb - scale; + InverseQuantizeBand(pSpectralCoefficient, noLines, lsb, scale); + } + } + } + } + + + return AAC_DEC_OK; +} + + +AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags) +{ + int i,index; + int window,group,groupwin,groupoffset,band; + UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + SPECTRAL_PTR pSpectralCoefficient = pAacDecoderChannelInfo->pSpectralCoefficient; + FIXP_DBL locMax; + + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + FDK_ASSERT(BandOffsets != NULL); + + FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM)); + + if ( (flags & AC_ER_HCR) == 0 ) + { + groupoffset = 0; + + /* plain huffman decoder short */ + for (group=0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) + { + for (band=0; band < ScaleFactorBandsTransmitted; band++) + { + int bnds = group*16+band; + UCHAR currentCB = pCodeBook[bnds]; + + /* patch to run plain-huffman-decoder with vcb11 input codebooks (LAV-checking might be possible below using the virtual cb and a LAV-table) */ + if ((currentCB >= 16) && (currentCB <= 31)) { + pCodeBook[bnds] = currentCB = 11; + } + if ( !((currentCB == ZERO_HCB) + || (currentCB == NOISE_HCB) + || (currentCB == INTENSITY_HCB) + || (currentCB == INTENSITY_HCB2)) ) + { + const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[currentCB]; + int step = hcb->Dimension; + int offset = hcb->Offset; + int bits = hcb->numBits; + int mask = (1<icsInfo,group); groupwin++) + { + window = groupoffset + groupwin; + + FIXP_DBL *mdctSpectrum = SPEC(pSpectralCoefficient, window, pAacDecoderChannelInfo->granuleLength); + + locMax = (FIXP_DBL)0 ; + + for (index=BandOffsets[band]; index < BandOffsets[band+1]; index+=step) + { + int idx = CBlock_DecodeHuffmanWord(bs,hcb); + + for (i=0; i>= bits; + + if (offset == 0) { + if (tmp != FIXP_DBL(0)) + tmp = (FDKreadBits(bs,1))? -tmp : tmp; + } + mdctSpectrum[index+i] = tmp; + } + + if (currentCB == ESCBOOK) + { + mdctSpectrum[index+0] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+0]); + mdctSpectrum[index+1] = (FIXP_DBL)CBlock_GetEscape(bs, (LONG)mdctSpectrum[index+1]); + + } + } + } + } + } + groupoffset += GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + } + /* plain huffman decoding (short) finished */ + } + /* HCR - Huffman Codeword Reordering short */ + else /* if ( flags & AC_ER_HCR ) */ + { + H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo; + int hcrStatus = 0; + + /* advanced Huffman decoding starts here (HCR decoding :) */ + if ( pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData != 0 ) { + + /* HCR initialization short */ + hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + /* HCR decoding short */ + hcrStatus = HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { +#if HCR_ERROR_CONCEALMENT + HcrMuteErroneousLines(hHcr); +#else + return AAC_DEC_DECODE_FRAME_ERROR; +#endif /* HCR_ERROR_CONCEALMENT */ + } + + FDKpushFor (bs, pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData); + } + } + /* HCR - Huffman Codeword Reordering short finished */ + + + + if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) && !(flags & (AC_ELD|AC_SCALABLE)) ) + { + /* apply pulse data */ + CPulseData_Apply(&pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo), + SPEC_LONG(pSpectralCoefficient)); + } + + + return AAC_DEC_OK; +} + + + +void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags, + const int channel ) +{ + + if ( !(flags & (AC_USAC|AC_RSVD50|AC_MPS_RES)) ) { + CPns_Apply( + &pAacDecoderChannelInfo[channel]->data.aac.PnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pAacDecoderChannelInfo[channel]->specScale, + pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor, + pSamplingRateInfo, + pAacDecoderChannelInfo[channel]->granuleLength, + channel + ); + } + + CTns_Apply ( + &pAacDecoderChannelInfo[channel]->pDynData->TnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pSamplingRateInfo, + pAacDecoderChannelInfo[channel]->granuleLength + ); +} + +static +int getWindow2Nr(int length, int shape) +{ + int nr = 0; + + if (shape == 2) { + /* Low Overlap, 3/4 zeroed */ + nr = (length * 3)>>2; + } + + return nr; +} + +void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + INT_PCM outSamples[], + const SHORT frameLen, + const int stride, + const int frameOk, + FIXP_DBL *pWorkBuffer1 ) +{ + int fr, fl, tl, nSamples, nSpec; + + /* Determine left slope length (fl), right slope length (fr) and transform length (tl). + USAC: The slope length may mismatch with the previous frame in case of LPD / FD + transitions. The adjustment is handled by the imdct implementation. + */ + tl = frameLen; + nSpec = 1; + + switch( pAacDecoderChannelInfo->icsInfo.WindowSequence ) { + default: + case OnlyLongSequence: + fl = frameLen; + fr = frameLen - getWindow2Nr(frameLen, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)); + break; + case LongStopSequence: + fl = frameLen >> 3; + fr = frameLen; + break; + case LongStartSequence: /* or StopStartSequence */ + fl = frameLen; + fr = frameLen >> 3; + break; + case EightShortSequence: + fl = fr = frameLen >> 3; + tl >>= 3; + nSpec = 8; + break; + } + + { + int i; + + { + FIXP_DBL *tmp = pAacDecoderChannelInfo->pComData->workBufferCore1->mdctOutTemp; + + nSamples = imdct_block( + &pAacDecoderStaticChannelInfo->IMdct, + tmp, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, + nSpec, + frameLen, + tl, + FDKgetWindowSlope(fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope(fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, + (FIXP_DBL)0 ); + + for (i=0; ipSpectralCoefficient), + pAacDecoderChannelInfo->specScale[0], + outSamples, + pAacDecoderStaticChannelInfo->pOverlapBuffer, + stride, + frameLen + ); +} diff --git a/libAACdec/src/block.h b/libAACdec/src/block.h new file mode 100644 index 00000000..f9394f6a --- /dev/null +++ b/libAACdec/src/block.h @@ -0,0 +1,322 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: long/short-block decoding + +******************************************************************************/ + +#ifndef BLOCK_H +#define BLOCK_H + +#include "common_fix.h" + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +/* PNS (of block) */ +void CPns_Read (CPnsData *pPnsData, + HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, + SHORT *pScaleFactor, + UCHAR global_gain, + int band, + int group); + + +void CPns_Apply (const CPnsData *pPnsData, + const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, + const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, + const int channel); + + + +/* TNS (of block) */ +/*! + \brief Read tns data-present flag from bitstream + + The function reads the data-present flag for tns from + the bitstream. + + \return none +*/ +void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, + CTnsData *pTnsData); + +void CTns_ReadDataPresentUsac( + HANDLE_FDK_BITSTREAM hBs, + CTnsData *pTnsData0, + CTnsData *pTnsData1, + const CIcsInfo *pIcsInfo, + const UINT flags, + const int fCommonWindow + ); + +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, + CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, + const UINT flags); + +void CTns_Apply ( CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength); + +/* Block */ + +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, const LONG q); + +/** + * \brief Read scale factor data. See chapter 4.6.2.3.2 of ISO/IEC 14496-3. + * The SF_OFFSET = 100 value referenced in chapter 4.6.2.3.3 is already substracted + * from the scale factor values. Also includes PNS data reading. + * \param bs bit stream handle data source + * \param pAacDecoderChannelInfo channel context info were decoded data is stored into. + * \param flags the decoder flags. + */ +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs, + const UINT flags + ); + +/** + * \brief Read Huffman encoded spectral data. + * \param pAacDecoderChannelInfo channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + * \param flags syntax flags. + */ +AAC_DECODER_ERROR CBlock_ReadSpectralData(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags); + + +AAC_DECODER_ERROR CBlock_ReadSectionData(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags); + +/** + * \brief find a common exponent (shift factor) for all sfb in each Spectral window, and store them into + * CAacDecoderChannelInfo::specScale. + * \param pAacDecoderChannelInfo channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + */ +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo); + +/** + * \brief Apply TNS and PNS tools. + */ +void ApplyTools ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags, + const int channel ); + +/** + * \brief Transform MDCT spectral data into time domain + */ +void CBlock_FrequencyToTime(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + INT_PCM outSamples[], + const SHORT frameLen, + const int stride, + const int frameOk, + FIXP_DBL *pWorkBuffer1); + +/** + * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain. + */ +void CBlock_FrequencyToTimeLowDelay(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + INT_PCM outSamples[], + const short frameLen, + const char stride); + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, SamplingRateInfo *pSamplingRateInfo); + +/** + * \brief Calculate 2^(lsb/4) * value^(4/3) + * \param pValue pointer to quantized value. The inverse quantized result is stored back here. + * \param lsb 2 LSBs of the scale factor (scaleFactor % 4) applied as power 2 factor to the + * resulting inverse quantized value. + * \return the exponent of the result (mantissa) stored into *pValue. + */ +FDK_INLINE +int EvaluatePower43 ( FIXP_DBL *pValue, + UINT lsb ) +{ + FIXP_DBL value; + UINT freeBits; + UINT exponent; + + value = *pValue; + freeBits = fNormz (value) ; + exponent = DFRACT_BITS - freeBits ; + FDK_ASSERT (exponent < 14); + + UINT x = (((int)value << freeBits) >> 19) ; + UINT tableIndex = (x & 0x0FFF) >> 4 ; + FIXP_DBL invQVal ; + + x = x & 0x0F; + + UINT r0=(LONG)InverseQuantTable [tableIndex+0]; + UINT r1=(LONG)InverseQuantTable [tableIndex+1]; + USHORT nx=16-x; + UINT temp=(r0)*nx+(r1)*x; + invQVal = (FIXP_DBL)temp; + + FDK_ASSERT(lsb < 4); + *pValue = fMultDiv2 (invQVal, MantissaTable [lsb][exponent]) ; + + /* + 1 compensates fMultDiv2(). */ + return ExponentTable [lsb][exponent] + 1; +} + +/** + * \brief determine the required shift scale for the given quantized value and scale (factor % 4) value. + */ +FDK_INLINE int GetScaleFromValue (FIXP_DBL value, unsigned int lsb) +{ + if (value!=(FIXP_DBL)0) + { + int scale = EvaluatePower43 (&value, lsb) ; + return CntLeadingZeros (value) - scale - 2 ; + } + else + return 0; /* Return zero, because its useless to scale a zero value, saves workload and avoids scaling overshifts. */ +} + + +//#ifdef AACDEC_HUFFMANDECODER_ENABLE + +/*! + \brief Read huffman codeword + + The function reads the huffman codeword from the bitstream and + returns the index value. + + \return index value +*/ +inline int CBlock_DecodeHuffmanWord( HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const CodeBookDescription *hcb ) /*!< pointer to codebook description */ +{ + UINT val; + UINT index = 0; + const USHORT (*CodeBook) [HuffmanEntries] = hcb->CodeBook; + + while (1) + { + val = CodeBook[index][FDKreadBits(bs,HuffmanBits)]; /* Expensive memory access */ + + if ((val & 1) == 0) + { + index = val>>2; + continue; + } + else + { + if (val & 2) + { + FDKpushBackCache(bs,1); + } + + val >>= 2; + break; + } + } + + return val; +} + +//#endif /* AACDEC_HUFFMANDECODER_ENABLE */ + +#endif /* #ifndef BLOCK_H */ diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp new file mode 100644 index 00000000..4b182e00 --- /dev/null +++ b/libAACdec/src/channel.cpp @@ -0,0 +1,466 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + +#include "channel.h" +#include "aacdecoder.h" +#include "block.h" +#include "aacdec_tns.h" +#include "FDK_bitstream.h" +#include "FDK_tools_rom.h" + +#include "conceal.h" + +#include "rvlc.h" + +#include "aacdec_hcr.h" + + +static +void MapMidSideMaskToPnsCorrelation (CAacDecoderChannelInfo *pAacDecoderChannelInfo[2]) +{ + int group; + + for (group = 0 ; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; group++) { + UCHAR groupMask = 1 << group; + + for (UCHAR band = 0 ; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; band++) { + if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & groupMask) { /* channels are correlated */ + CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band, 0); + + if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, band) && + CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, band)) + pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= groupMask; /* clear the groupMask-bit */ + } + } + } +} + +/*! + \brief Decode channel pair element + + The function decodes a channel pair element. + + \return none +*/ +void CChannelElement_Decode( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */ + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, + UINT flags, + int el_channels) +{ + int ch, maybe_jstereo = 0; + + maybe_jstereo = (el_channels > 1); + + for (ch = 0; ch < el_channels; ch++) { + if ( pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT + || pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB ) + { + CBlock_InverseQuantizeSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo); + } + } + + + + if (maybe_jstereo) { + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + int maxSfBandsL = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo); + int maxSfBandsR = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo); + if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) { + MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo); + } + + CJointStereo_ApplyMS(pAacDecoderChannelInfo, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), + maxSfBandsL, + maxSfBandsR); + } + + /* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb */ + CJointStereo_ApplyIS(pAacDecoderChannelInfo, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo), + pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow ? 1 : 0); + + } + + for (ch = 0; ch < el_channels; ch++) + { + { + /* write pAacDecoderChannelInfo[ch]->specScale */ + CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], pSamplingRateInfo); + + ApplyTools (pAacDecoderChannelInfo, pSamplingRateInfo, flags, ch); + } + + } + + CRvlc_ElementCheck( + pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, + flags, + el_channels + ); +} + +void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + int b, w, maxBands, maxWindows; + int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + + if ( IsLongBlock(&pAacDecoderChannelInfo->icsInfo) ) { + maxBands = 64; + maxWindows = 1; + } else { + maxBands = 16; + maxWindows = 8; + } + + for (w = 0; wpDynData->TnsData); + if (numberOfChannels == 2) { + CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData); + } + + if (flags & (AC_ELD|AC_SCALABLE)) { + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1; + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + switch (list->id[i]) { + case element_instance_tag: + pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->ElementInstanceTag = pAacDecoderChannelInfo[0]->ElementInstanceTag; + } + break; + case common_window: + decision_bit = pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = FDKreadBits(hBs, 1); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + break; + case ics_info: + /* Read individual channel info */ + error = IcsRead( hBs, + &pAacDecoderChannelInfo[ch]->icsInfo, + pSamplingRateInfo, + flags ); + + if (numberOfChannels == 2 && pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) { + pAacDecoderChannelInfo[1]->icsInfo = pAacDecoderChannelInfo[0]->icsInfo; + } + break; + + + case ltp_data_present: + if (FDKreadBits(hBs, 1) != 0) { + error = AAC_DEC_UNSUPPORTED_PREDICTION; + } + break; + + case ms: + if ( CJointStereo_Read( + hBs, + &pAacDecoderChannelInfo[0]->pComData->jointStereoData, + GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo), + GetScaleMaxFactorBandsTransmitted(&pAacDecoderChannelInfo[0]->icsInfo, + &pAacDecoderChannelInfo[1]->icsInfo), + flags) ) + { + error = AAC_DEC_PARSE_ERROR; + } + break; + + case global_gain: + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = (UCHAR) FDKreadBits(hBs,8); + break; + + case section_data: + error = CBlock_ReadSectionData( hBs, + pAacDecoderChannelInfo[ch], + pSamplingRateInfo, + flags ); + break; + + + case scale_factor_data: + if (flags & AC_ER_RVLC) { + /* read RVLC data from bitstream (error sens. cat. 1) */ + CRvlc_Read(pAacDecoderChannelInfo[ch], hBs); + } + else + { + error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, flags); + } + break; + + case pulse: + if ( CPulseData_Read( hBs, + &pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData, + pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only allowed to be present in long blocks! */ + (void*)&pAacDecoderChannelInfo[ch]->icsInfo, + frame_length + ) != 0 ) + { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + break; + case tns_data_present: + CTns_ReadDataPresentFlag(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData); + break; + case tns_data: + /* tns_data_present is checked inside CTns_Read(). */ + error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, &pAacDecoderChannelInfo[ch]->icsInfo, flags); + break; + + case gain_control_data: + break; + + case gain_control_data_present: + if (FDKreadBits(hBs, 1)) { + error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA; + } + break; + + case esc2_rvlc: + if (flags & AC_ER_RVLC) { + CRvlc_Decode( + pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], + hBs + ); + } + break; + + case esc1_hcr: + if (flags & AC_ER_HCR) { + CHcr_Read(hBs, pAacDecoderChannelInfo[ch] ); + } + break; + + case spectral_data: + error = CBlock_ReadSpectralData( hBs, + pAacDecoderChannelInfo[ch], + pSamplingRateInfo, + flags ); + if (flags & AC_ELD) { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB; + } else { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT; + } + break; + + + /* CRC handling */ + case adtscrc_start_reg1: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 192); + } + break; + case adtscrc_start_reg2: + if (pTpDec != NULL) { + crcReg2 = transportDec_CrcStartReg(pTpDec, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg1); + crcReg1 = -1; + } + break; + case adtscrc_end_reg2: + if (crcReg1 != -1) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } else if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg2); + crcReg2 = -1; + } + break; + case drmcrc_start_reg: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 0); + } + break; + + /* Non data cases */ + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i=-1; + break; + + default: + error = AAC_DEC_UNSUPPORTED_FORMAT; + break; + } + + if (error != AAC_DEC_OK) { + goto bail; + } + + i++; + + } while (list->id[i] != end_of_sequence); + +bail: + if (crcReg1 != -1 || crcReg2 != -1) { + if (error == AAC_DEC_OK) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + if (crcReg1 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg1); + } + if (crcReg2 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg2); + } + } + return error; +} diff --git a/libAACdec/src/channel.h b/libAACdec/src/channel.h new file mode 100644 index 00000000..11469988 --- /dev/null +++ b/libAACdec/src/channel.h @@ -0,0 +1,148 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" +#include "channelinfo.h" +#include "tpdec_lib.h" + +/** + * \brief Init codeBook SFB indices (section data) with HCB_ESC. Useful for bitstreams + * which do not have any section data, but still SFB's (scale factor bands). This has + * the effect that upto the amount of transmitted SFB are treated as non-zero. + * \param pAacDecoderChannelInfo channel info structure containing a valid icsInfo struct. + */ +void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +/** + * \brief decode a channel element. To be called after CChannelElement_Read() + * \param pAacDecoderChannelInfo pointer to channel data struct. Depending on el_channels either one or two. + * \param pSamplingRateInfo pointer to sample rate information structure + * \param el_channels amount of channels of the element to be decoded. + * \param output pointer to time domain output buffer (ACELP) + * \param stride factor for accessing output + */ +void CChannelElement_Decode ( CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, + UINT flags, + int el_channels ); + + +/** + * \brief Read channel element of given type from bitstream. + * \param hBs bitstream handle to access bitstream data. + * \param pAacDecoderChannelInfo pointer array to store channel information. + * \param aot Audio Object Type + * \param pSamplingRateInfo sampling rate info table. + * \param flags parser guidance flags + * \param numberOfChannels amoun of channels contained in the object to be parsed. + * \param epConfig the current epConfig value obtained from the Audio Specific Config. + * \param pTp transport decoder handle required for ADTS CRC checking. + * ... + * \return an AAC_DECODER_ERROR error code. + */ +AAC_DECODER_ERROR CChannelElement_Read(HANDLE_FDK_BITSTREAM hBs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const AUDIO_OBJECT_TYPE aot, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags, + const UINT frame_length, + const UCHAR numberOfChannels, + const SCHAR epConfig, + HANDLE_TRANSPORTDEC pTpDec + ); + +#endif /* #ifndef CHANNEL_H */ diff --git a/libAACdec/src/channelinfo.cpp b/libAACdec/src/channelinfo.cpp new file mode 100644 index 00000000..76d58957 --- /dev/null +++ b/libAACdec/src/channelinfo.cpp @@ -0,0 +1,276 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: individual channel stream info + +******************************************************************************/ + +#include "channelinfo.h" +#include "aac_rom.h" +#include "aac_ram.h" +#include "FDK_bitstream.h" + + +AAC_DECODER_ERROR IcsReadMaxSfb ( + HANDLE_FDK_BITSTREAM bs, + CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo + ) +{ + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + int nbits; + + if (IsLongBlock(pIcsInfo)) { + nbits = 6; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + } else { + nbits = 4; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + } + pIcsInfo->MaxSfBands = (UCHAR) FDKreadBits(bs, nbits); + + if (pIcsInfo->MaxSfBands > pIcsInfo->TotalSfBands){ + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + + return ErrorStatus; +} + + + +AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs, + CIcsInfo *pIcsInfo, + const SamplingRateInfo* pSamplingRateInfo, + const UINT flags) +{ + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + pIcsInfo->Valid = 0; + + if (flags & AC_ELD){ + pIcsInfo->WindowSequence = OnlyLongSequence; + pIcsInfo->WindowShape = 0; + } + else { + if ( !(flags & (AC_USAC|AC_RSVD50)) ) { + FDKreadBits(bs,1); + } + pIcsInfo->WindowSequence = (UCHAR) FDKreadBits(bs,2); + pIcsInfo->WindowShape = (UCHAR) FDKreadBits(bs,1); + if (flags & AC_LD) { + if (pIcsInfo->WindowShape) { + pIcsInfo->WindowShape = 2; /* select low overlap instead of KBD */ + } + } + } + + /* Sanity check */ + if ( (flags & (AC_ELD|AC_LD)) && pIcsInfo->WindowSequence != OnlyLongSequence) { + pIcsInfo->WindowSequence = OnlyLongSequence; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + + ErrorStatus = IcsReadMaxSfb(bs, pIcsInfo, pSamplingRateInfo); + if (ErrorStatus != AAC_DEC_OK) { + goto bail; + } + + if (IsLongBlock(pIcsInfo)) + { + if ( !(flags & (AC_ELD|AC_SCALABLE|AC_BSAC|AC_USAC|AC_RSVD50)) ) /* If not ELD nor Scalable nor BSAC nor USAC syntax then ... */ + { + if ((UCHAR)FDKreadBits(bs,1) != 0 ) /* UCHAR PredictorDataPresent */ + { + ErrorStatus = AAC_DEC_UNSUPPORTED_PREDICTION; + goto bail; + } + } + + pIcsInfo->WindowGroups = 1; + pIcsInfo->WindowGroupLength[0] = 1; + } + else + { + INT i; + UINT mask; + + pIcsInfo->ScaleFactorGrouping = (UCHAR) FDKreadBits(bs,7); + + pIcsInfo->WindowGroups = 0 ; + + for (i=0; i < (8-1); i++) + { + mask = 1 << (6 - i); + pIcsInfo->WindowGroupLength[i] = 1; + + if (pIcsInfo->ScaleFactorGrouping & mask) + { + pIcsInfo->WindowGroupLength[pIcsInfo->WindowGroups]++; + } + else + { + pIcsInfo->WindowGroups++; + } + } + + /* loop runs to i < 7 only */ + pIcsInfo->WindowGroupLength[8-1] = 1; + pIcsInfo->WindowGroups++; + } + + +bail: + if (ErrorStatus == AAC_DEC_OK) + pIcsInfo->Valid = 1; + + return ErrorStatus; +} + + +/* + interleave codebooks the following way + + 9 (84w) | 1 (51w) + 10 (82w) | 2 (39w) + SCL (65w) | 4 (38w) + 3 (39w) | 5 (41w) + | 6 (40w) + | 7 (31w) + | 8 (31w) + (270w) (271w) +*/ + + +/* + Table entries are sorted as following: + | num_swb_long_window | sfbands_long | num_swb_short_window | sfbands_short | +*/ +AAC_DECODER_ERROR getSamplingRateInfo( + SamplingRateInfo *t, + UINT samplesPerFrame, + UINT samplingRateIndex, + UINT samplingRate + ) +{ + int index = 0; + + + t->samplingRateIndex = samplingRateIndex; + t->samplingRate = samplingRate; + + switch (samplesPerFrame) { + case 1024: + index = 0; + break; + case 960: + index = 1; + break; + case 512: + index = 3; + break; + case 480: + index = 4; + break; + + default: + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + t->ScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].sfbOffsetLong; + t->ScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].sfbOffsetShort; + t->NumberOfScaleFactorBands_Long = sfbOffsetTables[index][samplingRateIndex].numberOfSfbLong; + t->NumberOfScaleFactorBands_Short = sfbOffsetTables[index][samplingRateIndex].numberOfSfbShort; + + if (t->ScaleFactorBands_Long == NULL || t->NumberOfScaleFactorBands_Long == 0) { + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + FDK_ASSERT(t->ScaleFactorBands_Long[t->NumberOfScaleFactorBands_Long] == samplesPerFrame); + FDK_ASSERT(t->ScaleFactorBands_Short == NULL || t->ScaleFactorBands_Short[t->NumberOfScaleFactorBands_Short]*8 == samplesPerFrame); + + return AAC_DEC_OK; +} diff --git a/libAACdec/src/channelinfo.h b/libAACdec/src/channelinfo.h new file mode 100644 index 00000000..e092ab38 --- /dev/null +++ b/libAACdec/src/channelinfo.h @@ -0,0 +1,450 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: individual channel stream info + +******************************************************************************/ + +#ifndef CHANNELINFO_H +#define CHANNELINFO_H + +#include "common_fix.h" + +#include "aac_rom.h" +#include "aacdecoder_lib.h" +#include "FDK_bitstream.h" +#include "overlapadd.h" + +#include "mdct.h" +#include "stereo.h" +#include "pulsedata.h" +#include "aacdec_tns.h" + +#include "aacdec_pns.h" + +#include "aacdec_hcr_types.h" +#include "rvlc_info.h" + + +#include "conceal_types.h" + + #include "aacdec_drc_types.h" + +/* Output rendering mode */ +typedef enum { + AACDEC_RENDER_INVALID = 0, + AACDEC_RENDER_IMDCT, + AACDEC_RENDER_ELDFB, + AACDEC_RENDER_LPD, + AACDEC_RENDER_INTIMDCT +} AACDEC_RENDER_MODE; + +enum { + MAX_QUANTIZED_VALUE = 8191 +}; + +enum +{ + OnlyLongSequence = 0, + LongStartSequence, + EightShortSequence, + LongStopSequence +}; + + +typedef struct +{ + const SHORT *ScaleFactorBands_Long; + const SHORT *ScaleFactorBands_Short; + UCHAR NumberOfScaleFactorBands_Long; + UCHAR NumberOfScaleFactorBands_Short; + UINT samplingRateIndex; + UINT samplingRate; +} SamplingRateInfo; + +typedef struct +{ + UCHAR CommonWindow; + UCHAR GlobalGain; + +} CRawDataInfo; + +typedef struct +{ + UCHAR WindowGroupLength[8]; + UCHAR WindowGroups; + UCHAR Valid; + + UCHAR WindowShape; /* 0: sine window, 1: KBD, 2: low overlap */ + UCHAR WindowSequence; /* See enum above, 0: long, 1: start, 2: short, 3: stop */ + UCHAR MaxSfBands; + UCHAR ScaleFactorGrouping; + + UCHAR TotalSfBands; + +} CIcsInfo; + + +enum +{ + ZERO_HCB = 0, + ESCBOOK = 11, + NSPECBOOKS = ESCBOOK + 1, + BOOKSCL = NSPECBOOKS, + NOISE_HCB = 13, + INTENSITY_HCB2 = 14, + INTENSITY_HCB = 15, + LAST_HCB +}; + +#define TNS_SCALE 3 + +/* + * This struct must be allocated one for every channel and must be persistent. + */ +typedef struct +{ + FIXP_DBL *pOverlapBuffer; + mdct_t IMdct; + + + + CDrcChannelData drcData; + CConcealmentInfo concealmentInfo; + +} CAacDecoderStaticChannelInfo; + + +/* + * This union must be allocated for every element (up to 2 channels). + */ +typedef struct { + + /* Common bit stream data */ + SHORT aScaleFactor[(8*16)]; /* Spectral scale factors for each sfb in each window. */ + SHORT aSfbScale[(8*16)]; /* could be free after ApplyTools() */ + UCHAR aCodeBook[(8*16)]; /* section data: codebook for each window and sfb. */ + CTnsData TnsData; + CRawDataInfo RawDataInfo; + + shouldBeUnion { + + struct { + CPulseData PulseData; + SHORT aNumLineInSec4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax */ + UCHAR aCodeBooks4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for Drm syntax. Same as "aCodeBook" ? */ + SHORT lenOfReorderedSpectralData; + SCHAR lenOfLongestCodeword; + SCHAR numberSection; + SCHAR rvlcCurrentScaleFactorOK; + SCHAR rvlcIntensityUsed; + } aac; + } specificTo; + +} CAacDecoderDynamicData; + +typedef shouldBeUnion { + CAacDecoderDynamicData pAacDecoderDynamicData[2]; + + /* Common signal data, can be used once the bit stream data from above is not used anymore. */ + FIXP_DBL mdctOutTemp[1024]; + FIXP_DBL sbrWorkBuffer[1024*2]; + +} CWorkBufferCore1; + +/* Common data referenced by all channels */ +typedef struct { + + CWorkBufferCore1 *workBufferCore1; + FIXP_DBL* workBufferCore2; + + CPnsInterChannelData pnsInterChannelData; + INT pnsCurrentSeed; + INT pnsRandomSeed[(8*16)]; + + CJointStereoData jointStereoData; /* One for one element */ + + shouldBeUnion { + struct { + CErHcrInfo erHcrInfo; + CErRvlcInfo erRvlcInfo; + SHORT aRvlcScfEsc[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfFwd[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfBwd[RVLC_MAX_SFB]; /* needed once for all channels */ + } aac; + + } overlay; + +} CAacDecoderCommonData; + + +/* + * This struct must be allocated one for every channels of every element and must be persistent. + * Among its members, the following memory areas can be overwritten under the given conditions: + * - pSpectralCoefficient The memory pointed to can be overwritten after time signal rendering. + * - data can be overwritten after time signal rendering. + * - pDynData memory pointed to can be overwritten after each CChannelElement_Decode() call. + * - pComData->overlay memory pointed to can be overwritten after each CChannelElement_Decode() call.. + */ +typedef struct +{ + SPECTRAL_PTR pSpectralCoefficient; /* Spectral coefficients of each window */ + SHORT specScale[8]; /* Scale shift values of each spectrum window */ + CIcsInfo icsInfo; + INT granuleLength; /* Size of smallest spectrum piece */ + UCHAR ElementInstanceTag; + + AACDEC_RENDER_MODE renderMode; /* Output signal rendering mode */ + + shouldBeUnion { + struct { + CPnsData PnsData; /* Not required for USAC */ + } aac; + + struct { + } usac; + } data; + + CAacDecoderDynamicData *pDynData; /* Data required for one element and discarded after decoding */ + CAacDecoderCommonData *pComData; /* Data required for one channel at a time during decode */ + +} CAacDecoderChannelInfo; + +/* channelinfo.cpp */ + +AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, UINT samplingRateIndex, UINT samplingRate); + +/** + * \brief Read max SFB from bit stream and assign TotalSfBands according + * to the window sequence and sample rate. + * \param hBs bit stream handle as data source + * \param pIcsInfo IcsInfo structure to read the window sequence and store MaxSfBands and TotalSfBands + * \param pSamplingRateInfo read only + */ +AAC_DECODER_ERROR IcsReadMaxSfb ( + HANDLE_FDK_BITSTREAM hBs, + CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo + ); + +AAC_DECODER_ERROR IcsRead( + HANDLE_FDK_BITSTREAM bs, + CIcsInfo *pIcsInfo, + const SamplingRateInfo* SamplingRateInfoTable, + const UINT flags + ); + +/* stereo.cpp, only called from this file */ + +/*! + \brief Applies MS stereo. + + The function applies MS stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmittedL number of transmitted scalefactor bands in left channel. + \param scaleFactorBandsTransmittedR number of transmitted scalefactor bands in right channel. + May differ from scaleFactorBandsTransmittedL only for USAC. + \return none +*/ +void CJointStereo_ApplyMS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const short *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR); + +/*! + \brief Applies intensity stereo + + The function applies intensity stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmitted number of transmitted scalefactor bands. + \param CommonWindow common window bit. + \return none +*/ +void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const short *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const UINT CommonWindow); + + +/* aacdec_pns.cpp */ +int CPns_IsPnsUsed (const CPnsData *pPnsData, + const int group, + const int band); + +void CPns_SetCorrelation(CPnsData *pPnsData, + const int group, + const int band, + const int outofphase); + +/****************** inline functions ******************/ + +inline UCHAR IsValid(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->Valid; +} + +inline UCHAR IsLongBlock(const CIcsInfo *pIcsInfo) +{ + return (pIcsInfo->WindowSequence != EightShortSequence); +} + +inline UCHAR GetWindowShape(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->WindowShape; +} + +inline UCHAR GetWindowSequence(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->WindowSequence; +} + +inline const SHORT *GetScaleFactorBandOffsets(const CIcsInfo *pIcsInfo, const SamplingRateInfo* samplingRateInfo) +{ + if (IsLongBlock(pIcsInfo)) + { + return samplingRateInfo->ScaleFactorBands_Long; + } + else + { + return samplingRateInfo->ScaleFactorBands_Short; + } +} + +inline int GetWindowsPerFrame(const CIcsInfo *pIcsInfo) +{ + return (pIcsInfo->WindowSequence == EightShortSequence) ? 8 : 1; +} + +inline UCHAR GetWindowGroups(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->WindowGroups; +} + +inline UCHAR GetWindowGroupLength(const CIcsInfo *pIcsInfo, const INT index) +{ + return pIcsInfo->WindowGroupLength[index]; +} + +inline const UCHAR *GetWindowGroupLengthTable(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->WindowGroupLength; +} + +inline UCHAR GetScaleFactorBandsTransmitted(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->MaxSfBands; +} + +inline UCHAR GetScaleMaxFactorBandsTransmitted(const CIcsInfo *pIcsInfo0, const CIcsInfo *pIcsInfo1) +{ + return fMax(pIcsInfo0->MaxSfBands, pIcsInfo1->MaxSfBands); +} + +inline UCHAR GetScaleFactorBandsTotal(const CIcsInfo *pIcsInfo) +{ + return pIcsInfo->TotalSfBands; +} + +/* Note: This function applies to AAC-LC only ! */ +inline UCHAR GetMaximumTnsBands(const CIcsInfo *pIcsInfo, const int samplingRateIndex) +{ + return tns_max_bands_tbl[samplingRateIndex][!IsLongBlock(pIcsInfo)]; +} + +#endif /* #ifndef CHANNELINFO_H */ + diff --git a/libAACdec/src/conceal.cpp b/libAACdec/src/conceal.cpp new file mode 100644 index 00000000..1c313efe --- /dev/null +++ b/libAACdec/src/conceal.cpp @@ -0,0 +1,1866 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: independent channel concealment + +******************************************************************************/ + +/*! + \page concealment AAC core concealment + + This AAC core implementation includes a concealment function, which can be enabled + using the several defines during compilation. + + There are various tests inside the core, starting with simple CRC tests and ending in + a variety of plausibility checks. If such a check indicates an invalid bitstream, then + concealment is applied. + + Concealment is also applied when the calling main program indicates a distorted or missing + data frame using the frameOK flag. This is used for error detection on the transport layer. + (See below) + + There are three concealment-modes: + + 1) Muting: The spectral data is simply set to zero in case of an detected error. + + 2) Noise substitution: In case of an detected error, concealment copies the last frame and adds + attenuates the spectral data. For this mode you have to set the #CONCEAL_NOISE define. + Noise substitution adds no additional delay. + + 3) Interpolation: The interpolation routine swaps the spectral data from the previous and the + current frame just before the final frequency to time conversion. In case a single frame is + corrupted, concealmant interpolates between the last good and the first good frame to create + the spectral data for the missing frame. If multiple frames are corrupted, concealment + implements first a fade out based on slightly modified spectral values from the last good + frame. As soon as good frames are available, concealmant fades in the new spectral data. + For this mode you have to set the #CONCEAL_INTER define. Note that in this case, you also + need to set #SBR_BS_DELAY_ENABLE, which basically adds approriate delay in the SBR decoder. + Note that the Interpolating-Concealment increases the delay of your decoder by one frame + and that it does require additional resources such as memory and computational complexity. + +

How concealment can be used with errors on the transport layer

+ + Many errors can or have to be detected on the transport layer. For example in IP based systems + packet loss can occur. The transport protocol used should indicate such packet loss by inserting + an empty frame with frameOK=0. +*/ + +#include "conceal.h" + +#include "aac_rom.h" +#include "genericStds.h" + + +/* PNS (of block) */ +#include "aacdec_pns.h" +#include "block.h" + +#include "FDK_tools_rom.h" + +#define CONCEAL_DFLT_COMF_NOISE_LEVEL ( 46 ) /* ~= -70 dB */ + + +/* default settings */ +#define CONCEAL_DFLT_FADEOUT_FRAMES ( 5 ) +#define CONCEAL_DFLT_FADEIN_FRAMES ( 5 ) +#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES ( 3 ) + +#define CONCEAL_DFLT_FADE_FACTOR ( 0.707106781186548f ) /* 1/sqrt(2) */ + +/* some often used constants: */ +#define FIXP_ZERO FL2FXCONST_DBL(0.0f) +#define FIXP_ONE FL2FXCONST_DBL(1.0f) +#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f) + +/* For parameter conversion */ +#define CONCEAL_PARAMETER_BITS ( 8 ) +#define CONCEAL_MAX_QUANT_FACTOR ( (1<method = ConcealMethodInter; + + pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES; + pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES; + pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES; + + pConcealCommonData->comfortNoiseLevel = CONCEAL_DFLT_COMF_NOISE_LEVEL; + + /* Init fade factors (symetric) */ + pConcealCommonData->fadeOutFactor[0] = FL2FXCONST_SGL( CONCEAL_DFLT_FADE_FACTOR ); + pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0]; + + for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + pConcealCommonData->fadeOutFactor[i] = FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i-1],FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR))); + pConcealCommonData->fadeInFactor[i] = pConcealCommonData->fadeOutFactor[i]; + } + } +} + + + +/*! + \brief Get current concealment method. + + \pConcealCommonData Pointer to common concealment data (for all channels) + + \return Concealment method. +*/ +CConcealmentMethod + CConcealment_GetMethod( CConcealParams *pConcealCommonData ) +{ + CConcealmentMethod method = ConcealMethodNone; + + if (pConcealCommonData != NULL) { + method = pConcealCommonData->method; + } + + return (method); +} + + +/*! + \brief Init concealment information for each channel + + The function initializes the concealment information. Two methods can be chosen: + 0 = interpolation method (adds delay) + 1 = noise substitution (no delay, low complexity) + + \return none +*/ +void + CConcealment_InitChannelData ( + CConcealmentInfo *pConcealChannelInfo, + CConcealParams *pConcealCommonData, + int samplesPerFrame ) +{ + int i; + + pConcealChannelInfo->pConcealParams = pConcealCommonData; + + FDKmemclear(pConcealChannelInfo->spectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + + for (i = 0; i < 8; i++) { + pConcealChannelInfo->specScale[i] = 0; + } + + pConcealChannelInfo->iRandomPhase = 0; + + pConcealChannelInfo->windowSequence = 0; + pConcealChannelInfo->windowShape = 0; + + pConcealChannelInfo->prevFrameOk[0] = 1; + pConcealChannelInfo->prevFrameOk[1] = 1; + + pConcealChannelInfo->cntFadeFrames = 0; + pConcealChannelInfo->cntValidFrames = 0; + + pConcealChannelInfo->concealState = ConcealState_Ok; + +} + + +/*! + \brief Set error concealment parameters + + \concealParams + \method + \fadeOutSlope + \fadeInSlope + \muteRelease + \comfNoiseLevel + + \return none +*/ +AAC_DECODER_ERROR + CConcealment_SetParams ( + CConcealParams *concealParams, + int method, + int fadeOutSlope, + int fadeInSlope, + int muteRelease, + int comfNoiseLevel ) +{ + /* set concealment technique */ + if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + switch ((CConcealmentMethod)method) + { + case ConcealMethodMute: + case ConcealMethodNoise: + case ConcealMethodInter: + /* Be sure to enable delay adjustment of SBR decoder! */ + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->method = (CConcealmentMethod)method; + } + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-out slope */ + if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ( (fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) + && (fadeOutSlope >= 0) ) + { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeOutFrames = fadeOutSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-in slope */ + if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ( (fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) + && (fadeInSlope >= 1) ) + { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeInFrames = fadeInSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of error-free frames after which the muting will be released */ + if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ( (muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS<<1)) + && (muteRelease >= 0) ) + { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numMuteReleaseFrames = muteRelease; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set confort noise level which will be inserted while in state 'muting' */ + if (comfNoiseLevel != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ( (comfNoiseLevel < -1) + || (comfNoiseLevel > 127) ) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + concealParams->comfortNoiseLevel = comfNoiseLevel; + } + } + + return (AAC_DEC_OK); +} + + +/*! + \brief Set fade-out/in attenuation factor vectors + + \concealParams + \fadeOutAttenuationVector + \fadeInAttenuationVector + + \return 0 if OK all other values indicate errors +*/ +AAC_DECODER_ERROR + CConcealment_SetAttenuation ( + CConcealParams *concealParams, + SHORT *fadeOutAttenuationVector, + SHORT *fadeInAttenuationVector ) +{ + if ( (fadeOutAttenuationVector == NULL) + && (fadeInAttenuationVector == NULL) ) { + return AAC_DEC_SET_PARAM_FAIL; + } + + /* Fade-out factors */ + if (fadeOutAttenuationVector != NULL) + { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeOutAttenuationVector[i] < 0) || (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) + { + concealParams->fadeOutFactor[i] = + FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, + 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0/2.0)>>(CONCEAL_PARAMETER_BITS-1)) * (INT)fadeOutAttenuationVector[i]), + CONCEAL_PARAMETER_BITS + ) + ); + } + } + + /* Fade-in factors */ + if (fadeInAttenuationVector != NULL) + { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeInAttenuationVector[i] < 0) || (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) + { + concealParams->fadeInFactor[i] = + FX_DBL2FX_SGL( fLdPow( CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, + 0, + (FIXP_DBL)((INT)(FIXP_ONE>>CONCEAL_PARAMETER_BITS) * (INT)fadeInAttenuationVector[i]), + CONCEAL_PARAMETER_BITS + ) + ); + } + } + + return (AAC_DEC_OK); +} + + +/*! + \brief Get state of concealment module. + + \pConcealChannelInfo + + \return Concealment state. +*/ +CConcealmentState + CConcealment_GetState ( + CConcealmentInfo *pConcealChannelInfo + ) +{ + CConcealmentState state = ConcealState_Ok; + + if (pConcealChannelInfo != NULL) { + state = pConcealChannelInfo->concealState; + } + + return (state); +} + + +static void CConcealment_fakePnsData ( + CPnsData *pPnsData, + CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo, + SHORT *pSpecScale, + SHORT *pScaleFactor, + const int level ) +{ + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + + int pnsBand, band, group, win; + //int delta = 0; + int windowsPerFrame = GetWindowsPerFrame(pIcsInfo); + int refLevel = (windowsPerFrame > 1) ? 82 : 91; + + FDK_ASSERT(level >= 0 && level <= 127); + + for (win = 0; win < windowsPerFrame; win++) { + pSpecScale[win] = 31; + } + + /* fake ICS info if necessary */ + if (!IsValid(pIcsInfo)) { + pIcsInfo->WindowGroups = 1; + if (IsLongBlock(pIcsInfo)) { + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pIcsInfo->WindowGroupLength[0] = 1; + } + else { + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pIcsInfo->WindowGroupLength[0] = 8; + } + pIcsInfo->MaxSfBands = pIcsInfo->TotalSfBands; + } + + /* global activate PNS */ + pPnsData->PnsActive = 1; + /* set energy level */ + pPnsData->CurrentEnergy = fixMax( 0, refLevel - level ); + + /* + value: | Avg. RMS power | Avg. RMS power | + | specScale = 22 | specScale = 31 | + -------+----------------+----------------+ + 5 | | -99.0 dB + 15 | | -90.0 dB + 25 | | -89.7 dB + 35 | | -85.3 dB + ... | ... | ... + 45 | -69.9 dB | -70.0 dB + 50 | -62.2 dB | + 55 | -55.6 dB | -54.6 dB + 60 | -47.0 dB | + 65 | -39.5 dB | -39.5 dB + 70 | -31.9 dB | + 75 | -24.4 dB | -24.4 dB + 80 | -16.9 dB | + 85 | -9.4 dB (c) | -9.4 dB + 90 | -3.9 dB (c) | + 95 | | -2.1 dB + 100 | | -1.6 dB + 105 | | -1.4 dB + */ + + for (group=0; group < GetWindowGroups(pIcsInfo); group++) + { + for (band=0; band < GetScaleFactorBandsTransmitted(pIcsInfo); band++) + { + pnsBand = group * 16 + band; + + if (pnsBand >= NO_OFBANDS) { + return; + } + //pPnsData->CurrentEnergy += delta ; + pScaleFactor[pnsBand] = pPnsData->CurrentEnergy; + pInterChannelData->correlated[pnsBand] = 0; + pPnsData->pnsUsed[pnsBand] = 1; + } + } +} + + +/*! + \brief Store data for concealment techniques applied later + + Interface function to store data for different concealment strategies + + \return none + */ +void + CConcealment_Store ( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo ) +{ + if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD + ) ) + { + FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + SHORT tSpecScale[8]; + UCHAR tWindowShape, tWindowSequence; + + /* store old window infos for swapping */ + tWindowSequence = hConcealmentInfo->windowSequence; + tWindowShape = hConcealmentInfo->windowShape; + + /* store old scale factors for swapping */ + FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8*sizeof(SHORT)); + + /* store new window infos */ + hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo); + hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo); + hConcealmentInfo->lastWinGrpLen = *(GetWindowGroupLengthTable(pIcsInfo)+GetWindowGroups(pIcsInfo)-1); + + /* store new scale factors */ + FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8*sizeof(SHORT)); + + if (CConcealment_GetDelay(hConcealmentInfo->pConcealParams) == 0) + { + /* store new spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL)); +#else + FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1]; + int i; + + for (i = 1024; i != 0; i--) { + *pCncl-- = FX_DBL2FX_CNCL(*pSpec--); + } +#endif + } + else + { + FIXP_CNCL *RESTRICT pCncl = &hConcealmentInfo->spectralCoefficient[1024-1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024-1]; + int i; + + /* swap spectral data */ + for (i = 1024; i != 0; i--) { + FIXP_DBL tSpec = *pSpec; + *pSpec-- = FX_CNCL2FX_DBL(*pCncl); + *pCncl-- = FX_DBL2FX_CNCL( tSpec); + } + + /* complete swapping of window infos */ + pIcsInfo->WindowSequence = tWindowSequence; + pIcsInfo->WindowShape = tWindowShape; + + /* complete swapping of scale factors */ + FDKmemcpy(pSpecScale, tSpecScale, 8*sizeof(SHORT)); + } + } + +} + + +/*! + \brief Apply concealment + + Interface function to different concealment strategies + + \return none + */ +int + CConcealment_Apply ( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const int samplesPerFrame, + const UCHAR lastLpdMode, + const int frameOk, + const UINT flags) +{ + int appliedProcessing = 0; + + if ( (frameOk == 0) + && (pAacDecoderChannelInfo->renderMode != (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode) ) { + /* restore the last render mode to stay in the same domain which allows to do a proper concealment */ + pAacDecoderChannelInfo->renderMode = (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode; + } else { + /* otherwise store the current mode */ + hConcealmentInfo->lastRenderMode = (SCHAR)pAacDecoderChannelInfo->renderMode; + } + + if ( frameOk ) + { + /* Rescue current data for concealment in future frames */ + CConcealment_Store ( hConcealmentInfo, + pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo ); + /* Reset index to random sign vector to make sign calculation frame agnostic + (only depends on number of subsequently concealed spectral blocks) */ + hConcealmentInfo->iRandomPhase = 0; + } + + /* hand current frame status to the state machine */ + CConcealment_UpdateState( hConcealmentInfo, + frameOk ); + + { + /* Create data for signal rendering according to the selected concealment method and decoder operating mode. */ + + + if ( !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD + ) + ) + { + switch (hConcealmentInfo->pConcealParams->method) + { + default: + case ConcealMethodMute: + if (!frameOk) { + /* Mute spectral data in case of errors */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + /* Set last window shape */ + pAacDecoderChannelInfo->icsInfo.WindowShape = hConcealmentInfo->windowShape; + appliedProcessing = 1; + } + break; + + case ConcealMethodNoise: + /* Noise substitution error concealment technique */ + appliedProcessing = + CConcealment_ApplyNoise (hConcealmentInfo, + pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, + pSamplingRateInfo, + samplesPerFrame, + flags); + break; + + case ConcealMethodInter: + /* Energy interpolation concealment based on 3GPP */ + appliedProcessing = + CConcealment_ApplyInter (hConcealmentInfo, + pAacDecoderChannelInfo, + pSamplingRateInfo, + samplesPerFrame, + 0, /* don't use tonal improvement */ + frameOk); + break; + + } + } + } + /* update history */ + hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1]; + hConcealmentInfo->prevFrameOk[1] = frameOk; + + return appliedProcessing; +} + +/*! +\brief Apply concealment noise substitution + + In case of frame lost this function produces a noisy frame with respect to the + energies values of past frame. + +\return none + */ +static int + CConcealment_ApplyNoise (CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const int samplesPerFrame, + const UINT flags) +{ + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; + + FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + int appliedProcessing = 0; + + FDK_ASSERT((samplesPerFrame>=480) && (samplesPerFrame<=1024)); + FDK_ASSERT((samplesPerFrame&0x1F) == 0); + + switch (pConcealmentInfo->concealState) + { + case ConcealState_Ok: + /* Nothing to do here! */ + break; + + case ConcealState_Single: + case ConcealState_FadeOut: + { + /* restore frequency coefficients from buffer with a specific muting */ + FIXP_SGL fac; + int win, numWindows = 1; + int windowLen = samplesPerFrame; + int tFadeFrames, lastWindow = 0; + int win_idx_stride = 1; + + FDK_ASSERT(pConcealmentInfo != NULL); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames <= pConcealCommonData->numFadeOutFrames); + + /* get attenuation factor */ + tFadeFrames = pConcealmentInfo->cntFadeFrames; + fac = pConcealCommonData->fadeOutFactor[tFadeFrames]; + + /* set old window parameters */ + { + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + if (pConcealmentInfo->windowSequence == 2) { + /* short block handling */ + numWindows = 8; + windowLen = samplesPerFrame >> 3; + lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen; + } + } + + for (win = 0; win < numWindows; win++) { + FIXP_CNCL *pCncl = pConcealmentInfo->spectralCoefficient + (lastWindow * windowLen); + FIXP_DBL *pOut = pSpectralCoefficient + (win * windowLen); + int i; + + FDK_ASSERT((lastWindow * windowLen + windowLen) <= samplesPerFrame); + + /* restore frequency coefficients from buffer with a specific attenuation */ + for (i = 0; i < windowLen; i++) { + pOut[i] = fMult(pCncl[i], fac); + } + + /* apply random change of sign for spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, + pOut, + windowLen ); + + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + + /* set old scale factors */ + pSpecScale[win*win_idx_stride] = pConcealmentInfo->specScale[win_idx_stride*lastWindow++]; + + if ( (lastWindow >= numWindows) + && (numWindows > 1) ) + { + /* end of sequence -> rewind */ + lastWindow = numWindows - pConcealmentInfo->lastWinGrpLen; + /* update the attenuation factor to get a faster fade-out */ + tFadeFrames += 1; + if (tFadeFrames < pConcealCommonData->numFadeOutFrames) { + fac = pConcealCommonData->fadeOutFactor[tFadeFrames]; + } else { + fac = (FIXP_SGL)0; + } + } + } + + /* store temp vars */ + pConcealmentInfo->cntFadeFrames = tFadeFrames; + appliedProcessing = 1; + } + break; + + case ConcealState_Mute: + { + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */ + pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + + if ( !(flags & (AC_USAC|AC_RSVD50)) + && pConcealCommonData->comfortNoiseLevel >= 0 + && pConcealCommonData->comfortNoiseLevel <= 61 /* -90dB */) + { + /* insert comfort noise using PNS */ + CConcealment_fakePnsData ( + &pAacDecoderChannelInfo->data.aac.PnsData, + pIcsInfo, + pSamplingRateInfo, + pAacDecoderChannelInfo->pDynData->aSfbScale, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + pConcealCommonData->comfortNoiseLevel + ); + + CPns_Apply ( + &pAacDecoderChannelInfo->data.aac.PnsData, + pIcsInfo, + pAacDecoderChannelInfo->pSpectralCoefficient, + pAacDecoderChannelInfo->specScale, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + pSamplingRateInfo, + pAacDecoderChannelInfo->granuleLength, + 0 /* always apply to first channel */ + ); + } + appliedProcessing = 1; + } + break; + + case ConcealState_FadeIn: + { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames); + + /* attenuate signal to get a smooth fade-in */ + FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; + FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames]; + int i; + + for (i = samplesPerFrame; i != 0; i--) { + *pOut = fMult(*pOut, fac); + pOut--; + } + appliedProcessing = 1; + } + break; + + default: + /* we shouldn't come here anyway */ + FDK_ASSERT(0); + break; + } + + return appliedProcessing; +} + + +/*! + \brief Apply concealment interpolation + + The function swaps the data from the current and the previous frame. If an + error has occured, frame interpolation is performed to restore the missing + frame. In case of multiple faulty frames, fade-in and fade-out is applied. + + \return none +*/ +static int + CConcealment_ApplyInter ( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const int samplesPerFrame, + const int improveTonal, + const int frameOk ) +{ + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; + + FIXP_DBL *pSpectralCoefficient = SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + + int sfbEnergyPrev[64]; + int sfbEnergyAct [64]; + + int i, appliedProcessing = 0; + + /* clear/init */ + FDKmemclear(sfbEnergyPrev, 64 * sizeof(int)); + FDKmemclear(sfbEnergyAct, 64 * sizeof(int)); + + + if (!frameOk) + { + /* Restore last frame from concealment buffer */ + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + /* Restore spectral data */ + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]); + } + + /* Restore scale factors */ + FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8*sizeof(SHORT)); + } + + /* if previous frame was not ok */ + if (!pConcealmentInfo->prevFrameOk[1]) { + + /* if current frame (f_n) is ok and the last but one frame (f_(n-2)) + was ok, too, then interpolate both frames in order to generate + the current output frame (f_(n-1)). Otherwise, use the last stored + frame (f_(n-2) or f_(n-3) or ...). */ + if (frameOk && pConcealmentInfo->prevFrameOk[0]) + { + appliedProcessing = 1; + + + /* Interpolate both frames in order to generate the current output frame (f_(n-1)). */ + if (pIcsInfo->WindowSequence == EightShortSequence) { + /* f_(n-2) == EightShortSequence */ + /* short--??????--short, short--??????--long interpolation */ + /* short--short---short, short---long---long interpolation */ + + int wnd; + + if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */ + /* short--short---short interpolation */ + + int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + pIcsInfo->WindowShape = 1; + pIcsInfo->WindowSequence = EightShortSequence; + + for (wnd = 0; wnd < 8; wnd++) + { + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-2) */ + pSamplingRateInfo, + EightShortSequence, + CConcealment_NoExpand, + sfbEnergyPrev); + + CConcealment_CalcBandEnergy( + &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_n */ + pSamplingRateInfo, + EightShortSequence, + CConcealment_NoExpand, + sfbEnergyAct); + + CConcealment_InterpolateBuffer( + &pSpectralCoefficient[wnd * (samplesPerFrame / 8)], /* spec_(n-1) */ + &pSpecScale[wnd], + &pConcealmentInfo->specScale[wnd], + &pSpecScale[wnd], + sfbEnergyPrev, + sfbEnergyAct, + scaleFactorBandsTotal, + pSfbOffset); + + } + } else { /* f_n != EightShortSequence */ + /* short---long---long interpolation */ + + int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleOut; + + CConcealment_CalcBandEnergy(&pSpectralCoefficient[samplesPerFrame - (samplesPerFrame / 8)], /* [wnd] spec_(n-2) */ + pSamplingRateInfo, + EightShortSequence, + CConcealment_Expand, + sfbEnergyAct); + + CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, + OnlyLongSequence, + CConcealment_NoExpand, + sfbEnergyPrev); + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = LongStopSequence; + + for (i = 0; i < samplesPerFrame ; i++) { + pSpectralCoefficient[i] = pConcealmentInfo->spectralCoefficient[i]; /* spec_n */ + } + + for (i = 0; i < 8; i++) { /* search for max(specScale) */ + if (pSpecScale[i] > pSpecScale[0]) { + pSpecScale[0] = pSpecScale[i]; + } + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pConcealmentInfo->specScale[0], + &pSpecScale[0], + &specScaleOut, + sfbEnergyPrev, + sfbEnergyAct, + scaleFactorBandsTotal, + pSfbOffset); + + pSpecScale[0] = specScaleOut; + } + } else { + /* long--??????--short, long--??????--long interpolation */ + /* long---long---short, long---long---long interpolation */ + + int scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleAct = pConcealmentInfo->specScale[0]; + + CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */ + pSamplingRateInfo, + OnlyLongSequence, + CConcealment_NoExpand, + sfbEnergyPrev); + + if (pConcealmentInfo->windowSequence == EightShortSequence) { /* f_n == EightShortSequence */ + /* long---long---short interpolation */ + + pIcsInfo->WindowShape = 1; + pIcsInfo->WindowSequence = LongStartSequence; + + for (i = 1; i < 8; i++) { /* search for max(specScale) */ + if (pConcealmentInfo->specScale[i] > specScaleAct) { + specScaleAct = pConcealmentInfo->specScale[i]; + } + } + + /* Expand first short spectrum */ + CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, + EightShortSequence, + CConcealment_Expand, /* !!! */ + sfbEnergyAct); + } else { + /* long---long---long interpolation */ + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = OnlyLongSequence; + + CConcealment_CalcBandEnergy(pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, + OnlyLongSequence, + CConcealment_NoExpand, + sfbEnergyAct); + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pSpecScale[0], + &specScaleAct, + &pSpecScale[0], + sfbEnergyPrev, + sfbEnergyAct, + scaleFactorBandsTotal, + pSfbOffset); + + } + } + + /* Noise substitution of sign of the output spectral coefficients */ + CConcealment_ApplyRandomSign (pConcealmentInfo->iRandomPhase, + pSpectralCoefficient, + samplesPerFrame); + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } + + /* scale spectrum according to concealment state */ + switch (pConcealmentInfo->concealState) + { + case ConcealState_Single: + appliedProcessing = 1; + break; + + case ConcealState_FadeOut: + { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeOutFrames); + + /* restore frequency coefficients from buffer with a specific muting */ + FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; + FIXP_SGL fac = pConcealCommonData->fadeOutFactor[pConcealmentInfo->cntFadeFrames]; + + for (i = samplesPerFrame; i != 0; i--) { + *pOut = fMult(*pOut, fac); + pOut--; + } + appliedProcessing = 1; + } + break; + + case ConcealState_FadeIn: + { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < pConcealCommonData->numFadeInFrames); + + /* attenuate signal to get a smooth fade-in */ + FIXP_DBL *RESTRICT pOut = &pSpectralCoefficient[samplesPerFrame-1]; + FIXP_SGL fac = pConcealCommonData->fadeInFactor[pConcealmentInfo->cntFadeFrames]; + + for (i = samplesPerFrame; i != 0; i--) { + *pOut = fMult(*pOut, fac); + pOut--; + } + appliedProcessing = 1; + } + break; + + case ConcealState_Mute: + { + int fac = pConcealCommonData->comfortNoiseLevel; + + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape (required for F/T transform) */ + pIcsInfo->WindowSequence = CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = pIcsInfo->WindowSequence; /* Store for next frame (spectrum in concealment buffer can't be used at all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + + if (fac >= 0 && fac <= 61) { + /* insert comfort noise using PNS */ + CConcealment_fakePnsData ( + &pAacDecoderChannelInfo->data.aac.PnsData, + pIcsInfo, + pSamplingRateInfo, + pAacDecoderChannelInfo->specScale, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + fac + ); + + CPns_Apply ( + &pAacDecoderChannelInfo->data.aac.PnsData, + pIcsInfo, + pAacDecoderChannelInfo->pSpectralCoefficient, + pAacDecoderChannelInfo->specScale, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + pSamplingRateInfo, + pAacDecoderChannelInfo->granuleLength, + 0 /* always apply to first channel */ + ); + } + appliedProcessing = 1; + } + break; + + default: + /* nothing to do here */ + break; + } + + return appliedProcessing; +} + + +/*! + \brief Calculate the spectral energy + + The function calculates band-wise the spectral energy. This is used for + frame interpolation. + + \return none +*/ +static void + CConcealment_CalcBandEnergy ( + FIXP_DBL *spectrum, + const SamplingRateInfo *pSamplingRateInfo, + const int blockType, + CConcealmentExpandType expandType, + int *sfbEnergy ) +{ + const SHORT *pSfbOffset; + int line, sfb, scaleFactorBandsTotal = 0; + + /* In the following calculations, enAccu is initialized with LSB-value in order to avoid zero energy-level */ + + line = 0; + + switch(blockType) { + + case OnlyLongSequence: + case LongStartSequence: + case LongStopSequence: + + if (expandType == CConcealment_NoExpand) { + /* standard long calculation */ + scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for ( ; line < pSfbOffset[sfb+1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + else { + /* compress long to short */ + scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb+1] << 3; line++) { + enAccu += (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + + case EightShortSequence: + + if (expandType == CConcealment_NoExpand) { + /* standard short calculation */ + scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for ( ; line < pSfbOffset[sfb+1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + else { + /* expand short to long spectrum */ + scaleFactorBandsTotal = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = (sizeof(LONG)<<3) - CntLeadingZeros(pSfbOffset[sfb+1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for ( ; line < pSfbOffset[sfb+1]; line++) { + enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + } +} + + +/*! + \brief Interpolate buffer + + The function creates the interpolated spectral data according to the + energy of the last good frame and the current (good) frame. + + \return none +*/ +static void + CConcealment_InterpolateBuffer ( + FIXP_DBL *spectrum, + SHORT *pSpecScalePrv, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, + int *enPrv, + int *enAct, + int sfbCnt, + const SHORT *pSfbOffset ) +{ + int sfb, line = 0; + int fac_shift; + int fac_mod; + FIXP_DBL accu; + + for (sfb = 0; sfb < sfbCnt; sfb++) { + + fac_shift = enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1); + fac_mod = fac_shift & 3; + fac_shift = (fac_shift >> 2) + 1; + fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct); + + for (; line < pSfbOffset[sfb+1]; line++) { + accu = fMult(*(spectrum+line), facMod4Table[fac_mod]); + if (fac_shift < 0) { + accu >>= -fac_shift; + } else { + accu <<= fac_shift; + } + *(spectrum+line) = accu; + } + } + *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct); +} + + + + +static INT findEquiFadeFrame ( + CConcealParams *pConcealCommonData, + INT actFadeIndex, + int direction ) +{ + FIXP_SGL *pFactor; + FIXP_SGL referenceVal; + FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL; + + INT numFrames = 0; + INT nextFadeIndex = 0; + + int i; + + /* init depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + numFrames = pConcealCommonData->numFadeInFrames; + referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1; + pFactor = pConcealCommonData->fadeInFactor; + } + else { /* FADE-IN => FADE-OUT */ + numFrames = pConcealCommonData->numFadeOutFrames; + referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1; + pFactor = pConcealCommonData->fadeOutFactor; + } + + /* search for minimum difference */ + for (i = 0; i < numFrames; i++) { + FIXP_SGL diff = fixp_abs((pFactor[i]>>1) - referenceVal); + if (diff < minDiff) { + minDiff = diff; + nextFadeIndex = i; + } + } + + /* check and adjust depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (((pFactor[nextFadeIndex]>>1) <= referenceVal) && (nextFadeIndex > 0)) { + nextFadeIndex -= 1; + } + } + else { /* FADE-IN => FADE-OUT */ + if (((pFactor[nextFadeIndex]>>1) >= referenceVal) && (nextFadeIndex < numFrames-1)) { + nextFadeIndex += 1; + } + } + + return (nextFadeIndex); +} + + +/*! + \brief Update the concealment state + + The function updates the state of the concealment state-machine. The + states are: mute, fade-in, fade-out, interpolate and frame-ok. + + \return none +*/ +static void + CConcealment_UpdateState ( + CConcealmentInfo *pConcealmentInfo, + int frameOk ) +{ + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; + + switch (pConcealCommonData->method) + { + case ConcealMethodNoise: + { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if (frameOk) { + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for Noise Substitution -- */ + switch (pConcealmentInfo->concealState) + { + case ConcealState_Ok: + if (!frameOk) { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state SINGLE-FRAME-LOSS */ + pConcealmentInfo->concealState = ConcealState_Single; + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + } + break; + + case ConcealState_Single: /* Just a pre-stage before fade-out begins. Stay here only one frame! */ + pConcealmentInfo->cntFadeFrames += 1; + if (frameOk) { + if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, + pConcealmentInfo->cntFadeFrames-1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + } + } + break; + + case ConcealState_FadeOut: + pConcealmentInfo->cntFadeFrames += 1; /* used to address the fade-out factors */ + if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, + pConcealmentInfo->cntFadeFrames-1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */ + if (frameOk) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, + pConcealmentInfo->cntFadeFrames+1, + 1 /* FadeIn -> FadeOut */); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + default: + FDK_ASSERT(0); + break; + } + } + break; + + case ConcealMethodInter: + case ConcealMethodTonal: + { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if ( pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk) ) { + /* The frame is OK even if it can be estimated by the energy interpolation algorithm */ + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for energy interpolation -- */ + switch (pConcealmentInfo->concealState) + { + case ConcealState_Ok: + if (!(pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && !pConcealmentInfo->prevFrameOk[1] && frameOk))) { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* Fade out only if the energy interpolation algorithm can not be applied! */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + } + break; + + case ConcealState_Single: + pConcealmentInfo->concealState = ConcealState_Ok; + break; + + case ConcealState_FadeOut: + pConcealmentInfo->cntFadeFrames += 1; + + if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, + pConcealmentInfo->cntFadeFrames-1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealmentInfo->cntFadeFrames >= pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= 1; /* used to address the fade-in factors */ + + if (frameOk || pConcealmentInfo->prevFrameOk[1]) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( pConcealCommonData, + pConcealmentInfo->cntFadeFrames+1, + 1 /* FadeIn -> FadeOut */); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + } /* End switch(pConcealmentInfo->concealState) */ + } + break; + + default: + /* Don't need a state machine for other concealment methods. */ + break; + } + +} + + +/*! +\brief Randomizes the sign of the spectral data + + The function toggles the sign of the spectral data randomly. This is + useful to ensure the quality of the concealed frames. + +\return none + */ +static +void CConcealment_ApplyRandomSign (int randomPhase, + FIXP_DBL *spec, + int samplesPerFrame + ) +{ + int i; + USHORT packedSign=0; + + /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit */ + + /* read current packed sign word */ + packedSign = randomSign[randomPhase>>4]; + packedSign >>= (randomPhase&0xf); + + for (i = 0; i < samplesPerFrame ; i++) { + if ((randomPhase & 0xf) == 0) { + packedSign = randomSign[randomPhase>>4]; + } + + if (packedSign & 0x1) { + spec[i] = -spec[i]; + } + packedSign >>= 1; + + randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } +} + + +/*! + \brief Get fadeing factor for current concealment state. + + The function returns the factor used for fading that belongs to the current internal state. + + \return Fade factor + */ +FIXP_DBL + CConcealment_GetFadeFactor ( + CConcealmentInfo *hConcealmentInfo, + const int fPreviousFactor + ) +{ + FIXP_DBL fac = (FIXP_DBL)0; + + CConcealParams *pConcealCommonData = hConcealmentInfo->pConcealParams; + + if (hConcealmentInfo->pConcealParams->method > ConcealMethodMute) { + switch (hConcealmentInfo->concealState) { + default: + case ConcealState_Mute: + /* Nothing to do here */ + break; + case ConcealState_Ok: + fac = (FIXP_DBL)MAXVAL_DBL; + break; + case ConcealState_Single: + case ConcealState_FadeOut: + { + int idx = hConcealmentInfo->cntFadeFrames - ((fPreviousFactor != 0) ? 1 : 0); + fac = (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(pConcealCommonData->fadeOutFactor[idx]); + } + break; + case ConcealState_FadeIn: + { + int idx = hConcealmentInfo->cntFadeFrames + ((fPreviousFactor != 0) ? 1 : 0); + fac = (idx >= hConcealmentInfo->pConcealParams->numFadeInFrames) ? (FIXP_DBL)0 : FX_SGL2FX_DBL(pConcealCommonData->fadeInFactor[idx]); + } + break; + } + } + + return (fac); +} + + +/*! + \brief Get fadeing factor for current concealment state. + + The function returns the state (ok or not) of the previous frame. + If called before the function CConcealment_Apply() set the fBeforeApply + flag to get the correct value. + + \return Frame OK flag of previous frame. + */ +int + CConcealment_GetLastFrameOk ( + CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply + ) +{ + int prevFrameOk = 1; + + if (hConcealmentInfo != NULL) { + prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1]; + } + + return prevFrameOk; +} + +/*! + \brief Get the number of delay frames introduced by concealment technique. + + \return Number of delay frames. + */ +UINT + CConcealment_GetDelay ( + CConcealParams *pConcealCommonData + ) +{ + UINT frameDelay = 0; + + if (pConcealCommonData != NULL) { + switch (pConcealCommonData->method) { + case ConcealMethodTonal: + case ConcealMethodInter: + frameDelay = 1; + break; + default: + break; + } + } + + return frameDelay; +} + diff --git a/libAACdec/src/conceal.h b/libAACdec/src/conceal.h new file mode 100644 index 00000000..20e674f6 --- /dev/null +++ b/libAACdec/src/conceal.h @@ -0,0 +1,148 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: independent channel concealment + +******************************************************************************/ + +#ifndef _CONCEAL_H_ +#define _CONCEAL_H_ + +#include "aacdecoder_lib.h" + +#include "channelinfo.h" + +#define AACDEC_CONCEAL_PARAM_NOT_SPECIFIED ( 0xFFFE ) + +void CConcealment_InitCommonData (CConcealParams *pConcealCommonData); + +void CConcealment_InitChannelData (CConcealmentInfo *hConcealmentInfo, + CConcealParams *pConcealCommonData, + int samplesPerFrame); + +CConcealmentMethod + CConcealment_GetMethod (CConcealParams *pConcealCommonData); + +UINT + CConcealment_GetDelay (CConcealParams *pConcealCommonData); + +AAC_DECODER_ERROR + CConcealment_SetParams (CConcealParams *concealParams, + int method, + int fadeOutSlope, + int fadeInSlope, + int muteRelease, + int comfNoiseLevel); + +CConcealmentState + CConcealment_GetState (CConcealmentInfo *hConcealmentInfo); + +AAC_DECODER_ERROR + CConcealment_SetAttenuation (CConcealParams *concealParams, + SHORT *fadeOutAttenuationVector, + SHORT *fadeInAttenuationVector); + +void CConcealment_Store (CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo ); + +int CConcealment_Apply (CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + const int samplesPerFrame, + const UCHAR lastLpdMode, + const int FrameOk, + const UINT flags); + +FIXP_DBL + CConcealment_GetFadeFactor (CConcealmentInfo *hConcealmentInfo, + const int fPreviousFactor); + +int CConcealment_GetLastFrameOk (CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply); + +#endif /* #ifndef _CONCEAL_H_ */ diff --git a/libAACdec/src/conceal_types.h b/libAACdec/src/conceal_types.h new file mode 100644 index 00000000..31bc645d --- /dev/null +++ b/libAACdec/src/conceal_types.h @@ -0,0 +1,178 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Error concealment structs and types + +******************************************************************************/ + +#ifndef CONCEAL_TYPES_H +#define CONCEAL_TYPES_H + + + +#include "machine_type.h" +#include "common_fix.h" + +#include "rvlc_info.h" + + +#define CONCEAL_MAX_NUM_FADE_FACTORS ( 16 ) + + #define FIXP_CNCL FIXP_DBL + #define FL2FXCONST_CNCL FL2FXCONST_DBL + #define FX_DBL2FX_CNCL + #define FX_CNCL2FX_DBL + #define CNCL_FRACT_BITS DFRACT_BITS + +/* Warning: Do not ever change these values. */ +typedef enum +{ + ConcealMethodNone = -1, + ConcealMethodMute = 0, + ConcealMethodNoise = 1, + ConcealMethodInter = 2, + ConcealMethodTonal = 3 + +} CConcealmentMethod; + + +typedef enum +{ + ConcealState_Ok, + ConcealState_Single, + ConcealState_FadeIn, + ConcealState_Mute, + ConcealState_FadeOut + +} CConcealmentState; + + +typedef struct +{ + FIXP_SGL fadeOutFactor[CONCEAL_MAX_NUM_FADE_FACTORS]; + FIXP_SGL fadeInFactor [CONCEAL_MAX_NUM_FADE_FACTORS]; + + CConcealmentMethod method; + + int numFadeOutFrames; + int numFadeInFrames; + int numMuteReleaseFrames; + int comfortNoiseLevel; + +} CConcealParams; + + + +typedef struct +{ + CConcealParams *pConcealParams; + + FIXP_CNCL spectralCoefficient[1024]; + SHORT specScale[8]; + + INT iRandomPhase; + INT prevFrameOk[2]; + INT cntFadeFrames; + INT cntValidFrames; + + SHORT aRvlcPreviousScaleFactor[RVLC_MAX_SFB]; /* needed once per channel */ + UCHAR aRvlcPreviousCodebook[RVLC_MAX_SFB]; /* needed once per channel */ + SCHAR rvlcPreviousScaleFactorOK; + SCHAR rvlcPreviousBlockType; + + + SCHAR lastRenderMode; + + UCHAR windowShape; + UCHAR windowSequence; + UCHAR lastWinGrpLen; + + CConcealmentState concealState; + +} CConcealmentInfo; + + +#endif /* #ifndef CONCEAL_TYPES_H */ diff --git a/libAACdec/src/debug.h b/libAACdec/src/debug.h new file mode 100644 index 00000000..e9032915 --- /dev/null +++ b/libAACdec/src/debug.h @@ -0,0 +1,97 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: debug output + +******************************************************************************/ + +#ifndef DEBUG_H +#define DEBUG_H + +#include "machine_type.h" + + +#endif diff --git a/libAACdec/src/ldfiltbank.cpp b/libAACdec/src/ldfiltbank.cpp new file mode 100644 index 00000000..c08cc41b --- /dev/null +++ b/libAACdec/src/ldfiltbank.cpp @@ -0,0 +1,208 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************************************************************\ +* + * filename: ldfiltbank.c + * project : MPEG-4 Audio Decoder + * contents/description: low delay filterbank + * +\***************************************************************************/ + +#include "ldfiltbank.h" + + +#include "aac_rom.h" +#include "dct.h" +#include "FDK_tools_rom.h" +#include "mdct.h" + +#define LDFB_HEADROOM 2 + +static void multE2_DinvF_fdk(INT_PCM *output, FIXP_DBL* x, const FIXP_WTB* fb, FIXP_DBL* z, const int N, const int stride) +{ + int i, scale; + + /* scale for FIXP_DBL -> INT_PCM conversion. */ + scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM; + + for(i=0;i> (-WTS2-1) ); + + z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) ); + + tmp = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ; + +#if (SAMPLE_BITS <= 16) + FDK_ASSERT( (-WTS1-1 + scale) >= 0); + output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp, -WTS1-1 + scale, SAMPLE_BITS); +#else + FDK_ASSERT( (WTS1+1 - scale) >= 0); + output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1+1 - scale, SAMPLE_BITS); +#endif + + z[i] = z0; + z[N + i] = z2; + } + + for(i=N/4;i> (-WTS2-1) ); + + z[N/2+i] = x[N/2-1-i] + ( fMultDiv2(z[N + i], fb[2*N + N/2 + i]) >> (-WTS2-1) ); + + tmp0 = ( fMultDiv2(z[N/2+i], fb[N/2-1-i]) + fMultDiv2(z[i], fb[N/2+i]) ) ; + tmp1 = ( fMultDiv2(z[N/2+i], fb[N+N/2-1-i]) + fMultDiv2(z[i], fb[N+N/2+i]) ) ; + +#if (SAMPLE_BITS <= 16) + FDK_ASSERT( (-WTS0-1 + scale) >= 0); + output[(i-N/4)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS); + output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp1, -WTS1-1 + scale, SAMPLE_BITS); +#else + FDK_ASSERT( (WTS0+1 - scale) >= 0); + output[(i-N/4)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS); + output[(N*3/4-1-i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1+1 - scale, SAMPLE_BITS); +#endif + z[i] = z0; + z[N + i] = z2; + } + + /* Exchange quarter parts of x to bring them in the "right" order */ + for(i=0;i= 0); + output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_RIGHT_SHIFT(tmp0, -WTS0-1 + scale, SAMPLE_BITS); +#else + FDK_ASSERT( (WTS0+1 - scale) >= 0); + output[(N*3/4 + i)*stride] = (INT_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0+1 - scale, SAMPLE_BITS); +#endif + } +} + +int InvMdctTransformLowDelay_fdk (FIXP_DBL *mdctData, const int mdctData_e, INT_PCM *output, FIXP_DBL *fs_buffer, const int stride, const int N) { + + const FIXP_WTB *coef; + FIXP_DBL gain = (FIXP_DBL)0; + int scale = mdctData_e + MDCT_OUT_HEADROOM - LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside multE2_DinvF_fdk() below */ + + /* Select LD window slope */ + if (N == 512) + coef = (FIXP_WTB*)LowDelaySynthesis512; + else + coef = (FIXP_WTB*)LowDelaySynthesis480; + + /* + Apply exponent and 1/N factor. + Note: "scale" is off by one because for LD_MDCT the window length is twice + the window length of a regular MDCT. This is corrected inside multE2_DinvF_fdk(). + Refer to ISO/IEC 14496-3:2009 page 277, chapter 4.6.20.2 "Low Delay Window". + */ + imdct_gain(&gain, &scale, N); + + dct_IV(mdctData, N, &scale); + + if (gain != (FIXP_DBL)0) { + scaleValuesWithFactor(mdctData, gain, N, scale); + } else { + scaleValues(mdctData, N, scale); + } + + /* Since all exponent and factors have been applied, current exponent is zero. */ + multE2_DinvF_fdk(output, mdctData, coef, fs_buffer, N, stride); + + return (1); +} + + + + diff --git a/libAACdec/src/ldfiltbank.h b/libAACdec/src/ldfiltbank.h new file mode 100644 index 00000000..d1f9402b --- /dev/null +++ b/libAACdec/src/ldfiltbank.h @@ -0,0 +1,109 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************************************************************\ + * + + * filename: ldfiltbank.h + * project : MPEG-4 Audio Decoder + * contents/description: low delay filterbank interface + * +\***************************************************************************/ + +#ifndef _LDFILTBANK_H +#define _LDFILTBANK_H + +#include "common_fix.h" + + +int InvMdctTransformLowDelay_fdk ( + FIXP_DBL *mdctdata_m, + const int mdctdata_e, + INT_PCM *mdctOut, + FIXP_DBL *fs_buffer, + const int stride, + const int frameLength + ); + + +#endif diff --git a/libAACdec/src/overlapadd.h b/libAACdec/src/overlapadd.h new file mode 100644 index 00000000..1469be77 --- /dev/null +++ b/libAACdec/src/overlapadd.h @@ -0,0 +1,105 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: + +******************************************************************************/ + +#ifndef OVERLAPADD_H +#define OVERLAPADD_H + +#include "common_fix.h" + +#define OverlapBufferSize (1024*2) + +typedef FIXP_DBL SPECTRUM[1024]; +typedef FIXP_DBL * SPECTRAL_PTR; + +#define SPEC_LONG(ptr) (ptr) +#define SPEC(ptr,w,gl) ((ptr)+((w)*(gl))) + + +#endif /* #ifndef OVERLAPADD_H */ diff --git a/libAACdec/src/pulsedata.cpp b/libAACdec/src/pulsedata.cpp new file mode 100644 index 00000000..0f2f0ecf --- /dev/null +++ b/libAACdec/src/pulsedata.cpp @@ -0,0 +1,158 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: pulse data tool + +******************************************************************************/ + +#include "pulsedata.h" + + +#include "channelinfo.h" + + +INT CPulseData_Read( + HANDLE_FDK_BITSTREAM bs, + CPulseData *const PulseData, + const SHORT *sfb_startlines, + const void *pIcsInfo, + const SHORT frame_length + ) +{ + int i, k=0; + const UINT MaxSfBands = GetScaleFactorBandsTransmitted((CIcsInfo*)pIcsInfo); + + /* reset pulse data flag */ + PulseData->PulseDataPresent = 0; + + if ((PulseData->PulseDataPresent = (UCHAR) FDKreadBit(bs)) != 0) { + if (!IsLongBlock((CIcsInfo*)pIcsInfo)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + PulseData->NumberPulse = (UCHAR) FDKreadBits(bs,2); + PulseData->PulseStartBand = (UCHAR) FDKreadBits(bs,6); + + if (PulseData->PulseStartBand >= MaxSfBands) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + k = sfb_startlines[PulseData->PulseStartBand]; + + for (i=0; i<=PulseData->NumberPulse; i++) { + PulseData->PulseOffset[i] = (UCHAR) FDKreadBits(bs,5); + PulseData->PulseAmp[i] = (UCHAR) FDKreadBits(bs,4); + k += PulseData->PulseOffset[i]; + } + + if (k >= frame_length) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + + return 0; +} + +void CPulseData_Apply(CPulseData *PulseData, /*!< pointer to pulse data side info */ + const short *pScaleFactorBandOffsets, /*!< pointer to scalefactor band offsets */ + FIXP_DBL *coef) /*!< pointer to spectrum */ +{ + int i,k; + + if (PulseData->PulseDataPresent) + { + k = pScaleFactorBandOffsets[PulseData->PulseStartBand]; + + for (i=0; i<=PulseData->NumberPulse; i++) + { + k += PulseData->PulseOffset[i]; + if (coef [k] > (FIXP_DBL)0) coef[k] += (FIXP_DBL)(int)PulseData->PulseAmp[i]; + else coef[k] -= (FIXP_DBL)(int)PulseData->PulseAmp[i]; + } + } +} + diff --git a/libAACdec/src/pulsedata.h b/libAACdec/src/pulsedata.h new file mode 100644 index 00000000..fa97d99c --- /dev/null +++ b/libAACdec/src/pulsedata.h @@ -0,0 +1,145 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: pulse data tool + +******************************************************************************/ + +#ifndef PULSEDATA_H +#define PULSEDATA_H + + + +#include "common_fix.h" +#include "FDK_bitstream.h" + +#define N_MAX_LINES 4 + +typedef struct +{ + UCHAR PulseDataPresent; + UCHAR NumberPulse; + UCHAR PulseStartBand; + UCHAR PulseOffset[N_MAX_LINES]; + UCHAR PulseAmp[N_MAX_LINES]; +} CPulseData; + +/** + * \brief Read pulse data from bitstream + * + * The function reads the elements for pulse data from + * the bitstream. + * + * \param bs bit stream handle data source. + * \param PulseData pointer to a CPulseData were the decoded data is stored into. + * \param MaxSfBands max number of scale factor bands. + * \return 0 on success, != 0 on parse error. + */ +INT CPulseData_Read( + const HANDLE_FDK_BITSTREAM bs, + CPulseData *const PulseData, + const SHORT *sfb_startlines, + const void *pIcsInfo, + const SHORT frame_length + ); + +/** + * \brief Apply pulse data to spectral lines + * + * The function applies the pulse data to the + * specified spectral lines. + * + * \param PulseData pointer to the previously decoded pulse data. + * \param pScaleFactorBandOffsets scale factor band line offset table. + * \param coef pointer to the spectral data were pulse data should be applied to. + * \return none +*/ +void CPulseData_Apply(CPulseData *PulseData, + const short *pScaleFactorBandOffsets, + FIXP_DBL *coef); + + +#endif /* #ifndef PULSEDATA_H */ diff --git a/libAACdec/src/rvlc.cpp b/libAACdec/src/rvlc.cpp new file mode 100644 index 00000000..16f0bf51 --- /dev/null +++ b/libAACdec/src/rvlc.cpp @@ -0,0 +1,1215 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief RVLC Decoder + \author Robert Weidner +*/ + +#include "rvlc.h" + + +#include "block.h" + +#include "aac_rom.h" +#include "rvlcbit.h" +#include "rvlcconceal.h" +#include "aacdec_hcr.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcInit + + description: init RVLC by data from channelinfo, which was decoded previously and + set up pointers +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void rvlcInit (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + /* RVLC common initialization part 2 of 2 */ + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + int bnds; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0; + + pRvlc->numDecodedEscapeWordsEsc = 0; + pRvlc->numDecodedEscapeWordsFwd = 0; + pRvlc->numDecodedEscapeWordsBwd = 0; + + pRvlc->intensity_used = 0; + pRvlc->errorLogRvlc = 0; + + pRvlc->conceal_max = CONCEAL_MAX_INIT; + pRvlc->conceal_min = CONCEAL_MIN_INIT; + + pRvlc->conceal_max_esc = CONCEAL_MAX_INIT; + pRvlc->conceal_min_esc = CONCEAL_MIN_INIT; + + pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape; + pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds; + + /* init scf arrays (for savety (in case of there are only zero codebooks)) */ + for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) { + pScfFwd[bnds] = 0; + pScfBwd[bnds] = 0; + pScfEsc[bnds] = 0; + pScaleFactor[bnds] = 0; + } + + /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) */ + FDKsyncCache (bs); + + pRvlc->bitstreamIndexRvlFwd = FDKgetBitCnt(bs); /* first bit within RVL coded block as start address for forward decoding */ + pRvlc->bitstreamIndexRvlBwd = FDKgetBitCnt(bs) + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start address for backward decoding */ + + /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS data (if present) */ + FDKpushFor (bs, pRvlc->length_of_rvlc_sf); + + if ( pRvlc->sf_escapes_present != 0 ) { + + /* locate internal bitstream ptr at escapes (which is the second part) */ + FDKsyncCache (bs); + pRvlc->bitstreamIndexEsc = FDKgetBitCnt(bs); + + /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to make decoder continue */ + /* decoding of RVLC should work despite this second pushFor during initialization because */ + /* bitstream initialization is valid for both ESC2 data parts (RVL-coded values and ESC-coded values) */ + FDKpushFor (bs, pRvlc->length_of_rvlc_escapes); + } + +#if VERBOSE_RVLC_INIT + DebugOutputInit(pRvlc,pAacDecoderChannelInfo); +#endif +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcCheckIntensityCb + + description: Check if a intensity codebook is used in the current channel. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + output: - intensity_used: 0 no intensity codebook is used + 1 intensity codebook is used +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void rvlcCheckIntensityCb (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + int group, band, bnds; + + pRvlc->intensity_used = 0; + + for (group=0; group < pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + if ( (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB) || (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == INTENSITY_HCB2) ) { + pRvlc->intensity_used = 1; + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapeWord + + description: Decode a huffman coded RVLC Escape-word. This value is part of a DPCM coded + scalefactor. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a single RVLC-Escape value which had to be applied to a DPCM value (which + has a absolute value of 7) +-------------------------------------------------------------------------------------------- */ + +static +SCHAR rvlcDecodeEscapeWord (CErRvlcInfo *pRvlc, + HANDLE_FDK_BITSTREAM bs) +{ + int i; + SCHAR value; + UCHAR carryBit; + UINT treeNode; + UINT branchValue; + UINT branchNode; + + USHORT* pBitstreamIndexEsc; + const UINT* pEscTree; + + pEscTree = pRvlc->pHuffTreeRvlcEscape; + pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc); + treeNode = *pEscTree; /* init at starting node */ + + for (i=MAX_LEN_RVLC_ESCAPE_WORD-1; i >= 0; i--) { + carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */ + pBitstreamIndexEsc, + FWD); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */ + treeNode, + &branchValue, + &branchNode); + + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is completely decoded */ + value = (SCHAR) branchNode & CLR_BIT_10; + pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i); + + if (pRvlc->length_of_rvlc_escapes < 0) { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + value = -1; + } + + return value; + } + else { + treeNode = *(pEscTree + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + + return -1; /* should not be reached */ +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapes + + description: Decodes all huffman coded RVLC Escape Words. + Here a difference to the pseudo-code-implementation from standard can be + found. A while loop (and not two nested for loops) is used for two reasons: + + 1. The plain huffman encoded escapes are decoded before the RVL-coded + scalefactors. Therefore the escapes are present in the second step + when decoding the RVL-coded-scalefactor values in forward and + backward direction. + + When the RVL-coded scalefactors are decoded and there a escape is + needed, then it is just taken out of the array in ascending order. + + 2. It's faster. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - 0 ok the decoded escapes seem to be valid + - 1 error there was a error detected during decoding escapes + --> all escapes are invalid +-------------------------------------------------------------------------------------------- */ + +static +void rvlcDecodeEscapes (CErRvlcInfo *pRvlc, + SHORT *pEsc, + HANDLE_FDK_BITSTREAM bs) +{ + SCHAR escWord; + SCHAR escCnt=0; + SHORT* pEscBitCntSum; + + pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes); + + /* Decode all RVLC-Escape words with a plain Huffman-Decoder */ + while ( *pEscBitCntSum > 0 ) { + escWord = rvlcDecodeEscapeWord(pRvlc, bs); + + if (escWord >= 0) { + + pEsc[escCnt] = escWord; + escCnt++; + } + else { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + pRvlc->numDecodedEscapeWordsEsc = escCnt; + + return; + } + } /* all RVLC escapes decoded */ + + pRvlc->numDecodedEscapeWordsEsc = escCnt; +} + + +/*--------------------------------------------------------------------------------------------- + function: decodeRVLCodeword + + description: Decodes a RVL-coded dpcm-word (-part). +----------------------------------------------------------------------------------------------- + input: - FDK bitstream handle + - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a dpcm value which is within range [0,1,..,14] in case of no errors. + The offset of 7 must be subtracted to get a valid dpcm scalefactor value. + In case of errors a forbidden codeword is detected --> returning -1 +-------------------------------------------------------------------------------------------- */ + +SCHAR decodeRVLCodeword (HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc) +{ + int i; + SCHAR value; + UCHAR carryBit; + UINT branchValue; + UINT branchNode; + + const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds; + UCHAR direction = pRvlc->direction; + USHORT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL; + UINT treeNode = *pRvlCodeTree; + + for (i=MAX_LEN_RVLC_CODE_WORD-1; i >= 0; i--) { + carryBit = rvlcReadBitFromBitstream(bs, /* get next bit */ + pBitstrIndxRvl, + direction); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in huffman decoding tree */ + treeNode, + &branchValue, + &branchNode); + + if ((branchNode & TEST_BIT_10) == TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-codeword is completely decoded */ + value = (SCHAR) (branchNode & CLR_BIT_10); + *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i); + + /* check available bits for decoding */ + if (*pRvlc->pRvlBitCnt_RVL < 0) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; } + else { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; } + value = -1; /* signalize an error in return value, because too many bits was decoded */ + } + + /* check max value of dpcm value */ + if (value > MAX_ALLOWED_DPCM_INDEX) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD; + } + else { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD; + } + value = -1; /* signalize an error in return value, because a forbidden cw was detected*/ + } + + return value; /* return a dpcm value with offset +7 or an error status */ + } + else { + treeNode = *(pRvlCodeTree + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + return -1; +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeForward + + description: Decode RVL-coded codewords in forward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void rvlcDecodeForward (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + int band = 0; + int group = 0; + int bnds = 0; + + SHORT dpcm; + + SHORT factor = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + SHORT position = - SF_OFFSET; + SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256; + + SHORT* pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT* pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR* pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd); + + *pEscFwdCnt = 0; + pRvlc->direction = FWD; + pRvlc->noise_used = 0; + pRvlc->sf_used = 0; + pRvlc->lastScf = 0; + pRvlc->lastNrg = 0; + pRvlc->lastIs = 0; + + rvlcCheckIntensityCb(pRvlc,pAacDecoderChannelInfo); + + /* main loop fwd long */ + for (group=0; group < pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + + case ZERO_HCB : + pScfFwd[bnds] = 0; + break; + + case INTENSITY_HCB2 : + case INTENSITY_HCB : + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } + else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + position += dpcm; + pScfFwd[bnds] = position; + pRvlc->lastIs = position; + break; + + case NOISE_HCB : + if (pRvlc->noise_used == 0) { + pRvlc->noise_used = 1; + pRvlc->first_noise_band = bnds; + noisenrg += pRvlc->dpcm_noise_nrg; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } + else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } + else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + noisenrg += dpcm; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } + pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1; + break ; + + default : + pRvlc->sf_used = 1; + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; } + else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + factor += dpcm; + pScfFwd[bnds] = factor; + pRvlc->lastScf = factor; + break; + } + } + } + + /* postfetch fwd long */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if ( dpcm < 0 ) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } + else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeBackward + + description: Decode RVL-coded codewords in backward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void rvlcDecodeBackward (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + SHORT band, group, dpcm, offset; + SHORT bnds = pRvlc->maxSfbTransmitted-1; + + SHORT factor = pRvlc->rev_global_gain - SF_OFFSET; + SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET; + SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256; + + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc); + UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd); + + *pEscBwdCnt = 0; + pRvlc->direction = BWD; + pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */ + pRvlc->firstScf = 0; + pRvlc->firstNrg = 0; + pRvlc->firstIs = 0; + + /* prefetch long BWD */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if ( dpcm < 0 ) { + pRvlc->dpcm_is_last_position = 0; + pRvlc->conceal_min = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_min = bnds; + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } + else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } + + /* main loop long BWD */ + for (group=pRvlc->numWindowGroups-1; group >= 0; group--) { + for (band=pRvlc->maxSfbTransmitted-1; band >= 0; band--) { + bnds = 16*group+band; + if ((band == 0) && (pRvlc->numWindowGroups != 1)) + offset = 16 - pRvlc->maxSfbTransmitted + 1; + else + offset = 1; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + + case ZERO_HCB : + pScfBwd[bnds] = 0; + break; + + case INTENSITY_HCB2 : + case INTENSITY_HCB : + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } + else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = FDKmax(0,bnds-offset); + } + } + } + pScfBwd[bnds] = position; + position -= dpcm; + pRvlc->firstIs = position; + break; + + case NOISE_HCB : + if ( bnds == pRvlc->first_noise_band ) { + pScfBwd[bnds] = pRvlc->dpcm_noise_nrg + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256; + pRvlc->firstNrg = pScfBwd[bnds]; + } + else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } + else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = FDKmax(0,bnds-offset); + } + } + } + pScfBwd[bnds] = noisenrg; + noisenrg -= dpcm; + pRvlc->firstNrg = noisenrg; + } + break ; + + default : + dpcm = decodeRVLCodeword(bs, pRvlc); + if ( dpcm < 0 ) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = FDKmax(0,bnds-offset); + return; + } + else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } + else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = FDKmax(0,bnds-offset); + } + } + } + pScfBwd[bnds] = factor; + factor -= dpcm; + pRvlc->firstScf = factor; + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + function: rvlcFinalErrorDetection + + description: Call RVLC concealment if error was detected in decoding process +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void rvlcFinalErrorDetection (CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + UCHAR ErrorStatusComplete = 0; + UCHAR ErrorStatusLengthFwd = 0; + UCHAR ErrorStatusLengthBwd = 0; + UCHAR ErrorStatusLengthEscapes = 0; + UCHAR ErrorStatusFirstScf = 0; + UCHAR ErrorStatusLastScf = 0; + UCHAR ErrorStatusFirstNrg = 0; + UCHAR ErrorStatusLastNrg = 0; + UCHAR ErrorStatusFirstIs = 0; + UCHAR ErrorStatusLastIs = 0; + UCHAR ErrorStatusForbiddenCwFwd = 0; + UCHAR ErrorStatusForbiddenCwBwd = 0; + UCHAR ErrorStatusNumEscapesFwd = 0; + UCHAR ErrorStatusNumEscapesBwd = 0; + UCHAR ConcealStatus = 1; + UCHAR currentBlockType; /* short: 0, not short: 1*/ + +#if VERBOSE_RVLC_OUTPUT + CHAR Strategy[60]="No"; + SHORT conceal_max; + SHORT conceal_min; +#endif + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1; + + /* invalid escape words, bit counter unequal zero, forbidden codeword detected */ + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD) + ErrorStatusForbiddenCwFwd = 1; + + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD) + ErrorStatusForbiddenCwBwd = 1; + + /* bit counter forward unequal zero */ + if (pRvlc->length_of_rvlc_sf_fwd) + ErrorStatusLengthFwd = 1; + + /* bit counter backward unequal zero */ + if (pRvlc->length_of_rvlc_sf_bwd) + ErrorStatusLengthBwd = 1; + + /* bit counter escape sequences unequal zero */ + if (pRvlc->sf_escapes_present) + if (pRvlc->length_of_rvlc_escapes) + ErrorStatusLengthEscapes = 1; + + if (pRvlc->sf_used) { + /* first decoded scf does not match to global gain in backward direction */ + if (pRvlc->firstScf != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET) ) + ErrorStatusFirstScf = 1; + + /* last decoded scf does not match to rev global gain in forward direction */ + if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET) ) + ErrorStatusLastScf = 1; + } + + if (pRvlc->noise_used) { + /* first decoded nrg does not match to dpcm_noise_nrg in backward direction */ + if (pRvlc->firstNrg != (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + pRvlc->dpcm_noise_nrg - SF_OFFSET -90 - 256) ) + ErrorStatusFirstNrg = 1; + + /* last decoded nrg does not match to dpcm_noise_last_position in forward direction */ + if (pRvlc->lastNrg != (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256) ) + ErrorStatusLastNrg = 1; + } + + if (pRvlc->intensity_used) { + /* first decoded is position does not match in backward direction */ + if (pRvlc->firstIs != (-SF_OFFSET) ) + ErrorStatusFirstIs = 1; + + /* last decoded is position does not match in forward direction */ + if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET) ) + ErrorStatusLastIs = 1; + } + + /* decoded escapes and used escapes in forward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_max == CONCEAL_MAX_INIT)) { + ErrorStatusNumEscapesFwd = 1; + } + + /* decoded escapes and used escapes in backward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + ErrorStatusNumEscapesBwd = 1; + } + +#if VERBOSE_RVLC_OUTPUT + conceal_max = pRvlc->conceal_max; + conceal_min = pRvlc->conceal_min; +#endif + + if ( ErrorStatusLengthEscapes + || ( + ( (pRvlc->conceal_max == CONCEAL_MAX_INIT) + && (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) + && (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs) ) + + && + + ( (pRvlc->conceal_min == CONCEAL_MIN_INIT) + && (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) + && (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs) ) + ) + || ( (pRvlc->conceal_max == CONCEAL_MAX_INIT) + && ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15) + ) + || ( (pRvlc->conceal_min == CONCEAL_MIN_INIT) + && ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - pRvlc->firstScf) < -15) + ) + ) { + if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + pRvlc->conceal_max = 0; + pRvlc->conceal_min = FDKmax(0, (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1); + } + else { + pRvlc->conceal_max = FDKmin(pRvlc->conceal_max,pRvlc->conceal_max_esc); + pRvlc->conceal_min = FDKmax(pRvlc->conceal_min,pRvlc->conceal_min_esc); + } + } + + ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || ErrorStatusLastNrg || ErrorStatusFirstNrg + || ErrorStatusLastIs || ErrorStatusFirstIs || ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd + || ErrorStatusLengthFwd || ErrorStatusLengthBwd || ErrorStatusLengthEscapes || ErrorStatusNumEscapesFwd + || ErrorStatusNumEscapesBwd; + + currentBlockType = (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) ? 0 : 1; + + + if (!ErrorStatusComplete) { + int band; + int group; + int bnds; + int lastSfbIndex; + + lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64; + + for (group=0; group < pRvlc->numWindowGroups; group++) { + for (band=0; bandmaxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + } + + for (group=0; group < pRvlc->numWindowGroups; group++) + { + for (band=0; bandmaxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]; + } + for (; band = 0 && bnds < RVLC_MAX_SFB); + pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds] = ZERO_HCB; + } + } + } + else { + int band; + int group; + + /* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding + of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just + after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward decoding, backward decoding + and previous frame. */ + if ( ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && (pRvlc->conceal_min <= pRvlc->conceal_max) + && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK + && pRvlc->sf_concealment && ConcealStatus ) + { + BidirectionalEstimation_UseScfOfPrevFrameAsReference (pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + ConcealStatus=0; +#if VERBOSE_RVLC_OUTPUT + FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseScfOfPrevFrameAsReference)"); +#endif + } + + /* A single bit error was detected in decoding of dpcm values. It also could be an error with more bits in decoding + of escapes and dpcm values whereby an illegal codeword followed not directly after the corrupted bits but just + after decoding some more (wrong) scalefactors. Use the smaller scalefactor from forward and backward decoding. */ + if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || (pRvlc->conceal_max != CONCEAL_MAX_INIT)) + && !(pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType)) + && ConcealStatus ) + { + BidirectionalEstimation_UseLowerScfOfCurrentFrame (pAacDecoderChannelInfo); + ConcealStatus=0; +#if VERBOSE_RVLC_OUTPUT + FDKstrcpy(Strategy,"Yes (BidirectionalEstimation_UseLowerScfOfCurrentFrame)"); +#endif + } + + /* No errors were detected in decoding of escapes and dpcm values however the first and last value + of a group (is,nrg,sf) is incorrect */ + if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && ((ErrorStatusLastScf && ErrorStatusFirstScf) + || (ErrorStatusLastNrg && ErrorStatusFirstNrg) || (ErrorStatusLastIs && ErrorStatusFirstIs)) + && !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || ErrorStatusLengthEscapes ) && ConcealStatus) + { + StatisticalEstimation (pAacDecoderChannelInfo); + ConcealStatus=0; +#if VERBOSE_RVLC_OUTPUT + FDKstrcpy(Strategy,"Yes (StatisticalEstimation)"); +#endif + } + + /* A error with more bits in decoding of escapes and dpcm values was detected. Use the smaller scalefactor from forward + decoding, backward decoding and previous frame. */ + if ( (pRvlc->conceal_min <= pRvlc->conceal_max) && pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousScaleFactorOK && pRvlc->sf_concealment + && (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == currentBlockType) && ConcealStatus ) + { + PredictiveInterpolation(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + ConcealStatus=0; +#if VERBOSE_RVLC_OUTPUT + FDKstrcpy(Strategy,"Yes (PredictiveInterpolation)"); +#endif + } + + /* Call frame concealment, because no better strategy was found. Setting the scalefactors to zero is done for debugging + purposes */ + if (ConcealStatus) { + for (group=0; group < pRvlc->numWindowGroups; group++) { + for (band=0; bandmaxSfbTransmitted; band++) { + pAacDecoderChannelInfo->pDynData->aScaleFactor[16*group+band] = 0; + } + } + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; +#if VERBOSE_RVLC_OUTPUT + FDKstrcpy(Strategy,"Yes (FrameConcealment)"); +#endif + } + } + +#if VERBOSE_RVLC_OUTPUT + DebugOutputDistortedBitstreams(pRvlc,pAacDecoderChannelInfo,ErrorStatusLengthFwd,ErrorStatusLengthBwd, + ErrorStatusLengthEscapes,ErrorStatusFirstScf,ErrorStatusLastScf, + ErrorStatusFirstNrg,ErrorStatusLastNrg,ErrorStatusFirstIs,ErrorStatusLastIs, + ErrorStatusForbiddenCwFwd,ErrorStatusForbiddenCwBwd,ErrorStatusNumEscapesFwd, + ErrorStatusNumEscapesBwd,conceal_max,conceal_min,Strategy); +#endif +} + + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Read + + description: Read RVLC ESC1 data (side info) from bitstream. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void CRvlc_Read ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + + int group,band; + + /* RVLC long specific initialization Init part 1 of 2 */ + pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + pRvlc->maxSfbTransmitted = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + pRvlc->noise_used = 0; /* noise detection */ + pRvlc->dpcm_noise_nrg = 0; /* only for debugging */ + pRvlc->dpcm_noise_last_position = 0; /* only for debugging */ + pRvlc->length_of_rvlc_escapes = -1; /* default value is used for error detection and concealment */ + + /* read only error sensitivity class 1 data (ESC 1 - data) */ + pRvlc->sf_concealment = FDKreadBits(bs,1); /* #1 */ + pRvlc->rev_global_gain = FDKreadBits(bs,8); /* #2 */ + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs,11); /* #3 */ + } + else { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs,9); /* #3 */ + } + + /* check if noise codebook is used */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + if (pAacDecoderChannelInfo->pDynData->aCodeBook[16*group+band] == NOISE_HCB) { + pRvlc->noise_used = 1; + break; + } + } + } + + if (pRvlc->noise_used) + pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */ + + pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */ + + if ( pRvlc->sf_escapes_present) { + pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */ + } + + if (pRvlc->noise_used) { + pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */ + pRvlc->length_of_rvlc_sf -= 9; + } + + pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf; + pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf; +} + + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Decode + + description: Decode rvlc data + The function reads both the escape sequences and the scalefactors in forward + and backward direction. If an error occured during decoding process which can + not be concealed with the rvlc concealment frame concealment will be initiated. + Then the element "rvlcCurrentScaleFactorOK" in the decoder channel info is set + to 0 otherwise it is set to 1. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer to persistent channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: ErrorStatus = AAC_DEC_OK +-------------------------------------------------------------------------------------------- */ + +void CRvlc_Decode ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs + ) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + INT bitCntOffst; + UINT saveBitCnt; + + rvlcInit(pRvlc,pAacDecoderChannelInfo,bs); + + /* save bitstream position */ + saveBitCnt = FDKgetBitCnt(bs); + +#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_SF + GenerateSingleBitError(pRvlc, + &(pRvlc->bitstreamIndexRvlFwd), + pRvlc->length_of_rvlc_sf, + 0); +#endif + +#if RVLC_ADVANCED_BITSTREAM_ERROR_GENERATOR_ESC + if (pRvlc->sf_escapes_present) + GenerateSingleBitError(pRvlc, + &(pRvlc->bitstreamIndexEsc), + pRvlc->length_of_rvlc_escapes, + 1); +#endif + + if ( pRvlc->sf_escapes_present) + rvlcDecodeEscapes(pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs); + + rvlcDecodeForward(pRvlc,pAacDecoderChannelInfo, bs); + rvlcDecodeBackward(pRvlc,pAacDecoderChannelInfo, bs); + rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = pRvlc->intensity_used; + pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used; + + /* restore bitstream position */ + bitCntOffst = saveBitCnt - FDKgetBitCnt(bs); + if( bitCntOffst ) { + FDKpushBiDirectional(bs, bitCntOffst); + } +} + +void CRvlc_ElementCheck ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, + const INT elChannels + ) +{ + int ch; + + /* Required for MPS residuals. */ + if (pAacDecoderStaticChannelInfo == NULL) { + return; + } + + /* RVLC specific sanity checks */ + if ( (flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */ + if ( ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) || + (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) ) + && pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent ) { + pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + + if ( (pAacDecoderChannelInfo[0]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) + && (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1) + && (pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcIntensityUsed == 1) ){ + pAacDecoderChannelInfo[1]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + } + + for (ch = 0; ch < elChannels; ch ++) + { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == EightShortSequence) ? 0 : 1; + if (flags & AC_ER_RVLC) { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK; + } + else { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousScaleFactorOK = 0; + } + } +} + + diff --git a/libAACdec/src/rvlc.h b/libAACdec/src/rvlc.h new file mode 100644 index 00000000..18d5fa39 --- /dev/null +++ b/libAACdec/src/rvlc.h @@ -0,0 +1,134 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Defines structures and prototypes for RVLC + \author Robert Weidner +*/ + +#ifndef RVLC_H +#define RVLC_H + + + +#include "aacdecoder.h" +#include "channel.h" +#include "rvlc_info.h" + +/* ------------------------------------------------------------------- */ +/* errorLogRvlc: A word of 32 bits used for logging possible errors */ +/* within RVLC in case of distorted bitstreams. */ +/* ------------------------------------------------------------------- */ +#define RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID 0x80000000 /* ESC-Dec During RVLC-Escape-decoding there have been more bits decoded as there are available */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD 0x40000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD 0x20000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD 0x08000000 /* RVL-Dec forbidden codeword detected fwd (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD 0x04000000 /* RVL-Dec forbidden codeword detected bwd (long+shrt) */ + + + +void CRvlc_Read (CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +void CRvlc_Decode (CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +/** + * \brief performe sanity checks to the channel data corresponding to one channel element. + * \param pAacDecoderChannelInfo + * \param pAacDecoderStaticChannelInfo + * \param elChannels amount of channels of the channel element. + */ +void CRvlc_ElementCheck ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, + const INT elChannels + ); + + + + +#endif /* RVLC_H */ diff --git a/libAACdec/src/rvlc_info.h b/libAACdec/src/rvlc_info.h new file mode 100644 index 00000000..63934af2 --- /dev/null +++ b/libAACdec/src/rvlc_info.h @@ -0,0 +1,176 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Defines structures for RVLC + \author Robert Weidner +*/ +#ifndef RVLC_INFO_H +#define RVLC_INFO_H + + + +#define FWD 0 /* bitstream decoding direction forward (RVL coded part) */ +#define BWD 1 /* bitstream decoding direction backward (RVL coded part) */ + +#define MAX_RVL 7 /* positive RVLC escape */ +#define MIN_RVL -7 /* negative RVLC escape */ +#define MAX_ALLOWED_DPCM_INDEX 14 /* the maximum allowed index of a decoded dpcm value (offset 'TABLE_OFFSET' incl --> must be subtracted) */ +#define TABLE_OFFSET 7 /* dpcm offset of valid output values of rvl table decoding, the rvl table ouly returns positive values, therefore the offset */ +#define MAX_LEN_RVLC_CODE_WORD 9 /* max length of a RVL codeword in bits */ +#define MAX_LEN_RVLC_ESCAPE_WORD 20 /* max length of huffman coded RVLC escape word in bits */ + +#define DPCM_NOISE_NRG_BITS 9 +#define SF_OFFSET 100 /* offset for correcting scf value */ + +#define CONCEAL_MAX_INIT 1311 /* arbitrary value */ +#define CONCEAL_MIN_INIT -1311 /* arbitrary value */ + +#define RVLC_MAX_SFB ((8) * (16)) + +/* sideinfo of RVLC */ +typedef struct +{ + /* ------- ESC 1 Data: --------- */ /* order of RVLC-bitstream components in bitstream (RVLC-initialization), every component appears only once in bitstream */ + INT sf_concealment; /* 1 */ + INT rev_global_gain; /* 2 */ + SHORT length_of_rvlc_sf; /* 3 */ /* original value, gets modified (subtract 9) in case of noise (PNS); is kept for later use */ + INT dpcm_noise_nrg; /* 4 optional */ + INT sf_escapes_present; /* 5 */ + SHORT length_of_rvlc_escapes; /* 6 optional */ + INT dpcm_noise_last_position; /* 7 optional */ + + INT dpcm_is_last_position; + + SHORT length_of_rvlc_sf_fwd; /* length_of_rvlc_sf used for forward decoding */ + SHORT length_of_rvlc_sf_bwd; /* length_of_rvlc_sf used for backward decoding */ + + /* for RVL-Codeword decoder to distinguish between fwd and bwd decoding */ + SHORT *pRvlBitCnt_RVL; + USHORT *pBitstrIndxRvl_RVL; + + UCHAR numWindowGroups; + UCHAR maxSfbTransmitted; + UCHAR first_noise_group; + UCHAR first_noise_band; + UCHAR direction; + + /* bitstream indices */ + USHORT bitstreamIndexRvlFwd; /* base address of RVL-coded-scalefactor data (ESC 2) for forward decoding */ + USHORT bitstreamIndexRvlBwd; /* base address of RVL-coded-scalefactor data (ESC 2) for backward decoding */ + USHORT bitstreamIndexEsc; /* base address where RVLC-escapes start (ESC 2) */ + + /* decoding trees */ + const UINT *pHuffTreeRvlCodewds; + const UINT *pHuffTreeRvlcEscape; + + /* escape counters */ + UCHAR numDecodedEscapeWordsFwd; /* when decoding RVL-codes forward */ + UCHAR numDecodedEscapeWordsBwd; /* when decoding RVL-codes backward */ + UCHAR numDecodedEscapeWordsEsc; /* when decoding the escape-Words */ + + SCHAR noise_used; + SCHAR intensity_used; + SCHAR sf_used; + + SHORT firstScf; + SHORT lastScf; + SHORT firstNrg; + SHORT lastNrg; + SHORT firstIs; + SHORT lastIs; + + /* ------ RVLC error detection ------ */ + UINT errorLogRvlc; /* store RVLC errors */ + SHORT conceal_min; /* is set at backward decoding */ + SHORT conceal_max; /* is set at forward decoding */ + SHORT conceal_min_esc; /* is set at backward decoding */ + SHORT conceal_max_esc; /* is set at forward decoding */ +} CErRvlcInfo; + +typedef CErRvlcInfo RVLC_INFO; /* temp */ + + + +#endif /* RVLC_INFO_H */ diff --git a/libAACdec/src/rvlcbit.cpp b/libAACdec/src/rvlcbit.cpp new file mode 100644 index 00000000..6efbb935 --- /dev/null +++ b/libAACdec/src/rvlcbit.cpp @@ -0,0 +1,131 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief RVLC bitstream reading + \author Robert Weidner +*/ + +#include "rvlcbit.h" + + +/*--------------------------------------------------------------------------------------------- + function: rvlcReadBitFromBitstream + + description: This function returns a bit from the bitstream according to read direction. + It is called very often, therefore it makes sense to inline it (runtime). +----------------------------------------------------------------------------------------------- + input: - bitstream + - pPosition + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- */ + +UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs, + USHORT *pPosition, + UCHAR readDirection) +{ + UINT bit; + INT readBitOffset = *pPosition-FDKgetBitCnt(bs); + + if( readBitOffset ) { + FDKpushBiDirectional(bs, readBitOffset); + } + + if (readDirection == FWD) { + bit = FDKreadBits(bs, 1); + + *pPosition += 1; + } else { + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pPosition -= 1; + } + + return (bit); +} + diff --git a/libAACdec/src/rvlcbit.h b/libAACdec/src/rvlcbit.h new file mode 100644 index 00000000..02fba88b --- /dev/null +++ b/libAACdec/src/rvlcbit.h @@ -0,0 +1,103 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder *************************** + + Author(s): Robert Weidner (DSP Solutions) + Description: RVLC Decoder: Bitstream reading + +*******************************************************************************/ + +#ifndef RVLCBIT_H +#define RVLCBIT_H + + + +#include "rvlc.h" + +UCHAR rvlcReadBitFromBitstream (HANDLE_FDK_BITSTREAM bs, + USHORT *pPosition, + UCHAR readDirection); + + +#endif /* RVLCBIT_H */ diff --git a/libAACdec/src/rvlcconceal.cpp b/libAACdec/src/rvlcconceal.cpp new file mode 100644 index 00000000..cf33dd59 --- /dev/null +++ b/libAACdec/src/rvlcconceal.cpp @@ -0,0 +1,697 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#include "rvlcconceal.h" + + +#include "block.h" +#include "rvlc.h" + +/*--------------------------------------------------------------------------------------------- + function: calcRefValFwd + + description: The function determines the scalefactor which is closed to the scalefactorband + conceal_min. The same is done for intensity data and noise energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void calcRefValFwd (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsFwd, + int *refNrgFwd, + int *refScfFwd) +{ + int band,bnds,group,startBand; + int idIs,idNrg,idScf; + int conceal_min,conceal_group_min; + int MaximumScaleFactorBands; + + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + + /* calculate first reference value for approach in forward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsFwd = - SF_OFFSET; + *refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - 90 - 256; + *refScfFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + + startBand = conceal_min-1; + for (group=conceal_group_min; group >= 0; group--) { + for (band=startBand; band >= 0; band--) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idIs=0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idNrg=0; /* reference value has been set */ + } + break ; + default: + if (idScf) { + *refScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idScf=0; /* reference value has been set */ + } + break; + } + } + startBand = pRvlc->maxSfbTransmitted-1; + } + +} + +/*--------------------------------------------------------------------------------------------- + function: calcRefValBwd + + description: The function determines the scalefactor which is closed to the scalefactorband + conceal_max. The same is done for intensity data and noise energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +static +void calcRefValBwd (CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsBwd, + int *refNrgBwd, + int *refScfBwd) +{ + int band,bnds,group,startBand; + int idIs,idNrg,idScf; + int conceal_max,conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + /* calculate first reference value for approach in backward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET; + *refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg; + *refScfBwd = pRvlc->rev_global_gain - SF_OFFSET; + + startBand=conceal_max+1; + + /* if needed, re-set reference values */ + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idIs=0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idNrg=0; /* reference value has been set */ + } + break ; + default: + if (idScf) { + *refScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idScf=0; /* reference value has been set */ + } + break; + } + } + startBand=0; + } + +} + + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseLowerScfOfCurrentFrame + + description: This approach by means of bidirectional estimation is generally performed when + a single bit error has been detected, the bit error can be isolated between + 'conceal_min' and 'conceal_max' and the 'sf_concealment' flag is not set. The + sets of scalefactors decoded in forward and backward direction are compared + with each other. The smaller scalefactor will be considered as the correct one + respectively. The reconstruction of the scalefactors with this approach archieve + good results in audio quality. The strategy must be applied to scalefactors, + intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between conceal_min and + conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame (CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,startBand,endBand,group; + int conceal_min,conceal_max; + int conceal_group_min,conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) { + MaximumScaleFactorBands = 16; + } + else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a + appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly + not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) + pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + if (pRvlc->conceal_min == pRvlc->conceal_max) { + + int refIsFwd,refNrgFwd,refScfFwd; + int refIsBwd,refNrgBwd,refScfBwd; + + bnds = pRvlc->conceal_min; + calcRefValFwd(pRvlc,pAacDecoderChannelInfo,&refIsFwd,&refNrgFwd,&refScfFwd); + calcRefValBwd(pRvlc,pAacDecoderChannelInfo,&refIsBwd,&refNrgBwd,&refScfBwd); + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (refIsFwd < refIsBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd; + break; + case NOISE_HCB: + if (refNrgFwd < refNrgBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd; + break; + default: + if (refScfFwd < refScfBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd; + break; + } + } + else { + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted-1; + + for (group=conceal_group_min; group <= conceal_group_max; group++) { + for (band=startBand; band <= endBand; band++) { + bnds = 16*group+band; + if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + if ((group+1) == conceal_group_max) + endBand = conceal_max; + } + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group=0; group <= conceal_group_min; group++) { + for (band=0; band < endBand; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group+1) == conceal_group_min) + endBand = conceal_min; + } + + startBand = conceal_max+1; + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseScfOfPrevFrameAsReference + + description: This approach by means of bidirectional estimation is generally performed when + a single bit error has been detected, the bit error can be isolated between + 'conceal_min' and 'conceal_max', the 'sf_concealment' flag is set and the + previous frame has the same block type as the current frame. The scalefactor + decoded in forward and backward direction and the scalefactor of the previous + frame are compared with each other. The smaller scalefactor will be considered + as the correct one. At this the codebook of the previous and current frame must + be of the same set (scf, nrg, is) in each scalefactorband. Otherwise the + scalefactor of the previous frame is not considered in the minimum calculation. + The reconstruction of the scalefactors with this approach archieve good results + in audio quality. The strategy must be applied to scalefactors, intensity data + and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between conceal_min and + conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,startBand,endBand,group; + int conceal_min,conceal_max; + int conceal_group_min,conceal_group_max; + int MaximumScaleFactorBands; + int commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) { + MaximumScaleFactorBands = 16; + } + else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the corresponding border for concealment to a + appropriate scalefactor band. The border is set to first or last sfb respectively, because the error will possibly + not follow directly after the corrupt bit but just after decoding some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) + pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = (pRvlc->numWindowGroups-1)*16+pRvlc->maxSfbTransmitted-1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_max] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[pRvlc->conceal_min] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted-1; + + for (group=conceal_group_min; group <= conceal_group_max; group++) { + for (band=startBand; band <= endBand; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + + case NOISE_HCB: + if ( pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + + default: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) + { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + } + break; + } + } + startBand = 0; + if ((group+1) == conceal_group_max) + endBand = conceal_max; + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group=0; group <= conceal_group_min; group++) { + for (band=0; band < endBand; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group+1) == conceal_group_min) + endBand = conceal_min; + } + + startBand = conceal_max+1; + for (group=conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band=startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: StatisticalEstimation + + description: This approach by means of statistical estimation is generally performed when + both the start value and the end value are different and no further errors have + been detected. Considering the forward and backward decoded scalefactors, the + set with the lower scalefactors in sum will be considered as the correct one. + The scalefactors are differentially encoded. Normally it would reach to compare + one pair of the forward and backward decoded scalefactors to specify the lower + set. But having detected no further errors does not necessarily mean the absence + of errors. Therefore all scalefactors decoded in forward and backward direction + are summed up seperately. The set with the lower sum will be used. The strategy + must be applied to scalefactors, intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,group; + int sumIsFwd,sumIsBwd; /* sum of intensity data forward/backward */ + int sumNrgFwd,sumNrgBwd; /* sum of noise energy data forward/backward */ + int sumScfFwd,sumScfBwd; /* sum of scalefactor data forward/backward */ + int useIsFwd,useNrgFwd,useScfFwd; /* the flags signals the elements which are used for the final result */ + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0; + useIsFwd = useNrgFwd = useScfFwd = 0; + + /* calculate sum of each group (scf,nrg,is) of forward and backward direction */ + for (group=0; groupnumWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + sumIsFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumIsBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + sumNrgFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumNrgBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break ; + + default: + sumScfFwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumScfBwd += pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } + + /* find for each group (scf,nrg,is) the correct direction */ + if ( sumIsFwd < sumIsBwd ) + useIsFwd = 1; + + if ( sumNrgFwd < sumNrgBwd ) + useNrgFwd = 1; + + if ( sumScfFwd < sumScfBwd ) + useScfFwd = 1; + + /* conceal each group (scf,nrg,is) */ + for (group=0; groupnumWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (useIsFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + if (useNrgFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break ; + + default: + if (useScfFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } +} + + +/*--------------------------------------------------------------------------------------------- + description: Approach by means of predictive interpolation + This approach by means of predictive estimation is generally performed when + the error cannot be isolated between 'conceal_min' and 'conceal_max', the + 'sf_concealment' flag is set and the previous frame has the same block type + as the current frame. Check for each scalefactorband if the same type of data + (scalefactor, internsity data, noise energies) is transmitted. If so use the + scalefactor (intensity data, noise energy) in the current frame. Otherwise set + the scalefactor (intensity data, noise energy) for this scalefactorband to zero. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- */ + +void PredictiveInterpolation ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ) +{ + CErRvlcInfo *pRvlc = &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band,bnds,group; + int MaximumScaleFactorBands; + int commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == EightShortSequence) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + for (group=0; groupnumWindowGroups; group++) { + for (band=0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16*group+band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB) || (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + case NOISE_HCB: + if ( pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]==NOISE_HCB ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + default: + if ( (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=ZERO_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=NOISE_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB) + && (pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousCodebook[bnds]!=INTENSITY_HCB2) ) { + commonMin = FDKmin(pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds],pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = FDKmin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo.aRvlcPreviousScaleFactor[bnds]); + } + else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + } + break; + } + } + } +} + diff --git a/libAACdec/src/rvlcconceal.h b/libAACdec/src/rvlcconceal.h new file mode 100644 index 00000000..750cbcd0 --- /dev/null +++ b/libAACdec/src/rvlcconceal.h @@ -0,0 +1,112 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#ifndef RVLCCONCEAL_H +#define RVLCCONCEAL_H + + + +#include "rvlc.h" + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ); + +void StatisticalEstimation (CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void PredictiveInterpolation ( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo + ); + + +#endif /* RVLCCONCEAL_H */ diff --git a/libAACdec/src/stereo.cpp b/libAACdec/src/stereo.cpp new file mode 100644 index 00000000..4f282446 --- /dev/null +++ b/libAACdec/src/stereo.cpp @@ -0,0 +1,297 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: joint stereo processing + +******************************************************************************/ + +#include "stereo.h" + + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" + +enum +{ + L = 0, + R = 1 +}; + + +int CJointStereo_Read( + HANDLE_FDK_BITSTREAM bs, + CJointStereoData *pJointStereoData, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const UINT flags + ) +{ + int group,band; + + pJointStereoData->MsMaskPresent = (UCHAR) FDKreadBits(bs,2); + + FDKmemclear(pJointStereoData->MsUsed, scaleFactorBandsTransmitted*sizeof(UCHAR)); + + switch (pJointStereoData->MsMaskPresent) + { + case 0 : /* no M/S */ + /* all flags are already cleared */ + break ; + + case 1 : /* read ms_used */ + + for (group=0; groupMsUsed[band] |= (FDKreadBits(bs,1) << group); + } + } + break ; + + case 2 : /* full spectrum M/S */ + + for (band=0; bandMsUsed[band] = 255 ; /* set all flags to 1 */ + } + break ; + } + + return 0; +} + +void CJointStereo_ApplyMS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const SHORT *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR + ) +{ + CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + int window, group, scaleFactorBandsTransmitted; + + FDK_ASSERT(scaleFactorBandsTransmittedL == scaleFactorBandsTransmittedR); + scaleFactorBandsTransmitted = scaleFactorBandsTransmittedL; + for (window = 0, group = 0; group < windowGroups; group++) + { + UCHAR groupMask = 1 << group; + + for (int groupwin=0; groupwinpDynData->aSfbScale[window*16]; + SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16]; + + leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength); + rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band=0; bandMsUsed[band] & groupMask) + { + int lScale=leftScale[band]; + int rScale=rightScale[band]; + int commonScale=lScale > rScale ? lScale:rScale; + + /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 : + M/S joint channel coding can only be used if common_window is ‘1’. */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + commonScale++; + leftScale[band]=commonScale; + rightScale[band]=commonScale; + + lScale = fMin(DFRACT_BITS-1, commonScale - lScale); + rScale = fMin(DFRACT_BITS-1, commonScale - rScale); + + FDK_ASSERT(lScale >= 0 && rScale >= 0); + + for (int index=pScaleFactorBandOffsets[band]; index>= lScale ; + rightCoefficient >>= rScale ; + + leftSpectrum [index] = leftCoefficient + rightCoefficient ; + rightSpectrum [index] = leftCoefficient - rightCoefficient ; + } + } + } + } + } + + /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary for intensity coding. + PNS correlation signalling was mapped before calling CJointStereo_ApplyMS(). */ + if (pJointStereoData->MsMaskPresent == 2) { + FDKmemclear(pJointStereoData->MsUsed, JointStereoMaximumBands * sizeof(UCHAR)); + } +} + +void CJointStereo_ApplyIS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const SHORT *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const UINT CommonWindow + ) +{ + CJointStereoData *pJointStereoData = &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + + for (int window=0,group=0; grouppDynData->aCodeBook[group*16]; + ScaleFactor = &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group*16]; + + for (int groupwin=0; groupwinpDynData->aSfbScale[window*16]; + SHORT *rightScale = &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window*16]; + int band; + + leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, window, pAacDecoderChannelInfo[L]->granuleLength); + rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band=0; band> 2 ; + int lsb = bandScale & 0x03 ; + + /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */ + FIXP_DBL scale = MantissaTable[lsb][0]; + + /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 : + The use of intensity stereo coding is signaled by the use of the pseudo codebooks + INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only in the right channel of a + channel_pair_element() having a common ics_info() (common_window == 1). */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + rightScale[band] = leftScale[band]+msb+1; + + if (CommonWindow && (pJointStereoData->MsUsed[band] & groupMask)) + { + + if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */ + { + scale = -scale ; + } + } + else + { + if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */ + { + scale = -scale ; + } + } + + for (int index=pScaleFactorBandOffsets[band]; index0 +\until } + +\section writeOutData Output Bitstream Data +If any AAC bitstream data is available, write it to output file or device. This can be done once the +following condition is true: +\dontinclude main.cpp +\skip Valid bitstream available +\skipline outargs + +\skipline outBytes>0 + +If you use file I/O then for example call mpegFileWrite_Write() from the library libMpegFileWrite + +\dontinclude main.cpp +\skipline mpegFileWrite_Write + +\section cfgMetaData Meta Data Configuration + +If the present library is configured with Metadata support, it is possible to insert meta data side info into the generated +audio bitstream while encoding. + +To work with meta data the encoder instance has to be \ref encOpen "allocated" with meta data support. The meta data mode must be be configured with +the ::AACENC_METADATA_MODE parameter and aacEncoder_SetParam() function. +\code aacEncoder_SetParam(hAacEncoder, AACENC_METADATA_MODE, 0-2); \endcode + +This configuration indicates how to embed meta data into bitstrem. Either no insertion, MPEG or ETSI style. +The meta data itself must be specified within the meta data setup structure AACENC_MetaData. + +Changing one of the AACENC_MetaData setup parameters can be achieved from outside the library within ::IN_METADATA_SETUP input +buffer. There is no need to supply meta data setup structure every frame. If there is no new meta setup data available, the +encoder uses the previous setup or the default configuration in initial state. + +In general the audio compressor and limiter within the encoder library can be configured with the ::AACENC_METADATA_DRC_PROFILE parameter +AACENC_MetaData::drc_profile and and AACENC_MetaData::comp_profile. +\n + +\section encReconf Encoder Reconfiguration + +The encoder library allows reconfiguration of the encoder instance with new settings +continuously between encoding frames. Each parameter to be changed must be set with +a single aacEncoder_SetParam() call. The internal status of each parameter can be +retrieved with an aacEncoder_GetParam() call.\n +There is no stand-alone reconfiguration function available. When parameters were +modified from outside the library, an internal control mechanism triggers the necessary +reconfiguration process which will be applied at the beginning of the following +aacEncEncode() call. This state can be observed from external via the AACENC_INIT_STATUS +and aacEncoder_GetParam() function. The reconfiguration process can also be applied +immediately when all parameters of an aacEncEncode() call are NULL with a valid encoder +handle.\n\n +The internal reconfiguration process can be controlled from extern with the following access. +\code aacEncoder_SetParam(hAacEncoder, AACENC_CONTROL_STATE, AACENC_CTRLFLAGS); \endcode + + +\section encParams Encoder Parametrization + +All parameteres listed in ::AACENC_PARAM can be modified within an encoder instance. + +\subsection encMandatory Mandatory Encoder Parameters +The following parameters must be specified when the encoder instance is initialized. +\code +aacEncoder_SetParam(hAacEncoder, AACENC_AOT, value); +aacEncoder_SetParam(hAacEncoder, AACENC_BITRATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_SAMPLERATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); +\endcode +Beyond that is an internal auto mode which preinitizializes the ::AACENC_BITRATE parameter +if the parameter was not set from extern. The bitrate depends on the number of effective +channels and sampling rate and is determined as follows. +\code +AAC-LC (AOT_AAC_LC): 1.5 bits per sample +HE-AAC (AOT_SBR): 0.625 bits per sample (dualrate sbr) +HE-AAC (AOT_SBR): 1.125 bits per sample (downsampled sbr) +HE-AAC v2 (AOT_PS): 0.5 bits per sample +\endcode + +\subsection channelMode Channel Mode Configuration +The input audio data is described with the ::AACENC_CHANNELMODE parameter in the +aacEncoder_SetParam() call. It is not possible to use the encoder instance with a 'number of +input channels' argument. Instead, the channelMode must be set as follows. +\code aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); \endcode +The parameter is specified in ::CHANNEL_MODE and can be mapped from the number of input channels +in the following way. +\dontinclude main.cpp +\skip CHANNEL_MODE chMode = MODE_INVALID; +\until return + +\subsection encQual Audio Quality Considerations +The default encoder configuration is suggested to be used. Encoder tools such as TNS and PNS +are activated by default and are internally controlled (see \ref BEHAVIOUR_TOOLS). + +There is an additional quality parameter called ::AACENC_AFTERBURNER. In the default +configuration this quality switch is deactivated because it would cause a workload +increase which might be significant. If workload is not an issue in the application +we recommended to activate this feature. +\code aacEncoder_SetParam(hAacEncoder, AACENC_AFTERBURNER, 1); \endcode + +\subsection encELD ELD Auto Configuration Mode +For ELD configuration a so called auto configurator is available which configures SBR and the SBR ratio by itself. +The configurator is used when the encoder parameter ::AACENC_SBR_MODE and ::AACENC_SBR_RATIO are not set explicitely. + +Based on sampling rate and chosen bitrate per channel a reasonable SBR configuration will be used. +\verbatim +------------------------------------------------------------ + Sampling Rate | Channel Bitrate | SBR | SBR Ratio +-----------------+-----------------+------+----------------- + ]min, 16] kHz | min - 27999 | on | downsampled SBR + | 28000 - max | off | --- +-----------------+-----------------+------+----------------- + ]16 - 24] kHz | min - 39999 | on | downsampled SBR + | 40000 - max | off | --- +-----------------+-----------------+------+----------------- + ]24 - 32] kHz | min - 27999 | on | dualrate SBR + | 28000 - 55999 | on | downsampled SBR + | 56000 - max | off | --- +-----------------+-----------------+------+----------------- + ]32 - 44.1] kHz | min - 63999 | on | dualrate SBR + | 64000 - max | off | --- +-----------------+-----------------+------+----------------- + ]44.1 - 48] kHz | min - 63999 | on | dualrate SBR + | 64000 - max | off | --- +------------------------------------------------------------ +\endverbatim + + +\section audiochCfg Audio Channel Configuration +The MPEG standard refers often to the so-called Channel Configuration. This Channel Configuration is used for a fixed Channel +Mapping. The configurations 1-7 are predefined in MPEG standard and used for implicit signalling within the encoded bitstream. +For user defined Configurations the Channel Configuration is set to 0 and the Channel Mapping must be explecitly described with an appropriate +Program Config Element. The present Encoder implementation does not allow the user to configure this Channel Configuration from +extern. The Encoder implementation supports fixed Channel Modes which are mapped to Channel Configuration as follow. +\verbatim +------------------------------------------------------------------------------- + ChannelMode | ChCfg | front_El | side_El | back_El | lfe_El +-----------------------+--------+---------------+----------+----------+-------- +MODE_1 | 1 | SCE | | | +MODE_2 | 2 | CPE | | | +MODE_1_2 | 3 | SCE, CPE | | | +MODE_1_2_1 | 4 | SCE, CPE | | SCE | +MODE_1_2_2 | 5 | SCE, CPE | | CPE | +MODE_1_2_2_1 | 6 | SCE, CPE | | CPE | LFE +MODE_1_2_2_2_1 | 7 | SCE, CPE, CPE | | CPE | LFE +-----------------------+--------+---------------+----------+----------+-------- +MODE_7_1_REAR_SURROUND | 0 | SCE, CPE | | CPE, CPE | LFE +MODE_7_1_FRONT_CENTER | 0 | SCE, CPE, CPE | | CPE | LFE +------------------------------------------------------------------------------- + - SCE: Single Channel Element. + - CPE: Channel Pair. + - SCE: Low Frequency Element. +\endverbatim + +Moreover, the Table describes all fixed Channel Elements for each Channel Mode which are assigned to a speaker arrangement. The +arrangement includes front, side, back and lfe Audio Channel Elements.\n +This mapping of Audio Channel Elements is defined in MPEG standard for Channel Config 1-7. The Channel assignment for MODE_1_1, +MODE_2_2 and MODE_2_1 is used from the ARIB standard. All other configurations are defined as suggested in MPEG.\n +In case of Channel Config 0 or writing matrix mixdown coefficients, the encoder enables the writing of Program Config Element +itself as described in \ref encPCE. The configuration used in Program Config Element refers to the denoted Table.\n +Beside the Channel Element assignment the Channel Modes are resposible for audio input data channel mapping. The Channel Mapping +of the audio data depends on the selected ::AACENC_CHANNELORDER which can be MPEG or WAV like order.\n +Following Table describes the complete channel mapping for both Channel Order configurations. +\verbatim +--------------------------------------------------------------------------------------- +ChannelMode | MPEG-Channelorder | WAV-Channelorder +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_1 | 0 | | | | | | | | 0 | | | | | | | +MODE_2 | 0 | 1 | | | | | | | 0 | 1 | | | | | | +MODE_1_2 | 0 | 1 | 2 | | | | | | 2 | 0 | 1 | | | | | +MODE_1_2_1 | 0 | 1 | 2 | 3 | | | | | 2 | 0 | 1 | 3 | | | | +MODE_1_2_2 | 0 | 1 | 2 | 3 | 4 | | | | 2 | 0 | 1 | 3 | 4 | | | +MODE_1_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | | | 2 | 0 | 1 | 4 | 5 | 3 | | +MODE_1_2_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 6 | 7 | 0 | 1 | 4 | 5 | 3 +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_7_1_REAR_SURROUND | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 0 | 1 | 6 | 7 | 4 | 5 | 3 +MODE_7_1_FRONT_CENTER | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 6 | 7 | 0 | 1 | 4 | 5 | 3 +--------------------------------------------------------------------------------------- +\endverbatim + +The denoted mapping is important for correct audio channel assignment when using MPEG or WAV ordering. The incoming audio +channels are distributed MPEG like starting at the front channels and ending at the back channels. The distribution is used as +described in Table concering Channel Config and fix channel elements. Please see the following example for clarification. + +\verbatim +Example: MODE_1_2_2_1 - WAV-Channelorder 5.1 +------------------------------------------ + Input Channel | Coder Channel +--------------------+--------------------- + 2 (front center) | 0 (SCE channel) + 0 (left center) | 1 (1st of 1st CPE) + 1 (right center) | 2 (2nd of 1st CPE) + 4 (left surround) | 3 (1st of 2nd CPE) + 5 (right surround) | 4 (2nd of 2nd CPE) + 3 (LFE) | 5 (LFE) +------------------------------------------ +\endverbatim + + +\section suppBitrates Supported Bitrates + +The FDK AAC Encoder provides a wide range of supported bitrates. +The minimum and maximum allowed bitrate depends on the Audio Object Type. For AAC-LC the minimum +bitrate is the bitrate that is required to write the most basic and minimal valid bitstream. +It consists of the bitstream format header information and other static/mandatory information +within the AAC payload. The maximum AAC framesize allowed by the MPEG-4 standard +determines the maximum allowed bitrate for AAC-LC. For HE-AAC and HE-AAC v2 a library internal +look-up table is used. + +A good working point in terms of audio quality, sampling rate and bitrate, is at 1 to 1.5 +bits/audio sample for AAC-LC, 0.625 bits/audio sample for dualrate HE-AAC, 1.125 bits/audio sample +for downsampled HE-AAC and 0.5 bits/audio sample for HE-AAC v2. +For example for one channel with a sampling frequency of 48 kHz, the range from +48 kbit/s to 72 kbit/s achieves reasonable audio quality for AAC-LC. + +For HE-AAC and HE-AAC v2 the lowest possible audio input sampling frequency is 16 kHz because then the +AAC-LC core encoder operates in dual rate mode at its lowest possible sampling frequency, which is 8 kHz. +HE-AAC v2 requires stereo input audio data. + +Please note that in HE-AAC or HE-AAC v2 mode the encoder supports much higher bitrates than are +appropriate for HE-AAC or HE-AAC v2. For example, at a bitrate of more than 64 kbit/s for a stereo +audio signal at 44.1 kHz it usually makes sense to use AAC-LC, which will produce better audio +quality at that bitrate than HE-AAC or HE-AAC v2. + +\section reommendedConfig Recommended Sampling Rate and Bitrate Combinations + +The following table provides an overview of recommended encoder configuration parameters +which we determined by virtue of numerous listening tests. + +\subsection reommendedConfigLC AAC-LC, HE-AAC, HE-AACv2 in Dualrate SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. of + | [bit/s] | Sampling Rates | Sampl. | Chan. + | | [kHz] | Rate | + | | | [kHz] | +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR + PS | 8000 - 11999 | 22.05, 24.00 | 24.00 | 2 +AAC LC + SBR + PS | 12000 - 17999 | 32.00 | 32.00 | 2 +AAC LC + SBR + PS | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR + PS | 40000 - 56000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 8000 - 11999 | 22.05, 24.00 | 24.00 | 1 +AAC LC + SBR | 12000 - 17999 | 32.00 | 32.00 | 1 +AAC LC + SBR | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC + SBR | 40000 - 56000 | 32.00, 44.10, 48.00 | 48.00 | 1 +AAC LC + SBR | 16000 - 27999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC + SBR | 28000 - 63999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR | 64000 - 128000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 64000 - 69999 | 32.00, 44.10, 48.00 | 32.00 | 5, 5.1 +AAC LC + SBR | 70000 - 159999 | 32.00, 44.10, 48.00 | 44.10 | 5, 5.1 +AAC LC + SBR | 160000 - 245999 | 32.00, 44.10, 48.00 | 48.00 | 5 +AAC LC + SBR | 160000 - 265999 | 32.00, 44.10, 48.00 | 48.00 | 5.1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 8000 - 15999 | 11.025, 12.00, 16.00 | 12.00 | 1 +AAC LC | 16000 - 23999 | 16.00 | 16.00 | 1 +AAC LC | 24000 - 31999 | 16.00, 22.05, 24.00 | 24.00 | 1 +AAC LC | 32000 - 55999 | 32.00 | 32.00 | 1 +AAC LC | 56000 - 160000 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC | 160001 - 288000 | 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 16000 - 23999 | 11.025, 12.00, 16.00 | 12.00 | 2 +AAC LC | 24000 - 31999 | 16.00 | 16.00 | 2 +AAC LC | 32000 - 39999 | 16.00, 22.05, 24.00 | 22.05 | 2 +AAC LC | 40000 - 95999 | 32.00 | 32.00 | 2 +AAC LC | 96000 - 111999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC | 112000 - 320001 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC | 320002 - 576000 | 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 160000 - 239999 | 32.00 | 32.00 | 5, 5.1 +AAC LC | 240000 - 279999 | 32.00, 44.10, 48.00 | 32.00 | 5, 5.1 +AAC LC | 280000 - 800000 | 32.00, 44.10, 48.00 | 44.10 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigLD AAC-LD, AAC-ELD, AAC-ELD with SBR in Dualrate SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. of + | [bit/s] | Sampling Rates | Sampl. | Chan. + | | [kHz] | Rate | + | | | [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 32.00 - 44.10 | 32.00 | 1 +ELD + SBR | 25000 - 31999 | 32.00 - 48.00 | 32.00 | 1 +ELD + SBR | 32000 - 64000 | 32.00 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 32000 - 51999 | 32.00 - 48.00 | 44.10 | 2 +ELD + SBR | 52000 - 128000 | 32.00 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 72000 - 160000 | 44.10 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 96000 - 212000 | 44.10 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 120000 - 246000 | 44.10 - 48.00 | 48.00 | 5 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 120000 - 266000 | 44.10 - 48.00 | 48.00 | 5.1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 16000 - 19999 | 16.00 - 24.00 | 16.00 | 1 +LD, ELD | 20000 - 39999 | 16.00 - 32.00 | 24.00 | 1 +LD, ELD | 40000 - 49999 | 22.05 - 32.00 | 32.00 | 1 +LD, ELD | 50000 - 61999 | 24.00 - 44.10 | 32.00 | 1 +LD, ELD | 62000 - 84999 | 32.00 - 48.00 | 44.10 | 1 +LD, ELD | 85000 - 192000 | 44.10 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 64000 - 75999 | 24.00 - 32.00 | 32.00 | 2 +LD, ELD | 76000 - 97999 | 24.00 - 44.10 | 32.00 | 2 +LD, ELD | 98000 - 135999 | 32.00 - 48.00 | 44.10 | 2 +LD, ELD | 136000 - 384000 | 44.10 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 96000 - 113999 | 24.00 - 32.00 | 32.00 | 3 +LD, ELD | 114000 - 146999 | 24.00 - 44.10 | 32.00 | 3 +LD, ELD | 147000 - 203999 | 32.00 - 48.00 | 44.10 | 3 +LD, ELD | 204000 - 576000 | 44.10 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 128000 - 151999 | 24.00 - 32.00 | 32.00 | 4 +LD, ELD | 152000 - 195999 | 24.00 - 44.10 | 32.00 | 4 +LD, ELD | 196000 - 271999 | 32.00 - 48.00 | 44.10 | 4 +LD, ELD | 272000 - 768000 | 44.10 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 160000 - 189999 | 24.00 - 32.00 | 32.00 | 5 +LD, ELD | 190000 - 244999 | 24.00 - 44.10 | 32.00 | 5 +LD, ELD | 245000 - 339999 | 32.00 - 48.00 | 44.10 | 5 +LD, ELD | 340000 - 960000 | 44.10 - 48.00 | 48.00 | 5 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigELD AAC-ELD with SBR in Downsampled SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. of + | [bit/s] | Sampling Rates | Sampl. | Chan. + | | [kHz] | Rate | + | | | [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 16.00 - 22.05 | 22.05 | 1 +(downsampled SBR) | 25000 - 35999 | 22.05 - 32.00 | 24.00 | 1 + | 36000 - 64000 | 32.00 - 48.00 | 32.00 | 1 +----------------------------------------------------------------------------------- +\endverbatim \n + + +\page ENCODERBEHAVIOUR Encoder Behaviour + +\section BEHAVIOUR_BANDWIDTH Bandwidth + +The FDK AAC encoder usually does not use the full frequency range of the input signal, but restricts the bandwidth +according to certain library-internal settings. They can be changed in the table "bandWidthTable" in the +file bandwidth.cpp (if available). + +The encoder API provides the ::AACENC_BANDWIDTH parameter to adjust the bandwidth explicitly. +\code +aacEncoder_SetParam(hAacEncoder, AACENC_BANDWIDTH, value); +\endcode + +However it is not recommended to change these settings, because they are based on numerious listening +tests and careful tweaks to ensure the best overall encoding quality. + +Theoretically a signal of for example 48 kHz can contain frequencies up to 24 kHz, but to use this full range +in an audio encoder usually does not make sense. Usually the encoder has a very limited amount of +bits to spend (typically 128 kbit/s for stereo 48 kHz content) and to allow full range bandwidth would +waste a lot of these bits for frequencies the human ear is hardly able to perceive anyway, if at all. Hence it +is wise to use the available bits for the really important frequency range and just skip the rest. +At lower bitrates (e. g. <= 80 kbit/s for stereo 48 kHz content) the encoder will choose an even smaller +bandwidth, because an encoded signal with smaller bandwidth and hence less artifacts sounds better than a signal +with higher bandwidth but then more coding artefacts across all frequencies. These artefacts would occur if +small bitrates and high bandwidths are chosen because the available bits are just not enough to encode all +frequencies well. + +Unfortunately some people evaluate encoding quality based on possible bandwidth as well, but it is a two-sided +sword considering the trade-off described above. + +Another aspect is workload consumption. The higher the allowed bandwidth, the more frequency lines have to be +processed, which in turn increases the workload. + +\section FRAMESIZES_AND_BIT_RESERVOIR Frame Sizes & Bit Reservoir + +For AAC there is a difference between constant bit rate and constant frame +length due to the so-called bit reservoir technique, which allows the encoder to use less +bits in an AAC frame for those audio signal sections which are easy to encode, +and then spend them at a later point in +time for more complex audio sections. The extent to which this "bit exchange" +is done is limited to allow for reliable and relatively low delay real time +streaming. +Over a longer period in time the bitrate will be constant in the AAC constant +bitrate mode, e.g. for ISDN transmission. This means that in AAC each bitstream +frame will in general have a different length in bytes but over time it +will reach the target bitrate. One could also make an MPEG compliant +AAC encoder which always produces constant length packages for each AAC frame, +but the audio quality would be considerably worse since the bit reservoir +technique would have to be switched off completely. A higher bit rate would have +to be used to get the same audio quality as with an enabled bit reservoir. + +The maximum AAC frame length, regardless of the available bit reservoir, is defined +as 6144 bits per channel. + +For mp3 by the way, the same bit reservoir technique exists, but there each bit +stream frame has a constant length for a given bit rate (ignoring the +padding byte). In mp3 there is a so-called "back pointer" which tells +the decoder which bits belong to the current mp3 frame - and in general some or +many bits have been transmitted in an earlier mp3 frame. Basically this leads to +the same "bit exchange between mp3 frames" as in AAC but with virtually constant +length frames. + +This variable frame length at "constant bit rate" is not something special +in this Fraunhofer IIS AAC encoder. AAC has been designed in that way. + +\subsection BEHAVIOUR_ESTIM_AVG_FRAMESIZES Estimating Average Frame Sizes + +A HE-AAC v1 or v2 audio frame contains 2048 PCM samples per channel (there is +also one mode with 1920 samples per channel but this is only for special purposes +such as DAB+ digital radio). + +The number of HE-AAC frames \f$N\_FRAMES\f$ per second at 44.1 kHz is: + +\f[ +N\_FRAMES = 44100 / 2048 = 21.5332 +\f] + +At a bit rate of 8 kbps the average number of bits per frame \f$N\_BITS\_PER\_FRAME\f$ is: + +\f[ +N\_BITS\_PER\_FRAME = 8000 / 21.5332 = 371.52 +\f] + +which is about 46.44 bytes per encoded frame. + +At a bit rate of 32 kbps, which is quite high for single channel HE-AAC v1, it is: + +\f[ +N\_BITS\_PER\_FRAME = 32000 / 21.5332 = 1486 +\f] + +which is about 185.76 bytes per encoded frame. + +These bits/frame figures are average figures where each AAC frame generally has a different +size in bytes. To calculate the same for AAC-LC just use 1024 instead of 2048 PCM samples per +frame and channel. +For AAC-LD/ELD it is either 480 or 512 PCM samples per frame and channel. + + +\section BEHAVIOUR_TOOLS Encoder Tools + +The AAC encoder supports TNS, PNS, MS, Intensity and activates these tools depending on the audio signal and +the encoder configuration (i.e. bitrate or AOT). It is not required to configure these tools manually. + +PNS improves encoding quality only for certain bitrates. Therefore it makes sense to activate PNS only for +these bitrates and save the processing power required for PNS (about 10 % of the encoder) when using other +bitrates. This is done automatically inside the encoder library. PNS is disabled inside the encoder library if +an MPEG-2 AOT is choosen since PNS is an MPEG-4 AAC feature. + +If SBR is activated, the encoder automatically deactivates PNS internally. If TNS is disabled but PNS is allowed, +the encoder deactivates PNS calculation internally. + +*/ + +#ifndef _AAC_ENC_LIB_H_ +#define _AAC_ENC_LIB_H_ + +#include "machine_type.h" +#include "FDK_audio.h" + +#define AACENCODER_LIB_VL0 3 +#define AACENCODER_LIB_VL1 4 +#define AACENCODER_LIB_VL2 22 + +/** + * AAC encoder error codes. + */ +typedef enum { + AACENC_OK = 0x0000, /*!< No error happened. All fine. */ + + AACENC_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */ + AACENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + AACENC_UNSUPPORTED_PARAMETER = 0x0022, /*!< Parameter not available. */ + AACENC_INVALID_CONFIG = 0x0023, /*!< Configuration not provided. */ + + AACENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + AACENC_INIT_AAC_ERROR = 0x0041, /*!< AAC library initialization error. */ + AACENC_INIT_SBR_ERROR = 0x0042, /*!< SBR library initialization error. */ + AACENC_INIT_TP_ERROR = 0x0043, /*!< Transport library initialization error. */ + AACENC_INIT_META_ERROR = 0x0044, /*!< Meta data library initialization error. */ + + AACENC_ENCODE_ERROR = 0x0060, /*!< The encoding process was interrupted by an unexpected error. */ + + AACENC_ENCODE_EOF = 0x0080 /*!< End of file reached. */ + +} AACENC_ERROR; + + +/** + * AAC encoder buffer descriptors identifier. + * This identifier are used within buffer descriptors AACENC_BufDesc::bufferIdentifiers. + */ +typedef enum { + /* Input buffer identifier. */ + IN_AUDIO_DATA = 0, /*!< Audio input buffer, interleaved INT_PCM samples. */ + IN_ANCILLRY_DATA = 1, /*!< Ancillary data to be embedded into bitstream. */ + IN_METADATA_SETUP = 2, /*!< Setup structure for embedding meta data. */ + + /* Output buffer identifier. */ + OUT_BITSTREAM_DATA = 3, /*!< Buffer holds bitstream output data. */ + OUT_AU_SIZES = 4 /*!< Buffer contains sizes of each access unit. This information + is necessary for superframing. */ + +} AACENC_BufferIdentifier; + + +/** + * AAC encoder handle. + */ +typedef struct AACENCODER *HANDLE_AACENCODER; + + +/** + * Provides some info about the encoder configuration. + */ +typedef struct { + + UINT maxOutBufBytes; /*!< Maximum number of encoder bitstream bytes within one frame. + Size depends on maximum number of supported channels in encoder instance. + For superframing (as used for example in DAB+), size has to be a multiple accordingly. */ + + UINT maxAncBytes; /*!< Maximum number of ancillary data bytes which can be inserted into + bitstream within one frame. */ + + UINT inBufFillLevel; /*!< Internal input buffer fill level in samples per channel. This parameter + will automatically be cleared if samplingrate or channel(Mode/Order) changes. */ + + UINT inputChannels; /*!< Number of input channels expected in encoding process. */ + + UINT frameLength; /*!< Amount of input audio samples consumed each frame per channel, depending + on audio object type configuration. */ + + UINT encoderDelay; /*!< Codec delay in PCM samples/channel. Depends on framelength and AOT. Does not + include framing delay for filling up encoder PCM input buffer. */ + + UCHAR confBuf[64]; /*!< Configuration buffer in binary format as an AudioSpecificConfig + or StreamMuxConfig according to the selected transport type. */ + + UINT confSize; /*!< Number of valid bytes in confBuf. */ + +} AACENC_InfoStruct; + + +/** + * Describes the input and output buffers for an aacEncEncode() call. + */ +typedef struct { + INT numBufs; /*!< Number of buffers. */ + void **bufs; /*!< Pointer to vector containing buffer addresses. */ + INT *bufferIdentifiers; /*!< Identifier of each buffer element. See ::AACENC_BufferIdentifier. */ + INT *bufSizes; /*!< Size of each buffer in 8-bit bytes. */ + INT *bufElSizes; /*!< Size of each buffer element in bytes. */ + +} AACENC_BufDesc; + + +/** + * Defines the input arguments for an aacEncEncode() call. + */ +typedef struct { + INT numInSamples; /*!< Number of valid input audio samples (multiple of input channels). */ + INT numAncBytes; /*!< Number of ancillary data bytes to be encoded. */ + +} AACENC_InArgs; + + +/** + * Defines the output arguments for an aacEncEncode() call. + */ +typedef struct { + INT numOutBytes; /*!< Number of valid bitstream bytes generated during aacEncEncode(). */ + INT numInSamples; /*!< Number of input audio samples consumed by the encoder. */ + INT numAncBytes; /*!< Number of ancillary data bytes consumed by the encoder. */ + +} AACENC_OutArgs; + + +/** + * Meta Data Compression Profiles. + */ +typedef enum { + AACENC_METADATA_DRC_NONE = 0, /*!< None. */ + AACENC_METADATA_DRC_FILMSTANDARD = 1, /*!< Film standard. */ + AACENC_METADATA_DRC_FILMLIGHT = 2, /*!< Film light. */ + AACENC_METADATA_DRC_MUSICSTANDARD = 3, /*!< Music standard. */ + AACENC_METADATA_DRC_MUSICLIGHT = 4, /*!< Music light. */ + AACENC_METADATA_DRC_SPEECH = 5 /*!< Speech. */ + +} AACENC_METADATA_DRC_PROFILE; + + +/** + * Meta Data setup structure. + */ +typedef struct { + + AACENC_METADATA_DRC_PROFILE drc_profile; /*!< MPEG DRC compression profile. See ::AACENC_METADATA_DRC_PROFILE. */ + AACENC_METADATA_DRC_PROFILE comp_profile; /*!< ETSI heavy compression profile. See ::AACENC_METADATA_DRC_PROFILE. */ + + INT drc_TargetRefLevel; /*!< Used to define expected level to: + Scaled with 16 bit. x*2^16. */ + INT comp_TargetRefLevel; /*!< Adjust limiter to avoid overload. + Scaled with 16 bit. x*2^16. */ + + INT prog_ref_level_present; /*!< Flag, if prog_ref_level is present */ + INT prog_ref_level; /*!< Programme Reference Level = Dialogue Level: + -31.75dB .. 0 dB ; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + + UCHAR PCE_mixdown_idx_present; /*!< Flag, if dmx-idx should be written in programme config element */ + UCHAR ETSI_DmxLvl_present; /*!< Flag, if dmx-lvl should be written in ETSI-ancData */ + + SCHAR centerMixLevel; /*!< Center downmix level (0...7, according to table) */ + SCHAR surroundMixLevel; /*!< Surround downmix level (0...7, according to table) */ + + UCHAR dolbySurroundMode; /*!< Indication for Dolby Surround Encoding Mode. + - 0: Dolby Surround mode not indicated + - 1: 2-ch audio part is not Dolby surround encoded + - 2: 2-ch audio part is Dolby surround encoded */ +} AACENC_MetaData; + + +/** + * AAC encoder control flags. + * + * In interaction with the ::AACENC_CONTROL_STATE parameter it is possible to get information about the internal + * initialization process. It is also possible to overwrite the internal state from extern when necessary. + */ +typedef enum +{ + AACENC_INIT_NONE = 0x0000, /*!< Do not trigger initialization. */ + AACENC_INIT_CONFIG = 0x0001, /*!< Initialize all encoder modules configuration. */ + AACENC_INIT_STATES = 0x0002, /*!< Reset all encoder modules history buffer. */ + AACENC_INIT_TRANSPORT = 0x1000, /*!< Initialize transport lib with new parameters. */ + AACENC_RESET_INBUFFER = 0x2000, /*!< Reset fill level of internal input buffer. */ + AACENC_INIT_ALL = 0xFFFF /*!< Initialize all. */ +} +AACENC_CTRLFLAGS; + + +/** + * \brief AAC encoder setting parameters. + * + * Use aacEncoder_SetParam() function to configure, or use aacEncoder_GetParam() function to read + * the internal status of the following parameters. + */ +typedef enum +{ + AACENC_AOT = 0x0100, /*!< Audio object type. See ::AUDIO_OBJECT_TYPE in FDK_audio.h. + - 2: MPEG-4 AAC Low Complexity. + - 5: MPEG-4 AAC Low Complexity with Spectral Band Replication (HE-AAC). + - 29: MPEG-4 AAC Low Complexity with Spectral Band Replication and Parametric Stereo (HE-AAC v2). + This configuration can be used only with stereo input audio data. + - 23: MPEG-4 AAC Low-Delay. + - 39: MPEG-4 AAC Enhanced Low-Delay. Since there is no ::AUDIO_OBJECT_TYPE for ELD in + combination with SBR defined, enable SBR explicitely by ::AACENC_SBR_MODE parameter. */ + + AACENC_BITRATE = 0x0101, /*!< Total encoder bitrate. This parameter is mandatory and interacts with ::AACENC_BITRATEMODE. + - CBR: Bitrate in bits/second. + See \ref suppBitrates for details. */ + + AACENC_BITRATEMODE = 0x0102, /*!< Bitrate mode. Configuration can be different kind of bitrate configurations: + - 0: Constant bitrate, use bitrate according to ::AACENC_BITRATE. (default) + Within none LD/ELD ::AUDIO_OBJECT_TYPE, the CBR mode makes use of full allowed bitreservoir. + In contrast, at Low-Delay ::AUDIO_OBJECT_TYPE the bitreservoir is kept very small. + - 8: LD/ELD full bitreservoir for packet based transmission. */ + + AACENC_SAMPLERATE = 0x0103, /*!< Audio input data sampling rate. Encoder supports following sampling rates: + 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 */ + + AACENC_SBR_MODE = 0x0104, /*!< Configure SBR independently of the chosen Audio Object Type ::AUDIO_OBJECT_TYPE. + This parameter is for ELD audio object type only. + - -1: Use ELD SBR auto configurator (default). + - 0: Disable Spectral Band Replication. + - 1: Enable Spectral Band Replication. */ + + AACENC_GRANULE_LENGTH = 0x0105, /*!< Core encoder (AAC) audio frame length in samples: + - 1024: Default configuration. + - 960: DRM/DAB+. + - 512: Default LD/ELD configuration. + - 480: Optional length in LD/ELD configuration. */ + + AACENC_CHANNELMODE = 0x0106, /*!< Set explicit channel mode. Channel mode must match with number of input channels. + - 1-7 and 33,34: MPEG channel modes supported, see ::CHANNEL_MODE in FDK_audio.h. */ + + AACENC_CHANNELORDER = 0x0107, /*!< Input audio data channel ordering scheme: + - 0: MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE). (default) + - 1: WAVE file format channel ordering (e. g. 5.1: L, R, C, LFE, SL, SR). */ + + AACENC_SBR_RATIO = 0x0108, /*!< Controls activation of downsampled SBR. With downsampled SBR, the delay will be + shorter. On the other hand, for achieving the same quality level, downsampled SBR + needs more bits than dual-rate SBR. + With downsampled SBR, the AAC encoder will work at the same sampling rate as the + SBR encoder (single rate). + Downsampled SBR is supported for AAC-ELD and HE-AACv1. + - 1: Downsampled SBR (default for ELD). + - 2: Dual-rate SBR (default for HE-AAC). */ + + AACENC_AFTERBURNER = 0x0200, /*!< This parameter controls the use of the afterburner feature. + The afterburner is a type of analysis by synthesis algorithm which increases the + audio quality but also the required processing power. It is recommended to always + activate this if additional memory consumption and processing power consumption + is not a problem. If increased MHz and memory consumption are an issue then the MHz + and memory cost of this optional module need to be evaluated against the improvement + in audio quality on a case by case basis. + - 0: Disable afterburner (default). + - 1: Enable afterburner. */ + + AACENC_BANDWIDTH = 0x0203, /*!< Core encoder audio bandwidth: + - 0: Determine bandwidth internally (default, see chapter \ref BEHAVIOUR_BANDWIDTH). + - 1 to fs/2: Frequency bandwidth in Hertz. (Experts only, better do not + touch this value to avoid degraded audio quality) */ + + AACENC_PEAK_BITRATE = 0x0207, /*!< Peak bitrate configuration parameter to adjust maximum bits per audio frame. Bitrate is in bits/second. + The peak bitrate will internally be limited to the chosen bitrate ::AACENC_BITRATE as lower limit + and the number_of_effective_channels*6144 bit as upper limit. + + Setting the peak bitrate equal to ::AACENC_BITRATE does not necessarily mean that the audio frames + will be of constant size. Since the peak bitate is in bits/second, the frame sizes can vary by + one byte in one or the other direction over various frames. However, it is not recommended to reduce + the peak pitrate to ::AACENC_BITRATE - it would disable the bitreservoir, which would affect the + audio quality by a large amount. */ + + AACENC_TRANSMUX = 0x0300, /*!< Transport type to be used. See ::TRANSPORT_TYPE in FDK_audio.h. Following + types can be configured in encoder library: + - 0: raw access units + - 1: ADIF bitstream format + - 2: ADTS bitstream format + - 6: Audio Mux Elements (LATM) with muxConfigPresent = 1 + - 7: Audio Mux Elements (LATM) with muxConfigPresent = 0, out of band StreamMuxConfig + - 10: Audio Sync Stream (LOAS) */ + + AACENC_HEADER_PERIOD = 0x0301, /*!< Frame count period for sending in-band configuration buffers within LATM/LOAS + transport layer. Additionally this parameter configures the PCE repetition period + in raw_data_block(). See \ref encPCE. + - 0xFF: auto-mode default 10 for TT_MP4_ADTS, TT_MP4_LOAS and TT_MP4_LATM_MCP1, otherwise 0. + - n: Frame count period. */ + + AACENC_SIGNALING_MODE = 0x0302, /*!< Signaling mode of the extension AOT: + - 0: Implicit backward compatible signaling (default for non-MPEG-4 based + AOT's and for the transport formats ADIF and ADTS) + - A stream that uses implicit signaling can be decoded by every AAC decoder, even AAC-LC-only decoders + - An AAC-LC-only decoder will only decode the low-frequency part of the stream, resulting in a band-limited output + - This method works with all transport formats + - This method does not work with downsampled SBR + - 1: Explicit backward compatible signaling + - A stream that uses explicit backward compatible signaling can be decoded by every AAC decoder, even AAC-LC-only decoders + - An AAC-LC-only decoder will only decode the low-frequency part of the stream, resulting in a band-limited output + - A decoder not capable of decoding PS will only decode the AAC-LC+SBR part. + If the stream contained PS, the result will be a a decoded mono downmix + - This method does not work with ADIF or ADTS. For LOAS/LATM, it only works with AudioMuxVersion==1 + - This method does work with downsampled SBR + - 2: Explicit hierarchical signaling (default for MPEG-4 based AOT's and for all transport formats excluding ADIF and ADTS) + - A stream that uses explicit hierarchical signaling can be decoded only by HE-AAC decoders + - An AAC-LC-only decoder will not decode a stream that uses explicit hierarchical signaling + - A decoder not capable of decoding PS will not decode the stream at all if it contained PS + - This method does not work with ADIF or ADTS. It works with LOAS/LATM and the MPEG-4 File format + - This method does work with downsampled SBR + + For making sure that the listener always experiences the best audio quality, + explicit hierarchical signaling should be used. + This makes sure that only a full HE-AAC-capable decoder will decode those streams. + The audio is played at full bandwidth. + For best backwards compatibility, it is recommended to encode with implicit SBR signaling. + A decoder capable of AAC-LC only will then only decode the AAC part, which means the decoded + audio will sound band-limited. + + For MPEG-2 transport types (ADTS,ADIF), only implicit signaling is possible. + + For LOAS and LATM, explicit backwards compatible signaling only works together with AudioMuxVersion==1. + The reason is that, for explicit backwards compatible signaling, additional information will be appended to the ASC. + A decoder that is only capable of decoding AAC-LC will skip this part. + Nevertheless, for jumping to the end of the ASC, it needs to know the ASC length. + Transmitting the length of the ASC is a feature of AudioMuxVersion==1, it is not possible to transmit the + length of the ASC with AudioMuxVersion==0, therefore an AAC-LC-only decoder will not be able to parse a + LOAS/LATM stream that was being encoded with AudioMuxVersion==0. + + For downsampled SBR, explicit signaling is mandatory. The reason for this is that the + extension sampling frequency (which is in case of SBR the sampling frequqncy of the SBR part) + can only be signaled in explicit mode. + + For AAC-ELD, the SBR information is transmitted in the ELDSpecific Config, which is part of the + AudioSpecificConfig. Therefore, the settings here will have no effect on AAC-ELD.*/ + + AACENC_TPSUBFRAMES = 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM, DAB+ or ADTS (default 1). + - ADTS: Maximum number of sub frames restricted to 4. + - DAB+: Maximum number of sub frames restricted to 6. + - LOAS/LATM: Maximum number of sub frames restricted to 2.*/ + + AACENC_AUDIOMUXVER = 0x0304, /*!< AudioMuxVersion to be used for LATM. (AudioMuxVersionA, currently not implemented): + - 0: Default, no transmission of tara Buffer fullness, no ASC length and including actual latm Buffer fullnes. + - 1: Transmission of tara Buffer fullness, ASC length and actual latm Buffer fullness. + - 2: Transmission of tara Buffer fullness, ASC length and maximum level of latm Buffer fullness. */ + + AACENC_PROTECTION = 0x0306, /*!< Configure protection in tranpsort layer: + - 0: No protection. (default) + - 1: CRC active for ADTS bitstream format. */ + + AACENC_ANCILLARY_BITRATE = 0x0500, /*!< Constant ancillary data bitrate in bits/second. + - 0: Either no ancillary data or insert exact number of bytes, denoted via + input parameter, numAncBytes in AACENC_InArgs. + - else: Insert ancillary data with specified bitrate. */ + + AACENC_METADATA_MODE = 0x0600, /*!< Configure Meta Data. See ::AACENC_MetaData for further details: + - 0: Do not embed any metadata. + - 1: Embed MPEG defined metadata only. + - 2: Embed all metadata. */ + + AACENC_CONTROL_STATE = 0xFF00, /*!< There is an automatic process which internally reconfigures the encoder instance + when a configuration parameter changed or an error occured. This paramerter allows + overwriting or getting the control status of this process. See ::AACENC_CTRLFLAGS. */ + + AACENC_NONE = 0xFFFF /*!< ------ */ + +} AACENC_PARAM; + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Open an instance of the encoder. + * + * Allocate memory for an encoder instance with a functional range denoted by the function parameters. + * Preinitialize encoder instance with default configuration. + * + * \param phAacEncoder A pointer to an encoder handle. Initialized on return. + * \param encModules Specify encoder modules to be supported in this encoder instance: + * - 0x0: Allocate memory for all available encoder modules. + * - else: Select memory allocation regarding encoder modules. Following flags are possible and can be combined. + * - 0x01: AAC module. + * - 0x02: SBR module. + * - 0x04: PS module. + * - 0x10: Metadata module. + * - example: (0x01|0x02|0x04|0x10) allocates all modules and is equivalent to default configuration denotet by 0x0. + * \param maxChannels Number of channels to be allocated. This parameter can be used in different ways: + * - 0: Allocate maximum number of AAC and SBR channels as supported by the library. + * - nChannels: Use same maximum number of channels for allocating memory in AAC and SBR module. + * - nChannels | (nSbrCh<<8): Number of SBR channels can be different to AAC channels to save data memory. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INVALID_HANDLE, AACENC_MEMORY_ERROR, AACENC_INVALID_CONFIG, on failure. + */ +AACENC_ERROR aacEncOpen( + HANDLE_AACENCODER *phAacEncoder, + const UINT encModules, + const UINT maxChannels + ); + + +/** + * \brief Close the encoder instance. + * + * Deallocate encoder instance and free whole memory. + * + * \param phAacEncoder Pointer to the encoder handle to be deallocated. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, on failure. + */ +AACENC_ERROR aacEncClose( + HANDLE_AACENCODER *phAacEncoder + ); + + +/** + * \brief Encode audio data. + * + * This function is mainly for encoding audio data. In addition the function can be used for an encoder (re)configuration + * process. + * - PCM input data will be retrieved from external input buffer until the fill level allows encoding a single frame. + * This functionality allows an external buffer with reduced size in comparison to the AAC or HE-AAC audio frame length. + * - If the value of the input samples argument is zero, just internal reinitialization will be applied if it is + * requested. + * - At the end of a file the flushing process can be triggerd via setting the value of the input samples argument to -1. + * The encoder delay lines are fully flushed when the encoder returns no valid bitstream data AACENC_OutArgs::numOutBytes. + * Furthermore the end of file is signaled by the return value AACENC_ENCODE_EOF. + * - If an error occured in the previous frame or any of the encoder parameters changed, an internal reinitialization + * process will be applied before encoding the incoming audio samples. + * - The function can also be used for an independent reconfiguration process without encoding. The first parameter has to be a + * valid encoder handle and all other parameters can be set to NULL. + * - If the size of the external bitbuffer in outBufDesc is not sufficient for writing the whole bitstream, an internal + * error will be the return value and a reconfiguration will be triggered. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param inBufDesc Input buffer descriptor, see AACENC_BufDesc: + * - At least one input buffer with audio data is expected. + * - Optionally a second input buffer with ancillary data can be fed. + * \param outBufDesc Output buffer descriptor, see AACENC_BufDesc: + * - Provide one output buffer for the encoded bitstream. + * \param inargs Input arguments, see AACENC_InArgs. + * \param outargs Output arguments, AACENC_OutArgs. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_ENCODE_ERROR, on failure in encoding process. + * - AACENC_INVALID_CONFIG, AACENC_INIT_ERROR, AACENC_INIT_AAC_ERROR, AACENC_INIT_SBR_ERROR, AACENC_INIT_TP_ERROR, + * AACENC_INIT_META_ERROR, on failure in encoder initialization. + * - AACENC_ENCODE_EOF, when flushing fully concluded. + */ +AACENC_ERROR aacEncEncode( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, + AACENC_OutArgs *outargs + ); + + +/** + * \brief Acquire info about present encoder instance. + * + * This function retrieves information of the encoder configuration. In addition to informative internal states, + * a configuration data block of the current encoder settings will be returned. The format is either Audio Specific Config + * in case of Raw Packets transport format or StreamMuxConfig in case of LOAS/LATM transport format. The configuration + * data block is binary coded as specified in ISO/IEC 14496-3 (MPEG-4 audio), to be used directly for MPEG-4 File Format + * or RFC3016 or RFC3640 applications. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param pInfo Pointer to AACENC_InfoStruct. Filled on return. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncInfo( + const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo + ); + + +/** + * \brief Set one single AAC encoder parameter. + * + * This function allows configuration of all encoder parameters specified in ::AACENC_PARAM. Each parameter must be + * set with a separate function call. An internal validation of the configuration value range will be done and an + * internal reconfiguration will be signaled. The actual configuration adoption is part of the subsequent aacEncEncode() call. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be set. See ::AACENC_PARAM. + * \param value Parameter value. See parameter description in ::AACENC_PARAM. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_UNSUPPORTED_PARAMETER, AACENC_INVALID_CONFIG, on failure. + */ +AACENC_ERROR aacEncoder_SetParam( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, + const UINT value + ); + + +/** + * \brief Get one single AAC encoder parameter. + * + * This function is the complement to aacEncoder_SetParam(). After encoder reinitialization with user defined settings, + * the internal status can be obtained of each parameter, specified with ::AACENC_PARAM. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be returned. See ::AACENC_PARAM. + * + * \return Internal configuration value of specifed parameter ::AACENC_PARAM. + */ +UINT aacEncoder_GetParam( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param + ); + + +/** + * \brief Get information about encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncGetLibInfo( + LIB_INFO *info + ); + + +#ifdef __cplusplus +} +#endif + +#endif /* _AAC_ENC_LIB_H_ */ diff --git a/libAACenc/src/aacEnc_ram.cpp b/libAACenc/src/aacEnc_ram.cpp new file mode 100644 index 00000000..be3eea27 --- /dev/null +++ b/libAACenc/src/aacEnc_ram.cpp @@ -0,0 +1,194 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/****************************************************************************** + + Initial authors: M. Lohwasser, M. Gayer + Contents/description: + +******************************************************************************/ +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#include "aacEnc_ram.h" + + C_AALLOC_MEM (AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE/sizeof(FIXP_DBL)) + +/* + Static memory areas, must not be overwritten in other sections of the decoder ! +*/ + +/* + The structure AacEncoder contains all Encoder structures. +*/ + +C_ALLOC_MEM (Ram_aacEnc_AacEncoder, AAC_ENC, 1) + + +/* + The structure PSY_INTERNAl contains all psych configuration and data pointer. + * PsyStatic holds last and current Psych data. + * PsyInputBuffer contains time input. Signal is needed at the beginning of Psych. + Memory can be reused after signal is in time domain. + * PsyData contains spectral, nrg and threshold information. Necessary data are + copied into PsyOut, so memory is available after leaving psych. + * TnsData, ChaosMeasure, PnsData are temporarily necessary, e.g. use memory from + PsyInputBuffer. +*/ + +C_ALLOC_MEM2 (Ram_aacEnc_PsyElement, PSY_ELEMENT, 1, (8)) + +C_ALLOC_MEM (Ram_aacEnc_PsyInternal, PSY_INTERNAL, 1) +C_ALLOC_MEM2 (Ram_aacEnc_PsyStatic, PSY_STATIC, 1, (8)) + +C_ALLOC_MEM2 (Ram_aacEnc_PsyInputBuffer, INT_PCM, MAX_INPUT_BUFFER_SIZE, (8)) + + PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic (int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((PSY_DYNAMIC*) (dynamic_RAM + P_BUF_1 + n*sizeof(PSY_DYNAMIC))); + } + + C_ALLOC_MEM (Ram_bsOutbuffer, UCHAR, OUTPUTBUFFER_SIZE) + +/* + The structure PSY_OUT holds all psychoaccoustic data needed + in quantization module +*/ +C_ALLOC_MEM2 (Ram_aacEnc_PsyOut, PSY_OUT, 1, (1)) + +C_ALLOC_MEM2 (Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT, 1, (1)*(8)) +C_ALLOC_MEM2 (Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL, 1, (1)*(8)) + + +/* + The structure QC_STATE contains preinitialized settings and quantizer structures. + * AdjustThreshold structure contains element-wise settings. + * ElementBits contains elemnt-wise bit consumption settings. + * When CRC is active, lookup table is necessary for fast crc calculation. + * Bitcounter contains buffer to find optimal codebooks and minimal bit consumption. + Values are temporarily, so dynamic memory can be used. +*/ + +C_ALLOC_MEM (Ram_aacEnc_QCstate, QC_STATE, 1) +C_ALLOC_MEM (Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE, 1) + +C_ALLOC_MEM2 (Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT, 1, (8)) +C_ALLOC_MEM2 (Ram_aacEnc_ElementBits, ELEMENT_BITS, 1, (8)) +C_ALLOC_MEM (Ram_aacEnc_BitCntrState, BITCNTR_STATE, 1) + + INT *GetRam_aacEnc_BitLookUp(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((INT*) (dynamic_RAM + P_BUF_1)); + } + INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((INT*) (dynamic_RAM + P_BUF_1 + sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)))); + } + + +/* + The structure QC_OUT contains settings and structures holding all necessary information + needed in bitstreamwriter. +*/ + +C_ALLOC_MEM2 (Ram_aacEnc_QCout, QC_OUT, 1, (1)) +C_ALLOC_MEM2 (Ram_aacEnc_QCelement, QC_OUT_ELEMENT, (1), (8)) + QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((QC_OUT_CHANNEL*) (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL))); + } + + + + + + + + + + + + diff --git a/libAACenc/src/aacEnc_ram.h b/libAACenc/src/aacEnc_ram.h new file mode 100644 index 00000000..cf7da7c2 --- /dev/null +++ b/libAACenc/src/aacEnc_ram.h @@ -0,0 +1,226 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/****************************************************************************** + + Initial authors: M. Lohwasser, M. Gayer + Contents/description: + +******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AAC_ENC_RAM_H +#define AAC_ENC_RAM_H + +#include "common_fix.h" + +#include "aacenc.h" +#include "psy_data.h" +#include "interface.h" +#include "psy_main.h" +#include "bitenc.h" +#include "bit_cnt.h" +#include "psy_const.h" + + #define OUTPUTBUFFER_SIZE (8192) /*!< Output buffer size has to be at least 6144 bits per channel (768 bytes). FDK bitbuffer implementation expects buffer of size 2^n. */ + + +/* + Moved AAC_ENC struct definition from aac_enc.cpp into aacEnc_ram.h to get size and respective + static memory in aacEnc_ram.cpp. + aac_enc.h is the outward visible header file and putting the struct into would cause necessity + of additional visible header files outside library. +*/ + +/* define hBitstream size: max AAC framelength is 6144 bits/channel */ +/*#define BUFFER_BITSTR_SIZE ((6400*(8)/bbWordSize) +((bbWordSize - 1) / bbWordSize))*/ + +struct AAC_ENC { + + AACENC_CONFIG *config; + + INT ancillaryBitsPerFrame; /* ancillary bits per frame calculated from ancillary rate */ + + CHANNEL_MAPPING channelMapping; + + QC_STATE *qcKernel; + QC_OUT *qcOut[(1)]; + + PSY_OUT *psyOut[(1)]; + PSY_INTERNAL *psyKernel; + + /* lifetime vars */ + + CHANNEL_MODE encoderMode; + INT bandwidth90dB; + AACENC_BITRATE_MODE bitrateMode; + + INT dontWriteAdif; /* use: write ADIF header only before 1st frame */ + + FIXP_DBL *dynamic_RAM; + + + INT maxChannels; /* used while allocation */ + INT maxElements; + INT maxFrames; + + AUDIO_OBJECT_TYPE aot; /* AOT to be used while encoding. */ + +} ; + +#define maxSize(a,b) ( ((a)>(b)) ? (a) : (b) ) + +#define BIT_LOOK_UP_SIZE ( sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)) ) +#define MERGE_GAIN_LOOK_UP_SIZE ( sizeof(INT)*MAX_SFB_LONG ) + + + +/* Dynamic RAM - Allocation */ +/* + ++++++++++++++++++++++++++++++++++++++++++++ + | P_BUF_0 | P_BUF_1 | + ++++++++++++++++++++++++++++++++++++++++++++ + | QC_OUT_CH | PSY_DYN | + ++++++++++++++++++++++++++++++++++++++++++++ + | | BitLookUp+MergeGainLookUp | + ++++++++++++++++++++++++++++++++++++++++++++ + | | Bitstream output buffer | + ++++++++++++++++++++++++++++++++++++++++++++ +*/ + +#define BUF_SIZE_0 ( ALIGN_SIZE(sizeof(QC_OUT_CHANNEL)*(8)) ) +#define BUF_SIZE_1 ( ALIGN_SIZE(maxSize(sizeof(PSY_DYNAMIC), \ + (BIT_LOOK_UP_SIZE+MERGE_GAIN_LOOK_UP_SIZE))) ) + +#define P_BUF_0 ( 0 ) +#define P_BUF_1 ( P_BUF_0 + BUF_SIZE_0 ) + +#define AAC_ENC_DYN_RAM_SIZE ( BUF_SIZE_0 + BUF_SIZE_1 ) + + + H_ALLOC_MEM (AACdynamic_RAM, FIXP_DBL) +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +END - Dynamic RAM - Allocation */ + +/* + See further Memory Allocation details in aacEnc_ram.cpp +*/ + H_ALLOC_MEM (Ram_aacEnc_AacEncoder, AAC_ENC) + + H_ALLOC_MEM (Ram_aacEnc_PsyElement, PSY_ELEMENT) + + H_ALLOC_MEM (Ram_aacEnc_PsyInternal, PSY_INTERNAL) + H_ALLOC_MEM (Ram_aacEnc_PsyStatic, PSY_STATIC) + H_ALLOC_MEM (Ram_aacEnc_PsyInputBuffer, INT_PCM) + + PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic (int n, UCHAR* dynamic_RAM); + H_ALLOC_MEM (Ram_bsOutbuffer, UCHAR) + + H_ALLOC_MEM (Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL) + + H_ALLOC_MEM (Ram_aacEnc_PsyOut, PSY_OUT) + H_ALLOC_MEM (Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT) + + H_ALLOC_MEM (Ram_aacEnc_QCstate, QC_STATE) + H_ALLOC_MEM (Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE) + + H_ALLOC_MEM (Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT) + H_ALLOC_MEM (Ram_aacEnc_ElementBits, ELEMENT_BITS) + H_ALLOC_MEM (Ram_aacEnc_BitCntrState, BITCNTR_STATE) + + INT *GetRam_aacEnc_BitLookUp(int n, UCHAR* dynamic_RAM); + INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR* dynamic_RAM); + QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel (int n, UCHAR* dynamic_RAM); + + H_ALLOC_MEM (Ram_aacEnc_QCout, QC_OUT) + H_ALLOC_MEM (Ram_aacEnc_QCelement, QC_OUT_ELEMENT) + + +#endif /* #ifndef AAC_ENC_RAM_H */ + diff --git a/libAACenc/src/aacEnc_rom.cpp b/libAACenc/src/aacEnc_rom.cpp new file mode 100644 index 00000000..c6477e3b --- /dev/null +++ b/libAACenc/src/aacEnc_rom.cpp @@ -0,0 +1,1232 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/****************************************************************************** + + Initial authors: M. Lohwasser, M. Gayer + Contents/description: + +******************************************************************************/ + +#include "aacEnc_rom.h" + +/* + Huffman Tables +*/ +const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]= +{ + { + { {0x000b0009,0x00090007,0x000b0009}, {0x000a0008,0x00070006,0x000a0008}, {0x000b0009,0x00090008,0x000b0009} }, + { {0x000a0008,0x00070006,0x000a0007}, {0x00070006,0x00050005,0x00070006}, {0x00090007,0x00070006,0x000a0008} }, + { {0x000b0009,0x00090007,0x000b0008}, {0x00090008,0x00070006,0x00090008}, {0x000b0009,0x00090007,0x000b0009} } + }, + { + { {0x00090008,0x00070006,0x00090007}, {0x00070006,0x00050005,0x00070006}, {0x00090007,0x00070006,0x00090008} }, + { {0x00070006,0x00050005,0x00070006}, {0x00050005,0x00010003,0x00050005}, {0x00070006,0x00050005,0x00070006} }, + { {0x00090008,0x00070006,0x00090007}, {0x00070006,0x00050005,0x00070006}, {0x00090008,0x00070006,0x00090008} } + }, + { + { {0x000b0009,0x00090007,0x000b0009}, {0x00090008,0x00070006,0x00090008}, {0x000b0008,0x00090007,0x000b0009} }, + { {0x000a0008,0x00070006,0x00090007}, {0x00070006,0x00050004,0x00070006}, {0x00090008,0x00070006,0x000a0007} }, + { {0x000b0009,0x00090007,0x000b0009}, {0x000a0007,0x00070006,0x00090008}, {0x000b0009,0x00090007,0x000b0009} } + } +}; + + +const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]= +{ + { + { {0x00010004,0x00040005,0x00080008}, {0x00040005,0x00050004,0x00080008}, {0x00090009,0x00090008,0x000a000b} }, + { {0x00040005,0x00060005,0x00090008}, {0x00060005,0x00060004,0x00090008}, {0x00090008,0x00090007,0x000a000a} }, + { {0x00090009,0x000a0008,0x000d000b}, {0x00090008,0x00090008,0x000b000a}, {0x000b000b,0x000a000a,0x000c000b} } + }, + { + { {0x00040004,0x00060005,0x000a0008}, {0x00060004,0x00070004,0x000a0008}, {0x000a0008,0x000a0008,0x000c000a} }, + { {0x00050004,0x00070004,0x000b0008}, {0x00060004,0x00070004,0x000a0007}, {0x00090008,0x00090007,0x000b0009} }, + { {0x00090008,0x000a0008,0x000d000a}, {0x00080007,0x00090007,0x000c0009}, {0x000a000a,0x000b0009,0x000c000a} } + }, + { + { {0x00080008,0x000a0008,0x000f000b}, {0x00090008,0x000b0007,0x000f000a}, {0x000d000b,0x000e000a,0x0010000c} }, + { {0x00080008,0x000a0007,0x000e000a}, {0x00090007,0x000a0007,0x000e0009}, {0x000c000a,0x000c0009,0x000f000b} }, + { {0x000b000b,0x000c000a,0x0010000c}, {0x000a000a,0x000b0009,0x000f000b}, {0x000c000b,0x000c000a,0x000f000b} } + } +}; + +const ULONG FDKaacEnc_huff_ltab5_6[9][9]= +{ + {0x000d000b, 0x000c000a, 0x000b0009, 0x000b0009, 0x000a0009, 0x000b0009, 0x000b0009, 0x000c000a, 0x000d000b}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, 0x000a0008, 0x000b0009, 0x000c000a}, + {0x000c0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, 0x00090006, 0x000a0008, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, 0x00080006, 0x00090007, 0x000b0009}, + {0x000a0009, 0x00080007, 0x00070006, 0x00040004, 0x00010004, 0x00040004, 0x00070006, 0x00080007, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, 0x00080006, 0x00090007, 0x000b0009}, + {0x000b0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, 0x00090006, 0x000a0008, 0x000b0009}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, 0x000a0007, 0x000b0008, 0x000c000a}, + {0x000d000b, 0x000c000a, 0x000c0009, 0x000b0009, 0x000a0009, 0x000a0009, 0x000b0009, 0x000c000a, 0x000d000b} +}; + +const ULONG FDKaacEnc_huff_ltab7_8[8][8]= +{ + {0x00010005, 0x00030004, 0x00060005, 0x00070006, 0x00080007, 0x00090008, 0x000a0009, 0x000b000a}, + {0x00030004, 0x00040003, 0x00060004, 0x00070005, 0x00080006, 0x00080007, 0x00090007, 0x00090008}, + {0x00060005, 0x00060004, 0x00070004, 0x00080005, 0x00080006, 0x00090007, 0x00090007, 0x000a0008}, + {0x00070006, 0x00070005, 0x00080005, 0x00080006, 0x00090006, 0x00090007, 0x000a0008, 0x000a0008}, + {0x00080007, 0x00080006, 0x00090006, 0x00090006, 0x000a0007, 0x000a0007, 0x000a0008, 0x000b0009}, + {0x00090008, 0x00080007, 0x00090006, 0x00090007, 0x000a0007, 0x000a0008, 0x000b0008, 0x000b000a}, + {0x000a0009, 0x00090007, 0x00090007, 0x000a0008, 0x000a0008, 0x000b0008, 0x000c0009, 0x000c0009}, + {0x000b000a, 0x000a0008, 0x000a0008, 0x000a0008, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c000a} +}; + +const ULONG FDKaacEnc_huff_ltab9_10[13][13]= +{ + {0x00010006, 0x00030005, 0x00060006, 0x00080006, 0x00090007, 0x000a0008, 0x000a0009, 0x000b000a, 0x000b000a, 0x000c000a, 0x000c000b, 0x000d000b, 0x000d000c}, + {0x00030005, 0x00040004, 0x00060004, 0x00070005, 0x00080006, 0x00080007, 0x00090007, 0x000a0008, 0x000a0008, 0x000a0009, 0x000b000a, 0x000c000a, 0x000c000b}, + {0x00060006, 0x00060004, 0x00070005, 0x00080005, 0x00080006, 0x00090006, 0x000a0007, 0x000a0008, 0x000a0008, 0x000b0009, 0x000c0009, 0x000c000a, 0x000c000a}, + {0x00080006, 0x00070005, 0x00080005, 0x00090005, 0x00090006, 0x000a0007, 0x000a0007, 0x000b0008, 0x000b0008, 0x000b0009, 0x000c0009, 0x000c000a, 0x000d000a}, + {0x00090007, 0x00080006, 0x00090006, 0x00090006, 0x000a0006, 0x000a0007, 0x000b0007, 0x000b0008, 0x000b0008, 0x000c0009, 0x000c0009, 0x000c000a, 0x000d000a}, + {0x000a0008, 0x00090007, 0x00090006, 0x000a0007, 0x000b0007, 0x000b0007, 0x000b0008, 0x000c0008, 0x000b0008, 0x000c0009, 0x000c000a, 0x000d000a, 0x000d000b}, + {0x000b0009, 0x00090007, 0x000a0007, 0x000b0007, 0x000b0007, 0x000b0008, 0x000c0008, 0x000c0009, 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000c0008, 0x000c0009, 0x000d0009, 0x000d0009, 0x000d000a, 0x000d000a, 0x000d000b, 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000b0008, 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, 0x000e000a, 0x000d000b, 0x000e000b}, + {0x000b000a, 0x000a0009, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, 0x000c0009, 0x000c000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, 0x000e000c}, + {0x000c000a, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, 0x000c000a, 0x000d000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, 0x000e000b, 0x000f000c}, + {0x000c000b, 0x000b000a, 0x000c0009, 0x000c000a, 0x000c000a, 0x000d000a, 0x000d000a, 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000b, 0x000f000b, 0x000f000c}, + {0x000d000b, 0x000c000a, 0x000c000a, 0x000c000a, 0x000d000a, 0x000d000a, 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000c, 0x000e000c, 0x000e000c, 0x000f000c} +}; + +const UCHAR FDKaacEnc_huff_ltab11[17][17]= +{ + {0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0b, 0x0c, 0x0c, 0x0a}, + {0x05, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x06, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x07, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x0a, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0c, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x09}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x05} +}; + +const UCHAR FDKaacEnc_huff_ltabscf[121]= +{ + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x12, 0x13, 0x12, 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0c, 0x0b, 0x0a, 0x0a, + 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x01, 0x04, 0x04, 0x05, + 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, + 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x10, 0x0f, 0x10, 0x0f, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 +}; + + +const USHORT FDKaacEnc_huff_ctab1[3][3][3][3]= +{ + { + { {0x07f8,0x01f1,0x07fd}, {0x03f5,0x0068,0x03f0}, {0x07f7,0x01ec,0x07f5} }, + { {0x03f1,0x0072,0x03f4}, {0x0074,0x0011,0x0076}, {0x01eb,0x006c,0x03f6} }, + { {0x07fc,0x01e1,0x07f1}, {0x01f0,0x0061,0x01f6}, {0x07f2,0x01ea,0x07fb} } + }, + { + { {0x01f2,0x0069,0x01ed}, {0x0077,0x0017,0x006f}, {0x01e6,0x0064,0x01e5} }, + { {0x0067,0x0015,0x0062}, {0x0012,0x0000,0x0014}, {0x0065,0x0016,0x006d} }, + { {0x01e9,0x0063,0x01e4}, {0x006b,0x0013,0x0071}, {0x01e3,0x0070,0x01f3} } + }, + { + { {0x07fe,0x01e7,0x07f3}, {0x01ef,0x0060,0x01ee}, {0x07f0,0x01e2,0x07fa} }, + { {0x03f3,0x006a,0x01e8}, {0x0075,0x0010,0x0073}, {0x01f4,0x006e,0x03f7} }, + { {0x07f6,0x01e0,0x07f9}, {0x03f2,0x0066,0x01f5}, {0x07ff,0x01f7,0x07f4} } + } +}; + +const USHORT FDKaacEnc_huff_ctab2[3][3][3][3]= +{ + { + { {0x01f3,0x006f,0x01fd}, {0x00eb,0x0023,0x00ea}, {0x01f7,0x00e8,0x01fa} }, + { {0x00f2,0x002d,0x0070}, {0x0020,0x0006,0x002b}, {0x006e,0x0028,0x00e9} }, + { {0x01f9,0x0066,0x00f8}, {0x00e7,0x001b,0x00f1}, {0x01f4,0x006b,0x01f5} } + }, + { + { {0x00ec,0x002a,0x006c}, {0x002c,0x000a,0x0027}, {0x0067,0x001a,0x00f5} }, + { {0x0024,0x0008,0x001f}, {0x0009,0x0000,0x0007}, {0x001d,0x000b,0x0030} }, + { {0x00ef,0x001c,0x0064}, {0x001e,0x000c,0x0029}, {0x00f3,0x002f,0x00f0} } + }, + { + { {0x01fc,0x0071,0x01f2}, {0x00f4,0x0021,0x00e6}, {0x00f7,0x0068,0x01f8} }, + { {0x00ee,0x0022,0x0065}, {0x0031,0x0002,0x0026}, {0x00ed,0x0025,0x006a} }, + { {0x01fb,0x0072,0x01fe}, {0x0069,0x002e,0x00f6}, {0x01ff,0x006d,0x01f6} } + } +}; + +const USHORT FDKaacEnc_huff_ctab3[3][3][3][3]= +{ + { + { {0x0000,0x0009,0x00ef}, {0x000b,0x0019,0x00f0}, {0x01eb,0x01e6,0x03f2} }, + { {0x000a,0x0035,0x01ef}, {0x0034,0x0037,0x01e9}, {0x01ed,0x01e7,0x03f3} }, + { {0x01ee,0x03ed,0x1ffa}, {0x01ec,0x01f2,0x07f9}, {0x07f8,0x03f8,0x0ff8} } + }, + { + { {0x0008,0x0038,0x03f6}, {0x0036,0x0075,0x03f1}, {0x03eb,0x03ec,0x0ff4} }, + { {0x0018,0x0076,0x07f4}, {0x0039,0x0074,0x03ef}, {0x01f3,0x01f4,0x07f6} }, + { {0x01e8,0x03ea,0x1ffc}, {0x00f2,0x01f1,0x0ffb}, {0x03f5,0x07f3,0x0ffc} } + }, + { + { {0x00ee,0x03f7,0x7ffe}, {0x01f0,0x07f5,0x7ffd}, {0x1ffb,0x3ffa,0xffff} }, + { {0x00f1,0x03f0,0x3ffc}, {0x01ea,0x03ee,0x3ffb}, {0x0ff6,0x0ffa,0x7ffc} }, + { {0x07f2,0x0ff5,0xfffe}, {0x03f4,0x07f7,0x7ffb}, {0x0ff7,0x0ff9,0x7ffa} } + } +}; + +const USHORT FDKaacEnc_huff_ctab4[3][3][3][3]= +{ + { + { {0x0007,0x0016,0x00f6}, {0x0018,0x0008,0x00ef}, {0x01ef,0x00f3,0x07f8} }, + { {0x0019,0x0017,0x00ed}, {0x0015,0x0001,0x00e2}, {0x00f0,0x0070,0x03f0} }, + { {0x01ee,0x00f1,0x07fa}, {0x00ee,0x00e4,0x03f2}, {0x07f6,0x03ef,0x07fd} } + }, + { + { {0x0005,0x0014,0x00f2}, {0x0009,0x0004,0x00e5}, {0x00f4,0x00e8,0x03f4} }, + { {0x0006,0x0002,0x00e7}, {0x0003,0x0000,0x006b}, {0x00e3,0x0069,0x01f3} }, + { {0x00eb,0x00e6,0x03f6}, {0x006e,0x006a,0x01f4}, {0x03ec,0x01f0,0x03f9} } + }, + { + { {0x00f5,0x00ec,0x07fb}, {0x00ea,0x006f,0x03f7}, {0x07f9,0x03f3,0x0fff} }, + { {0x00e9,0x006d,0x03f8}, {0x006c,0x0068,0x01f5}, {0x03ee,0x01f2,0x07f4} }, + { {0x07f7,0x03f1,0x0ffe}, {0x03ed,0x01f1,0x07f5}, {0x07fe,0x03f5,0x07fc} } + } +}; +const USHORT FDKaacEnc_huff_ctab5[9][9]= +{ + {0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8, 0x1ffd}, + {0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee, 0x07f2, 0x0ffa}, + {0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec, 0x01f0, 0x03ea, 0x07f3}, + {0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008, 0x0019, 0x00ee, 0x01ef, 0x07ed}, + {0x03f0, 0x00f2, 0x0073, 0x000b, 0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9}, + {0x07ef, 0x01ee, 0x00ef, 0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec}, + {0x07f6, 0x03eb, 0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7}, + {0x0ff6, 0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9}, + {0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb, 0x1ffe} +}; + +const USHORT FDKaacEnc_huff_ctab6[9][9]= +{ + {0x07fe, 0x03fd, 0x01f1, 0x01eb, 0x01f4, 0x01ea, 0x01f0, 0x03fc, 0x07fd}, + {0x03f6, 0x01e5, 0x00ea, 0x006c, 0x0071, 0x0068, 0x00f0, 0x01e6, 0x03f7}, + {0x01f3, 0x00ef, 0x0032, 0x0027, 0x0028, 0x0026, 0x0031, 0x00eb, 0x01f7}, + {0x01e8, 0x006f, 0x002e, 0x0008, 0x0004, 0x0006, 0x0029, 0x006b, 0x01ee}, + {0x01ef, 0x0072, 0x002d, 0x0002, 0x0000, 0x0003, 0x002f, 0x0073, 0x01fa}, + {0x01e7, 0x006e, 0x002b, 0x0007, 0x0001, 0x0005, 0x002c, 0x006d, 0x01ec}, + {0x01f9, 0x00ee, 0x0030, 0x0024, 0x002a, 0x0025, 0x0033, 0x00ec, 0x01f2}, + {0x03f8, 0x01e4, 0x00ed, 0x006a, 0x0070, 0x0069, 0x0074, 0x00f1, 0x03fa}, + {0x07ff, 0x03f9, 0x01f6, 0x01ed, 0x01f8, 0x01e9, 0x01f5, 0x03fb, 0x07fc} +}; + +const USHORT FDKaacEnc_huff_ctab7[8][8]= +{ + {0x0000, 0x0005, 0x0037, 0x0074, 0x00f2, 0x01eb, 0x03ed, 0x07f7}, + {0x0004, 0x000c, 0x0035, 0x0071, 0x00ec, 0x00ee, 0x01ee, 0x01f5}, + {0x0036, 0x0034, 0x0072, 0x00ea, 0x00f1, 0x01e9, 0x01f3, 0x03f5}, + {0x0073, 0x0070, 0x00eb, 0x00f0, 0x01f1, 0x01f0, 0x03ec, 0x03fa}, + {0x00f3, 0x00ed, 0x01e8, 0x01ef, 0x03ef, 0x03f1, 0x03f9, 0x07fb}, + {0x01ed, 0x00ef, 0x01ea, 0x01f2, 0x03f3, 0x03f8, 0x07f9, 0x07fc}, + {0x03ee, 0x01ec, 0x01f4, 0x03f4, 0x03f7, 0x07f8, 0x0ffd, 0x0ffe}, + {0x07f6, 0x03f0, 0x03f2, 0x03f6, 0x07fa, 0x07fd, 0x0ffc, 0x0fff} +}; + +const USHORT FDKaacEnc_huff_ctab8[8][8]= +{ + {0x000e, 0x0005, 0x0010, 0x0030, 0x006f, 0x00f1, 0x01fa, 0x03fe}, + {0x0003, 0x0000, 0x0004, 0x0012, 0x002c, 0x006a, 0x0075, 0x00f8}, + {0x000f, 0x0002, 0x0006, 0x0014, 0x002e, 0x0069, 0x0072, 0x00f5}, + {0x002f, 0x0011, 0x0013, 0x002a, 0x0032, 0x006c, 0x00ec, 0x00fa}, + {0x0071, 0x002b, 0x002d, 0x0031, 0x006d, 0x0070, 0x00f2, 0x01f9}, + {0x00ef, 0x0068, 0x0033, 0x006b, 0x006e, 0x00ee, 0x00f9, 0x03fc}, + {0x01f8, 0x0074, 0x0073, 0x00ed, 0x00f0, 0x00f6, 0x01f6, 0x01fd}, + {0x03fd, 0x00f3, 0x00f4, 0x00f7, 0x01f7, 0x01fb, 0x01fc, 0x03ff} +}; + +const USHORT FDKaacEnc_huff_ctab9[13][13]= +{ + {0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8, 0x07cd, 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec}, + {0x0004, 0x000c, 0x0035, 0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, 0x03e0, 0x07d8, 0x0fcf, 0x0fd5}, + {0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1, 0x03cf, 0x03dd, 0x03db, 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4}, + {0x00e6, 0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca, 0x07de, 0x0fd8, 0x0fea, 0x1fdb}, + {0x01df, 0x00eb, 0x01dc, 0x01e6, 0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, 0x0fcd, 0x0fe2, 0x0fe7, 0x1fe1}, + {0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db, 0x0fd2, 0x07e0, 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9}, + {0x07c4, 0x01e5, 0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, 0x0fe9, 0x1fe6, 0x1ff3, 0x1ff7}, + {0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9, 0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6}, + {0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb, 0x1fd8, 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2}, + {0x07e1, 0x03df, 0x07c9, 0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, 0x1fef, 0x3ff3, 0x3ff4, 0x3ff5}, + {0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1, 0x1fe0, 0x1fe8, 0x1ff0, 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc}, + {0x0fe8, 0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5, 0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe}, + {0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf, 0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, 0x3ff7, 0x3ffc, 0x3ffd, 0x7fff} +}; + +const USHORT FDKaacEnc_huff_ctab10[13][13]= +{ + {0x0022, 0x0008, 0x001d, 0x0026, 0x005f, 0x00d3, 0x01cf, 0x03d0, 0x03d7, 0x03ed, 0x07f0, 0x07f6, 0x0ffd}, + {0x0007, 0x0000, 0x0001, 0x0009, 0x0020, 0x0054, 0x0060, 0x00d5, 0x00dc, 0x01d4, 0x03cd, 0x03de, 0x07e7}, + {0x001c, 0x0002, 0x0006, 0x000c, 0x001e, 0x0028, 0x005b, 0x00cd, 0x00d9, 0x01ce, 0x01dc, 0x03d9, 0x03f1}, + {0x0025, 0x000b, 0x000a, 0x000d, 0x0024, 0x0057, 0x0061, 0x00cc, 0x00dd, 0x01cc, 0x01de, 0x03d3, 0x03e7}, + {0x005d, 0x0021, 0x001f, 0x0023, 0x0027, 0x0059, 0x0064, 0x00d8, 0x00df, 0x01d2, 0x01e2, 0x03dd, 0x03ee}, + {0x00d1, 0x0055, 0x0029, 0x0056, 0x0058, 0x0062, 0x00ce, 0x00e0, 0x00e2, 0x01da, 0x03d4, 0x03e3, 0x07eb}, + {0x01c9, 0x005e, 0x005a, 0x005c, 0x0063, 0x00ca, 0x00da, 0x01c7, 0x01ca, 0x01e0, 0x03db, 0x03e8, 0x07ec}, + {0x01e3, 0x00d2, 0x00cb, 0x00d0, 0x00d7, 0x00db, 0x01c6, 0x01d5, 0x01d8, 0x03ca, 0x03da, 0x07ea, 0x07f1}, + {0x01e1, 0x00d4, 0x00cf, 0x00d6, 0x00de, 0x00e1, 0x01d0, 0x01d6, 0x03d1, 0x03d5, 0x03f2, 0x07ee, 0x07fb}, + {0x03e9, 0x01cd, 0x01c8, 0x01cb, 0x01d1, 0x01d7, 0x01df, 0x03cf, 0x03e0, 0x03ef, 0x07e6, 0x07f8, 0x0ffa}, + {0x03eb, 0x01dd, 0x01d3, 0x01d9, 0x01db, 0x03d2, 0x03cc, 0x03dc, 0x03ea, 0x07ed, 0x07f3, 0x07f9, 0x0ff9}, + {0x07f2, 0x03ce, 0x01e4, 0x03cb, 0x03d8, 0x03d6, 0x03e2, 0x03e5, 0x07e8, 0x07f4, 0x07f5, 0x07f7, 0x0ffb}, + {0x07fa, 0x03ec, 0x03df, 0x03e1, 0x03e4, 0x03e6, 0x03f0, 0x07e9, 0x07ef, 0x0ff8, 0x0ffe, 0x0ffc, 0x0fff} +}; + +const USHORT FDKaacEnc_huff_ctab11[21][17]= +{ + {0x0000, 0x0006, 0x0019, 0x003d, 0x009c, 0x00c6, 0x01a7, 0x0390, 0x03c2, 0x03df, 0x07e6, 0x07f3, 0x0ffb, 0x07ec, 0x0ffa, 0x0ffe, 0x038e}, + {0x0005, 0x0001, 0x0008, 0x0014, 0x0037, 0x0042, 0x0092, 0x00af, 0x0191, 0x01a5, 0x01b5, 0x039e, 0x03c0, 0x03a2, 0x03cd, 0x07d6, 0x00ae}, + {0x0017, 0x0007, 0x0009, 0x0018, 0x0039, 0x0040, 0x008e, 0x00a3, 0x00b8, 0x0199, 0x01ac, 0x01c1, 0x03b1, 0x0396, 0x03be, 0x03ca, 0x009d}, + {0x003c, 0x0015, 0x0016, 0x001a, 0x003b, 0x0044, 0x0091, 0x00a5, 0x00be, 0x0196, 0x01ae, 0x01b9, 0x03a1, 0x0391, 0x03a5, 0x03d5, 0x0094}, + {0x009a, 0x0036, 0x0038, 0x003a, 0x0041, 0x008c, 0x009b, 0x00b0, 0x00c3, 0x019e, 0x01ab, 0x01bc, 0x039f, 0x038f, 0x03a9, 0x03cf, 0x0093}, + {0x00bf, 0x003e, 0x003f, 0x0043, 0x0045, 0x009e, 0x00a7, 0x00b9, 0x0194, 0x01a2, 0x01ba, 0x01c3, 0x03a6, 0x03a7, 0x03bb, 0x03d4, 0x009f}, + {0x01a0, 0x008f, 0x008d, 0x0090, 0x0098, 0x00a6, 0x00b6, 0x00c4, 0x019f, 0x01af, 0x01bf, 0x0399, 0x03bf, 0x03b4, 0x03c9, 0x03e7, 0x00a8}, + {0x01b6, 0x00ab, 0x00a4, 0x00aa, 0x00b2, 0x00c2, 0x00c5, 0x0198, 0x01a4, 0x01b8, 0x038c, 0x03a4, 0x03c4, 0x03c6, 0x03dd, 0x03e8, 0x00ad}, + {0x03af, 0x0192, 0x00bd, 0x00bc, 0x018e, 0x0197, 0x019a, 0x01a3, 0x01b1, 0x038d, 0x0398, 0x03b7, 0x03d3, 0x03d1, 0x03db, 0x07dd, 0x00b4}, + {0x03de, 0x01a9, 0x019b, 0x019c, 0x01a1, 0x01aa, 0x01ad, 0x01b3, 0x038b, 0x03b2, 0x03b8, 0x03ce, 0x03e1, 0x03e0, 0x07d2, 0x07e5, 0x00b7}, + {0x07e3, 0x01bb, 0x01a8, 0x01a6, 0x01b0, 0x01b2, 0x01b7, 0x039b, 0x039a, 0x03ba, 0x03b5, 0x03d6, 0x07d7, 0x03e4, 0x07d8, 0x07ea, 0x00ba}, + {0x07e8, 0x03a0, 0x01bd, 0x01b4, 0x038a, 0x01c4, 0x0392, 0x03aa, 0x03b0, 0x03bc, 0x03d7, 0x07d4, 0x07dc, 0x07db, 0x07d5, 0x07f0, 0x00c1}, + {0x07fb, 0x03c8, 0x03a3, 0x0395, 0x039d, 0x03ac, 0x03ae, 0x03c5, 0x03d8, 0x03e2, 0x03e6, 0x07e4, 0x07e7, 0x07e0, 0x07e9, 0x07f7, 0x0190}, + {0x07f2, 0x0393, 0x01be, 0x01c0, 0x0394, 0x0397, 0x03ad, 0x03c3, 0x03c1, 0x03d2, 0x07da, 0x07d9, 0x07df, 0x07eb, 0x07f4, 0x07fa, 0x0195}, + {0x07f8, 0x03bd, 0x039c, 0x03ab, 0x03a8, 0x03b3, 0x03b9, 0x03d0, 0x03e3, 0x03e5, 0x07e2, 0x07de, 0x07ed, 0x07f1, 0x07f9, 0x07fc, 0x0193}, + {0x0ffd, 0x03dc, 0x03b6, 0x03c7, 0x03cc, 0x03cb, 0x03d9, 0x03da, 0x07d3, 0x07e1, 0x07ee, 0x07ef, 0x07f5, 0x07f6, 0x0ffc, 0x0fff, 0x019d}, + {0x01c2, 0x00b5, 0x00a1, 0x0096, 0x0097, 0x0095, 0x0099, 0x00a0, 0x00a2, 0x00ac, 0x00a9, 0x00b1, 0x00b3, 0x00bb, 0x00c0, 0x018f, 0x0004}, + {0x0018, 0x002e, 0x0000, 0x005a, 0x00a5, 0x00f8, 0x00b7, 0x0094, 0x00f9, 0x004d, 0x0021, 0x002b, 0x004f, 0x007b, 0x00bc, 0x0046, 0x0015}, + {0x0042, 0x0037, 0x0078, 0x000d, 0x0068, 0x005f, 0x000d, 0x005e, 0x005a, 0x00be, 0x0063, 0x007e, 0x001f, 0x0092, 0x001a, 0x00ab, 0x0032}, + {0x00e6, 0x0037, 0x0000, 0x0058, 0x000b, 0x005a, 0x00e1, 0x005d, 0x0029, 0x0017, 0x007e, 0x0069, 0x00aa, 0x0054, 0x0029, 0x0032, 0x0041}, + {0x0046, 0x00ea, 0x0034, 0x00ea, 0x0011, 0x001b, 0x00a9, 0x0094, 0x00e2, 0x0031, 0x00d0, 0x00e5, 0x0007, 0x0070, 0x0069, 0x003e, 0x0021} +}; + +const ULONG FDKaacEnc_huff_ctabscf[121]= +{ + 0x0003ffe8, 0x0003ffe6, 0x0003ffe7, 0x0003ffe5, 0x0007fff5, 0x0007fff1, 0x0007ffed, 0x0007fff6, + 0x0007ffee, 0x0007ffef, 0x0007fff0, 0x0007fffc, 0x0007fffd, 0x0007ffff, 0x0007fffe, 0x0007fff7, + 0x0007fff8, 0x0007fffb, 0x0007fff9, 0x0003ffe4, 0x0007fffa, 0x0003ffe3, 0x0001ffef, 0x0001fff0, + 0x0000fff5, 0x0001ffee, 0x0000fff2, 0x0000fff3, 0x0000fff4, 0x0000fff1, 0x00007ff6, 0x00007ff7, + 0x00003ff9, 0x00003ff5, 0x00003ff7, 0x00003ff3, 0x00003ff6, 0x00003ff2, 0x00001ff7, 0x00001ff5, + 0x00000ff9, 0x00000ff7, 0x00000ff6, 0x000007f9, 0x00000ff4, 0x000007f8, 0x000003f9, 0x000003f7, + 0x000003f5, 0x000001f8, 0x000001f7, 0x000000fa, 0x000000f8, 0x000000f6, 0x00000079, 0x0000003a, + 0x00000038, 0x0000001a, 0x0000000b, 0x00000004, 0x00000000, 0x0000000a, 0x0000000c, 0x0000001b, + 0x00000039, 0x0000003b, 0x00000078, 0x0000007a, 0x000000f7, 0x000000f9, 0x000001f6, 0x000001f9, + 0x000003f4, 0x000003f6, 0x000003f8, 0x000007f5, 0x000007f4, 0x000007f6, 0x000007f7, 0x00000ff5, + 0x00000ff8, 0x00001ff4, 0x00001ff6, 0x00001ff8, 0x00003ff8, 0x00003ff4, 0x0000fff0, 0x00007ff4, + 0x0000fff6, 0x00007ff5, 0x0003ffe2, 0x0007ffd9, 0x0007ffda, 0x0007ffdb, 0x0007ffdc, 0x0007ffdd, + 0x0007ffde, 0x0007ffd8, 0x0007ffd2, 0x0007ffd3, 0x0007ffd4, 0x0007ffd5, 0x0007ffd6, 0x0007fff2, + 0x0007ffdf, 0x0007ffe7, 0x0007ffe8, 0x0007ffe9, 0x0007ffea, 0x0007ffeb, 0x0007ffe6, 0x0007ffe0, + 0x0007ffe1, 0x0007ffe2, 0x0007ffe3, 0x0007ffe4, 0x0007ffe5, 0x0007ffd7, 0x0007ffec, 0x0007fff4, + 0x0007fff3 +}; + +/* + table of (0.50000...1.00000) ^0.75 +*/ +const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE] = +{ + QTC(0x4c1bf829), QTC(0x4c3880de), QTC(0x4c550603), QTC(0x4c71879c), QTC(0x4c8e05aa), QTC(0x4caa8030), QTC(0x4cc6f72f), QTC(0x4ce36aab), + QTC(0x4cffdaa4), QTC(0x4d1c471d), QTC(0x4d38b019), QTC(0x4d55159a), QTC(0x4d7177a1), QTC(0x4d8dd631), QTC(0x4daa314b), QTC(0x4dc688f3), + QTC(0x4de2dd2a), QTC(0x4dff2df2), QTC(0x4e1b7b4d), QTC(0x4e37c53d), QTC(0x4e540bc5), QTC(0x4e704ee6), QTC(0x4e8c8ea3), QTC(0x4ea8cafd), + QTC(0x4ec503f7), QTC(0x4ee13992), QTC(0x4efd6bd0), QTC(0x4f199ab4), QTC(0x4f35c640), QTC(0x4f51ee75), QTC(0x4f6e1356), QTC(0x4f8a34e4), + QTC(0x4fa65321), QTC(0x4fc26e10), QTC(0x4fde85b2), QTC(0x4ffa9a0a), QTC(0x5016ab18), QTC(0x5032b8e0), QTC(0x504ec362), QTC(0x506acaa1), + QTC(0x5086cea0), QTC(0x50a2cf5e), QTC(0x50becce0), QTC(0x50dac725), QTC(0x50f6be31), QTC(0x5112b205), QTC(0x512ea2a3), QTC(0x514a900d), + QTC(0x51667a45), QTC(0x5182614c), QTC(0x519e4524), QTC(0x51ba25cf), QTC(0x51d60350), QTC(0x51f1dda7), QTC(0x520db4d6), QTC(0x522988e0), + QTC(0x524559c6), QTC(0x52612789), QTC(0x527cf22d), QTC(0x5298b9b1), QTC(0x52b47e19), QTC(0x52d03f65), QTC(0x52ebfd98), QTC(0x5307b8b4), + QTC(0x532370b9), QTC(0x533f25aa), QTC(0x535ad789), QTC(0x53768656), QTC(0x53923215), QTC(0x53addac6), QTC(0x53c9806b), QTC(0x53e52306), + QTC(0x5400c298), QTC(0x541c5f24), QTC(0x5437f8ab), QTC(0x54538f2e), QTC(0x546f22af), QTC(0x548ab330), QTC(0x54a640b3), QTC(0x54c1cb38), + QTC(0x54dd52c2), QTC(0x54f8d753), QTC(0x551458eb), QTC(0x552fd78d), QTC(0x554b5339), QTC(0x5566cbf3), QTC(0x558241bb), QTC(0x559db492), + QTC(0x55b9247b), QTC(0x55d49177), QTC(0x55effb87), QTC(0x560b62ad), QTC(0x5626c6eb), QTC(0x56422842), QTC(0x565d86b4), QTC(0x5678e242), + QTC(0x56943aee), QTC(0x56af90b9), QTC(0x56cae3a4), QTC(0x56e633b2), QTC(0x570180e4), QTC(0x571ccb3b), QTC(0x573812b8), QTC(0x5753575e), + QTC(0x576e992e), QTC(0x5789d829), QTC(0x57a51450), QTC(0x57c04da6), QTC(0x57db842b), QTC(0x57f6b7e1), QTC(0x5811e8c9), QTC(0x582d16e6), + QTC(0x58484238), QTC(0x58636ac0), QTC(0x587e9081), QTC(0x5899b37c), QTC(0x58b4d3b1), QTC(0x58cff123), QTC(0x58eb0bd3), QTC(0x590623c2), + QTC(0x592138f2), QTC(0x593c4b63), QTC(0x59575b19), QTC(0x59726812), QTC(0x598d7253), QTC(0x59a879da), QTC(0x59c37eab), QTC(0x59de80c6), + QTC(0x59f9802d), QTC(0x5a147ce0), QTC(0x5a2f76e2), QTC(0x5a4a6e34), QTC(0x5a6562d6), QTC(0x5a8054cb), QTC(0x5a9b4414), QTC(0x5ab630b2), + QTC(0x5ad11aa6), QTC(0x5aec01f1), QTC(0x5b06e696), QTC(0x5b21c895), QTC(0x5b3ca7ef), QTC(0x5b5784a6), QTC(0x5b725ebc), QTC(0x5b8d3631), + QTC(0x5ba80b06), QTC(0x5bc2dd3e), QTC(0x5bddacd9), QTC(0x5bf879d8), QTC(0x5c13443d), QTC(0x5c2e0c09), QTC(0x5c48d13e), QTC(0x5c6393dc), + QTC(0x5c7e53e5), QTC(0x5c99115a), QTC(0x5cb3cc3c), QTC(0x5cce848d), QTC(0x5ce93a4e), QTC(0x5d03ed80), QTC(0x5d1e9e24), QTC(0x5d394c3b), + QTC(0x5d53f7c7), QTC(0x5d6ea0c9), QTC(0x5d894742), QTC(0x5da3eb33), QTC(0x5dbe8c9e), QTC(0x5dd92b84), QTC(0x5df3c7e5), QTC(0x5e0e61c3), + QTC(0x5e28f920), QTC(0x5e438dfc), QTC(0x5e5e2059), QTC(0x5e78b037), QTC(0x5e933d99), QTC(0x5eadc87e), QTC(0x5ec850e9), QTC(0x5ee2d6da), + QTC(0x5efd5a53), QTC(0x5f17db54), QTC(0x5f3259e0), QTC(0x5f4cd5f6), QTC(0x5f674f99), QTC(0x5f81c6c8), QTC(0x5f9c3b87), QTC(0x5fb6add4), + QTC(0x5fd11db3), QTC(0x5feb8b23), QTC(0x6005f626), QTC(0x60205ebd), QTC(0x603ac4e9), QTC(0x605528ac), QTC(0x606f8a05), QTC(0x6089e8f7), + QTC(0x60a44583), QTC(0x60be9fa9), QTC(0x60d8f76b), QTC(0x60f34cca), QTC(0x610d9fc7), QTC(0x6127f062), QTC(0x61423e9e), QTC(0x615c8a7a), + QTC(0x6176d3f9), QTC(0x61911b1b), QTC(0x61ab5fe1), QTC(0x61c5a24d), QTC(0x61dfe25f), QTC(0x61fa2018), QTC(0x62145b7a), QTC(0x622e9485), + QTC(0x6248cb3b), QTC(0x6262ff9d), QTC(0x627d31ab), QTC(0x62976167), QTC(0x62b18ed1), QTC(0x62cbb9eb), QTC(0x62e5e2b6), QTC(0x63000933), + QTC(0x631a2d62), QTC(0x63344f45), QTC(0x634e6edd), QTC(0x63688c2b), QTC(0x6382a730), QTC(0x639cbfec), QTC(0x63b6d661), QTC(0x63d0ea90), + QTC(0x63eafc7a), QTC(0x64050c1f), QTC(0x641f1982), QTC(0x643924a2), QTC(0x64532d80), QTC(0x646d341f), QTC(0x6487387e), QTC(0x64a13a9e), + QTC(0x64bb3a81), QTC(0x64d53828), QTC(0x64ef3393), QTC(0x65092cc4), QTC(0x652323bb), QTC(0x653d1879), QTC(0x65570b00), QTC(0x6570fb50), + QTC(0x658ae96b), QTC(0x65a4d550), QTC(0x65bebf01), QTC(0x65d8a680), QTC(0x65f28bcc), QTC(0x660c6ee8), QTC(0x66264fd3), QTC(0x66402e8f), + QTC(0x665a0b1c), QTC(0x6673e57d), QTC(0x668dbdb0), QTC(0x66a793b8), QTC(0x66c16795), QTC(0x66db3949), QTC(0x66f508d4), QTC(0x670ed636), + QTC(0x6728a172), QTC(0x67426a87), QTC(0x675c3177), QTC(0x6775f643), QTC(0x678fb8eb), QTC(0x67a97971), QTC(0x67c337d5), QTC(0x67dcf418), + QTC(0x67f6ae3b), QTC(0x6810663f), QTC(0x682a1c25), QTC(0x6843cfed), QTC(0x685d8199), QTC(0x68773129), QTC(0x6890de9f), QTC(0x68aa89fa), + QTC(0x68c4333d), QTC(0x68ddda67), QTC(0x68f77f7a), QTC(0x69112277), QTC(0x692ac35e), QTC(0x69446230), QTC(0x695dfeee), QTC(0x6977999a), + QTC(0x69913232), QTC(0x69aac8ba), QTC(0x69c45d31), QTC(0x69ddef98), QTC(0x69f77ff0), QTC(0x6a110e3a), QTC(0x6a2a9a77), QTC(0x6a4424a8), + QTC(0x6a5daccc), QTC(0x6a7732e6), QTC(0x6a90b6f6), QTC(0x6aaa38fd), QTC(0x6ac3b8fb), QTC(0x6add36f2), QTC(0x6af6b2e2), QTC(0x6b102ccd), + QTC(0x6b29a4b2), QTC(0x6b431a92), QTC(0x6b5c8e6f), QTC(0x6b76004a), QTC(0x6b8f7022), QTC(0x6ba8ddf9), QTC(0x6bc249d0), QTC(0x6bdbb3a7), + QTC(0x6bf51b80), QTC(0x6c0e815a), QTC(0x6c27e537), QTC(0x6c414718), QTC(0x6c5aa6fd), QTC(0x6c7404e7), QTC(0x6c8d60d7), QTC(0x6ca6bace), + QTC(0x6cc012cc), QTC(0x6cd968d2), QTC(0x6cf2bce1), QTC(0x6d0c0ef9), QTC(0x6d255f1d), QTC(0x6d3ead4b), QTC(0x6d57f985), QTC(0x6d7143cc), + QTC(0x6d8a8c21), QTC(0x6da3d283), QTC(0x6dbd16f5), QTC(0x6dd65976), QTC(0x6def9a08), QTC(0x6e08d8ab), QTC(0x6e221560), QTC(0x6e3b5027), + QTC(0x6e548902), QTC(0x6e6dbff1), QTC(0x6e86f4f5), QTC(0x6ea0280e), QTC(0x6eb9593e), QTC(0x6ed28885), QTC(0x6eebb5e3), QTC(0x6f04e15a), + QTC(0x6f1e0aea), QTC(0x6f373294), QTC(0x6f505859), QTC(0x6f697c39), QTC(0x6f829e35), QTC(0x6f9bbe4e), QTC(0x6fb4dc85), QTC(0x6fcdf8d9), + QTC(0x6fe7134d), QTC(0x70002be0), QTC(0x70194293), QTC(0x70325767), QTC(0x704b6a5d), QTC(0x70647b76), QTC(0x707d8ab1), QTC(0x70969811), + QTC(0x70afa394), QTC(0x70c8ad3d), QTC(0x70e1b50c), QTC(0x70fabb01), QTC(0x7113bf1d), QTC(0x712cc161), QTC(0x7145c1ce), QTC(0x715ec064), + QTC(0x7177bd24), QTC(0x7190b80f), QTC(0x71a9b124), QTC(0x71c2a866), QTC(0x71db9dd4), QTC(0x71f49170), QTC(0x720d8339), QTC(0x72267331), + QTC(0x723f6159), QTC(0x72584db0), QTC(0x72713838), QTC(0x728a20f1), QTC(0x72a307db), QTC(0x72bbecf9), QTC(0x72d4d049), QTC(0x72edb1ce), + QTC(0x73069187), QTC(0x731f6f75), QTC(0x73384b98), QTC(0x735125f3), QTC(0x7369fe84), QTC(0x7382d54d), QTC(0x739baa4e), QTC(0x73b47d89), + QTC(0x73cd4efd), QTC(0x73e61eab), QTC(0x73feec94), QTC(0x7417b8b8), QTC(0x74308319), QTC(0x74494bb6), QTC(0x74621291), QTC(0x747ad7aa), + QTC(0x74939b02), QTC(0x74ac5c98), QTC(0x74c51c6f), QTC(0x74ddda86), QTC(0x74f696de), QTC(0x750f5178), QTC(0x75280a54), QTC(0x7540c174), + QTC(0x755976d7), QTC(0x75722a7e), QTC(0x758adc69), QTC(0x75a38c9b), QTC(0x75bc3b12), QTC(0x75d4e7cf), QTC(0x75ed92d4), QTC(0x76063c21), + QTC(0x761ee3b6), QTC(0x76378994), QTC(0x76502dbc), QTC(0x7668d02e), QTC(0x768170eb), QTC(0x769a0ff3), QTC(0x76b2ad47), QTC(0x76cb48e7), + QTC(0x76e3e2d5), QTC(0x76fc7b10), QTC(0x7715119a), QTC(0x772da673), QTC(0x7746399b), QTC(0x775ecb13), QTC(0x77775adc), QTC(0x778fe8f6), + QTC(0x77a87561), QTC(0x77c1001f), QTC(0x77d98930), QTC(0x77f21095), QTC(0x780a964d), QTC(0x78231a5b), QTC(0x783b9cbd), QTC(0x78541d75), + QTC(0x786c9c84), QTC(0x788519e9), QTC(0x789d95a6), QTC(0x78b60fbb), QTC(0x78ce8828), QTC(0x78e6feef), QTC(0x78ff740f), QTC(0x7917e78a), + QTC(0x7930595f), QTC(0x7948c990), QTC(0x7961381d), QTC(0x7979a506), QTC(0x7992104c), QTC(0x79aa79f0), QTC(0x79c2e1f1), QTC(0x79db4852), + QTC(0x79f3ad11), QTC(0x7a0c1031), QTC(0x7a2471b0), QTC(0x7a3cd191), QTC(0x7a552fd3), QTC(0x7a6d8c76), QTC(0x7a85e77d), QTC(0x7a9e40e6), + QTC(0x7ab698b2), QTC(0x7aceeee3), QTC(0x7ae74378), QTC(0x7aff9673), QTC(0x7b17e7d2), QTC(0x7b303799), QTC(0x7b4885c5), QTC(0x7b60d259), + QTC(0x7b791d55), QTC(0x7b9166b9), QTC(0x7ba9ae86), QTC(0x7bc1f4bc), QTC(0x7bda395c), QTC(0x7bf27c66), QTC(0x7c0abddb), QTC(0x7c22fdbb), + QTC(0x7c3b3c07), QTC(0x7c5378c0), QTC(0x7c6bb3e5), QTC(0x7c83ed78), QTC(0x7c9c2579), QTC(0x7cb45be9), QTC(0x7ccc90c7), QTC(0x7ce4c414), + QTC(0x7cfcf5d2), QTC(0x7d152600), QTC(0x7d2d549f), QTC(0x7d4581b0), QTC(0x7d5dad32), QTC(0x7d75d727), QTC(0x7d8dff8f), QTC(0x7da6266a), + QTC(0x7dbe4bba), QTC(0x7dd66f7d), QTC(0x7dee91b6), QTC(0x7e06b264), QTC(0x7e1ed188), QTC(0x7e36ef22), QTC(0x7e4f0b34), QTC(0x7e6725bd), + QTC(0x7e7f3ebd), QTC(0x7e975636), QTC(0x7eaf6c28), QTC(0x7ec78093), QTC(0x7edf9378), QTC(0x7ef7a4d7), QTC(0x7f0fb4b1), QTC(0x7f27c307), + QTC(0x7f3fcfd8), QTC(0x7f57db25), QTC(0x7f6fe4ef), QTC(0x7f87ed36), QTC(0x7f9ff3fb), QTC(0x7fb7f93e), QTC(0x7fcffcff), QTC(0x7fe7ff40) +}; + +/* + table of pow(2.0,0.25*q)/2.0, q[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableQ[4] = { QTC(0x40000000), QTC(0x4c1bf7ff), QTC(0x5a82797f), QTC(0x6ba27e7f) }; + +/* + table of pow(2.0,0.75*e)/8.0, e[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableE[4] = { QTC(0x10000000), QTC(0x1ae89f99), QTC(0x2d413ccd), QTC(0x4c1bf828) }; + + +/* + table to count used number of bits +*/ +const SHORT FDKaacEnc_sideInfoTabLong[MAX_SFB_LONG + 1] = +{ + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e +}; + + +const SHORT FDKaacEnc_sideInfoTabShort[MAX_SFB_SHORT + 1] = +{ + 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000d, 0x000d +}; + + + + + + +/* + Psy Configuration constants +*/ + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024 = { + 40, + { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 16, + 20, 20, 20, 20, 24, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024 = { + 43, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, + 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024 = { + 43, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, + 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024 = { + 43, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, + 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024 = { + 47, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, + 52, 52, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024 = { + 47, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, + 52, 52, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024 = { + 51, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 96 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 96 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024 = { + 47, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, + 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024 = { + 41, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 } +}; +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024 = { + 41, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36 } +}; + + +/* + TNS filter coefficients +*/ + +/* + 3 bit resolution +*/ +const FIXP_DBL FDKaacEnc_tnsEncCoeff3[8]= +{ + (FIXP_DBL)0x81f1d201, (FIXP_DBL)0x91261481, (FIXP_DBL)0xadb92301, (FIXP_DBL)0xd438af00, (FIXP_DBL)0x00000000, (FIXP_DBL)0x37898080, (FIXP_DBL)0x64130dff, (FIXP_DBL)0x7cca6fff +}; +const FIXP_DBL FDKaacEnc_tnsCoeff3Borders[8]={ + (FIXP_DBL)0x80000001 /*-4*/, (FIXP_DBL)0x87b826df /*-3*/, (FIXP_DBL)0x9df24154 /*-2*/, (FIXP_DBL)0xbfffffe5 /*-1*/, + (FIXP_DBL)0xe9c5e578 /* 0*/, (FIXP_DBL)0x1c7b90f0 /* 1*/, (FIXP_DBL)0x4fce83a9 /* 2*/, (FIXP_DBL)0x7352f2c3 /* 3*/ +}; + +/* + 4 bit resolution +*/ +const FIXP_DBL FDKaacEnc_tnsEncCoeff4[16]= +{ + (FIXP_DBL)0x808bc881, (FIXP_DBL)0x84e2e581, (FIXP_DBL)0x8d6b4a01, (FIXP_DBL)0x99da9201, (FIXP_DBL)0xa9c45701, (FIXP_DBL)0xbc9dde81, (FIXP_DBL)0xd1c2d500, (FIXP_DBL)0xe87ae540, + (FIXP_DBL)0x00000000, (FIXP_DBL)0x1a9cd9c0, (FIXP_DBL)0x340ff240, (FIXP_DBL)0x4b3c8bff, (FIXP_DBL)0x5f1f5e7f, (FIXP_DBL)0x6ed9eb7f, (FIXP_DBL)0x79bc387f, (FIXP_DBL)0x7f4c7e7f +}; +const FIXP_DBL FDKaacEnc_tnsCoeff4Borders[16]= +{ + (FIXP_DBL)0x80000001 /*-8*/, (FIXP_DBL)0x822deff0 /*-7*/, (FIXP_DBL)0x88a4bfe6 /*-6*/, (FIXP_DBL)0x932c159d /*-5*/, + (FIXP_DBL)0xa16827c2 /*-4*/, (FIXP_DBL)0xb2dcde27 /*-3*/, (FIXP_DBL)0xc6f20b91 /*-2*/, (FIXP_DBL)0xdcf89c64 /*-1*/, + (FIXP_DBL)0xf4308ce1 /* 0*/, (FIXP_DBL)0x0d613054 /* 1*/, (FIXP_DBL)0x278dde80 /* 2*/, (FIXP_DBL)0x4000001b /* 3*/, + (FIXP_DBL)0x55a6127b /* 4*/, (FIXP_DBL)0x678dde8f /* 5*/, (FIXP_DBL)0x74ef0ed7 /* 6*/, (FIXP_DBL)0x7d33f0da /* 7*/ +}; +const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512]={ + FL2FXCONST_DBL(0.3968502629920499),FL2FXCONST_DBL(0.3978840634868335),FL2FXCONST_DBL(0.3989185359354711),FL2FXCONST_DBL(0.3999536794661432), + FL2FXCONST_DBL(0.4009894932098531),FL2FXCONST_DBL(0.4020259763004115),FL2FXCONST_DBL(0.4030631278744227),FL2FXCONST_DBL(0.4041009470712695), + FL2FXCONST_DBL(0.4051394330330996),FL2FXCONST_DBL(0.4061785849048110),FL2FXCONST_DBL(0.4072184018340380),FL2FXCONST_DBL(0.4082588829711372), + FL2FXCONST_DBL(0.4093000274691739),FL2FXCONST_DBL(0.4103418344839078),FL2FXCONST_DBL(0.4113843031737798),FL2FXCONST_DBL(0.4124274326998980), + FL2FXCONST_DBL(0.4134712222260245),FL2FXCONST_DBL(0.4145156709185620),FL2FXCONST_DBL(0.4155607779465400),FL2FXCONST_DBL(0.4166065424816022), + FL2FXCONST_DBL(0.4176529636979932),FL2FXCONST_DBL(0.4187000407725452),FL2FXCONST_DBL(0.4197477728846652),FL2FXCONST_DBL(0.4207961592163222), + FL2FXCONST_DBL(0.4218451989520345),FL2FXCONST_DBL(0.4228948912788567),FL2FXCONST_DBL(0.4239452353863673),FL2FXCONST_DBL(0.4249962304666564), + FL2FXCONST_DBL(0.4260478757143130),FL2FXCONST_DBL(0.4271001703264124),FL2FXCONST_DBL(0.4281531135025046),FL2FXCONST_DBL(0.4292067044446017), + FL2FXCONST_DBL(0.4302609423571658),FL2FXCONST_DBL(0.4313158264470970),FL2FXCONST_DBL(0.4323713559237216),FL2FXCONST_DBL(0.4334275299987803), + FL2FXCONST_DBL(0.4344843478864161),FL2FXCONST_DBL(0.4355418088031630),FL2FXCONST_DBL(0.4365999119679339),FL2FXCONST_DBL(0.4376586566020096), + FL2FXCONST_DBL(0.4387180419290272),FL2FXCONST_DBL(0.4397780671749683),FL2FXCONST_DBL(0.4408387315681480),FL2FXCONST_DBL(0.4419000343392039), + FL2FXCONST_DBL(0.4429619747210847),FL2FXCONST_DBL(0.4440245519490388),FL2FXCONST_DBL(0.4450877652606038),FL2FXCONST_DBL(0.4461516138955953), + FL2FXCONST_DBL(0.4472160970960963),FL2FXCONST_DBL(0.4482812141064458),FL2FXCONST_DBL(0.4493469641732286),FL2FXCONST_DBL(0.4504133465452648), + FL2FXCONST_DBL(0.4514803604735984),FL2FXCONST_DBL(0.4525480052114875),FL2FXCONST_DBL(0.4536162800143939),FL2FXCONST_DBL(0.4546851841399719), + FL2FXCONST_DBL(0.4557547168480591),FL2FXCONST_DBL(0.4568248774006652),FL2FXCONST_DBL(0.4578956650619623),FL2FXCONST_DBL(0.4589670790982746), + FL2FXCONST_DBL(0.4600391187780688),FL2FXCONST_DBL(0.4611117833719430),FL2FXCONST_DBL(0.4621850721526184),FL2FXCONST_DBL(0.4632589843949278), + FL2FXCONST_DBL(0.4643335193758069),FL2FXCONST_DBL(0.4654086763742842),FL2FXCONST_DBL(0.4664844546714713),FL2FXCONST_DBL(0.4675608535505532), + FL2FXCONST_DBL(0.4686378722967790),FL2FXCONST_DBL(0.4697155101974522),FL2FXCONST_DBL(0.4707937665419216),FL2FXCONST_DBL(0.4718726406215713), + FL2FXCONST_DBL(0.4729521317298118),FL2FXCONST_DBL(0.4740322391620711),FL2FXCONST_DBL(0.4751129622157845),FL2FXCONST_DBL(0.4761943001903867), + FL2FXCONST_DBL(0.4772762523873015),FL2FXCONST_DBL(0.4783588181099338),FL2FXCONST_DBL(0.4794419966636599),FL2FXCONST_DBL(0.4805257873558190), + FL2FXCONST_DBL(0.4816101894957042),FL2FXCONST_DBL(0.4826952023945537),FL2FXCONST_DBL(0.4837808253655421),FL2FXCONST_DBL(0.4848670577237714), + FL2FXCONST_DBL(0.4859538987862632),FL2FXCONST_DBL(0.4870413478719488),FL2FXCONST_DBL(0.4881294043016621),FL2FXCONST_DBL(0.4892180673981298), + FL2FXCONST_DBL(0.4903073364859640),FL2FXCONST_DBL(0.4913972108916533),FL2FXCONST_DBL(0.4924876899435545),FL2FXCONST_DBL(0.4935787729718844), + FL2FXCONST_DBL(0.4946704593087116),FL2FXCONST_DBL(0.4957627482879484),FL2FXCONST_DBL(0.4968556392453423),FL2FXCONST_DBL(0.4979491315184684), + FL2FXCONST_DBL(0.4990432244467211),FL2FXCONST_DBL(0.5001379173713062),FL2FXCONST_DBL(0.5012332096352328),FL2FXCONST_DBL(0.5023291005833056), + FL2FXCONST_DBL(0.5034255895621171),FL2FXCONST_DBL(0.5045226759200399),FL2FXCONST_DBL(0.5056203590072181),FL2FXCONST_DBL(0.5067186381755611), + FL2FXCONST_DBL(0.5078175127787346),FL2FXCONST_DBL(0.5089169821721536),FL2FXCONST_DBL(0.5100170457129749),FL2FXCONST_DBL(0.5111177027600893), + FL2FXCONST_DBL(0.5122189526741143),FL2FXCONST_DBL(0.5133207948173868),FL2FXCONST_DBL(0.5144232285539552),FL2FXCONST_DBL(0.5155262532495726), + FL2FXCONST_DBL(0.5166298682716894),FL2FXCONST_DBL(0.5177340729894460),FL2FXCONST_DBL(0.5188388667736652),FL2FXCONST_DBL(0.5199442489968457), + FL2FXCONST_DBL(0.5210502190331544),FL2FXCONST_DBL(0.5221567762584198),FL2FXCONST_DBL(0.5232639200501247),FL2FXCONST_DBL(0.5243716497873989), + FL2FXCONST_DBL(0.5254799648510130),FL2FXCONST_DBL(0.5265888646233705),FL2FXCONST_DBL(0.5276983484885021),FL2FXCONST_DBL(0.5288084158320574), + FL2FXCONST_DBL(0.5299190660412995),FL2FXCONST_DBL(0.5310302985050975),FL2FXCONST_DBL(0.5321421126139198),FL2FXCONST_DBL(0.5332545077598274), + FL2FXCONST_DBL(0.5343674833364678),FL2FXCONST_DBL(0.5354810387390675),FL2FXCONST_DBL(0.5365951733644262),FL2FXCONST_DBL(0.5377098866109097), + FL2FXCONST_DBL(0.5388251778784438),FL2FXCONST_DBL(0.5399410465685075),FL2FXCONST_DBL(0.5410574920841272),FL2FXCONST_DBL(0.5421745138298695), + FL2FXCONST_DBL(0.5432921112118353),FL2FXCONST_DBL(0.5444102836376534),FL2FXCONST_DBL(0.5455290305164744),FL2FXCONST_DBL(0.5466483512589642), + FL2FXCONST_DBL(0.5477682452772976),FL2FXCONST_DBL(0.5488887119851529),FL2FXCONST_DBL(0.5500097507977050),FL2FXCONST_DBL(0.5511313611316194), + FL2FXCONST_DBL(0.5522535424050467),FL2FXCONST_DBL(0.5533762940376158),FL2FXCONST_DBL(0.5544996154504284),FL2FXCONST_DBL(0.5556235060660528), + FL2FXCONST_DBL(0.5567479653085183),FL2FXCONST_DBL(0.5578729926033087),FL2FXCONST_DBL(0.5589985873773569),FL2FXCONST_DBL(0.5601247490590389), + FL2FXCONST_DBL(0.5612514770781683),FL2FXCONST_DBL(0.5623787708659898),FL2FXCONST_DBL(0.5635066298551742),FL2FXCONST_DBL(0.5646350534798125), + FL2FXCONST_DBL(0.5657640411754097),FL2FXCONST_DBL(0.5668935923788799),FL2FXCONST_DBL(0.5680237065285404),FL2FXCONST_DBL(0.5691543830641059), + FL2FXCONST_DBL(0.5702856214266832),FL2FXCONST_DBL(0.5714174210587655),FL2FXCONST_DBL(0.5725497814042271),FL2FXCONST_DBL(0.5736827019083177), + FL2FXCONST_DBL(0.5748161820176573),FL2FXCONST_DBL(0.5759502211802304),FL2FXCONST_DBL(0.5770848188453810),FL2FXCONST_DBL(0.5782199744638067), + FL2FXCONST_DBL(0.5793556874875542),FL2FXCONST_DBL(0.5804919573700131),FL2FXCONST_DBL(0.5816287835659116),FL2FXCONST_DBL(0.5827661655313104), + FL2FXCONST_DBL(0.5839041027235979),FL2FXCONST_DBL(0.5850425946014850),FL2FXCONST_DBL(0.5861816406250000),FL2FXCONST_DBL(0.5873212402554834), + FL2FXCONST_DBL(0.5884613929555826),FL2FXCONST_DBL(0.5896020981892474),FL2FXCONST_DBL(0.5907433554217242),FL2FXCONST_DBL(0.5918851641195517), + FL2FXCONST_DBL(0.5930275237505556),FL2FXCONST_DBL(0.5941704337838434),FL2FXCONST_DBL(0.5953138936897999),FL2FXCONST_DBL(0.5964579029400819), + FL2FXCONST_DBL(0.5976024610076139),FL2FXCONST_DBL(0.5987475673665825),FL2FXCONST_DBL(0.5998932214924321),FL2FXCONST_DBL(0.6010394228618597), + FL2FXCONST_DBL(0.6021861709528106),FL2FXCONST_DBL(0.6033334652444733),FL2FXCONST_DBL(0.6044813052172748),FL2FXCONST_DBL(0.6056296903528761), + FL2FXCONST_DBL(0.6067786201341671),FL2FXCONST_DBL(0.6079280940452625),FL2FXCONST_DBL(0.6090781115714966),FL2FXCONST_DBL(0.6102286721994192), + FL2FXCONST_DBL(0.6113797754167908),FL2FXCONST_DBL(0.6125314207125777),FL2FXCONST_DBL(0.6136836075769482),FL2FXCONST_DBL(0.6148363355012674), + FL2FXCONST_DBL(0.6159896039780929),FL2FXCONST_DBL(0.6171434125011708),FL2FXCONST_DBL(0.6182977605654305),FL2FXCONST_DBL(0.6194526476669808), + FL2FXCONST_DBL(0.6206080733031054),FL2FXCONST_DBL(0.6217640369722584),FL2FXCONST_DBL(0.6229205381740598),FL2FXCONST_DBL(0.6240775764092919), + FL2FXCONST_DBL(0.6252351511798939),FL2FXCONST_DBL(0.6263932619889586),FL2FXCONST_DBL(0.6275519083407275),FL2FXCONST_DBL(0.6287110897405869), + FL2FXCONST_DBL(0.6298708056950635),FL2FXCONST_DBL(0.6310310557118203),FL2FXCONST_DBL(0.6321918392996523),FL2FXCONST_DBL(0.6333531559684823), + FL2FXCONST_DBL(0.6345150052293571),FL2FXCONST_DBL(0.6356773865944432),FL2FXCONST_DBL(0.6368402995770224),FL2FXCONST_DBL(0.6380037436914881), + FL2FXCONST_DBL(0.6391677184533411),FL2FXCONST_DBL(0.6403322233791856),FL2FXCONST_DBL(0.6414972579867254),FL2FXCONST_DBL(0.6426628217947594), + FL2FXCONST_DBL(0.6438289143231779),FL2FXCONST_DBL(0.6449955350929588),FL2FXCONST_DBL(0.6461626836261636),FL2FXCONST_DBL(0.6473303594459330), + FL2FXCONST_DBL(0.6484985620764839),FL2FXCONST_DBL(0.6496672910431047),FL2FXCONST_DBL(0.6508365458721518),FL2FXCONST_DBL(0.6520063260910459), + FL2FXCONST_DBL(0.6531766312282679),FL2FXCONST_DBL(0.6543474608133552),FL2FXCONST_DBL(0.6555188143768979),FL2FXCONST_DBL(0.6566906914505349), + FL2FXCONST_DBL(0.6578630915669509),FL2FXCONST_DBL(0.6590360142598715),FL2FXCONST_DBL(0.6602094590640603),FL2FXCONST_DBL(0.6613834255153149), + FL2FXCONST_DBL(0.6625579131504635),FL2FXCONST_DBL(0.6637329215073610),FL2FXCONST_DBL(0.6649084501248851),FL2FXCONST_DBL(0.6660844985429335), + FL2FXCONST_DBL(0.6672610663024197),FL2FXCONST_DBL(0.6684381529452691),FL2FXCONST_DBL(0.6696157580144163),FL2FXCONST_DBL(0.6707938810538011), + FL2FXCONST_DBL(0.6719725216083646),FL2FXCONST_DBL(0.6731516792240465),FL2FXCONST_DBL(0.6743313534477807),FL2FXCONST_DBL(0.6755115438274927), + FL2FXCONST_DBL(0.6766922499120955),FL2FXCONST_DBL(0.6778734712514865),FL2FXCONST_DBL(0.6790552073965435),FL2FXCONST_DBL(0.6802374578991223), + FL2FXCONST_DBL(0.6814202223120524),FL2FXCONST_DBL(0.6826035001891340),FL2FXCONST_DBL(0.6837872910851345),FL2FXCONST_DBL(0.6849715945557853), + FL2FXCONST_DBL(0.6861564101577784),FL2FXCONST_DBL(0.6873417374487629),FL2FXCONST_DBL(0.6885275759873420),FL2FXCONST_DBL(0.6897139253330697), + FL2FXCONST_DBL(0.6909007850464473),FL2FXCONST_DBL(0.6920881546889198),FL2FXCONST_DBL(0.6932760338228737),FL2FXCONST_DBL(0.6944644220116332), + FL2FXCONST_DBL(0.6956533188194565),FL2FXCONST_DBL(0.6968427238115332),FL2FXCONST_DBL(0.6980326365539813),FL2FXCONST_DBL(0.6992230566138435), + FL2FXCONST_DBL(0.7004139835590845),FL2FXCONST_DBL(0.7016054169585869),FL2FXCONST_DBL(0.7027973563821499),FL2FXCONST_DBL(0.7039898014004843), + FL2FXCONST_DBL(0.7051827515852106),FL2FXCONST_DBL(0.7063762065088554),FL2FXCONST_DBL(0.7075701657448483),FL2FXCONST_DBL(0.7087646288675196), + FL2FXCONST_DBL(0.7099595954520960),FL2FXCONST_DBL(0.7111550650746988),FL2FXCONST_DBL(0.7123510373123402),FL2FXCONST_DBL(0.7135475117429202), + FL2FXCONST_DBL(0.7147444879452244),FL2FXCONST_DBL(0.7159419654989200),FL2FXCONST_DBL(0.7171399439845538),FL2FXCONST_DBL(0.7183384229835486), + FL2FXCONST_DBL(0.7195374020782005),FL2FXCONST_DBL(0.7207368808516762),FL2FXCONST_DBL(0.7219368588880097),FL2FXCONST_DBL(0.7231373357720997), + FL2FXCONST_DBL(0.7243383110897066),FL2FXCONST_DBL(0.7255397844274496),FL2FXCONST_DBL(0.7267417553728043),FL2FXCONST_DBL(0.7279442235140992), + FL2FXCONST_DBL(0.7291471884405130),FL2FXCONST_DBL(0.7303506497420724),FL2FXCONST_DBL(0.7315546070096487),FL2FXCONST_DBL(0.7327590598349553), + FL2FXCONST_DBL(0.7339640078105445),FL2FXCONST_DBL(0.7351694505298055),FL2FXCONST_DBL(0.7363753875869610),FL2FXCONST_DBL(0.7375818185770647), + FL2FXCONST_DBL(0.7387887430959987),FL2FXCONST_DBL(0.7399961607404706),FL2FXCONST_DBL(0.7412040711080108),FL2FXCONST_DBL(0.7424124737969701), + FL2FXCONST_DBL(0.7436213684065166),FL2FXCONST_DBL(0.7448307545366334),FL2FXCONST_DBL(0.7460406317881158),FL2FXCONST_DBL(0.7472509997625686), + FL2FXCONST_DBL(0.7484618580624036),FL2FXCONST_DBL(0.7496732062908372),FL2FXCONST_DBL(0.7508850440518872),FL2FXCONST_DBL(0.7520973709503704), + FL2FXCONST_DBL(0.7533101865919009),FL2FXCONST_DBL(0.7545234905828862),FL2FXCONST_DBL(0.7557372825305252),FL2FXCONST_DBL(0.7569515620428062), + FL2FXCONST_DBL(0.7581663287285035),FL2FXCONST_DBL(0.7593815821971756),FL2FXCONST_DBL(0.7605973220591619),FL2FXCONST_DBL(0.7618135479255810), + FL2FXCONST_DBL(0.7630302594083277),FL2FXCONST_DBL(0.7642474561200708),FL2FXCONST_DBL(0.7654651376742505),FL2FXCONST_DBL(0.7666833036850760), + FL2FXCONST_DBL(0.7679019537675227),FL2FXCONST_DBL(0.7691210875373307),FL2FXCONST_DBL(0.7703407046110011),FL2FXCONST_DBL(0.7715608046057948), + FL2FXCONST_DBL(0.7727813871397293),FL2FXCONST_DBL(0.7740024518315765),FL2FXCONST_DBL(0.7752239983008605),FL2FXCONST_DBL(0.7764460261678551), + FL2FXCONST_DBL(0.7776685350535814),FL2FXCONST_DBL(0.7788915245798054),FL2FXCONST_DBL(0.7801149943690360),FL2FXCONST_DBL(0.7813389440445223), + FL2FXCONST_DBL(0.7825633732302513),FL2FXCONST_DBL(0.7837882815509458),FL2FXCONST_DBL(0.7850136686320621),FL2FXCONST_DBL(0.7862395340997874), + FL2FXCONST_DBL(0.7874658775810378),FL2FXCONST_DBL(0.7886926987034559),FL2FXCONST_DBL(0.7899199970954088),FL2FXCONST_DBL(0.7911477723859853), + FL2FXCONST_DBL(0.7923760242049944),FL2FXCONST_DBL(0.7936047521829623),FL2FXCONST_DBL(0.7948339559511308),FL2FXCONST_DBL(0.7960636351414546), + FL2FXCONST_DBL(0.7972937893865995),FL2FXCONST_DBL(0.7985244183199399),FL2FXCONST_DBL(0.7997555215755570),FL2FXCONST_DBL(0.8009870987882359), + FL2FXCONST_DBL(0.8022191495934644),FL2FXCONST_DBL(0.8034516736274301),FL2FXCONST_DBL(0.8046846705270185),FL2FXCONST_DBL(0.8059181399298110), + FL2FXCONST_DBL(0.8071520814740822),FL2FXCONST_DBL(0.8083864947987989),FL2FXCONST_DBL(0.8096213795436166),FL2FXCONST_DBL(0.8108567353488784), + FL2FXCONST_DBL(0.8120925618556127),FL2FXCONST_DBL(0.8133288587055308),FL2FXCONST_DBL(0.8145656255410253),FL2FXCONST_DBL(0.8158028620051674), + FL2FXCONST_DBL(0.8170405677417053),FL2FXCONST_DBL(0.8182787423950622),FL2FXCONST_DBL(0.8195173856103341),FL2FXCONST_DBL(0.8207564970332875), + FL2FXCONST_DBL(0.8219960763103580),FL2FXCONST_DBL(0.8232361230886477),FL2FXCONST_DBL(0.8244766370159234),FL2FXCONST_DBL(0.8257176177406150), + FL2FXCONST_DBL(0.8269590649118125),FL2FXCONST_DBL(0.8282009781792650),FL2FXCONST_DBL(0.8294433571933784),FL2FXCONST_DBL(0.8306862016052132), + FL2FXCONST_DBL(0.8319295110664831),FL2FXCONST_DBL(0.8331732852295520),FL2FXCONST_DBL(0.8344175237474336),FL2FXCONST_DBL(0.8356622262737878), + FL2FXCONST_DBL(0.8369073924629202),FL2FXCONST_DBL(0.8381530219697793),FL2FXCONST_DBL(0.8393991144499545),FL2FXCONST_DBL(0.8406456695596752), + FL2FXCONST_DBL(0.8418926869558079),FL2FXCONST_DBL(0.8431401662958544),FL2FXCONST_DBL(0.8443881072379507),FL2FXCONST_DBL(0.8456365094408642), + FL2FXCONST_DBL(0.8468853725639923),FL2FXCONST_DBL(0.8481346962673606),FL2FXCONST_DBL(0.8493844802116208),FL2FXCONST_DBL(0.8506347240580492), + FL2FXCONST_DBL(0.8518854274685442),FL2FXCONST_DBL(0.8531365901056253),FL2FXCONST_DBL(0.8543882116324307),FL2FXCONST_DBL(0.8556402917127157), + FL2FXCONST_DBL(0.8568928300108512),FL2FXCONST_DBL(0.8581458261918209),FL2FXCONST_DBL(0.8593992799212207),FL2FXCONST_DBL(0.8606531908652563), + FL2FXCONST_DBL(0.8619075586907414),FL2FXCONST_DBL(0.8631623830650962),FL2FXCONST_DBL(0.8644176636563452),FL2FXCONST_DBL(0.8656734001331161), + FL2FXCONST_DBL(0.8669295921646375),FL2FXCONST_DBL(0.8681862394207371),FL2FXCONST_DBL(0.8694433415718407),FL2FXCONST_DBL(0.8707008982889695), + FL2FXCONST_DBL(0.8719589092437391),FL2FXCONST_DBL(0.8732173741083574),FL2FXCONST_DBL(0.8744762925556232),FL2FXCONST_DBL(0.8757356642589241), + FL2FXCONST_DBL(0.8769954888922352),FL2FXCONST_DBL(0.8782557661301171),FL2FXCONST_DBL(0.8795164956477146),FL2FXCONST_DBL(0.8807776771207545), + FL2FXCONST_DBL(0.8820393102255443),FL2FXCONST_DBL(0.8833013946389704),FL2FXCONST_DBL(0.8845639300384969),FL2FXCONST_DBL(0.8858269161021629), + FL2FXCONST_DBL(0.8870903525085819),FL2FXCONST_DBL(0.8883542389369399),FL2FXCONST_DBL(0.8896185750669933),FL2FXCONST_DBL(0.8908833605790678), + FL2FXCONST_DBL(0.8921485951540565),FL2FXCONST_DBL(0.8934142784734187),FL2FXCONST_DBL(0.8946804102191776),FL2FXCONST_DBL(0.8959469900739191), + FL2FXCONST_DBL(0.8972140177207906),FL2FXCONST_DBL(0.8984814928434985),FL2FXCONST_DBL(0.8997494151263077),FL2FXCONST_DBL(0.9010177842540390), + FL2FXCONST_DBL(0.9022865999120682),FL2FXCONST_DBL(0.9035558617863242),FL2FXCONST_DBL(0.9048255695632878),FL2FXCONST_DBL(0.9060957229299895), + FL2FXCONST_DBL(0.9073663215740092),FL2FXCONST_DBL(0.9086373651834729),FL2FXCONST_DBL(0.9099088534470528),FL2FXCONST_DBL(0.9111807860539647), + FL2FXCONST_DBL(0.9124531626939672),FL2FXCONST_DBL(0.9137259830573594),FL2FXCONST_DBL(0.9149992468349805),FL2FXCONST_DBL(0.9162729537182071), + FL2FXCONST_DBL(0.9175471033989524),FL2FXCONST_DBL(0.9188216955696648),FL2FXCONST_DBL(0.9200967299233258),FL2FXCONST_DBL(0.9213722061534494), + FL2FXCONST_DBL(0.9226481239540795),FL2FXCONST_DBL(0.9239244830197896),FL2FXCONST_DBL(0.9252012830456805),FL2FXCONST_DBL(0.9264785237273793), + FL2FXCONST_DBL(0.9277562047610376),FL2FXCONST_DBL(0.9290343258433305),FL2FXCONST_DBL(0.9303128866714547),FL2FXCONST_DBL(0.9315918869431275), + FL2FXCONST_DBL(0.9328713263565848),FL2FXCONST_DBL(0.9341512046105802),FL2FXCONST_DBL(0.9354315214043836),FL2FXCONST_DBL(0.9367122764377792), + FL2FXCONST_DBL(0.9379934694110648),FL2FXCONST_DBL(0.9392751000250497),FL2FXCONST_DBL(0.9405571679810542),FL2FXCONST_DBL(0.9418396729809072), + FL2FXCONST_DBL(0.9431226147269456),FL2FXCONST_DBL(0.9444059929220124),FL2FXCONST_DBL(0.9456898072694558),FL2FXCONST_DBL(0.9469740574731275), + FL2FXCONST_DBL(0.9482587432373810),FL2FXCONST_DBL(0.9495438642670713),FL2FXCONST_DBL(0.9508294202675522),FL2FXCONST_DBL(0.9521154109446763), + FL2FXCONST_DBL(0.9534018360047926),FL2FXCONST_DBL(0.9546886951547455),FL2FXCONST_DBL(0.9559759881018738),FL2FXCONST_DBL(0.9572637145540087), + FL2FXCONST_DBL(0.9585518742194732),FL2FXCONST_DBL(0.9598404668070802),FL2FXCONST_DBL(0.9611294920261317),FL2FXCONST_DBL(0.9624189495864168), + FL2FXCONST_DBL(0.9637088391982110),FL2FXCONST_DBL(0.9649991605722750),FL2FXCONST_DBL(0.9662899134198524),FL2FXCONST_DBL(0.9675810974526697), + FL2FXCONST_DBL(0.9688727123829343),FL2FXCONST_DBL(0.9701647579233330),FL2FXCONST_DBL(0.9714572337870316),FL2FXCONST_DBL(0.9727501396876727), + FL2FXCONST_DBL(0.9740434753393749),FL2FXCONST_DBL(0.9753372404567313),FL2FXCONST_DBL(0.9766314347548087),FL2FXCONST_DBL(0.9779260579491460), + FL2FXCONST_DBL(0.9792211097557527),FL2FXCONST_DBL(0.9805165898911081),FL2FXCONST_DBL(0.9818124980721600),FL2FXCONST_DBL(0.9831088340163232), + FL2FXCONST_DBL(0.9844055974414786),FL2FXCONST_DBL(0.9857027880659716),FL2FXCONST_DBL(0.9870004056086111),FL2FXCONST_DBL(0.9882984497886684), + FL2FXCONST_DBL(0.9895969203258759),FL2FXCONST_DBL(0.9908958169404255),FL2FXCONST_DBL(0.9921951393529680),FL2FXCONST_DBL(0.9934948872846116), + FL2FXCONST_DBL(0.9947950604569206),FL2FXCONST_DBL(0.9960956585919144),FL2FXCONST_DBL(0.9973966814120665),FL2FXCONST_DBL(0.9986981286403025) +}; + +const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14] = +{ + {FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), + FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), + FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), + FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366)}, + + {FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), + FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), + FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), + FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408)}, + + {FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), + FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), + FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), + FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393)}, + + {FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), + FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), + FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), + FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477)} +}; + +const UCHAR FDKaacEnc_specExpTableComb[4][14] = +{ + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19} +}; + + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +const FIXP_WTB ELDAnalysis512[1536] = { + /* part 0 */ + WTC0(0xfac5a770), WTC0(0xfaafbab8), WTC0(0xfa996a40), WTC0(0xfa82bbd0), WTC0(0xfa6bb538), WTC0(0xfa545c38), WTC0(0xfa3cb698), WTC0(0xfa24ca28), + WTC0(0xfa0c9ca8), WTC0(0xf9f433e8), WTC0(0xf9db9580), WTC0(0xf9c2c298), WTC0(0xf9a9b800), WTC0(0xf9907250), WTC0(0xf976ee38), WTC0(0xf95d2b88), + WTC0(0xf9432d10), WTC0(0xf928f5c0), WTC0(0xf90e8868), WTC0(0xf8f3e400), WTC0(0xf8d903a0), WTC0(0xf8bde238), WTC0(0xf8a27af0), WTC0(0xf886cde8), + WTC0(0xf86ae020), WTC0(0xf84eb6c0), WTC0(0xf83256f8), WTC0(0xf815c4b8), WTC0(0xf7f902c0), WTC0(0xf7dc13b0), WTC0(0xf7befa60), WTC0(0xf7a1ba40), + WTC0(0xf78457c0), WTC0(0xf766d780), WTC0(0xf7493d90), WTC0(0xf72b8990), WTC0(0xf70db5f0), WTC0(0xf6efbd30), WTC0(0xf6d19a20), WTC0(0xf6b352e0), + WTC0(0xf694f8c0), WTC0(0xf6769da0), WTC0(0xf6585310), WTC0(0xf63a28d0), WTC0(0xf61c2c60), WTC0(0xf5fe6b10), WTC0(0xf5e0f250), WTC0(0xf5c3ceb0), + WTC0(0xf5a70be0), WTC0(0xf58ab5a0), WTC0(0xf56ed7b0), WTC0(0xf5537e40), WTC0(0xf538b610), WTC0(0xf51e8bf0), WTC0(0xf5050c90), WTC0(0xf4ec4330), + WTC0(0xf4d439b0), WTC0(0xf4bcf9b0), WTC0(0xf4a68ce0), WTC0(0xf490fa80), WTC0(0xf47c4760), WTC0(0xf4687830), WTC0(0xf4558f00), WTC0(0xf4434fc0), + WTC0(0xf4314070), WTC0(0xf41ee450), WTC0(0xf40bc130), WTC0(0xf3f799c0), WTC0(0xf3e26d30), WTC0(0xf3cc3d70), WTC0(0xf3b50c80), WTC0(0xf39cdd60), + WTC0(0xf383b440), WTC0(0xf3699550), WTC0(0xf34e84c0), WTC0(0xf33286b0), WTC0(0xf3159f10), WTC0(0xf2f7d1b0), WTC0(0xf2d92290), WTC0(0xf2b994d0), + WTC0(0xf2992ad0), WTC0(0xf277e6d0), WTC0(0xf255cb60), WTC0(0xf232dd00), WTC0(0xf20f2240), WTC0(0xf1eaa1d0), WTC0(0xf1c56240), WTC0(0xf19f63d0), + WTC0(0xf178a0f0), WTC0(0xf15113a0), WTC0(0xf128b5c0), WTC0(0xf0ff7fd0), WTC0(0xf0d56860), WTC0(0xf0aa6610), WTC0(0xf07e6fd0), WTC0(0xf0518190), + WTC0(0xf0239cd0), WTC0(0xeff4c320), WTC0(0xefc4f720), WTC0(0xef945080), WTC0(0xef62fce0), WTC0(0xef312a40), WTC0(0xeeff05c0), WTC0(0xeecca2c0), + WTC0(0xee99faa0), WTC0(0xee6705a0), WTC0(0xee33bb60), WTC0(0xee000060), WTC0(0xedcba660), WTC0(0xed967e80), WTC0(0xed605b80), WTC0(0xed293b40), + WTC0(0xecf146a0), WTC0(0xecb8a8a0), WTC0(0xec7f8bc0), WTC0(0xec461260), WTC0(0xec0c5720), WTC0(0xebd27440), WTC0(0xeb988220), WTC0(0xeb5e7040), + WTC0(0xeb2404c0), WTC0(0xeae90440), WTC0(0xeaad33c0), WTC0(0xea7066c0), WTC0(0xea327f60), WTC0(0xe9f36000), WTC0(0xe9b2ed60), WTC0(0xe9713920), + WTC0(0xe92e81e0), WTC0(0xe8eb08c0), WTC0(0xe8a70e60), WTC0(0xe862d8e0), WTC0(0xe81eb340), WTC0(0xe7dae8a0), WTC0(0xe797c1a0), WTC0(0xe7554ca0), + WTC0(0xe7135dc0), WTC0(0xe6d1c6a0), WTC0(0xe6905720), WTC0(0xe64eb9c0), WTC0(0xe60c7300), WTC0(0xe5c90600), WTC0(0xe583f920), WTC0(0xe53d1ce0), + WTC0(0xe4f48c80), WTC0(0xe4aa6640), WTC0(0xe45ecaa0), WTC0(0xe4120be0), WTC0(0xe3c4ae60), WTC0(0xe3773860), WTC0(0xe32a2ea0), WTC0(0xe2ddeea0), + WTC0(0xe292af00), WTC0(0xe248a4a0), WTC0(0xe2000140), WTC0(0xe1b8b640), WTC0(0xe1727440), WTC0(0xe12ce900), WTC0(0xe0e7c280), WTC0(0xe0a2b420), + WTC0(0xe05d76c0), WTC0(0xe017c360), WTC0(0xdfd15440), WTC0(0xdf8a0540), WTC0(0xdf41d300), WTC0(0xdef8bb40), WTC0(0xdeaebd40), WTC0(0xde63e7c0), + WTC0(0xde185940), WTC0(0xddcc3180), WTC0(0xdd7f9000), WTC0(0xdd329e80), WTC0(0xdce58e80), WTC0(0xdc989300), WTC0(0xdc4bde40), WTC0(0xdbff96c0), + WTC0(0xdbb3d780), WTC0(0xdb68bb80), WTC0(0xdb1e5c80), WTC0(0xdad4c380), WTC0(0xda8be840), WTC0(0xda43c1c0), WTC0(0xd9fc4740), WTC0(0xd9b56640), + WTC0(0xd96f0440), WTC0(0xd9290600), WTC0(0xd8e35080), WTC0(0xd89dcd40), WTC0(0xd8586b40), WTC0(0xd8131940), WTC0(0xd7cdc640), WTC0(0xd7886180), + WTC0(0xd742dc80), WTC0(0xd6fd2780), WTC0(0xd6b73400), WTC0(0xd670fd80), WTC0(0xd62a8a40), WTC0(0xd5e3e080), WTC0(0xd59d0840), WTC0(0xd5562b80), + WTC0(0xd50f9540), WTC0(0xd4c992c0), WTC0(0xd4846f80), WTC0(0xd4405a80), WTC0(0xd3fd6580), WTC0(0xd3bba140), WTC0(0xd37b1c80), WTC0(0xd33bb780), + WTC0(0xd2fd2400), WTC0(0xd2bf1240), WTC0(0xd2813300), WTC0(0xd2435ac0), WTC0(0xd2057fc0), WTC0(0xd1c79a00), WTC0(0xd189a240), WTC0(0xd14b9dc0), + WTC0(0xd10d9e00), WTC0(0xd0cfb580), WTC0(0xd091f6c0), WTC0(0xd0548100), WTC0(0xd0177f40), WTC0(0xcfdb1cc0), WTC0(0xcf9f84c0), WTC0(0xcf64d780), + WTC0(0xcf2b2b00), WTC0(0xcef29440), WTC0(0xcebb2640), WTC0(0xce84c000), WTC0(0xce4f0bc0), WTC0(0xce19b200), WTC0(0xcde45d40), WTC0(0xcdaeedc0), + WTC0(0xcd7979c0), WTC0(0xcd4419c0), WTC0(0xcd0ee6c0), WTC0(0xccda0540), WTC0(0xcca5a500), WTC0(0xcc71f640), WTC0(0xcc3f2800), WTC0(0xcc0d4300), + WTC0(0xcbdc2a00), WTC0(0xcbabbe80), WTC0(0xcb7be200), WTC0(0xcb4c8200), WTC0(0xcb1d9800), WTC0(0xcaef1d40), WTC0(0xcac10bc0), WTC0(0xca936440), + WTC0(0xca662d00), WTC0(0xca396d40), WTC0(0xca0d2b80), WTC0(0xc9e16f80), WTC0(0xc9b63f80), WTC0(0xc98ba2c0), WTC0(0xc961a000), WTC0(0xc9383ec0), + WTC0(0xc90a0440), WTC0(0xc8e0d280), WTC0(0xc8b73b80), WTC0(0xc88d4900), WTC0(0xc86304c0), WTC0(0xc83878c0), WTC0(0xc80dae80), WTC0(0xc7e2afc0), + WTC0(0xc7b78640), WTC0(0xc78c3c40), WTC0(0xc760da80), WTC0(0xc7356640), WTC0(0xc709de40), WTC0(0xc6de41c0), WTC0(0xc6b28fc0), WTC0(0xc686bd40), + WTC0(0xc65ab600), WTC0(0xc62e6580), WTC0(0xc601b880), WTC0(0xc5d4bac0), WTC0(0xc5a79640), WTC0(0xc57a76c0), WTC0(0xc54d8780), WTC0(0xc520e840), + WTC0(0xc4f4acc0), WTC0(0xc4c8e880), WTC0(0xc49dad80), WTC0(0xc472e640), WTC0(0xc44856c0), WTC0(0xc41dc140), WTC0(0xc3f2e940), WTC0(0xc3c7bc00), + WTC0(0xc39c4f00), WTC0(0xc370b9c0), WTC0(0xc34513c0), WTC0(0xc3197940), WTC0(0xc2ee0a00), WTC0(0xc2c2e640), WTC0(0xc2982d80), WTC0(0xc26df5c0), + WTC0(0xc2444b00), WTC0(0xc21b3940), WTC0(0xc1f2cbc0), WTC0(0xc1cb05c0), WTC0(0xc1a3e340), WTC0(0xc17d5f00), WTC0(0xc15773c0), WTC0(0xc1320940), + WTC0(0xc10cf480), WTC0(0xc0e80a00), WTC0(0xc0c31f00), WTC0(0xc09e2640), WTC0(0xc0792ec0), WTC0(0xc0544940), WTC0(0xc02f86c0), WTC0(0xc00b04c0), + WTC0(0xbfe6ed01), WTC0(0xbfc36a01), WTC0(0xbfa0a581), WTC0(0xbf7eb581), WTC0(0xbf5d9a81), WTC0(0xbf3d5501), WTC0(0xbf1de601), WTC0(0xbeff4801), + WTC0(0xbee17201), WTC0(0xbec45881), WTC0(0xbea7f301), WTC0(0xbe8c3781), WTC0(0xbe712001), WTC0(0xbe56a381), WTC0(0xbe3cbc01), WTC0(0xbe236001), + WTC0(0xbe0a8581), WTC0(0xbdf22181), WTC0(0xbdda2a01), WTC0(0xbdc29a81), WTC0(0xbdab7181), WTC0(0xbd94b001), WTC0(0xbd7e5581), WTC0(0xbd686681), + WTC0(0xbd52eb01), WTC0(0xbd3deb81), WTC0(0xbd297181), WTC0(0xbd158801), WTC0(0xbd023f01), WTC0(0xbcefa601), WTC0(0xbcddcc81), WTC0(0xbcccbd01), + WTC0(0xbcbc7e01), WTC0(0xbcad1501), WTC0(0xbc9e8801), WTC0(0xbc90d481), WTC0(0xbc83f201), WTC0(0xbc77d601), WTC0(0xbc6c7781), WTC0(0xbc61c401), + WTC0(0xbc57a301), WTC0(0xbc4dfb81), WTC0(0xbc44b481), WTC0(0xbc3bbc01), WTC0(0xbc330781), WTC0(0xbc2a8c81), WTC0(0xbc224181), WTC0(0xbc1a2401), + WTC0(0xbc123b81), WTC0(0xbc0a8f01), WTC0(0xbc032601), WTC0(0xbbfc0f81), WTC0(0xbbf56181), WTC0(0xbbef3301), WTC0(0xbbe99981), WTC0(0xbbe49d01), + WTC0(0xbbe03801), WTC0(0xbbdc6481), WTC0(0xbbd91b81), WTC0(0xbbd64d01), WTC0(0xbbd3e101), WTC0(0xbbd1bd81), WTC0(0xbbcfca81), WTC0(0xbbce0601), + WTC0(0xbbcc8201), WTC0(0xbbcb5301), WTC0(0xbbca8d01), WTC0(0xbbca5081), WTC0(0xbbcaca01), WTC0(0xbbcc2681), WTC0(0xbbce9181), WTC0(0xbbd21281), + WTC0(0xbbd68c81), WTC0(0xbbdbe201), WTC0(0xbbe1f401), WTC0(0xbbe89901), WTC0(0xbbef9b81), WTC0(0xbbf6c601), WTC0(0xbbfde481), WTC0(0xbc04e381), + WTC0(0xbc0bcf81), WTC0(0xbc12b801), WTC0(0xbc19ab01), WTC0(0xbc20ae01), WTC0(0xbc27bd81), WTC0(0xbc2ed681), WTC0(0xbc35f501), WTC0(0xbc3d1801), + WTC0(0xbc444081), WTC0(0xbc4b6e81), WTC0(0xbc52a381), WTC0(0xbc59df81), WTC0(0xbc612301), WTC0(0xbc686e01), WTC0(0xbc6fc101), WTC0(0xbc771c01), + WTC0(0xbc7e7e01), WTC0(0xbc85e801), WTC0(0xbc8d5901), WTC0(0xbc94d201), WTC0(0xbc9c5281), WTC0(0xbca3db01), WTC0(0xbcab6c01), WTC0(0xbcb30601), + WTC0(0xbcbaa801), WTC0(0xbcc25181), WTC0(0xbcca0301), WTC0(0xbcd1bb81), WTC0(0xbcd97c81), WTC0(0xbce14601), WTC0(0xbce91801), WTC0(0xbcf0f381), + WTC0(0xbcf8d781), WTC0(0xbd00c381), WTC0(0xbd08b781), WTC0(0xbd10b381), WTC0(0xbd18b781), WTC0(0xbd20c401), WTC0(0xbd28d981), WTC0(0xbd30f881), + WTC0(0xbd391f81), WTC0(0xbd414f01), WTC0(0xbd498601), WTC0(0xbd51c481), WTC0(0xbd5a0b01), WTC0(0xbd625981), WTC0(0xbd6ab101), WTC0(0xbd731081), + WTC0(0xbd7b7781), WTC0(0xbd83e681), WTC0(0xbd8c5c01), WTC0(0xbd94d801), WTC0(0xbd9d5b81), WTC0(0xbda5e601), WTC0(0xbdae7881), WTC0(0xbdb71201), + WTC0(0xbdbfb281), WTC0(0xbdc85981), WTC0(0xbdd10681), WTC0(0xbdd9b981), WTC0(0xbde27201), WTC0(0xbdeb3101), WTC0(0xbdf3f701), WTC0(0xbdfcc301), + WTC0(0xbe059481), WTC0(0xbe0e6c01), WTC0(0xbe174781), WTC0(0xbe202801), WTC0(0xbe290d01), WTC0(0xbe31f701), WTC0(0xbe3ae601), WTC0(0xbe43da81), + WTC0(0xbe4cd381), WTC0(0xbe55d001), WTC0(0xbe5ed081), WTC0(0xbe67d381), WTC0(0xbe70da01), WTC0(0xbe79e481), WTC0(0xbe82f301), WTC0(0xbe8c0501), + WTC0(0xbe951a81), WTC0(0xbe9e3281), WTC0(0xbea74c81), WTC0(0xbeb06881), WTC0(0xbeb98681), WTC0(0xbec2a781), WTC0(0xbecbca81), WTC0(0xbed4f081), + WTC0(0xbede1901), WTC0(0xbee74281), WTC0(0xbef06d01), WTC0(0xbef99901), WTC0(0xbf02c581), WTC0(0xbf0bf381), WTC0(0xbf152381), WTC0(0xbf1e5501), + WTC0(0xbf278801), WTC0(0xbf30bb01), WTC0(0xbf39ee81), WTC0(0xbf432281), WTC0(0xbf4c5681), WTC0(0xbf558b01), WTC0(0xbf5ec101), WTC0(0xbf67f801), + WTC0(0xbf712f01), WTC0(0xbf7a6681), WTC0(0xbf839d81), WTC0(0xbf8cd481), WTC0(0xbf960b01), WTC0(0xbf9f4181), WTC0(0xbfa87901), WTC0(0xbfb1b101), + WTC0(0xbfbae981), WTC0(0xbfc42201), WTC0(0xbfcd5a01), WTC0(0xbfd69101), WTC0(0xbfdfc781), WTC0(0xbfe8fc01), WTC0(0xbff22f81), WTC0(0xbffb6081), + /* part 1 */ + WTC1(0x80093e01), WTC1(0x801b9b01), WTC1(0x802df701), WTC1(0x80405101), WTC1(0x8052a881), WTC1(0x8064fc81), WTC1(0x80774c81), WTC1(0x80899881), + WTC1(0x809bdf01), WTC1(0x80ae1f81), WTC1(0x80c05a01), WTC1(0x80d28d81), WTC1(0x80e4bb81), WTC1(0x80f6e481), WTC1(0x81090981), WTC1(0x811b2981), + WTC1(0x812d4481), WTC1(0x813f5981), WTC1(0x81516701), WTC1(0x81636d81), WTC1(0x81756d81), WTC1(0x81876781), WTC1(0x81995c01), WTC1(0x81ab4b01), + WTC1(0x81bd3401), WTC1(0x81cf1581), WTC1(0x81e0ee81), WTC1(0x81f2bf81), WTC1(0x82048881), WTC1(0x82164a81), WTC1(0x82280581), WTC1(0x8239b981), + WTC1(0x824b6601), WTC1(0x825d0901), WTC1(0x826ea201), WTC1(0x82803101), WTC1(0x8291b601), WTC1(0x82a33281), WTC1(0x82b4a601), WTC1(0x82c61101), + WTC1(0x82d77201), WTC1(0x82e8c801), WTC1(0x82fa1181), WTC1(0x830b4f81), WTC1(0x831c8101), WTC1(0x832da781), WTC1(0x833ec381), WTC1(0x834fd481), + WTC1(0x8360d901), WTC1(0x8371d081), WTC1(0x8382ba01), WTC1(0x83939501), WTC1(0x83a46181), WTC1(0x83b52101), WTC1(0x83c5d381), WTC1(0x83d67881), + WTC1(0x83e70f01), WTC1(0x83f79681), WTC1(0x84080d81), WTC1(0x84187401), WTC1(0x8428ca01), WTC1(0x84391081), WTC1(0x84494881), WTC1(0x84597081), + WTC1(0x84698881), WTC1(0x84798f81), WTC1(0x84898481), WTC1(0x84996701), WTC1(0x84a93801), WTC1(0x84b8f801), WTC1(0x84c8a701), WTC1(0x84d84601), + WTC1(0x84e7d381), WTC1(0x84f74e01), WTC1(0x8506b581), WTC1(0x85160981), WTC1(0x85254a81), WTC1(0x85347901), WTC1(0x85439601), WTC1(0x8552a181), + WTC1(0x85619a01), WTC1(0x85707f81), WTC1(0x857f5101), WTC1(0x858e0e01), WTC1(0x859cb781), WTC1(0x85ab4f01), WTC1(0x85b9d481), WTC1(0x85c84801), + WTC1(0x85d6a981), WTC1(0x85e4f801), WTC1(0x85f33281), WTC1(0x86015981), WTC1(0x860f6e01), WTC1(0x861d7081), WTC1(0x862b6201), WTC1(0x86394301), + WTC1(0x86471281), WTC1(0x8654d001), WTC1(0x86627b01), WTC1(0x86701381), WTC1(0x867d9a81), WTC1(0x868b1001), WTC1(0x86987581), WTC1(0x86a5ca81), + WTC1(0x86b30f01), WTC1(0x86c04381), WTC1(0x86cd6681), WTC1(0x86da7901), WTC1(0x86e77b81), WTC1(0x86f46d81), WTC1(0x87014f81), WTC1(0x870e2301), + WTC1(0x871ae981), WTC1(0x8727a381), WTC1(0x87345381), WTC1(0x8740f681), WTC1(0x874d8681), WTC1(0x8759fd01), WTC1(0x87665481), WTC1(0x87729701), + WTC1(0x877ede01), WTC1(0x878b4301), WTC1(0x8797dd81), WTC1(0x87a48b01), WTC1(0x87b0ef01), WTC1(0x87bcab81), WTC1(0x87c76201), WTC1(0x87d0ca81), + WTC1(0x87fdd781), WTC1(0x881dd301), WTC1(0x88423301), WTC1(0x886a8a81), WTC1(0x88962981), WTC1(0x88c45e81), WTC1(0x88f47901), WTC1(0x8925f101), + WTC1(0x89586901), WTC1(0x898b8301), WTC1(0x89bee581), WTC1(0x89f26101), WTC1(0x8a25f301), WTC1(0x8a599a81), WTC1(0x8a8d5801), WTC1(0x8ac13381), + WTC1(0x8af53e81), WTC1(0x8b298b81), WTC1(0x8b5e2c81), WTC1(0x8b933001), WTC1(0x8bc8a401), WTC1(0x8bfe9401), WTC1(0x8c350d01), WTC1(0x8c6c1b01), + WTC1(0x8ca3cb01), WTC1(0x8cdc2901), WTC1(0x8d154081), WTC1(0x8d4f1b01), WTC1(0x8d89be81), WTC1(0x8dc53001), WTC1(0x8e017581), WTC1(0x8e3e9481), + WTC1(0x8e7c9301), WTC1(0x8ebb7581), WTC1(0x8efb4181), WTC1(0x8f3bfb01), WTC1(0x8f7da401), WTC1(0x8fc03f01), WTC1(0x9003ce81), WTC1(0x90485401), + WTC1(0x908dd101), WTC1(0x90d44781), WTC1(0x911bb981), WTC1(0x91642781), WTC1(0x91ad9281), WTC1(0x91f7f981), WTC1(0x92435d01), WTC1(0x928fbe01), + WTC1(0x92dd1b01), WTC1(0x932b7501), WTC1(0x937acb01), WTC1(0x93cb1c81), WTC1(0x941c6901), WTC1(0x946eaf81), WTC1(0x94c1ee01), WTC1(0x95162381), + WTC1(0x956b4f81), WTC1(0x95c17081), WTC1(0x96188501), WTC1(0x96708b81), WTC1(0x96c98381), WTC1(0x97236b01), WTC1(0x977e4181), WTC1(0x97da0481), + WTC1(0x9836b201), WTC1(0x98944901), WTC1(0x98f2c601), WTC1(0x99522801), WTC1(0x99b26c81), WTC1(0x9a139101), WTC1(0x9a759301), WTC1(0x9ad87081), + WTC1(0x9b3c2801), WTC1(0x9ba0b701), WTC1(0x9c061b81), WTC1(0x9c6c5481), WTC1(0x9cd35f81), WTC1(0x9d3b3b81), WTC1(0x9da3e601), WTC1(0x9e0d5e01), + WTC1(0x9e779f81), WTC1(0x9ee2a901), WTC1(0x9f4e7801), WTC1(0x9fbb0981), WTC1(0xa0285d81), WTC1(0xa0967201), WTC1(0xa1054701), WTC1(0xa174da81), + WTC1(0xa1e52a81), WTC1(0xa2563501), WTC1(0xa2c7f801), WTC1(0xa33a7201), WTC1(0xa3ada281), WTC1(0xa4218801), WTC1(0xa4962181), WTC1(0xa50b6e81), + WTC1(0xa5816e81), WTC1(0xa5f81f81), WTC1(0xa66f8201), WTC1(0xa6e79401), WTC1(0xa7605601), WTC1(0xa7d9c681), WTC1(0xa853e501), WTC1(0xa8ceb201), + WTC1(0xa94a2c01), WTC1(0xa9c65401), WTC1(0xaa432981), WTC1(0xaac0ad01), WTC1(0xab3edf01), WTC1(0xabbdc001), WTC1(0xac3d5001), WTC1(0xacbd9081), + WTC1(0xad3e8101), WTC1(0xadc02281), WTC1(0xae427481), WTC1(0xaec57801), WTC1(0xaf492f01), WTC1(0xafcd9a81), WTC1(0xb052bc01), WTC1(0xb0d89401), + WTC1(0xb15f2381), WTC1(0xb1e66a01), WTC1(0xb26e6881), WTC1(0xb2f71f01), WTC1(0xb3808d81), WTC1(0xb40ab501), WTC1(0xb4959501), WTC1(0xb5212e81), + WTC1(0x4a6cf67f), WTC1(0x49dffeff), WTC1(0x495265ff), WTC1(0x48c4277f), WTC1(0x4835407f), WTC1(0x47a5aeff), WTC1(0x471570ff), WTC1(0x468484ff), + WTC1(0x45f2eaff), WTC1(0x4560a2ff), WTC1(0x44cdad7f), WTC1(0x443a0c7f), WTC1(0x43a5c07f), WTC1(0x4310caff), WTC1(0x427b2bff), WTC1(0x41e4e3ff), + WTC1(0x414df2ff), WTC1(0x40b6557f), WTC1(0x401e06ff), WTC1(0x3f8503c0), WTC1(0x3eeb4e00), WTC1(0x3e50ebc0), WTC1(0x3db5e680), WTC1(0x3d1a4680), + WTC1(0x3c7e10c0), WTC1(0x3be14cc0), WTC1(0x3b4402c0), WTC1(0x3aa63800), WTC1(0x3a07e840), WTC1(0x39690880), WTC1(0x38c98700), WTC1(0x38295b40), + WTC1(0x37888a80), WTC1(0x36e71d40), WTC1(0x36451d80), WTC1(0x35a29400), WTC1(0x34ff8800), WTC1(0x345c04c0), WTC1(0x33b81940), WTC1(0x3313d200), + WTC1(0x326f3800), WTC1(0x31ca5600), WTC1(0x31253840), WTC1(0x307fe8c0), WTC1(0x2fda6e40), WTC1(0x2f34ce40), WTC1(0x2e8f0e40), WTC1(0x2de92ec0), + WTC1(0x2d432780), WTC1(0x2c9cea40), WTC1(0x2bf66300), WTC1(0x2b4f88c0), WTC1(0x2aa864c0), WTC1(0x2a010240), WTC1(0x29596e40), WTC1(0x28b1ba80), + WTC1(0x2809ff40), WTC1(0x27625b80), WTC1(0x26baf580), WTC1(0x2613e7c0), WTC1(0x256d3dc0), WTC1(0x24c70300), WTC1(0x24214380), WTC1(0x237c0800), + WTC1(0x22d75400), WTC1(0x22332a80), WTC1(0x218f8cc0), WTC1(0x20ec7e40), WTC1(0x204a04c0), WTC1(0x1fa82540), WTC1(0x1f06e300), WTC1(0x1e664000), + WTC1(0x1dc63bc0), WTC1(0x1d26d3c0), WTC1(0x1c8803a0), WTC1(0x1be9cc40), WTC1(0x1b4c34c0), WTC1(0x1aaf4480), WTC1(0x1a130260), WTC1(0x197774a0), + WTC1(0x18dca260), WTC1(0x184294e0), WTC1(0x17a95840), WTC1(0x1710fd80), WTC1(0x16799ce0), WTC1(0x15e35340), WTC1(0x154e41a0), WTC1(0x14ba8360), + WTC1(0x14282be0), WTC1(0x13975100), WTC1(0x13080aa0), WTC1(0x127a6240), WTC1(0x11ee50a0), WTC1(0x1163cc80), WTC1(0x10dacb20), WTC1(0x105333a0), + WTC1(0x0fccdb30), WTC1(0x0f478f40), WTC1(0x0ec31700), WTC1(0x0e3f4e80), WTC1(0x0dbc27f0), WTC1(0x0d399000), WTC1(0x0cb76d00), WTC1(0x0c359d50), + WTC1(0x0bb3fd50), WTC1(0x0b326bd0), WTC1(0x0ab0ca80), WTC1(0x0a2f0dc0), WTC1(0x09ad40c0), WTC1(0x092b7a90), WTC1(0x08a9db80), WTC1(0x08285c80), + WTC1(0x07a6c7b8), WTC1(0x0724e4e0), WTC1(0x06a27b80), WTC1(0x061f52f8), WTC1(0x059b2ad0), WTC1(0x0515b568), WTC1(0x048ea058), WTC1(0x04066408), + WTC1(0x037e52d8), WTC1(0x02f7d3c8), WTC1(0x0274614c), WTC1(0x01f63008), WTC1(0x0180403a), WTC1(0x0115c442), WTC1(0x00ba09e2), WTC1(0x006f077c), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfff36be1), WTC2(0xffdafbc1), WTC2(0xffc28035), WTC2(0xffa9fe8a), WTC2(0xff917c08), WTC2(0xff78fdfc), WTC2(0xff6089af), WTC2(0xff48246c), + WTC2(0xff2fd37f), WTC2(0xff179c31), WTC2(0xfeff83b6), WTC2(0xfee78d18), WTC2(0xfecfb93e), WTC2(0xfeb808f2), WTC2(0xfea07d06), WTC2(0xfe8916b4), + WTC2(0xfe71d7a0), WTC2(0xfe5ac174), WTC2(0xfe43d5d6), WTC2(0xfe2d167e), WTC2(0xfe16852e), WTC2(0xfe0023a6), WTC2(0xfde9f3f8), WTC2(0xfdd3ff7c), + WTC2(0xfdbe56c0), WTC2(0xfda90aa8), WTC2(0xfd942b78), WTC2(0xfd7fbb20), WTC2(0xfd6bad50), WTC2(0xfd57f510), WTC2(0xfd44857c), WTC2(0xfd3153fc), + WTC2(0xfd1e5840), WTC2(0xfd0b8a0c), WTC2(0xfcf8e180), WTC2(0xfce65eec), WTC2(0xfcd40ad0), WTC2(0xfcc1ee0c), WTC2(0xfcb011e8), WTC2(0xfc9e896c), + WTC2(0xfc8d716c), WTC2(0xfc7ce720), WTC2(0xfc6d072c), WTC2(0xfc5de09c), WTC2(0xfc4f74e8), WTC2(0xfc41c4e8), WTC2(0xfc34d0dc), WTC2(0xfc288a68), + WTC2(0xfc1cd49c), WTC2(0xfc1191e0), WTC2(0xfc06a4d0), WTC2(0xfbfbf3e8), WTC2(0xfbf16990), WTC2(0xfbe6f068), WTC2(0xfbdc7428), WTC2(0xfbd1fc68), + WTC2(0xfbc7ac50), WTC2(0xfbbda868), WTC2(0xfbb41500), WTC2(0xfbab1438), WTC2(0xfba2c5f8), WTC2(0xfb9b4a00), WTC2(0xfb94bfa8), WTC2(0xfb8f3b48), + WTC2(0xfb8ac638), WTC2(0xfb876970), WTC2(0xfb852d20), WTC2(0xfb840ae0), WTC2(0xfb83ed60), WTC2(0xfb84bec0), WTC2(0xfb866918), WTC2(0xfb88d4a8), + WTC2(0xfb8be810), WTC2(0xfb8f89d0), WTC2(0xfb93a080), WTC2(0xfb981418), WTC2(0xfb9ccdf0), WTC2(0xfba1b770), WTC2(0xfba6bae0), WTC2(0xfbabd5c0), + WTC2(0xfbb118d8), WTC2(0xfbb695c0), WTC2(0xfbbc5e90), WTC2(0xfbc29030), WTC2(0xfbc95268), WTC2(0xfbd0cd78), WTC2(0xfbd929c8), WTC2(0xfbe294d0), + WTC2(0xfbed4108), WTC2(0xfbf96118), WTC2(0xfc0726c8), WTC2(0xfc16b064), WTC2(0xfc280890), WTC2(0xfc3b3920), WTC2(0xfc504a98), WTC2(0xfc67271c), + WTC2(0xfc7f9a74), WTC2(0xfc996f18), WTC2(0xfcb46eb8), WTC2(0xfcd050b0), WTC2(0xfcecba24), WTC2(0xfd094f64), WTC2(0xfd25b720), WTC2(0xfd41ce40), + WTC2(0xfd5da7f8), WTC2(0xfd7959d8), WTC2(0xfd94fb74), WTC2(0xfdb0d3fc), WTC2(0xfdcd5a34), WTC2(0xfdeb06e4), WTC2(0xfe0a5184), WTC2(0xfe2b92c4), + WTC2(0xfe4f0486), WTC2(0xfe74df54), WTC2(0xfe9d5886), WTC2(0xfec85b92), WTC2(0xfef58a16), WTC2(0xff248275), WTC2(0xff54e401), WTC2(0xff866330), + WTC2(0xffb8c99b), WTC2(0xffebe1c9), WTC2(0x001f786a), WTC2(0x00538bf9), WTC2(0x00884cbc), WTC2(0x00bded23), WTC2(0x00f49f54), WTC2(0x012c8ee4), + WTC2(0x0165e0d2), WTC2(0x01a0b9d6), WTC2(0x01dd3d80), WTC2(0x021b74d4), WTC2(0x025b4e48), WTC2(0x029cb730), WTC2(0x02df9d0c), WTC2(0x0323f1a4), + WTC2(0x0369ab00), WTC2(0x03b0bf5c), WTC2(0x03f925a0), WTC2(0x0442e3d8), WTC2(0x048e0f40), WTC2(0x04dabdb0), WTC2(0x05290430), WTC2(0x0578e428), + WTC2(0x05ca4b60), WTC2(0x061d26c0), WTC2(0x067163d8), WTC2(0x06c6ff10), WTC2(0x071e03b0), WTC2(0x07767da0), WTC2(0x07d07918), WTC2(0x082c08e0), + WTC2(0x08894660), WTC2(0x08e84b70), WTC2(0x094930b0), WTC2(0x09abf8d0), WTC2(0x0a109020), WTC2(0x0a76e210), WTC2(0x0adeda50), WTC2(0x0b486b80), + WTC2(0x0bb38f00), WTC2(0x0c203e80), WTC2(0x0c8e73e0), WTC2(0x0cfe2c30), WTC2(0x0d6f6820), WTC2(0x0de22850), WTC2(0x0e566d90), WTC2(0x0ecc3dd0), + WTC2(0x0f43a3a0), WTC2(0x0fbca9f0), WTC2(0x10375b80), WTC2(0x10b3be20), WTC2(0x1131d280), WTC2(0x11b19960), WTC2(0x123313a0), WTC2(0x12b64380), + WTC2(0x133b2d00), WTC2(0x13c1d440), WTC2(0x144a3d60), WTC2(0x14d46900), WTC2(0x15605480), WTC2(0x15edfd20), WTC2(0x167d6040), WTC2(0x170e7e80), + WTC2(0x17a15b80), WTC2(0x1835fb00), WTC2(0x18cc60a0), WTC2(0x19648dc0), WTC2(0x19fe80e0), WTC2(0x1a9a38a0), WTC2(0x1b37b3e0), WTC2(0x1bd6f400), + WTC2(0x1c77fd20), WTC2(0x1d1ad400), WTC2(0x1dbf7c80), WTC2(0x1e65f820), WTC2(0x1f0e4540), WTC2(0x1fb861e0), WTC2(0x20644cc0), WTC2(0x21120640), + WTC2(0x21c19240), WTC2(0x2272f480), WTC2(0x23263000), WTC2(0x23db4580), WTC2(0x24923340), WTC2(0x254af700), WTC2(0x26058e80), WTC2(0x26c1fa00), + WTC2(0x27803d00), WTC2(0x28405a40), WTC2(0x29025500), WTC2(0x29c62d40), WTC2(0x2a8be0c0), WTC2(0x2b536cc0), WTC2(0x2c1ccf80), WTC2(0x2ce80840), + WTC2(0x2db519c0), WTC2(0x2e840600), WTC2(0x2f54cf80), WTC2(0x302775c0), WTC2(0x30fbf640), WTC2(0x31d24e00), WTC2(0x32aa7a00), WTC2(0x338479c0), + WTC2(0x34604e40), WTC2(0x353df900), WTC2(0x361d7ac0), WTC2(0x36fed200), WTC2(0x37e1fb40), WTC2(0x38c6f240), WTC2(0x39adb2c0), WTC2(0x3a963a00), + WTC2(0x3b808740), WTC2(0x3c6c9880), WTC2(0x3d5a6cc0), WTC2(0x3e4a0040), WTC2(0x3f3b4bc0), WTC2(0x402e48ff), WTC2(0x4122f17f), WTC2(0x42193f7f), + WTC2(0x43112eff), WTC2(0x440abbff), WTC2(0x4505e2ff), WTC2(0x46029e7f), WTC2(0x4700e9ff), WTC2(0x4800bfff), WTC2(0x49021bff), WTC2(0x4a050eff), + WTC2(0x4b09bc7f), WTC2(0x4c104aff), WTC2(0x4d18df7f), WTC2(0x4e23a07f), WTC2(0x4f30b2ff), WTC2(0x50403c7f), WTC2(0x515262ff), WTC2(0x52674b7f), + WTC2(0x001678b2), WTC2(0x00061a3b), WTC2(0xfffb4622), WTC2(0xfff5ea94), WTC2(0xfff5f5b9), WTC2(0xfffb55bd), WTC2(0x0005f8cb), WTC2(0x0015cd0c), + WTC2(0x002ac0ac), WTC2(0x0044c1d5), WTC2(0x0063beb2), WTC2(0x0087a56d), WTC2(0x00b06431), WTC2(0x00dde929), WTC2(0x01102280), WTC2(0x0146fe5e), + WTC2(0x01826af2), WTC2(0x01c25662), WTC2(0x0206aedc), WTC2(0x024f6288), WTC2(0x029c5f94), WTC2(0x02ed9424), WTC2(0x0342ee6c), WTC2(0x039c5c90), + WTC2(0x03f9ccbc), WTC2(0x045b2d18), WTC2(0x04c06bd8), WTC2(0x05297718), WTC2(0x05963d10), WTC2(0x0606abe8), WTC2(0x067ab1c0), WTC2(0x06f23cd0), + WTC2(0x076d3b40), WTC2(0x07eb9b38), WTC2(0x086d4ae0), WTC2(0x08f23860), WTC2(0x097a51f0), WTC2(0x0a0585b0), WTC2(0x0a93c1d0), WTC2(0x0b24f470), + WTC2(0x0bb90bc0), WTC2(0x0c4ff5f0), WTC2(0x0ce9a130), WTC2(0x0d85fb90), WTC2(0x0e24f360), WTC2(0x0ec676b0), WTC2(0x0f6a73b0), WTC2(0x1010d880), + WTC2(0x10b99360), WTC2(0x11649280), WTC2(0x1211c400), WTC2(0x12c115e0), WTC2(0x137276a0), WTC2(0x1425d420), WTC2(0x14db1ca0), WTC2(0x15923e60), + WTC2(0x164b2780), WTC2(0x1705c620), WTC2(0x17c20860), WTC2(0x187fdca0), WTC2(0x193f30e0), WTC2(0x19fff340), WTC2(0x1ac21200), WTC2(0x1b857b40), + WTC2(0x1c4a1d40), WTC2(0x1d0fe600), WTC2(0x1dd6c3e0), WTC2(0x1e9ea4e0), WTC2(0x1f677740), WTC2(0x20312940), WTC2(0x20fba8c0), WTC2(0x21c6e440), + WTC2(0x2292c9c0), WTC2(0x235f4780), WTC2(0x242c4b80), WTC2(0x24f9c400), WTC2(0x25c79f40), WTC2(0x2695cb40), WTC2(0x27643680), WTC2(0x2832cec0), + WTC2(0x29018240), WTC2(0x29d03f80), WTC2(0x2a9ef480), WTC2(0x2b6d8f00), WTC2(0x2c3bfdc0), WTC2(0x2d0a2ec0), WTC2(0x2dd81000), WTC2(0x2ea58fc0), + WTC2(0x2f729c40), WTC2(0x303f2380), WTC2(0x310b1400), WTC2(0x31d65b80), WTC2(0x32a0e840), WTC2(0x336aa8c0), WTC2(0x34338ac0), WTC2(0x34fb7cc0), + WTC2(0x35c26cc0), WTC2(0x36884900), WTC2(0x374cff80), WTC2(0x38107e80), WTC2(0x38d2b440), WTC2(0x39938ec0), WTC2(0x3a52fc40), WTC2(0x3b10eb00), + WTC2(0x3bcd4900), WTC2(0x3c880480), WTC2(0x3d410bc0), WTC2(0x3df84d00), WTC2(0x3eadb600), WTC2(0x3f613540), WTC2(0x4012b8ff), WTC2(0x40c22eff), + WTC2(0x416f85ff), WTC2(0x421aab7f), WTC2(0x42c38e7f), WTC2(0x436a1c7f), WTC2(0x440e437f), WTC2(0x44aff27f), WTC2(0x454f167f), WTC2(0x45eb9eff), + WTC2(0x468578ff), WTC2(0x471c937f), WTC2(0x47b0dc7f), WTC2(0x484241ff), WTC2(0x48d0b1ff), WTC2(0x495c1a7f), WTC2(0x49e46a7f), WTC2(0x4a698f7f), + WTC2(0x4aeb77ff), WTC2(0x4b6a11ff), WTC2(0x4be54b7f), WTC2(0x4c5d12ff), WTC2(0x4cd155ff), WTC2(0x4d4203ff), WTC2(0x4daf09ff), WTC2(0x4e18567f), + WTC2(0x4e7dd77f), WTC2(0x4edf7b7f), WTC2(0x4f3d307f), WTC2(0x4f96e47f), WTC2(0x4fec85ff), WTC2(0x503e02ff), WTC2(0x508b497f), WTC2(0x50d447ff), + WTC2(0x5118ec7f), WTC2(0x515924ff), WTC2(0x5194dfff), WTC2(0x51cc0b7f), WTC2(0x51fe95ff), WTC2(0x522c6cff), WTC2(0x52557eff), WTC2(0x5279b9ff), + WTC2(0x52990c7f), WTC2(0x52b364ff), WTC2(0x52c8b07f), WTC2(0x52d8ddff), WTC2(0x52e3db7f), WTC2(0x52e996ff), WTC2(0x52e9ff7f), WTC2(0x52e501ff), + WTC2(0x52da8cff), WTC2(0x52ca8f7f), WTC2(0x52b4f67f), WTC2(0x5299b07f), WTC2(0x5278ac7f), WTC2(0x5251d77f), WTC2(0x52251fff), WTC2(0x51f274ff), + WTC2(0x51b9c37f), WTC2(0x517af9ff), WTC2(0x5136077f), WTC2(0x50ead8ff), WTC2(0x50995cff), WTC2(0x504181ff), WTC2(0x4fe335ff), WTC2(0x4f7e677f), + WTC2(0x4f1303ff), WTC2(0x4ea0f9ff), WTC2(0x4e2837ff), WTC2(0x4da8ab7f), WTC2(0x4d2242ff), WTC2(0x4c94ecff), WTC2(0x4c0096ff), WTC2(0x4b652f7f), + WTC2(0x4ac2a4ff), WTC2(0x4a18e4ff), WTC2(0x4967ddff), WTC2(0x48af7e7f), WTC2(0x47efb3ff), WTC2(0x47286cff), WTC2(0x4659ad7f), WTC2(0x45856f7f), + WTC2(0x44afa3ff), WTC2(0x43dc507f), WTC2(0x430f657f), WTC2(0x424ad47f), WTC2(0x418e927f), WTC2(0x40da7bff), WTC2(0x402e6f7f), WTC2(0x3f8a3100), + WTC2(0x3eed6f40), WTC2(0x3e57d700), WTC2(0x3dc914c0), WTC2(0x3d40cc40), WTC2(0x3cbe98c0), WTC2(0x3c421540), WTC2(0x3bcadbc0), WTC2(0x3b588880), + WTC2(0x3aeab780), WTC2(0x3a810540), WTC2(0x3a1b0e00), WTC2(0x39b86d00), WTC2(0x3958bcc0), WTC2(0x38fb9700), WTC2(0x38a095c0), WTC2(0x38473d80), + WTC2(0x37eeff40), WTC2(0x37974b40), WTC2(0x373f9500), WTC2(0x36e7ae00), WTC2(0x368fc4c0), WTC2(0x36380b80), WTC2(0x35e0b300), WTC2(0x3589c140), + WTC2(0x35331180), WTC2(0x34dc7c80), WTC2(0x3485dc80), WTC2(0x342f1600), WTC2(0x33d81780), WTC2(0x3380d0c0), WTC2(0x33293100), WTC2(0x32d11800), + WTC2(0x32785780), WTC2(0x321ec0c0), WTC2(0x31c42680), WTC2(0x316885c0), WTC2(0x310c0580), WTC2(0x30aecec0), WTC2(0x30510940), WTC2(0x2ff2b8c0), + WTC2(0x2f93bf40), WTC2(0x2f33fc00), WTC2(0x2ed350c0), WTC2(0x2e71ba80), WTC2(0x2e0f5340), WTC2(0x2dac35c0), WTC2(0x2d487c80), WTC2(0x2ce431c0), + WTC2(0x2c7f4fc0), WTC2(0x2c19d080), WTC2(0x2bb3ad80), WTC2(0x2b4ce080), WTC2(0x2ae56340), WTC2(0x2a7d2f80), WTC2(0x2a143f00), WTC2(0x29aa8b40) +}; + +const FIXP_WTB ELDAnalysis480[1440] = { + WTC0(0xfacfbef0), WTC0(0xfab88c18), WTC0(0xfaa0e520), WTC0(0xfa88d110), WTC0(0xfa7056e8), WTC0(0xfa577db0), WTC0(0xfa3e4c70), WTC0(0xfa24ca28), + WTC0(0xfa0afde0), WTC0(0xf9f0eea0), WTC0(0xf9d6a2c8), WTC0(0xf9bc1ab8), WTC0(0xf9a15230), WTC0(0xf9864510), WTC0(0xf96af058), WTC0(0xf94f55c0), + WTC0(0xf93378e0), WTC0(0xf9175d80), WTC0(0xf8fb0468), WTC0(0xf8de68b8), WTC0(0xf8c18438), WTC0(0xf8a450d8), WTC0(0xf886cde8), WTC0(0xf8690148), + WTC0(0xf84af148), WTC0(0xf82ca410), WTC0(0xf80e1e18), WTC0(0xf7ef62a0), WTC0(0xf7d074e0), WTC0(0xf7b15870), WTC0(0xf7921240), WTC0(0xf772a7a0), + WTC0(0xf7531e50), WTC0(0xf7337820), WTC0(0xf713afd0), WTC0(0xf6f3bea0), WTC0(0xf6d39dc0), WTC0(0xf6b352e0), WTC0(0xf692f280), WTC0(0xf6729250), + WTC0(0xf65247a0), WTC0(0xf63224c0), WTC0(0xf6123a00), WTC0(0xf5f297c0), WTC0(0xf5d34dd0), WTC0(0xf5b46b10), WTC0(0xf595fd90), WTC0(0xf5781390), + WTC0(0xf55abba0), WTC0(0xf53e0510), WTC0(0xf521ff70), WTC0(0xf506ba30), WTC0(0xf4ec4330), WTC0(0xf4d2a680), WTC0(0xf4b9efe0), WTC0(0xf4a22ac0), + WTC0(0xf48b5f70), WTC0(0xf4759310), WTC0(0xf460cde0), WTC0(0xf44cfcc0), WTC0(0xf439aff0), WTC0(0xf4264e00), WTC0(0xf4123d90), WTC0(0xf3fd1370), + WTC0(0xf3e6be00), WTC0(0xf3cf41a0), WTC0(0xf3b6a030), WTC0(0xf39cdd60), WTC0(0xf381fe00), WTC0(0xf3660760), WTC0(0xf348fe70), WTC0(0xf32ae820), + WTC0(0xf30bc940), WTC0(0xf2eba690), WTC0(0xf2ca8480), WTC0(0xf2a86670), WTC0(0xf2854f40), WTC0(0xf2614190), WTC0(0xf23c41e0), WTC0(0xf21657a0), + WTC0(0xf1ef8ae0), WTC0(0xf1c7e3e0), WTC0(0xf19f63d0), WTC0(0xf1760450), WTC0(0xf14bbdf0), WTC0(0xf1208960), WTC0(0xf0f45cd0), WTC0(0xf0c72ce0), + WTC0(0xf098ee00), WTC0(0xf06996f0), WTC0(0xf0392620), WTC0(0xf0079e10), WTC0(0xefd4ffc0), WTC0(0xefa15ca0), WTC0(0xef6ce600), WTC0(0xef37d460), + WTC0(0xef025f80), WTC0(0xeecca2c0), WTC0(0xee969760), WTC0(0xee603440), WTC0(0xee296d20), WTC0(0xedf21c00), WTC0(0xedba07e0), WTC0(0xed80f640), + WTC0(0xed46bf40), WTC0(0xed0b7b00), WTC0(0xeccf5fc0), WTC0(0xec92a120), WTC0(0xec556d60), WTC0(0xec17e700), WTC0(0xebda2d40), WTC0(0xeb9c5fa0), + WTC0(0xeb5e7040), WTC0(0xeb201b20), WTC0(0xeae117c0), WTC0(0xeaa12000), WTC0(0xea600180), WTC0(0xea1d9940), WTC0(0xe9d9c160), WTC0(0xe99468a0), + WTC0(0xe94dc040), WTC0(0xe9061940), WTC0(0xe8bdc140), WTC0(0xe8750ae0), WTC0(0xe82c4fa0), WTC0(0xe7e3ea40), WTC0(0xe79c35e0), WTC0(0xe7554ca0), + WTC0(0xe70efc00), WTC0(0xe6c90c20), WTC0(0xe6833f00), WTC0(0xe63d2300), WTC0(0xe5f620a0), WTC0(0xe5ad9dc0), WTC0(0xe5632080), WTC0(0xe5169da0), + WTC0(0xe4c83e60), WTC0(0xe4782400), WTC0(0xe4269840), WTC0(0xe3d42dc0), WTC0(0xe38188c0), WTC0(0xe32f4be0), WTC0(0xe2ddeea0), WTC0(0xe28db520), + WTC0(0xe23ee000), WTC0(0xe1f1a580), WTC0(0xe1a5e3a0), WTC0(0xe15b35a0), WTC0(0xe1113860), WTC0(0xe0c78a00), WTC0(0xe07dd0e0), WTC0(0xe033b7c0), + WTC0(0xdfe8e680), WTC0(0xdf9d1fc0), WTC0(0xdf5055c0), WTC0(0xdf0287c0), WTC0(0xdeb3b340), WTC0(0xde63e7c0), WTC0(0xde134a00), WTC0(0xddc20000), + WTC0(0xdd703180), WTC0(0xdd1e1280), WTC0(0xdccbe080), WTC0(0xdc79d980), WTC0(0xdc283600), WTC0(0xdbd71e00), WTC0(0xdb86b140), WTC0(0xdb3710c0), + WTC0(0xdae850c0), WTC0(0xda9a6bc0), WTC0(0xda4d5640), WTC0(0xda010640), WTC0(0xd9b56640), WTC0(0xd96a5700), WTC0(0xd91fb700), WTC0(0xd8d56600), + WTC0(0xd88b4a40), WTC0(0xd8414f00), WTC0(0xd7f75f80), WTC0(0xd7ad6740), WTC0(0xd76352c0), WTC0(0xd7191040), WTC0(0xd6ce8c80), WTC0(0xd683bd00), + WTC0(0xd638a5c0), WTC0(0xd5ed4f80), WTC0(0xd5a1c240), WTC0(0xd5562b80), WTC0(0xd50ae500), WTC0(0xd4c04c80), WTC0(0xd476bb40), WTC0(0xd42e62c0), + WTC0(0xd3e75680), WTC0(0xd3a1ad00), WTC0(0xd35d6780), WTC0(0xd31a4300), WTC0(0xd2d7dc00), WTC0(0xd295d080), WTC0(0xd253d8c0), WTC0(0xd211df40), + WTC0(0xd1cfdbc0), WTC0(0xd18dc480), WTC0(0xd14b9dc0), WTC0(0xd1097c80), WTC0(0xd0c77700), WTC0(0xd085a500), WTC0(0xd0442f40), WTC0(0xd0034a80), + WTC0(0xcfc32c00), WTC0(0xcf840400), WTC0(0xcf45f400), WTC0(0xcf0913c0), WTC0(0xcecd8000), WTC0(0xce932c80), WTC0(0xce59bf40), WTC0(0xce20cd40), + WTC0(0xcde7ec40), WTC0(0xcdaeedc0), WTC0(0xcd75ea00), WTC0(0xcd3cfec0), WTC0(0xcd044b40), WTC0(0xcccbff00), WTC0(0xcc945480), WTC0(0xcc5d8780), + WTC0(0xcc27c3c0), WTC0(0xcbf2fc40), WTC0(0xcbbf0a00), WTC0(0xcb8bc7c0), WTC0(0xcb591880), WTC0(0xcb26f0c0), WTC0(0xcaf54980), WTC0(0xcac41ac0), + WTC0(0xca936440), WTC0(0xca632d80), WTC0(0xca337f00), WTC0(0xca046180), WTC0(0xc9d5dd40), WTC0(0xc9a7fa80), WTC0(0xc97ac200), WTC0(0xc94e3c00), + WTC0(0xc91d1840), WTC0(0xc8f15980), WTC0(0xc8c52340), WTC0(0xc8988100), WTC0(0xc86b7f00), WTC0(0xc83e28c0), WTC0(0xc8108a80), WTC0(0xc7e2afc0), + WTC0(0xc7b4a480), WTC0(0xc7867480), WTC0(0xc7582b40), WTC0(0xc729cc80), WTC0(0xc6fb5700), WTC0(0xc6ccca40), WTC0(0xc69e2180), WTC0(0xc66f49c0), + WTC0(0xc64029c0), WTC0(0xc610a740), WTC0(0xc5e0bfc0), WTC0(0xc5b09e80), WTC0(0xc5807900), WTC0(0xc5508440), WTC0(0xc520e840), WTC0(0xc4f1bdc0), + WTC0(0xc4c31d00), WTC0(0xc4951780), WTC0(0xc4678a00), WTC0(0xc43a28c0), WTC0(0xc40ca800), WTC0(0xc3deccc0), WTC0(0xc3b09940), WTC0(0xc3822c00), + WTC0(0xc353a0c0), WTC0(0xc3251740), WTC0(0xc2f6b500), WTC0(0xc2c8a140), WTC0(0xc29b02c0), WTC0(0xc26df5c0), WTC0(0xc2418940), WTC0(0xc215cbc0), + WTC0(0xc1eaca00), WTC0(0xc1c08680), WTC0(0xc196fb00), WTC0(0xc16e22c0), WTC0(0xc145f040), WTC0(0xc11e3a80), WTC0(0xc0f6cc00), WTC0(0xc0cf6ec0), + WTC0(0xc0a802c0), WTC0(0xc0809280), WTC0(0xc0593340), WTC0(0xc031f880), WTC0(0xc00b04c0), WTC0(0xbfe48981), WTC0(0xbfbebb81), WTC0(0xbf99cb01), + WTC0(0xbf75cc81), WTC0(0xbf52c101), WTC0(0xbf30a901), WTC0(0xbf0f8301), WTC0(0xbeef4601), WTC0(0xbecfe601), WTC0(0xbeb15701), WTC0(0xbe938c81), + WTC0(0xbe767e81), WTC0(0xbe5a2301), WTC0(0xbe3e7201), WTC0(0xbe236001), WTC0(0xbe08e181), WTC0(0xbdeee981), WTC0(0xbdd56b81), WTC0(0xbdbc6381), + WTC0(0xbda3d081), WTC0(0xbd8bb281), WTC0(0xbd740b81), WTC0(0xbd5ce281), WTC0(0xbd464281), WTC0(0xbd303581), WTC0(0xbd1ac801), WTC0(0xbd060c81), + WTC0(0xbcf21601), WTC0(0xbcdef701), WTC0(0xbcccbd01), WTC0(0xbcbb7001), WTC0(0xbcab1781), WTC0(0xbc9bb901), WTC0(0xbc8d5101), WTC0(0xbc7fd301), + WTC0(0xbc733401), WTC0(0xbc676501), WTC0(0xbc5c4c81), WTC0(0xbc51cb01), WTC0(0xbc47c281), WTC0(0xbc3e1981), WTC0(0xbc34c081), WTC0(0xbc2bab01), + WTC0(0xbc22cd81), WTC0(0xbc1a2401), WTC0(0xbc11b681), WTC0(0xbc098d81), WTC0(0xbc01b381), WTC0(0xbbfa3c01), WTC0(0xbbf34281), WTC0(0xbbece281), + WTC0(0xbbe73201), WTC0(0xbbe23281), WTC0(0xbbdddb01), WTC0(0xbbda2501), WTC0(0xbbd70201), WTC0(0xbbd45601), WTC0(0xbbd20301), WTC0(0xbbcfea81), + WTC0(0xbbce0601), WTC0(0xbbcc6b01), WTC0(0xbbcb3201), WTC0(0xbbca7481), WTC0(0xbbca5d01), WTC0(0xbbcb2281), WTC0(0xbbccfc81), WTC0(0xbbd01301), + WTC0(0xbbd45881), WTC0(0xbbd9a781), WTC0(0xbbdfdb81), WTC0(0xbbe6c801), WTC0(0xbbee2f81), WTC0(0xbbf5d181), WTC0(0xbbfd6c01), WTC0(0xbc04e381), + WTC0(0xbc0c4581), WTC0(0xbc13a481), WTC0(0xbc1b1081), WTC0(0xbc228f01), WTC0(0xbc2a1a81), WTC0(0xbc31af01), WTC0(0xbc394901), WTC0(0xbc40e881), + WTC0(0xbc488e81), WTC0(0xbc503b81), WTC0(0xbc57f101), WTC0(0xbc5fae81), WTC0(0xbc677501), WTC0(0xbc6f4401), WTC0(0xbc771c01), WTC0(0xbc7efc81), + WTC0(0xbc86e581), WTC0(0xbc8ed701), WTC0(0xbc96d101), WTC0(0xbc9ed481), WTC0(0xbca6e101), WTC0(0xbcaef701), WTC0(0xbcb71701), WTC0(0xbcbf4001), + WTC0(0xbcc77181), WTC0(0xbccfac01), WTC0(0xbcd7ef01), WTC0(0xbce03b81), WTC0(0xbce89281), WTC0(0xbcf0f381), WTC0(0xbcf95e81), WTC0(0xbd01d281), + WTC0(0xbd0a4f81), WTC0(0xbd12d581), WTC0(0xbd1b6501), WTC0(0xbd23ff01), WTC0(0xbd2ca281), WTC0(0xbd355081), WTC0(0xbd3e0801), WTC0(0xbd46c801), + WTC0(0xbd4f9101), WTC0(0xbd586281), WTC0(0xbd613d81), WTC0(0xbd6a2201), WTC0(0xbd731081), WTC0(0xbd7c0781), WTC0(0xbd850701), WTC0(0xbd8e0e01), + WTC0(0xbd971c81), WTC0(0xbda03381), WTC0(0xbda95301), WTC0(0xbdb27b01), WTC0(0xbdbbab01), WTC0(0xbdc4e301), WTC0(0xbdce2181), WTC0(0xbdd76701), + WTC0(0xbde0b301), WTC0(0xbdea0681), WTC0(0xbdf36101), WTC0(0xbdfcc301), WTC0(0xbe062b81), WTC0(0xbe0f9a01), WTC0(0xbe190d81), WTC0(0xbe228681), + WTC0(0xbe2c0501), WTC0(0xbe358901), WTC0(0xbe3f1381), WTC0(0xbe48a301), WTC0(0xbe523781), WTC0(0xbe5bd001), WTC0(0xbe656c01), WTC0(0xbe6f0c01), + WTC0(0xbe78b001), WTC0(0xbe825801), WTC0(0xbe8c0501), WTC0(0xbe95b581), WTC0(0xbe9f6901), WTC0(0xbea91f01), WTC0(0xbeb2d681), WTC0(0xbebc9181), + WTC0(0xbec64e81), WTC0(0xbed00f81), WTC0(0xbed9d281), WTC0(0xbee39801), WTC0(0xbeed5f01), WTC0(0xbef72681), WTC0(0xbf00ef81), WTC0(0xbf0aba01), + WTC0(0xbf148681), WTC0(0xbf1e5501), WTC0(0xbf282501), WTC0(0xbf31f501), WTC0(0xbf3bc601), WTC0(0xbf459681), WTC0(0xbf4f6801), WTC0(0xbf593a01), + WTC0(0xbf630d81), WTC0(0xbf6ce201), WTC0(0xbf76b701), WTC0(0xbf808b81), WTC0(0xbf8a5f81), WTC0(0xbf943301), WTC0(0xbf9e0701), WTC0(0xbfa7dc01), + WTC0(0xbfb1b101), WTC0(0xbfbb8701), WTC0(0xbfc55c81), WTC0(0xbfcf3181), WTC0(0xbfd90601), WTC0(0xbfe2d901), WTC0(0xbfecaa81), WTC0(0xbff67a01), + /* part 1 */ + WTC1(0x80130981), WTC1(0x80269f81), WTC1(0x803a3381), WTC1(0x804dc481), WTC1(0x80615281), WTC1(0x8074dc01), WTC1(0x80886081), WTC1(0x809bdf01), + WTC1(0x80af5701), WTC1(0x80c2c781), WTC1(0x80d63101), WTC1(0x80e99401), WTC1(0x80fcf181), WTC1(0x81104a01), WTC1(0x81239d81), WTC1(0x8136ea01), + WTC1(0x814a2f81), WTC1(0x815d6c01), WTC1(0x8170a181), WTC1(0x8183cf81), WTC1(0x8196f781), WTC1(0x81aa1981), WTC1(0x81bd3401), WTC1(0x81d04681), + WTC1(0x81e34f81), WTC1(0x81f64f01), WTC1(0x82094581), WTC1(0x821c3401), WTC1(0x822f1b01), WTC1(0x8241fa01), WTC1(0x8254cf01), WTC1(0x82679901), + WTC1(0x827a5801), WTC1(0x828d0b01), WTC1(0x829fb401), WTC1(0x82b25301), WTC1(0x82c4e801), WTC1(0x82d77201), WTC1(0x82e9ef01), WTC1(0x82fc5f01), + WTC1(0x830ec081), WTC1(0x83211501), WTC1(0x83335c81), WTC1(0x83459881), WTC1(0x8357c701), WTC1(0x8369e781), WTC1(0x837bf801), WTC1(0x838df801), + WTC1(0x839fe801), WTC1(0x83b1c881), WTC1(0x83c39a81), WTC1(0x83d55d01), WTC1(0x83e70f01), WTC1(0x83f8b001), WTC1(0x840a3e81), WTC1(0x841bb981), + WTC1(0x842d2281), WTC1(0x843e7a81), WTC1(0x844fc081), WTC1(0x8460f581), WTC1(0x84721701), WTC1(0x84832481), WTC1(0x84941d81), WTC1(0x84a50201), + WTC1(0x84b5d301), WTC1(0x84c69101), WTC1(0x84d73c01), WTC1(0x84e7d381), WTC1(0x84f85581), WTC1(0x8508c181), WTC1(0x85191801), WTC1(0x85295881), + WTC1(0x85398481), WTC1(0x85499d01), WTC1(0x8559a081), WTC1(0x85698e81), WTC1(0x85796601), WTC1(0x85892681), WTC1(0x8598d081), WTC1(0x85a86581), + WTC1(0x85b7e601), WTC1(0x85c75201), WTC1(0x85d6a981), WTC1(0x85e5eb81), WTC1(0x85f51681), WTC1(0x86042c01), WTC1(0x86132c01), WTC1(0x86221801), + WTC1(0x8630f181), WTC1(0x863fb701), WTC1(0x864e6901), WTC1(0x865d0581), WTC1(0x866b8d81), WTC1(0x867a0081), WTC1(0x86886001), WTC1(0x8696ad01), + WTC1(0x86a4e781), WTC1(0x86b30f01), WTC1(0x86c12401), WTC1(0x86cf2601), WTC1(0x86dd1481), WTC1(0x86eaf081), WTC1(0x86f8ba81), WTC1(0x87067281), + WTC1(0x87141b01), WTC1(0x8721b481), WTC1(0x872f4201), WTC1(0x873cc201), WTC1(0x874a2f01), WTC1(0x87578181), WTC1(0x8764b101), WTC1(0x8771c601), + WTC1(0x877ede01), WTC1(0x878c1881), WTC1(0x87998f01), WTC1(0x87a70e81), WTC1(0x87b42481), WTC1(0x87c05e81), WTC1(0x87cb5101), WTC1(0x87d4ac81), + WTC1(0x87e73d81), WTC1(0x88124281), WTC1(0x88353501), WTC1(0x885f8481), WTC1(0x888d3181), WTC1(0x88be1681), WTC1(0x88f13801), WTC1(0x8925f101), + WTC1(0x895bcd01), WTC1(0x89925a81), WTC1(0x89c92f81), WTC1(0x8a001f01), WTC1(0x8a372881), WTC1(0x8a6e4a01), WTC1(0x8aa58681), WTC1(0x8adcee01), + WTC1(0x8b149701), WTC1(0x8b4c9701), WTC1(0x8b850281), WTC1(0x8bbde981), WTC1(0x8bf75b01), WTC1(0x8c316681), WTC1(0x8c6c1b01), WTC1(0x8ca78781), + WTC1(0x8ce3ba81), WTC1(0x8d20c301), WTC1(0x8d5eaa01), WTC1(0x8d9d7781), WTC1(0x8ddd3201), WTC1(0x8e1de001), WTC1(0x8e5f8881), WTC1(0x8ea23201), + WTC1(0x8ee5e301), WTC1(0x8f2aa101), WTC1(0x8f706f01), WTC1(0x8fb74f81), WTC1(0x8fff4601), WTC1(0x90485401), WTC1(0x90927b81), WTC1(0x90ddc001), + WTC1(0x912a2201), WTC1(0x9177a301), WTC1(0x91c64301), WTC1(0x92160301), WTC1(0x9266e281), WTC1(0x92b8e101), WTC1(0x930bff81), WTC1(0x93603d01), + WTC1(0x93b59901), WTC1(0x940c1281), WTC1(0x9463a881), WTC1(0x94bc5981), WTC1(0x95162381), WTC1(0x95710601), WTC1(0x95ccff01), WTC1(0x962a0c81), + WTC1(0x96882e01), WTC1(0x96e76101), WTC1(0x9747a481), WTC1(0x97a8f681), WTC1(0x980b5501), WTC1(0x986ebd81), WTC1(0x98d32d81), WTC1(0x9938a281), + WTC1(0x999f1981), WTC1(0x9a069001), WTC1(0x9a6f0381), WTC1(0x9ad87081), WTC1(0x9b42d581), WTC1(0x9bae2f81), WTC1(0x9c1a7c81), WTC1(0x9c87ba81), + WTC1(0x9cf5e701), WTC1(0x9d650081), WTC1(0x9dd50481), WTC1(0x9e45f081), WTC1(0x9eb7c101), WTC1(0x9f2a7281), WTC1(0x9f9e0301), WTC1(0xa0127081), + WTC1(0xa087b981), WTC1(0xa0fddd81), WTC1(0xa174da81), WTC1(0xa1ecae01), WTC1(0xa2655581), WTC1(0xa2dece81), WTC1(0xa3591801), WTC1(0xa3d43001), + WTC1(0xa4501601), WTC1(0xa4ccc901), WTC1(0xa54a4701), WTC1(0xa5c89001), WTC1(0xa647a301), WTC1(0xa6c77e01), WTC1(0xa7482101), WTC1(0xa7c98b01), + WTC1(0xa84bbb81), WTC1(0xa8ceb201), WTC1(0xa9526d81), WTC1(0xa9d6ef01), WTC1(0xaa5c3601), WTC1(0xaae24301), WTC1(0xab691681), WTC1(0xabf0b181), + WTC1(0xac791401), WTC1(0xad023f01), WTC1(0xad8c3301), WTC1(0xae16f001), WTC1(0xaea27681), WTC1(0xaf2ec901), WTC1(0xafbbe801), WTC1(0xb049d601), + WTC1(0xb0d89401), WTC1(0xb1682281), WTC1(0xb1f88181), WTC1(0xb289b181), WTC1(0xb31bb301), WTC1(0xb3ae8601), WTC1(0xb4422b81), WTC1(0xb4d6a381), + WTC1(0x4a5a327f), WTC1(0x49c4adff), WTC1(0x492e637f), WTC1(0x48974f7f), WTC1(0x47ff6d7f), WTC1(0x4766baff), WTC1(0x46cd35ff), WTC1(0x4632dd7f), + WTC1(0x4597b0ff), WTC1(0x44fbb1ff), WTC1(0x445eeaff), WTC1(0x43c165ff), WTC1(0x4323227f), WTC1(0x4284277f), WTC1(0x41e48aff), WTC1(0x4144557f), + WTC1(0x40a3867f), WTC1(0x4001f5ff), WTC1(0x3f5f5d80), WTC1(0x3ebbad00), WTC1(0x3e16ee40), WTC1(0x3d713d00), WTC1(0x3ccab700), WTC1(0x3c236500), + WTC1(0x3b7b5800), WTC1(0x3ad2ecc0), WTC1(0x3a2a6540), WTC1(0x3981b7c0), WTC1(0x38d8ba00), WTC1(0x382f01c0), WTC1(0x37846240), WTC1(0x36d8eb00), + WTC1(0x362c9ec0), WTC1(0x357f7a00), WTC1(0x34d18340), WTC1(0x3422c900), WTC1(0x33736c40), WTC1(0x32c39040), WTC1(0x32134280), WTC1(0x31629280), + WTC1(0x30b1a000), WTC1(0x30008380), WTC1(0x2f4f4240), WTC1(0x2e9df180), WTC1(0x2decc780), WTC1(0x2d3bd640), WTC1(0x2c8b0cc0), WTC1(0x2bda3080), + WTC1(0x2b28ec80), WTC1(0x2a773500), WTC1(0x29c51b40), WTC1(0x291293c0), WTC1(0x285f9280), WTC1(0x27ac35c0), WTC1(0x26f8ab40), WTC1(0x26454c00), + WTC1(0x25925600), WTC1(0x24dfd580), WTC1(0x242ddd40), WTC1(0x237c87c0), WTC1(0x22cbe240), WTC1(0x221bef40), WTC1(0x216cb040), WTC1(0x20be2800), + WTC1(0x20105c80), WTC1(0x1f6352a0), WTC1(0x1eb71240), WTC1(0x1e0ba140), WTC1(0x1d60fe40), WTC1(0x1cb723e0), WTC1(0x1c0e0300), WTC1(0x1b6596c0), + WTC1(0x1abde8a0), WTC1(0x1a16fbe0), WTC1(0x1970c680), WTC1(0x18cb4840), WTC1(0x18268e20), WTC1(0x1782a0c0), WTC1(0x16df8960), WTC1(0x163d6300), + WTC1(0x159c52c0), WTC1(0x14fc87e0), WTC1(0x145e2c80), WTC1(0x13c15b60), WTC1(0x13263240), WTC1(0x128cd9a0), WTC1(0x11f562a0), WTC1(0x115fc1c0), + WTC1(0x10cbf160), WTC1(0x1039f200), WTC1(0x0fa9a080), WTC1(0x0f1abd90), WTC1(0x0e8d01d0), WTC1(0x0e003330), WTC1(0x0d743590), WTC1(0x0ce8ef40), + WTC1(0x0c5e1900), WTC1(0x0bd35d70), WTC1(0x0b488eb0), WTC1(0x0abd8410), WTC1(0x0a320a00), WTC1(0x09a60e70), WTC1(0x0919ab00), WTC1(0x088d0de0), + WTC1(0x080065e0), WTC1(0x07739710), WTC1(0x06e65808), WTC1(0x06588348), WTC1(0x05ca0ae0), WTC1(0x053aaaf8), WTC1(0x04a9faf0), WTC1(0x0417f698), + WTC1(0x03859ff4), WTC1(0x02f49be4), WTC1(0x0266b668), WTC1(0x01de554e), WTC1(0x015f50ca), WTC1(0x00eb7e5d), WTC1(0x00904f24), WTC1(0x00212889), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfffece02), WTC2(0xffe4c3df), WTC2(0xffcaaa55), WTC2(0xffb087d1), WTC2(0xff9662bf), WTC2(0xff7c418b), WTC2(0xff622aa0), WTC2(0xff48246c), + WTC2(0xff2e355a), WTC2(0xff1463db), WTC2(0xfefab608), WTC2(0xfee12f0a), WTC2(0xfec7cfd2), WTC2(0xfeae995a), WTC2(0xfe958cc4), WTC2(0xfe7cabce), + WTC2(0xfe63f882), WTC2(0xfe4b74e0), WTC2(0xfe3322f6), WTC2(0xfe1b04dc), WTC2(0xfe031ccc), WTC2(0xfdeb6cf0), WTC2(0xfdd3ff7c), WTC2(0xfdbce834), + WTC2(0xfda63bb8), WTC2(0xfd900c68), WTC2(0xfd7a590c), WTC2(0xfd6511b4), WTC2(0xfd5026c0), WTC2(0xfd3b8954), WTC2(0xfd272df0), WTC2(0xfd130adc), + WTC2(0xfcff15ac), WTC2(0xfceb4a68), WTC2(0xfcd7b110), WTC2(0xfcc454d0), WTC2(0xfcb14064), WTC2(0xfc9e896c), WTC2(0xfc8c5264), WTC2(0xfc7abef0), + WTC2(0xfc69f078), WTC2(0xfc59f5e8), WTC2(0xfc4acfec), WTC2(0xfc3c8060), WTC2(0xfc2f0264), WTC2(0xfc223b7c), WTC2(0xfc160714), WTC2(0xfc0a4150), + WTC2(0xfbfec920), WTC2(0xfbf38320), WTC2(0xfbe855d0), WTC2(0xfbdd2740), WTC2(0xfbd1fc68), WTC2(0xfbc6fea0), WTC2(0xfbbc5a48), WTC2(0xfbb23b48), + WTC2(0xfba8ca78), WTC2(0xfba02e50), WTC2(0xfb988de0), WTC2(0xfb920b40), WTC2(0xfb8cb870), WTC2(0xfb889f68), WTC2(0xfb85cbe8), WTC2(0xfb843dd0), + WTC2(0xfb83df78), WTC2(0xfb8495d0), WTC2(0xfb864660), WTC2(0xfb88d4a8), WTC2(0xfb8c21e8), WTC2(0xfb900f28), WTC2(0xfb947dc0), WTC2(0xfb9950c0), + WTC2(0xfb9e6d08), WTC2(0xfba3b658), WTC2(0xfba91908), WTC2(0xfbae9e08), WTC2(0xfbb45bd0), WTC2(0xfbba66f8), WTC2(0xfbc0dcf0), WTC2(0xfbc7ead8), + WTC2(0xfbcfc200), WTC2(0xfbd89330), WTC2(0xfbe294d0), WTC2(0xfbee03d0), WTC2(0xfbfb1de8), WTC2(0xfc0a1da4), WTC2(0xfc1b22e0), WTC2(0xfc2e38f0), + WTC2(0xfc436d48), WTC2(0xfc5abf7c), WTC2(0xfc74024c), WTC2(0xfc8ef2e8), WTC2(0xfcab51ac), WTC2(0xfcc8d024), WTC2(0xfce704f0), WTC2(0xfd0580cc), + WTC2(0xfd23d4d0), WTC2(0xfd41ce40), WTC2(0xfd5f81b0), WTC2(0xfd7d08f0), WTC2(0xfd9a8560), WTC2(0xfdb85938), WTC2(0xfdd71798), WTC2(0xfdf753b8), + WTC2(0xfe1993ee), WTC2(0xfe3e30f8), WTC2(0xfe656cba), WTC2(0xfe8f8fdc), WTC2(0xfebca8a4), WTC2(0xfeec590e), WTC2(0xff1e285c), WTC2(0xff51a0b7), + WTC2(0xff866330), WTC2(0xffbc2cbb), WTC2(0xfff2bbff), WTC2(0x0029d79d), WTC2(0x00618a22), WTC2(0x009a1185), WTC2(0x00d3aa8c), WTC2(0x010e8ff6), + WTC2(0x014af29e), WTC2(0x0188fe56), WTC2(0x01c8e108), WTC2(0x020ab3c4), WTC2(0x024e68a8), WTC2(0x0293e824), WTC2(0x02db1bc8), WTC2(0x0323f1a4), + WTC2(0x036e5d6c), WTC2(0x03ba5320), WTC2(0x0407c938), WTC2(0x0456cad0), WTC2(0x04a77288), WTC2(0x04f9db88), WTC2(0x054e1888), WTC2(0x05a41ef0), + WTC2(0x05fbd6e0), WTC2(0x065528c0), WTC2(0x06b00838), WTC2(0x070c7ee0), WTC2(0x076a9bb0), WTC2(0x07ca6d10), WTC2(0x082c08e0), WTC2(0x088f8da0), + WTC2(0x08f51ac0), WTC2(0x095ccc20), WTC2(0x09c69f70), WTC2(0x0a327b40), WTC2(0x0aa046d0), WTC2(0x0b0febb0), WTC2(0x0b815dd0), WTC2(0x0bf49600), + WTC2(0x0c698c50), WTC2(0x0ce03ba0), WTC2(0x0d58a380), WTC2(0x0dd2c510), WTC2(0x0e4ea110), WTC2(0x0ecc3dd0), WTC2(0x0f4ba800), WTC2(0x0fcced10), + WTC2(0x10501960), WTC2(0x10d532a0), WTC2(0x115c39c0), WTC2(0x11e52fa0), WTC2(0x12701560), WTC2(0x12fcef20), WTC2(0x138bc200), WTC2(0x141c9300), + WTC2(0x14af64a0), WTC2(0x154434e0), WTC2(0x15db0020), WTC2(0x1673c360), WTC2(0x170e7e80), WTC2(0x17ab35e0), WTC2(0x1849ee40), WTC2(0x18eaaba0), + WTC2(0x198d6f00), WTC2(0x1a3236a0), WTC2(0x1ad90080), WTC2(0x1b81cc60), WTC2(0x1c2c9da0), WTC2(0x1cd97980), WTC2(0x1d8865c0), WTC2(0x1e396540), + WTC2(0x1eec7700), WTC2(0x1fa198c0), WTC2(0x2058c840), WTC2(0x21120640), WTC2(0x21cd5700), WTC2(0x228abec0), WTC2(0x234a4180), WTC2(0x240bdf80), + WTC2(0x24cf95c0), WTC2(0x259561c0), WTC2(0x265d4200), WTC2(0x27273840), WTC2(0x27f348c0), WTC2(0x28c17700), WTC2(0x2991c500), WTC2(0x2a643080), + WTC2(0x2b38b680), WTC2(0x2c0f53c0), WTC2(0x2ce80840), WTC2(0x2dc2d680), WTC2(0x2e9fc100), WTC2(0x2f7ecac0), WTC2(0x305ff280), WTC2(0x314334c0), + WTC2(0x32288e00), WTC2(0x330ffb80), WTC2(0x33f97d80), WTC2(0x34e515c0), WTC2(0x35d2c5c0), WTC2(0x36c28d00), WTC2(0x37b467c0), WTC2(0x38a85080), + WTC2(0x399e4240), WTC2(0x3a963a00), WTC2(0x3b903600), WTC2(0x3c8c3480), WTC2(0x3d8a3380), WTC2(0x3e8a2dc0), WTC2(0x3f8c1b40), WTC2(0x408ff2ff), + WTC2(0x4195ae7f), WTC2(0x429d477f), WTC2(0x43a6b87f), WTC2(0x44b1fdff), WTC2(0x45bf11ff), WTC2(0x46cdee7f), WTC2(0x47de8cff), WTC2(0x48f0e77f), + WTC2(0x4a050eff), WTC2(0x4b1b2dff), WTC2(0x4c3372ff), WTC2(0x4d4e0bff), WTC2(0x4e6b257f), WTC2(0x4f8aedff), WTC2(0x50ad92ff), WTC2(0x51d341ff), + WTC2(0x002006a9), WTC2(0x000bfb36), WTC2(0xfffe45ac), WTC2(0xfff6d064), WTC2(0xfff585bc), WTC2(0xfffa500d), WTC2(0x000519b4), WTC2(0x0015cd0c), + WTC2(0x002c5470), WTC2(0x00489a3b), WTC2(0x006a88c8), WTC2(0x00920a74), WTC2(0x00bf0999), WTC2(0x00f17092), WTC2(0x012929bc), WTC2(0x01661f70), + WTC2(0x01a83c0c), WTC2(0x01ef69e8), WTC2(0x023b9364), WTC2(0x028ca2d4), WTC2(0x02e2829c), WTC2(0x033d1d10), WTC2(0x039c5c90), WTC2(0x04002b78), + WTC2(0x04687418), WTC2(0x04d520e0), WTC2(0x05461c18), WTC2(0x05bb5020), WTC2(0x0634a758), WTC2(0x06b20c20), WTC2(0x073368c8), WTC2(0x07b8a7b0), + WTC2(0x0841b340), WTC2(0x08ce75b0), WTC2(0x095ed980), WTC2(0x09f2c900), WTC2(0x0a8a2e80), WTC2(0x0b24f470), WTC2(0x0bc30510), WTC2(0x0c644ad0), + WTC2(0x0d08b010), WTC2(0x0db01f10), WTC2(0x0e5a8250), WTC2(0x0f07c400), WTC2(0x0fb7cea0), WTC2(0x106a8c80), WTC2(0x111fe800), WTC2(0x11d7cb60), + WTC2(0x12922120), WTC2(0x134ed3a0), WTC2(0x140dcd00), WTC2(0x14cef7e0), WTC2(0x15923e60), WTC2(0x16578b00), WTC2(0x171ec820), WTC2(0x17e7e020), + WTC2(0x18b2bd20), WTC2(0x197f49c0), WTC2(0x1a4d7040), WTC2(0x1b1d1b00), WTC2(0x1bee3460), WTC2(0x1cc0a6a0), WTC2(0x1d945c40), WTC2(0x1e693f80), + WTC2(0x1f3f3ac0), WTC2(0x20163880), WTC2(0x20ee22c0), WTC2(0x21c6e440), WTC2(0x22a06740), WTC2(0x237a9600), WTC2(0x24555ac0), WTC2(0x2530a040), + WTC2(0x260c5080), WTC2(0x26e85600), WTC2(0x27c49b00), WTC2(0x28a10a00), WTC2(0x297d8d80), WTC2(0x2a5a0f80), WTC2(0x2b367a80), WTC2(0x2c12b8c0), + WTC2(0x2ceeb500), WTC2(0x2dca5940), WTC2(0x2ea58fc0), WTC2(0x2f804340), WTC2(0x305a5dc0), WTC2(0x3133ca00), WTC2(0x320c7200), WTC2(0x32e44000), + WTC2(0x33bb1ec0), WTC2(0x3490f880), WTC2(0x3565b7c0), WTC2(0x36394640), WTC2(0x370b8f00), WTC2(0x37dc7c00), WTC2(0x38abf7c0), WTC2(0x3979ecc0), + WTC2(0x3a464500), WTC2(0x3b10eb00), WTC2(0x3bd9c940), WTC2(0x3ca0c9c0), WTC2(0x3d65d740), WTC2(0x3e28dc00), WTC2(0x3ee9c240), WTC2(0x3fa87480), + WTC2(0x4064dcff), WTC2(0x411ee67f), WTC2(0x41d67a7f), WTC2(0x428b847f), WTC2(0x433ded7f), WTC2(0x43eda0ff), WTC2(0x449a887f), WTC2(0x45448f7f), + WTC2(0x45eb9eff), WTC2(0x468fa1ff), WTC2(0x473082ff), WTC2(0x47ce2c7f), WTC2(0x4868887f), WTC2(0x48ff80ff), WTC2(0x499300ff), WTC2(0x4a22f2ff), + WTC2(0x4aaf407f), WTC2(0x4b37d47f), WTC2(0x4bbc997f), WTC2(0x4c3d78ff), WTC2(0x4cba5e7f), WTC2(0x4d33337f), WTC2(0x4da7e27f), WTC2(0x4e18567f), + WTC2(0x4e8478ff), WTC2(0x4eec347f), WTC2(0x4f4f737f), WTC2(0x4fae20ff), WTC2(0x500825ff), WTC2(0x505d6dff), WTC2(0x50ade37f), WTC2(0x50f96f7f), + WTC2(0x513ffdff), WTC2(0x518177ff), WTC2(0x51bdc87f), WTC2(0x51f4d9ff), WTC2(0x5226967f), WTC2(0x5252e87f), WTC2(0x5279b9ff), WTC2(0x529af5ff), + WTC2(0x52b6867f), WTC2(0x52cc55ff), WTC2(0x52dc4eff), WTC2(0x52e65aff), WTC2(0x52ea657f), WTC2(0x52e857ff), WTC2(0x52e01d7f), WTC2(0x52d19fff), + WTC2(0x52bcc9ff), WTC2(0x52a1857f), WTC2(0x527fbd7f), WTC2(0x52575b7f), WTC2(0x52284a7f), WTC2(0x51f274ff), WTC2(0x51b5c47f), WTC2(0x5172247f), + WTC2(0x51277dff), WTC2(0x50d5bc7f), WTC2(0x507cc9ff), WTC2(0x501c90ff), WTC2(0x4fb4fb7f), WTC2(0x4f45f3ff), WTC2(0x4ecf64ff), WTC2(0x4e5138ff), + WTC2(0x4dcb597f), WTC2(0x4d3db1ff), WTC2(0x4ca82bff), WTC2(0x4c0ab27f), WTC2(0x4b652f7f), WTC2(0x4ab78d7f), WTC2(0x4a01b67f), WTC2(0x4943957f), + WTC2(0x487d12ff), WTC2(0x47ae1f7f), WTC2(0x46d68f7f), WTC2(0x45f7187f), WTC2(0x4513597f), WTC2(0x4430467f), WTC2(0x4352d2ff), WTC2(0x427e6bff), + WTC2(0x41b390ff), WTC2(0x40f2077f), WTC2(0x4039a87f), WTC2(0x3f8a3100), WTC2(0x3ee33e00), WTC2(0x3e446ac0), WTC2(0x3dad5180), WTC2(0x3d1d7fc0), + WTC2(0x3c947b00), WTC2(0x3c11c7c0), WTC2(0x3b94ebc0), WTC2(0x3b1d6dc0), WTC2(0x3aaad480), WTC2(0x3a3ca740), WTC2(0x39d26c40), WTC2(0x396ba8c0), + WTC2(0x3907e080), WTC2(0x38a69800), WTC2(0x38473d80), WTC2(0x37e923c0), WTC2(0x378b9b80), WTC2(0x372e0380), WTC2(0x36d03a80), WTC2(0x36727f00), + WTC2(0x36150e40), WTC2(0x35b81540), WTC2(0x355b8000), WTC2(0x34ff1dc0), WTC2(0x34a2bfc0), WTC2(0x34463e80), WTC2(0x33e982c0), WTC2(0x338c7880), + WTC2(0x332f0bc0), WTC2(0x32d11800), WTC2(0x327265c0), WTC2(0x3212bbc0), WTC2(0x31b1e740), WTC2(0x314fef00), WTC2(0x30ed0540), WTC2(0x30895c80), + WTC2(0x30251880), WTC2(0x2fc02880), WTC2(0x2f5a6480), WTC2(0x2ef3a480), WTC2(0x2e8bd640), WTC2(0x2e231100), WTC2(0x2db97680), WTC2(0x2d4f2700), + WTC2(0x2ce431c0), WTC2(0x2c789080), WTC2(0x2c0c3bc0), WTC2(0x2b9f2bc0), WTC2(0x2b315940), WTC2(0x2ac2bc00), WTC2(0x2a534cc0), WTC2(0x29e303c0) +}; + + diff --git a/libAACenc/src/aacEnc_rom.h b/libAACenc/src/aacEnc_rom.h new file mode 100644 index 00000000..862417f0 --- /dev/null +++ b/libAACenc/src/aacEnc_rom.h @@ -0,0 +1,203 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/****************************************************************************** + + Initial authors: M. Lohwasser, M. Gayer + Contents/description: + +******************************************************************************/ +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AAC_ENC_ROM_H +#define AAC_ENC_ROM_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "psy_configuration.h" +#include "FDK_tools_rom.h" + +/* + Huffman Tables +*/ +extern const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab5_6[9][9]; +extern const ULONG FDKaacEnc_huff_ltab7_8[8][8]; +extern const ULONG FDKaacEnc_huff_ltab9_10[13][13]; +extern const UCHAR FDKaacEnc_huff_ltab11[17][17]; +extern const UCHAR FDKaacEnc_huff_ltabscf[121]; +extern const USHORT FDKaacEnc_huff_ctab1[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab2[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab3[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab4[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab5[9][9]; +extern const USHORT FDKaacEnc_huff_ctab6[9][9]; +extern const USHORT FDKaacEnc_huff_ctab7[8][8]; +extern const USHORT FDKaacEnc_huff_ctab8[8][8]; +extern const USHORT FDKaacEnc_huff_ctab9[13][13]; +extern const USHORT FDKaacEnc_huff_ctab10[13][13]; +extern const USHORT FDKaacEnc_huff_ctab11[21][17]; +extern const ULONG FDKaacEnc_huff_ctabscf[121]; + +/* + quantizer +*/ +#define MANT_DIGITS 9 +#define MANT_SIZE (1< +#include "aacenc.h" + +#include "bitenc.h" +#include "interface.h" +#include "psy_configuration.h" +#include "psy_main.h" +#include "qc_main.h" +#include "bandwidth.h" +#include "channel_map.h" +#include "tns_func.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + + + + +#define MIN_BUFSIZE_PER_EFF_CHAN 6144 + +INT FDKaacEnc_CalcBitsPerFrame( + const INT bitRate, + const INT frameLength, + const INT samplingRate + ) +{ + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength + && (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) + { + shift++; + } + + return (bitRate*(frameLength>>shift)) / (samplingRate>>shift); +} + +INT FDKaacEnc_CalcBitrate( + const INT bitsPerFrame, + const INT frameLength, + const INT samplingRate + ) +{ + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength + && (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) + { + shift++; + } + + return (bitsPerFrame * (samplingRate>>shift)) / ( frameLength>>shift) ; + +} + +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate, + INT framelength, + INT ancillaryRate, + INT *ancillaryBitsPerFrame, + INT sampleRate); + +INT FDKaacEnc_LimitBitrate( + HANDLE_TRANSPORTENC hTpEnc, + INT coreSamplingRate, + INT frameLength, + INT nChannels, + INT nChannelsEff, + INT bitRate, + INT averageBits, + INT *pAverageBitsPerFrame, + INT bitrateMode, + INT nSubFrames + ) +{ + INT transportBits, prevBitRate, averageBitsPerFrame, shift = 0, iter=0; + + while ( (frameLength & ~((1<<(shift+1))-1)) == frameLength + && (coreSamplingRate & ~((1<<(shift+1))-1)) == coreSamplingRate ) + { + shift ++; + } + + do { + prevBitRate = bitRate; + averageBitsPerFrame = (bitRate*(frameLength>>shift)) / (coreSamplingRate>>shift) / nSubFrames; + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): averageBitsPerFrame=%d, prevBitRate=%d, nSubFrames=%d\n", averageBitsPerFrame, prevBitRate, bitRate); + + if (pAverageBitsPerFrame != NULL) { + *pAverageBitsPerFrame = averageBitsPerFrame; + } + + if (hTpEnc != NULL) { + transportBits = transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame); + } else { + /* Assume some worst case */ + transportBits = 208; + } + + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): transportBits=%d, FDKmax(%d, %d)\n", transportBits, bitRate, + // ((((40 * nChannels) + transportBits) * (coreSamplingRate)) / frameLength)); + bitRate = FDKmax(bitRate, ((((40 * nChannels) + transportBits) * (coreSamplingRate)) / frameLength) ); + FDK_ASSERT(bitRate >= 0); + + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): FDKmin(%d, %d)\n", bitRate, ((nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN)*(coreSamplingRate>>shift)) / (frameLength>>shift)); + bitRate = FDKmin(bitRate, ((nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN)*(coreSamplingRate>>shift)) / (frameLength>>shift)) ; + FDK_ASSERT(bitRate >= 0); + + } while (prevBitRate != bitRate && iter++ < 3) ; + + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): bitRate=%d\n", bitRate); + return bitRate; +} + + +typedef struct +{ + AACENC_BITRATE_MODE bitrateMode; + int chanBitrate[2]; /* mono/stereo settings */ +} CONFIG_TAB_ENTRY_VBR; + +static const CONFIG_TAB_ENTRY_VBR configTabVBR[] = { + {AACENC_BR_MODE_CBR, { 0, 0}} , + {AACENC_BR_MODE_VBR_1, { 32000, 20000}} , + {AACENC_BR_MODE_VBR_2, { 40000, 32000}} , + {AACENC_BR_MODE_VBR_3, { 56000, 48000}} , + {AACENC_BR_MODE_VBR_4, { 72000, 64000}} , + {AACENC_BR_MODE_VBR_5, {112000, 96000}} +}; + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + + ------------------------------------------------------------------------------*/ +INT FDKaacEnc_GetVBRBitrate(INT bitrateMode, CHANNEL_MODE channelMode) +{ + INT bitrate = 0; + INT monoStereoMode = 0; /* default mono */ + + if (FDKaacEnc_GetMonoStereoMode(channelMode)==EL_MODE_STEREO) { + monoStereoMode = 1; + } + + switch((AACENC_BITRATE_MODE)bitrateMode){ + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + bitrate = configTabVBR[bitrateMode].chanBitrate[monoStereoMode]; + break; + case AACENC_BR_MODE_INVALID: + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + default: + bitrate = 0; + break; + } + + /* convert channel bitrate to overall bitrate*/ + bitrate *= FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; + + return bitrate; +} + +/** + * \brief Convert encoder bitreservoir value for transport library. + * + * \param hAacEnc Encoder handle + * + * \return Corrected bitreservoir level used in transport library. + */ +static INT FDKaacEnc_EncBitresToTpBitres( + const HANDLE_AAC_ENC hAacEnc + ) +{ + INT transporBitreservoir = 0; + + switch (hAacEnc->bitrateMode) { + case AACENC_BR_MODE_CBR: + transporBitreservoir = hAacEnc->qcKernel->bitResTot; /* encoder bitreservoir level */ + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + transporBitreservoir = FDK_INT_MAX; /* signal variable bitrate */ + break; + case AACENC_BR_MODE_FF: + case AACENC_BR_MODE_SFR: + transporBitreservoir = 0; /* super framing and fixed framing */ + break; /* without bitreservoir signaling */ + default: + case AACENC_BR_MODE_INVALID: + transporBitreservoir = 0; /* invalid configuration*/ + FDK_ASSERT(0); + } + + if (hAacEnc->config->audioMuxVersion==2) { + transporBitreservoir = MIN_BUFSIZE_PER_EFF_CHAN * hAacEnc->channelMapping.nChannelsEff; + } + + return transporBitreservoir; +} + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config) +{ + /* make thepre initialization of the structs flexible */ + FDKmemclear(config, sizeof(AACENC_CONFIG)); + + /* default ancillary */ + config->anc_Rate = 0; /* no ancillary data */ + config->ancDataBitRate = 0; /* no additional consumed bitrate */ + + /* default configurations */ + config->bitRate = -1; /* bitrate must be set*/ + config->averageBits = -1; /* instead of bitrate/s we can configure bits/superframe */ + config->bitrateMode = 0; + config->bandWidth = 0; /* get bandwidth from table */ + config->useTns = TNS_ENABLE_MASK; /* tns enabled completly */ + config->usePns = 1; /* depending on channelBitrate this might be set to 0 later */ + config->useIS = 1; /* Intensity Stereo Configuration */ + config->framelength = -1; /* Framesize not configured */ + config->syntaxFlags = 0; /* default syntax with no specialities */ + config->epConfig = -1; /* no ER syntax -> no additional error protection */ + config->nSubFrames = 1; /* default, no sub frames */ + config->channelOrder = CH_ORDER_MPEG; /* Use MPEG channel ordering. */ + config->channelMode = MODE_UNKNOWN; + config->minBitsPerFrame = -1; /* minum number of bits in each AU */ + config->maxBitsPerFrame = -1; /* minum number of bits in each AU */ + config->bitreservoir = -1; /* default, uninitialized value */ + config->audioMuxVersion = -1; /* audio mux version not configured */ + + /* init tabs in fixpoint_math */ + InitLdInt(); + InitInvSqrtTab(); +} + + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc, + const INT nElements, + const INT nChannels, + const INT nSubFrames) +{ + AAC_ENCODER_ERROR ErrorStatus; + AAC_ENC *hAacEnc = NULL; + UCHAR *dynamicRAM = NULL; + + if (phAacEnc==NULL) { + return AAC_ENC_INVALID_HANDLE; + } + + /* allocate encoder structure */ + hAacEnc = GetRam_aacEnc_AacEncoder(); + if (hAacEnc == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + FDKmemclear(hAacEnc, sizeof(AAC_ENC)); + + hAacEnc->dynamic_RAM = GetAACdynamic_RAM(); + dynamicRAM = (UCHAR*)hAacEnc->dynamic_RAM; + + /* allocate the Psy aud Psy Out structure */ + ErrorStatus = FDKaacEnc_PsyNew(&hAacEnc->psyKernel, + nElements, + nChannels + ,dynamicRAM + ); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + ErrorStatus = FDKaacEnc_PsyOutNew(hAacEnc->psyOut, + nElements, + nChannels, + nSubFrames + ,dynamicRAM + ); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + /* allocate the Q&C Out structure */ + ErrorStatus = FDKaacEnc_QCOutNew(hAacEnc->qcOut, + nElements, + nChannels, + nSubFrames + ,dynamicRAM + ); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + /* allocate the Q&C kernel */ + ErrorStatus = FDKaacEnc_QCNew(&hAacEnc->qcKernel, + nElements + ,dynamicRAM + ); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + hAacEnc->maxChannels = nChannels; + hAacEnc->maxElements = nElements; + hAacEnc->maxFrames = nSubFrames; + +bail: + *phAacEnc = hAacEnc; + return ErrorStatus; +} + + +AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEnc, + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, + ULONG initFlags) +{ + AAC_ENCODER_ERROR ErrorStatus; + INT psyBitrate, tnsMask; //INT profile = 1; + CHANNEL_MAPPING *cm = NULL; + + INT qmbfac, qbw; + FIXP_DBL mbfac, bw_ratio; + QC_INIT qcInit; + INT averageBitsPerFrame = 0; + + if (config==NULL) + return AAC_ENC_INVALID_HANDLE; + + /******************* sanity checks *******************/ + + /* check config structure */ + if (config->nChannels < 1 || config->nChannels > (8)) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + /* check sample rate */ + switch (config->sampleRate) + { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + case 24000: + case 32000: + case 44100: + case 48000: + case 64000: + case 88200: + case 96000: + break; + default: + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* bitrate has to be set */ + if (config->bitRate==-1) { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + INT superframe_size = 110*8*(config->bitRate/8000); + INT frames_per_superframe = 6; + INT staticBits = 0; + if((config->syntaxFlags & AC_DAB) && hTpEnc) { + staticBits = transportEnc_GetStaticBits(hTpEnc, 0); + switch(config->sampleRate) { + case 48000: + frames_per_superframe=6; + break; + case 32000: + frames_per_superframe=4; + break; + case 24000: + frames_per_superframe=3; + break; + case 16000: + frames_per_superframe=2; + break; + } + + //config->nSubFrames = frames_per_superframe; + //fprintf(stderr, "DAB+ superframe size=%d\n", superframe_size); + config->bitRate = (superframe_size - 16*(frames_per_superframe-1) - staticBits) * 1000/120; + //fprintf(stderr, "DAB+ tuned bitrate=%d\n", config->bitRate); + config->maxBitsPerFrame = (superframe_size - 16*(frames_per_superframe-1) - staticBits) / frames_per_superframe; + config->maxBitsPerFrame += 7; /*padding*/ + //config->bitreservoir=(superframe_size - 16*(frames_per_superframe-1) - staticBits - 2*8)/frames_per_superframe; + //fprintf(stderr, "DAB+ tuned maxBitsPerFrame=%d\n", (superframe_size - 16*(frames_per_superframe-1) - staticBits)/frames_per_superframe); + } + + /* check bit rate */ + + if (FDKaacEnc_LimitBitrate( + hTpEnc, + config->sampleRate, + config->framelength, + config->nChannels, + FDKaacEnc_GetChannelModeConfiguration(config->channelMode)->nChannelsEff, + config->bitRate, + config->averageBits, + &averageBitsPerFrame, + config->bitrateMode, + config->nSubFrames + ) != config->bitRate + && !((config->bitrateMode>=1) && (config->bitrateMode<=5)) + ) + { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + if (config->syntaxFlags & AC_ER_VCB11) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + if (config->syntaxFlags & AC_ER_HCR) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + + /* check frame length */ + switch (config->framelength) + { + case 1024: + case 960: //TODO: DRM + if ( config->audioObjectType == AOT_ER_AAC_LD + || config->audioObjectType == AOT_ER_AAC_ELD ) + { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + case 512: + case 480: + if ( config->audioObjectType != AOT_ER_AAC_LD + && config->audioObjectType != AOT_ER_AAC_ELD ) + { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + if (config->anc_Rate != 0) { + + ErrorStatus = FDKaacEnc_InitCheckAncillary(config->bitRate, + config->framelength, + config->anc_Rate, + &hAacEnc->ancillaryBitsPerFrame, + config->sampleRate); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + + /* update estimated consumed bitrate */ + config->ancDataBitRate += ( (hAacEnc->ancillaryBitsPerFrame * config->sampleRate) / config->framelength ); + + } + + /* maximal allowed DSE bytes in frame */ + { + /* fixpoint calculation*/ + INT q_res, encBitrate, sc; + FIXP_DBL tmp = fDivNorm(config->framelength, config->sampleRate, &q_res); + encBitrate = (config->bitRate/*-config->ancDataBitRate*/)- (INT)(config->nChannels*8000); + sc = CountLeadingBits(encBitrate); + config->maxAncBytesPerAU = FDKmin( (256), FDKmax(0,(INT)(fMultDiv2(tmp, (FIXP_DBL)(encBitrate<>(-q_res+sc-1+3))) ); + } + + /* bind config to hAacEnc->config */ + hAacEnc->config = config; + + /* set hAacEnc->bitrateMode */ + hAacEnc->bitrateMode = (AACENC_BITRATE_MODE)config->bitrateMode; + + hAacEnc->encoderMode = config->channelMode; + + ErrorStatus = FDKaacEnc_InitChannelMapping(hAacEnc->encoderMode, config->channelOrder, &hAacEnc->channelMapping); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + cm = &hAacEnc->channelMapping; + + ErrorStatus = FDKaacEnc_DetermineBandWidth(&hAacEnc->config->bandWidth, + config->bandWidth, + config->bitRate - config->ancDataBitRate, + hAacEnc->bitrateMode, + config->sampleRate, + config->framelength, + cm, + hAacEnc->encoderMode); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + hAacEnc->bandwidth90dB = (INT)hAacEnc->config->bandWidth; + + tnsMask = config->useTns ? TNS_ENABLE_MASK : 0x0; + psyBitrate = config->bitRate - config->ancDataBitRate; + + ErrorStatus = FDKaacEnc_psyInit(hAacEnc->psyKernel, + hAacEnc->psyOut, + hAacEnc->maxFrames, + hAacEnc->maxChannels, + config->audioObjectType, + cm); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + ErrorStatus = FDKaacEnc_psyMainInit(hAacEnc->psyKernel, + config->audioObjectType, + cm, + config->sampleRate, + config->framelength, + psyBitrate, + tnsMask, + hAacEnc->bandwidth90dB, + config->usePns, + config->useIS, + config->syntaxFlags, + initFlags); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + ErrorStatus = FDKaacEnc_QCOutInit(hAacEnc->qcOut, hAacEnc->maxFrames, cm); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + + + qcInit.channelMapping = &hAacEnc->channelMapping; + qcInit.sceCpe = 0; + + if ((config->bitrateMode>=1) && (config->bitrateMode<=5)) { + qcInit.averageBits = (averageBitsPerFrame+7)&~7; + qcInit.bitRes = MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff; + qcInit.maxBits = MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff; + qcInit.maxBits = (config->maxBitsPerFrame!=-1) ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) : qcInit.maxBits; + qcInit.maxBits = fixMax(qcInit.maxBits, (averageBitsPerFrame+7)&~7); + qcInit.minBits = (config->minBitsPerFrame!=-1) ? config->minBitsPerFrame : 0; + qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame&~7); + } + else + { + int maxBitres; + qcInit.averageBits = (averageBitsPerFrame+7)&~7; + maxBitres = (MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff) - qcInit.averageBits; + qcInit.bitRes = (config->bitreservoir!=-1) ? FDKmin(config->bitreservoir, maxBitres) : maxBitres; + //fprintf(stderr, "qcInit.bitRes=%d\n", qcInit.bitRes); + + qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes); + qcInit.maxBits = (config->maxBitsPerFrame!=-1) ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) : qcInit.maxBits; + qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN*cm->nChannelsEff, fixMax(qcInit.maxBits, (averageBitsPerFrame+7+8)&~7)); + + qcInit.minBits = fixMax(0, ((averageBitsPerFrame-1)&~7)-qcInit.bitRes-transportEnc_GetStaticBits(hTpEnc, ((averageBitsPerFrame+7)&~7)+qcInit.bitRes)); + qcInit.minBits = (config->minBitsPerFrame!=-1) ? fixMax(qcInit.minBits, config->minBitsPerFrame) : qcInit.minBits; + qcInit.minBits = fixMin(qcInit.minBits, (averageBitsPerFrame - transportEnc_GetStaticBits(hTpEnc, qcInit.maxBits))&~7); + } + + qcInit.sampleRate = config->sampleRate; + qcInit.advancedBitsToPe = isLowDelay(config->audioObjectType) ? 1 : 0 ; + qcInit.nSubFrames = config->nSubFrames; + qcInit.padding.paddingRest = config->sampleRate; + + /* Calc meanPe: qcInit.meanPe = 10.0f * FRAME_LEN_LONG * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */ + bw_ratio = fDivNorm((FIXP_DBL)(10*config->framelength*hAacEnc->bandwidth90dB), (FIXP_DBL)(config->sampleRate), &qbw); + qcInit.meanPe = FDKmax((INT)scaleValue(bw_ratio, qbw+1-(DFRACT_BITS-1)), 1); + + /* Calc maxBitFac */ + mbfac = fDivNorm((MIN_BUFSIZE_PER_EFF_CHAN-744)*cm->nChannelsEff, qcInit.averageBits/qcInit.nSubFrames, &qmbfac); + qmbfac = DFRACT_BITS-1-qmbfac; + qcInit.maxBitFac = (qmbfac > 24) ? (mbfac >> (qmbfac - 24)):(mbfac << (24 - qmbfac)); + + switch(config->bitrateMode){ + case AACENC_BR_MODE_CBR: + qcInit.bitrateMode = QCDATA_BR_MODE_CBR; + break; + case AACENC_BR_MODE_VBR_1: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_1; + break; + case AACENC_BR_MODE_VBR_2: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_2; + break; + case AACENC_BR_MODE_VBR_3: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_3; + break; + case AACENC_BR_MODE_VBR_4: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_4; + break; + case AACENC_BR_MODE_VBR_5: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_5; + break; + case AACENC_BR_MODE_SFR: + qcInit.bitrateMode = QCDATA_BR_MODE_SFR; + break; + case AACENC_BR_MODE_FF: + qcInit.bitrateMode = QCDATA_BR_MODE_FF; + break; + default: + ErrorStatus = AAC_ENC_UNSUPPORTED_BITRATE_MODE; + goto bail; + } + + qcInit.invQuant = (config->useRequant)?2:0; + + /* maxIterations should be set to the maximum number of requantization iterations that are + * allowed before the crash recovery functionality is activated. This setting should be adjusted + * to the processing power available, i.e. to the processing power headroom in one frame that is + * still left after normal encoding without requantization. Please note that if activated this + * functionality is used most likely only in cases where the encoder is operating beyond + * recommended settings, i.e. the audio quality is suboptimal anyway. Activating the crash + * recovery does not further reduce audio quality significantly in these cases. */ + if ( (config->audioObjectType == AOT_ER_AAC_LD) || (config->audioObjectType == AOT_ER_AAC_ELD) ) { + qcInit.maxIterations = 2; + } + else + { + qcInit.maxIterations = 5; + } + + qcInit.bitrate = config->bitRate - config->ancDataBitRate; + + qcInit.staticBits = transportEnc_GetStaticBits(hTpEnc, qcInit.averageBits/qcInit.nSubFrames); + + ErrorStatus = FDKaacEnc_QCInit(hAacEnc->qcKernel, &qcInit); + if (ErrorStatus != AAC_ENC_OK) + goto bail; + + hAacEnc->aot = hAacEnc->config->audioObjectType; + + /* common things */ + + return AAC_ENC_OK; + +bail: + + return ErrorStatus; +} + + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encodes one frame + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, + INT_PCM* RESTRICT inputBuffer, + INT* nOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS] + ) +{ + AAC_ENCODER_ERROR ErrorStatus; + int el, n, c=0; + UCHAR extPayloadUsed[MAX_TOTAL_EXT_PAYLOADS]; + + CHANNEL_MAPPING *cm = &hAacEnc->channelMapping; + + + + PSY_OUT *psyOut = hAacEnc->psyOut[c]; + QC_OUT *qcOut = hAacEnc->qcOut[c]; + + FDKmemclear(extPayloadUsed, MAX_TOTAL_EXT_PAYLOADS * sizeof(UCHAR)); + + qcOut->elementExtBits = 0; /* sum up all extended bit of each element */ + qcOut->staticBits = 0; /* sum up side info bits of each element */ + qcOut->totalNoRedPe = 0; /* sum up PE */ + + /* advance psychoacoustics */ + for (el=0; elnElements; el++) { + ELEMENT_INFO elInfo = cm->elInfo[el]; + //fprintf(stderr, "elInfo.elType=%d\n", elInfo.elType); + + if ( (elInfo.elType == ID_SCE) + || (elInfo.elType == ID_CPE) + || (elInfo.elType == ID_LFE) ) + { + int ch; + + /* update pointer!*/ + for(ch=0;chpsyOutElement[el]->psyOutChannel[ch]; + QC_OUT_CHANNEL *qcOutChan = qcOut->qcElement[el]->qcOutChannel[ch]; + + psyOutChan->mdctSpectrum = qcOutChan->mdctSpectrum; + psyOutChan->sfbSpreadEnergy = qcOutChan->sfbSpreadEnergy; + psyOutChan->sfbEnergy = qcOutChan->sfbEnergy; + psyOutChan->sfbEnergyLdData = qcOutChan->sfbEnergyLdData; + psyOutChan->sfbMinSnrLdData = qcOutChan->sfbMinSnrLdData; + psyOutChan->sfbThresholdLdData = qcOutChan->sfbThresholdLdData; + + } + + FDKaacEnc_psyMain(elInfo.nChannelsInEl, + hAacEnc->psyKernel->psyElement[el], + hAacEnc->psyKernel->psyDynamic, + hAacEnc->psyKernel->psyConf, + psyOut->psyOutElement[el], + inputBuffer, + cm->elInfo[el].ChannelIndex, + cm->nChannels + + ); + + /* FormFactor, Pe and staticBitDemand calculation */ + ErrorStatus = FDKaacEnc_QCMainPrepare(&elInfo, + hAacEnc->qcKernel->hAdjThr->adjThrStateElem[el], + psyOut->psyOutElement[el], + qcOut->qcElement[el], + hAacEnc->aot, + hAacEnc->config->syntaxFlags, + hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + /*-------------------------------------------- */ + + qcOut->qcElement[el]->extBitsUsed = 0; + qcOut->qcElement[el]->nExtensions = 0; + /* reset extension payload */ + FDKmemclear(&qcOut->qcElement[el]->extension, (1)*sizeof(QC_OUT_EXTENSION)); + + for ( n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++ ) { + if ( !extPayloadUsed[n] + && (extPayload[n].associatedChElement == el) + && (extPayload[n].dataSize > 0) + && (extPayload[n].pData != NULL) ) + { + int idx = qcOut->qcElement[el]->nExtensions++; + + qcOut->qcElement[el]->extension[idx].type = extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->qcElement[el]->extension[idx].nPayloadBits = extPayload[n].dataSize; + qcOut->qcElement[el]->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the data with the current bitstream syntax: */ + qcOut->qcElement[el]->extBitsUsed += + FDKaacEnc_writeExtensionData( NULL, + &qcOut->qcElement[el]->extension[idx], + 0, 0, + hAacEnc->config->syntaxFlags, + hAacEnc->aot, + hAacEnc->config->epConfig ); + extPayloadUsed[n] = 1; + } + } + + /* sum up extension and static bits for all channel elements */ + qcOut->elementExtBits += qcOut->qcElement[el]->extBitsUsed; + qcOut->staticBits += qcOut->qcElement[el]->staticBitsUsed; + + /* sum up pe */ + qcOut->totalNoRedPe += qcOut->qcElement[el]->peData.pe; + } + } + + qcOut->nExtensions = 0; + qcOut->globalExtBits = 0; + + /* reset extension payload */ + FDKmemclear(&qcOut->extension, (2+2)*sizeof(QC_OUT_EXTENSION)); + + /* Add extension payload not assigned to an channel element + (Ancillary data is the only supported type up to now) */ + for ( n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++ ) { + if ( !extPayloadUsed[n] + && (extPayload[n].associatedChElement == -1) + && (extPayload[n].pData != NULL) ) + { + UINT payloadBits = 0; + + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + if (hAacEnc->ancillaryBitsPerFrame) { + /* granted frame dse bitrate */ + payloadBits = hAacEnc->ancillaryBitsPerFrame; + } + else { + /* write anc data if bitrate constraint fulfilled */ + if ((extPayload[n].dataSize>>3) <= hAacEnc->config->maxAncBytesPerAU) { + payloadBits = extPayload[n].dataSize; + } + } + payloadBits = fixMin( extPayload[n].dataSize, payloadBits ); + } else { + payloadBits = extPayload[n].dataSize; + } + + if (payloadBits > 0) + { + int idx = qcOut->nExtensions++; + + qcOut->extension[idx].type = extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->extension[idx].nPayloadBits = payloadBits; + qcOut->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the data with the current bitstream syntax: */ + qcOut->globalExtBits += FDKaacEnc_writeExtensionData( NULL, + &qcOut->extension[idx], + 0, 0, + hAacEnc->config->syntaxFlags, + hAacEnc->aot, + hAacEnc->config->epConfig ); + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + /* substract the processed bits */ + extPayload[n].dataSize -= payloadBits; + } + extPayloadUsed[n] = 1; + } + } + } + + if (!(hAacEnc->config->syntaxFlags & (AC_SCALABLE|AC_ER))) { + qcOut->globalExtBits += EL_ID_BITS; /* add bits for ID_END */ + } + + /* build bitstream all nSubFrames */ + { + INT totalBits = 0; /* Total AU bits */; + INT avgTotalBits = 0; + + /*-------------------------------------------- */ + /* Get average total bits */ + /*-------------------------------------------- */ + { + /* frame wise bitrate adaption */ + FDKaacEnc_AdjustBitrate(hAacEnc->qcKernel, + cm, + &avgTotalBits, + hAacEnc->config->bitRate, + hAacEnc->config->sampleRate, + hAacEnc->config->framelength); + + /* adjust super frame bitrate */ + avgTotalBits *= hAacEnc->config->nSubFrames; + //fprintf(stderr, "avgTotalBits=%d x %d\n", avgTotalBits, hAacEnc->config->nSubFrames); + } + + /* Make first estimate of transport header overhead. + Take maximum possible frame size into account to prevent bitreservoir underrun. */ + + //fprintf(stderr, "avgTotalBits=%d, bitResTot=%d\n", avgTotalBits, hAacEnc->qcKernel->bitResTot); + hAacEnc->qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, avgTotalBits + hAacEnc->qcKernel->bitResTot); + + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + ErrorStatus = FDKaacEnc_QCMain(hAacEnc->qcKernel, + hAacEnc->psyOut, + hAacEnc->qcOut, + avgTotalBits, + cm + ,hAacEnc->aot, + hAacEnc->config->syntaxFlags, + hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_updateFillBits(cm, + hAacEnc->qcKernel, + hAacEnc->qcKernel->elementBits, + hAacEnc->qcOut); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_FinalizeBitConsumption(cm, + hAacEnc->qcKernel, + qcOut, + qcOut->qcElement, + hTpEnc, + hAacEnc->aot, + hAacEnc->config->syntaxFlags, + hAacEnc->config->epConfig); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + /*-------------------------------------------- */ + totalBits += qcOut->totalBits; + + + /*-------------------------------------------- */ + FDKaacEnc_updateBitres(cm, + hAacEnc->qcKernel, + hAacEnc->qcOut); + + /*-------------------------------------------- */ + + /* for ( all sub frames ) ... */ + //fprintf(stderr, "totalBits=%d, qcOut->totalBits=%d, qcOut->totFillBits=%d\n", totalBits, qcOut->totalBits, qcOut->totFillBits); + /* write bitstream header */ + transportEnc_WriteAccessUnit( + hTpEnc, + totalBits, + FDKaacEnc_EncBitresToTpBitres(hAacEnc), + cm->nChannelsEff); + + /* write bitstream */ + ErrorStatus = FDKaacEnc_WriteBitstream( + hTpEnc, + cm, + qcOut, + psyOut, + hAacEnc->qcKernel, + hAacEnc->aot, + hAacEnc->config->syntaxFlags, + hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + /* transportEnc_EndAccessUnit() is being called inside FDKaacEnc_WriteBitstream() */ + transportEnc_GetFrame(hTpEnc, nOutBytes); + + } /* -end- if (curFrame==hAacEnc->qcKernel->nSubFrames) */ + + + /*-------------------------------------------- */ + return AAC_ENC_OK; +} + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close( HANDLE_AAC_ENC* phAacEnc) /* encoder handle */ +{ + if (*phAacEnc == NULL) { + return; + } + AAC_ENC *hAacEnc = (AAC_ENC*)*phAacEnc; + + if (hAacEnc->dynamic_RAM != NULL) + FreeAACdynamic_RAM(&hAacEnc->dynamic_RAM); + + FDKaacEnc_PsyClose(&hAacEnc->psyKernel,hAacEnc->psyOut); + + FDKaacEnc_QCClose(&hAacEnc->qcKernel, hAacEnc->qcOut); + + FreeRam_aacEnc_AacEncoder(phAacEnc); +} + + +/* The following functions are in this source file only for convenience and */ +/* need not be visible outside of a possible encoder library. */ + +/* basic defines for ancillary data */ +#define MAX_ANCRATE 19200 /* ancillary rate >= 19200 isn't valid */ + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_InitCheckAncillary + description: initialize and check ancillary data struct + return: if success or NULL if error + + ---------------------------------------------------------------------------*/ +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary(INT bitRate, + INT framelength, + INT ancillaryRate, + INT *ancillaryBitsPerFrame, + INT sampleRate) +{ + INT diffToByteAlign; + + /* don't use negative ancillary rates */ + if ( ancillaryRate < -1 ) + return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + + /* check if ancillary rate is ok */ + if ( (ancillaryRate != (-1)) && (ancillaryRate != 0) ) { + /* ancRate <= 15% of bitrate && ancRate < 19200 */ + if ( ( ancillaryRate >= MAX_ANCRATE ) || + ( (ancillaryRate * 20) > (bitRate * 3) ) ) { + return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + } + } + else if (ancillaryRate == -1) { + /* if no special ancRate is requested but a ancillary file is + stated, then generate a ancillary rate matching to the bitrate */ + if (bitRate >= (MAX_ANCRATE * 10)) { + /* ancillary rate is 19199 */ + ancillaryRate = (MAX_ANCRATE - 1); + } + else { /* 10% of bitrate */ + ancillaryRate = bitRate / 10; + } + } + + /* make ancillaryBitsPerFrame byte align */ + *ancillaryBitsPerFrame = (ancillaryRate * framelength ) / sampleRate; + diffToByteAlign = *ancillaryBitsPerFrame % 8; + *ancillaryBitsPerFrame = *ancillaryBitsPerFrame - diffToByteAlign; + + return AAC_ENC_OK; +} diff --git a/libAACenc/src/aacenc.h b/libAACenc/src/aacenc.h new file mode 100644 index 00000000..dd09ed9f --- /dev/null +++ b/libAACenc/src/aacenc.h @@ -0,0 +1,360 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: M. Schug / A. Groeschel + contents/description: fast aac coder interface library functions + +******************************************************************************/ + +#ifndef _aacenc_h_ +#define _aacenc_h_ + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "tpenc_lib.h" + +#include "sbr_encoder.h" + +#define BITRES_MAX_LD 4000 +#define BITRES_MIN_LD 500 +#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */ +#define BITRATE_MIN_LD 12000 /* Min assumed bitrate for bitres calculation */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * AAC-LC error codes. + */ +typedef enum { + AAC_ENC_OK = 0x0000, /*!< All fine. */ + + AAC_ENC_UNKNOWN = 0x0002, /*!< Error condition is of unknown reason, or from another module. */ + + /* initialization errors */ + aac_enc_init_error_start = 0x2000, + AAC_ENC_INVALID_HANDLE = 0x2020, /*!< The handle passed to the function call was invalid (probably NULL). */ + AAC_ENC_INVALID_FRAME_LENGTH = 0x2080, /*!< Invalid frame length. */ + AAC_ENC_INVALID_N_CHANNELS = 0x20e0, /*!< Invalid amount of audio input channels. */ + AAC_ENC_INVALID_SFB_TABLE = 0x2140, /*!< Internal encoder error. */ + + AAC_ENC_UNSUPPORTED_AOT = 0x3000, /*!< The Audio Object Type (AOT) is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE = 0x3020, /*!< The chosen bitrate is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE_MODE = 0x3028, /*!< Unsupported bit rate mode (CBR or VBR). */ + AAC_ENC_UNSUPPORTED_ANC_BITRATE = 0x3040, /*!< Unsupported ancillay bitrate. */ + AAC_ENC_UNSUPPORTED_ANC_MODE = 0x3060, + AAC_ENC_UNSUPPORTED_TRANSPORT_TYPE = 0x3080, /*!< The bitstream format is not supported. */ + AAC_ENC_UNSUPPORTED_ER_FORMAT = 0x30a0, /*!< The error resilience tool format is not supported. */ + AAC_ENC_UNSUPPORTED_EPCONFIG = 0x30c0, /*!< The error protection format is not supported. */ + AAC_ENC_UNSUPPORTED_CHANNELCONFIG = 0x30e0, /*!< The channel configuration (either number or arrangement) is not supported. */ + AAC_ENC_UNSUPPORTED_SAMPLINGRATE = 0x3100, /*!< Sample rate of audio input is not supported. */ + AAC_ENC_NO_MEMORY = 0x3120, /*!< Could not allocate memory. */ + AAC_ENC_PE_INIT_TABLE_NOT_FOUND = 0x3140, /*!< Internal encoder error. */ + + aac_enc_init_error_end, + + /* encode errors */ + aac_enc_error_start = 0x4000, + AAC_ENC_QUANT_ERROR = 0x4020, /*!< Too many bits used in quantization. */ + AAC_ENC_WRITTEN_BITS_ERROR = 0x4040, /*!< Unexpected number of written bits, differs to + calculated number of bits. */ + AAC_ENC_PNS_TABLE_ERROR = 0x4060, /*!< PNS level out of range. */ + AAC_ENC_GLOBAL_GAIN_TOO_HIGH = 0x4080, /*!< Internal quantizer error. */ + AAC_ENC_BITRES_TOO_LOW = 0x40a0, /*!< Too few bits in bit reservoir. */ + AAC_ENC_BITRES_TOO_HIGH = 0x40a1, /*!< Too many bits in bit reservoir. */ + AAC_ENC_INVALID_CHANNEL_BITRATE = 0x4100, + AAC_ENC_INVALID_ELEMENTINFO_TYPE = 0x4120, /*!< Internal encoder error. */ + + AAC_ENC_WRITE_SCAL_ERROR = 0x41e0, /*!< Error writing scalefacData. */ + AAC_ENC_WRITE_SEC_ERROR = 0x4200, /*!< Error writing sectionData. */ + AAC_ENC_WRITE_SPEC_ERROR = 0x4220, /*!< Error writing spectralData. */ + aac_enc_error_end + +} AAC_ENCODER_ERROR; +/*-------------------------- defines --------------------------------------*/ + +#define ANC_DATA_BUFFERSIZE 1024 /* ancBuffer size */ + +#define MAX_TOTAL_EXT_PAYLOADS (((8) * (1)) + (2+2)) + + +typedef enum { + AACENC_BR_MODE_INVALID = -1, /*!< Invalid bitrate mode. */ + AACENC_BR_MODE_CBR = 0, /*!< Constant bitrate mode. */ + AACENC_BR_MODE_VBR_1 = 1, /*!< Variable bitrate mode, about 32 kbps/channel. */ + AACENC_BR_MODE_VBR_2 = 2, /*!< Variable bitrate mode, about 40 kbps/channel. */ + AACENC_BR_MODE_VBR_3 = 3, /*!< Variable bitrate mode, about 48-56 kbps/channel. */ + AACENC_BR_MODE_VBR_4 = 4, /*!< Variable bitrate mode, about 64 kbps/channel. */ + AACENC_BR_MODE_VBR_5 = 5, /*!< Variable bitrate mode, about 80-96 kbps/channel. */ + AACENC_BR_MODE_FF = 6, /*!< Fixed frame mode. */ + AACENC_BR_MODE_SFR = 7 /*!< Superframe mode. */ + +} AACENC_BITRATE_MODE; + +typedef enum { + + CH_ORDER_MPEG = 0, /*!< MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE) */ + CH_ORDER_WAV, /*!< WAV fileformat channel ordering (e. g. 5.1: L, R, C, LFE, SL, SR) */ + CH_ORDER_WG4 /*!< WG4 fileformat channel ordering (e. g. 5.1: L, R, SL, SR, C, LFE) */ + +} CHANNEL_ORDER; + +/*-------------------- structure definitions ------------------------------*/ + +struct AACENC_CONFIG { + INT sampleRate; /* encoder sample rate */ + INT bitRate; /* encoder bit rate in bits/sec */ + INT ancDataBitRate; /* additional bits consumed by anc data or sbr have to be consiedered while configuration */ + + INT nSubFrames; /* number of frames in super frame (not ADTS/LATM subframes !) */ + AUDIO_OBJECT_TYPE audioObjectType; /* Audio Object Type */ + + INT averageBits; /* encoder bit rate in bits/superframe */ + INT bitrateMode; /* encoder bitrate mode (CBR/VBR) */ + INT nChannels; /* number of channels to process */ + CHANNEL_ORDER channelOrder; /* Input Channel ordering scheme. */ + INT bandWidth; /* targeted audio bandwidth in Hz */ + CHANNEL_MODE channelMode; /* encoder channel mode configuration */ + INT framelength; /* used frame size */ + + UINT syntaxFlags; /* bitstreams syntax configuration */ + SCHAR epConfig; /* error protection configuration */ + + INT anc_Rate; /* ancillary rate, 0 (disabled), -1 (default) else desired rate */ + UINT maxAncBytesPerAU; + INT minBitsPerFrame; /* minimum number of bits in AU */ + INT maxBitsPerFrame; /* maximum number of bits in AU */ + INT bitreservoir; /* size of bitreservoir */ + + INT audioMuxVersion; /* audio mux version in loas/latm transport format */ + + UINT sbrRatio; /* sbr sampling rate ratio: dual- or single-rate */ + + UCHAR useTns; /* flag: use temporal noise shaping */ + UCHAR usePns; /* flag: use perceptual noise substitution */ + UCHAR useIS; /* flag: use intensity coding */ + + UCHAR useRequant; /* flag: use afterburner */ +}; + +typedef struct { + UCHAR *pData; /* pointer to extension payload data */ + UINT dataSize; /* extension payload data size in bits */ + EXT_PAYLOAD_TYPE dataType; /* extension payload data type */ + INT associatedChElement; /* number of the channel element the data is assigned to */ +} AACENC_EXT_PAYLOAD; + +typedef struct AAC_ENC *HANDLE_AAC_ENC; + +/** + * \brief Calculate framesize in bits for given bit rate, frame length and sampling rate. + * + * \param bitRate Ttarget bitrate in bits per second. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Framesize in bits per frame. +*/ +INT FDKaacEnc_CalcBitsPerFrame( + const INT bitRate, + const INT frameLength, + const INT samplingRate + ); + +/** + * \brief Calculate bitrate in bits per second for given framesize, frame length and sampling rate. + * + * \param bitsPerFrame Framesize in bits per frame. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Bitrate in bits per second. +*/ +INT FDKaacEnc_CalcBitrate( + const INT bitsPerFrame, + const INT frameLength, + const INT samplingRate + ); + +/** + * \brief Limit given bit rate to a valid value + * \param hTpEnc transport encoder handle + * \param coreSamplingRate the sample rate to be used for the AAC encoder + * \param frameLength the frameLength to be used for the AAC encoder + * \param nChannels number of total channels + * \param nChannelsEff number of effective channels + * \param bitRate the initial bit rate value for which the closest valid bit rate value is searched for + * \param averageBits average bits per frame for fixed framing. Set to -1 if not available. + * \param optional pointer where the current bits per frame are stored into. + * \param bitrateMode the current bit rate mode + * \param nSubFrames number of sub frames for super framing (not transport frames). + * \return a valid bit rate value as close as possible or identical to bitRate + */ +INT FDKaacEnc_LimitBitrate( + HANDLE_TRANSPORTENC hTpEnc, + INT coreSamplingRate, + INT frameLength, + INT nChannels, + INT nChannelsEff, + INT bitRate, + INT averageBits, + INT *pAverageBitsPerFrame, + INT bitrateMode, + INT nSubFrames + ); + + /*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + + ------------------------------------------------------------------------------*/ + INT FDKaacEnc_GetVBRBitrate(INT bitrateMode, CHANNEL_MODE channelMode); + + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: 0 if success + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc, /* pointer to an encoder handle, initialized on return */ + const INT nElements, /* number of maximal elements in instance to support */ + const INT nChannels, /* number of maximal channels in instance to support */ + const INT nSubFrames); /* support superframing in instance */ + + +AAC_ENCODER_ERROR FDKaacEnc_Initialize(HANDLE_AAC_ENC hAacEncoder, /* pointer to an encoder handle, initialized on return */ + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, + ULONG initFlags); + + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encode one frame + returns: 0 if success + + ---------------------------------------------------------------------------*/ + +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, + INT_PCM* inputBuffer, + INT* numOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS] + ); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close( HANDLE_AAC_ENC* phAacEnc); /* encoder handle */ + +#ifdef __cplusplus +} +#endif + +#endif /* _aacenc_h_ */ + diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp new file mode 100644 index 00000000..1ea9a5c2 --- /dev/null +++ b/libAACenc/src/aacenc_lib.cpp @@ -0,0 +1,2220 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/**************************** MPEG-4 HE-AAC Encoder ************************* + + Initial author: M. Lohwasser + contents/description: FDK HE-AAC Encoder interface library functions + +****************************************************************************/ +#include +#include "aacenc_lib.h" +#include "FDK_audio.h" +#include "aacenc.h" + +#include "aacEnc_ram.h" +#include "FDK_core.h" /* FDK_tools versioning info */ + +/* Encoder library info */ +#define AACENCODER_LIB_VL0 3 +#define AACENCODER_LIB_VL1 4 +#define AACENCODER_LIB_VL2 22 +#define AACENCODER_LIB_TITLE "AAC Encoder" +#ifdef __ANDROID__ +#define AACENCODER_LIB_BUILD_DATE "" +#define AACENCODER_LIB_BUILD_TIME "" +#else +#define AACENCODER_LIB_BUILD_DATE __DATE__ +#define AACENCODER_LIB_BUILD_TIME __TIME__ +#endif + + +#include "sbr_encoder.h" +#include "../src/sbr_ram.h" +#include "channel_map.h" + +#include "psy_const.h" +#include "bitenc.h" + +#include "tpenc_lib.h" + +#include "metadata_main.h" + +#define SBL(fl) (fl/8) /*!< Short block length (hardcoded to 8 short blocks per long block) */ +#define BSLA(fl) (4*SBL(fl)+SBL(fl)/2) /*!< AAC block switching look-ahead */ +#define DELAY_AAC(fl) (fl+BSLA(fl)) /*!< MDCT + blockswitching */ +#define DELAY_AACELD(fl) ((fl)/2) /*!< ELD FB delay (no framing delay included) */ + +#define INPUTBUFFER_SIZE (1537+100+2048) + +#define DEFAULT_HEADER_PERIOD_REPETITION_RATE 10 /*!< Default header repetition rate used in transport library and for SBR header. */ + +//////////////////////////////////////////////////////////////////////////////////// +/** + * Flags to characterize encoder modules to be supported in present instance. + */ +enum { + ENC_MODE_FLAG_AAC = 0x0001, + ENC_MODE_FLAG_SBR = 0x0002, + ENC_MODE_FLAG_PS = 0x0004, + ENC_MODE_FLAG_SAC = 0x0008, + ENC_MODE_FLAG_META = 0x0010 +}; + +//////////////////////////////////////////////////////////////////////////////////// +typedef struct { + AUDIO_OBJECT_TYPE userAOT; /*!< Audio Object Type. */ + UINT userSamplerate; /*!< Sampling frequency. */ + UINT nChannels; /*!< will be set via channelMode. */ + CHANNEL_MODE userChannelMode; + UINT userBitrate; + UINT userBitrateMode; + UINT userBandwidth; + UINT userAfterburner; + UINT userFramelength; + UINT userAncDataRate; + UINT userPeakBitrate; + + UCHAR userTns; /*!< Use TNS coding. */ + UCHAR userPns; /*!< Use PNS coding. */ + UCHAR userIntensity; /*!< Use Intensity coding. */ + + TRANSPORT_TYPE userTpType; /*!< Transport type */ + UCHAR userTpSignaling; /*!< Extension AOT signaling mode. */ + UCHAR userTpNsubFrames; /*!< Number of sub frames in a transport frame for LOAS/LATM or ADTS (default 1). */ + UCHAR userTpAmxv; /*!< AudioMuxVersion to be used for LATM (default 0). */ + UCHAR userTpProtection; + UCHAR userTpHeaderPeriod; /*!< Parameter used to configure LATM/LOAS SMC rate. Moreover this parameters is + used to configure repetition rate of PCE in raw_data_block. */ + + UCHAR userErTools; /*!< Use VCB11, HCR and/or RVLC ER tool. */ + UINT userPceAdditions; /*!< Configure additional bits in PCE. */ + + UCHAR userMetaDataMode; /*!< Meta data library configuration. */ + + UCHAR userSbrEnabled; /*!< Enable SBR for ELD. */ + UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */ + +} USER_PARAM; + +//////////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + Structure Definitions +****************************************************************************/ + +typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG; + + +struct AACENCODER +{ + USER_PARAM extParam; + CODER_CONFIG coderConfig; + + /* AAC */ + AACENC_CONFIG aacConfig; + HANDLE_AAC_ENC hAacEnc; + + /* SBR */ + HANDLE_SBR_ENCODER hEnvEnc; + + /* Meta Data */ + HANDLE_FDK_METADATA_ENCODER hMetadataEnc; + INT metaDataAllowed; /* Signal whether chosen configuration allows metadata. Necessary for delay + compensation. Metadata mode is a separate parameter. */ + + /* Transport */ + HANDLE_TRANSPORTENC hTpEnc; + + /* Output */ + UCHAR *outBuffer; /* Internal bitstream buffer */ + INT outBufferInBytes; /* Size of internal bitstream buffer*/ + + /* Input */ + INT_PCM *inputBuffer; /* Internal input buffer. Input source for AAC encoder */ + INT inputBufferOffset; /* Where to write new input samples. */ + + INT nSamplesToRead; /* number of input samples neeeded for encoding one frame */ + INT nSamplesRead; /* number of input samples already in input buffer */ + INT nZerosAppended; /* appended zeros at end of file*/ + INT nDelay; /* encoder delay */ + + AACENC_EXT_PAYLOAD extPayload [MAX_TOTAL_EXT_PAYLOADS]; + /* Extension payload */ + UCHAR extPayloadData [(1)][(8)][MAX_PAYLOAD_SIZE]; + UINT extPayloadSize [(1)][(8)]; /* payload sizes in bits */ + + ULONG InitFlags; /* internal status to treggier re-initialization */ + + + /* Memory allocation info. */ + INT nMaxAacElements; + INT nMaxAacChannels; + INT nMaxSbrElements; + INT nMaxSbrChannels; + UINT nMaxSubFrames; + + UINT encoder_modis; + + /* Capability flags */ + UINT CAPF_tpEnc; + +} ; + +typedef struct +{ + ULONG samplingRate; /*!< Encoder output sampling rate. */ + ULONG bitrateRange; /*!< Lower bitrate range for config entry. */ + + UCHAR lowDelaySbr; /*!< 0: ELD sbr off, + 1: ELD sbr on */ + + UCHAR downsampledSbr; /*!< 0: ELD with dualrate sbr, + 1: ELD with downsampled sbr */ + +} ELD_SBR_CONFIGURATOR; + +/** + * \brief This table defines ELD/SBR default configurations. + */ +static const ELD_SBR_CONFIGURATOR eldSbrAutoConfigTab[] = +{ + { 48000, 0, 1, 0 }, + { 48000, 64001, 0, 0 }, + + { 44100, 0, 1, 0 }, + { 44100, 64001, 0, 0 }, + + { 32000, 0, 1, 0 }, + { 32000, 28000, 1, 1 }, + { 32000, 56000, 0, 0 }, + + { 24000, 0, 1, 1 }, + { 24000, 40000, 0, 0 }, + + { 16000, 0, 1, 1 }, + { 16000, 28000, 0, 0 } + +}; + +/* + * \brief Configure SBR for ELD configuration. + * + * This function finds default SBR configuration for ELD based on sampling rate and channel bitrate. + * Outputparameters are SBR on/off, and SBR ratio. + * + * \param samplingRate Audio signal sampling rate. + * \param channelMode Channel configuration to be used. + * \param totalBitrate Overall bitrate. + * \param eldSbr Pointer to eldSbr parameter, filled on return. + * \param eldSbrRatio Pointer to eldSbrRatio parameter, filled on return. + * + * \return - AACENC_OK, all fine. + * - AACENC_INVALID_CONFIG, on failure. + */ +static AACENC_ERROR eldSbrConfigurator( + const ULONG samplingRate, + const CHANNEL_MODE channelMode, + const ULONG totalBitrate, + UINT * const eldSbr, + UINT * const eldSbrRatio + ) +{ + AACENC_ERROR err = AACENC_OK; + int i, cfgIdx = -1; + const ULONG channelBitrate = totalBitrate / FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; + + for (i=0; i<(int)(sizeof(eldSbrAutoConfigTab)/sizeof(ELD_SBR_CONFIGURATOR)); i++) { + if ( (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) + && (channelBitrate >= eldSbrAutoConfigTab[i].bitrateRange) ) + { + cfgIdx = i; + } + } + + if (cfgIdx != -1) { + *eldSbr = (eldSbrAutoConfigTab[cfgIdx].lowDelaySbr==0) ? 0 : 1; + *eldSbrRatio = (eldSbrAutoConfigTab[cfgIdx].downsampledSbr==0) ? 2 : 1; + } + else { + err = AACENC_INVALID_CONFIG; /* no default configuration for eld-sbr available. */ + } + + return err; +} + +static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) +{ + INT sbrUsed = 0; + + if ( (hAacConfig->audioObjectType==AOT_SBR) || (hAacConfig->audioObjectType==AOT_PS) + || (hAacConfig->audioObjectType==AOT_DABPLUS_SBR) || (hAacConfig->audioObjectType==AOT_DABPLUS_PS) ) + { + sbrUsed = 1; + } + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && (hAacConfig->syntaxFlags & AC_SBR_PRESENT)) + { + sbrUsed = 1; + } + + return ( sbrUsed ); +} + +static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) +{ + INT psUsed = 0; + + if ( (audioObjectType==AOT_PS) + || (audioObjectType==AOT_DABPLUS_PS) ) + { + psUsed = 1; + } + + return ( psUsed ); +} + +static SBR_PS_SIGNALING getSbrSignalingMode( + const AUDIO_OBJECT_TYPE audioObjectType, + const TRANSPORT_TYPE transportType, + const UCHAR transportSignaling, + const UINT sbrRatio + ) + +{ + SBR_PS_SIGNALING sbrSignaling; + + if (transportType==TT_UNKNOWN || sbrRatio==0) { + sbrSignaling = SIG_UNKNOWN; /* Needed parameters have not been set */ + return sbrSignaling; + } else { + sbrSignaling = SIG_IMPLICIT; /* default: implicit signaling */ + } + + if ((audioObjectType==AOT_AAC_LC) || (audioObjectType==AOT_SBR) || (audioObjectType==AOT_PS) || + (audioObjectType==AOT_DABPLUS_SBR) || (audioObjectType==AOT_DABPLUS_PS) ) { + switch (transportType) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only implicit signaling is possible */ + break; + + case TT_MP4_RAW: + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + case TT_MP4_LOAS: + default: + if ( transportSignaling==0xFF ) { + /* Defaults */ + if ( sbrRatio==1 ) { + sbrSignaling = SIG_EXPLICIT_HIERARCHICAL; /* For downsampled SBR, explicit signaling is mandatory */ + } else { + sbrSignaling = SIG_IMPLICIT; /* For dual-rate SBR, implicit signaling is default */ + } + } else { + /* User set parameters */ + /* Attention: Backward compatible explicit signaling does only work with AMV1 for LATM/LOAS */ + sbrSignaling = (SBR_PS_SIGNALING)transportSignaling; + } + break; + } + } + + return sbrSignaling; +} + +/**************************************************************************** + Allocate Encoder +****************************************************************************/ + +H_ALLOC_MEM (_AacEncoder, AACENCODER) +C_ALLOC_MEM (_AacEncoder, AACENCODER, 1) + + + + +/* + * Map Encoder specific config structures to CODER_CONFIG. + */ +static void FDKaacEnc_MapConfig( + CODER_CONFIG *const cc, + const USER_PARAM *const extCfg, + const SBR_PS_SIGNALING sbrSignaling, + const HANDLE_AACENC_CONFIG hAacConfig + ) +{ + AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT; + FDKmemclear(cc, sizeof(CODER_CONFIG)); + + cc->flags = 0; + + /* Map virtual aot to transport aot. */ + switch (hAacConfig->audioObjectType) { + case AOT_DABPLUS_AAC_LC: + transport_AOT = AOT_AAC_LC; + break; + case AOT_DABPLUS_SBR: + transport_AOT = AOT_SBR; + cc->flags |= CC_SBR; + break; + case AOT_DABPLUS_PS: + transport_AOT = AOT_PS; + cc->flags |= CC_SBR; + break; + default: + transport_AOT = hAacConfig->audioObjectType; + } + + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0; + } + + /* transport type is usually AAC-LC. */ + if ( (transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS) ) { + cc->aot = AOT_AAC_LC; + } + else { + cc->aot = transport_AOT; + } + + /* Configure extension aot. */ + if (sbrSignaling==SIG_IMPLICIT) { + cc->extAOT = AOT_NULL_OBJECT; /* implicit */ + } + else { + if ( (sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE) && ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) ) { + cc->extAOT = AOT_SBR; /* explicit backward compatible */ + } + else { + cc->extAOT = transport_AOT; /* explicit hierarchical */ + } + } + + if ( (transport_AOT==AOT_SBR) || (transport_AOT==AOT_PS) ) { + cc->sbrPresent=1; + if (transport_AOT==AOT_PS) { + cc->psPresent=1; + } + } + cc->sbrSignaling = sbrSignaling; + + cc->extSamplingRate = extCfg->userSamplerate; + cc->bitRate = hAacConfig->bitRate; + cc->noChannels = hAacConfig->nChannels; + cc->flags |= CC_IS_BASELAYER; + cc->channelMode = hAacConfig->channelMode; + + if(extCfg->userTpType == TT_DABPLUS && hAacConfig->nSubFrames==1) { + switch(hAacConfig->sampleRate) { + case 48000: + cc->nSubFrames=6; + break; + case 32000: + cc->nSubFrames=4; + break; + case 24000: + cc->nSubFrames=3; + break; + case 16000: + cc->nSubFrames=2; + break; + } + //fprintf(stderr, "hAacConfig->nSubFrames=%d hAacConfig->sampleRate=%d\n", hAacConfig->nSubFrames, hAacConfig->sampleRate); + } else { + cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1) + ? hAacConfig->nSubFrames + : extCfg->userTpNsubFrames; + } + + cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; + + if (extCfg->userTpHeaderPeriod!=0xFF) { + cc->headerPeriod = extCfg->userTpHeaderPeriod; + } + else { /* auto-mode */ + switch (extCfg->userTpType) { + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP1: + cc->headerPeriod = DEFAULT_HEADER_PERIOD_REPETITION_RATE; + break; + default: + cc->headerPeriod = 0; + } + } + + cc->samplesPerFrame = hAacConfig->framelength; + cc->samplingRate = hAacConfig->sampleRate; + + /* Mpeg-4 signaling for transport library. */ + cc->flags |= CC_MPEG_ID; + + /* ER-tools signaling. */ + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_HCR) ? CC_HCR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_RVLC) ? CC_RVLC : 0; + + /* Matrix mixdown coefficient configuration. */ + if ( (extCfg->userPceAdditions&0x1) && (hAacConfig->epConfig==-1) + && ((cc->channelMode==MODE_1_2_2)||(cc->channelMode==MODE_1_2_2_1)) ) + { + cc->matrixMixdownA = ((extCfg->userPceAdditions>>1)&0x3)+1; + cc->flags |= (extCfg->userPceAdditions>>3)&0x1 ? CC_PSEUDO_SURROUND : 0; + } + else { + cc->matrixMixdownA = 0; + } +} + +/* + * Examine buffer descriptor regarding choosen identifier. + * + * \param pBufDesc Pointer to buffer descriptor + * \param identifier Buffer identifier to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx( + const AACENC_BufDesc *pBufDesc, + const AACENC_BufferIdentifier identifier +) +{ + INT i, idx = -1; + + for (i=0; inumBufs; i++) { + if ( (AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == identifier ) { + idx = i; + break; + } + } + return idx; +} + + +/**************************************************************************** + Function Declarations +****************************************************************************/ + +AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, + USER_PARAM *config) +{ + /* make reasonable default settings */ + FDKaacEnc_AacInitDefaultConfig (hAacConfig); + + /* clear configuration structure and copy default settings */ + FDKmemclear(config, sizeof(USER_PARAM)); + + /* copy encoder configuration settings */ + config->nChannels = hAacConfig->nChannels; + config->userAOT = hAacConfig->audioObjectType = AOT_AAC_LC; + config->userSamplerate = hAacConfig->sampleRate; + config->userChannelMode = hAacConfig->channelMode; + config->userBitrate = hAacConfig->bitRate; + config->userBitrateMode = hAacConfig->bitrateMode; + config->userPeakBitrate = (UINT)-1; + config->userBandwidth = hAacConfig->bandWidth; + config->userTns = hAacConfig->useTns; + config->userPns = hAacConfig->usePns; + config->userIntensity = hAacConfig->useIS; + config->userAfterburner = hAacConfig->useRequant; + config->userFramelength = (UINT)-1; + + if (hAacConfig->syntaxFlags & AC_ER_VCB11) { + config->userErTools |= 0x01; + } + if (hAacConfig->syntaxFlags & AC_ER_HCR) { + config->userErTools |= 0x02; + } + + /* initialize transport parameters */ + config->userTpType = TT_UNKNOWN; + config->userTpAmxv = 0; + config->userTpSignaling = 0xFF; /* choose signaling automatically */ + config->userTpNsubFrames = 1; + config->userTpProtection = 0; /* not crc protected*/ + config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */ + config->userPceAdditions = 0; /* no matrix mixdown coefficient */ + config->userMetaDataMode = 0; /* do not embed any meta data info */ + + config->userAncDataRate = 0; + + /* SBR rate is set to 0 here, which means it should be set automatically + in FDKaacEnc_AdjustEncSettings() if the user did not set a rate + expilicitely. */ + config->userSbrRatio = 0; + + /* SBR enable set to -1 means to inquire ELD audio configurator for reasonable configuration. */ + config->userSbrEnabled = -1; + + return AAC_ENC_OK; +} + +static +void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, SBR_ELEMENT_INFO *sbrElInfo, INT bitRate) +{ + INT codebits = bitRate; + int el; + + /* Copy Element info */ + for (el=0; elnElements; el++) { + sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0]; + sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1]; + sbrElInfo[el].elType = channelMapping->elInfo[el].elType; + sbrElInfo[el].bitRate = (INT)(fMultNorm(channelMapping->elInfo[el].relativeBits, (FIXP_DBL)bitRate)); + sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag; + sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl; + + codebits -= sbrElInfo[el].bitRate; + } + sbrElInfo[0].bitRate += codebits; +} + + +static +INT aacEncoder_LimitBitrate( + const HANDLE_TRANSPORTENC hTpEnc, + const INT samplingRate, + const INT frameLength, + const INT nChannels, + const CHANNEL_MODE channelMode, + INT bitRate, + const INT nSubFrames, + const INT sbrActive, + const INT sbrDownSampleRate, + const AUDIO_OBJECT_TYPE aot + ) +{ + INT coreSamplingRate; + CHANNEL_MAPPING cm; + + FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm); + + if (sbrActive) { + coreSamplingRate = samplingRate >> (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate-1):1); + } else { + coreSamplingRate = samplingRate; + } + + /* Consider bandwidth channel bit rate limit (see bandwidth.cpp: GetBandwidthEntry()) */ + if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) { + bitRate = FDKmin(360000*nChannels, bitRate); + bitRate = FDKmax(8000*nChannels, bitRate); + } + + if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) { + bitRate = FDKmin(576000*nChannels, bitRate); + /*bitRate = FDKmax(0*nChannels, bitRate);*/ + } + + + /* Limit bit rate in respect to the core coder */ + bitRate = FDKaacEnc_LimitBitrate( + hTpEnc, + coreSamplingRate, + frameLength, + nChannels, + cm.nChannelsEff, + bitRate, + -1, + NULL, + -1, + nSubFrames + ); + + /* Limit bit rate in respect to available SBR modes if active */ + if (sbrActive) + { + int numIterations = 0; + INT initialBitrate, adjustedBitrate; + initialBitrate = adjustedBitrate = bitRate; + + /* Find total bitrate which provides valid configuration for each SBR element. */ + do { + int e; + SBR_ELEMENT_INFO sbrElInfo[(8)]; + FDK_ASSERT(cm.nElements <= (8)); + + initialBitrate = adjustedBitrate; + + /* Get bit rate for each SBR element */ + aacEncDistributeSbrBits(&cm, sbrElInfo, initialBitrate); + + for (e=0; e sbrBitRateOut) { + adjustedBitrate = fMin(initialBitrate, (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut-8), cm.elInfo[e].relativeBits)); + break; + } + + } /* sbrElementBitRateIn != sbrBitRateOut */ + + } /* elements */ + + numIterations++; /* restrict iteration to worst case of num elements */ + + } while ( (initialBitrate!=adjustedBitrate) && (numIterations<=cm.nElements) ); + + /* Unequal bitrates mean that no reasonable bitrate configuration found. */ + bitRate = (initialBitrate==adjustedBitrate) ? adjustedBitrate : 0; + } + + FDK_ASSERT(bitRate > 0); + + //fprintf(stderr, "aacEncoder_LimitBitrate(): bitRate=%d\n", bitRate); + return bitRate; +} + +/* + * \brief Consistency check of given USER_PARAM struct and + * copy back configuration from public struct into internal + * encoder configuration struct. + * + * \hAacEncoder Internal encoder config which is to be updated + * \param config User provided config (public struct) + * \return �returns always AAC_ENC_OK + */ +static +AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, + USER_PARAM *config) +{ + AACENC_ERROR err = AACENC_OK; + + /* Get struct pointers. */ + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + hAacConfig->nChannels = config->nChannels; + + /* Encoder settings update. */ + hAacConfig->sampleRate = config->userSamplerate; + hAacConfig->useTns = config->userTns; + hAacConfig->usePns = config->userPns; + hAacConfig->useIS = config->userIntensity; + hAacConfig->bitRate = config->userBitrate; + hAacConfig->channelMode = config->userChannelMode; + hAacConfig->bitrateMode = config->userBitrateMode; + hAacConfig->bandWidth = config->userBandwidth; + hAacConfig->useRequant = config->userAfterburner; + + hAacConfig->audioObjectType = config->userAOT; + hAacConfig->anc_Rate = config->userAncDataRate; + hAacConfig->syntaxFlags = 0; + hAacConfig->epConfig = -1; + + if (config->userTpType==TT_MP4_LATM_MCP1 || config->userTpType==TT_MP4_LATM_MCP0 || config->userTpType==TT_MP4_LOAS) { + hAacConfig->audioMuxVersion = config->userTpAmxv; + } + else { + hAacConfig->audioMuxVersion = -1; + } + + /* Adapt internal AOT when necessary. */ + switch ( hAacConfig->audioObjectType ) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_ADTS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 1024; + if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + break; + case AOT_DABPLUS_SBR: + case AOT_DABPLUS_PS: + hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0); + case AOT_DABPLUS_AAC_LC: + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_DABPLUS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 960; + if (hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + config->userTpSignaling=2; + if(config->userTpType == TT_DABPLUS) + hAacConfig->syntaxFlags |= AC_DAB; + break; +#if 0 + case AOT_ER_AAC_LC: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER; + hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 1024; + if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + break; +#endif + case AOT_ER_AAC_LD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER|AC_LD; + hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512; + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) { + return AACENC_INVALID_CONFIG; + } + break; + case AOT_ER_AAC_ELD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER|AC_ELD; + hAacConfig->syntaxFlags |= ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + hAacConfig->syntaxFlags |= ((config->userSbrEnabled==1) ? AC_SBR_PRESENT : 0); + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 512; + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + + + switch ( hAacConfig->audioObjectType ) { + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + if (config->userBitrateMode==0) { + /* bitreservoir = (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; */ + if ( isLowDelay(hAacConfig->audioObjectType) ) { + INT bitreservoir; + INT brPerChannel = hAacConfig->bitRate/hAacConfig->nChannels; + brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); + FIXP_DBL slope = fDivNorm((brPerChannel-BITRATE_MIN_LD), BITRATE_MAX_LD-BITRATE_MIN_LD); /* calc slope for interpolation */ + bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD-BITRES_MIN_LD)) + BITRES_MIN_LD; /* interpolate */ + hAacConfig->bitreservoir = bitreservoir & ~7; /* align to bytes */ + } + } + if (hAacConfig->bitrateMode!=0) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + + hAacConfig->bitRate = config->userBitrate; + + /* get bitrate in VBR configuration */ + if ( (hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5) ) { + /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. */ + hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, hAacConfig->channelMode); + } + + + + /* Set default bitrate if no external bitrate declared. */ + if ( (hAacConfig->bitrateMode==0) && (config->userBitrate==(UINT)-1) ) { + INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff * hAacConfig->sampleRate; + + if ( isPsActive(hAacConfig->audioObjectType) ) { + hAacConfig->bitRate = (bitrate>>1); /* 0.5 bit per sample */ + } + else if ( isSbrActive(hAacConfig) ) + { + if ( (config->userSbrRatio==2) || ((config->userSbrRatio==0)&&(hAacConfig->audioObjectType!=AOT_ER_AAC_ELD)) ) { + hAacConfig->bitRate = (bitrate + (bitrate>>2))>>1; /* 0.625 bits per sample */ + } + if ( (config->userSbrRatio==1) || ((config->userSbrRatio==0)&&(hAacConfig->audioObjectType==AOT_ER_AAC_ELD)) ) { + hAacConfig->bitRate = (bitrate + (bitrate>>3)); /* 1.125 bits per sample */ + } + } else + { + hAacConfig->bitRate = bitrate + (bitrate>>1); /* 1.5 bits per sample */ + } + } + + if ((hAacConfig->bitrateMode >= 0) && (hAacConfig->bitrateMode <= 5)) { + if ((INT)config->userPeakBitrate != -1) { + hAacConfig->maxBitsPerFrame = (FDKaacEnc_CalcBitsPerFrame(fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), hAacConfig->framelength, hAacConfig->sampleRate) + 7)&~7; + } + else { + hAacConfig->maxBitsPerFrame = -1; + } + if (hAacConfig->audioMuxVersion==2) { + hAacConfig->minBitsPerFrame = fMin(32*8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, hAacConfig->framelength, hAacConfig->sampleRate))&~7; + } + } + + /* Initialize SBR parameters */ + if ( (hAacConfig->audioObjectType==AOT_ER_AAC_ELD) + && (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio==0) ) + { + UINT eldSbr = 0; + UINT eldSbrRatio = 0; + + if ( AACENC_OK!=(err=eldSbrConfigurator( + hAacConfig->sampleRate, + hAacConfig->channelMode, + hAacConfig->bitRate, + &eldSbr, + &eldSbrRatio)) ) + { + return err; + } + + hAacConfig->syntaxFlags |= ((eldSbr) ? AC_SBR_PRESENT : 0); + hAacConfig->sbrRatio = eldSbrRatio; + } + else + if ( (config->userSbrRatio==0) && (isSbrActive(hAacConfig)) ) { + /* Automatic SBR ratio configuration + * - downsampled SBR for ELD + * - otherwise always dualrate SBR + */ + hAacConfig->sbrRatio = (hAacConfig->audioObjectType==AOT_ER_AAC_ELD) ? 1 : 2; + } + else { + /* SBR ratio has been set by the user, so use it. */ + hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; + } + + { + UCHAR tpSignaling=getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, config->userTpSignaling, hAacConfig->sbrRatio); + + if ( (hAacConfig->audioObjectType==AOT_AAC_LC || hAacConfig->audioObjectType==AOT_SBR || hAacConfig->audioObjectType==AOT_PS) && + (config->userTpType==TT_MP4_LATM_MCP1 || config->userTpType==TT_MP4_LATM_MCP0 || config->userTpType==TT_MP4_LOAS) && + (tpSignaling==1) && (config->userTpAmxv==0) ) { + /* For backward compatible explicit signaling, AMV1 has to be active */ + return AACENC_INVALID_CONFIG; + } + + if ( (hAacConfig->audioObjectType==AOT_AAC_LC || hAacConfig->audioObjectType==AOT_SBR || hAacConfig->audioObjectType==AOT_PS) && + (tpSignaling==0) && (hAacConfig->sbrRatio==1)) { + /* Downsampled SBR has to be signaled explicitely (for transmission of SBR sampling fequency) */ + return AACENC_INVALID_CONFIG; + } + } + + + + //fprintf(stderr, "config->userBitrate=%d\n", config->userBitrate); + /* We need the frame length to call aacEncoder_LimitBitrate() */ + hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, + hAacConfig->sampleRate, + hAacConfig->framelength, + hAacConfig->nChannels, + hAacConfig->channelMode, + hAacConfig->bitRate, + hAacConfig->nSubFrames, + isSbrActive(hAacConfig), + hAacConfig->sbrRatio, + hAacConfig->audioObjectType + ); + //fprintf(stderr, "hAacConfig->bitRate=%d\n", hAacConfig->bitRate); + + /* Configure PNS */ + if ( ((hAacConfig->bitrateMode>=1) && (hAacConfig->bitrateMode<=5)) /* VBR without PNS. */ + || (hAacConfig->useTns == 0) ) /* TNS required. */ + { + hAacConfig->usePns = 0; + } + + if (hAacConfig->epConfig >= 0) { + hAacConfig->syntaxFlags |= AC_ER; + if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) { + return AACENC_INVALID_CONFIG; /* Cannel config 0 not supported. */ + } + } + + if ( FDKaacEnc_DetermineEncoderMode(&hAacConfig->channelMode, hAacConfig->nChannels) != AAC_ENC_OK) { + return AACENC_INVALID_CONFIG; /* nChannels doesn't match chMode, this is just a check-up */ + } + + if ( (hAacConfig->nChannels > hAacEncoder->nMaxAacChannels) + || ( (FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannelsEff > hAacEncoder->nMaxSbrChannels) && + isSbrActive(hAacConfig) ) + ) + { + return AACENC_INVALID_CONFIG; /* not enough channels allocated */ + } + + /* Meta data restriction. */ + switch (hAacConfig->audioObjectType) + { + /* Allow metadata support */ + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + hAacEncoder->metaDataAllowed = 1; + if (((INT)hAacConfig->channelMode < 1) || ((INT)hAacConfig->channelMode > 7)) { + config->userMetaDataMode = 0; + } + break; + /* Prohibit metadata support */ + default: + hAacEncoder->metaDataAllowed = 0; + } + + //fprintf(stderr, "hAacEncoder->metaDataAllowed=%d\n", hAacEncoder->metaDataAllowed); + return err; +} + +static +INT aacenc_SbrCallback( + void * self, + HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, + const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex + ) +{ + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; + + sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0); + + return 0; +} + +static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, + ULONG InitFlags, + USER_PARAM *config) +{ + AACENC_ERROR err = AACENC_OK; + + INT aacBufferOffset = 0; + HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc; + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + hAacEncoder->nZerosAppended = 0; /* count appended zeros */ + + INT frameLength = hAacConfig->framelength; + + if ( (InitFlags & AACENC_INIT_CONFIG) ) + { + CHANNEL_MODE prevChMode = hAacConfig->channelMode; + + /* Verify settings and update: config -> heAacEncoder */ + if ( (err=FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK ) { + return err; + } + frameLength = hAacConfig->framelength; /* adapt temporal framelength */ + + /* Seamless channel reconfiguration in sbr not fully implemented */ + if ( (prevChMode!=hAacConfig->channelMode) && isSbrActive(hAacConfig) ) { + InitFlags |= AACENC_INIT_STATES; + } + } + + /* Clear input buffer */ + if ( InitFlags == AACENC_INIT_ALL ) { + FDKmemclear(hAacEncoder->inputBuffer, sizeof(INT_PCM)*hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE); + } + + if ( (InitFlags & AACENC_INIT_CONFIG) ) + { + aacBufferOffset = 0; + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength); + } else + { + hAacEncoder->nDelay = DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */ + } + hAacConfig->ancDataBitRate = 0; + } + + if ( isSbrActive(hAacConfig) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) ) + { + INT sbrError; + SBR_ELEMENT_INFO sbrElInfo[(8)]; + CHANNEL_MAPPING channelMapping; + + if ( FDKaacEnc_InitChannelMapping(hAacConfig->channelMode, + hAacConfig->channelOrder, + &channelMapping) != AAC_ENC_OK ) + { + return AACENC_INIT_ERROR; + } + + /* Check return value and if the SBR encoder can handle enough elements */ + if (channelMapping.nElements > (8)) { + return AACENC_INIT_ERROR; + } + + aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate); + + UINT initFlag = 0; + initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0; + + /* Let the SBR encoder take a look at the configuration and change if required. */ + sbrError = sbrEncoder_Init( + *hSbrEncoder, + sbrElInfo, + channelMapping.nElements, + hAacEncoder->inputBuffer, + &hAacConfig->bandWidth, + &aacBufferOffset, + &hAacConfig->nChannels, + &hAacConfig->sampleRate, + &hAacConfig->sbrRatio, + &frameLength, + hAacConfig->audioObjectType, + &hAacEncoder->nDelay, + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC, + (config->userTpHeaderPeriod!=0xFF) ? config->userTpHeaderPeriod : DEFAULT_HEADER_PERIOD_REPETITION_RATE, + initFlag + ); + + /* Suppress AOT reconfiguration and check error status. */ + if (sbrError) { + return AACENC_INIT_SBR_ERROR; + } + + if (hAacConfig->nChannels == 1) { + hAacConfig->channelMode = MODE_1; + } + + /* Never use PNS if SBR is active */ + if ( hAacConfig->usePns ) { + hAacConfig->usePns = 0; + } + + /* estimated bitrate consumed by SBR or PS */ + hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder) ; + + } /* sbr initialization */ + + + /* + * Initialize Transport - Module. + */ + if ( (InitFlags & AACENC_INIT_TRANSPORT) ) + { + UINT flags = 0; + + FDKaacEnc_MapConfig( + &hAacEncoder->coderConfig, + config, + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, config->userTpSignaling, hAacConfig->sbrRatio), + hAacConfig); + + /* create flags for transport encoder */ + if (config->userTpAmxv != 0) { + flags |= TP_FLAG_LATM_AMV; + } + /* Clear output buffer */ + FDKmemclear(hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes*sizeof(UCHAR)); + + /* Initialize Bitstream encoder */ + if ( transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, hAacEncoder->outBufferInBytes, config->userTpType, &hAacEncoder->coderConfig, flags) != 0) { + return AACENC_INIT_TP_ERROR; + } + + } /* transport initialization */ + + /* + * Initialize AAC - Core. + */ + if ( (InitFlags & AACENC_INIT_CONFIG) || + (InitFlags & AACENC_INIT_STATES) ) + { + AAC_ENCODER_ERROR err; + err = FDKaacEnc_Initialize(hAacEncoder->hAacEnc, + hAacConfig, + hAacEncoder->hTpEnc, + (InitFlags & AACENC_INIT_STATES) ? 1 : 0); + + if (err != AAC_ENC_OK) { + return AACENC_INIT_AAC_ERROR; + } + + } /* aac initialization */ + + /* + * Initialize Meta Data - Encoder. + */ + if ( hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed!=0) && + ((InitFlags & AACENC_INIT_CONFIG) ||(InitFlags & AACENC_INIT_STATES)) ) + { + INT inputDataDelay = DELAY_AAC(hAacConfig->framelength); + + if ( isSbrActive(hAacConfig) && hSbrEncoder!=NULL) { + inputDataDelay = hAacConfig->sbrRatio*inputDataDelay + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } + + if ( FDK_MetadataEnc_Init(hAacEncoder->hMetadataEnc, + ((InitFlags&AACENC_INIT_STATES) ? 1 : 0), + config->userMetaDataMode, + inputDataDelay, + frameLength, + config->userSamplerate, + config->nChannels, + config->userChannelMode, + hAacConfig->channelOrder) != 0) + { + return AACENC_INIT_META_ERROR; + } + + hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc); + } + + /* + * Update pointer to working buffer. + */ + if ( (InitFlags & AACENC_INIT_CONFIG) ) + { + hAacEncoder->inputBufferOffset = aacBufferOffset; + + hAacEncoder->nSamplesToRead = frameLength * config->nChannels; + + /* Make nDelay comparison compatible with config->nSamplesRead */ + hAacEncoder->nDelay *= config->nChannels; + + } /* parameter changed */ + + return AACENC_OK; +} + + +AACENC_ERROR aacEncOpen( + HANDLE_AACENCODER *phAacEncoder, + const UINT encModules, + const UINT maxChannels + ) +{ + AACENC_ERROR err = AACENC_OK; + HANDLE_AACENCODER hAacEncoder = NULL; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + hAacEncoder = Get_AacEncoder(); + + if (hAacEncoder == NULL) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + FDKmemclear(hAacEncoder, sizeof(AACENCODER)); + + /* Specify encoder modules to be allocated. */ + if (encModules==0) { + hAacEncoder->encoder_modis = ENC_MODE_FLAG_AAC; + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR; + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS; + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META; + } + else { + /* consider SAC and PS module */ + hAacEncoder->encoder_modis = encModules; + } + + /* Determine max channel configuration. */ + if (maxChannels==0) { + hAacEncoder->nMaxAacChannels = (8); + hAacEncoder->nMaxSbrChannels = (8); + } + else { + hAacEncoder->nMaxAacChannels = (maxChannels&0x00FF); + if ( (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) ) { + hAacEncoder->nMaxSbrChannels = (maxChannels&0xFF00) ? (maxChannels>>8) : hAacEncoder->nMaxAacChannels; + } + + if ( (hAacEncoder->nMaxAacChannels>(8)) || (hAacEncoder->nMaxSbrChannels>(8)) ) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + } /* maxChannels==0 */ + + /* Max number of elements could be tuned any more. */ + hAacEncoder->nMaxAacElements = fixMin((8), hAacEncoder->nMaxAacChannels); + hAacEncoder->nMaxSbrElements = fixMin((8), hAacEncoder->nMaxSbrChannels); + hAacEncoder->nMaxSubFrames = (1); + + + /* In case of memory overlay, allocate memory out of libraries */ + + hAacEncoder->inputBuffer = (INT_PCM*)FDKcalloc(hAacEncoder->nMaxAacChannels*INPUTBUFFER_SIZE, sizeof(INT_PCM)); + + /* Open SBR Encoder */ + if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SBR) { + if ( sbrEncoder_Open(&hAacEncoder->hEnvEnc, + hAacEncoder->nMaxSbrElements, + hAacEncoder->nMaxSbrChannels, + (hAacEncoder->encoder_modis&ENC_MODE_FLAG_PS) ? 1 : 0 ) ) + { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_SBR) */ + + + /* Open Aac Encoder */ + if ( FDKaacEnc_Open(&hAacEncoder->hAacEnc, + hAacEncoder->nMaxAacElements, + hAacEncoder->nMaxAacChannels, + (1)) != AAC_ENC_OK ) + { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + { /* Get bitstream outputbuffer size */ + UINT buffer_bytes_min = (hAacEncoder->nMaxSubFrames*hAacEncoder->nMaxAacChannels*6144)>>3; + buffer_bytes_min = fixMax(buffer_bytes_min, (UINT) (24 * 110)); // consider maximum DAB+ Superframe size + UINT ld_M; + for (ld_M=1; (UINT)(1<outBufferInBytes = (1<outBuffer = GetRam_bsOutbuffer(); + if (OUTPUTBUFFER_SIZE < hAacEncoder->outBufferInBytes ) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Open Meta Data Encoder */ + if (hAacEncoder->encoder_modis&ENC_MODE_FLAG_META) { + if ( FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc) ) + { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_META) */ + + /* Open Transport Encoder */ + if ( transportEnc_Open(&hAacEncoder->hTpEnc) != 0 ) + { + err = AACENC_MEMORY_ERROR; + goto bail; + } + else { + C_ALLOC_SCRATCH_START(pLibInfo, LIB_INFO, FDK_MODULE_LAST); + + FDKinitLibInfo( pLibInfo); + transportEnc_GetLibInfo( pLibInfo ); + + /* Get capabilty flag for transport encoder. */ + hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities( pLibInfo, FDK_TPENC); + + C_ALLOC_SCRATCH_END(pLibInfo, LIB_INFO, FDK_MODULE_LAST); + } + if ( transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, hAacEncoder) != 0 ) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } + + /* Initialize encoder instance with default parameters. */ + aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam); + + /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */ + hAacEncoder->coderConfig.headerPeriod = hAacEncoder->extParam.userTpHeaderPeriod; + + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + + /* Return encoder instance */ + *phAacEncoder = hAacEncoder; + + return err; + +bail: + aacEncClose(&hAacEncoder); + + return err; +} + + + +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder) +{ + AACENC_ERROR err = AACENC_OK; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + if (*phAacEncoder != NULL) { + HANDLE_AACENCODER hAacEncoder = *phAacEncoder; + + + if (hAacEncoder->inputBuffer!=NULL) { + FDKfree(hAacEncoder->inputBuffer); + hAacEncoder->inputBuffer = NULL; + } + + if (hAacEncoder->outBuffer) { + FreeRam_bsOutbuffer(&hAacEncoder->outBuffer); + } + + if (hAacEncoder->hEnvEnc) { + sbrEncoder_Close (&hAacEncoder->hEnvEnc); + } + if (hAacEncoder->hAacEnc) { + FDKaacEnc_Close (&hAacEncoder->hAacEnc); + } + + transportEnc_Close(&hAacEncoder->hTpEnc); + + if (hAacEncoder->hMetadataEnc) { + FDK_MetadataEnc_Close (&hAacEncoder->hMetadataEnc); + } + + Free_AacEncoder(phAacEncoder); + } + +bail: + return err; +} + +AACENC_ERROR aacEncEncode( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, + AACENC_OutArgs *outargs + ) +{ + AACENC_ERROR err = AACENC_OK; + INT i, nBsBytes = 0; + INT outBytes[(1)]; + int nExtensions = 0; + int ancDataExtIdx = -1; + + /* deal with valid encoder handle */ + if (hAacEncoder==NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + + /* + * Adjust user settings and trigger reinitialization. + */ + if (hAacEncoder->InitFlags!=0) { + + err = aacEncInit(hAacEncoder, + hAacEncoder->InitFlags, + &hAacEncoder->extParam); + + if (err!=AACENC_OK) { + /* keep init flags alive! */ + goto bail; + } + hAacEncoder->InitFlags = AACENC_INIT_NONE; + } + + if (outargs!=NULL) { + FDKmemclear(outargs, sizeof(AACENC_OutArgs)); + } + + if (outBufDesc!=NULL) { + for (i=0; inumBufs; i++) { + if (outBufDesc->bufs[i]!=NULL) { + FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]); + } + } + } + + /* + * If only encoder handle given, independent (re)initialization can be triggered. + */ + if ( (hAacEncoder!=NULL) & (inBufDesc==NULL) && (outBufDesc==NULL) && (inargs==NULL) && (outargs==NULL) ) { + goto bail; + } + + /* reset buffer wich signals number of valid bytes in output bitstream buffer */ + FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames*sizeof(INT)); + + /* + * Manage incoming audio samples. + */ + if ( (inargs->numInSamples > 0) && (getBufDescIdx(inBufDesc,IN_AUDIO_DATA) != -1) ) + { + /* Fetch data until nSamplesToRead reached */ + INT idx = getBufDescIdx(inBufDesc,IN_AUDIO_DATA); + INT newSamples = fixMax(0,fixMin(inargs->numInSamples, hAacEncoder->nSamplesToRead-hAacEncoder->nSamplesRead)); + INT_PCM *pIn = hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead; + + /* Copy new input samples to internal buffer */ + if (inBufDesc->bufElSizes[idx]==(INT)sizeof(INT_PCM)) { + FDKmemcpy(pIn, (INT_PCM*)inBufDesc->bufs[idx], newSamples*sizeof(INT_PCM)); /* Fast copy. */ + } + else if (inBufDesc->bufElSizes[idx]>(INT)sizeof(INT_PCM)) { + for (i=0; ibufs[idx])[i]>>16); /* Convert 32 to 16 bit. */ + } + } + else { + for (i=0; ibufs[idx])[i]))<<16; /* Convert 16 to 32 bit. */ + } + } + hAacEncoder->nSamplesRead += newSamples; + + /* Number of fetched input buffer samples. */ + outargs->numInSamples = newSamples; + } + + /* input buffer completely filled ? */ + if (hAacEncoder->nSamplesRead < hAacEncoder->nSamplesToRead) + { + /* - eof reached and flushing enabled, or + - return to main and wait for further incoming audio samples */ + if (inargs->numInSamples==-1) + { + if ( (hAacEncoder->nZerosAppended < hAacEncoder->nDelay) + ) + { + int nZeros = hAacEncoder->nSamplesToRead - hAacEncoder->nSamplesRead; + + FDK_ASSERT(nZeros >= 0); + + /* clear out until end-of-buffer */ + if (nZeros) { + FDKmemclear(hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset+hAacEncoder->nSamplesRead, sizeof(INT_PCM)*nZeros ); + hAacEncoder->nZerosAppended += nZeros; + hAacEncoder->nSamplesRead = hAacEncoder->nSamplesToRead; + } + } + else { /* flushing completed */ + err = AACENC_ENCODE_EOF; /* eof reached */ + goto bail; + } + } + else { /* inargs->numInSamples!= -1 */ + goto bail; /* not enough samples in input buffer and no flushing enabled */ + } + } + + /* init payload */ + FDKmemclear(hAacEncoder->extPayload, sizeof(AACENC_EXT_PAYLOAD) * MAX_TOTAL_EXT_PAYLOADS); + for (i = 0; i < MAX_TOTAL_EXT_PAYLOADS; i++) { + hAacEncoder->extPayload[i].associatedChElement = -1; + } + FDKmemclear(hAacEncoder->extPayloadData, sizeof(hAacEncoder->extPayloadData)); + FDKmemclear(hAacEncoder->extPayloadSize, sizeof(hAacEncoder->extPayloadSize)); + + + /* + * Calculate Meta Data info. + */ + if ( (hAacEncoder->hMetadataEnc!=NULL) && (hAacEncoder->metaDataAllowed!=0) ) { + + const AACENC_MetaData *pMetaData = NULL; + AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL; + UINT nMetaDataExtensions = 0; + INT matrix_mixdown_idx = 0; + + /* New meta data info available ? */ + if ( getBufDescIdx(inBufDesc,IN_METADATA_SETUP) != -1 ) { + pMetaData = (AACENC_MetaData*)inBufDesc->bufs[getBufDescIdx(inBufDesc,IN_METADATA_SETUP)]; + } + + FDK_MetadataEnc_Process(hAacEncoder->hMetadataEnc, + hAacEncoder->inputBuffer+hAacEncoder->inputBufferOffset, + hAacEncoder->nSamplesRead, + pMetaData, + &pMetaDataExtPayload, + &nMetaDataExtensions, + &matrix_mixdown_idx + ); + + for (i=0; i<(INT)nMetaDataExtensions; i++) { /* Get meta data extension payload. */ + hAacEncoder->extPayload[nExtensions++] = pMetaDataExtPayload[i]; + } + + if ( (matrix_mixdown_idx!=-1) + && ((hAacEncoder->extParam.userChannelMode==MODE_1_2_2)||(hAacEncoder->extParam.userChannelMode==MODE_1_2_2_1)) ) + { + /* Set matrix mixdown coefficient. */ + UINT pceValue = (UINT)( (0<<3) | ((matrix_mixdown_idx&0x3)<<1) | 1 ); + if (hAacEncoder->extParam.userPceAdditions != pceValue) { + hAacEncoder->extParam.userPceAdditions = pceValue; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + } + } + + + if ( isSbrActive(&hAacEncoder->aacConfig) ) { + + INT nPayload = 0; + + /* + * Encode SBR data. + */ + if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc, + hAacEncoder->inputBuffer, + hAacEncoder->extParam.nChannels, + hAacEncoder->extPayloadSize[nPayload], + hAacEncoder->extPayloadData[nPayload] +#if defined(EVAL_PACKAGE_SILENCE) || defined(EVAL_PACKAGE_SBR_SILENCE) + ,hAacEncoder->hAacEnc->clearOutput +#endif + )) + { + err = AACENC_ENCODE_ERROR; + goto bail; + } + else { + /* Add SBR extension payload */ + for (i = 0; i < (8); i++) { + if (hAacEncoder->extPayloadSize[nPayload][i] > 0) { + hAacEncoder->extPayload[nExtensions].pData = hAacEncoder->extPayloadData[nPayload][i]; + { + hAacEncoder->extPayload[nExtensions].dataSize = hAacEncoder->extPayloadSize[nPayload][i]; + hAacEncoder->extPayload[nExtensions].associatedChElement = i; + } + hAacEncoder->extPayload[nExtensions].dataType = EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set EXT_SBR_DATA_CRC */ + nExtensions++; /* or EXT_SBR_DATA according to configuration. */ + FDK_ASSERT(nExtensions<=MAX_TOTAL_EXT_PAYLOADS); + } + } + nPayload++; + } + } /* sbrEnabled */ + + if ( (inargs->numAncBytes > 0) && ( getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA)!=-1 ) ) { + INT idx = getBufDescIdx(inBufDesc,IN_ANCILLRY_DATA); + hAacEncoder->extPayload[nExtensions].dataSize = inargs->numAncBytes * 8; + hAacEncoder->extPayload[nExtensions].pData = (UCHAR*)inBufDesc->bufs[idx]; + hAacEncoder->extPayload[nExtensions].dataType = EXT_DATA_ELEMENT; + hAacEncoder->extPayload[nExtensions].associatedChElement = -1; + ancDataExtIdx = nExtensions; /* store index */ + nExtensions++; + } + + /* + * Encode AAC - Core. + */ + if ( FDKaacEnc_EncodeFrame( hAacEncoder->hAacEnc, + hAacEncoder->hTpEnc, + hAacEncoder->inputBuffer, + outBytes, + hAacEncoder->extPayload + ) != AAC_ENC_OK ) + { + err = AACENC_ENCODE_ERROR; + goto bail; + } + + if (ancDataExtIdx >= 0) { + outargs->numAncBytes = inargs->numAncBytes - (hAacEncoder->extPayload[ancDataExtIdx].dataSize>>3); + } + + /* samples exhausted */ + hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead; + + /* + * Delay balancing buffer handling + */ + if (isSbrActive(&hAacEncoder->aacConfig)) { + sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer); + } + + /* + * Make bitstream public + */ + if (outBufDesc->numBufs>=1) { + + INT bsIdx = getBufDescIdx(outBufDesc,OUT_BITSTREAM_DATA); + INT auIdx = getBufDescIdx(outBufDesc,OUT_AU_SIZES); + + for (i=0,nBsBytes=0; iaacConfig.nSubFrames; i++) { + nBsBytes += outBytes[i]; + + if (auIdx!=-1) { + ((INT*)outBufDesc->bufs[auIdx])[i] = outBytes[i]; + } + } + + if ( (bsIdx!=-1) && (outBufDesc->bufSizes[bsIdx]>=nBsBytes) ) { + FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, sizeof(UCHAR)*nBsBytes); + outargs->numOutBytes = nBsBytes; + } + else { + /* output buffer too small, can't write valid bitstream */ + err = AACENC_ENCODE_ERROR; + goto bail; + } + } + +bail: + if (err == AACENC_ENCODE_ERROR) { + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + } + + return err; +} + +static +AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder, + UINT *size, + UCHAR *confBuffer) +{ + FDK_BITSTREAM tmpConf; + UINT confType; + UCHAR buf[64]; + int err; + + /* Init bit buffer */ + FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER); + + /* write conf in tmp buffer */ + err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, &tmpConf, &confType); + + /* copy data to outbuffer: length in bytes */ + FDKbyteAlign(&tmpConf, 0); + + /* Check buffer size */ + if (FDKgetValidBits(&tmpConf) > ((*size)<<3)) + return AAC_ENC_UNKNOWN; + + FDKfetchBuffer(&tmpConf, confBuffer, size); + + if (err != 0) + return AAC_ENC_UNKNOWN; + else + return AAC_ENC_OK; +} + + +AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) +{ + int i = 0; + + if (info == NULL) { + return AACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo( info ); + transportEnc_GetLibInfo( info ); + + sbrEncoder_GetLibInfo( info ); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return AACENC_INIT_ERROR; + } + + info[i].module_id = FDK_AACENC; + info[i].build_date = (char*)AACENCODER_LIB_BUILD_DATE; + info[i].build_time = (char*)AACENCODER_LIB_BUILD_TIME; + info[i].title = (char*)AACENCODER_LIB_TITLE; + info[i].version = LIB_VERSION(AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2);; + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0 + | CAPF_AAC_1024 | CAPF_AAC_LC + | CAPF_AAC_960 + | CAPF_AAC_512 + | CAPF_AAC_480 + | CAPF_AAC_DRC + ; + /* End of flags */ + + return AACENC_OK; +} + +AACENC_ERROR aacEncoder_SetParam( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, + const UINT value + ) +{ + AACENC_ERROR err = AACENC_OK; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) + { + case AACENC_AOT: + if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) { + /* check if AOT matches the allocated modules */ + switch ( value ) { + case AOT_PS: + case AOT_DRM_SBR: // Added mfeilen + case AOT_DABPLUS_PS: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + case AOT_SBR: + case AOT_DABPLUS_SBR: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + case AOT_AAC_LC: + case AOT_DABPLUS_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + break; + default: + err = AACENC_INVALID_CONFIG; + goto bail; + }/* switch value */ + settings->userAOT = (AUDIO_OBJECT_TYPE)value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATE: + if (settings->userBitrate != value) { + settings->userBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATEMODE: + if (settings->userBitrateMode != value) { + switch ( value ) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 7: + case 8: + settings->userBitrateMode = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } /* switch value */ + } + break; + case AACENC_SAMPLERATE: + if (settings->userSamplerate != value) { + if ( !( (value==8000) || (value==11025) || (value==12000) || (value==16000) || (value==22050) || (value==24000) || + (value==32000) || (value==44100) || (value==48000) || (value==64000) || (value==88200) || (value==96000) ) ) + { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSamplerate = value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_CHANNELMODE: + if (settings->userChannelMode != (CHANNEL_MODE)value) { + const CHANNEL_MODE_CONFIG_TAB* pConfig = FDKaacEnc_GetChannelModeConfiguration((CHANNEL_MODE)value); + if (pConfig==NULL) { + err = AACENC_INVALID_CONFIG; + break; + } + if ( (pConfig->nElements > hAacEncoder->nMaxAacElements) + || (pConfig->nChannelsEff > hAacEncoder->nMaxAacChannels) + || !(((value>=1) && (value<=7))||((value>=33) && (value<=34))) + ) + { + err = AACENC_INVALID_CONFIG; + break; + } + + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = pConfig->nChannels; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BANDWIDTH: + if (settings->userBandwidth != value) { + settings->userBandwidth = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_CHANNELORDER: + if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) { + if (! ((value==0) || (value==1) || (value==2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + hAacEncoder->aacConfig.channelOrder = (CHANNEL_ORDER)value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AFTERBURNER: + if (settings->userAfterburner != value) { + if (! ((value==0) || (value==1)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userAfterburner = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_GRANULE_LENGTH: + if (settings->userFramelength != value) { + switch (value) { + case 1024: + case 960: + case 512: + case 480: + settings->userFramelength = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } + } + break; + case AACENC_SBR_RATIO: + if (settings->userSbrRatio != value) { + if (! ((value==0) || (value==1) || (value==2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSbrRatio = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SBR_MODE: + if (settings->userSbrEnabled != value) { + settings->userSbrEnabled = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TRANSMUX: + if (settings->userTpType != (TRANSPORT_TYPE)value) { + + TRANSPORT_TYPE type = (TRANSPORT_TYPE)value; + UINT flags = hAacEncoder->CAPF_tpEnc; + + if ( !( ((type==TT_MP4_ADIF) && (flags&CAPF_ADIF)) + || ((type==TT_MP4_ADTS) && (flags&CAPF_ADTS)) + || ((type==TT_MP4_LATM_MCP0) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS))) + || ((type==TT_MP4_LATM_MCP1) && ((flags&CAPF_LATM) && (flags&CAPF_RAWPACKETS))) + || ((type==TT_MP4_LOAS) && (flags&CAPF_LOAS)) + || ((type==TT_MP4_RAW) && (flags&CAPF_RAWPACKETS)) + || ((type==TT_DABPLUS) && ((flags&CAPF_DAB_AAC) && (flags&CAPF_RAWPACKETS))) + ) ) + { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpType = (TRANSPORT_TYPE)value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SIGNALING_MODE: + if (settings->userTpSignaling != value) { + if ( !((value==0) || (value==1) || (value==2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpSignaling = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_PROTECTION: + if (settings->userTpProtection != value) { + if ( !((value==0) || (value==1)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpProtection = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_HEADER_PERIOD: + if (settings->userTpHeaderPeriod != value) { + settings->userTpHeaderPeriod = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AUDIOMUXVER: + if (settings->userTpAmxv != value) { + if ( !((value==0) || (value==1) || (value==2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpAmxv = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TPSUBFRAMES: + if (settings->userTpNsubFrames != value) { + if (! ( (value>=1) && (value<=6) ) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpNsubFrames = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_ANCILLARY_BITRATE: + if (settings->userAncDataRate != value) { + settings->userAncDataRate = value; + } + break; + case AACENC_CONTROL_STATE: + if (hAacEncoder->InitFlags != value) { + if (value&AACENC_RESET_INBUFFER) { + hAacEncoder->nSamplesRead = 0; + } + hAacEncoder->InitFlags = value; + } + break; + case AACENC_METADATA_MODE: + if ((UINT)settings->userMetaDataMode != value) { + if ( !(((INT)value>=0) && ((INT)value<=2)) ) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userMetaDataMode = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_PEAK_BITRATE: + if (settings->userPeakBitrate != value) { + settings->userPeakBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + default: + err = AACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ + +bail: + return err; +} + +UINT aacEncoder_GetParam( + const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param + ) +{ + UINT value = 0; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + goto bail; + } + + /* apply param value */ + switch (param) + { + case AACENC_AOT: + value = (UINT)hAacEncoder->aacConfig.audioObjectType; + break; + case AACENC_BITRATE: + value = (UINT)((hAacEncoder->aacConfig.bitrateMode==AACENC_BR_MODE_CBR) ? hAacEncoder->aacConfig.bitRate : -1); + break; + case AACENC_BITRATEMODE: + value = (UINT)hAacEncoder->aacConfig.bitrateMode; + break; + case AACENC_SAMPLERATE: + value = (UINT)hAacEncoder->coderConfig.extSamplingRate; + break; + case AACENC_CHANNELMODE: + value = (UINT)hAacEncoder->aacConfig.channelMode; + break; + case AACENC_BANDWIDTH: + value = (UINT)hAacEncoder->aacConfig.bandWidth; + break; + case AACENC_CHANNELORDER: + value = (UINT)hAacEncoder->aacConfig.channelOrder; + break; + case AACENC_AFTERBURNER: + value = (UINT)hAacEncoder->aacConfig.useRequant; + break; + case AACENC_GRANULE_LENGTH: + value = (UINT)hAacEncoder->aacConfig.framelength; + break; + case AACENC_SBR_RATIO: + value = isSbrActive(&hAacEncoder->aacConfig) ? hAacEncoder->aacConfig.sbrRatio : 0; + break; + case AACENC_SBR_MODE: + value = (UINT) (hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0; + break; + case AACENC_TRANSMUX: + value = (UINT)settings->userTpType; + break; + case AACENC_SIGNALING_MODE: + value = (UINT)getSbrSignalingMode(hAacEncoder->aacConfig.audioObjectType, settings->userTpType, settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio); + break; + case AACENC_PROTECTION: + value = (UINT)settings->userTpProtection; + break; + case AACENC_HEADER_PERIOD: + value = (UINT)hAacEncoder->coderConfig.headerPeriod; + break; + case AACENC_AUDIOMUXVER: + value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; + break; + case AACENC_TPSUBFRAMES: + value = (UINT)settings->userTpNsubFrames; + break; + case AACENC_ANCILLARY_BITRATE: + value = (UINT)hAacEncoder->aacConfig.anc_Rate; + break; + case AACENC_CONTROL_STATE: + value = (UINT)hAacEncoder->InitFlags; + break; + case AACENC_METADATA_MODE: + value = (hAacEncoder->metaDataAllowed==0) ? 0 : (UINT)settings->userMetaDataMode; + break; + case AACENC_PEAK_BITRATE: + value = (UINT)-1; /* peak bitrate parameter is meaningless */ + if ( ((INT)hAacEncoder->extParam.userPeakBitrate!=-1) ) { + value = (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, hAacEncoder->aacConfig.bitRate)); /* peak bitrate parameter is in use */ + } + break; + default: + //err = MPS_INVALID_PARAMETER; + break; + } /* switch(param) */ + +bail: + return value; +} + +AACENC_ERROR aacEncInfo( + const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo + ) +{ + AACENC_ERROR err = AACENC_OK; + + FDKmemclear(pInfo, sizeof(AACENC_InfoStruct)); + pInfo->confSize = 64; /* pre-initialize */ + + pInfo->maxOutBufBytes = ((hAacEncoder->nMaxAacChannels*6144)+7)>>3; + pInfo->maxAncBytes = hAacEncoder->aacConfig.maxAncBytesPerAU; + pInfo->inBufFillLevel = hAacEncoder->nSamplesRead/hAacEncoder->extParam.nChannels; + pInfo->inputChannels = hAacEncoder->extParam.nChannels; + pInfo->frameLength = hAacEncoder->nSamplesToRead/hAacEncoder->extParam.nChannels; + pInfo->encoderDelay = hAacEncoder->nDelay/hAacEncoder->extParam.nChannels; + + /* Get encoder configuration */ + if ( aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != AAC_ENC_OK) { + err = AACENC_INIT_ERROR; + goto bail; + } +bail: + return err; +} + diff --git a/libAACenc/src/aacenc_pns.cpp b/libAACenc/src/aacenc_pns.cpp new file mode 100644 index 00000000..b9640d95 --- /dev/null +++ b/libAACenc/src/aacenc_pns.cpp @@ -0,0 +1,591 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: pns.c + +******************************************************************************/ + +#include "aacenc_pns.h" +#include "psy_data.h" +#include "pnsparam.h" +#include "noisedet.h" +#include "bit_cnt.h" +#include "interface.h" + + +/* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ +static const FIXP_DBL minCorrelationEnergy = FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ +/* noiseCorrelationThresh = 0.6^2 */ +static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); + +static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf, + PNS_DATA *pnsData, + const INT sfbActive, + const INT *sfbOffset, + INT tnsOrder, + INT tnsPredictionGain, + INT tnsActive, + FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + FIXP_SGL *sfbtonality ); + +static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive, + INT *pnsFlag, + FIXP_DBL *sfbEnergyLdData, + INT *noiseNrg ); + +/***************************************************************************** + + functionname: initPnsConfiguration + description: fill pnsConf with pns parameters + returns: error status + input: PNS Config struct (modified) + bitrate, samplerate, usePns, + number of sfb's, pointer to sfb offset + output: error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf, + INT bitRate, + INT sampleRate, + INT usePns, + INT sfbCnt, + const INT *sfbOffset, + const INT numChan, + const INT isLC) +{ + AAC_ENCODER_ERROR ErrorStatus; + + /* init noise detection */ + ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np, + bitRate, + sampleRate, + sfbCnt, + sfbOffset, + &usePns, + numChan, + isLC); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + pnsConf->minCorrelationEnergy = minCorrelationEnergy; + pnsConf->noiseCorrelationThresh = noiseCorrelationThresh; + + pnsConf->usePns = usePns; + + return AAC_ENC_OK; +} + + + +/***************************************************************************** + + functionname: FDKaacEnc_PnsDetect + description: do decision, if PNS shall used or not + returns: + input: pns config structure + pns data structure (modified), + lastWindowSequence (long or short blocks) + sfbActive + pointer to Sfb Energy, Threshold, Offset + pointer to mdct Spectrum + length of each group + pointer to tonality calculated in chaosmeasure + tns order and prediction gain + calculated noiseNrg at active PNS + output: pnsFlag in pns data structure + +*****************************************************************************/ +void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, + PNS_DATA *pnsData, + const INT lastWindowSequence, + const INT sfbActive, + const INT maxSfbPerGroup, + FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, + FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + FIXP_SGL *sfbtonality, + INT tnsOrder, + INT tnsPredictionGain, + INT tnsActive, + FIXP_DBL *sfbEnergyLdData, + INT *noiseNrg ) + +{ + int sfb; + int startNoiseSfb; + + if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) { + if ( (!pnsConf->usePns) || /* pns enabled? */ + (lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */ + { + FDKmemclear(pnsData->pnsFlag, MAX_GROUPED_SFB*sizeof(INT)); /* clear all pnsFlags */ + for (sfb=0; sfbusePns) + return; + + /* PNS only for long Windows */ + if (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) { + if(lastWindowSequence != LONG_WINDOW) { + for (sfb = 0; sfb < sfbActive; sfb++) { + pnsData->pnsFlag[sfb] = 0; /* clear all pnsFlags */ + } + return; + } + } + } + /* + call noise detection + */ + FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf, + pnsData, + sfbActive, + sfbOffset, + tnsOrder, + tnsPredictionGain, + tnsActive, + mdctSpectrum, + sfbMaxScaleSpec, + sfbtonality ); + + /* set startNoiseSfb (long) */ + startNoiseSfb = pnsConf->np.startSfb; + + /* Set noise substitution status */ + for(sfb = 0; sfb < sfbActive; sfb++) { + + /* No PNS below startNoiseSfb */ + if(sfb < startNoiseSfb){ + pnsData->pnsFlag[sfb] = 0; + continue; + } + + /* + do noise substitution if + fuzzy measure is high enough + sfb freq > minimum sfb freq + signal in coder band is not masked + */ + + if((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && + ( (sfbThresholdLdData[sfb] + FL2FXCONST_DBL(0.5849625f/64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ + < sfbEnergyLdData[sfb] ) ) + { + /* + mark in psyout flag array that we will code + this band with PNS + */ + pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ + } + else{ + pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ + } + + /* no PNS if LTP is active */ + } + + /* avoid PNS holes */ + if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) { + pnsData->pnsFlag[0] = 1; + } + + for(sfb=1; sfbnoiseFuzzyMeasure[sfb]>pnsConf->np.gapFillThr) && + (pnsData->pnsFlag[sfb-1]) && (pnsData->pnsFlag[sfb+1])) { + pnsData->pnsFlag[sfb] = 1; + } + } + + if(maxSfbPerGroup>0) { + /* avoid PNS hole */ + if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) { + pnsData->pnsFlag[maxSfbPerGroup-1] = 1; + } + /* avoid single PNS band */ + if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) { + pnsData->pnsFlag[maxSfbPerGroup-1] = 0; + } + } + + /* avoid single PNS bands */ + if(pnsData->pnsFlag[1]==0) { + pnsData->pnsFlag[0] = 0; + } + + for(sfb=1; sfbpnsFlag[sfb-1]==0)&&(pnsData->pnsFlag[sfb+1]==0)) { + pnsData->pnsFlag[sfb] = 0; + } + } + + + /* + calculate noiseNrg's + */ + FDKaacEnc_CalcNoiseNrgs( sfbActive, + pnsData->pnsFlag, + sfbEnergyLdData, + noiseNrg ); +} + + +/***************************************************************************** + + functionname:FDKaacEnc_FDKaacEnc_noiseDetection + description: wrapper for noisedet.c + returns: + input: pns config structure + pns data structure (modified), + sfbActive + tns order and prediction gain + pointer to mdct Spectrumand Sfb Energy + pointer to Sfb tonality + output: noiseFuzzyMeasure in structure pnsData + flags tonal / nontonal + +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf, + PNS_DATA *pnsData, + const INT sfbActive, + const INT *sfbOffset, + int tnsOrder, + INT tnsPredictionGain, + INT tnsActive, + FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + FIXP_SGL *sfbtonality ) +{ + INT condition = TRUE; + if ( !(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) ) { + condition = (tnsOrder > 3); + } + /* + no PNS if heavy TNS activity + clear pnsData->noiseFuzzyMeasure + */ + if((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) && + (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition && + !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && (tnsActive)) ) + { + /* clear all noiseFuzzyMeasure */ + FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive*sizeof(FIXP_SGL)); + } + else + { + /* + call noise detection, output in pnsData->noiseFuzzyMeasure, + use real mdct spectral data + */ + FDKaacEnc_noiseDetect( mdctSpectrum, + sfbMaxScaleSpec, + sfbActive, + sfbOffset, + pnsData->noiseFuzzyMeasure, + &pnsConf->np, + sfbtonality); + } +} + + +/***************************************************************************** + + functionname:FDKaacEnc_CalcNoiseNrgs + description: Calculate the NoiseNrg's + returns: + input: sfbActive + if pnsFlag calculate NoiseNrg + pointer to sfbEnergy and groupLen + pointer to noiseNrg (modified) + output: noiseNrg's in pnsFlaged sfb's + +*****************************************************************************/ + +static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive, + INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg ) +{ + int sfb; + INT tmp = (-LOG_NORM_PCM)<<2; + + for(sfb = 0; sfb < sfbActive; sfb++) { + if(pnsFlag[sfb]) { + INT nrg = (-sfbEnergyLdData[sfb]+FL2FXCONST_DBL(0.5f/64.0f))>>(DFRACT_BITS-1-7); + noiseNrg[sfb] = tmp - nrg; + } + } +} + + +/***************************************************************************** + + functionname:FDKaacEnc_CodePnsChannel + description: Execute pns decission + returns: + input: sfbActive + pns config structure + use PNS if pnsFlag + pointer to Sfb Energy, noiseNrg, Threshold + output: set sfbThreshold high to code pe with 0, + noiseNrg marks flag for pns coding + +*****************************************************************************/ + +void FDKaacEnc_CodePnsChannel(const INT sfbActive, + PNS_CONFIG *pnsConf, + INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg, + FIXP_DBL *RESTRICT sfbThresholdLdData) +{ + INT sfb; + INT lastiNoiseEnergy = 0; + INT firstPNSband = 1; /* TRUE for first PNS-coded band */ + + /* no PNS */ + if(!pnsConf->usePns) { + for(sfb = 0; sfb < sfbActive; sfb++) { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + return; + } + + /* code PNS */ + for(sfb = 0; sfb < sfbActive; sfb++) { + if(pnsFlag[sfb]) { + /* high sfbThreshold causes pe = 0 */ + if(noiseNrg[sfb] != NO_NOISE_PNS) + sfbThresholdLdData[sfb] = sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f/LD_DATA_SCALING); + + /* set noiseNrg in valid region */ + if(!firstPNSband) { + INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy; + + if(deltaiNoiseEnergy > CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV; + else if(deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV; + } + else { + firstPNSband = 0; + } + lastiNoiseEnergy = noiseNrg[sfb]; + } + else { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + } +} + + +/***************************************************************************** + + functionname:FDKaacEnc_PreProcessPnsChannelPair + description: Calculate the correlation of noise in a channel pair + + returns: + input: sfbActive + pointer to sfb energies left, right and mid channel + pns config structure + pns data structure left and right (modified) + + output: noiseEnergyCorrelation in pns data structure + +*****************************************************************************/ + +void FDKaacEnc_PreProcessPnsChannelPair(const INT sfbActive, + FIXP_DBL *RESTRICT sfbEnergyLeft, + FIXP_DBL *RESTRICT sfbEnergyRight, + FIXP_DBL *RESTRICT sfbEnergyLeftLD, + FIXP_DBL *RESTRICT sfbEnergyRightLD, + FIXP_DBL *RESTRICT sfbEnergyMid, + PNS_CONFIG *RESTRICT pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight) +{ + INT sfb; + FIXP_DBL ccf; + + if(!pnsConf->usePns) + return; + + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = pnsDataLeft->noiseEnergyCorrelation; + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = pnsDataRight->noiseEnergyCorrelation; + + for(sfb=0;sfb< sfbActive;sfb++) { + FIXP_DBL quot = (sfbEnergyLeftLD[sfb]>>1) + (sfbEnergyRightLD[sfb]>>1); + + if(quot < FL2FXCONST_DBL(-32.0f/(float)LD_DATA_SCALING)) + ccf = FL2FXCONST_DBL(0.0f); + else { + FIXP_DBL accu = sfbEnergyMid[sfb]- (((sfbEnergyLeft[sfb]>>1)+(sfbEnergyRight[sfb]>>1))>>1); + INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0 ; + accu = fixp_abs(accu); + + ccf = CalcLdData(accu) + FL2FXCONST_DBL((float)1.0f/(float)LD_DATA_SCALING) - quot; /* ld(accu*2) = ld(accu) + 1 */ + ccf = (ccf>=FL2FXCONST_DBL(0.0)) ? ((FIXP_DBL)MAXVAL_DBL) : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf); + } + + pNoiseEnergyCorrelationL[sfb] = ccf; + pNoiseEnergyCorrelationR[sfb] = ccf; + } +} + + + +/***************************************************************************** + + functionname:FDKaacEnc_PostProcessPnsChannelPair + description: if PNS used at left and right channel, + use msMask to flag correlation + returns: + input: sfbActive + pns config structure + pns data structure left and right (modified) + pointer to msMask, flags correlation by pns coding (modified) + Digest of MS coding + output: pnsFlag in pns data structure, + msFlag in msMask (flags correlation) + +*****************************************************************************/ + +void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, + INT *RESTRICT msMask, + INT *msDigest ) +{ + INT sfb; + + if(!pnsConf->usePns) + return; + + for(sfb=0;sfbpnsFlag[sfb]) && + (pnsDataRight->pnsFlag[sfb]) ) { + /* AAC only: Standard */ + /* do this to avoid ms flags in layers that should not have it */ + if(pnsDataLeft->noiseEnergyCorrelation[sfb] <= pnsConf->noiseCorrelationThresh){ + msMask[sfb] = 0; + *msDigest = MS_SOME; + } + } + else { + /* + No PNS coding + */ + pnsDataLeft->pnsFlag[sfb] = 0; + pnsDataRight->pnsFlag[sfb] = 0; + } + } + + /* + Use MS flag to signal noise correlation if + pns is active in both channels + */ + if( (pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb]) ) { + if(pnsDataLeft->noiseEnergyCorrelation[sfb] > pnsConf->noiseCorrelationThresh) { + msMask[sfb] = 1; + *msDigest = MS_SOME; + } + } + } +} diff --git a/libAACenc/src/aacenc_pns.h b/libAACenc/src/aacenc_pns.h new file mode 100644 index 00000000..3bda9def --- /dev/null +++ b/libAACenc/src/aacenc_pns.h @@ -0,0 +1,113 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: pns.h + +******************************************************************************/ + +#ifndef __PNS_H +#define __PNS_H + +#include "common_fix.h" + +#include "pnsparam.h" + +#define NO_NOISE_PNS FDK_INT_MIN + +typedef struct{ + NOISEPARAMS np; + FIXP_DBL minCorrelationEnergy; + FIXP_DBL noiseCorrelationThresh; + INT usePns; +} PNS_CONFIG; + +typedef struct{ + FIXP_SGL noiseFuzzyMeasure[MAX_GROUPED_SFB]; + FIXP_DBL noiseEnergyCorrelation[MAX_GROUPED_SFB]; + INT pnsFlag[MAX_GROUPED_SFB]; +} PNS_DATA; + +#endif diff --git a/libAACenc/src/aacenc_tns.cpp b/libAACenc/src/aacenc_tns.cpp new file mode 100644 index 00000000..d0ff6acd --- /dev/null +++ b/libAACenc/src/aacenc_tns.cpp @@ -0,0 +1,1362 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: Alex Groeschel, Tobias Chalupka + contents/description: Temporal noise shaping + +******************************************************************************/ + +#include "aacenc_tns.h" +#include "psy_const.h" +#include "psy_configuration.h" +#include "tns_func.h" +#include "aacEnc_rom.h" +#include "aacenc_tns.h" + +#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */ + +static const FIXP_DBL acfWindowLong[12+3+1] = { + 0x7fffffff,0x7fb80000,0x7ee00000,0x7d780000,0x7b800000,0x78f80000,0x75e00000,0x72380000, + 0x6e000000,0x69380000,0x63e00000,0x5df80000,0x57800000,0x50780000,0x48e00000,0x40b80000 +}; + +static const FIXP_DBL acfWindowShort[4+3+1] = { + 0x7fffffff,0x7e000000,0x78000000,0x6e000000,0x60000000,0x4e000000,0x38000000,0x1e000000 +}; + +typedef struct{ + INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */ + INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */ + TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */ + +} TNS_INFO_TAB; + +#define TNS_TIMERES_SCALE (1) +#define FL2_TIMERES_FIX(a) ( FL2FXCONST_DBL(a/(float)(1<= tnsInfoTab[i].bitRateFrom[sbrLd?1:0]) && + bitRate <= tnsInfoTab[i].bitRateTo[sbrLd?1:0]) + { + tnsConfigTab = &tnsInfoTab[i].paramTab[(channels==1)?0:1]; + } + } + + return tnsConfigTab; +} + + +static INT getTnsMaxBands( + const INT sampleRate, + const INT granuleLength, + const INT isShortBlock + ) +{ + int i; + INT numBands = -1; + const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL; + int maxBandsTabSize = 0; + + switch (granuleLength) { + case 960: + pMaxBandsTab = tnsMaxBandsTab960; + maxBandsTabSize = sizeof(tnsMaxBandsTab960)/sizeof(TNS_MAX_TAB_ENTRY); + break; + case 1024: + pMaxBandsTab = tnsMaxBandsTab1024; + maxBandsTabSize = sizeof(tnsMaxBandsTab1024)/sizeof(TNS_MAX_TAB_ENTRY); + break; + case 480: + pMaxBandsTab = tnsMaxBandsTab480; + maxBandsTabSize = sizeof(tnsMaxBandsTab480)/sizeof(TNS_MAX_TAB_ENTRY); + break; + case 512: + pMaxBandsTab = tnsMaxBandsTab512; + maxBandsTabSize = sizeof(tnsMaxBandsTab512)/sizeof(TNS_MAX_TAB_ENTRY); + break; + default: + numBands = -1; + } + + if (pMaxBandsTab!=NULL) { + for (i=0; i= pMaxBandsTab[i].samplingRate) { + break; + } + } + } + + return numBands; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_FreqToBandWithRounding + + Returns index of nearest band border + + \param frequency + \param sampling frequency + \param total number of bands + \param pointer to table of band borders + + \return band border +****************************************************************************/ + +INT FDKaacEnc_FreqToBandWithRounding( + const INT freq, + const INT fs, + const INT numOfBands, + const INT *bandStartOffset + ) +{ + INT lineNumber, band; + + /* assert(freq >= 0); */ + lineNumber = (freq*bandStartOffset[numOfBands]*4/fs+1)/2; + + /* freq > fs/2 */ + if (lineNumber >= bandStartOffset[numOfBands]) + return numOfBands; + + /* find band the line number lies in */ + for (band=0; bandlineNumber) break; + } + + /* round to nearest band border */ + if (lineNumber - bandStartOffset[band] > + bandStartOffset[band+1] - lineNumber ) + { + band++; + } + + return(band); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_InitTnsConfiguration + description: fill TNS_CONFIG structure with sensible content + returns: + input: bitrate, samplerate, number of channels, + blocktype (long or short), + TNS Config struct (modified), + psy config struct, + tns active flag + output: + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitRate, + INT sampleRate, + INT channels, + INT blockType, + INT granuleLength, + INT isLowDelay, + INT ldSbrPresent, + TNS_CONFIG *tC, + PSY_CONFIGURATION *pC, + INT active, + INT useTnsPeak) +{ + int i; + //float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f; + + if (channels <= 0) + return (AAC_ENCODER_ERROR)1; + + tC->isLowDelay = isLowDelay; + + /* initialize TNS filter flag, order, and coefficient resolution (in bits per coeff) */ + tC->tnsActive = (active) ? TRUE : FALSE; + tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ + if (bitRate < 16000) + tC->maxOrder -= 2; + tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4; + + /* LPC stop line: highest MDCT line to be coded, but do not go beyond TNS_MAX_BANDS! */ + tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, (blockType == SHORT_WINDOW) ? 1 : 0); + + if (tC->lpcStopBand < 0) { + return (AAC_ENCODER_ERROR)1; + } + + tC->lpcStopBand = FDKmin(tC->lpcStopBand, pC->sfbActive); + tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; + + switch (granuleLength) { + case 960: + case 1024: + /* TNS start line: skip lower MDCT lines to prevent artifacts due to filter mismatch */ + tC->lpcStartBand[LOFILT] = (blockType == SHORT_WINDOW) ? 0 : ((sampleRate < 18783) ? 4 : 8); + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + i = tC->lpcStopBand; + while (pC->sfbOffset[i] > (tC->lpcStartLine[LOFILT] + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) i--; + tC->lpcStartBand[HIFILT] = i; + tC->lpcStartLine[HIFILT] = pC->sfbOffset[i]; + + tC->confTab.threshOn[HIFILT] = 1437; + tC->confTab.threshOn[LOFILT] = 1500; + + tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder; + tC->confTab.tnsLimitOrder[LOFILT] = tC->maxOrder - 7; + + tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION; + tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION; + + tC->confTab.acfSplit[HIFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation*/ + tC->confTab.acfSplit[LOFILT] = -1; /* signal Merged4to2QuartersAutoCorrelation in FDKaacEnc_MergedAutoCorrelation */ + + tC->confTab.filterEnabled[HIFILT] = 1; + tC->confTab.filterEnabled[LOFILT] = 1; + tC->confTab.seperateFiltersAllowed = 1; + + /* compute autocorrelation window based on maximum filter order for given block type */ + /* for (i = 0; i <= tC->maxOrder + 3; i++) { + float acfWinTemp = acfTimeRes * i; + acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp); + } + */ + if (blockType == SHORT_WINDOW) { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, FDKmin(sizeof(acfWindowShort), sizeof(tC->acfWindow[HIFILT]))); + } + else { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, FDKmin(sizeof(acfWindowLong), sizeof(tC->acfWindow[HIFILT]))); + } + break; + case 480: + case 512: + { + const TNS_PARAMETER_TABULATED* pCfg = FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent); + + if ( pCfg != NULL ) { + + FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab)); + + tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); + tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; + tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWithRounding(pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, pC->sfbOffset); + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + FDKaacEnc_CalcGaussWindow(tC->acfWindow[HIFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE); + FDKaacEnc_CalcGaussWindow(tC->acfWindow[LOFILT], tC->maxOrder+1, sampleRate, granuleLength, pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE); + } + else { + tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ + } + } + break; + default: + tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ + } + + return AAC_ENC_OK; + +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_ScaleUpSpectrum + + Scales up spectrum lines in a given frequency section + + \param scaled spectrum + \param original spectrum + \param frequency line to start scaling + \param frequency line to enc scaling + + \return scale factor + +****************************************************************************/ +static inline INT FDKaacEnc_ScaleUpSpectrum( + FIXP_DBL *dest, + const FIXP_DBL *src, + const INT startLine, + const INT stopLine + ) +{ + INT i, scale; + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.f); + + /* Get highest value in given spectrum */ + for (i=startLine; i>scale); + } + } + else { + for (i=startLine; i<(stopLine-lag); i++) { + result += (fMult(spectrum[i], spectrum[i+lag])>>scale); + } + } + + return result; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_AutoCorrNormFac + + Autocorrelation function for 1st and 2nd half of the spectrum + + \param pointer to spectrum + \param pointer to autocorrelation window + \param filter start line + +****************************************************************************/ +static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac( + const FIXP_DBL value, + const INT scale, + INT *sc + ) +{ + #define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */ + #define MAX_INV_NRGFAC (1.f/HLM_MIN_NRG) + + FIXP_DBL retValue; + FIXP_DBL A, B; + + if (scale>=0) { + A = value; + B = FL2FXCONST_DBL(HLM_MIN_NRG)>>fixMin(DFRACT_BITS-1,scale); + } + else { + A = value>>fixMin(DFRACT_BITS-1,(-scale)); + B = FL2FXCONST_DBL(HLM_MIN_NRG); + } + + if (A > B) { + int shift = 0; + FIXP_DBL tmp = invSqrtNorm2(value,&shift); + + retValue = fMult(tmp,tmp); + *sc += (2*shift); + } + else { + /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */ + retValue = /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL; + *sc += scale+28; + } + + return retValue; +} + +static void FDKaacEnc_MergedAutoCorrelation( + const FIXP_DBL *spectrum, + const INT isLowDelay, + const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER+3+1], + const INT lpcStartLine[MAX_NUM_OF_FILTERS], + const INT lpcStopLine, + const INT maxOrder, + const INT acfSplit[MAX_NUM_OF_FILTERS], + FIXP_DBL *_rxx1, + FIXP_DBL *_rxx2 + ) +{ + int i, idx0, idx1, idx2, idx3, idx4, lag; + FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0; + + /* buffer for temporal spectrum */ + C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024)); + + /* pre-initialization output */ + FDKmemclear(&_rxx1[0], sizeof(FIXP_DBL)*(maxOrder+1)); + FDKmemclear(&_rxx2[0], sizeof(FIXP_DBL)*(maxOrder+1)); + + idx0 = idx1 = idx2 = idx3 = idx4 = 0; + + /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters */ + if ( (acfSplit[LOFILT]==-1) || (acfSplit[HIFILT]==-1) ) { + /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the spectrum */ + idx0 = lpcStartLine[LOFILT]; + i = lpcStopLine - lpcStartLine[LOFILT]; + idx1 = idx0 + i / 4; + idx2 = idx0 + i / 2; + idx3 = idx0 + i * 3 / 4; + idx4 = lpcStopLine; + } + else { + FDK_ASSERT(acfSplit[LOFILT]==1); + FDK_ASSERT(acfSplit[HIFILT]==3); + i = (lpcStopLine - lpcStartLine[HIFILT]) / 3; + idx0 = lpcStartLine[LOFILT]; + idx1 = lpcStartLine[HIFILT]; + idx2 = idx1 + i; + idx3 = idx2 + i; + idx4 = lpcStopLine; + } + + /* copy spectrum to temporal buffer and scale up as much as possible */ + INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1); + INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2); + INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3); + INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4); + + /* get scaling values for summation */ + INT nsc1, nsc2, nsc3, nsc4; + for (nsc1=1; (1<dataRaw.Short.subBlockInfo[subBlockNumber] + : &tnsData->dataRaw.Long.subBlockInfo; + + tnsData->filtersMerged = FALSE; + + tsbi->tnsActive[HIFILT] = FALSE; + tsbi->predictionGain[HIFILT] = 1000; + tsbi->tnsActive[LOFILT] = FALSE; + tsbi->predictionGain[LOFILT] = 1000; + + tnsInfo->numOfFilters[subBlockNumber] = 0; + tnsInfo->coefRes[subBlockNumber] = tC->coefRes; + for (i = 0; i < tC->maxOrder; i++) { + tnsInfo->coef[subBlockNumber][HIFILT][i] = tnsInfo->coef[subBlockNumber][LOFILT][i] = 0; + } + + tnsInfo->length[subBlockNumber][HIFILT] = tnsInfo->length[subBlockNumber][LOFILT] = 0; + tnsInfo->order [subBlockNumber][HIFILT] = tnsInfo->order [subBlockNumber][LOFILT] = 0; + + if ( (tC->tnsActive) && (tC->maxOrder>0) ) + { + int sumSqrCoef; + + FDKaacEnc_MergedAutoCorrelation( + spectrum, + tC->isLowDelay, + tC->acfWindow, + tC->lpcStartLine, + tC->lpcStopLine, + tC->maxOrder, + tC->confTab.acfSplit, + rxx1, + rxx2); + + /* compute higher TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ + tsbi->predictionGain[HIFILT] = FDKaacEnc_AutoToParcor(rxx2, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT]); + + /* non-linear quantization of TNS lattice coefficients with given resolution */ + FDKaacEnc_Parcor2Index( + parcor_tmp, + tnsInfo->coef[subBlockNumber][HIFILT], + tC->confTab.tnsLimitOrder[HIFILT], + tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */ + for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] * tnsInfo->coef[subBlockNumber][HIFILT][i]; + } + + tnsInfo->direction[subBlockNumber][HIFILT] = tC->confTab.tnsFilterDirection[HIFILT]; + tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT]; + + /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small */ + if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT]/2 + 2))) + { + tsbi->tnsActive[HIFILT] = TRUE; + tnsInfo->numOfFilters[subBlockNumber]++; + + /* compute second filter for lower quarter; only allowed for long windows! */ + if ( (blockType != SHORT_WINDOW) && + (tC->confTab.filterEnabled[LOFILT]) && (tC->confTab.seperateFiltersAllowed) ) + { + /* compute second filter for lower frequencies */ + + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ + INT predGain = FDKaacEnc_AutoToParcor(rxx1, parcor_tmp, tC->confTab.tnsLimitOrder[LOFILT]); + + /* non-linear quantization of TNS lattice coefficients with given resolution */ + FDKaacEnc_Parcor2Index( + parcor_tmp, + tnsInfo->coef[subBlockNumber][LOFILT], + tC->confTab.tnsLimitOrder[LOFILT], + tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) */ + for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) { + break; + } + } + tnsInfo->order[subBlockNumber][LOFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] * tnsInfo->coef[subBlockNumber][LOFILT][i]; + } + + tnsInfo->direction[subBlockNumber][LOFILT] = tC->confTab.tnsFilterDirection[LOFILT]; + tnsInfo->length[subBlockNumber][LOFILT] = tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT]; + + /* filter lower quarter if gain is high enough, but not if it's too high */ + if ( ( (predGain > tC->confTab.threshOn[LOFILT]) && (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT])) ) + || ( (sumSqrCoef > 9) && (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]) ) ) + { + /* compare lower to upper filter; if they are very similar, merge them */ + tsbi->tnsActive[LOFILT] = TRUE; + sumSqrCoef = 0; + for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) { + sumSqrCoef += FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i] - tnsInfo->coef[subBlockNumber][LOFILT][i]); + } + if ( (sumSqrCoef < 2) && + (tnsInfo->direction[subBlockNumber][LOFILT] == tnsInfo->direction[subBlockNumber][HIFILT]) ) + { + tnsData->filtersMerged = TRUE; + tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[LOFILT]; + for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) { + if (FDKabs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) { + break; + } + } + for (i--; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + if (i < tnsInfo->order[subBlockNumber][HIFILT]) { + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + } + } + else { + tnsInfo->numOfFilters[subBlockNumber]++; + } + } /* filter lower part */ + tsbi->predictionGain[LOFILT]=predGain; + + } /* second filter allowed */ + } /* if predictionGain > 1437 ... */ + } /* maxOrder > 0 && tnsActive */ + + return 0; + +} + + +/***************************************************************************/ +/*! + \brief FDKaacLdEnc_TnsSync + + synchronize TNS parameters when TNS gain difference small (relative) + + \param pointer to TNS data structure (destination) + \param pointer to TNS data structure (source) + \param pointer to TNS config structure + \param number of sub-block + \param block type + + \return void +****************************************************************************/ +void FDKaacEnc_TnsSync( + TNS_DATA *tnsDataDest, + const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, + TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, + const INT blockTypeSrc, + const TNS_CONFIG *tC + ) +{ + int i, w, absDiff, nWindows; + TNS_SUBBLOCK_INFO *sbInfoDest; + const TNS_SUBBLOCK_INFO *sbInfoSrc; + + /* if one channel contains short blocks and the other not, do not synchronize */ + if ( (blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) || + (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW) ) + { + return; + } + + if (blockTypeDest != SHORT_WINDOW) { + sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo; + sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo; + nWindows = 1; + } else { + sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0]; + sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0]; + nWindows = 8; + } + + for (w=0; wtnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) { + for (i = 0; i < tC->maxOrder; i++) { + absDiff = FDKabs(tnsInfoDest->coef[w][HIFILT][i] - tnsInfoSrc->coef[w][HIFILT][i]); + absDiffSum += absDiff; + /* if coefficients diverge too much between channels, do not synchronize */ + if ((absDiff > 1) || (absDiffSum > 2)) { + doSync = 0; + break; + } + } + + if (doSync) { + /* if no significant difference was detected, synchronize coefficient sets */ + if (pSbInfoSrcW->tnsActive[HIFILT]) { + /* no dest filter, or more dest than source filters: use one dest filter */ + if ((!pSbInfoDestW->tnsActive[HIFILT]) || + ((pSbInfoDestW->tnsActive[HIFILT]) && (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) + { + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1; + } + tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged; + tnsInfoDest->order [w][HIFILT] = tnsInfoSrc->order [w][HIFILT]; + tnsInfoDest->length [w][HIFILT] = tnsInfoSrc->length [w][HIFILT]; + tnsInfoDest->direction [w][HIFILT] = tnsInfoSrc->direction [w][HIFILT]; + tnsInfoDest->coefCompress[w][HIFILT] = tnsInfoSrc->coefCompress[w][HIFILT]; + + for (i = 0; i < tC->maxOrder; i++) { + tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i]; + } + } + else + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0; + } + } + + } +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_TnsEncode + + perform TNS encoding + + \param pointer to TNS info structure + \param pointer to TNS data structure + \param number of sfbs + \param pointer to TNS config structure + \param low-pass line + \param pointer to spectrum + \param number of sub-block + \param block type + + \return ERROR STATUS +****************************************************************************/ +INT FDKaacEnc_TnsEncode( + TNS_INFO* tnsInfo, + TNS_DATA* tnsData, + const INT numOfSfb, + const TNS_CONFIG *tC, + const INT lowPassLine, + FIXP_DBL* spectrum, + const INT subBlockNumber, + const INT blockType + ) +{ + INT i, startLine, stopLine; + + if ( ( (blockType == SHORT_WINDOW) && (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber].tnsActive[HIFILT]) ) + || ( (blockType != SHORT_WINDOW) && (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]) ) ) + { + return 1; + } + + startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT] : tC->lpcStartLine[HIFILT]; + stopLine = tC->lpcStopLine; + + for (i=0; inumOfFilters[subBlockNumber]; i++) { + + INT lpcGainFactor; + FIXP_DBL LpcCoeff[TNS_MAX_ORDER]; + FIXP_DBL workBuffer[TNS_MAX_ORDER]; + FIXP_DBL parcor_tmp[TNS_MAX_ORDER]; + + FDKaacEnc_Index2Parcor( + tnsInfo->coef[subBlockNumber][i], + parcor_tmp, + tnsInfo->order[subBlockNumber][i], + tC->coefRes); + + lpcGainFactor = FDKaacEnc_ParcorToLpc( + parcor_tmp, + LpcCoeff, + tnsInfo->order[subBlockNumber][i], + workBuffer); + + FDKaacEnc_AnalysisFilter( + &spectrum[startLine], + stopLine - startLine, + LpcCoeff, + tnsInfo->order[subBlockNumber][i], + lpcGainFactor); + + /* update for second filter */ + startLine = tC->lpcStartLine[LOFILT]; + stopLine = tC->lpcStartLine[HIFILT]; + } + + return(0); + +} + +static void FDKaacEnc_CalcGaussWindow( + FIXP_DBL *win, + const int winSize, + const INT samplingRate, + const INT transformResolution, + const FIXP_DBL timeResolution, + const INT timeResolution_e + ) +{ + #define PI_E (2) + #define PI_M FL2FXCONST_DBL(3.1416f/(float)(1<> (DFRACT_BITS-1)); + tmp = (FIXP_DBL)((LONG)workBuffer[0]^sign); + + if(input[0]=0; j--) { + FIXP_DBL accu1 = fMult(tmp, input[j]); + FIXP_DBL accu2 = fMult(tmp, workBuffer[j]); + workBuffer[j] += accu1; + input[j] += accu2; + } + + workBuffer++; + } + + tmp = fMult((FIXP_DBL)((LONG)TNS_PREDGAIN_SCALE<<21), fDivNorm(fAbs(autoCorr_0), fAbs(input[0]), &scale)); + if ( fMultDiv2(autoCorr_0, input[0]) FDKaacEnc_tnsCoeff3Borders[i]) + index=i; + } + return(index-4); +} + +static INT FDKaacEnc_Search4(FIXP_DBL parcor) +{ + INT i, index=0; + + for(i=0;i<16;i++){ + if(parcor > FDKaacEnc_tnsCoeff4Borders[i]) + index=i; + } + return(index-8); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_Parcor2Index + +*****************************************************************************/ +static void FDKaacEnc_Parcor2Index( + const FIXP_DBL *parcor, + INT *RESTRICT index, + const INT order, + const INT bitsPerCoeff + ) +{ + INT i; + for(i=0; i, + ptr. to work buffer (required size: order) + output: LPC coefficients + +*****************************************************************************/ +static INT FDKaacEnc_ParcorToLpc( + const FIXP_DBL *reflCoeff, + FIXP_DBL *RESTRICT LpcCoeff, + const INT numOfCoeff, + FIXP_DBL *RESTRICT workBuffer + ) +{ + INT i, j; + INT shiftval, par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + LpcCoeff[0] = reflCoeff[0] >> par2LpcShiftVal; + for(i=1; i> par2LpcShiftVal; + } + + /* normalize LpcCoeff and calc shiftfactor */ + for(i=0; i=par2LpcShiftVal) ? par2LpcShiftVal : shiftval; + + for(i=0; i0) { + + INT idx = 0; + + /* keep filter coefficients twice and save memory copy operation in + modulo state buffer */ +#if defined(ARCH_PREFER_MULT_32x16) + FIXP_SGL coeff[2*TNS_MAX_ORDER]; + const FIXP_SGL *pCoeff; + for(i=0;i=0); + signal[j] = (tmp< 12 */ + /* for Short: length TRANS_FAC*TNS_MAX_ORDER (only 5 for short LC) is required -> 8*5=40 */ + /* Currently TRANS_FAC*TNS_MAX_ORDER = 8*12 = 96 (for LC) is used (per channel)! Memory could be saved here! */ + INT coef[TRANS_FAC][MAX_NUM_OF_FILTERS][TNS_MAX_ORDER]; +}TNS_INFO; + +INT FDKaacEnc_FreqToBandWithRounding( + const INT freq, + const INT fs, + const INT numOfBands, + const INT *bandStartOffset + ); + +#endif /* _TNS_H */ diff --git a/libAACenc/src/adj_thr.cpp b/libAACenc/src/adj_thr.cpp new file mode 100644 index 00000000..a79a9aee --- /dev/null +++ b/libAACenc/src/adj_thr.cpp @@ -0,0 +1,2666 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Threshold compensation + +******************************************************************************/ + +#include "common_fix.h" + +#include "adj_thr_data.h" +#include "adj_thr.h" +#include "qc_data.h" +#include "sf_estim.h" +#include "aacEnc_ram.h" + + + + +#define INV_INT_TAB_SIZE (8) +static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = +{ + 0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa, 0x20000000, 0x19999999, 0x15555555, 0x12492492 +}; + + +#define INV_SQRT4_TAB_SIZE (8) +static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = +{ + 0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5, 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1 +}; + + +/*static const INT invRedExp = 4;*/ +static const FIXP_DBL SnrLdMin1 = (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin2 = (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16) /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdFac = (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8) /FDKlog(2.0)/LD_DATA_SCALING);*/ + +static const FIXP_DBL SnrLdMin3 = (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5) /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin4 = (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0) /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin5 = (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) /FDKlog(2.0)/LD_DATA_SCALING);*/ + + +/* +The bits2Pe factors are choosen for the case that some times +the crash recovery strategy will be activated once. +*/ + +typedef struct { + INT bitrate; + ULONG bits2PeFactor_mono; + ULONG bits2PeFactor_mono_slope; + ULONG bits2PeFactor_stereo; + ULONG bits2PeFactor_stereo_slope; + ULONG bits2PeFactor_mono_scfOpt; + ULONG bits2PeFactor_mono_scfOpt_slope; + ULONG bits2PeFactor_stereo_scfOpt; + ULONG bits2PeFactor_stereo_scfOpt_slope; + +} BIT_PE_SFAC; + +typedef struct { + const INT sampleRate; + const BIT_PE_SFAC * pPeTab; + const INT nEntries; + +} BITS2PE_CFG_TAB; + +static const BIT_PE_SFAC S_Bits2PeTab16000[] = { + { 10000, 0x228F5C29, 0x02FEF55D, 0x1D70A3D7, 0x09BC9D6D, 0x228F5C29, 0x02FEF55D, 0x1C28F5C3, 0x0CBB92CA}, + { 24000, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413}, + { 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105}, + { 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105}, + { 64000, 0x25c28f40, 0x00000000, 0x251EB852, 0x01480000, 0x25c28f40, 0x00000000, 0x2570A3D7, 0x01480000}, + { 96000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000}, + {128000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000}, + {148000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000} +}; + +static const BIT_PE_SFAC S_Bits2PeTab22050[] = { + { 16000, 0x1a8f5c29, 0x1797cc3a, 0x128f5c29, 0x18e75793, 0x175c28f6, 0x221426fe, 0x00000000, 0x5a708ede}, + { 24000, 0x2051eb85, 0x092ccf6c, 0x18a3d70a, 0x13a92a30, 0x1fae147b, 0xbcbe61d, 0x16147ae1, 0x18e75793}, + { 32000, 0x228f5c29, 0x029f16b1, 0x1d70a3d7, 0x088509c0, 0x228f5c29, 0x29f16b1, 0x1c28f5c3, 0x0b242071}, + { 48000, 0x23d70a3d, 0x014f8b59, 0x2199999a, 0x03eea20a, 0x23d70a3d, 0x14f8b59, 0x2199999a, 0x03eea20a}, + { 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0, 0x23851eb8, 0x00fba882}, + { 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882}, + {128000, 0x25c28f40, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x25c28f40, 0x2570a3d7, 0x009f16b1}, + {148000, 0x25c28f40, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x25c28f40, 0x270a3d71, 0x00000000} +}; + +static const BIT_PE_SFAC S_Bits2PeTab24000[] = { + { 16000, 0x19eb851f, 0x13a92a30, 0x1147ae14, 0x164840e1, 0x1999999a, 0x12599ed8, 0x00000000, 0x46c764ae}, + { 24000, 0x1eb851ec, 0x0d1b7176, 0x16b851ec, 0x18e75793, 0x1e147ae1, 0x0fba8827, 0x1147ae14, 0x2c9081c3}, + { 32000, 0x21eb851f, 0x049667b6, 0x1ccccccd, 0x07357e67, 0x21eb851f, 0x03eea20a, 0x1c28f5c3, 0x07357e67}, + { 48000, 0x2428f5c3, 0x014f8b59, 0x2051eb85, 0x053e2d62, 0x23d70a3d, 0x01f75105, 0x1fae147b, 0x07357e67}, + { 64000, 0x24cccccd, 0x05e5f30e, 0x22e147ae, 0x01a36e2f, 0x24cccccd, 0x05e5f30e, 0x23333333, 0x014f8b59}, + { 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882}, + {128000, 0x4e666666, 0x1cd5f99c, 0x2570a3d7, 0x010c6f7a, 0x50a3d70a, 0x192a7371, 0x2570a3d7, 0x010c6f7a}, + {148000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000} +}; + +static const BIT_PE_SFAC S_Bits2PeTab32000[] = { + { 16000, 0x247ae140, 0xFFFFAC1E, 0x270a3d80, 0xFFFE9B7C, 0x14ccccc0, 0x000110A1, 0x15c28f60, 0xFFFEEF5F}, + { 24000, 0x23333340, 0x0fba8827, 0x21999980, 0x1b866e44, 0x18f5c280, 0x0fba8827, 0x119999a0, 0x4d551d69}, + { 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f}, + { 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e}, + { 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a}, + { 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f}, + {128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737}, + {148000, 0x25c28f40, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476}, + {160000, 0x25c28f40, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184}, + {200000, 0x25c28f40, 0x00000000, 0x2b333333, 0x0836be91, 0x25c28f40, 0x00000000, 0x2b333333, 0x0890390f}, + {320000, 0x25c28f40, 0x00000000, 0x4947ae14, 0x00000000, 0x25c28f40, 0x00000000, 0x4a8f5c29, 0x00000000} +}; + +static const BIT_PE_SFAC S_Bits2PeTab44100[] = { + { 16000, 0x10a3d70a, 0x1797cc3a, 0x00000000, 0x00000000, 0x00000000, 0x59210386, 0x00000000, 0x00000000}, + { 24000, 0x16666666, 0x1797cc3a, 0x00000000, 0x639d5e4a, 0x15c28f5c, 0x12599ed8, 0x00000000, 0x5bc01a37}, + { 32000, 0x1c28f5c3, 0x049667b6, 0x1851eb85, 0x049667b6, 0x1a3d70a4, 0x088509c0, 0x16666666, 0x053e2d62}, + { 48000, 0x1e666666, 0x05e5f30e, 0x1a8f5c29, 0x049667b6, 0x1e666666, 0x05e5f30e, 0x18f5c28f, 0x05e5f30e}, + { 64000, 0x2147ae14, 0x0346dc5d, 0x1ccccccd, 0x02f2f987, 0x2147ae14, 0x02f2f987, 0x1bd70a3d, 0x039abf34}, + { 96000, 0x247ae148, 0x068db8bb, 0x1fae147b, 0x029f16b1, 0x2428f5c3, 0x0639d5e5, 0x1f5c28f6, 0x029f16b1}, + {128000, 0x2ae147ae, 0x1b435265, 0x223d70a4, 0x0192a737, 0x2a3d70a4, 0x1040bfe4, 0x21eb851f, 0x0192a737}, + {148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b}, + {160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316}, + {200000, 0x25c28f40, 0x00000000, 0x25c28f5c, 0x0713f078, 0x25c28f40, 0x00000000, 0x2570a3d7, 0x072a4f17}, + {320000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000} +}; + +static const BIT_PE_SFAC S_Bits2PeTab48000[] = { + { 16000, 0x0f5c28f6, 0x31ceaf25, 0x00000000, 0x00000000, 0x00000000, 0x74a771c9, 0x00000000, 0x00000000}, + { 24000, 0x1b851eb8, 0x029f16b1, 0x00000000, 0x663c74fb, 0x1c7ae148, 0xe47991bd, 0x00000000, 0x49667b5f}, + { 32000, 0x1c28f5c3, 0x029f16b1, 0x18f5c28f, 0x07357e67, 0x15c28f5c, 0x0f12c27a, 0x11eb851f, 0x13016484}, + { 48000, 0x1d70a3d7, 0x053e2d62, 0x1c7ae148, 0xfe08aefc, 0x1d1eb852, 0x068db8bb, 0x1b333333, 0xfeb074a8}, + { 64000, 0x20000000, 0x03eea20a, 0x1b851eb8, 0x0346dc5d, 0x2051eb85, 0x0346dc5d, 0x1a8f5c29, 0x039abf34}, + { 96000, 0x23d70a3d, 0x053e2d62, 0x1eb851ec, 0x029f16b1, 0x23851eb8, 0x04ea4a8c, 0x1e147ae1, 0x02f2f987}, + {128000, 0x28f5c28f, 0x14727dcc, 0x2147ae14, 0x0218def4, 0x2851eb85, 0x0e27e0f0, 0x20f5c28f, 0x0218def4}, + {148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476}, + {160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737}, + {200000, 0x25c28f40, 0x00000000, 0x251eb852, 0x06775a1b, 0x25c28f40, 0x00000000, 0x24cccccd, 0x06a4175a}, + {320000, 0x25c28f40, 0x00000000, 0x3ccccccd, 0x00000000, 0x25c28f40, 0x00000000, 0x3d1eb852, 0x00000000} +}; + +static const BITS2PE_CFG_TAB bits2PeConfigTab[] = { + { 16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000)/sizeof(BIT_PE_SFAC) }, + { 22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050)/sizeof(BIT_PE_SFAC) }, + { 24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000)/sizeof(BIT_PE_SFAC) }, + { 32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000)/sizeof(BIT_PE_SFAC) }, + { 44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100)/sizeof(BIT_PE_SFAC) }, + { 48000, S_Bits2PeTab48000, sizeof(S_Bits2PeTab48000)/sizeof(BIT_PE_SFAC) } +}; + + + +/* values for avoid hole flag */ +enum _avoid_hole_state { + NO_AH =0, + AH_INACTIVE =1, + AH_ACTIVE =2 +}; + + +/* Q format definitions */ +#define Q_BITFAC (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */ +#define Q_AVGBITS (17) /* scale bit values */ + + +/***************************************************************************** + functionname: FDKaacEnc_InitBits2PeFactor + description: retrieve bits2PeFactor from table +*****************************************************************************/ +static void FDKaacEnc_InitBits2PeFactor( + FIXP_DBL *bits2PeFactor_m, + INT *bits2PeFactor_e, + const INT bitRate, + const INT nChannels, + const INT sampleRate, + const INT advancedBitsToPe, + const INT dZoneQuantEnable, + const INT invQuant + ) +{ + /* default bits2pe factor */ + FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f/(1<<(1))); + INT bit2PE_e = 1; + + /* make use of advanced bits to pe factor table */ + if (advancedBitsToPe) { + + int i; + const BIT_PE_SFAC *peTab = NULL; + INT size = 0; + + + /* Get correct table entry */ + for (i=0; i<(INT)(sizeof(bits2PeConfigTab)/sizeof(BITS2PE_CFG_TAB)); i++) { + if (sampleRate >= bits2PeConfigTab[i].sampleRate) { + peTab = bits2PeConfigTab[i].pPeTab; + size = bits2PeConfigTab[i].nEntries; + } + } + + if ( (peTab!=NULL) && (size!=0) ) { + + INT startB = -1; + LONG startPF = 0; + LONG peSlope = 0; + + /* stereo or mono mode and invQuant used or not */ + for (i=0; ibitRate) || ((i==size-2)) )) + { + if (nChannels==1) + { + startPF = (!invQuant) ? peTab[i].bits2PeFactor_mono : peTab[i].bits2PeFactor_mono_scfOpt; + peSlope = (!invQuant) ? peTab[i].bits2PeFactor_mono_slope : peTab[i].bits2PeFactor_mono_scfOpt_slope; + /*endPF = (!invQuant) ? peTab[i+1].bits2PeFactor_mono : peTab[i+1].bits2PeFactor_mono_scfOpt; + endB=peTab[i+1].bitrate;*/ + startB=peTab[i].bitrate; + break; + } + else + { + startPF = (!invQuant) ? peTab[i].bits2PeFactor_stereo : peTab[i].bits2PeFactor_stereo_scfOpt; + peSlope = (!invQuant) ? peTab[i].bits2PeFactor_stereo_slope : peTab[i].bits2PeFactor_stereo_scfOpt_slope; + /*endPF = (!invQuant) ? peTab[i+1].bits2PeFactor_stereo : peTab[i+1].bits2PeFactor_stereo_scfOpt; + endB=peTab[i+1].bitrate;*/ + startB=peTab[i].bitrate; + break; + } + } + } /* for i */ + + /* if a configuration is available */ + if (startB!=-1) { + /* linear interpolate to actual PEfactor */ + FIXP_DBL peFac = fMult((FIXP_DBL)(bitRate-startB)<<14, (FIXP_DBL)peSlope) << 2; + FIXP_DBL bit2PE = peFac + (FIXP_DBL)startPF; /* startPF_float = startPF << 2 */ + + /* sanity check if bits2pe value is high enough */ + if ( bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2) ) { + bit2PE_m = bit2PE; + bit2PE_e = 2; /* table is fixed scaled */ + } + } /* br */ + } /* sr */ + } /* advancedBitsToPe */ + + + if (dZoneQuantEnable) + { + if(bit2PE_m >= (FL2FXCONST_DBL(0.6f))>>bit2PE_e) + { + /* Additional headroom for addition */ + bit2PE_m >>= 1; + bit2PE_e += 1; + } + + /* the quantTendencyCompensator compensates a lower bit consumption due to increasing the tendency to quantize low spectral values to the lower quantizer border for bitrates below a certain bitrate threshold --> see also function calcSfbDistLD in quantize.c */ + if ((bitRate/nChannels > 32000) && (bitRate/nChannels <= 40000)) { + bit2PE_m += (FL2FXCONST_DBL(0.4f))>>bit2PE_e; + } + else if (bitRate/nChannels > 20000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e; + } + else if (bitRate/nChannels >= 16000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e; + } + else { + bit2PE_m += (FL2FXCONST_DBL(0.0f))>>bit2PE_e; + } + } + + + /***** 3.) Return bits2pe factor *****/ + *bits2PeFactor_m = bit2PE_m; + *bits2PeFactor_e = bit2PE_e; +} + + +/***************************************************************************** +functionname: FDKaacEnc_bits2pe2 +description: convert from bits to pe +*****************************************************************************/ +static INT FDKaacEnc_bits2pe2( + const INT bits, + const FIXP_DBL factor_m, + const INT factor_e + ) +{ + return (INT)(fMult(factor_m, (FIXP_DBL)(bits<> (Q_AVGBITS-factor_e)); +} + +/***************************************************************************** +functionname: FDKaacEnc_calcThreshExp +description: loudness calculation (threshold to the power of redExp) +*****************************************************************************/ +static void FDKaacEnc_calcThreshExp(FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], + QC_OUT_CHANNEL* qcOutChannel[(2)], + PSY_OUT_CHANNEL* psyOutChannel[(2)], + const INT nChannels) +{ + INT ch, sfb, sfbGrp; + FIXP_DBL thrExpLdData; + + for (ch=0; chsfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb]>>2 ; + thrExp[ch][sfbGrp+sfb] = CalcInvLdData(thrExpLdData); + } + } + } +} + + +/***************************************************************************** + functionname: FDKaacEnc_adaptMinSnr + description: reduce minSnr requirements for bands with relative low energies +*****************************************************************************/ +static void FDKaacEnc_adaptMinSnr(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + MINSNR_ADAPT_PARAM *msaParam, + const INT nChannels) +{ + INT ch, sfb, sfbGrp, nSfb; + FIXP_DBL avgEnLD64, dbRatio, minSnrRed; + FIXP_DBL minSnrLimitLD64 = FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */ + FIXP_DBL nSfbLD64; + FIXP_DBL accu; + + for (ch=0; chsfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + accu += psyOutChannel[ch]->sfbEnergy[sfbGrp+sfb]>>6; + nSfb++; + } + } + + if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) { + avgEnLD64 = FL2FXCONST_DBL(-1.0f); + } + else { + nSfbLD64 = CalcLdInt(nSfb); + avgEnLD64 = CalcLdData(accu); + avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - nSfbLD64; /* 0.09375f: compensate shift with 6 */ + } + + /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ + for (sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if ( (msaParam->startRatio + qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]) < avgEnLD64 ) { + dbRatio = fMult((avgEnLD64 - qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]),FL2FXCONST_DBL(0.3010299956f)); /* scaled by (1.0f/(10.0f*64.0f)) */ + minSnrRed = msaParam->redOffs + fMult(msaParam->redRatioFac,dbRatio); /* scaled by 1.0f/64.0f*/ + minSnrRed = fixMax(minSnrRed, msaParam->maxRed); /* scaled by 1.0f/64.0f*/ + qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb] = (fMult(qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb],minSnrRed)) << 6; + qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(minSnrLimitLD64, qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb]); + } + } + } + } +} + + +/***************************************************************************** +functionname: FDKaacEnc_initAvoidHoleFlag +description: determine bands where avoid hole is not necessary resp. possible +*****************************************************************************/ +static void FDKaacEnc_initAvoidHoleFlag(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + struct TOOLSINFO *toolsInfo, + const INT nChannels, + const PE_DATA *peData, + AH_PARAM *ahParam) +{ + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEn, sfbEnm1; + FIXP_DBL sfbEnLdData; + FIXP_DBL avgEnLdData; + + /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts + (avoid more holes in long blocks) */ + for (ch=0; chlastWindowSequence != SHORT_WINDOW) { + for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup) + for (sfb=0; sfbmaxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] >>= 1 ; + } + else { + for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup) + for (sfb=0; sfbmaxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] = + fMult(FL2FXCONST_DBL(0.63f), + qcOutChan->sfbSpreadEnergy[sfbGrp+sfb]) ; + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for(ch=0; chsfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + FIXP_DBL sfbEnp1, avgEn; + if (sfb > 0) + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp+sfb-1]; + else + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp+sfb]; + + if (sfb < psyOutChannel[ch]->maxSfbPerGroup-1) + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp+sfb+1]; + else + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp+sfb]; + + avgEn = (sfbEnm1>>1) + (sfbEnp1>>1); + avgEnLdData = CalcLdData(avgEn); + sfbEn = qcOutChan->sfbEnergy[sfbGrp+sfb]; + sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp+sfb]; + /* peak ? */ + if (sfbEn > avgEn) { + FIXP_DBL tmpMinSnrLdData; + if (psyOutChannel[ch]->lastWindowSequence==LONG_WINDOW) + tmpMinSnrLdData = fixMax( SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), (FIXP_DBL)SnrLdMin1 ) ; + else + tmpMinSnrLdData = fixMax( SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), (FIXP_DBL)SnrLdMin3 ) ; + + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] = + fixMin(qcOutChan->sfbMinSnrLdData[sfbGrp+sfb], tmpMinSnrLdData); + } + /* valley ? */ + if ( ((sfbEnLdData+(FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) && (sfbEn > FL2FXCONST_DBL(0.0)) ) { + FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData -(FIXP_DBL)SnrLdMin4 + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]; + tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData); + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(tmpMinSnrLdData, + (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + SnrLdMin2 )); + } + } + } + } + } + + /* stereo: adapt the minimum requirements sfbMinSnr of mid and + side channels to avoid spending unnoticable bits */ + if (nChannels == 2) { + QC_OUT_CHANNEL* qcOutChanM = qcOutChannel[0]; + QC_OUT_CHANNEL* qcOutChanS = qcOutChannel[1]; + PSY_OUT_CHANNEL* psyOutChanM = psyOutChannel[0]; + for(sfbGrp = 0;sfbGrp < psyOutChanM->sfbCnt;sfbGrp+= psyOutChanM->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if (toolsInfo->msMask[sfbGrp+sfb]) { + FIXP_DBL maxSfbEnLd = fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp+sfb],qcOutChanS->sfbEnergyLdData[sfbGrp+sfb]); + FIXP_DBL maxThrLd, sfbMinSnrTmpLd; + + if ( ((SnrLdMin5>>1) + (maxSfbEnLd>>1) + (qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb]>>1)) <= FL2FXCONST_DBL(-0.5f)) + maxThrLd = FL2FXCONST_DBL(-1.0f) ; + else + maxThrLd = SnrLdMin5 + maxSfbEnLd + qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb]; + + if (qcOutChanM->sfbEnergy[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp+sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] = fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb],sfbMinSnrTmpLd); + + if (qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb], (FIXP_DBL)SnrLdFac); + + if (qcOutChanS->sfbEnergy[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp+sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] = fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb],sfbMinSnrTmpLd); + + if (qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb],(FIXP_DBL)SnrLdFac); + + if (qcOutChanM->sfbEnergy[sfbGrp+sfb]>qcOutChanM->sfbSpreadEnergy[sfbGrp+sfb]) + qcOutChanS->sfbSpreadEnergy[sfbGrp+sfb] = + fMult(qcOutChanS->sfbEnergy[sfbGrp+sfb], FL2FXCONST_DBL(0.9f)); + + if (qcOutChanS->sfbEnergy[sfbGrp+sfb]>qcOutChanS->sfbSpreadEnergy[sfbGrp+sfb]) + qcOutChanM->sfbSpreadEnergy[sfbGrp+sfb] = + fMult(qcOutChanM->sfbEnergy[sfbGrp+sfb], FL2FXCONST_DBL(0.9f)); + } + } + } + } + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + for(ch=0; chsfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if ((qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] > qcOutChan->sfbEnergy[sfbGrp+sfb]) + || (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f))) { + ahFlag[ch][sfbGrp+sfb] = NO_AH; + } + else { + ahFlag[ch][sfbGrp+sfb] = AH_INACTIVE; + } + } + } + } +} + + + +/** + * \brief Calculate constants that do not change during successive pe calculations. + * + * \param peData Pointer to structure containing PE data of current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding nChannels elements. + * \param nChannels Number of channels in element. + * \param peOffset Fixed PE offset defined while FDKaacEnc_AdjThrInit() depending on bitrate. + * + * \return void + */ +static +void FDKaacEnc_preparePe(PE_DATA *peData, + PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + const INT nChannels, + const INT peOffset) +{ + INT ch; + + for(ch=0; chpeChannelData[ch], + psyOutChan->sfbEnergyLdData, + psyOutChan->sfbThresholdLdData, + qcOutChannel[ch]->sfbFormFactorLdData, + psyOutChan->sfbOffsets, + psyOutChan->sfbCnt, + psyOutChan->sfbPerGroup, + psyOutChan->maxSfbPerGroup); + } + peData->offset = peOffset; +} + +/** + * \brief Calculate weighting factor for threshold adjustment. + * + * Calculate weighting factor to be applied at energies and thresholds in ld64 format. + * + * \param peData, Pointer to PE data in current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding nChannels elements. + * \param toolsInfo Pointer to tools info struct of current element. + * \param adjThrStateElement Pointer to ATS_ELEMENT holding enFacPatch states. + * \param nChannels Number of channels in element. + * \param usePatchTool Apply the weighting tool 0 (no) else (yes). + * + * \return void + */ +static +void FDKaacEnc_calcWeighting(PE_DATA *peData, + PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + struct TOOLSINFO *toolsInfo, + ATS_ELEMENT* adjThrStateElement, + const INT nChannels, + const INT usePatchTool) +{ + int ch, noShortWindowInFrame = TRUE; + INT exePatchM = 0; + + for (ch=0; chlastWindowSequence == SHORT_WINDOW) { + noShortWindowInFrame = FALSE; + } + FDKmemclear(qcOutChannel[ch]->sfbEnFacLd, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); + } + + if (usePatchTool==0) { + return; /* tool is disabled */ + } + + for (ch=0; chsfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1); /* nrg^(1/2) */ + FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>2); /* nrg^(1/4) */ + + /* maximal number of bands is 64, results scaling factor 6 */ + nLinesSum += peData->peChannelData[ch].sfbNLines[sfbGrp+sfb]; /* relevant lines */ + nrgTotal += ( psyOutChan->sfbEnergy[sfbGrp+sfb] >> 6 ); /* sum up nrg */ + nrgSum12 += ( nrgFac12 >> 6 ); /* sum up nrg^(2/4) */ + nrgSum14 += ( nrgFac14 >> 6 ); /* sum up nrg^(1/4) */ + nrgSum34 += ( fMult(nrgFac14, nrgFac12) >> 6 ); /* sum up nrg^(3/4) */ + } + } + + nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */ + + nrgFacLd_14 = CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */ + nrgFacLd_12 = CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */ + nrgFacLd_34 = CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */ + + adjThrStateElement->chaosMeasureEnFac[ch] = FDKmax( FL2FXCONST_DBL(0.1875f), fDivNorm(nLinesSum,psyOutChan->sfbOffsets[psyOutChan->sfbCnt]) ); + + usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.78125f)); + exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch])); + + for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + INT sfbExePatch; + + /* for MS coupled SFBs, also execute patch in side channel if done in mid channel */ + if ((ch == 1) && (toolsInfo->msMask[sfbGrp+sfb])) { + sfbExePatch = exePatchM; + } + else { + sfbExePatch = exePatch; + } + + if ( (sfbExePatch) && (psyOutChan->sfbEnergy[sfbGrp+sfb]>FL2FXCONST_DBL(0.f)) ) + { + /* execute patch based on spectral flatness calculated above */ + if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.8125f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_14 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]+(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1)))>>1 ); /* sfbEnergy^(3/4) */ + } + else if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.796875f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp+sfb])>>1 ); /* sfbEnergy^(2/4) */ + } + else { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_34 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1))>>1 ); /* sfbEnergy^(1/4) */ + } + qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb],(FIXP_DBL)0); + + } + } + } /* sfb loop */ + + adjThrStateElement->lastEnFacPatch[ch] = usePatch; + exePatchM = exePatch; + } + else { + /* !noShortWindowInFrame */ + adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f); + adjThrStateElement->lastEnFacPatch[ch] = TRUE; /* allow use of sfbEnFac patch in upcoming frame */ + } + + } /* ch loop */ + +} + + + + +/***************************************************************************** +functionname: FDKaacEnc_calcPe +description: calculate pe for both channels +*****************************************************************************/ +static +void FDKaacEnc_calcPe(PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + PE_DATA *peData, + const INT nChannels) +{ + INT ch; + + peData->pe = peData->offset; + peData->constPart = 0; + peData->nActiveLines = 0; + for(ch=0; chpeChannelData[ch]; + FDKaacEnc_calcSfbPe(&peData->peChannelData[ch], + qcOutChannel[ch]->sfbWeightedEnergyLdData, + qcOutChannel[ch]->sfbThresholdLdData, + psyOutChannel[ch]->sfbCnt, + psyOutChannel[ch]->sfbPerGroup, + psyOutChannel[ch]->maxSfbPerGroup, + psyOutChannel[ch]->isBook, + psyOutChannel[ch]->isScale); + + peData->pe += peChanData->pe; + peData->constPart += peChanData->constPart; + peData->nActiveLines += peChanData->nActiveLines; + } +} + +void FDKaacEnc_peCalculation(PE_DATA *peData, + PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + struct TOOLSINFO *toolsInfo, + ATS_ELEMENT* adjThrStateElement, + const INT nChannels) +{ + /* constants that will not change during successive pe calculations */ + FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels, adjThrStateElement->peOffset); + + /* calculate weighting factor for threshold adjustment */ + FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo, adjThrStateElement, nChannels, 1); +{ + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + int ch; + for (ch=0; chsfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + pQcOutCh->sfbWeightedEnergyLdData[sfb+sfbGrp] = pQcOutCh->sfbEnergyLdData[sfb+sfbGrp] - pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; + pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] -= pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; + } + } + } +} + + /* pe without reduction */ + FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels); +} + + + +/***************************************************************************** +functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH +description: sum the pe data only for bands where avoid hole is inactive +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_calcPeNoAH(INT *pe, + INT *constPart, + INT *nActiveLines, + PE_DATA *peData, + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + PSY_OUT_CHANNEL* psyOutChannel[(2)], + const INT nChannels) +{ + INT ch, sfb,sfbGrp; + + INT pe_tmp = peData->offset; + INT constPart_tmp = 0; + INT nActiveLines_tmp = 0; + for(ch=0; chpeChannelData[ch]; + for(sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if(ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) { + pe_tmp += peChanData->sfbPe[sfbGrp+sfb]; + constPart_tmp += peChanData->sfbConstPart[sfbGrp+sfb]; + nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp+sfb]; + } + } + } + } + /* correct scaled pe and constPart values */ + *pe = pe_tmp >> PE_CONSTPART_SHIFT; + *constPart = constPart_tmp >> PE_CONSTPART_SHIFT; + + *nActiveLines = nActiveLines_tmp; +} + + +/***************************************************************************** +functionname: FDKaacEnc_reduceThresholdsCBR +description: apply reduction formula +*****************************************************************************/ +static const FIXP_DBL limitThrReducedLdData = (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/ + +static void FDKaacEnc_reduceThresholdsCBR(QC_OUT_CHANNEL* qcOutChannel[(2)], + PSY_OUT_CHANNEL* psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], + const INT nChannels, + const FIXP_DBL redVal, + const SCHAR redValScaling) +{ + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL sfbThrExp; + + for(ch=0; chsfbCnt; sfbGrp+= psyOutChannel[ch]->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb]; + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp+sfb]; + sfbThrExp = thrExp[ch][sfbGrp+sfb]; + if ((sfbEnLdData > sfbThrLdData) && (ahFlag[ch][sfbGrp+sfb] != AH_ACTIVE)) { + + /* threshold reduction formula: + float tmp = thrExp[ch][sfb]+redVal; + tmp *= tmp; + sfbThrReduced = tmp*tmp; + */ + int minScale = fixMin(CountLeadingBits(sfbThrExp), CountLeadingBits(redVal) - (DFRACT_BITS-1-redValScaling) )-1; + + /* 4*log( sfbThrExp + redVal ) */ + sfbThrReducedLdData = CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) + scaleValue(redVal,(DFRACT_BITS-1-redValScaling)+minScale))) + - (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT)); + sfbThrReducedLdData <<= 2; + + /* avoid holes */ + if ( ((sfbThrReducedLdData - sfbEnLdData) > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] ) + && (ahFlag[ch][sfbGrp+sfb] != NO_AH) ) + { + if (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] > (FL2FXCONST_DBL(-1.0f) - sfbEnLdData) ){ + sfbThrReducedLdData = fixMax((qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData), sfbThrLdData); + } + else sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; + } + + /* minimum of 29 dB Ratio for Thresholds */ + if ((sfbEnLdData+(FIXP_DBL)MAXVAL_DBL) > FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)){ + sfbThrReducedLdData = fixMax(sfbThrReducedLdData, (sfbEnLdData - FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING))); + } + + qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/* similar to prepareSfbPe1() */ +static FIXP_DBL FDKaacEnc_calcChaosMeasure(PSY_OUT_CHANNEL *psyOutChannel, + const FIXP_DBL *sfbFormFactorLdData) +{ + #define SCALE_FORM_FAC (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/ + #define SCALE_NRGS (8) + #define SCALE_NLINES (16) + #define SCALE_NRGS_SQRT4 (2) /* 0.25 * SCALE_NRGS */ + #define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */ + + INT sfbGrp, sfb; + FIXP_DBL chaosMeasure; + INT frameNLines = 0; + FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f); + FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f); + + for (sfbGrp=0; sfbGrpsfbCnt; sfbGrp+=psyOutChannel->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++){ + if (psyOutChannel->sfbEnergyLdData[sfbGrp+sfb] > psyOutChannel->sfbThresholdLdData[sfbGrp+sfb]) { + frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp+sfb])>>SCALE_FORM_FAC); + frameNLines += (psyOutChannel->sfbOffsets[sfbGrp+sfb+1] - psyOutChannel->sfbOffsets[sfbGrp+sfb]); + frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp+sfb]>>SCALE_NRGS); + } + } + } + + if(frameNLines > 0){ + + /* frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy *2^SCALE_NRGS)/frameNLines)^-0.25 + chaosMeasure = frameNActiveLines / frameNLines */ + chaosMeasure = + CalcInvLdData( (((CalcLdData(frameFormFactor)>>1) - + (CalcLdData(frameEnergy)>>(2+1))) - + (fMultDiv2(FL2FXCONST_DBL(0.75f),CalcLdData((FIXP_DBL)frameNLines<<(DFRACT_BITS-1-SCALE_NLINES))) - + (((FIXP_DBL)(SCALE_FORM_FAC-SCALE_NRGS_SQRT4+FORM_FAC_SHIFT-(SCALE_NLINES_P34))<<(DFRACT_BITS-1-LD_DATA_SHIFT))>>1)) + )<<1 ); + } else { + + /* assuming total chaos, if no sfb is above thresholds */ + chaosMeasure = FL2FXCONST_DBL(1.f); + } + + return chaosMeasure; +} + +/* apply reduction formula for VBR-mode */ +static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], + PSY_OUT_CHANNEL* psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], + const INT nChannels, + const FIXP_DBL vbrQualFactor, + FIXP_DBL* chaosMeasureOld) +{ + INT ch, sfbGrp, sfb; + FIXP_DBL chGroupEnergy[TRANS_FAC][2];/*energy for each group and channel*/ + FIXP_DBL chChaosMeasure[2]; + FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f); + FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f); + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp; + FIXP_DBL sfbThrReducedLdData; + FIXP_DBL chaosMeasureAvg; + INT groupCnt; /* loop counter */ + FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one redVal for each group */ + QC_OUT_CHANNEL *qcOutChan = NULL; + PSY_OUT_CHANNEL *psyOutChan = NULL; + +#define SCALE_GROUP_ENERGY (8) + +#define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f)) +#define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f-0.25f)) + +#define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f)) + + + for(ch=0; chsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup, groupCnt++) { + chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f); + for (sfb=0; sfbmaxSfbPerGroup; sfb++){ + chGroupEnergy[groupCnt][ch] += (psyOutChan->sfbEnergy[sfbGrp+sfb]>>SCALE_GROUP_ENERGY); + } + chEnergy += chGroupEnergy[groupCnt][ch]; + } + frameEnergy += chEnergy; + + /* chaosMeasure */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { + chChaosMeasure[ch] = FL2FXCONST_DBL(0.5f); /* assume a constant chaos measure of 0.5f for short blocks */ + } else { + chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure(psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData); + } + chaosMeasure += fMult(chChaosMeasure[ch], chEnergy); + } + + if(frameEnergy > chaosMeasure) { + INT scale = CntLeadingZeros(frameEnergy) - 1; + FIXP_DBL num = chaosMeasure<>2) + fMult(FL2FXCONST_DBL(0.7f/(4.f*0.3f)), (chaosMeasure - FL2FXCONST_DBL(0.2f)))); + chaosMeasure = (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f)>>2), fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f)>>2), chaosMeasure)))<<2; + + /* calculation of reduction value */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW){ /* short-blocks */ + FDK_ASSERT(TRANS_FAC==8); + #define WIN_TYPE_SCALE (3) + + INT sfbGrp, groupCnt=0; + for (sfbGrp=0; sfbGrpsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup,groupCnt++) { + + FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f); + + for(ch=0;chgroupLen[groupCnt]<=INV_INT_TAB_SIZE); + groupEnergy = fMult(groupEnergy,invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of group energy */ + groupEnergy = fixMin(groupEnergy, frameEnergy>>WIN_TYPE_SCALE); /* do not allow an higher redVal as calculated framewise */ + + groupEnergy>>=2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */ + + redVal[groupCnt] = fMult(fMult(vbrQualFactor,chaosMeasure), + CalcInvLdData(CalcLdData(groupEnergy)>>2) ) + << (int)( ( 2 + (2*WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY )>>2 ) ; + + } + } else { /* long-block */ + + redVal[0] = fMult( fMult(vbrQualFactor,chaosMeasure), + CalcInvLdData(CalcLdData(frameEnergy)>>2) ) + << (int)( SCALE_GROUP_ENERGY>>2 ) ; + } + + for(ch=0; chsfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++){ + + sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb]); + sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp+sfb]); + sfbThrExp = thrExp[ch][sfbGrp+sfb]; + + if ( (sfbThrLdData>=MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) && (ahFlag[ch][sfbGrp+sfb] != AH_ACTIVE)) { + + /* Short-Window */ + if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) { + const int groupNumber = (int) sfb/psyOutChan->sfbPerGroup; + + FDK_ASSERT(INV_SQRT4_TAB_SIZE>psyOutChan->groupLen[groupNumber]); + + sfbThrExp = fMult(sfbThrExp, fMult( FL2FXCONST_DBL(2.82f/4.f), invSqrt4[psyOutChan->groupLen[groupNumber]]))<<2 ; + + if ( sfbThrExp <= (limitThrReducedLdData-redVal[groupNumber]) ) { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f); + } + else { + if ((FIXP_DBL)redVal[groupNumber] >= FL2FXCONST_DBL(1.0f)-sfbThrExp) + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + else { + /* threshold reduction formula */ + sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[groupNumber]); + sfbThrReducedLdData <<= 2; + } + } + sfbThrReducedLdData += ( CalcLdInt(psyOutChan->groupLen[groupNumber]) - + ((FIXP_DBL)6<<(DFRACT_BITS-1-LD_DATA_SHIFT)) ); + } + + /* Long-Window */ + else { + if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f)-sfbThrExp) { + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + } + else { + /* threshold reduction formula */ + sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]); + sfbThrReducedLdData <<= 2; + } + } + + /* avoid holes */ + if ( ((sfbThrReducedLdData - sfbEnLdData) > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] ) + && (ahFlag[ch][sfbGrp+sfb] != NO_AH) ) + { + if (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] > (FL2FXCONST_DBL(-1.0f) - sfbEnLdData) ){ + sfbThrReducedLdData = fixMax((qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData), sfbThrLdData); + } + else sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE; + } + + if (sfbThrReducedLdData FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)){ + sfbThrReducedLdData = fixMax(sfbThrReducedLdData, sfbEnLdData - FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)); + } + + sfbThrReducedLdData = fixMax(MIN_LDTHRESH,sfbThrReducedLdData); + + qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/***************************************************************************** +functionname: FDKaacEnc_correctThresh +description: if pe difference deltaPe between desired pe and real pe is small enough, +the difference can be distributed among the scale factor bands. +New thresholds can be derived from this pe-difference +*****************************************************************************/ +static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(8)], + PSY_OUT_ELEMENT* psyOutElement[(8)], + UCHAR ahFlag[(8)][(2)][MAX_GROUPED_SFB], + FIXP_DBL thrExp[(8)][(2)][MAX_GROUPED_SFB], + const FIXP_DBL redVal[(8)], + const SCHAR redValScaling[(8)], + const INT deltaPe, + const INT processElements, + const INT elementOffset) +{ + INT ch, sfb, sfbGrp; + QC_OUT_CHANNEL *qcOutChan; + PSY_OUT_CHANNEL *psyOutChan; + PE_CHANNEL_DATA *peChanData; + FIXP_DBL thrFactorLdData; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL *sfbPeFactorsLdData[(8)][(2)]; + FIXP_DBL sfbNActiveLinesLdData[(8)][(2)][MAX_GROUPED_SFB]; + INT normFactorInt; + FIXP_DBL normFactorLdData; + + INT nElements = elementOffset+processElements; + INT elementId; + + /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */ + for(elementId=elementOffset;elementIdelInfo[elementId].nChannelsInEl; ch++) { + SHORT* ptr = qcElement[elementId]->qcOutChannel[ch]->quantSpec; + sfbPeFactorsLdData[elementId][ch] = (FIXP_DBL*)ptr; + } + } + + /* for each sfb calc relative factors for pe changes */ + normFactorInt = 0; + + for(elementId=elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + + qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if ( peChanData->sfbNActiveLines[sfbGrp+sfb] == 0 ) { + sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); + } + else { + /* Both CalcLdInt and CalcLdData can be used! + * No offset has to be subtracted, because sfbNActiveLinesLdData + * is shorted while thrFactor calculation */ + sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = CalcLdInt(peChanData->sfbNActiveLines[sfbGrp+sfb]); + } + if ( ((ahFlag[elementId][ch][sfbGrp+sfb] < AH_ACTIVE) || (deltaPe > 0)) && + peChanData->sfbNActiveLines[sfbGrp+sfb] != 0 ) + { + if (thrExp[elementId][ch][sfbGrp+sfb] > -redVal[elementId]) { + + /* sfbPeFactors[ch][sfbGrp+sfb] = peChanData->sfbNActiveLines[sfbGrp+sfb] / + (thrExp[elementId][ch][sfbGrp+sfb] + redVal[elementId]); */ + + int minScale = fixMin(CountLeadingBits(thrExp[elementId][ch][sfbGrp+sfb]), CountLeadingBits(redVal[elementId]) - (DFRACT_BITS-1-redValScaling[elementId]) ) - 1; + + /* sumld = ld64( sfbThrExp + redVal ) */ + FIXP_DBL sumLd = CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp+sfb], minScale) + scaleValue(redVal[elementId], (DFRACT_BITS-1-redValScaling[elementId])+minScale)) + - (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT)); + + if (sumLd < FL2FXCONST_DBL(0.f)) { + sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd; + } + else { + if ( sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) { + sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd; + } + else { + sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb]; + } + } + + normFactorInt += (INT)CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb]); + } + else sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(1.0f); + } + else sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); + } + } + } + } + } + + /* normFactorLdData = ld64(deltaPe/normFactorInt) */ + normFactorLdData = CalcLdData((FIXP_DBL)((deltaPe<0) ? (-deltaPe) : (deltaPe))) - CalcLdData((FIXP_DBL)normFactorInt); + + /* distribute the pe difference to the scalefactors + and calculate the according thresholds */ + for(elementId=elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){ + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + + if (peChanData->sfbNActiveLines[sfbGrp+sfb] > 0) { + + /* pe difference for this sfb */ + if ( (sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb]==FL2FXCONST_DBL(-1.0f)) || + (deltaPe==0) ) + { + thrFactorLdData = FL2FXCONST_DBL(0.f); + } + else { + /* new threshold */ + FIXP_DBL tmp = CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] + normFactorLdData - sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - FL2FXCONST_DBL((float)LD_DATA_SHIFT/LD_DATA_SCALING)); + + /* limit thrFactor to 60dB */ + tmp = (deltaPe<0) ? tmp : (-tmp); + thrFactorLdData = FDKmin(tmp, FL2FXCONST_DBL(20.f/LD_DATA_SCALING)); + } + + /* new threshold */ + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp+sfb]; + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb]; + + if (thrFactorLdData < FL2FXCONST_DBL(0.f)) { + if( sfbThrLdData > (FL2FXCONST_DBL(-1.f)-thrFactorLdData) ) { + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } + else { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.f); + } + } + else{ + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } + + /* avoid hole */ + if ( (sfbThrReducedLdData - sfbEnLdData > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]) && + (ahFlag[elementId][ch][sfbGrp+sfb] == AH_INACTIVE) ) + { + /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */ + if ( sfbEnLdData > (sfbThrLdData-qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]) ) { + sfbThrReducedLdData = qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData; + } + else { + sfbThrReducedLdData = sfbThrLdData; + } + ahFlag[elementId][ch][sfbGrp+sfb] = AH_ACTIVE; + } + + qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData; + } + } + } + } + } + } +} + +/***************************************************************************** + functionname: FDKaacEnc_reduceMinSnr + description: if the desired pe can not be reached, reduce pe by + reducing minSnr +*****************************************************************************/ +void FDKaacEnc_reduceMinSnr(CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(8)], + PSY_OUT_ELEMENT* psyOutElement[(8)], + UCHAR ahFlag[(8)][(2)][MAX_GROUPED_SFB], + const INT desiredPe, + INT* redPeGlobal, + const INT processElements, + const INT elementOffset) + +{ + INT elementId; + INT nElements = elementOffset+processElements; + + INT newGlobalPe = *redPeGlobal; + + for(elementId=elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + INT ch; + INT maxSfbPerGroup[2]; + INT sfbCnt[2]; + INT sfbPerGroup[2]; + + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + maxSfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup-1; + sfbCnt[ch] = psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt; + sfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup; + } + + PE_DATA *peData = &qcElement[elementId]->peData; + + do + { + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + + INT sfb, sfbGrp; + QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + INT noReduction = 1; + + if (maxSfbPerGroup[ch]>=0) { /* sfb in next channel */ + INT deltaPe = 0; + sfb = maxSfbPerGroup[ch]--; + noReduction = 0; + + for (sfbGrp = 0; sfbGrp < sfbCnt[ch]; sfbGrp += sfbPerGroup[ch]) { + + if (ahFlag[elementId][ch][sfbGrp+sfb] != NO_AH && + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] < SnrLdFac) + { + /* increase threshold to new minSnr of 1dB */ + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] = SnrLdFac; + + /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */ + if ( qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb] >= qcOutChan->sfbThresholdLdData[sfbGrp+sfb] - qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] ) { + + qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb] + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]; + + /* calc new pe */ + /* C2 + C3*ld(1/0.8) = 1.5 */ + deltaPe -= (peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT); + + /* sfbPe = 1.5 * sfbNLines */ + peData->peChannelData[ch].sfbPe[sfbGrp+sfb] = (3*peData->peChannelData[ch].sfbNLines[sfbGrp+sfb]) << (PE_CONSTPART_SHIFT-1); + deltaPe += (peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT); + } + } + + } /* sfbGrp loop */ + + peData->pe += deltaPe; + peData->peChannelData[ch].pe += deltaPe; + newGlobalPe += deltaPe; + + /* stop if enough has been saved */ + if (peData->pe <= desiredPe) { + goto bail; + } + + } /* sfb > 0 */ + + if ( (ch==(cm->elInfo[elementId].nChannelsInEl-1)) && noReduction ) { + goto bail; + } + + } /* ch loop */ + + } while ( peData->pe > desiredPe); + + } /* != ID_DSE */ + } /* element loop */ + + +bail: + /* update global PE */ + *redPeGlobal = newGlobalPe; +} + + +/***************************************************************************** + functionname: FDKaacEnc_allowMoreHoles + description: if the desired pe can not be reached, some more scalefactor + bands have to be quantized to zero +*****************************************************************************/ +static void FDKaacEnc_allowMoreHoles(CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(8)], + PSY_OUT_ELEMENT* psyOutElement[(8)], + ATS_ELEMENT* AdjThrStateElement[(8)], + UCHAR ahFlag[(8)][(2)][MAX_GROUPED_SFB], + const INT desiredPe, + const INT currentPe, + const int processElements, + const int elementOffset) +{ + INT elementId; + INT nElements = elementOffset+processElements; + INT actPe = currentPe; + + if (actPe <= desiredPe) { + return; /* nothing to do */ + } + + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT ch, sfb, sfbGrp; + + PE_DATA *peData = &qcElement[elementId]->peData; + const INT nChannels = cm->elInfo[elementId].nChannelsInEl; + + QC_OUT_CHANNEL* qcOutChannel[(2)] = {NULL}; + PSY_OUT_CHANNEL* psyOutChannel[(2)] = {NULL}; + + for (ch=0; chqcOutChannel[ch]; + psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch]; + + for(sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+= psyOutChannel[ch]->sfbPerGroup) { + for (sfb=psyOutChannel[ch]->maxSfbPerGroup; sfbsfbPerGroup; sfb++) { + peData->peChannelData[ch].sfbPe[sfbGrp+sfb] = 0; + } + } + } + + /* for MS allow hole in the channel with less energy */ + if ( nChannels==2 && psyOutChannel[0]->lastWindowSequence==psyOutChannel[1]->lastWindowSequence ) { + + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + for(sfbGrp=0; sfbGrp < psyOutChannel[0]->sfbCnt; sfbGrp+=psyOutChannel[0]->sfbPerGroup) { + if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp+sfb]) { + FIXP_DBL EnergyLd_L = qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp+sfb]; + FIXP_DBL EnergyLd_R = qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp+sfb]; + + /* allow hole in side channel ? */ + if ( (ahFlag[elementId][1][sfbGrp+sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f)>>1) + (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp+sfb]>>1)) + > ((EnergyLd_R>>1) - (EnergyLd_L>>1))) ) + { + ahFlag[elementId][1][sfbGrp+sfb] = NO_AH; + qcOutChannel[1]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + EnergyLd_R; + actPe -= peData->peChannelData[1].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT; + } + /* allow hole in mid channel ? */ + else if ( (ahFlag[elementId][0][sfbGrp+sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f)>>1) + (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp+sfb]>>1)) + > ((EnergyLd_L>>1) - (EnergyLd_R>>1))) ) + { + ahFlag[elementId][0][sfbGrp+sfb] = NO_AH; + qcOutChannel[0]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + EnergyLd_L; + actPe -= peData->peChannelData[0].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT; + } /* if (ahFlag) */ + } /* if MS */ + } /* sfbGrp */ + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfb */ + } /* MS possible ? */ + + /* more holes necessary? subsequently erase bands + starting with low energies */ + INT startSfb[2]; + FIXP_DBL avgEnLD64,minEnLD64; + INT ahCnt; + FIXP_DBL ahCntLD64; + INT enIdx; + FIXP_DBL enLD64[4]; + FIXP_DBL avgEn; + + /* do not go below startSfb */ + for (ch=0; chlastWindowSequence != SHORT_WINDOW) + startSfb[ch] = AdjThrStateElement[elementId]->ahParam.startSfbL; + else + startSfb[ch] = AdjThrStateElement[elementId]->ahParam.startSfbS; + } + + /* calc avg and min energies of bands that avoid holes */ + avgEn = FL2FXCONST_DBL(0.0f); + minEnLD64 = FL2FXCONST_DBL(0.0f); + ahCnt = 0; + + for (ch=0; chmaxSfbPerGroup; sfb++) { + if ((ahFlag[elementId][ch][sfbGrp+sfb]!=NO_AH) && + (qcOutChannel[ch]->sfbWeightedEnergyLdData[sfbGrp+sfb] > qcOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb])){ + minEnLD64 = fixMin(minEnLD64,qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]); + avgEn += qcOutChannel[ch]->sfbEnergy[sfbGrp+sfb] >> 6; + ahCnt++; + } + } + + sfbGrp += psyOutChannel[ch]->sfbPerGroup; + sfb=0; + + } while (sfbGrp < psyOutChannel[ch]->sfbCnt); + } + + if ( (avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0) ) { + avgEnLD64 = FL2FXCONST_DBL(0.0f); + } + else { + avgEnLD64 = CalcLdData(avgEn); + ahCntLD64 = CalcLdInt(ahCnt); + avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - ahCntLD64; /* compensate shift with 6 */ + } + + /* calc some energy borders between minEn and avgEn */ + /* for (enIdx=0; enIdx<4; enIdx++) */ + /* en[enIdx] = minEn * (float)FDKpow(avgEn/(minEn+FLT_MIN), (2*enIdx+1)/7.0f); */ + enLD64[0] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.14285714285f)); + enLD64[1] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.42857142857f)); + enLD64[2] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.71428571428f)); + enLD64[3] = minEnLD64 + (avgEnLD64-minEnLD64); + + for (enIdx=0; enIdx<4; enIdx++) { + INT noReduction = 1; + + INT maxSfbPerGroup[2]; + INT sfbCnt[2]; + INT sfbPerGroup[2]; + + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + maxSfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup-1; + sfbCnt[ch] = psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt; + sfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup; + } + + do { + + noReduction = 1; + + for(ch=0; chelInfo[elementId].nChannelsInEl; ch++) { + + INT sfb, sfbGrp; + + /* start with lowest energy border at highest sfb */ + if (maxSfbPerGroup[ch]>=startSfb[ch]) { /* sfb in next channel */ + sfb = maxSfbPerGroup[ch]--; + noReduction = 0; + + for (sfbGrp = 0; sfbGrp < sfbCnt[ch]; sfbGrp += sfbPerGroup[ch]) { + /* sfb energy below border ? */ + if (ahFlag[elementId][ch][sfbGrp+sfb] != NO_AH && qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb] < enLD64[enIdx]) { + /* allow hole */ + ahFlag[elementId][ch][sfbGrp+sfb] = NO_AH; + qcOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + qcOutChannel[ch]->sfbWeightedEnergyLdData[sfbGrp+sfb]; + actPe -= peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT; + } + } /* sfbGrp */ + + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfb > 0 */ + } /* ch loop */ + + } while( (noReduction == 0) && (actPe > desiredPe) ); + + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + + } /* enIdx loop */ + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + +} + +/* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE */ +static void FDKaacEnc_resetAHFlags( UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const int nChannels, + PSY_OUT_CHANNEL *psyOutChannel[(2)]) +{ + int ch, sfb, sfbGrp; + + for(ch=0; chsfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbmaxSfbPerGroup; sfb++) { + if ( ahFlag[ch][sfbGrp+sfb] == AH_ACTIVE) { + ahFlag[ch][sfbGrp+sfb] = AH_INACTIVE; + } + } + } + } +} + + +static FIXP_DBL CalcRedValPower(FIXP_DBL num, + FIXP_DBL denum, + INT* scaling ) +{ + FIXP_DBL value = FL2FXCONST_DBL(0.f); + + if (num>=FL2FXCONST_DBL(0.f)) { + value = fDivNorm( num, denum, scaling); + } + else { + value = -fDivNorm( -num, denum, scaling); + } + value = f2Pow(value, *scaling, scaling); + *scaling = DFRACT_BITS-1-*scaling; + + return value; +} + + +/***************************************************************************** +functionname: FDKaacEnc_adaptThresholdsToPe +description: two guesses for the reduction value and one final correction of the thresholds +*****************************************************************************/ +static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING* cm, + ATS_ELEMENT* AdjThrStateElement[(8)], + QC_OUT_ELEMENT* qcElement[(8)], + PSY_OUT_ELEMENT* psyOutElement[(8)], + const INT desiredPe, + const INT maxIter2ndGuess, + const INT processElements, + const INT elementOffset) +{ + FIXP_DBL redValue[(8)]; + SCHAR redValScaling[(8)]; + UCHAR pAhFlag[(8)][(2)][MAX_GROUPED_SFB]; + FIXP_DBL pThrExp[(8)][(2)][MAX_GROUPED_SFB]; + int iter; + + INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal; + constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0; + + int elementId; + + int nElements = elementOffset+processElements; + if(nElements > cm->nElements) { + nElements = cm->nElements; + } + + /* ------------------------------------------------------- */ + /* Part I: Initialize data structures and variables... */ + /* ------------------------------------------------------- */ + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp(pThrExp[elementId], qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, &AdjThrStateElement[elementId]->minSnrAdaptParam, nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], &psyOutElement[elementId]->toolsInfo, nChannels, peData, &AdjThrStateElement[elementId]->ahParam); + + /* sum up */ + constPartGlobal += peData->constPart; + noRedPeGlobal += peData->pe; + nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1); + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* ----------------------------------------------------------------------- */ + /* Part II: Calculate bit consumption of initial bit constraints setup */ + /* ----------------------------------------------------------------------- */ + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + /* + redVal = ( 2 ^ ( (constPartGlobal-desiredPe) / (invRedExp*nActiveLinesGlobal) ) + - 2 ^ ( (constPartGlobal-noRedPeGlobal) / (invRedExp*nActiveLinesGlobal) ) ) + */ + + + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* first guess of reduction value */ + int scale0=0, scale1=0; + FIXP_DBL tmp0 = CalcRedValPower( constPartGlobal-desiredPe, 4*nActiveLinesGlobal, &scale0 ); + FIXP_DBL tmp1 = CalcRedValPower( constPartGlobal-noRedPeGlobal, 4*nActiveLinesGlobal, &scale1 ); + + int scalMin = FDKmin(scale0, scale1)-1; + + redValue[elementId] = scaleValue(tmp0,(scalMin-scale0)) - scaleValue(tmp1,(scalMin-scale1)); + redValScaling[elementId] = scalMin; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], pThrExp[elementId], nChannels, redValue[elementId], redValScaling[elementId]); + + /* pe after first guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels); + + redPeGlobal += peData->pe; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* -------------------------------------------------- */ + /* Part III: Iterate until bit constraints are met */ + /* -------------------------------------------------- */ + iter = 0; + while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < maxIter2ndGuess)) { + + INT desiredPeNoAHGlobal; + INT redPeNoAHGlobal = 0; + INT constPartNoAHGlobal = 0; + INT nActiveLinesNoAHGlobal = 0; + + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT redPeNoAH, constPartNoAH, nActiveLinesNoAH; + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe for bands where avoid hole is inactive */ + FDKaacEnc_FDKaacEnc_calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, + peData, pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel, nChannels); + + redPeNoAHGlobal += redPeNoAH; + constPartNoAHGlobal += constPartNoAH; + nActiveLinesNoAHGlobal += nActiveLinesNoAH; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* Calculate new redVal ... */ + if(desiredPe < redPeGlobal) { + + /* new desired pe without bands where avoid hole is active */ + desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal); + + /* limit desiredPeNoAH to positive values, as the PE can not become negative */ + desiredPeNoAHGlobal = FDKmax(0,desiredPeNoAHGlobal); + + /* second guess (only if there are bands left where avoid hole is inactive)*/ + if (nActiveLinesNoAHGlobal > 0) { + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + /* + redVal += ( 2 ^ ( (constPartNoAHGlobal-desiredPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) ) + - 2 ^ ( (constPartNoAHGlobal-redPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) ) ) + */ + int scale0 = 0; + int scale1 = 0; + + FIXP_DBL tmp0 = CalcRedValPower( constPartNoAHGlobal-desiredPeNoAHGlobal, 4*nActiveLinesNoAHGlobal, &scale0 ); + FIXP_DBL tmp1 = CalcRedValPower( constPartNoAHGlobal-redPeNoAHGlobal, 4*nActiveLinesNoAHGlobal, &scale1 ); + + int scalMin = FDKmin(scale0, scale1)-1; + + tmp0 = scaleValue(tmp0,(scalMin-scale0)) - scaleValue(tmp1,(scalMin-scale1)); + scale0 = scalMin; + + /* old reduction value */ + tmp1 = redValue[elementId]; + scale1 = redValScaling[elementId]; + + scalMin = fixMin(scale0,scale1)-1; + + /* sum up old and new reduction value */ + redValue[elementId] = scaleValue(tmp0,(scalMin-scale0)) + scaleValue(tmp1,(scalMin-scale1)); + redValScaling[elementId] = scalMin; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } /* nActiveLinesNoAHGlobal > 0 */ + } + else { + /* desiredPe >= redPeGlobal */ + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT redVal_scale = 0; + FIXP_DBL tmp = fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &redVal_scale); + + /* redVal *= redPeGlobal/desiredPe; */ + redValue[elementId] = fMult(redValue[elementId], tmp); + redValScaling[elementId] -= redVal_scale; + + FDKaacEnc_resetAHFlags(pAhFlag[elementId], cm->elInfo[elementId].nChannelsInEl, psyOutElement[elementId]->psyOutChannel); + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + redPeGlobal = 0; + /* Calculate new redVal's PE... */ + for (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], pThrExp[elementId], nChannels, redValue[elementId], redValScaling[elementId]); + + /* pe after second guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + iter++; + } /* EOF while */ + + + /* ------------------------------------------------------- */ + /* Part IV: if still required, further reduce constraints */ + /* ------------------------------------------------------- */ + /* 1.0* 1.15* 1.20* + * desiredPe desiredPe desiredPe + * | | | + * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| | + * | | |XXXXXXXXXXX... + * | |XXXXXXXXXXX| + * --- A --- | --- B --- | --- C --- + * + * (X): redPeGlobal + * (A): FDKaacEnc_correctThresh() + * (B): FDKaacEnc_allowMoreHoles() + * (C): FDKaacEnc_reduceMinSnr() + */ + + /* correct thresholds to get closer to the desired pe */ + if ( redPeGlobal > desiredPe ) { + FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp, redValue, redValScaling, + desiredPe - redPeGlobal, processElements, elementOffset); + + /* update PE */ + redPeGlobal = 0; + for(elementId=elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe after correctThresh */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + if ( redPeGlobal > desiredPe ) { + /* reduce pe by reducing minSnr requirements */ + FDKaacEnc_reduceMinSnr(cm, qcElement, psyOutElement, pAhFlag, + (fMultI(FL2FXCONST_DBL(0.15f),desiredPe) + desiredPe), + &redPeGlobal, processElements, elementOffset); + + /* reduce pe by allowing additional spectral holes */ + FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement, pAhFlag, + desiredPe, redPeGlobal, processElements, elementOffset); + } + +} + +/* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */ +void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)], + PSY_OUT_CHANNEL* psyOutChannel[(2)], + ATS_ELEMENT* AdjThrStateElement, + struct TOOLSINFO *toolsInfo, + PE_DATA *peData, + const INT nChannels) +{ + UCHAR (*pAhFlag)[MAX_GROUPED_SFB]; + FIXP_DBL (*pThrExp)[MAX_GROUPED_SFB]; + + /* allocate scratch memory */ + C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB) + pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag; + pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel, &AdjThrStateElement->minSnrAdaptParam, nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo, + nChannels, peData, &AdjThrStateElement->ahParam); + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp, nChannels, + AdjThrStateElement->vbrQualFactor, + &AdjThrStateElement->chaosMeasureOld); + + /* free scratch memory */ + C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB) +} + + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSave + description: Calculates percentage of bit save, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit save + +*****************************************************************************/ +/* + bitsave + maxBitSave(%)| clipLow + |---\ + | \ + | \ + | \ + | \ + |--------\--------------> bitres + | \ + minBitSave(%)| \------------ + clipHigh maxBitres +*/ +static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSave, + const FIXP_DBL maxBitSave, + const FIXP_DBL bitsave_slope) +{ + FIXP_DBL bitsave; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitsave = maxBitSave - fMult((fillLevel-clipLow), bitsave_slope); + + return (bitsave); +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSpend + description: Calculates percentage of bit spend, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit spend + +*****************************************************************************/ +/* + bitspend clipHigh + maxBitSpend(%)| /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> bitres + | / + minBitSpend(%)|--/ + clipLow +*/ +static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSpend, + const FIXP_DBL maxBitSpend, + const FIXP_DBL bitspend_slope) +{ + FIXP_DBL bitspend; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitspend = minBitSpend + fMult(fillLevel-clipLow, bitspend_slope); + + return (bitspend); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_adjustPeMinMax() + description: adjusts peMin and peMax parameters over time + returns: + input: current pe, peMin, peMax, bitres size + output: adjusted peMin/peMax + +*****************************************************************************/ +static void FDKaacEnc_adjustPeMinMax(const INT currPe, + INT *peMin, + INT *peMax) +{ + FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL, minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f); + INT diff; + + INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe); + + if (currPe > *peMax) + { + diff = (currPe-*peMax) ; + *peMin += fMultI(minFacHi,diff); + *peMax += fMultI(maxFacHi,diff); + } + else if (currPe < *peMin) + { + diff = (*peMin-currPe) ; + *peMin -= fMultI(minFacLo,diff); + *peMax -= fMultI(maxFacLo,diff); + } + else + { + *peMin += fMultI(minFacHi, (currPe - *peMin)); + *peMax -= fMultI(maxFacLo, (*peMax - currPe)); + } + + if ((*peMax - *peMin) < minDiff_fix) + { + INT peMax_fix = *peMax, peMin_fix = *peMin; + FIXP_DBL partLo_fix, partHi_fix; + + partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix); + partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe); + + peMax_fix = (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix+partHi_fix)), minDiff_fix)); + peMin_fix = (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix+partHi_fix)), minDiff_fix)); + peMin_fix = fixMax(0, peMin_fix); + + *peMax = peMax_fix; + *peMin = peMin_fix; + } +} + + + +/***************************************************************************** + + functionname: BitresCalcBitFac + description: calculates factor of spending bits for one frame + 1.0 : take all frame dynpart bits + >1.0 : take all frame dynpart bits + bitres + <1.0 : put bits in bitreservoir + returns: BitFac + input: bitres-fullness, pe, blockType, parameter-settings + output: + +*****************************************************************************/ +/* + bitfac(%) pemax + bitspend(%) | /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> pe + | / + bitsave(%) |--/ + pemin +*/ + +static FIXP_DBL FDKaacEnc_bitresCalcBitFac(const INT bitresBits, + const INT maxBitresBits, + const INT pe, + const INT lastWindowSequence, + const INT avgBits, + const FIXP_DBL maxBitFac, + ADJ_THR_STATE *AdjThr, + ATS_ELEMENT *adjThrChan) +{ + BRES_PARAM *bresParam; + INT pex; + + INT qmin, qbr, qbres, qmbr; + FIXP_DBL bitSave, bitSpend; + + FIXP_DBL bitresFac_fix, tmp_cst, tmp_fix; + FIXP_DBL pe_pers, bits_ratio, maxBrVal; + FIXP_DBL bitsave_slope, bitspend_slope, maxBitFac_tmp; + FIXP_DBL fillLevel_fix = (FIXP_DBL)0x7fffffff; + FIXP_DBL UNITY = (FIXP_DBL)0x7fffffff; + FIXP_DBL POINT7 = (FIXP_DBL)0x5999999A; + + if (maxBitresBits > bitresBits) { + fillLevel_fix = fDivNorm(bitresBits, maxBitresBits); + } + + if (lastWindowSequence != SHORT_WINDOW) + { + bresParam = &(AdjThr->bresParamLong); + bitsave_slope = (FIXP_DBL)0x3BBBBBBC; + bitspend_slope = (FIXP_DBL)0x55555555; + } + else + { + bresParam = &(AdjThr->bresParamShort); + bitsave_slope = (FIXP_DBL)0x2E8BA2E9; + bitspend_slope = (FIXP_DBL)0x7fffffff; + } + + pex = fixMax(pe, adjThrChan->peMin); + pex = fixMin(pex, adjThrChan->peMax); + + bitSave = FDKaacEnc_calcBitSave(fillLevel_fix, + bresParam->clipSaveLow, bresParam->clipSaveHigh, + bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope); + + bitSpend = FDKaacEnc_calcBitSpend(fillLevel_fix, + bresParam->clipSpendLow, bresParam->clipSpendHigh, + bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope); + + pe_pers = (pex > adjThrChan->peMin) ? fDivNorm(pex - adjThrChan->peMin, adjThrChan->peMax - adjThrChan->peMin) : 0; + tmp_fix = fMult(((FIXP_DBL)bitSpend + (FIXP_DBL)bitSave), pe_pers); + bitresFac_fix = (UNITY>>1) - ((FIXP_DBL)bitSave>>1) + (tmp_fix>>1); qbres = (DFRACT_BITS-2); + + /* (float)bitresBits/(float)avgBits */ + bits_ratio = fDivNorm(bitresBits, avgBits, &qbr); + qbr = DFRACT_BITS-1-qbr; + + /* Add 0.7 in q31 to bits_ratio in qbr */ + /* 0.7f + (float)bitresBits/(float)avgBits */ + qmin = fixMin(qbr, (DFRACT_BITS-1)); + bits_ratio = bits_ratio >> (qbr - qmin); + tmp_cst = POINT7 >> ((DFRACT_BITS-1) - qmin); + maxBrVal = (bits_ratio>>1) + (tmp_cst>>1); qmbr = qmin - 1; + + /* bitresFac_fix = fixMin(bitresFac_fix, 0.7 + bitresBits/avgBits); */ + bitresFac_fix = bitresFac_fix >> (qbres - qmbr); qbres = qmbr; + bitresFac_fix = fixMin(bitresFac_fix, maxBrVal); + + /* Compare with maxBitFac */ + qmin = fixMin(Q_BITFAC, qbres); + bitresFac_fix = bitresFac_fix >> (qbres - qmin); + maxBitFac_tmp = maxBitFac >> (Q_BITFAC - qmin); + if(maxBitFac_tmp < bitresFac_fix) + { + bitresFac_fix = maxBitFac; + } + else + { + if(qmin < Q_BITFAC) + { + bitresFac_fix = bitresFac_fix << (Q_BITFAC-qmin); + } + else + { + bitresFac_fix = bitresFac_fix >> (qmin-Q_BITFAC); + } + } + + FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); + + return bitresFac_fix; +} + + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrNew +description: allocate ADJ_THR_STATE +*****************************************************************************/ +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr, + INT nElements) +{ + INT err = 0; + INT i; + ADJ_THR_STATE* hAdjThr = GetRam_aacEnc_AdjustThreshold(); + if (hAdjThr==NULL) { + err = 1; + goto bail; + } + + for (i=0; iadjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i); + if (hAdjThr->adjThrStateElem[i]==NULL) { + err = 1; + goto bail; + } + } + +bail: + *phAdjThr = hAdjThr; + return err; +} + + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrInit +description: initialize ADJ_THR_STATE +*****************************************************************************/ +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *hAdjThr, + const INT meanPe, + ELEMENT_BITS *elBits[(8)], + INT invQuant, + INT nElements, + INT nChannelsEff, + INT sampleRate, + INT advancedBitsToPe, + FIXP_DBL vbrQualFactor, + const INT dZoneQuantEnable + ) +{ + INT i; + + FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); + FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); + + /* Max number of iterations in second guess is 3 for lowdelay aot and for configurations with + multiple audio elements in general, otherwise iteration value is always 1. */ + hAdjThr->maxIter2ndGuess = (advancedBitsToPe!=0 || nElements>1) ? 3 : 1; + + /* common for all elements: */ + /* parameters for bitres control */ + hAdjThr->bresParamLong.clipSaveLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSaveHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSave = (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamLong.maxBitSave = (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */ + hAdjThr->bresParamLong.clipSpendLow = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSpendHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSpend = (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */ + hAdjThr->bresParamLong.maxBitSpend = (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */ + + hAdjThr->bresParamShort.clipSaveLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSaveHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSave = (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */ + hAdjThr->bresParamShort.maxBitSave = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendLow = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSpend = (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamShort.maxBitSpend = (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */ + + /* specific for each element: */ + for (i=0; iadjThrStateElem[i]; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + INT chBitrate = elBits[i]->chBitrateEl; + + /* parameters for bitres control */ + atsElem->peMin = fMultI(POINT8, meanPe) >> 1; + atsElem->peMax = fMultI(POINT6, meanPe); + + /* for use in FDKaacEnc_reduceThresholdsVBR */ + atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f); + + /* additional pe offset to correct pe2bits for low bitrates */ + atsElem->peOffset = 0; + + /* vbr initialisation */ + atsElem->vbrQualFactor = vbrQualFactor; + if (chBitrate < 32000) + { + atsElem->peOffset = fixMax(50, 100-fMultI((FIXP_DBL)0x666667, chBitrate)); + } + + /* avoid hole parameters */ + if (chBitrate > 20000) { + atsElem->ahParam.modifyMinSnr = TRUE; + atsElem->ahParam.startSfbL = 15; + atsElem->ahParam.startSfbS = 3; + } + else { + atsElem->ahParam.modifyMinSnr = FALSE; + atsElem->ahParam.startSfbL = 0; + atsElem->ahParam.startSfbS = 0; + } + + /* minSnr adaptation */ + msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */ + /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ + msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */ + /* maximum minSnr reduction to minSnr^maxRed is reached for + avgEn/sfbEn >= maxRatio */ + /* msaParam->maxRatio = 1000.0f; */ + /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/ + msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */ + /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/ + msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */ + + /* init pe correction */ + atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */ + atsElem->peCorrectionFactor_e = 1; + + atsElem->dynBitsLast = -1; + atsElem->peLast = 0; + + /* init bits to pe factor */ + + /* init bits2PeFactor */ + FDKaacEnc_InitBits2PeFactor( + &atsElem->bits2PeFactor_m, + &atsElem->bits2PeFactor_e, + chBitrate*nChannelsEff, /* overall bitrate */ + nChannelsEff, /* number of channels */ + sampleRate, + advancedBitsToPe, + dZoneQuantEnable, + invQuant + ); + + } /* for nElements */ + +} + + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection + description: calc desired pe +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_calcPeCorrection( + FIXP_DBL *const correctionFac_m, + INT *const correctionFac_e, + const INT peAct, + const INT peLast, + const INT bitsLast, + const FIXP_DBL bits2PeFactor_m, + const INT bits2PeFactor_e + ) +{ + if ( (bitsLast > 0) && (peAct < 1.5f*peLast) && (peAct > 0.7f*peLast) && + (FDKaacEnc_bits2pe2(bitsLast, fMult(FL2FXCONST_DBL(1.2f/2.f), bits2PeFactor_m), bits2PeFactor_e+1) > peLast) && + (FDKaacEnc_bits2pe2(bitsLast, fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m), bits2PeFactor_e ) < peLast) ) + { + FIXP_DBL corrFac = *correctionFac_m; + + int scaling = 0; + FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e); + FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling); + + /* dead zone, newFac and corrFac are scaled by 0.5 */ + if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */ + newFac = fixMax(scaleValue(fixMin( fMult(FL2FXCONST_DBL(1.1f/2.f), newFac), scaleValue(FL2FXCONST_DBL( 1.f/2.f), -scaling)), scaling), FL2FXCONST_DBL(0.85f/2.f) ); + } + else { /* ratio < 1.f */ + newFac = fixMax( fixMin( scaleValue(fMult(FL2FXCONST_DBL(0.9f/2.f), newFac), scaling), FL2FXCONST_DBL(1.15f/2.f) ), FL2FXCONST_DBL( 1.f/2.f) ); + } + + if ( ((newFac > FL2FXCONST_DBL(1.f/2.f)) && (corrFac < FL2FXCONST_DBL(1.f/2.f))) + || ((newFac < FL2FXCONST_DBL(1.f/2.f)) && (corrFac > FL2FXCONST_DBL(1.f/2.f)))) + { + corrFac = FL2FXCONST_DBL(1.f/2.f); + } + + /* faster adaptation towards 1.0, slower in the other direction */ + if ( (corrFac < FL2FXCONST_DBL(1.f/2.f) && newFac < corrFac) + || (corrFac > FL2FXCONST_DBL(1.f/2.f) && newFac > corrFac) ) + { + corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) + fMult(FL2FXCONST_DBL(0.15f), newFac); + } + else { + corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) + fMult(FL2FXCONST_DBL(0.3f), newFac); + } + + corrFac = fixMax( fixMin( corrFac, FL2FXCONST_DBL(1.15f/2.f) ), FL2FXCONST_DBL(0.85/2.f) ); + + *correctionFac_m = corrFac; + *correctionFac_e = 1; + } + else { + *correctionFac_m = FL2FXCONST_DBL(1.f/2.f); + *correctionFac_e = 1; + } +} + + +static void FDKaacEnc_calcPeCorrectionLowBitRes( + FIXP_DBL *const correctionFac_m, + INT *const correctionFac_e, + const INT peLast, + const INT bitsLast, + const INT bitresLevel, + const INT nChannels, + const FIXP_DBL bits2PeFactor_m, + const INT bits2PeFactor_e + ) +{ + /* tuning params */ + const FIXP_DBL amp = FL2FXCONST_DBL(0.005); + const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f); + + if (bitsLast > 0) { + + /* Estimate deviation of granted and used dynamic bits in previous frame, in PE units */ + const int bitsBalLast = peLast - FDKaacEnc_bits2pe2( + bitsLast, + bits2PeFactor_m, + bits2PeFactor_e); + + /* reserve n bits per channel */ + int headroom = (bitresLevel>=50*nChannels) ? 0 : (100*nChannels); + + /* in PE units */ + headroom = FDKaacEnc_bits2pe2( + headroom, + bits2PeFactor_m, + bits2PeFactor_e); + + /* + * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom) + * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2 + */ + FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(bitresLevel, bits2PeFactor_m, bits2PeFactor_e) + (FIXP_DBL)headroom; + + int scaling = 0; + FIXP_DBL diff = (bitsBalLast>=headroom) + ? fMult(amp, fDivNorm( (FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling)) + : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling)) ; + + scaling -= 1; /* divide by 2 */ + + diff = (scaling<=0) ? FDKmax( FDKmin (diff>>(-scaling), maxDiff>>1), -maxDiff>>1) + : FDKmax( FDKmin (diff, maxDiff>>(1+scaling)), -maxDiff>>(1+scaling)) << scaling; + + /* + * corrFac += diff + * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) ) + */ + *correctionFac_m = FDKmax(FDKmin((*correctionFac_m)+diff, FL2FXCONST_DBL(1.0f/2.f)), FL2FXCONST_DBL(0.75f/2.f)) ; + *correctionFac_e = 1; + } + else { + *correctionFac_m = FL2FXCONST_DBL(0.75/2.f); + *correctionFac_e = 1; + } +} + +void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, + ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], + PE_DATA *peData, + INT *grantedPe, + INT *grantedPeCorr, + const INT nChannels, + const INT commonWindow, + const INT grantedDynBits, + const INT bitresBits, + const INT maxBitresBits, + const FIXP_DBL maxBitFac, + const INT bitDistributionMode) +{ + FIXP_DBL bitFactor; + INT noRedPe = peData->pe; + + /* prefer short windows for calculation of bitFactor */ + INT curWindowSequence = LONG_WINDOW; + if (nChannels==2) { + if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) || + (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) { + curWindowSequence = SHORT_WINDOW; + } + } + else { + curWindowSequence = psyOutChannel[0]->lastWindowSequence; + } + + if (grantedDynBits >= 1) { + if (bitDistributionMode!=0) { + *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->bits2PeFactor_e); + } + else + { + /* factor dependend on current fill level and pe */ + bitFactor = FDKaacEnc_bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe, + curWindowSequence, grantedDynBits, maxBitFac, + adjThrState, + AdjThrStateElement + ); + + /* desired pe for actual frame */ + /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */ + *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, + fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m), AdjThrStateElement->bits2PeFactor_e+(DFRACT_BITS-1-Q_BITFAC) + ); + } + } + else { + *grantedPe = 0; /* prevent divsion by 0 */ + } + + /* correction of pe value */ + switch (bitDistributionMode) { + case 2: + case 1: + FDKaacEnc_calcPeCorrectionLowBitRes( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, + AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, + bitresBits, + nChannels, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e + ); + break; + case 0: + default: + FDKaacEnc_FDKaacEnc_calcPeCorrection( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, + fixMin(*grantedPe, noRedPe), + AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e + ); + break; + } + + *grantedPeCorr = (INT)(fMult((FIXP_DBL)(*grantedPe<peCorrectionFactor_m) >> (Q_AVGBITS-AdjThrStateElement->peCorrectionFactor_e)); + + /* update last pe */ + AdjThrStateElement->peLast = *grantedPe; + AdjThrStateElement->dynBitsLast = -1; + +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjustThresholds +description: adjust thresholds +*****************************************************************************/ +void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)], + QC_OUT_ELEMENT* qcElement[(8)], + QC_OUT* qcOut, + PSY_OUT_ELEMENT* psyOutElement[(8)], + INT CBRbitrateMode, + INT maxIter2ndGuess, + CHANNEL_MAPPING* cm) +{ + int i; + if (CBRbitrateMode) + { + /* In case, no bits must be shifted between different elements, */ + /* an element-wise execution of the pe-dependent threshold- */ + /* adaption becomes necessary... */ + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging */ + //if (totalGrantedPeCorr < totalNoRedPe) { + if (qcElement[i]->grantedPe < qcElement[i]->peData.pe) + { + /* calc threshold necessary for desired pe */ + FDKaacEnc_adaptThresholdsToPe(cm, + AdjThrStateElement, + qcElement, + psyOutElement, + qcElement[i]->grantedPeCorr, + maxIter2ndGuess, + 1, /* Process only 1 element */ + i); /* Process exactly THIS element */ + + } + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + } + else { + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* for VBR-mode */ + FDKaacEnc_AdaptThresholdsVBR(qcElement[i]->qcOutChannel, + psyOutElement[i]->psyOutChannel, + AdjThrStateElement[i], + &psyOutElement[i]->toolsInfo, + &qcElement[i]->peData, + cm->elInfo[i].nChannelsInEl); + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + } + for (i=0; inElements; i++) { + int ch,sfb,sfbGrp; + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + for (ch=0; chelInfo[i].nChannelsInEl; ch++) { + QC_OUT_CHANNEL* pQcOutCh = qcElement[i]->qcOutChannel[ch]; + for (sfbGrp = 0;sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) { + for (sfb=0; sfbpsyOutChannel[ch]->maxSfbPerGroup; sfb++) { + pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp]; + } + } + } + } +} + +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** phAdjThr) +{ + INT i; + ADJ_THR_STATE* hAdjThr = *phAdjThr; + + if (hAdjThr!=NULL) { + for (i=0; i<(8); i++) { + if (hAdjThr->adjThrStateElem[i]!=NULL) { + FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]); + } + } + FreeRam_aacEnc_AdjustThreshold(phAdjThr); + } +} + diff --git a/libAACenc/src/adj_thr.h b/libAACenc/src/adj_thr.h new file mode 100644 index 00000000..be68c6eb --- /dev/null +++ b/libAACenc/src/adj_thr.h @@ -0,0 +1,149 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Threshold compensation + +******************************************************************************/ + +#ifndef __ADJ_THR_H +#define __ADJ_THR_H + + +#include "adj_thr_data.h" +#include "qc_data.h" +#include "line_pe.h" +#include "interface.h" + + +void FDKaacEnc_peCalculation( + PE_DATA *peData, + PSY_OUT_CHANNEL* psyOutChannel[(2)], + QC_OUT_CHANNEL* qcOutChannel[(2)], + struct TOOLSINFO *toolsInfo, + ATS_ELEMENT* adjThrStateElement, + const INT nChannels + ); + +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr, + INT nElements); + +void FDKaacEnc_AdjThrInit(ADJ_THR_STATE *hAdjThr, + const INT peMean, + ELEMENT_BITS* elBits[(8)], + INT invQuant, + INT nElements, + INT nChannelsEff, + INT sampleRate, + INT advancedBitsToPe, + FIXP_DBL vbrQualFactor, + const INT dZoneQuantEnable); + + +void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState, + ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], + PE_DATA *peData, + INT *grantedPe, + INT *grantedPeCorr, + const INT nChannels, + const INT commonWindow, + const INT avgBits, + const INT bitresBits, + const INT maxBitresBits, + const FIXP_DBL maxBitFac, + const INT bitDistributionMode); + +void FDKaacEnc_AdjustThresholds(ATS_ELEMENT* AdjThrStateElement[(8)], + QC_OUT_ELEMENT* qcElement[(8)], + QC_OUT* qcOut, + PSY_OUT_ELEMENT* psyOutElement[(8)], + INT CBRbitrateMode, + INT maxIter2ndGuess, + CHANNEL_MAPPING* cm); + +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** hAdjThr); + +#endif diff --git a/libAACenc/src/adj_thr_data.h b/libAACenc/src/adj_thr_data.h new file mode 100644 index 00000000..7c3a1914 --- /dev/null +++ b/libAACenc/src/adj_thr_data.h @@ -0,0 +1,151 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: M. Schug / A. Groeschel + contents/description: threshold calculations + +******************************************************************************/ + +#ifndef __ADJ_THR_DATA_H +#define __ADJ_THR_DATA_H + + +#include "psy_const.h" + +typedef struct { + FIXP_DBL clipSaveLow, clipSaveHigh; + FIXP_DBL minBitSave, maxBitSave; + FIXP_DBL clipSpendLow, clipSpendHigh; + FIXP_DBL minBitSpend, maxBitSpend; +} BRES_PARAM; + +typedef struct { + INT modifyMinSnr; + INT startSfbL, startSfbS; +} AH_PARAM; + +typedef struct { + FIXP_DBL maxRed; + FIXP_DBL startRatio; + FIXP_DBL maxRatio; + FIXP_DBL redRatioFac; + FIXP_DBL redOffs; +} MINSNR_ADAPT_PARAM; + +typedef struct { + /* parameters for bitreservoir control */ + INT peMin, peMax; + /* constant offset to pe */ + INT peOffset; + /* constant PeFactor */ + FIXP_DBL bits2PeFactor_m; + INT bits2PeFactor_e; + /* avoid hole parameters */ + AH_PARAM ahParam; + /* values for correction of pe */ + /* paramters for adaptation of minSnr */ + MINSNR_ADAPT_PARAM minSnrAdaptParam; + INT peLast; + INT dynBitsLast; + FIXP_DBL peCorrectionFactor_m; + INT peCorrectionFactor_e; + + /* vbr encoding */ + FIXP_DBL vbrQualFactor; + FIXP_DBL chaosMeasureOld; + + /* threshold weighting */ + FIXP_DBL chaosMeasureEnFac[(2)]; + INT lastEnFacPatch[(2)]; + +} ATS_ELEMENT; + +typedef struct { + BRES_PARAM bresParamLong, bresParamShort; + ATS_ELEMENT* adjThrStateElem[(8)]; + INT maxIter2ndGuess; +} ADJ_THR_STATE; + +#endif diff --git a/libAACenc/src/band_nrg.cpp b/libAACenc/src/band_nrg.cpp new file mode 100644 index 00000000..861f7a8e --- /dev/null +++ b/libAACenc/src/band_nrg.cpp @@ -0,0 +1,359 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Initial author: M. Werner + contents/description: Band/Line energy calculations + +******************************************************************************/ + +#include "band_nrg.h" + + +/***************************************************************************** + functionname: FDKaacEnc_CalcSfbMaxScaleSpec + description: + input: + output: +*****************************************************************************/ +void +FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *RESTRICT mdctSpectrum, + const INT *RESTRICT bandOffset, + INT *RESTRICT sfbMaxScaleSpec, + const INT numBands) +{ + INT i,j; + FIXP_DBL maxSpc, tmp; + + for(i=0; i 0 */ + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CheckBandEnergyOptim + description: + input: + output: +*****************************************************************************/ +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData, + INT minSpecShift) +{ + INT i, j, scale, nr = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(-1.0f); + FIXP_DBL maxNrg = 0; + FIXP_DBL spec; + + for(i=0; i maxNrgLd) { + maxNrgLd = bandEnergyLdData[i]; + nr = i; + } + } + + /* return unscaled maxNrg*/ + scale = fixMax(0,sfbMaxScaleSpec[nr]-4); + scale = fixMax(2*(minSpecShift-scale),-(DFRACT_BITS-1)); + + maxNrg = scaleValue(bandEnergy[nr], scale); + + return maxNrg; +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimLong + description: + input: + output: +*****************************************************************************/ +INT +FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData) +{ + INT i, j, shiftBits = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(0.0f); + + FIXP_DBL spec; + + for(i=0; i 7/2 = 4 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + /* don't use scaleValue() here, it increases workload quite sufficiently... */ + if (leadingBits>=0) { + for (j=bandOffset[i];j>shift; + tmp = fPow2AddDiv2(tmp, spec); + } + } + bandEnergy[i] = tmp<<1; + } + + /* calculate ld of bandNrg, subtract scaling */ + LdDataVector(bandEnergy, bandEnergyLdData, numBands); + for(i=numBands; i--!=0; ) { + FIXP_DBL scaleDiff = (sfbMaxScaleSpec[i]-4)*FL2FXCONST_DBL(2.0/64); + + bandEnergyLdData[i] = (bandEnergyLdData[i] >= ((FL2FXCONST_DBL(-1.f)>>1) + (scaleDiff>>1))) + ? bandEnergyLdData[i]-scaleDiff : FL2FXCONST_DBL(-1.f); + /* find maxNrgLd */ + maxNrgLd = fixMax(maxNrgLd, bandEnergyLdData[i]); + } + + if (maxNrgLd<=(FIXP_DBL)0) + { + for(i=numBands; i--!=0; ) + { + INT scale = fixMin((sfbMaxScaleSpec[i]-4)<<1,(DFRACT_BITS-1)); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return 0; + } + else + { /* scale down NRGs */ + while (maxNrgLd>FL2FXCONST_DBL(0.0f)) + { + maxNrgLd -= FL2FXCONST_DBL(2.0/64); + shiftBits++; + } + for(i=numBands; i--!=0; ) + { + INT scale = fixMin( ((sfbMaxScaleSpec[i]-4)+shiftBits)<<1, (DFRACT_BITS-1)); + bandEnergyLdData[i] -= shiftBits*FL2FXCONST_DBL(2.0/64); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return shiftBits; + } +} + + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimShort + description: + input: + output: +*****************************************************************************/ +void +FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy) +{ + INT i, j; + + for(i=0; i 6/2 = 3 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + for (j=bandOffset[i];j 6/2 = 3 (spc*spc) */ + scale = fixMax(fixMin(scale,(DFRACT_BITS-1)),-(DFRACT_BITS-1)); + bandEnergy[i] = scaleValueSaturate(bandEnergy[i], -scale); + } +} + + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandNrgMSOpt + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcBandNrgMSOpt(const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, + INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, + FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, + FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData) +{ + INT i, j, minScale; + FIXP_DBL NrgMid, NrgSide, specm, specs; + + for (i=0; i 0) { + for (j=bandOffset[i];j>1; + FIXP_DBL specR = mdctSpectrumRight[j]>>1; + specm = specL + specR; + specs = specL - specR; + NrgMid = fPow2AddDiv2(NrgMid, specm); + NrgSide = fPow2AddDiv2(NrgSide, specs); + } + } + bandEnergyMid[i] = NrgMid<<1; + bandEnergySide[i] = NrgSide<<1; + } + + if(calcLdData) { + LdDataVector(bandEnergyMid, bandEnergyMidLdData, numBands); + LdDataVector(bandEnergySide, bandEnergySideLdData, numBands); + } + + for (i=0; i>= scale; + bandEnergySide[i] >>= scale; + } +} diff --git a/libAACenc/src/band_nrg.h b/libAACenc/src/band_nrg.h new file mode 100644 index 00000000..540a8ef7 --- /dev/null +++ b/libAACenc/src/band_nrg.h @@ -0,0 +1,149 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Author(s): M. Werner + Description: Band/Line energy calculation + +******************************************************************************/ + +#ifndef _BAND_NRG_H +#define _BAND_NRG_H + +#include "common_fix.h" + + +void +FDKaacEnc_CalcSfbMaxScaleSpec( + const FIXP_DBL *mdctSpectrum, + const INT *bandOffset, + INT *sfbMaxScaleSpec, + const INT numBands + ); + +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim( + const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, + const INT numBands, + FIXP_DBL *bandEnergy, + FIXP_DBL *bandEnergyLdData, + INT minSpecShift + ); + +INT +FDKaacEnc_CalcBandEnergyOptimLong( + const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, + const INT numBands, + FIXP_DBL *bandEnergy, + FIXP_DBL *bandEnergyLdData + ); + +void +FDKaacEnc_CalcBandEnergyOptimShort( + const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, + const INT numBands, + FIXP_DBL *bandEnergy + ); + + +void FDKaacEnc_CalcBandNrgMSOpt( + const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, + INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, + FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, + FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData); + +#endif diff --git a/libAACenc/src/bandwidth.cpp b/libAACenc/src/bandwidth.cpp new file mode 100644 index 00000000..af2a2cfe --- /dev/null +++ b/libAACenc/src/bandwidth.cpp @@ -0,0 +1,381 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: M. Schug / A. Groeschel + contents/description: bandwidth expert + +******************************************************************************/ + +#include "channel_map.h" +#include "bandwidth.h" +#include "aacEnc_ram.h" + +typedef struct{ + INT chanBitRate; + INT bandWidthMono; + INT bandWidth2AndMoreChan; + +} BANDWIDTH_TAB; + +static const BANDWIDTH_TAB bandWidthTable[] = { + {0, 3700, 5000}, + {12000, 5000, 6400}, + {20000, 6900, 9640}, + {28000, 9600, 13050}, + {40000, 12060, 14260}, + {56000, 13950, 15500}, + {72000, 14200, 16120}, + {96000, 17000, 17000}, + {576001,17000, 17000} +}; + + +static const BANDWIDTH_TAB bandWidthTable_LD_22050[] = { + { 8000, 2000, 2400}, + {12000, 2500, 2700}, + {16000, 3300, 3100}, + {24000, 6250, 7200}, + {32000, 9200, 10500}, + {40000, 16000, 16000}, + {48000, 16000, 16000}, + {360001, 16000, 16000} +}; + +static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = { + { 8000, 2000, 2000}, + {12000, 2000, 2300}, + {16000, 2200, 2500}, + {24000, 5650, 7200}, + {32000, 11600, 12000}, + {40000, 12000, 16000}, + {48000, 16000, 16000}, + {64000, 16000, 16000}, + {360001, 16000, 16000} +}; + +static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = { + { 8000, 2000, 2000}, + {12000, 2000, 2000}, + {24000, 4250, 7200}, + {32000, 8400, 9000}, + {40000, 9400, 11300}, + {48000, 11900, 14700}, + {64000, 14800, 16000}, + {76000, 16000, 16000}, + {360001, 16000, 16000} +}; + +static const BANDWIDTH_TAB bandWidthTable_LD_44100[] = { + { 8000, 2000, 2000}, + {24000, 2000, 2000}, + {32000, 4400, 5700}, + {40000, 7400, 8800}, + {48000, 9000, 10700}, + {56000, 11000, 12900}, + {64000, 14400, 15500}, + {80000, 16000, 16200}, + {96000, 16500, 16000}, + {128000, 16000, 16000}, + {360001, 16000, 16000} +}; + +static const BANDWIDTH_TAB bandWidthTable_LD_48000[] = { + { 8000, 2000, 2000}, + {24000, 2000, 2000}, + {32000, 4400, 5700}, + {40000, 7400, 8800}, + {48000, 9000, 10700}, + {56000, 11000, 12800}, + {64000, 14300, 15400}, + {80000, 16000, 16200}, + {96000, 16500, 16000}, + {128000, 16000, 16000}, + {360001, 16000, 16000} +}; + +typedef struct{ + AACENC_BITRATE_MODE bitrateMode; + int bandWidthMono; + int bandWidth2AndMoreChan; +} BANDWIDTH_TAB_VBR; + +static const BANDWIDTH_TAB_VBR bandWidthTableVBR[]= { + {AACENC_BR_MODE_CBR, 0, 0}, + {AACENC_BR_MODE_VBR_1, 13050, 13050}, + {AACENC_BR_MODE_VBR_2, 13050, 13050}, + {AACENC_BR_MODE_VBR_3, 14260, 14260}, + {AACENC_BR_MODE_VBR_4, 15500, 15500}, + {AACENC_BR_MODE_VBR_5, 48000, 48000}, + {AACENC_BR_MODE_SFR, 0, 0}, + {AACENC_BR_MODE_FF, 0, 0} + +}; + +static INT GetBandwidthEntry( + const INT frameLength, + const INT sampleRate, + const INT chanBitRate, + const INT entryNo) +{ + INT bandwidth = -1; + const BANDWIDTH_TAB *pBwTab = NULL; + INT bwTabSize = 0; + + switch (frameLength) { + case 960: + case 1024: + pBwTab = bandWidthTable; + bwTabSize = sizeof(bandWidthTable)/sizeof(BANDWIDTH_TAB); + break; + case 480: + case 512: + switch (sampleRate) { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + pBwTab = bandWidthTable_LD_22050; + bwTabSize = sizeof(bandWidthTable_LD_22050)/sizeof(BANDWIDTH_TAB); + break; + case 24000: + pBwTab = bandWidthTable_LD_24000; + bwTabSize = sizeof(bandWidthTable_LD_24000)/sizeof(BANDWIDTH_TAB); + break; + case 32000: + pBwTab = bandWidthTable_LD_32000; + bwTabSize = sizeof(bandWidthTable_LD_32000)/sizeof(BANDWIDTH_TAB); + break; + case (44100): + pBwTab = bandWidthTable_LD_44100; + bwTabSize = sizeof(bandWidthTable_LD_44100)/sizeof(BANDWIDTH_TAB); + break; + case 48000: + case 64000: + case 88200: + case 96000: + pBwTab = bandWidthTable_LD_48000; + bwTabSize = sizeof(bandWidthTable_LD_48000)/sizeof(BANDWIDTH_TAB); + break; + } + break; + default: + pBwTab = NULL; + bwTabSize = 0; + } + + if (pBwTab!=NULL) { + int i; + for (i=0; i= pBwTab[i].chanBitRate && + chanBitRate < pBwTab[i+1].chanBitRate) + { + switch (frameLength) { + case 960: + case 1024: + bandwidth = (entryNo==0) + ? pBwTab[i].bandWidthMono + : pBwTab[i].bandWidth2AndMoreChan; + break; + case 480: + case 512: + { + INT q_res = 0; + INT startBw = (entryNo==0) ? pBwTab[i ].bandWidthMono : pBwTab[i ].bandWidth2AndMoreChan; + INT endBw = (entryNo==0) ? pBwTab[i+1].bandWidthMono : pBwTab[i+1].bandWidth2AndMoreChan; + INT startBr = pBwTab[i].chanBitRate; + INT endBr = pBwTab[i+1].chanBitRate; + + FIXP_DBL bwFac_fix = fDivNorm(chanBitRate-startBr, endBr-startBr, &q_res); + bandwidth = (INT)scaleValue(fMult(bwFac_fix, (FIXP_DBL)(endBw-startBw)),q_res) + startBw; + } + break; + default: + bandwidth = -1; + } + break; + } /* within bitrate range */ + } + } /* pBwTab!=NULL */ + + return bandwidth; +} + + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth(INT* bandWidth, + INT proposedBandWidth, + INT bitrate, + AACENC_BITRATE_MODE bitrateMode, + INT sampleRate, + INT frameLength, + CHANNEL_MAPPING* cm, + CHANNEL_MODE encoderMode) +{ + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT chanBitRate = bitrate/cm->nChannels; + + /* vbr */ + switch(bitrateMode){ + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + if (proposedBandWidth != 0){ + /* use given bw */ + *bandWidth = proposedBandWidth; + } else { + /* take bw from table */ + switch(encoderMode){ + case MODE_1: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidthMono; + break; + case MODE_2: + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidth2AndMoreChan; + break; + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + } + break; + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + + /* bandwidth limiting */ + if (proposedBandWidth != 0) { + *bandWidth = FDKmin(proposedBandWidth, FDKmin(20000, sampleRate>>1)); + } + else { /* search reasonable bandwidth */ + + int entryNo = 0; + + switch(encoderMode){ + case MODE_1: /* mono */ + entryNo = 0; /* use mono bandwith settings */ + break; + + case MODE_2: /* stereo */ + case MODE_1_2: /* sce + cpe */ + case MODE_1_2_1: /* sce + cpe + sce */ + case MODE_1_2_2: /* sce + cpe + cpe */ + case MODE_1_2_2_1: /* (5.1) sce + cpe + cpe + lfe */ + case MODE_1_2_2_2_1: /* (7.1) sce + cpe + cpe + cpe + lfe */ + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + entryNo = 1; /* use stereo bandwith settings */ + break; + + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + *bandWidth = GetBandwidthEntry( + frameLength, + sampleRate, + chanBitRate, + entryNo); + + if (*bandWidth==-1) { + ErrorStatus = AAC_ENC_INVALID_CHANNEL_BITRATE; + } + } + break; + default: + *bandWidth = 0; + return AAC_ENC_UNSUPPORTED_BITRATE_MODE; + } + + *bandWidth = FDKmin(*bandWidth, sampleRate/2); + + return ErrorStatus;; +} diff --git a/libAACenc/src/bandwidth.h b/libAACenc/src/bandwidth.h new file mode 100644 index 00000000..2e92453a --- /dev/null +++ b/libAACenc/src/bandwidth.h @@ -0,0 +1,106 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: M. Schug / A. Groeschel + contents/description: bandwidth expert + +******************************************************************************/ + +#ifndef _BANDWIDTH_H +#define _BANDWIDTH_H + + +#include "qc_data.h" + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth(INT* bandWidth, + INT proposedBandwidth, + INT bitrate, + AACENC_BITRATE_MODE bitrateMode, + INT sampleRate, + INT frameLength, + CHANNEL_MAPPING* cm, + CHANNEL_MODE encoderMode); + +#endif /* BANDWIDTH_H */ diff --git a/libAACenc/src/bit_cnt.cpp b/libAACenc/src/bit_cnt.cpp new file mode 100644 index 00000000..926ee493 --- /dev/null +++ b/libAACenc/src/bit_cnt.cpp @@ -0,0 +1,1122 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Huffman Bitcounter & coder + +******************************************************************************/ + +#include "bit_cnt.h" + +#include "aacEnc_ram.h" + +#define HI_LTAB(a) (a>>16) +#define LO_LTAB(a) (a & 0xffff) + +/***************************************************************************** + + + functionname: FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11 + description: counts tables 1-11 + returns: + input: quantized spectrum + output: bitCount for tables 1-11 + +*****************************************************************************/ + +static void FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc1_2,bc3_4,bc5_6,bc7_8,bc9_10,bc11,sc; + INT t0,t1,t2,t3; + bc1_2=0; + bc3_4=0; + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0)+(t1>0)+(t2>0)+(t3>0); + } + + bitCount[1]=HI_LTAB(bc1_2); + bitCount[2]=LO_LTAB(bc1_2); + bitCount[3]=HI_LTAB(bc3_4)+sc; + bitCount[4]=LO_LTAB(bc3_4)+sc; + bitCount[5]=HI_LTAB(bc5_6); + bitCount[6]=LO_LTAB(bc5_6); + bitCount[7]=HI_LTAB(bc7_8)+sc; + bitCount[8]=LO_LTAB(bc7_8)+sc; + bitCount[9]=HI_LTAB(bc9_10)+sc; + bitCount[10]=LO_LTAB(bc9_10)+sc; + bitCount[11]=bc11+sc; + +} + + +/***************************************************************************** + + functionname: FDKaacEnc_count3_4_5_6_7_8_9_10_11 + description: counts tables 3-11 + returns: + input: quantized spectrum + output: bitCount for tables 3-11 + +*****************************************************************************/ + +static void FDKaacEnc_count3_4_5_6_7_8_9_10_11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc3_4,bc5_6,bc7_8,bc9_10,bc11,sc; + INT t0,t1,t2,t3; + + bc3_4=0; + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0)+(t1>0)+(t2>0)+(t3>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=HI_LTAB(bc3_4)+sc; + bitCount[4]=LO_LTAB(bc3_4)+sc; + bitCount[5]=HI_LTAB(bc5_6); + bitCount[6]=LO_LTAB(bc5_6); + bitCount[7]=HI_LTAB(bc7_8)+sc; + bitCount[8]=LO_LTAB(bc7_8)+sc; + bitCount[9]=HI_LTAB(bc9_10)+sc; + bitCount[10]=LO_LTAB(bc9_10)+sc; + bitCount[11]=bc11+sc; +} + + + +/***************************************************************************** + + functionname: FDKaacEnc_count5_6_7_8_9_10_11 + description: counts tables 5-11 + returns: + input: quantized spectrum + output: bitCount for tables 5-11 + +*****************************************************************************/ + + +static void FDKaacEnc_count5_6_7_8_9_10_11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc5_6,bc7_8,bc9_10,bc11,sc; + INT t0,t1; + bc5_6=0; + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0)+(t1>0); + } + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=HI_LTAB(bc5_6); + bitCount[6]=LO_LTAB(bc5_6); + bitCount[7]=HI_LTAB(bc7_8)+sc; + bitCount[8]=LO_LTAB(bc7_8)+sc; + bitCount[9]=HI_LTAB(bc9_10)+sc; + bitCount[10]=LO_LTAB(bc9_10)+sc; + bitCount[11]=bc11+sc; + +} + + +/***************************************************************************** + + functionname: FDKaacEnc_count7_8_9_10_11 + description: counts tables 7-11 + returns: + input: quantized spectrum + output: bitCount for tables 7-11 + +*****************************************************************************/ + +static void FDKaacEnc_count7_8_9_10_11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc7_8,bc9_10,bc11,sc; + INT t0,t1; + + bc7_8=0; + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0)+(t1>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=HI_LTAB(bc7_8)+sc; + bitCount[8]=LO_LTAB(bc7_8)+sc; + bitCount[9]=HI_LTAB(bc9_10)+sc; + bitCount[10]=LO_LTAB(bc9_10)+sc; + bitCount[11]=bc11+sc; + +} + +/***************************************************************************** + + functionname: FDKaacEnc_count9_10_11 + description: counts tables 9-11 + returns: + input: quantized spectrum + output: bitCount for tables 9-11 + +*****************************************************************************/ + + + +static void FDKaacEnc_count9_10_11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc9_10,bc11,sc; + INT t0,t1; + + bc9_10=0; + bc11=0; + sc=0; + + for(i=0;i0)+(t1>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=INVALID_BITCOUNT; + bitCount[8]=INVALID_BITCOUNT; + bitCount[9]=HI_LTAB(bc9_10)+sc; + bitCount[10]=LO_LTAB(bc9_10)+sc; + bitCount[11]=bc11+sc; + +} + +/***************************************************************************** + + functionname: FDKaacEnc_count11 + description: counts table 11 + returns: + input: quantized spectrum + output: bitCount for table 11 + +*****************************************************************************/ + +static void FDKaacEnc_count11(const SHORT *RESTRICT values, + const INT width, + INT *bitCount) +{ + + INT i; + INT bc11,sc; + INT t0,t1; + + bc11=0; + sc=0; + for(i=0;i0)+(t1>0); + } + + bitCount[1]=INVALID_BITCOUNT; + bitCount[2]=INVALID_BITCOUNT; + bitCount[3]=INVALID_BITCOUNT; + bitCount[4]=INVALID_BITCOUNT; + bitCount[5]=INVALID_BITCOUNT; + bitCount[6]=INVALID_BITCOUNT; + bitCount[7]=INVALID_BITCOUNT; + bitCount[8]=INVALID_BITCOUNT; + bitCount[9]=INVALID_BITCOUNT; + bitCount[10]=INVALID_BITCOUNT; + bitCount[11]=bc11+sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_countEsc + description: counts table 11 (with Esc) + returns: + input: quantized spectrum + output: bitCount for tables 11 (with Esc) + +*****************************************************************************/ + +static void FDKaacEnc_countEsc(const SHORT *RESTRICT values, + const INT width, + INT *RESTRICT bitCount) +{ + + INT i; + INT bc11,ec,sc; + INT t0,t1,t00,t01; + + bc11=0; + sc=0; + ec=0; + for(i=0;i0)+(t1>0); + + t00 = fixMin(t0,16); + t01 = fixMin(t1,16); + bc11+= (INT) FDKaacEnc_huff_ltab11[t00][t01]; + + if(t0>=16){ + ec+=5; + while((t0>>=1) >= 16) + ec+=2; + } + + if(t1>=16){ + ec+=5; + while((t1>>=1) >= 16) + ec+=2; + } + } + + for (i=0; i<11; i++) + bitCount[i]=INVALID_BITCOUNT; + + bitCount[11]=bc11+sc+ec; +} + + +typedef void (*COUNT_FUNCTION)(const SHORT *RESTRICT values, + const INT width, + INT *RESTRICT bitCount); + +static const COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV+1] = +{ + + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 0 */ + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 1 */ + FDKaacEnc_count3_4_5_6_7_8_9_10_11, /* 2 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 3 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 4 */ + FDKaacEnc_count7_8_9_10_11, /* 5 */ + FDKaacEnc_count7_8_9_10_11, /* 6 */ + FDKaacEnc_count7_8_9_10_11, /* 7 */ + FDKaacEnc_count9_10_11, /* 8 */ + FDKaacEnc_count9_10_11, /* 9 */ + FDKaacEnc_count9_10_11, /* 10 */ + FDKaacEnc_count9_10_11, /* 11 */ + FDKaacEnc_count9_10_11, /* 12 */ + FDKaacEnc_count11, /* 13 */ + FDKaacEnc_count11, /* 14 */ + FDKaacEnc_count11, /* 15 */ + FDKaacEnc_countEsc /* 16 */ +}; + + + +INT FDKaacEnc_bitCount(const SHORT *values, + const INT width, + INT maxVal, + INT *bitCount) +{ + + /* + check if we can use codebook 0 + */ + + if(maxVal == 0) + bitCount[0] = 0; + else + bitCount[0] = INVALID_BITCOUNT; + + maxVal = fixMin(maxVal,(INT)CODE_BOOK_ESC_LAV); + countFuncTable[maxVal](values,width,bitCount); + return(0); +} + + + + +/* + count difference between actual and zeroed lines +*/ +INT FDKaacEnc_countValues(SHORT *RESTRICT values, INT width, INT codeBook) +{ + + INT i,t0,t1,t2,t3,t00,t01; + INT codeLength; + INT signLength; + INT bitCnt=0; + + switch(codeBook){ + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for(i=0; i=16){ + INT n,p; + n=0; + p=t0; + while((p>>=1) >=16){ + bitCnt++; + n++; + } + bitCnt+=(n+5); + } + if(t1 >=16){ + INT n,p; + n=0; + p=t1; + while((p>>=1) >=16){ + bitCnt++; + n++; + } + bitCnt+=(n+5); + } + } + break; + + default: + break; + } + + return(bitCnt); +} + + + +INT FDKaacEnc_codeValues(SHORT *RESTRICT values, INT width, INT codeBook, HANDLE_FDK_BITSTREAM hBitstream) +{ + + INT i,t0,t1,t2,t3,t00,t01; + INT codeWord,codeLength; + INT sign,signLength; + + switch(codeBook){ + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for(i=0; i=16){ + INT n,p; + n=0; + p=t0; + while((p>>=1) >=16){ + FDKwriteBits(hBitstream,1,1); + n++; + } + FDKwriteBits(hBitstream,0,1); + FDKwriteBits(hBitstream,t0-(1<<(n+4)),n+4); + } + if(t1 >=16){ + INT n,p; + n=0; + p=t1; + while((p>>=1) >=16){ + FDKwriteBits(hBitstream,1,1); + n++; + } + FDKwriteBits(hBitstream,0,1); + FDKwriteBits(hBitstream,t1-(1<<(n+4)),n+4); + } + } + break; + + default: + break; + } + return(0); +} + +INT FDKaacEnc_codeScalefactorDelta(INT delta, HANDLE_FDK_BITSTREAM hBitstream) +{ + INT codeWord,codeLength; + + if(fixp_abs(delta) >CODE_BOOK_SCF_LAV) + return(1); + + codeWord = FDKaacEnc_huff_ctabscf[delta+CODE_BOOK_SCF_LAV]; + codeLength = (INT)FDKaacEnc_huff_ltabscf[delta+CODE_BOOK_SCF_LAV]; + FDKwriteBits(hBitstream,codeWord,codeLength); + return(0); +} + + + diff --git a/libAACenc/src/bit_cnt.h b/libAACenc/src/bit_cnt.h new file mode 100644 index 00000000..7c4b59e4 --- /dev/null +++ b/libAACenc/src/bit_cnt.h @@ -0,0 +1,187 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Huffman Bitcounter & coder + +******************************************************************************/ + +#ifndef __BITCOUNT_H +#define __BITCOUNT_H + + +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "aacEnc_rom.h" + +#define INVALID_BITCOUNT (FDK_INT_MAX/4) + +/* + code book number table +*/ + +enum codeBookNo{ + CODE_BOOK_ZERO_NO= 0, + CODE_BOOK_1_NO= 1, + CODE_BOOK_2_NO= 2, + CODE_BOOK_3_NO= 3, + CODE_BOOK_4_NO= 4, + CODE_BOOK_5_NO= 5, + CODE_BOOK_6_NO= 6, + CODE_BOOK_7_NO= 7, + CODE_BOOK_8_NO= 8, + CODE_BOOK_9_NO= 9, + CODE_BOOK_10_NO= 10, + CODE_BOOK_ESC_NO= 11, + CODE_BOOK_RES_NO= 12, + CODE_BOOK_PNS_NO= 13, + CODE_BOOK_IS_OUT_OF_PHASE_NO= 14, + CODE_BOOK_IS_IN_PHASE_NO= 15 + +}; + +/* + code book index table +*/ + +enum codeBookNdx{ + CODE_BOOK_ZERO_NDX, + CODE_BOOK_1_NDX, + CODE_BOOK_2_NDX, + CODE_BOOK_3_NDX, + CODE_BOOK_4_NDX, + CODE_BOOK_5_NDX, + CODE_BOOK_6_NDX, + CODE_BOOK_7_NDX, + CODE_BOOK_8_NDX, + CODE_BOOK_9_NDX, + CODE_BOOK_10_NDX, + CODE_BOOK_ESC_NDX, + CODE_BOOK_RES_NDX, + CODE_BOOK_PNS_NDX, + CODE_BOOK_IS_OUT_OF_PHASE_NDX, + CODE_BOOK_IS_IN_PHASE_NDX, + NUMBER_OF_CODE_BOOKS +}; + +/* + code book lav table +*/ + +enum codeBookLav{ + CODE_BOOK_ZERO_LAV=0, + CODE_BOOK_1_LAV=1, + CODE_BOOK_2_LAV=1, + CODE_BOOK_3_LAV=2, + CODE_BOOK_4_LAV=2, + CODE_BOOK_5_LAV=4, + CODE_BOOK_6_LAV=4, + CODE_BOOK_7_LAV=7, + CODE_BOOK_8_LAV=7, + CODE_BOOK_9_LAV=12, + CODE_BOOK_10_LAV=12, + CODE_BOOK_ESC_LAV=16, + CODE_BOOK_SCF_LAV=60, + CODE_BOOK_PNS_LAV=60 + }; + +INT FDKaacEnc_bitCount(const SHORT *aQuantSpectrum, + const INT noOfSpecLines, + INT maxVal, + INT *bitCountLut); + +INT FDKaacEnc_countValues(SHORT *values, INT width, INT codeBook); + +INT FDKaacEnc_codeValues(SHORT *values, INT width, INT codeBook, HANDLE_FDK_BITSTREAM hBitstream); + +INT FDKaacEnc_codeScalefactorDelta(INT scalefactor, HANDLE_FDK_BITSTREAM hBitstream); + +inline INT FDKaacEnc_bitCountScalefactorDelta(const INT delta) +{ + FDK_ASSERT( (0 <= (delta+CODE_BOOK_SCF_LAV)) && ((delta+CODE_BOOK_SCF_LAV)<(int)(sizeof(FDKaacEnc_huff_ltabscf)/sizeof((FDKaacEnc_huff_ltabscf[0])))) ); + return((INT)FDKaacEnc_huff_ltabscf[delta+CODE_BOOK_SCF_LAV]); +} + +#endif diff --git a/libAACenc/src/bitenc.cpp b/libAACenc/src/bitenc.cpp new file mode 100644 index 00000000..45524579 --- /dev/null +++ b/libAACenc/src/bitenc.cpp @@ -0,0 +1,1508 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + + /******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Bitstream encoder + +******************************************************************************/ +#include +#include "bitenc.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "qc_data.h" +#include "interface.h" +#include "aacEnc_ram.h" + + +#include "tpenc_lib.h" + +#include "FDK_tools_rom.h" /* needed for the bitstream syntax tables */ + +static const int globalGainOffset = 100; +static const int icsReservedBit = 0; +static const int noiseOffset = 90; + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSpectralData + description: encode spectral data + returns: the number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSpectralData(INT *sfbOffset, + SECTION_DATA *sectionData, + SHORT *quantSpectrum, + HANDLE_FDK_BITSTREAM hBitStream) +{ + INT i,sfb; + INT dbgVal = FDKgetValidBits(hBitStream); + + for(i=0;inoOfSections;i++) + { + if(sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO) + { + /* huffencode spectral data for this huffsection */ + INT tmp = sectionData->huffsection[i].sfbStart+sectionData->huffsection[i].sfbCnt; + for(sfb=sectionData->huffsection[i].sfbStart; sfbhuffsection[i].codeBook, + hBitStream); + } + } + } + return(FDKgetValidBits(hBitStream)-dbgVal); +} + +/***************************************************************************** + + functionname:FDKaacEnc_encodeGlobalGain + description: encodes Global Gain (common scale factor) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGlobalGain(INT globalGain, + INT scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT mdctScale) +{ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream,globalGain - scalefac + globalGainOffset-4*(LOG_NORM_PCM-mdctScale),8); + } + return (8); +} + + +/***************************************************************************** + + functionname:FDKaacEnc_encodeIcsInfo + description: encodes Ics Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ + +static INT FDKaacEnc_encodeIcsInfo(INT blockType, + INT windowShape, + INT groupingMask, + INT maxSfbPerGroup, + HANDLE_FDK_BITSTREAM hBitStream, + UINT syntaxFlags) +{ + INT statBits; + + if (blockType == SHORT_WINDOW) { + statBits = 8 + TRANS_FAC - 1; + } else { + if (syntaxFlags & AC_ELD) { + statBits = 6; + } else + { + statBits = (!(syntaxFlags & AC_SCALABLE)) ? 11 : 10; + } + } + + if (hBitStream != NULL) { + + if (!(syntaxFlags & AC_ELD)){ + FDKwriteBits(hBitStream,icsReservedBit,1); + FDKwriteBits(hBitStream,blockType,2); + FDKwriteBits(hBitStream, (windowShape == LOL_WINDOW) ? KBD_WINDOW : windowShape,1); + } + + switch(blockType){ + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + FDKwriteBits(hBitStream,maxSfbPerGroup,6); + + if (!(syntaxFlags & (AC_SCALABLE|AC_ELD)) ) { /* If not scalable syntax then ... */ + /* No predictor data present */ + FDKwriteBits(hBitStream, 0, 1); + } + break; + + case SHORT_WINDOW: + FDKwriteBits(hBitStream,maxSfbPerGroup,4); + + /* Write grouping bits */ + FDKwriteBits(hBitStream,groupingMask,TRANS_FAC-1); + break; + } + } + + return (statBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSectionData + description: encode section data (common Huffman codebooks for adjacent + SFB's) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSectionData(SECTION_DATA *sectionData, + HANDLE_FDK_BITSTREAM hBitStream, + UINT useVCB11) +{ + if (hBitStream != NULL) { + INT sectEscapeVal=0,sectLenBits=0; + INT sectLen; + INT i; + INT dbgVal=FDKgetValidBits(hBitStream); + INT sectCbBits = 4; + + switch(sectionData->blockType) + { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sectEscapeVal = SECT_ESC_VAL_LONG; + sectLenBits = SECT_BITS_LONG; + break; + + case SHORT_WINDOW: + sectEscapeVal = SECT_ESC_VAL_SHORT; + sectLenBits = SECT_BITS_SHORT; + break; + } + + for(i=0;inoOfSections;i++) + { + INT codeBook = sectionData->huffsection[i].codeBook; + + FDKwriteBits(hBitStream,codeBook,sectCbBits); + + { + sectLen = sectionData->huffsection[i].sfbCnt; + + while(sectLen >= sectEscapeVal) + { + FDKwriteBits(hBitStream,sectEscapeVal,sectLenBits); + sectLen-=sectEscapeVal; + } + FDKwriteBits(hBitStream,sectLen,sectLenBits); + } + } + return(FDKgetValidBits(hBitStream)-dbgVal); + } + return (0); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeScaleFactorData + description: encode DPCM coded scale factors + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeScaleFactorData(UINT *maxValueInSfb, + SECTION_DATA *sectionData, + INT *scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT *RESTRICT noiseNrg, + const INT *isScale, + INT globalGain) +{ + if (hBitStream != NULL) { + INT i,j,lastValScf,deltaScf; + INT deltaPns; + INT lastValPns = 0; + INT noisePCMFlag = TRUE; + INT lastValIs; + + INT dbgVal = FDKgetValidBits(hBitStream); + + lastValScf=scalefac[sectionData->firstScf]; + lastValPns = globalGain-scalefac[sectionData->firstScf]+globalGainOffset-4*LOG_NORM_PCM-noiseOffset; + lastValIs = 0; + + for(i=0; inoOfSections; i++){ + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { + + if ((sectionData->huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) + { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for(j=sfbStart; jhuffsection[i].codeBook == CODE_BOOK_PNS_NO) { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for(j=sfbStart; jhuffsection[i].sfbStart+sectionData->huffsection[i].sfbCnt; + for(j=sectionData->huffsection[i].sfbStart; jhuffsection[i].codeBook != CODE_BOOK_ZERO_NO */ + } /* section loop */ + + return(FDKgetValidBits(hBitStream)-dbgVal); + } /* if (hBitStream != NULL) */ + + return (0); +} + +/***************************************************************************** + + functionname:encodeMsInfo + description: encodes MS-Stereo Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeMSInfo(INT sfbCnt, + INT grpSfb, + INT maxSfb, + INT msDigest, + INT *jsFlags, + HANDLE_FDK_BITSTREAM hBitStream) +{ + INT sfb, sfbOff, msBits = 0; + + if (hBitStream != NULL) + { + switch(msDigest) + { + case MS_NONE: + FDKwriteBits(hBitStream,SI_MS_MASK_NONE,2); + msBits += 2; + break; + + case MS_ALL: + FDKwriteBits(hBitStream,SI_MS_MASK_ALL,2); + msBits += 2; + break; + + case MS_SOME: + FDKwriteBits(hBitStream,SI_MS_MASK_SOME,2); + msBits += 2; + for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) + { + for(sfb=0; sfbnumOfFilters[i]!=0) { + tnsPresent=1; + break; + } + } + + if (tnsPresent==0) { + FDKwriteBits(hBitStream,0,1); + } else { + FDKwriteBits(hBitStream,1,1); + } + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeTnsData + description: encode TNS data (filter order, coeffs, ..) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeTnsData(TNS_INFO *tnsInfo, + INT blockType, + HANDLE_FDK_BITSTREAM hBitStream) +{ + INT tnsBits = 0; + + if (tnsInfo!=NULL) { + + INT i,j,k; + INT tnsPresent = 0; + INT coefBits; + INT numOfWindows=(blockType==SHORT_WINDOW?TRANS_FAC:1); + + for (i=0; inumOfFilters[i]!=0) { + tnsPresent=1; + } + } + + if (hBitStream != NULL) + { + if (tnsPresent==1) { /* there is data to be written*/ + for (i=0; inumOfFilters[i],(blockType==SHORT_WINDOW?1:2)); + tnsBits += (blockType==SHORT_WINDOW?1:2); + if (tnsInfo->numOfFilters[i]) { + FDKwriteBits(hBitStream,(tnsInfo->coefRes[i]==4?1:0),1); + tnsBits += 1; + } + for (j=0; jnumOfFilters[i]; j++) { + FDKwriteBits(hBitStream,tnsInfo->length[i][j],(blockType==SHORT_WINDOW?4:6)); + tnsBits += (blockType==SHORT_WINDOW?4:6); + FDK_ASSERT(tnsInfo->order[i][j] <= 12); + FDKwriteBits(hBitStream,tnsInfo->order[i][j],(blockType==SHORT_WINDOW?3:5)); + tnsBits += (blockType==SHORT_WINDOW?3:5); + if (tnsInfo->order[i][j]){ + FDKwriteBits(hBitStream,tnsInfo->direction[i][j],1); + tnsBits +=1; /*direction*/ + if(tnsInfo->coefRes[i] == 4) { + coefBits = 3; + for(k=0; korder[i][j]; k++) { + if (tnsInfo->coef[i][j][k]> 3 || + tnsInfo->coef[i][j][k]< -4) { + coefBits = 4; + break; + } + } + } else { + coefBits = 2; + for(k=0; korder[i][j]; k++) { + if ( tnsInfo->coef[i][j][k]> 1 + || tnsInfo->coef[i][j][k]< -2) { + coefBits = 3; + break; + } + } + } + FDKwriteBits(hBitStream,-(coefBits - tnsInfo->coefRes[i]),1); /*coef_compres*/ + tnsBits +=1; /*coef_compression */ + for (k=0; korder[i][j]; k++ ) { + static const INT rmask[] = {0,1,3,7,15}; + FDKwriteBits(hBitStream,tnsInfo->coef[i][j][k] & rmask[coefBits],coefBits); + tnsBits += coefBits; + } + } + } + } + } + } + else { + if (tnsPresent != 0) { + for (i=0; inumOfFilters[i]) { + tnsBits += 1; + for (j=0; jnumOfFilters[i]; j++) { + tnsBits += (blockType==SHORT_WINDOW?4:6); + tnsBits += (blockType==SHORT_WINDOW?3:5); + if (tnsInfo->order[i][j]) { + tnsBits +=1; /*direction*/ + tnsBits +=1; /*coef_compression */ + if (tnsInfo->coefRes[i] == 4) { + coefBits=3; + for (k=0; korder[i][j]; k++) { + if (tnsInfo->coef[i][j][k]> 3 || tnsInfo->coef[i][j][k]< -4) { + coefBits = 4; + break; + } + } + } + else { + coefBits = 2; + for (k=0; korder[i][j]; k++) { + if (tnsInfo->coef[i][j][k]> 1 || tnsInfo->coef[i][j][k]< -2) { + coefBits = 3; + break; + } + } + } + for (k=0; korder[i][j]; k++) { + tnsBits += coefBits; + } + } + } + } + } + } + } + } /* (tnsInfo!=NULL) */ + + return (tnsBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeGainControlData + description: unsupported + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGainControlData(HANDLE_FDK_BITSTREAM hBitStream) +{ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream,0,1); + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodePulseData + description: not supported yet (dummy) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodePulseData(HANDLE_FDK_BITSTREAM hBitStream) +{ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream,0,1); + } + return (1); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_writeExtensionPayload + description: write extension payload to bitstream + returns: number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_writeExtensionPayload( HANDLE_FDK_BITSTREAM hBitStream, + EXT_PAYLOAD_TYPE extPayloadType, + const UCHAR *extPayloadData, + INT extPayloadBits + ) +{ + #define EXT_TYPE_BITS ( 4 ) + #define DATA_EL_VERSION_BITS ( 4 ) + #define FILL_NIBBLE_BITS ( 4 ) + + INT extBitsUsed = 0; + //fprintf(stderr, "FDKaacEnc_writeExtensionPayload() extPayloadType=%d\n", extPayloadType); + if (extPayloadBits >= EXT_TYPE_BITS) + { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + case EXT_DYNAMIC_RANGE: + /* case EXT_SAC_DATA: */ + case EXT_SBR_DATA: + case EXT_SBR_DATA_CRC: + if (hBitStream != NULL) { + int i, writeBits = extPayloadBits; + for (i=0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, extPayloadData[i]>>(8-writeBits), writeBits); + } + } + extBitsUsed += extPayloadBits; + break; + + case EXT_DATA_ELEMENT: + { + INT dataElementLength = (extPayloadBits+7)>>3; + INT cnt = dataElementLength; + int loopCounter = 1; + + while (dataElementLength >= 255) { + loopCounter++; + dataElementLength -= 255; + } + + if (hBitStream != NULL) { + int i; + FDKwriteBits(hBitStream, 0x00, DATA_EL_VERSION_BITS); /* data_element_version = ANC_DATA */ + + for (i=1; i= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_writeDataStreamElement + description: write data stream elements like ancillary data ... + returns: the amount of used bits + input: + output: + +******************************************************************************/ +static INT FDKaacEnc_writeDataStreamElement( HANDLE_TRANSPORTENC hTpEnc, + INT elementInstanceTag, + INT dataPayloadBytes, + UCHAR *dataBuffer, + UINT alignAnchor ) +{ + #define DATA_BYTE_ALIGN_FLAG ( 0 ) + + #define EL_INSTANCE_TAG_BITS ( 4 ) + #define DATA_BYTE_ALIGN_FLAG_BITS ( 1 ) + #define DATA_LEN_COUNT_BITS ( 8 ) + #define DATA_LEN_ESC_COUNT_BITS ( 8 ) + + #define MAX_DATA_ALIGN_BITS ( 7 ) + #define MAX_DSE_DATA_BYTES ( 510 ) + + INT dseBitsUsed = 0; + //fprintf(stderr, "FDKaacEnc_writeDataStreamElement() dataPayloadBytes=%d\n", dataPayloadBytes); + while (dataPayloadBytes > 0) + { + int esc_count = -1; + int cnt = 0; + INT crcReg = -1; + + dseBitsUsed += EL_ID_BITS + EL_INSTANCE_TAG_BITS + + DATA_BYTE_ALIGN_FLAG_BITS + DATA_LEN_COUNT_BITS; + + if (DATA_BYTE_ALIGN_FLAG) { + dseBitsUsed += MAX_DATA_ALIGN_BITS; + } + + cnt = fixMin(MAX_DSE_DATA_BYTES, dataPayloadBytes); + if ( cnt >= 255 ) { + esc_count = cnt - 255; + dseBitsUsed += DATA_LEN_ESC_COUNT_BITS; + } + + dataPayloadBytes -= cnt; + dseBitsUsed += cnt * 8; + + if (hTpEnc != NULL) { + HANDLE_FDK_BITSTREAM hBitStream = transportEnc_GetBitstream(hTpEnc); + int i; + + FDKwriteBits(hBitStream, ID_DSE, EL_ID_BITS); + + crcReg = transportEnc_CrcStartReg(hTpEnc, 0); + + FDKwriteBits(hBitStream, elementInstanceTag, EL_INSTANCE_TAG_BITS); + FDKwriteBits(hBitStream, DATA_BYTE_ALIGN_FLAG, DATA_BYTE_ALIGN_FLAG_BITS); + + /* write length field(s) */ + if ( esc_count >= 0 ) { + FDKwriteBits(hBitStream, 255, DATA_LEN_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, DATA_LEN_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, DATA_LEN_COUNT_BITS); + } + + if (DATA_BYTE_ALIGN_FLAG) { + INT tmp = (INT)FDKgetValidBits(hBitStream); + FDKbyteAlign(hBitStream, alignAnchor); + /* count actual bits */ + dseBitsUsed += (INT)FDKgetValidBits(hBitStream) - tmp - MAX_DATA_ALIGN_BITS; + } + + /* write payload */ + for (i=0; inPayloadBits; + INT extBitsUsed = 0; + + if (hTpEnc != NULL) { + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + //fprintf(stderr, "FDKaacEnc_writeExtensionData() pExtension->type=%d\n", pExtension->type); + if (syntaxFlags & (AC_SCALABLE|AC_ER)) + { + if ( syntaxFlags & AC_DRM ) + { /* CAUTION: The caller has to assure that fill + data is written before the SBR payload. */ + UCHAR *extPayloadData = pExtension->pPayload; + + switch (pExtension->type) + { + case EXT_SBR_DATA: + case EXT_SBR_DATA_CRC: + /* SBR payload is written in reverse */ + if (hBitStream != NULL) { + int i, writeBits = payloadBits; + + FDKpushFor(hBitStream, payloadBits-1); /* Does a cache sync internally */ + + for (i=0; writeBits >= 8; i++) { + FDKwriteBitsBwd(hBitStream, extPayloadData[i], 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBitsBwd(hBitStream, extPayloadData[i]>>(8-writeBits), writeBits); + } + + FDKsyncCacheBwd (hBitStream); + FDKpushFor (hBitStream, payloadBits+1); + } + extBitsUsed += payloadBits; + break; + + case EXT_FILL_DATA: + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = payloadBits; + while (writeBits >= 8) { + FDKwriteBits(hBitStream, 0x00, 8); + writeBits -= 8; + } + FDKwriteBits(hBitStream, 0x00, writeBits); + } + extBitsUsed += payloadBits; + break; + } + } + else { + if ( (syntaxFlags & AC_ELD) && ((pExtension->type==EXT_SBR_DATA) || (pExtension->type==EXT_SBR_DATA_CRC)) ) { + + if (hBitStream != NULL) { + int i, writeBits = payloadBits; + UCHAR *extPayloadData = pExtension->pPayload; + + for (i=0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, extPayloadData[i]>>(8-writeBits), writeBits); + } + } + extBitsUsed += payloadBits; + } + else + { + /* ER or scalable syntax -> write extension en bloc */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( hBitStream, + pExtension->type, + pExtension->pPayload, + payloadBits ); + } + } + } + else { + /* We have normal GA bitstream payload (AOT 2,5,29) so pack + the data into a fill elements or DSEs */ + + if ( pExtension->type == EXT_DATA_ELEMENT ) + { + extBitsUsed += FDKaacEnc_writeDataStreamElement( hTpEnc, + elInstanceTag, + pExtension->nPayloadBits>>3, + pExtension->pPayload, + alignAnchor ); + } + else { + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count=-1, alignBits=7; + + if ( (pExtension->type == EXT_FILL_DATA) || (pExtension->type == EXT_FIL) ) + { + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15*8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + } + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits+alignBits)>>3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + ((esc_count>=0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt*8, payloadBits); /* convert back to bits */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( hBitStream, + pExtension->type, + pExtension->pPayload, + cnt ); + payloadBits -= cnt; + } + } + } + + return (extBitsUsed); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_ByteAlignment + description: + returns: + input: + output: + +*****************************************************************************/ +static void FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream, int alignBits) +{ + FDKwriteBits(hBitStream, 0, alignBits); +} + +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( HANDLE_TRANSPORTENC hTpEnc, + ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], + UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, + INT *pBitDemand, + UCHAR minCnt + ) +{ + AAC_ENCODER_ERROR error = AAC_ENC_OK; + HANDLE_FDK_BITSTREAM hBitStream = NULL; + INT bitDemand = 0; + const element_list_t *list; + int i, ch, decision_bit; + INT crcReg1 = -1, crcReg2 = -1; + UCHAR numberOfChannels; + + if (hTpEnc != NULL) { + /* Get bitstream handle */ + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + if ( (pElInfo->elType==ID_SCE) || (pElInfo->elType==ID_LFE) ) { + numberOfChannels = 1; + } else { + numberOfChannels = 2; + } + + /* Get channel element sequence table */ + list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0); + if (list == NULL) { + error = AAC_ENC_UNSUPPORTED_AOT; + goto bail; + } + + if (!(syntaxFlags & (AC_SCALABLE|AC_ER))) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->elType, EL_ID_BITS); + } + bitDemand += EL_ID_BITS; + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + /* some tmp values */ + SECTION_DATA *pChSectionData = NULL; + INT *pChScf = NULL; + UINT *pChMaxValueInSfb = NULL; + TNS_INFO *pTnsInfo = NULL; + INT chGlobalGain = 0; + INT chBlockType = 0; + INT chMaxSfbPerGrp = 0; + INT chSfbPerGrp = 0; + INT chSfbCnt = 0; + INT chFirstScf = 0; + + if (minCnt==0) { + if ( qcOutChannel!=NULL ) { + pChSectionData = &(qcOutChannel[ch]->sectionData); + pChScf = qcOutChannel[ch]->scf; + chGlobalGain = qcOutChannel[ch]->globalGain; + pChMaxValueInSfb = qcOutChannel[ch]->maxValueInSfb; + chBlockType = pChSectionData->blockType; + chMaxSfbPerGrp = pChSectionData->maxSfbPerGroup; + chSfbPerGrp = pChSectionData->sfbPerGroup; + chSfbCnt = pChSectionData->sfbCnt; + chFirstScf = pChScf[pChSectionData->firstScf]; + } + else { + /* get values from PSY */ + chSfbCnt = psyOutChannel[ch]->sfbCnt; + chSfbPerGrp = psyOutChannel[ch]->sfbPerGroup; + chMaxSfbPerGrp = psyOutChannel[ch]->maxSfbPerGroup; + } + pTnsInfo = &psyOutChannel[ch]->tnsInfo; + } /* minCnt==0 */ + + if ( qcOutChannel==NULL ) { + chBlockType = psyOutChannel[ch]->lastWindowSequence; + } + + switch (list->id[i]) + { + case element_instance_tag: + /* Write element instance tag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->instanceTag, 4); + } + bitDemand += 4; + break; + + case common_window: + /* Write common window flag */ + decision_bit = psyOutElement->commonWindow; + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, psyOutElement->commonWindow, 1); + } + bitDemand += 1; + break; + + case ics_info: + /* Write individual channel info */ + bitDemand += FDKaacEnc_encodeIcsInfo( chBlockType, + psyOutChannel[ch]->windowShape, + psyOutChannel[ch]->groupingMask, + chMaxSfbPerGrp, + hBitStream, + syntaxFlags); + break; + + case ltp_data_present: + /* Write LTP data present flag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + bitDemand += 1; + break; + + case ltp_data: + /* Predictor data not supported. + Nothing to do here. */ + break; + + case ms: + /* Write MS info */ + bitDemand += FDKaacEnc_encodeMSInfo( chSfbCnt, + chSfbPerGrp, + chMaxSfbPerGrp, + (minCnt==0) ? psyOutElement->toolsInfo.msDigest : MS_NONE, + psyOutElement->toolsInfo.msMask, + hBitStream); + break; + + case global_gain: + bitDemand += FDKaacEnc_encodeGlobalGain( chGlobalGain, + chFirstScf, + hBitStream, + psyOutChannel[ch]->mdctScale ); + break; + + case section_data: + { + INT siBits = FDKaacEnc_encodeSectionData(pChSectionData, hBitStream, (syntaxFlags & AC_ER_VCB11)?1:0); + if (hBitStream != NULL) { + if (siBits != qcOutChannel[ch]->sectionData.sideInfoBits) { + error = AAC_ENC_WRITE_SEC_ERROR; + } + } + bitDemand += siBits; + } + break; + + case scale_factor_data: + { + INT sfDataBits = FDKaacEnc_encodeScaleFactorData( pChMaxValueInSfb, + pChSectionData, + pChScf, + hBitStream, + psyOutChannel[ch]->noiseNrg, + psyOutChannel[ch]->isScale, + chGlobalGain ); + if ( (hBitStream != NULL) + && (sfDataBits != (qcOutChannel[ch]->sectionData.scalefacBits + qcOutChannel[ch]->sectionData.noiseNrgBits)) ) { + error = AAC_ENC_WRITE_SCAL_ERROR; + } + bitDemand += sfDataBits; + } + break; + + case esc2_rvlc: + if (syntaxFlags & AC_ER_RVLC) { + /* write RVLC data into bitstream (error sens. cat. 2) */ + error = AAC_ENC_UNSUPPORTED_AOT; + } + break; + + case pulse: + /* Write pulse data */ + bitDemand += FDKaacEnc_encodePulseData(hBitStream); + break; + + case tns_data_present: + /* Write TNS data present flag */ + bitDemand += FDKaacEnc_encodeTnsDataPresent(pTnsInfo, + chBlockType, + hBitStream); + break; + case tns_data: + /* Write TNS data */ + bitDemand += FDKaacEnc_encodeTnsData(pTnsInfo, + chBlockType, + hBitStream); + break; + + case gain_control_data: + /* Nothing to do here */ + break; + + case gain_control_data_present: + bitDemand += FDKaacEnc_encodeGainControlData(hBitStream); + break; + + + case esc1_hcr: + //TODO: DRM! + if (syntaxFlags & AC_ER_HCR) + { + error = AAC_ENC_UNKNOWN; + } + break; + + case spectral_data: + if (hBitStream != NULL) + { + INT spectralBits = 0; + + spectralBits = FDKaacEnc_encodeSpectralData( psyOutChannel[ch]->sfbOffsets, + pChSectionData, + qcOutChannel[ch]->quantSpec, + hBitStream ); + + if (spectralBits != qcOutChannel[ch]->sectionData.huffmanBits) { + return AAC_ENC_WRITE_SPEC_ERROR; + } + bitDemand += spectralBits; + } + break; + + /* Non data cases */ + case adtscrc_start_reg1: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 192); + } + break; + case adtscrc_start_reg2: + if (hTpEnc != NULL) { + crcReg2 = transportEnc_CrcStartReg(hTpEnc, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg1); + } + break; + case adtscrc_end_reg2: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg2); + } + break; + case drmcrc_start_reg: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 0); + } + break; + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i=-1; + break; + + default: + error = AAC_ENC_UNKNOWN; + break; + } + + if (error != AAC_ENC_OK) { + return error; + } + + i++; + + } while (list->id[i] != end_of_sequence); + +bail: + if (pBitDemand != NULL) { + *pBitDemand = bitDemand; + } + + return error; +} + + +//----------------------------------------------------------------------------------------------- + +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT *qcOut, + PSY_OUT* psyOut, + QC_STATE *qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ) +{ + HANDLE_FDK_BITSTREAM hBs = transportEnc_GetBitstream(hTpEnc); + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, n, doByteAlign = 1; + INT bitMarkUp; + INT frameBits; + /* Get first bit of raw data block. + In case of ADTS+PCE, AU would start at PCE. + This is okay because PCE assures alignment. */ + UINT alignAnchor = FDKgetValidBits(hBs); + + frameBits = bitMarkUp = alignAnchor; + + + /* Write DSEs first in case of DAB */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) + { + if ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type == EXT_DATA_ELEMENT) ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here */ + } + + /* Channel element loop */ + for (i=0; inElements; i++) { + + ELEMENT_INFO elInfo = channelMapping->elInfo[i]; + INT elementUsedBits = 0; + + switch (elInfo.elType) + { + case ID_SCE: /* single channel */ + case ID_CPE: /* channel pair */ + case ID_LFE: /* low freq effects channel */ + { + if ( AAC_ENC_OK != (ErrorStatus = FDKaacEnc_ChannelElementWrite( hTpEnc, + &elInfo, + qcOut->qcElement[i]->qcOutChannel, + psyOut->psyOutElement[i], + psyOut->psyOutElement[i]->psyOutChannel, + syntaxFlags, /* syntaxFlags (ER tools ...) */ + aot, /* aot: AOT_AAC_LC, AOT_SBR, AOT_PS */ + epConfig, /* epConfig -1, 0, 1 */ + NULL, + 0 )) ) + { + return ErrorStatus; + } + + if ( !(syntaxFlags & AC_ER) ) + { + /* Write associated extension payload */ + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->qcElement[i]->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + } + } + break; + + /* In FDK, DSE signalling explicit done in elDSE. See channel_map.cpp */ + default: + return AAC_ENC_INVALID_ELEMENTINFO_TYPE; + + } /* switch */ + + if(elInfo.elType != ID_DSE) { + elementUsedBits -= bitMarkUp; + bitMarkUp = FDKgetValidBits(hBs); + elementUsedBits += bitMarkUp; + frameBits += elementUsedBits; + } + + } /* for (i=0; inElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + + if ( (qcOut->qcElement[i]->extension[n].type==EXT_SBR_DATA) + || (qcOut->qcElement[i]->extension[n].type==EXT_SBR_DATA_CRC) ) + { + /* Write sbr extension payload */ + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->qcElement[i]->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + + channelElementExtensionWritten[i][n] = 1; + } /* SBR */ + } /* n */ + } /* i */ + } /* AC_ELD */ + + for (i=0; inElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + + if (channelElementExtensionWritten[i][n]==0) + { + /* Write all remaining extension payloads in element */ + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->qcElement[i]->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + } /* n */ + } /* i */ + } /* if AC_ER */ + + /* Extend global extension payload table with fill bits */ + if ( syntaxFlags & AC_DRM ) + { + /* Exception for Drm */ + for (n = 0; n < qcOut->nExtensions; n++) { + if ( (qcOut->extension[n].type == EXT_SBR_DATA) + || (qcOut->extension[n].type == EXT_SBR_DATA_CRC) ) { + /* SBR data must be the last extension! */ + FDKmemcpy(&qcOut->extension[qcOut->nExtensions], &qcOut->extension[n], sizeof(QC_OUT_EXTENSION)); + break; + } + } + /* Do byte alignment after AAC (+ MPS) payload. + Assure that MPS has been written as channel assigned extension payload! */ + if (((FDKgetValidBits(hBs)-alignAnchor+(UINT)qcOut->totFillBits)&0x7)!=(UINT)qcOut->alignBits) { + return AAC_ENC_WRITTEN_BITS_ERROR; + } + FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits); + doByteAlign = 0; + + } /* AC_DRM */ + + /* Add fill data / stuffing bits */ + n = qcOut->nExtensions; + +// if (!(syntaxFlags & AC_DAB)) { + qcOut->extension[n].type = EXT_FILL_DATA; + qcOut->extension[n].nPayloadBits = qcOut->totFillBits; + qcOut->nExtensions++; +// } else { +// doByteAlign = 0; +// } + if (syntaxFlags & AC_DAB) + doByteAlign = 0; + + /* Write global extension payload and fill data */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) + { + if ( !(syntaxFlags & AC_DAB) || + ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type != EXT_DATA_ELEMENT) + ) + ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here */ + } + + if (!(syntaxFlags & (AC_SCALABLE|AC_ER|AC_DAB))) { + FDKwriteBits(hBs, ID_END, EL_ID_BITS); + } + + if (doByteAlign) { + /* Assure byte alignment*/ + if (((alignAnchor-FDKgetValidBits(hBs))&0x7)!=(UINT)qcOut->alignBits) { + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits); + } + + frameBits -= bitMarkUp; + frameBits += FDKgetValidBits(hBs); + + transportEnc_EndAccessUnit(hTpEnc, &frameBits); + + if (frameBits != qcOut->totalBits + qcKernel->globHdrBits){ + fprintf(stderr, "frameBits != qcOut->totalBits + qcKernel->globHdrBits: %d != %d + %d", frameBits, qcOut->totalBits, qcKernel->globHdrBits); + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + //fprintf(stderr, "ErrorStatus=%d", ErrorStatus); + return ErrorStatus; +} + diff --git a/libAACenc/src/bitenc.h b/libAACenc/src/bitenc.h new file mode 100644 index 00000000..498be7cc --- /dev/null +++ b/libAACenc/src/bitenc.h @@ -0,0 +1,183 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Bitstream encoder + +******************************************************************************/ + +#ifndef _BITENC_H +#define _BITENC_H + + +#include "qc_data.h" +#include "aacenc_tns.h" +#include "channel_map.h" +#include "interface.h" /* obsolete, when PSY_OUT is thrown out of the WritBS-call! */ +#include "FDK_audio.h" +#include "aacenc.h" + +#include "tpenc_lib.h" + +typedef enum{ + MAX_ENCODER_CHANNELS = 9, + MAX_BLOCK_TYPES = 4, + MAX_AAC_LAYERS = 9, + MAX_LAYERS = MAX_AAC_LAYERS , /* only one core layer if present */ + FIRST_LAY = 1 /* default layer number for AAC nonscalable */ +} _MAX_CONST; + +#define BUFFER_MX_HUFFCB_SIZE (32*sizeof(INT)) /* our FDK_bitbuffer needs size of power 2 */ + +#define EL_ID_BITS ( 3 ) + + +/** + * \brief Arbitrary order bitstream writer. This function can either assemble a bit stream + * and write into the bit buffer of hTpEnc or calculate the number of static bits (signal independent) + * TpEnc handle must be NULL in this case. Or also Calculate the minimum possible number of + * static bits which by disabling all tools e.g. MS, TNS and sbfCnt=0. The minCnt parameter + * has to be 1 in this latter case. + * \param hTpEnc Transport encoder handle. If NULL, the number of static bits will be returned into + * *pBitDemand. + * \param pElInfo + * \param qcOutChannel + * \param hReorderInfo + * \param psyOutElement + * \param psyOutChannel + * \param syntaxFlags Bit stream syntax flags as defined in FDK_audio.h (Audio Codec flags). + * \param aot + * \param epConfig + * \param pBitDemand Pointer to an int where the amount of bits is returned into. The returned value + * depends on if hTpEnc is NULL and minCnt. + * \param minCnt If non-zero the value returned into *pBitDemand is the absolute minimum required amount of + * static bits in order to write a valid bit stream. + * \return AAC_ENCODER_ERROR error code + */ +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( HANDLE_TRANSPORTENC hTpEnc, + ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], + UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, + INT *pBitDemand, + UCHAR minCnt + ); +/** + * \brief Write bit stream or account static bits + * \param hTpEnc transport encoder handle. If NULL, the function will + * not write any bit stream data but only count the amount + * of static (signal independent) bits + * \param channelMapping Channel mapping info + * \param qcOut + * \param psyOut + * \param qcKernel + * \param hBSE + * \param aot Audio Object Type being encoded + * \param syntaxFlags Flags indicating format specific detail + * \param epConfig Error protection config + */ +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream (HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT* qcOut, + PSY_OUT* psyOut, + QC_STATE* qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ); + +INT FDKaacEnc_writeExtensionData( HANDLE_TRANSPORTENC hTpEnc, + QC_OUT_EXTENSION *pExtension, + INT elInstanceTag, + UINT alignAnchor, + UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, + SCHAR epConfig + ); + +#endif /* _BITENC_H */ diff --git a/libAACenc/src/block_switch.cpp b/libAACenc/src/block_switch.cpp new file mode 100644 index 00000000..7b3e275f --- /dev/null +++ b/libAACenc/src/block_switch.cpp @@ -0,0 +1,545 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): M. Werner, Tobias Chalupka + Description: Block switching + +******************************************************************************/ + +/****************** Includes *****************************/ + +#include "block_switch.h" +#include "genericStds.h" + + +#define LOWOV_WINDOW _LOWOV_WINDOW + +/**************** internal function prototypes ***********/ + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx); + +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, + INT windowLen, + const INT_PCM *pTimeSignal + ); + +/****************** Constants *****************************/ +/* LONG START SHORT STOP LOWOV */ +static const INT blockType2windowShape[2][5] = { {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */ + {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW} }; /* LC */ + +/* IIR high pass coeffs */ + +#ifndef SINETABLE_16BIT + +static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]= +{ + FL2FXCONST_DBL(-0.5095),FL2FXCONST_DBL(0.7548) +}; + +static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_DBL invAttackRatio = FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */ + +/* The next constants are scaled, because they are used for comparison with scaled values*/ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#else + +static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN]= +{ + FL2FXCONST_SGL(-0.5095),FL2FXCONST_SGL(0.7548) +}; + +static const FIXP_DBL accWindowNrgFac = FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_SGL invAttackRatio = FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = (FL2FXCONST_DBL(1e+6f*NORM_PCM_ENERGY)>>BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#endif + +/**************** internal function prototypes ***********/ + +/****************** Routines ****************************/ +void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) +{ + FDKmemclear (blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); + + if (isLowDelay) + { + blockSwitchingControl->nBlockSwitchWindows = 4; + blockSwitchingControl->allowShortFrames = 0; + blockSwitchingControl->allowLookAhead = 0; + } + else + { + blockSwitchingControl->nBlockSwitchWindows = 8; + blockSwitchingControl->allowShortFrames = 1; + blockSwitchingControl->allowLookAhead = 1; + } + + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + /* Initialize startvalue for blocktype */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence]; + +} + +static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = +{ + /* Attack in Window 0 */ {1, 3, 3, 1}, + /* Attack in Window 1 */ {1, 1, 3, 3}, + /* Attack in Window 2 */ {2, 1, 3, 2}, + /* Attack in Window 3 */ {3, 1, 3, 1}, + /* Attack in Window 4 */ {3, 1, 1, 3}, + /* Attack in Window 5 */ {3, 2, 1, 2}, + /* Attack in Window 6 */ {3, 3, 1, 1}, + /* Attack in Window 7 */ {3, 3, 1, 1} +}; + +/* change block type depending on current blocktype and whether there's an attack */ +/* assume no look-ahead */ +static const INT chgWndSq[2][N_BLOCKTYPES] = +{ + /* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, LOWOV_WINDOW, WRONG_WINDOW */ + /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, STOP_WINDOW , WRONG_WINDOW }, + /*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW } +}; + +/* change block type depending on current blocktype and whether there's an attack */ +/* assume look-ahead */ +static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = +{ + /*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */ + /*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* no attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} }, /* no attack */ + /*no attack*/ { {LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, WRONG_WINDOW, WRONG_WINDOW}, /* attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, WRONG_WINDOW, WRONG_WINDOW} } /* attack */ +}; + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE, const INT_PCM *pTimeSignal) +{ + UINT i; + FIXP_DBL enM1, enMax; + + UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows; + + /* for LFE : only LONG window allowed */ + if (isLFE) { + + /* case LFE: */ + /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = SINE_WINDOW; + blockSwitchingControl->noOfGroups = 1; + blockSwitchingControl->groupLen[0] = 1; + + return(0); + }; + + /* Save current attack index as last attack index */ + blockSwitchingControl->lastattack = blockSwitchingControl->attack; + blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex; + + /* Save current window energy as last window energy */ + FDKmemcpy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->windowNrg[1], sizeof(blockSwitchingControl->windowNrg[0])); + FDKmemcpy(blockSwitchingControl->windowNrgF[0], blockSwitchingControl->windowNrgF[1], sizeof(blockSwitchingControl->windowNrgF[0])); + + if (blockSwitchingControl->allowShortFrames) + { + /* Calculate suggested grouping info for the last frame */ + + /* Reset grouping info */ + FDKmemclear (blockSwitchingControl->groupLen, sizeof(blockSwitchingControl->groupLen)); + + /* Set grouping info */ + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + FDKmemcpy(blockSwitchingControl->groupLen, suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], sizeof(blockSwitchingControl->groupLen)); + + if (blockSwitchingControl->attack == TRUE) + blockSwitchingControl->maxWindowNrg = FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], blockSwitchingControl->lastAttackIndex); + else + blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0); + + } + + + /* Calculate unfiltered and filtered energies in subwindows and combine to segments */ + FDKaacEnc_CalcWindowEnergy(blockSwitchingControl, granuleLength>>(nBlockSwitchWindows==4? 2:3 ), pTimeSignal); + + /* now calculate if there is an attack */ + + /* reset attack */ + blockSwitchingControl->attack = FALSE; + + /* look for attack */ + enMax = FL2FXCONST_DBL(0.0f); + enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1]; + + for (i=0; iaccWindowNrg); + blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1) ; + + if (fMult(blockSwitchingControl->windowNrgF[1][i],invAttackRatio) > blockSwitchingControl->accWindowNrg ) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = i; + } + enM1 = blockSwitchingControl->windowNrgF[1][i]; + enMax = fixMax(enMax, enM1); + } + + + if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE; + + /* Check if attack spreads over frame border */ + if((blockSwitchingControl->attack == FALSE) && (blockSwitchingControl->lastattack == TRUE)) { + /* if attack is in last window repeat SHORT_WINDOW */ + if ( ((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows-1]>>4) > fMult((FIXP_DBL)(10<<(DFRACT_BITS-1-4)), blockSwitchingControl->windowNrgF[1][1])) + && (blockSwitchingControl->lastAttackIndex == (INT)nBlockSwitchWindows-1) + ) + { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = 0; + } + } + + + if(blockSwitchingControl->allowLookAhead) + { + + + blockSwitchingControl->lastWindowSequence = + chgWndSqLkAhd[blockSwitchingControl->lastattack][blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence]; + } + else + { + /* Low Delay */ + blockSwitchingControl->lastWindowSequence = + chgWndSq[blockSwitchingControl->attack][blockSwitchingControl->lastWindowSequence]; + } + + + /* update window shape */ + blockSwitchingControl->windowShape = blockType2windowShape[blockSwitchingControl->allowShortFrames][blockSwitchingControl->lastWindowSequence]; + + return(0); +} + + + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], const INT blSwWndIdx) +{ +/* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy for a block switching analysis windows, + not for a short block. The same is done FDKaacEnc_CalcWindowEnergy(). The result of FDKaacEnc_GetWindowEnergy() + is used for a comparision of the max energy of left/right channel. */ + + return in[blSwWndIdx]; + +} + +static void FDKaacEnc_CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, const INT_PCM *pTimeSignal) +{ + INT i; + UINT w; + + FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; + FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; + + /* sum up scalarproduct of timesignal as windowed Energies */ + for (w=0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { + + FIXP_DBL temp_windowNrg = FL2FXCONST_DBL(0.0f); + FIXP_DBL temp_windowNrgF = FL2FXCONST_DBL(0.0f); + FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0]; + FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1]; + + /* windowNrg = sum(timesample^2) */ + for(i=0;i> 1; +#else + tempUnfiltered = (FIXP_DBL) *pTimeSignal++ << (DFRACT_BITS-SAMPLE_BITS-1); +#endif + t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered-temp_iirState0); + t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); + tempFiltred = (t1 - t2) << 1; + + temp_iirState0 = tempUnfiltered; + temp_iirState1 = tempFiltred; + + /* subtract 2 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT) + * because tempUnfiltered was already scaled with 1 (is 2 after squaring) + * subtract 1 from overallscaling (BLOCK_SWITCH_ENERGY_SHIFT) + * because of fMultDiv2 is doing a scaling by one */ + temp_windowNrg += fPow2Div2(tempUnfiltered) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + temp_windowNrgF += fPow2Div2(tempFiltred) >> (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + } + blockSwitchingControl->windowNrg[1][w] = temp_windowNrg; + blockSwitchingControl->windowNrgF[1][w] = temp_windowNrgF; + blockSwitchingControl->iirStates[0] = temp_iirState0; + blockSwitchingControl->iirStates[1] = temp_iirState1; + } +} + + +static const UCHAR synchronizedBlockTypeTable[5][5] = +{ + /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW*/ + /* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, + /* START_WINDOW */ {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW}, + /* SHORT_WINDOW */ {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW}, + /* STOP_WINDOW */ {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, + /* LOWOV_WINDOW */ {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW}, +}; + +int FDKaacEnc_SyncBlockSwitching ( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, + const INT nChannels, + const INT commonWindow ) +{ + UCHAR patchType = LONG_WINDOW; + + if( nChannels == 2 && commonWindow == TRUE) + { + /* could be better with a channel loop (need a handle to psy_data) */ + /* get suggested Block Types and synchronize */ + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->lastWindowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->lastWindowSequence]; + + /* sanity check (no change from low overlap window to short winow and vice versa) */ + if (patchType == WRONG_WINDOW) + return -1; /* mixed up AAC-LC and AAC-LD */ + + /* Set synchronized Blocktype */ + blockSwitchingControlLeft->lastWindowSequence = patchType; + blockSwitchingControlRight->lastWindowSequence = patchType; + + /* update window shape */ + blockSwitchingControlLeft->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlLeft->lastWindowSequence]; + blockSwitchingControlRight->windowShape = blockType2windowShape[blockSwitchingControlLeft->allowShortFrames][blockSwitchingControlRight->lastWindowSequence]; + } + + if (blockSwitchingControlLeft->allowShortFrames) + { + int i; + + if( nChannels == 2 ) + { + if (commonWindow == TRUE) + { + /* Synchronize grouping info */ + int windowSequenceLeftOld = blockSwitchingControlLeft->lastWindowSequence; + int windowSequenceRightOld = blockSwitchingControlRight->lastWindowSequence; + + /* Long Blocks */ + if(patchType != SHORT_WINDOW) { + /* Set grouping info */ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + blockSwitchingControlRight->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) + { + blockSwitchingControlLeft->groupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + + /* Short Blocks */ + else { + /* in case all two channels were detected as short-blocks before syncing, use the grouping of channel with higher maxWindowNrg */ + if( (windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld == SHORT_WINDOW) ) + { + if(blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++){ + blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i]; + } + } + else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++){ + blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i]; + } + } + } + else if ( (windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld != SHORT_WINDOW) ) + { + /* else use grouping of short-block channel */ + blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++){ + blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i]; + } + } + else if ( (windowSequenceRightOld == SHORT_WINDOW) && + (windowSequenceLeftOld != SHORT_WINDOW) ) + { + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++){ + blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i]; + } + } else { + /* syncing a start and stop window ... */ + blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups = 2; + blockSwitchingControlLeft->groupLen[0] = blockSwitchingControlRight->groupLen[0] = 4; + blockSwitchingControlLeft->groupLen[1] = blockSwitchingControlRight->groupLen[1] = 4; + } + } /* Short Blocks */ + } + else { + /* stereo, no common window */ + if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) + { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + if (blockSwitchingControlRight->lastWindowSequence!=SHORT_WINDOW){ + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlRight->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) + { + blockSwitchingControlRight->groupLen[i] = 0; + } + } + } /* common window */ + } else { + /* Mono */ + if (blockSwitchingControlLeft->lastWindowSequence!=SHORT_WINDOW){ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) + { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + } + } /* allowShortFrames */ + + + /* Translate LOWOV_WINDOW block type to a meaningful window shape. */ + if ( ! blockSwitchingControlLeft->allowShortFrames ) { + if ( blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW + && blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW ) + { + blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlLeft->windowShape = LOL_WINDOW; + } + } + if (nChannels == 2) { + if ( ! blockSwitchingControlRight->allowShortFrames ) { + if ( blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW + && blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW ) + { + blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlRight->windowShape = LOL_WINDOW; + } + } + } + + return 0; +} + + diff --git a/libAACenc/src/block_switch.h b/libAACenc/src/block_switch.h new file mode 100644 index 00000000..e94b6f59 --- /dev/null +++ b/libAACenc/src/block_switch.h @@ -0,0 +1,146 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): M. Werner + Description: Block switching + +******************************************************************************/ + +#ifndef _BLOCK_SWITCH_H +#define _BLOCK_SWITCH_H + +#include "common_fix.h" + +#include "psy_const.h" + +/****************** Defines ******************************/ + #define BLOCK_SWITCH_WINDOWS 8 /* number of windows for energy calculation */ + +#define BLOCK_SWITCHING_IIR_LEN 2 /* Length of HighPass-IIR-Filter for Attack-Detection */ +#define BLOCK_SWITCH_ENERGY_SHIFT 7 /* should be logDualis(BLOCK_SWITCH_WINDOW_LEN) to avoid overflow in windowNrgs. */ + +#define LAST_WINDOW 0 +#define THIS_WINDOW 1 + + +/****************** Structures ***************************/ +typedef struct{ + INT lastWindowSequence; + INT windowShape; + INT lastWindowShape; + UINT nBlockSwitchWindows; /* number of windows for energy calculation */ + INT attack; + INT lastattack; + INT attackIndex; + INT lastAttackIndex; + INT allowShortFrames; /* for Low Delay, don't allow short frames */ + INT allowLookAhead; /* for Low Delay, don't do look-ahead */ + INT noOfGroups; + INT groupLen[MAX_NO_OF_GROUPS]; + FIXP_DBL maxWindowNrg; /* max energy in subwindows */ + + FIXP_DBL windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows (last and current) */ + FIXP_DBL windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy in segments (last and current) */ + FIXP_DBL accWindowNrg; /* recursively accumulated windowNrgF */ + + FIXP_DBL iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */ + +} BLOCK_SWITCHING_CONTROL; + + + + + +void FDKaacEnc_InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay); + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, const INT granuleLength, const int isLFE, const INT_PCM *pTimeSignal); + +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, + const INT noOfChannels, + const INT commonWindow); + +#endif /* #ifndef _BLOCK_SWITCH_H */ diff --git a/libAACenc/src/channel_map.cpp b/libAACenc/src/channel_map.cpp new file mode 100644 index 00000000..99ed2b58 --- /dev/null +++ b/libAACenc/src/channel_map.cpp @@ -0,0 +1,566 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: A. Groeschel + contents/description: channel mapping functionality + +******************************************************************************/ + +#include "channel_map.h" +#include "bitenc.h" +#include "psy_const.h" +#include "qc_data.h" +#include "aacEnc_ram.h" + + +/* channel_assignment treats the relationship of Input file channels + to the encoder channels. + This is necessary because the usual order in RIFF files (.wav) + is different from the elements order in the coder given + by Table 8.1 (implicit speaker mapping) of the AAC standard. + + In mono and stereo case, this is trivial. + In mc case, it looks like this: + + Channel Input file coder chan +5ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 3 3 (1st of 2nd CPE) + right surround 4 4 (2nd of 2nd CPE) + +5.1ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 4 3 (1st of 2nd CPE) + right surround 5 4 (2nd of 2nd CPE) + LFE 3 5 (LFE) +*/ + +typedef struct { + + CHANNEL_MODE encoderMode; + INT channel_assignment[/*(8)*/12]; + +} CHANNEL_ASSIGNMENT_INFO_TAB; + + +static const CHANNEL_ASSIGNMENT_INFO_TAB assignmentInfoTabMpeg[] = +{ + { MODE_INVALID, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* invalid */ + { MODE_1, { 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* mono */ + { MODE_2, { 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* stereo */ + { MODE_1_2, { 0, 1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 3ch */ + { MODE_1_2_1, { 0, 1, 2, 3,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 4ch */ + { MODE_1_2_2, { 0, 1, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1} }, /* 5ch */ + { MODE_1_2_2_1, { 0, 1, 2, 3, 4, 5,-1,-1,-1,-1,-1,-1} }, /* 5.1ch */ + { MODE_1_2_2_2_1, { 0, 1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1} }, /* 7.1ch */ + { MODE_7_1_REAR_SURROUND, { 0, 1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1} }, /* 7.1ch */ + { MODE_7_1_FRONT_CENTER, { 0, 1, 2, 3, 4, 5, 6, 7,-1,-1,-1,-1} } /* 7.1ch */ +}; + +static const CHANNEL_ASSIGNMENT_INFO_TAB assignmentInfoTabWav[] = +{ + { MODE_INVALID, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* invalid */ + { MODE_1, { 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* mono */ + { MODE_2, { 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* stereo */ + { MODE_1_2, { 2, 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 3ch */ + { MODE_1_2_1, { 2, 0, 1, 3,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 4ch */ + { MODE_1_2_2, { 2, 0, 1, 3, 4,-1,-1,-1,-1,-1,-1,-1} }, /* 5ch */ + { MODE_1_2_2_1, { 2, 0, 1, 4, 5, 3,-1,-1,-1,-1,-1,-1} }, /* 5.1ch */ + { MODE_1_2_2_2_1, { 2, 6, 7, 0, 1, 4, 5, 3,-1,-1,-1,-1} }, /* 7.1ch */ + { MODE_7_1_REAR_SURROUND, { 2, 0, 1, 6, 7, 4, 5, 3,-1,-1,-1,-1} }, /* 7.1ch */ + { MODE_7_1_FRONT_CENTER, { 2, 6, 7, 0, 1, 4, 5, 3,-1,-1,-1,-1} }, /* 7.1ch */ +}; + +static const CHANNEL_ASSIGNMENT_INFO_TAB assignmentInfoTabWg4[] = +{ + { MODE_INVALID, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* invalid */ + { MODE_1, { 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* mono */ + { MODE_2, { 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* stereo */ + { MODE_1_2, { 2, 0, 1,-1,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 3ch */ + { MODE_1_2_1, { 3, 0, 1, 2,-1,-1,-1,-1,-1,-1,-1,-1} }, /* 4ch */ + { MODE_1_2_2, { 4, 0, 1, 2, 3,-1,-1,-1,-1,-1,-1,-1} }, /* 5ch */ + { MODE_1_2_2_1, { 4, 0, 1, 2, 3, 5,-1,-1,-1,-1,-1,-1} }, /* 5.1ch */ + { MODE_1_2_2_2_1, { 6, 0, 1, 2, 3, 4, 5, 7,-1,-1,-1,-1} }, /* 7.1ch */ +}; + +/* Channel mode configuration tab provides, + corresponding number of channels and elements +*/ +static const CHANNEL_MODE_CONFIG_TAB channelModeConfig[] = +{ + { MODE_1, 1, 1, 1 }, /* SCE */ + { MODE_2, 2, 2, 1 }, /* CPE */ + { MODE_1_2, 3, 3, 2 }, /* SCE,CPE */ + { MODE_1_2_1, 4, 4, 3 }, /* SCE,CPE,SCE */ + { MODE_1_2_2, 5, 5, 3 }, /* SCE,CPE,CPE */ + { MODE_1_2_2_1, 6, 5, 4 }, /* SCE,CPE,CPE,LFE */ + { MODE_1_2_2_2_1, 8, 7, 5 }, /* SCE,CPE,CPE,CPE,LFE */ + { MODE_7_1_REAR_SURROUND, 8, 7, 5 }, + { MODE_7_1_FRONT_CENTER, 8, 7, 5 }, +}; + +#define MAX_MODES (sizeof(assignmentInfoTabWav)/sizeof(CHANNEL_ASSIGNMENT_INFO_TAB)) + +const INT* FDKaacEnc_getChannelAssignment(CHANNEL_MODE encMode, CHANNEL_ORDER co) +{ + const CHANNEL_ASSIGNMENT_INFO_TAB *pTab; + int i; + + if (co == CH_ORDER_MPEG) + pTab = assignmentInfoTabMpeg; + else if (co == CH_ORDER_WAV) + pTab = assignmentInfoTabWav; + else + pTab = assignmentInfoTabWg4; + + for(i=MAX_MODES-1; i>0; i--) { + if (encMode== pTab[i].encoderMode) { + break; + } + } + return (pTab[i].channel_assignment); +} + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, INT nChannels) +{ + INT i; + CHANNEL_MODE encMode = MODE_INVALID; + + if (*mode==MODE_UNKNOWN) { + for (i=0; i<(INT)sizeof(channelModeConfig)/(INT)sizeof(CHANNEL_MODE_CONFIG_TAB); i++) { + if (channelModeConfig[i].nChannels==nChannels) { + encMode = channelModeConfig[i].encMode; + break; + } + } + *mode = encMode; + } + else { + /* check if valid channel configuration */ + if (FDKaacEnc_GetChannelModeConfiguration(*mode)->nChannels==nChannels) { + encMode = *mode; + } + } + + if (encMode==MODE_INVALID) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +static INT FDKaacEnc_initElement (ELEMENT_INFO* elInfo, MP4_ELEMENT_ID elType, INT* cnt, CHANNEL_MODE mode, CHANNEL_ORDER co, INT* it_cnt, const FIXP_DBL relBits) { + + INT error=0; + INT counter =*cnt; + + const INT *assign = FDKaacEnc_getChannelAssignment(mode, co); + + elInfo->elType=elType; + elInfo->relativeBits = relBits; + + switch(elInfo->elType) { + case ID_SCE: case ID_LFE: case ID_CCE: + elInfo->nChannelsInEl=1; + elInfo->ChannelIndex[0]=assign[counter++]; + elInfo->instanceTag=it_cnt[elType]++; + + break; + case ID_CPE: + elInfo->nChannelsInEl=2; + elInfo->ChannelIndex[0]=assign[counter++]; + elInfo->ChannelIndex[1]=assign[counter++]; + elInfo->instanceTag=it_cnt[elType]++; + break; + case ID_DSE: + elInfo->nChannelsInEl=0; + elInfo->ChannelIndex[0]=0; + elInfo->ChannelIndex[1]=0; + elInfo->instanceTag=it_cnt[elType]++; + break; + default: error=1; + }; + *cnt = counter; + return error; + +} + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, CHANNEL_ORDER co, CHANNEL_MAPPING* cm) +{ + INT count=0; /* count through coder channels */ + INT it_cnt[ID_END+1]; + INT i; + + for (i=0; iencMode = channelModeConfig[i].encMode; + cm->nChannels = channelModeConfig[i].nChannels; + cm->nChannelsEff = channelModeConfig[i].nChannelsEff; + cm->nElements = channelModeConfig[i].nElements; + + break; + } + } + + /* init element info struct */ + switch(mode) { + case MODE_1: + /* (mono) sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + case MODE_2: + /* (stereo) cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_CPE, &count, mode, co, it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + + case MODE_1_2: + /* sce + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.6f)); + break; + + case MODE_1_2_1: + /* sce + cpe + sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.3f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.3f)); + break; + + case MODE_1_2_2: + /* sce + cpe + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.37f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.37f)); + break; + + case MODE_1_2_2_1: + /* (5.1) sce + cpe + cpe + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.24f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.06f)); + break; + + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + /* (7.1) sce + cpe + cpe + cpe + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.18f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_CPE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, mode, co, it_cnt, FL2FXCONST_DBL(0.04f)); + break; + default: + //*chMap=0; + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + }; + + + FDK_ASSERT(cm->nElements<=(8)); + + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE *hQC, + CHANNEL_MAPPING *cm, + INT bitrateTot, + INT averageBitsTot, + INT maxChannelBits) +{ + int sc_brTot = CountLeadingBits(bitrateTot); + + switch(cm->encMode) { + case MODE_1: + hQC->elementBits[0]->chBitrateEl = bitrateTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + + case MODE_2: + hQC->elementBits[0]->chBitrateEl = bitrateTot>>1; + + hQC->elementBits[0]->maxBitsEl = 2*maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + case MODE_1_2: { + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + + hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + hQC->elementBits[1]->chBitrateEl = fMult(cpeRate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits; + break; + } + case MODE_1_2_1: { + /* sce + cpe + sce */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sce1Rate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + FIXP_DBL sce2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = fMult(sce1Rate, (FIXP_DBL)(bitrateTot<>sc_brTot; + hQC->elementBits[1]->chBitrateEl = fMult(cpeRate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[2]->chBitrateEl = fMult(sce2Rate, (FIXP_DBL)(bitrateTot<>sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[2]->maxBitsEl = maxChannelBits; + break; + } + case MODE_1_2_2: { + /* sce + cpe + cpe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits; + break; + } + + case MODE_1_2_2_1: { + /* (5.1) sce + cpe + cpe + lfe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + hQC->elementBits[3]->relativeBitsEl = cm->elInfo[3].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + FIXP_DBL lfeRate = cm->elInfo[3].relativeBits; + + int maxBitsTot = maxChannelBits * 5; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits,averageBitsTot)); + int maxLfeBits = (int) FDKmax ( (INT)((fMult(lfeRate,(FIXP_DBL)(maxChannelBits<>sc)<<1), + (INT)((fMult(FL2FXCONST_DBL(1.1f/2.f),fMult(lfeRate,(FIXP_DBL)(averageBitsTot<>sc) ); + + maxChannelBits = (maxBitsTot - maxLfeBits); + sc = CountLeadingBits(maxChannelBits); + + maxChannelBits = fMult((FIXP_DBL)maxChannelBits<>sc; + + hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[3]->chBitrateEl = fMult(lfeRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[3]->maxBitsEl = maxLfeBits; + + break; + } + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_1_2_2_2_1: { + int cpe3Idx = 3; + int lfeIdx = 4; + + /* (7.1) sce + cpe + cpe + cpe + lfe */ + FIXP_DBL sceRate = hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL cpe3Rate = hQC->elementBits[cpe3Idx]->relativeBitsEl = cm->elInfo[cpe3Idx].relativeBits; + FIXP_DBL lfeRate = hQC->elementBits[lfeIdx]->relativeBitsEl = cm->elInfo[lfeIdx].relativeBits; + + int maxBitsTot = maxChannelBits * 7; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits,averageBitsTot)); + int maxLfeBits = (int) FDKmax ( (INT)((fMult(lfeRate,(FIXP_DBL)(maxChannelBits<>sc)<<1), + (INT)((fMult(FL2FXCONST_DBL(1.1f/2.f),fMult(lfeRate,(FIXP_DBL)(averageBitsTot<>sc) ); + + maxChannelBits = (maxBitsTot - maxLfeBits) / 7; + + hQC->elementBits[0]->chBitrateEl = fMult(sceRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + hQC->elementBits[1]->chBitrateEl = fMult(cpe1Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[2]->chBitrateEl = fMult(cpe2Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[cpe3Idx]->chBitrateEl = fMult(cpe3Rate, (FIXP_DBL)(bitrateTot<>(sc_brTot+1); + hQC->elementBits[lfeIdx]->chBitrateEl = fMult(lfeRate, (FIXP_DBL)(bitrateTot<>sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[cpe3Idx]->maxBitsEl = 2*maxChannelBits; + hQC->elementBits[lfeIdx]->maxBitsEl = maxLfeBits; + break; + } + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +/********************************************************************************/ +/* */ +/* function: GetMonoStereoMODE(const CHANNEL_MODE mode) */ +/* */ +/* description: Determines encoder setting from channel mode. */ +/* Multichannel modes are mapped to mono or stereo modes */ +/* returns MODE_MONO in case of mono, */ +/* MODE_STEREO in case of stereo */ +/* MODE_INVALID in case of error */ +/* */ +/* input: CHANNEL_MODE mode: Encoder mode (see qc_data.h). */ +/* output: return: CM_STEREO_MODE monoStereoSetting */ +/* (MODE_INVALID: error, */ +/* MODE_MONO: mono */ +/* MODE_STEREO: stereo). */ +/* */ +/* misc: No memory is allocated. */ +/* */ +/********************************************************************************/ + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode){ + + ELEMENT_MODE monoStereoSetting = EL_MODE_INVALID; + + switch(mode){ + case MODE_1: /* mono setups */ + monoStereoSetting = EL_MODE_MONO; + break; + case MODE_2: /* stereo setups */ + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + monoStereoSetting = EL_MODE_STEREO; + break; + default: /* error */ + monoStereoSetting = EL_MODE_INVALID; + break; + } + + return monoStereoSetting; +} + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration(const CHANNEL_MODE mode) +{ + INT i; + const CHANNEL_MODE_CONFIG_TAB *cm_config = NULL; + + /* get channel mode config */ + for (i=0; i<(INT)sizeof(channelModeConfig)/(INT)sizeof(CHANNEL_MODE_CONFIG_TAB); i++) { + if (channelModeConfig[i].encMode==mode) + { + cm_config = &channelModeConfig[i]; + break; + } + } + return cm_config; +} diff --git a/libAACenc/src/channel_map.h b/libAACenc/src/channel_map.h new file mode 100644 index 00000000..2cfb4867 --- /dev/null +++ b/libAACenc/src/channel_map.h @@ -0,0 +1,132 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************* Fast MPEG AAC Audio Encoder ********************** + + Initial author: A. Groeschel + contents/description: channel mapping functionality + +******************************************************************************/ + +#ifndef _CHANNEL_MAP_H +#define _CHANNEL_MAP_H + + +#include "aacenc.h" +#include "psy_const.h" +#include "qc_data.h" + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; +} CHANNEL_MODE_CONFIG_TAB; + + +/* Element mode */ +typedef enum { + EL_MODE_INVALID = 0, + EL_MODE_MONO, + EL_MODE_STEREO +} ELEMENT_MODE; + + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, + INT nChannels); + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, + CHANNEL_ORDER co, + CHANNEL_MAPPING* chMap); + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE *hQC, + CHANNEL_MAPPING *cm, + INT bitrateTot, + INT averageBitsTot, + INT maxChannelBits); + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode); + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration(const CHANNEL_MODE mode); + +#endif /* CHANNEL_MAP_H */ diff --git a/libAACenc/src/chaosmeasure.cpp b/libAACenc/src/chaosmeasure.cpp new file mode 100644 index 00000000..4e56e9e7 --- /dev/null +++ b/libAACenc/src/chaosmeasure.cpp @@ -0,0 +1,161 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Chaos measure calculation + +******************************************************************************/ + +#include "chaosmeasure.h" + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast + description: Eberlein method of chaos measure calculation by high-pass + filtering amplitude spectrum + A special case of FDKaacEnc_CalculateChaosMeasureTonalGeneric -- + highly optimized +*****************************************************************************/ +static void +FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( FIXP_DBL *RESTRICT paMDCTDataNM0, + INT numberOfLines, + FIXP_DBL *RESTRICT chaosMeasure ) +{ + INT i, j; + + /* calculate chaos measure by "peak filter" */ + for (i=0; i<2; i++) { + /* make even and odd pass through data */ + FIXP_DBL left,center; /* left, center tap of filter */ + + left = (FIXP_DBL)((LONG)paMDCTDataNM0[i]^((LONG)paMDCTDataNM0[i]>>(DFRACT_BITS-1))); + center = (FIXP_DBL)((LONG)paMDCTDataNM0[i+2]^((LONG)paMDCTDataNM0[i+2]>>(DFRACT_BITS-1))); + + for (j = i+2; j < numberOfLines - 2; j+=2) { + FIXP_DBL right = (FIXP_DBL)((LONG)paMDCTDataNM0[j+2]^((LONG)paMDCTDataNM0[j+2]>>(DFRACT_BITS-1))); + FIXP_DBL tmp = (left>>1)+(right>>1); + + if (tmp < center ) { + INT leadingBits = CntLeadingZeros(center)-1; + tmp = schur_div(tmp<codeBook == 11) || (huffsection->codeBook >= 16)) ) { + sideInfoBits = 5; + } + else { + sideInfoBits = sideInfoTab[huffsection->sfbCnt]; + } + + return (sideInfoBits); +} + +/* count bits using all possible tables */ +static void FDKaacEnc_buildBitLookUp( + const SHORT* const quantSpectrum, + const INT maxSfb, + const INT* const sfbOffset, + const UINT* const sfbMax, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO* const huffsection + ) +{ + INT i, sfbWidth; + + for (i = 0; i < maxSfb; i++) + { + huffsection[i].sfbCnt = 1; + huffsection[i].sfbStart = i; + huffsection[i].sectionBits = INVALID_BITCOUNT; + huffsection[i].codeBook = -1; + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + FDKaacEnc_bitCount(quantSpectrum + sfbOffset[i], sfbWidth, sfbMax[i], bitLookUp[i]); + } +} + +/* essential helper functions */ +static INT FDKaacEnc_findBestBook( + const INT* const bc, + INT* const book, + const INT useVCB11 + ) +{ + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + + for (j = 0; j <= end; j++) + { + if (bc[j] < minBits) + { + minBits = bc[j]; + *book = j; + } + } + return (minBits); +} + +static INT FDKaacEnc_findMinMergeBits( + const INT* const bc1, + const INT* const bc2, + const INT useVCB11 + ) +{ + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + + for (j = 0; j <= end; j++) + { + if (bc1[j] + bc2[j] < minBits) + { + minBits = bc1[j] + bc2[j]; + } + } + return (minBits); +} + +static void FDKaacEnc_mergeBitLookUp( + INT* const bc1, + const INT* const bc2 + ) +{ + int j; + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) + { + bc1[j] = fixMin(bc1[j] + bc2[j], INVALID_BITCOUNT); + } +} + +static INT FDKaacEnc_findMaxMerge( + const INT* const mergeGainLookUp, + const SECTION_INFO* const huffsection, + const INT maxSfb, + INT* const maxNdx + ) +{ + INT i, maxMergeGain = 0; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) + { + if (mergeGainLookUp[i] > maxMergeGain) + { + maxMergeGain = mergeGainLookUp[i]; + *maxNdx = i; + } + } + return (maxMergeGain); +} + +static INT FDKaacEnc_CalcMergeGain( + const SECTION_INFO* const huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const sideInfoTab, + const INT ndx1, + const INT ndx2, + const INT useVCB11 + ) +{ + INT MergeGain, MergeBits, SplitBits; + + MergeBits = sideInfoTab[huffsection[ndx1].sfbCnt + huffsection[ndx2].sfbCnt] + FDKaacEnc_findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2], useVCB11); + SplitBits = huffsection[ndx1].sectionBits + huffsection[ndx2].sectionBits; /* Bit amount for splitted huffsections */ + MergeGain = SplitBits - MergeBits; + + if ( (huffsection[ndx1].codeBook==CODE_BOOK_PNS_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_PNS_NO) + || (huffsection[ndx1].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO) + || (huffsection[ndx1].codeBook==CODE_BOOK_IS_IN_PHASE_NO)||(huffsection[ndx2].codeBook==CODE_BOOK_IS_IN_PHASE_NO) + ) + { + MergeGain = -1; + } + + return (MergeGain); +} + + +/* sectioning Stage 0:find minimum codbooks */ +static void FDKaacEnc_gmStage0( + SECTION_INFO* const RESTRICT huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const INT* const noiseNrg, + const INT* const isBook + ) +{ + INT i; + + for (i = 0; i < maxSfb; i++) + { + /* Side-Info bits will be calculated in Stage 1! */ + if (huffsection[i].sectionBits == INVALID_BITCOUNT) + { + /* intensity and pns codebooks are already allocated in bitcount.c */ + if(noiseNrg[i] != NO_NOISE_PNS){ + huffsection[i].codeBook=CODE_BOOK_PNS_NO; + huffsection[i].sectionBits = 0; + } + else if( isBook[i] ) { + huffsection[i].codeBook=isBook[i]; + huffsection[i].sectionBits = 0; + } + else { + huffsection[i].sectionBits = FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), 0); /* useVCB11 must be 0!!! */ + } + } + } +} + +/* + sectioning Stage 1:merge all connected regions with the same code book and + calculate side info + */ +static void FDKaacEnc_gmStage1( + SECTION_INFO* const RESTRICT huffsection, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const SHORT* const sideInfoTab, + const INT useVCB11 + ) +{ + INT mergeStart = 0, mergeEnd; + + do + { + for (mergeEnd = mergeStart + 1; mergeEnd < maxSfb; mergeEnd++) + { + if (huffsection[mergeStart].codeBook != huffsection[mergeEnd].codeBook) + break; + + + /* we can merge. update tables, side info bits will be updated outside of this loop */ + huffsection[mergeStart].sfbCnt++; + huffsection[mergeStart].sectionBits += huffsection[mergeEnd].sectionBits; + + /* update bit look up for all code books */ + FDKaacEnc_mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + /* add side info info bits */ + huffsection[mergeStart].sectionBits += FDKaacEnc_getSideInfoBits(&huffsection[mergeStart], sideInfoTab, useVCB11); + huffsection[mergeEnd - 1].sfbStart = huffsection[mergeStart].sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + } while (mergeStart < maxSfb); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible + */ +static void +FDKaacEnc_gmStage2( + SECTION_INFO* const RESTRICT huffsection, + INT* const RESTRICT mergeGainLookUp, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const INT maxSfb, + const SHORT* const sideInfoTab, + const INT useVCB11 + ) +{ + INT i; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) + { + mergeGainLookUp[i] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + i, + i + huffsection[i].sfbCnt, + useVCB11); + } + + while (TRUE) + { + INT maxMergeGain, maxNdx = 0, maxNdxNext, maxNdxLast; + + maxMergeGain = FDKaacEnc_findMaxMerge(mergeGainLookUp, huffsection, maxSfb, &maxNdx); + + /* exit while loop if no more gain is possible */ + if (maxMergeGain <= 0) + break; + + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + /* merge sections with maximum bit gain */ + huffsection[maxNdx].sfbCnt += huffsection[maxNdxNext].sfbCnt; + huffsection[maxNdx].sectionBits += huffsection[maxNdxNext].sectionBits - maxMergeGain; + + /* update bit look up table for merged huffsection */ + FDKaacEnc_mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]); + + /* update mergeLookUpTable */ + if (maxNdx != 0) + { + maxNdxLast = huffsection[maxNdx - 1].sfbStart; + mergeGainLookUp[maxNdxLast] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + maxNdxLast, + maxNdx, + useVCB11); + + } + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + huffsection[maxNdxNext - 1].sfbStart = huffsection[maxNdx].sfbStart; + + if (maxNdxNext < maxSfb) + mergeGainLookUp[maxNdx] = FDKaacEnc_CalcMergeGain(huffsection, + bitLookUp, + sideInfoTab, + maxNdx, + maxNdxNext, + useVCB11); + + } +} + +/* count bits used by the noiseless coder */ +static void FDKaacEnc_noiselessCounter( + SECTION_DATA* const RESTRICT sectionData, + INT mergeGainLookUp[MAX_SFB_LONG], + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const sfbOffset, + const INT blockType, + const INT* const noiseNrg, + const INT* const isBook, + const INT useVCB11 + ) +{ + INT grpNdx, i; + const SHORT *sideInfoTab = NULL; + SECTION_INFO *huffsection; + + /* use appropriate side info table */ + switch (blockType) + { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabLong; + break; + case SHORT_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabShort; + break; + } + + FDK_ASSERT(sideInfoTab != NULL); + + sectionData->noOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + + if (sectionData->maxSfbPerGroup == 0) + return; + + /* loop trough groups */ + for (grpNdx = 0; grpNdx < sectionData->sfbCnt; grpNdx += sectionData->sfbPerGroup) + { + huffsection = sectionData->huffsection + sectionData->noOfSections; + + /* count bits in this group */ + FDKaacEnc_buildBitLookUp(quantSpectrum, + sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, + maxValueInSfb + grpNdx, + bitLookUp, + huffsection); + + /* 0.Stage :Find minimum Codebooks */ + FDKaacEnc_gmStage0(huffsection, bitLookUp, sectionData->maxSfbPerGroup, noiseNrg+grpNdx, isBook+grpNdx); + + /* 1.Stage :Merge all connected regions with the same code book */ + FDKaacEnc_gmStage1(huffsection, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab, useVCB11); + + + /* + 2.Stage + greedy merge algorithm, merge connected huffsections with maximum bit + gain until no more gain is possible + */ + + FDKaacEnc_gmStage2(huffsection, + mergeGainLookUp, + bitLookUp, + sectionData->maxSfbPerGroup, + sideInfoTab, + useVCB11); + + + + /* + compress output, calculate total huff and side bits + since we did not update the actual codebook in stage 2 + to save time, we must set it here for later use in bitenc + */ + + for (i = 0; i < sectionData->maxSfbPerGroup; i += huffsection[i].sfbCnt) + { + if ((huffsection[i].codeBook==CODE_BOOK_PNS_NO) || + (huffsection[i].codeBook==CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[i].codeBook==CODE_BOOK_IS_IN_PHASE_NO)) + { + huffsection[i].sectionBits=0; + } else { + /* the sections in the sectionData are now marked with the optimal code book */ + + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), useVCB11); + + sectionData->huffmanBits += huffsection[i].sectionBits - FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + } + + huffsection[i].sfbStart += grpNdx; + + /* sum up side info bits (section data bits) */ + sectionData->sideInfoBits += FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + sectionData->huffsection[sectionData->noOfSections++] = huffsection[i]; + } + } +} + + +/******************************************************************************* + + functionname: FDKaacEnc_scfCount + returns : --- + description : count bits used by scalefactors. + + not in all cases if maxValueInSfb[] == 0 we set deltaScf + to zero. only if the difference of the last and future + scalefacGain is not greater then CODE_BOOK_SCF_LAV (60). + + example: + ^ + scalefacGain | + | + | last 75 + | | + | | + | | + | | current 50 + | | | + | | | + | | | + | | | + | | | future 5 + | | | | + --- ... ---------------------------- ... ---------> + sfb + + + if maxValueInSfb[] of current is zero because of a + notfallstrategie, we do not save bits and transmit a + deltaScf of 25. otherwise the deltaScf between the last + scalfacGain (75) and the future scalefacGain (5) is 70. + +********************************************************************************/ +static void FDKaacEnc_scfCount( + const INT* const scalefacGain, + const UINT* const maxValueInSfb, + SECTION_DATA* const RESTRICT sectionData, + const INT* const isScale + ) +{ + INT i, j, k, m, n; + + INT lastValScf = 0; + INT deltaScf = 0; + INT found = 0; + INT scfSkipCounter = 0; + INT lastValIs = 0; + + sectionData->scalefacBits = 0; + + if (scalefacGain == NULL) + return; + + sectionData->firstScf = 0; + + for (i=0; inoOfSections; i++) + { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) + { + sectionData->firstScf = sectionData->huffsection[i].sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + } + } + + for (i=0; inoOfSections; i++) + { + if ((sectionData->huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) + { + for (j = sectionData->huffsection[i].sfbStart; + j < sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt; + j++) + { + INT deltaIs = isScale[j]-lastValIs; + lastValIs = isScale[j]; + sectionData->scalefacBits+=FDKaacEnc_bitCountScalefactorDelta(deltaIs); + } + } /* Intensity */ + else if ((sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO)) + { + INT tmp = sectionData->huffsection[i].sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; jnoOfSections) && (found == 0); m++) + { + if ((sectionData->huffsection[m].codeBook != CODE_BOOK_ZERO_NO) && (sectionData->huffsection[m].codeBook != CODE_BOOK_PNS_NO)) + { + INT end = sectionData->huffsection[m].sfbStart + sectionData->huffsection[m].sfbCnt; + for (n = sectionData->huffsection[m].sfbStart; nscalefacBits += FDKaacEnc_bitCountScalefactorDelta(deltaScf); + } + } + } /* for (i=0; inoOfSections; i++) */ +} + +#ifdef PNS_PRECOUNT_ENABLE +/* + preCount bits used pns +*/ +/* estimate bits used by pns for correction of static bits */ +/* no codebook switch estimation, see AAC LD FASTENC */ +INT noisePreCount(const INT *noiseNrg, INT maxSfb) +{ + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, bits=0; + + for (i = 0; i < maxSfb; i++) { + if (noiseNrg[i] != NO_NOISE_PNS) { + + if (noisePCMFlag) { + bits+=PNS_PCM_BITS; + lastValPns = noiseNrg[i]; + noisePCMFlag = FALSE; + }else { + deltaPns = noiseNrg[i]-lastValPns; + lastValPns = noiseNrg[i]; + bits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + return ( bits ); +} +#endif /* PNS_PRECOUNT_ENABLE */ + +/* count bits used by pns */ +static void FDKaacEnc_noiseCount( + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg + ) +{ + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, j; + + sectionData->noiseNrgBits = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + int sfbStart = sectionData->huffsection[i].sfbStart; + int sfbEnd = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j=sfbStart; jnoiseNrgBits+=PNS_PCM_BITS; + lastValPns = noiseNrg[j]; + noisePCMFlag = FALSE; + } else { + deltaPns = noiseNrg[j]-lastValPns; + lastValPns = noiseNrg[j]; + sectionData->noiseNrgBits+=FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + } +} + +INT FDKaacEnc_dynBitCount( + BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, + const INT blockType, + const INT sfbCnt, + const INT maxSfbPerGroup, + const INT sfbPerGroup, + const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, + const INT* const isBook, + const INT* const isScale, + const UINT syntaxFlags + ) +{ + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + sectionData->noOfGroups = sfbCnt / sfbPerGroup; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + FDKaacEnc_noiselessCounter( + sectionData, + hBC->mergeGainLookUp, + (lookUpTable)hBC->bitLookUp, + quantSpectrum, + maxValueInSfb, + sfbOffset, + blockType, + noiseNrg, + isBook, + (syntaxFlags & AC_ER_VCB11)?1:0); + + FDKaacEnc_scfCount( + scalefac, + maxValueInSfb, + sectionData, + isScale); + + FDKaacEnc_noiseCount(sectionData, + noiseNrg); + + return (sectionData->huffmanBits + + sectionData->sideInfoBits + + sectionData->scalefacBits + + sectionData->noiseNrgBits); +} + +INT FDKaacEnc_BCNew(BITCNTR_STATE **phBC + ,UCHAR* dynamic_RAM + ) +{ + BITCNTR_STATE *hBC = GetRam_aacEnc_BitCntrState(); + + if (hBC) + { + *phBC = hBC; + hBC->bitLookUp = GetRam_aacEnc_BitLookUp(0,dynamic_RAM); + hBC->mergeGainLookUp = GetRam_aacEnc_MergeGainLookUp(0,dynamic_RAM); + if (hBC->bitLookUp == 0 || + hBC->mergeGainLookUp == 0) + { + return 1; + } + } + return (hBC == 0) ? 1 : 0; +} + +void FDKaacEnc_BCClose(BITCNTR_STATE **phBC) +{ + if (*phBC!=NULL) { + + FreeRam_aacEnc_BitCntrState(phBC); + } +} + + + diff --git a/libAACenc/src/dyn_bits.h b/libAACenc/src/dyn_bits.h new file mode 100644 index 00000000..ae78a4cc --- /dev/null +++ b/libAACenc/src/dyn_bits.h @@ -0,0 +1,167 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Noiseless coder module + +******************************************************************************/ + +#ifndef __DYN_BITS_H +#define __DYN_BITS_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" + +#define MAX_SECTIONS MAX_GROUPED_SFB +#define SECT_ESC_VAL_LONG 31 +#define SECT_ESC_VAL_SHORT 7 +#define CODE_BOOK_BITS 4 +#define SECT_BITS_LONG 5 +#define SECT_BITS_SHORT 3 +#define PNS_PCM_BITS 9 + +typedef struct +{ + INT codeBook; + INT sfbStart; + INT sfbCnt; + INT sectionBits; /* huff + si ! */ +} SECTION_INFO; + + +typedef struct +{ + INT blockType; + INT noOfGroups; + INT sfbCnt; + INT maxSfbPerGroup; + INT sfbPerGroup; + INT noOfSections; + SECTION_INFO huffsection[MAX_SECTIONS]; + INT sideInfoBits; /* sectioning bits */ + INT huffmanBits; /* huffman coded bits */ + INT scalefacBits; /* scalefac coded bits */ + INT noiseNrgBits; /* noiseEnergy coded bits */ + INT firstScf; /* first scf to be coded */ +} SECTION_DATA; + + +struct BITCNTR_STATE +{ + INT *bitLookUp; + INT *mergeGainLookUp; +}; + + +INT FDKaacEnc_BCNew(BITCNTR_STATE **phBC + ,UCHAR* dynamic_RAM + ); + +void FDKaacEnc_BCClose(BITCNTR_STATE **phBC); + +#if defined(PNS_PRECOUNT_ENABLE) +INT noisePreCount(const INT *noiseNrg, INT maxSfb); +#endif + +INT FDKaacEnc_dynBitCount( + BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, + const INT blockType, + const INT sfbCnt, + const INT maxSfbPerGroup, + const INT sfbPerGroup, + const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, + const INT* const isBook, + const INT* const isScale, + const UINT syntaxFlags + ); + +#endif diff --git a/libAACenc/src/grp_data.cpp b/libAACenc/src/grp_data.cpp new file mode 100644 index 00000000..465865f1 --- /dev/null +++ b/libAACenc/src/grp_data.cpp @@ -0,0 +1,272 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Short block grouping + +******************************************************************************/ +#include "psy_const.h" +#include "interface.h" + +/* +* this routine does not work in-place +*/ + +static inline FIXP_DBL nrgAddSaturate(const FIXP_DBL a, const FIXP_DBL b) { + return ( (a>=(FIXP_DBL)MAXVAL_DBL-b) ? (FIXP_DBL)MAXVAL_DBL : (a + b) ); +} + +void +FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, + const INT sfbCnt, + const INT sfbActive, + const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, /* out */ + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, + const INT *groupLen, + const INT granuleLength) +{ + INT i,j; + INT line; /* counts through lines */ + INT sfb; /* counts through scalefactor bands */ + INT grp; /* counts through groups */ + INT wnd; /* counts through windows in a group */ + INT offset; /* needed in sfbOffset grouping */ + INT highestSfb; + + INT granuleLength_short = granuleLength/TRANS_FAC; + + /* for short blocks: regroup spectrum and */ + /* group energies and thresholds according to grouping */ + C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024)); + + /* calculate maxSfbPerGroup */ + highestSfb = 0; + for (wnd = 0; wnd < TRANS_FAC; wnd++) + { + for (sfb = sfbActive-1; sfb >= highestSfb; sfb--) + { + for (line = sfbOffset[sfb+1]-1; line >= sfbOffset[sfb]; line--) + { + if ( mdctSpectrum[wnd*granuleLength_short+line] != FL2FXCONST_SPC(0.0) ) break; /* this band is not completely zero */ + } + if (line >= sfbOffset[sfb]) break; /* this band was not completely zero */ + } + highestSfb = fixMax(highestSfb, sfb); + } + highestSfb = highestSfb > 0 ? highestSfb : 0; + *maxSfbPerGroup = highestSfb+1; + + /* calculate groupedSfbOffset */ + i = 0; + offset = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive+1; sfb++) + { + groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp]; + } + i += sfbCnt-sfb; + offset += groupLen[grp] * granuleLength_short; + } + groupedSfbOffset[i++] = granuleLength; + + /* calculate groupedSfbMinSnr */ + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb]; + } + i += sfbCnt-sfb; + } + + /* sum up sfbThresholds */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb]; + for (j=1; jShort[wnd+j][sfb]); + } + sfbThreshold->Long[i++] = thresh; + } + i += sfbCnt-sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies left/right */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + FIXP_DBL energy = sfbEnergy->Short[wnd][sfb]; + for (j=1; jShort[wnd+j][sfb]); + } + sfbEnergy->Long[i++] = energy; + } + i += sfbCnt-sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies mid/side */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb]; + for (j=1; jShort[wnd+j][sfb]); + } + sfbEnergyMS->Long[i++] = energy; + } + i += sfbCnt-sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbSpreadEnergies */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb]; + for (j=1; jShort[wnd+j][sfb]); + } + sfbSpreadEnergy->Long[i++] = energy; + } + i += sfbCnt-sfb; + wnd += groupLen[grp]; + } + + /* re-group spectrum */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) + { + for (sfb = 0; sfb < sfbActive; sfb++) + { + int width = sfbOffset[sfb+1]-sfbOffset[sfb]; + FIXP_DBL *pMdctSpectrum = &mdctSpectrum[sfbOffset[sfb]] + wnd*granuleLength_short; + for (j = 0; j < groupLen[grp]; j++) + { + FIXP_DBL *pTmp = pMdctSpectrum; + for (line = width; line > 0; line--) + { + tmpSpectrum[i++] = *pTmp++; + } + pMdctSpectrum += granuleLength_short; + } + } + i += (groupLen[grp]*(sfbOffset[sfbCnt]-sfbOffset[sfb])); + wnd += groupLen[grp]; + } + + FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength*sizeof(FIXP_DBL)); + + C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024)) +} diff --git a/libAACenc/src/grp_data.h b/libAACenc/src/grp_data.h new file mode 100644 index 00000000..f061855f --- /dev/null +++ b/libAACenc/src/grp_data.h @@ -0,0 +1,115 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Short block grouping + +******************************************************************************/ +#ifndef __GRP_DATA_H__ +#define __GRP_DATA_H__ + +#include "common_fix.h" + +#include "psy_data.h" + + +void +FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, + const INT sfbCnt, + const INT sfbActive, + const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, + const INT *groupLen, + const INT granuleLength); + +#endif /* _INTERFACE_H */ diff --git a/libAACenc/src/intensity.cpp b/libAACenc/src/intensity.cpp new file mode 100644 index 00000000..b45b27b5 --- /dev/null +++ b/libAACenc/src/intensity.cpp @@ -0,0 +1,760 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK) + contents/description: intensity stereo processing + +******************************************************************************/ + +#include "intensity.h" +#include "interface.h" +#include "psy_configuration.h" +#include "psy_const.h" +#include "qc_main.h" +#include "bit_cnt.h" + +/* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH */ +#define IS_CORR_THRESH FL2FXCONST_DBL(0.95f) + +/* when expanding the IS region to more SFBs only accept an error that is + * not more than IS_TOTAL_ERROR_THRESH overall and + * not more than IS_LOCAL_ERROR_THRESH for the current SFB */ +#define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f) +#define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f) + +/* the maximum allowed change of the intensity direction (unit: IS scale) - scaled with factor 0.25 - */ +#define IS_DIRECTION_DEVIATION_THRESH_SF 2 +#define IS_DIRECTION_DEVIATION_THRESH FL2FXCONST_DBL(2.0f/(1< no IS if the panning angle is not far from the middle, MS will do */ +/* this is equivalent to a scale of +/-1.02914634566 */ +#define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f) + +/* scalefactor of realScale */ +#define REAL_SCALE_SF 1 + +/* scalefactor overallLoudness */ +#define OVERALL_LOUDNESS_SF 6 + +/* scalefactor for sum over max samples per goup */ +#define MAX_SFB_PER_GROUP_SF 6 + +/* scalefactor for sum of mdct spectrum */ +#define MDCT_SPEC_SF 6 + + +typedef struct +{ + + FIXP_DBL corr_thresh; /*!< Only set an IS seed it left/right channel correlation is above corr_thresh */ + + FIXP_DBL total_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is + not more than 'total_error_thresh' overall. */ + + FIXP_DBL local_error_thresh; /*!< When expanding the IS region to more SFBs only accept an error that is + not more than 'local_error_thresh' for the current SFB. */ + + FIXP_DBL direction_deviation_thresh; /*!< The maximum allowed change of the intensity direction (unit: IS scale) */ + + FIXP_DBL is_region_min_loudness; /*!< IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */ + + INT min_is_sfbs; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be processed */ + + FIXP_DBL left_right_ratio_threshold; /*!< No IS if the panning angle is not far from the middle, MS will do */ + +} INTENSITY_PARAMETERS; + + +/***************************************************************************** + + functionname: calcSfbMaxScale + + description: Calc max value in scalefactor band + + input: *mdctSpectrum + l1 + l2 + + output: none + + returns: scalefactor + +*****************************************************************************/ +static INT +calcSfbMaxScale(const FIXP_DBL *mdctSpectrum, + const INT l1, + const INT l2) +{ + INT i; + INT sfbMaxScale; + FIXP_DBL maxSpc; + + maxSpc = FL2FXCONST_DBL(0.0); + for (i=l1; icorr_thresh = IS_CORR_THRESH; + isParams->total_error_thresh = IS_TOTAL_ERROR_THRESH; + isParams->local_error_thresh = IS_LOCAL_ERROR_THRESH; + isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH; + isParams->is_region_min_loudness = IS_REGION_MIN_LOUDNESS; + isParams->min_is_sfbs = IS_MIN_SFBS; + isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH; +} + + +/***************************************************************************** + + functionname: FDKaacEnc_prepareIntensityDecision + + description: Prepares intensity decision + + input: sfbEnergyLeft + sfbEnergyRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + mdctSpectrumLeft + sfbEnergyLdDataRight + isParams + + output: hrrErr scale: none + isMask scale: none + realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + returns: none + +*****************************************************************************/ +static void +FDKaacEnc_prepareIntensityDecision(const FIXP_DBL *sfbEnergyLeft, + const FIXP_DBL *sfbEnergyRight, + const FIXP_DBL *sfbEnergyLdDataLeft, + const FIXP_DBL *sfbEnergyLdDataRight, + const FIXP_DBL *mdctSpectrumLeft, + const FIXP_DBL *mdctSpectrumRight, + const INTENSITY_PARAMETERS *isParams, + FIXP_DBL *hrrErr, + INT *isMask, + FIXP_DBL *realScale, + FIXP_DBL *normSfbLoudness, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset) +{ + INT j,sfb,sfboffs; + INT grpCounter; + + /* temporary variables to compute loudness */ + FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS]; + + /* temporary variables to compute correlation */ + FIXP_DBL channelCorr[MAX_GROUPED_SFB]; + FIXP_DBL ml, mr; + FIXP_DBL prod_lr; + FIXP_DBL square_l, square_r; + FIXP_DBL tmp_l, tmp_r; + FIXP_DBL inv_n; + + FDKmemclear(channelCorr, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); + FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); + FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS*sizeof(FIXP_DBL)); + FDKmemclear(realScale, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) { + overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f); + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT sL,sR,s; + FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb+sfboffs]-sfbEnergyLdDataRight[sfb+sfboffs]; + + /* delimitate intensity scale value to representable range */ + realScale[sfb + sfboffs] = fixMin(FL2FXCONST_DBL(60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), fixMax(FL2FXCONST_DBL(-60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), isValue)); + + sL = fixMax(0,(CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs])-1)); + sR = fixMax(0,(CntLeadingZeros(sfbEnergyRight[sfb + sfboffs])-1)); + s = (fixMin(sL,sR)>>2)<<2; + normSfbLoudness[sfb + sfboffs] = sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs]<> 1) + ((sfbEnergyRight[sfb + sfboffs]<> 1))) >> (s>>2); + + overallLoudness[grpCounter] += normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF; + /* don't do intensity if + * - panning angle is too close to the middle or + * - one channel is non-existent or + * - if it is dual mono */ + if( (sfbEnergyLeft[sfb + sfboffs] >= fMult(isParams->left_right_ratio_threshold,sfbEnergyRight[sfb + sfboffs])) + && (fMult(isParams->left_right_ratio_threshold,sfbEnergyLeft[sfb + sfboffs]) <= sfbEnergyRight[sfb + sfboffs]) ) { + + /* this will prevent post processing from considering this SFB for merging */ + hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0/8.0); + } + } + } + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) { + INT invOverallLoudnessSF; + FIXP_DBL invOverallLoudness; + + if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) { + invOverallLoudness = FL2FXCONST_DBL(0.0); + invOverallLoudnessSF = 0; + } + else { + invOverallLoudness = fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter],&invOverallLoudnessSF); + invOverallLoudnessSF = invOverallLoudnessSF - OVERALL_LOUDNESS_SF + 1; /* +1: compensate fMultDiv2() in subsequent loop */ + } + invOverallLoudnessSF = fixMin(fixMax(invOverallLoudnessSF,-(DFRACT_BITS-1)),DFRACT_BITS-1); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + FIXP_DBL tmp; + + tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs]>>OVERALL_LOUDNESS_SF)<>1); + + if (inv_n > FL2FXCONST_DBL(0.0f)) { + INT s,sL,sR; + + /* correlation := Pearson's product-moment coefficient */ + /* compute correlation between channels and check if it is over threshold */ + ml = FL2FXCONST_DBL(0.0f); + mr = FL2FXCONST_DBL(0.0f); + prod_lr = FL2FXCONST_DBL(0.0f); + square_l = FL2FXCONST_DBL(0.0f); + square_r = FL2FXCONST_DBL(0.0f); + + sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]); + sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]); + s = fixMin(sL,sR); + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) { + ml += fMultDiv2((mdctSpectrumLeft[j] << s),inv_n); // scaled with mdctScale - s + inv_n + mr += fMultDiv2((mdctSpectrumRight[j] << s),inv_n); // scaled with mdctScale - s + inv_n + } + ml = fMultDiv2(ml,inv_n); // scaled with mdctScale - s + inv_n + mr = fMultDiv2(mr,inv_n); // scaled with mdctScale - s + inv_n + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) { + tmp_l = fMultDiv2((mdctSpectrumLeft[j] << s),inv_n) - ml; // scaled with mdctScale - s + inv_n + tmp_r = fMultDiv2((mdctSpectrumRight[j] << s),inv_n) - mr; // scaled with mdctScale - s + inv_n + + prod_lr += fMultDiv2(tmp_l,tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_l += fPow2Div2(tmp_l); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_r += fPow2Div2(tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + } + prod_lr = prod_lr << 1; // scaled with 2*(mdctScale - s + inv_n) + square_l = square_l << 1; // scaled with 2*(mdctScale - s + inv_n) + square_r = square_r << 1; // scaled with 2*(mdctScale - s + inv_n) + + if (square_l > FL2FXCONST_DBL(0.0f) && square_r > FL2FXCONST_DBL(0.0f)) { + INT channelCorrSF = 0; + + /* local scaling of square_l and square_r is compensated after sqrt calculation */ + sL = fixMax(0,(CntLeadingZeros(square_l)-1)); + sR = fixMax(0,(CntLeadingZeros(square_r)-1)); + s = ((sL + sR)>>1)<<1; + sL = fixMin(sL,s); + sR = s-sL; + tmp = fMult(square_l< FL2FXCONST_DBL(0.0f)); + + /* numerator and denominator have the same scaling */ + if (prod_lr < FL2FXCONST_DBL(0.0f) ) { + channelCorr[sfb + sfboffs] = -(fDivNorm(-prod_lr,tmp,&channelCorrSF)); + + } + else { + channelCorr[sfb + sfboffs] = (fDivNorm( prod_lr,tmp,&channelCorrSF)); + } + channelCorrSF = fixMin(fixMax(( channelCorrSF + ((sL+sR)>>1)),-(DFRACT_BITS-1)),DFRACT_BITS-1); + + if (channelCorrSF < 0) { + channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] >> (-channelCorrSF); + } + else { + /* avoid overflows due to limited computational accuracy */ + if ( fAbs(channelCorr[sfb + sfboffs]) > (((FIXP_DBL)MAXVAL_DBL)>>channelCorrSF) ) { + if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f)) + channelCorr[sfb + sfboffs] = -(FIXP_DBL) MAXVAL_DBL; + else + channelCorr[sfb + sfboffs] = (FIXP_DBL) MAXVAL_DBL; + } + else { + channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] << channelCorrSF; + } + } + } + } + + /* for post processing: hrrErr is the error in terms of (too little) correlation + * weighted with the loudness of the SFB; SFBs with small hrrErr can be merged */ + if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0/8.0)) { + continue; + } + + hrrErr[sfb + sfboffs] = fMultDiv2((FL2FXCONST_DBL(0.25f)-(channelCorr[sfb + sfboffs]>>2)),normSfbLoudness[sfb + sfboffs]); + + /* set IS mask/vector to 1, if correlation is high enough */ + if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) { + isMask[sfb + sfboffs] = 1; + } + } + } +} + + +/***************************************************************************** + + functionname: FDKaacEnc_finalizeIntensityDecision + + description: Finalizes intensity decision + + input: isParams scale: none + hrrErr scale: none + realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + output: isMask scale: none + + returns: none + +*****************************************************************************/ +static void +FDKaacEnc_finalizeIntensityDecision(const FIXP_DBL *hrrErr, + INT *isMask, + const FIXP_DBL *realIsScale, + const FIXP_DBL *normSfbLoudness, + const INTENSITY_PARAMETERS *isParams, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup) +{ + INT sfb,sfboffs, j; + FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f); + INT isStartValueFound = 0; + + for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) { + INT startIsSfb = 0; + INT inIsBlock = 0; + INT currentIsSfbCount = 0; + FIXP_DBL overallHrrError = FL2FXCONST_DBL(0.0f); + FIXP_DBL isRegionLoudness = FL2FXCONST_DBL(0.0f); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + if (isMask[sfboffs + sfb] == 1) { + if (currentIsSfbCount == 0) { + startIsSfb = sfboffs + sfb; + } + if (isStartValueFound==0) { + isScaleLast = realIsScale[sfboffs + sfb]; + isStartValueFound = 1; + } + inIsBlock = 1; + currentIsSfbCount++; + overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3); + isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + } + else { + /* based on correlation, IS should not be used + * -> use it anyway, if overall error is below threshold + * and if local error does not exceed threshold + * otherwise: check if there are enough IS SFBs + */ + if (inIsBlock) { + overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3); + isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + + if ( (hrrErr[sfboffs + sfb] < (isParams->local_error_thresh>>3)) && (overallHrrError < (isParams->total_error_thresh>>MAX_SFB_PER_GROUP_SF)) ) { + currentIsSfbCount++; + /* overwrite correlation based decision */ + isMask[sfboffs + sfb] = 1; + } else { + inIsBlock = 0; + } + } + } + /* check for large direction deviation */ + if (inIsBlock) { + if( fAbs(isScaleLast-realIsScale[sfboffs + sfb]) < (isParams->direction_deviation_thresh>>(REAL_SCALE_SF+LD_DATA_SHIFT-IS_DIRECTION_DEVIATION_THRESH_SF)) ) { + isScaleLast = realIsScale[sfboffs + sfb]; + } + else{ + isMask[sfboffs + sfb] = 0; + inIsBlock = 0; + currentIsSfbCount--; + } + } + + if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) { + /* not enough SFBs -> do not use IS */ + if (currentIsSfbCount < isParams->min_is_sfbs || (isRegionLoudness < isParams->is_region_min_loudness>>MAX_SFB_PER_GROUP_SF)) { + for(j = startIsSfb; j <= sfboffs + sfb; j++) { + isMask[j] = 0; + } + isScaleLast = FL2FXCONST_DBL(0.0f); + isStartValueFound = 0; + for (j=0; j < startIsSfb; j++) { + if (isMask[j]!=0) { + isScaleLast = realIsScale[j]; + isStartValueFound = 1; + } + } + } + currentIsSfbCount = 0; + overallHrrError = FL2FXCONST_DBL(0.0f); + isRegionLoudness = FL2FXCONST_DBL(0.0f); + } + } + } +} + + +/***************************************************************************** + + functionname: FDKaacEnc_IntensityStereoProcessing + + description: Intensity stereo processing tool + + input: sfbEnergyLeft + sfbEnergyRight + mdctSpectrumLeft + mdctSpectrumRight + sfbThresholdLeft + sfbThresholdRight + sfbSpreadEnLeft + sfbSpreadEnRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + + output: isBook + isScale + pnsData->pnsFlag + msDigest zeroed from start to sfbCnt + msMask zeroed from start to sfbCnt + mdctSpectrumRight zeroed where isBook!=0 + sfbEnergyRight zeroed where isBook!=0 + sfbSpreadEnRight zeroed where isBook!=0 + sfbThresholdRight zeroed where isBook!=0 + sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0 + sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where isBook!=0 + + returns: none + +*****************************************************************************/ +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, + FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, + FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, + FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, + FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, + FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, + INT *msDigest, + INT *msMask, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset, + const INT allowIS, + INT *isBook, + INT *isScale, + PNS_DATA *RESTRICT pnsData[2] + ) +{ + INT sfb,sfboffs, j; + FIXP_DBL scale; + FIXP_DBL lr; + FIXP_DBL hrrErr[MAX_GROUPED_SFB]; + FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB]; + FIXP_DBL realIsScale[MAX_GROUPED_SFB]; + INTENSITY_PARAMETERS isParams; + INT isMask[MAX_GROUPED_SFB]; + + FDKmemclear((void*)isBook,sfbCnt*sizeof(INT)); + FDKmemclear((void*)isMask,sfbCnt*sizeof(INT)); + FDKmemclear((void*)realIsScale,sfbCnt*sizeof(FIXP_DBL)); + FDKmemclear((void*)isScale,sfbCnt*sizeof(INT)); + FDKmemclear((void*)hrrErr,sfbCnt*sizeof(FIXP_DBL)); + + if (!allowIS) + return; + + FDKaacEnc_initIsParams(&isParams); + + /* compute / set the following values per SFB: + * - left/right ratio between channels + * - normalized loudness + * + loudness == average of energy in channels to 0.25 + * + normalization: division by sum of all SFB loudnesses + * - isMask (is set to 0 if channels are the same or one is 0) + */ + FDKaacEnc_prepareIntensityDecision(sfbEnergyLeft, + sfbEnergyRight, + sfbEnergyLdDataLeft, + sfbEnergyLdDataRight, + mdctSpectrumLeft, + mdctSpectrumRight, + &isParams, + hrrErr, + isMask, + realIsScale, + normSfbLoudness, + sfbCnt, + sfbPerGroup, + maxSfbPerGroup, + sfbOffset); + + FDKaacEnc_finalizeIntensityDecision(hrrErr, + isMask, + realIsScale, + normSfbLoudness, + &isParams, + sfbCnt, + sfbPerGroup, + maxSfbPerGroup); + + for (sfb=0; sfb sfbThresholdRight[sfb+sfboffs]) ) { + continue; + } + /* NEW: if there is a big-enough IS region, switch off PNS */ + if (pnsData[0]) { + if(pnsData[0]->pnsFlag[sfb+sfboffs]) { + pnsData[0]->pnsFlag[sfb+sfboffs] = 0; + } + if(pnsData[1]->pnsFlag[sfb+sfboffs]) { + pnsData[1]->pnsFlag[sfb+sfboffs] = 0; + } + } + + inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1); // scaled with 2 to compensate fMultDiv2() in subsequent loop + sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]); + sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]); + + lr = FL2FXCONST_DBL(0.0f); + for (j=sfbOffset[sfb+sfboffs]; j>1) - ((mdctSpectrumRight[j]<>1); + ed += fMultDiv2(d,d)>>(MDCT_SPEC_SF-1); + } + msMask[sfb+sfboffs] = 1; + tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],ed,&s1); + s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF; + if (s2 & 1) { + tmp = tmp>>1; + s2 = s2+1; + } + s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j=sfbOffset[sfb+sfboffs]; j> s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + else { + for (j=sfbOffset[sfb+sfboffs]; j>1) + ((mdctSpectrumRight[j]<>1); + es += fMultDiv2(s,s)>>(MDCT_SPEC_SF-1); // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF + } + msMask[sfb+sfboffs] = 0; + tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],es,&s1); + s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF; + if (s2 & 1) { + tmp = tmp>>1; + s2 = s2 + 1; + } + s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j=sfbOffset[sfb+sfboffs]; j> s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + else { + for (j=sfbOffset[sfb+sfboffs]; j>1)-FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1)) + 1; + } + else { + isScale[sfb+sfboffs] = (INT)(((realIsScale[sfb+sfboffs]>>1)+FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1)); + } + + sfbEnergyRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f); + sfbEnergyLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-1.0f); + sfbThresholdRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f); + sfbThresholdLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-0.515625f); + sfbSpreadEnRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f); + + *msDigest = MS_SOME; + } + } +} + diff --git a/libAACenc/src/intensity.h b/libAACenc/src/intensity.h new file mode 100644 index 00000000..2acc2920 --- /dev/null +++ b/libAACenc/src/intensity.h @@ -0,0 +1,122 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: A. Horndasch (code originally from lwr and rtb) / Josef Höpfl (FDK) + contents/description: intensity stereo prototype + +******************************************************************************/ + +#ifndef _INTENSITY_H +#define _INTENSITY_H + +#include "aacenc_pns.h" + + +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, + FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, + FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, + FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, + FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, + FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, + INT *msDigest, + INT *msMask, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset, + const INT allowIS, + INT *isBook, + INT *isScale, + PNS_DATA *RESTRICT pnsData[2] + ); + +#endif /* _INTENSITY_H */ + diff --git a/libAACenc/src/interface.h b/libAACenc/src/interface.h new file mode 100644 index 00000000..51fb72aa --- /dev/null +++ b/libAACenc/src/interface.h @@ -0,0 +1,169 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Interface psychoaccoustic/quantizer + +******************************************************************************/ + +#ifndef _INTERFACE_H +#define _INTERFACE_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "psy_data.h" +#include "aacenc_tns.h" + +enum +{ + MS_NONE = 0, + MS_SOME = 1, + MS_ALL = 2 +}; + +enum +{ + MS_ON = 1 +}; + +struct TOOLSINFO { + INT msDigest; /* 0 = no MS; 1 = some MS, 2 = all MS */ + INT msMask[MAX_GROUPED_SFB]; +}; + + +typedef struct { + INT sfbCnt; + INT sfbPerGroup; + INT maxSfbPerGroup; + INT lastWindowSequence; + INT windowShape; + INT groupingMask; + INT sfbOffsets[MAX_GROUPED_SFB+1]; + + INT mdctScale; /* number of transform shifts */ + INT groupLen[MAX_NO_OF_GROUPS]; + + TNS_INFO tnsInfo; + INT noiseNrg[MAX_GROUPED_SFB]; + INT isBook[MAX_GROUPED_SFB]; + INT isScale[MAX_GROUPED_SFB]; + + /* memory located in QC_OUT_CHANNEL */ + FIXP_DBL *mdctSpectrum; + FIXP_DBL *sfbEnergy; + FIXP_DBL *sfbSpreadEnergy; + FIXP_DBL *sfbThresholdLdData; + FIXP_DBL *sfbMinSnrLdData; + FIXP_DBL *sfbEnergyLdData; + + + }PSY_OUT_CHANNEL; + +typedef struct { + + /* information specific to each channel */ + PSY_OUT_CHANNEL* psyOutChannel[(2)]; + + /* information shared by both channels */ + INT commonWindow; + struct TOOLSINFO toolsInfo; + +} PSY_OUT_ELEMENT; + +typedef struct { + + PSY_OUT_ELEMENT* psyOutElement[(8)]; + PSY_OUT_CHANNEL* pPsyOutChannels[(8)]; + +}PSY_OUT; + +inline int isLowDelay( AUDIO_OBJECT_TYPE aot ) +{ + return (aot==AOT_ER_AAC_LD || aot==AOT_ER_AAC_ELD); +} + +#endif /* _INTERFACE_H */ diff --git a/libAACenc/src/line_pe.cpp b/libAACenc/src/line_pe.cpp new file mode 100644 index 00000000..f3c0dab6 --- /dev/null +++ b/libAACenc/src/line_pe.cpp @@ -0,0 +1,209 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Perceptual entropie module + +******************************************************************************/ + +#include "line_pe.h" +#include "sf_estim.h" +#include "bit_cnt.h" + +#include "genericStds.h" + +static const FIXP_DBL C1LdData = FL2FXCONST_DBL(3.0/LD_DATA_SCALING); /* C1 = 3.0 = log(8.0)/log(2) */ +static const FIXP_DBL C2LdData = FL2FXCONST_DBL(1.3219281/LD_DATA_SCALING); /* C2 = 1.3219281 = log(2.5)/log(2) */ +static const FIXP_DBL C3LdData = FL2FXCONST_DBL(0.5593573); /* 1-C2/C1 */ + + +/* constants that do not change during successive pe calculations */ +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *peChanData, + const FIXP_DBL *sfbEnergyLdData, + const FIXP_DBL *sfbThresholdLdData, + const FIXP_DBL *sfbFormFactorLdData, + const INT *sfbOffset, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup) +{ + INT sfbGrp,sfb; + INT sfbWidth; + FIXP_DBL avgFormFactorLdData; + const FIXP_DBL formFacScaling = FL2FXCONST_DBL((float)FORM_FAC_SHIFT/LD_DATA_SCALING); + + for (sfbGrp = 0;sfbGrp < sfbCnt;sfbGrp+=sfbPerGroup) { + for (sfb=0; sfb (FIXP_DBL)sfbThresholdLdData[sfbGrp+sfb]) { + sfbWidth = sfbOffset[sfbGrp+sfb+1] - sfbOffset[sfbGrp+sfb]; + /* estimate number of active lines */ + avgFormFactorLdData = ((-sfbEnergyLdData[sfbGrp+sfb]>>1) + (CalcLdInt(sfbWidth)>>1))>>1; + peChanData->sfbNLines[sfbGrp+sfb] = + (INT)CalcInvLdData( (sfbFormFactorLdData[sfbGrp+sfb] + formFacScaling) + avgFormFactorLdData); + /* Make sure sfbNLines is never greater than sfbWidth due to unaccuracies (e.g. sfbEnergyLdData[sfbGrp+sfb] = 0x80000000) */ + peChanData->sfbNLines[sfbGrp+sfb] = fMin(sfbWidth, peChanData->sfbNLines[sfbGrp+sfb]); + } + else { + peChanData->sfbNLines[sfbGrp+sfb] = 0; + } + } + } +} + +/* + formula for one sfb: + pe = n * ld(en/thr), if ld(en/thr) >= C1 + pe = n * (C2 + C3 * ld(en/thr)), if ld(en/thr) < C1 + n: estimated number of lines in sfb, + ld(x) = log(x)/log(2) + + constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr) +*/ +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT peChanData, + const FIXP_DBL *RESTRICT sfbEnergyLdData, + const FIXP_DBL *RESTRICT sfbThresholdLdData, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *isBook, + const INT *isScale) +{ + INT sfbGrp,sfb; + INT nLines; + FIXP_DBL logDataRatio; + INT lastValIs = 0; + + peChanData->pe = 0; + peChanData->constPart = 0; + peChanData->nActiveLines = 0; + + for(sfbGrp = 0;sfbGrp < sfbCnt;sfbGrp+=sfbPerGroup){ + for (sfb=0; sfb (FIXP_DBL)sfbThresholdLdData[sfbGrp+sfb]) { + logDataRatio = (FIXP_DBL)(sfbEnergyLdData[sfbGrp+sfb] - sfbThresholdLdData[sfbGrp+sfb]); + nLines = peChanData->sfbNLines[sfbGrp+sfb]; + if (logDataRatio >= C1LdData) { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + peChanData->sfbPe[sfbGrp+sfb] = fMultDiv2(logDataRatio, (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))); + peChanData->sfbConstPart[sfbGrp+sfb] = + fMultDiv2(sfbEnergyLdData[sfbGrp+sfb], (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))); ; + + } + else { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + peChanData->sfbPe[sfbGrp+sfb] = + fMultDiv2(((FIXP_DBL)C2LdData + fMult(C3LdData,logDataRatio)), (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))); + + peChanData->sfbConstPart[sfbGrp+sfb] = + fMultDiv2(((FIXP_DBL)C2LdData + fMult(C3LdData,sfbEnergyLdData[sfbGrp+sfb])), + (FIXP_DBL)(nLines<<(LD_DATA_SHIFT+PE_CONSTPART_SHIFT+1))) ; + + nLines = fMultI(C3LdData, nLines); + } + peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines; + } + else if( isBook[sfbGrp+sfb] ) { + /* provide for cost of scale factor for Intensity */ + INT delta = isScale[sfbGrp+sfb] - lastValIs; + lastValIs = isScale[sfbGrp+sfb]; + peChanData->sfbPe[sfbGrp+sfb] = FDKaacEnc_bitCountScalefactorDelta(delta)<sfbConstPart[sfbGrp+sfb] = 0; + peChanData->sfbNActiveLines[sfbGrp+sfb] = 0; + } + else { + peChanData->sfbPe[sfbGrp+sfb] = 0; + peChanData->sfbConstPart[sfbGrp+sfb] = 0; + peChanData->sfbNActiveLines[sfbGrp+sfb] = 0; + } + /* sum up peChanData values */ + peChanData->pe += peChanData->sfbPe[sfbGrp+sfb]; + peChanData->constPart += peChanData->sfbConstPart[sfbGrp+sfb]; + peChanData->nActiveLines += peChanData->sfbNActiveLines[sfbGrp+sfb]; + } + } + /* correct scaled pe and constPart values */ + peChanData->pe>>=PE_CONSTPART_SHIFT; + peChanData->constPart>>=PE_CONSTPART_SHIFT; +} diff --git a/libAACenc/src/line_pe.h b/libAACenc/src/line_pe.h new file mode 100644 index 00000000..3d5cfd53 --- /dev/null +++ b/libAACenc/src/line_pe.h @@ -0,0 +1,139 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Perceptual entropie module + +******************************************************************************/ +#ifndef __LINE_PE_H +#define __LINE_PE_H + + +#include "common_fix.h" + +#include "psy_const.h" + +#define PE_CONSTPART_SHIFT FRACT_BITS + +typedef struct { + /* calculated by FDKaacEnc_prepareSfbPe */ + INT sfbNLines[MAX_GROUPED_SFB]; /* number of relevant lines in sfb */ + /* the rest is calculated by FDKaacEnc_calcSfbPe */ + INT sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */ + INT sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */ + INT sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */ + INT pe; /* sum of sfbPe */ + INT constPart; /* sum of sfbConstPart */ + INT nActiveLines; /* sum of sfbNActiveLines */ +} PE_CHANNEL_DATA; + +typedef struct { + PE_CHANNEL_DATA peChannelData[(2)]; + INT pe; + INT constPart; + INT nActiveLines; + INT offset; +} PE_DATA; + + +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *peChanData, + const FIXP_DBL *sfbEnergyLdData, + const FIXP_DBL *sfbThresholdLdData, + const FIXP_DBL *sfbFormFactorLdData, + const INT *sfbOffset, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup); + +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT peChanData, + const FIXP_DBL *RESTRICT sfbEnergyLdData, + const FIXP_DBL *RESTRICT sfbThresholdLdData, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *isBook, + const INT *isScale); + +#endif diff --git a/libAACenc/src/metadata_compressor.cpp b/libAACenc/src/metadata_compressor.cpp new file mode 100644 index 00000000..68a64ae7 --- /dev/null +++ b/libAACenc/src/metadata_compressor.cpp @@ -0,0 +1,1038 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/********************** Fraunhofer IIS FDK AAC Encoder lib ****************** + + Author(s): M. Neusinger + Description: Compressor for AAC Metadata Generator + +******************************************************************************/ + + +#include "metadata_compressor.h" +#include "channel_map.h" + + +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2/2)) + +/*----------------- defines ----------------------*/ + +#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */ +#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */ +#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */ + +#define METADATA_INT_BITS 10 +#define METADATA_LINT_BITS 20 +#define METADATA_INT_SCALE (INT64(1)<<(METADATA_INT_BITS)) +#define METADATA_FRACT_BITS (DFRACT_BITS-1-METADATA_INT_BITS) +#define METADATA_FRACT_SCALE (INT64(1)<<(METADATA_FRACT_BITS)) + +/** + * Enum for channel assignment. + */ +enum { + L = 0, + R = 1, + C = 2, + LFE = 3, + LS = 4, + RS = 5, + S = 6, + LS2 = 7, + RS2 = 8 +}; + +/*--------------- structure definitions --------------------*/ + +/** + * Structure holds weighting filter filter states. + */ +struct WEIGHTING_STATES { + FIXP_DBL x1; + FIXP_DBL x2; + FIXP_DBL y1; + FIXP_DBL y2; +}; + +/** + * Dynamic Range Control compressor structure. + */ +struct DRC_COMP { + + FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */ + FIXP_DBL boostThr[2]; /*!< Boost threshold. */ + FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */ + FIXP_DBL cutThr[2]; /*!< Cut threshold. */ + FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */ + + FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */ + FIXP_DBL earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */ + FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */ + + FIXP_DBL maxBoost[2]; /*!< Maximum boost. */ + FIXP_DBL maxCut[2]; /*!< Maximum cut. */ + FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */ + + FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */ + FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */ + FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */ + FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */ + UINT holdOff[2]; /*!< Hold time in blocks. */ + + FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */ + FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */ + + DRC_PROFILE profile[2]; /*!< DRC profile. */ + INT blockLength; /*!< Block length in samples. */ + UINT sampleRate; /*!< Sample rate. */ + CHANNEL_MODE chanConfig; /*!< Channel configuration. */ + + UCHAR useWeighting; /*!< Use weighting filter. */ + + UINT channels; /*!< Number of channels. */ + UINT fullChannels; /*!< Number of full range channels. */ + INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, Ls, Rs, S, Ls2, Rs2). */ + + FIXP_DBL smoothLevel[2]; /*!< level smoothing states */ + FIXP_DBL smoothGain[2]; /*!< gain smoothing states */ + UINT holdCnt[2]; /*!< hold counter */ + + FIXP_DBL limGain[2]; /*!< limiter gain */ + FIXP_DBL limDecay; /*!< limiter decay (linear) */ + FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/ + + WEIGHTING_STATES filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */ + +}; + +/*---------------- constants -----------------------*/ + +/** + * Profile tables. + */ +static const FIXP_DBL tabMaxBoostThr[] = { + (FIXP_DBL)(int)((unsigned)-43<limDecay = FL2FXCONST_DBL( ((0.006f / 256) * blockLength) / METADATA_INT_SCALE ); + + /* Save parameters. */ + drcComp->blockLength = blockLength; + drcComp->sampleRate = sampleRate; + drcComp->chanConfig = channelMode; + drcComp->useWeighting = useWeighting; + + if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF)!=0) { /* expects initialized blockLength and sampleRate */ + return (-1); + } + + /* Set number of channels and channel offsets. */ + if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, &channelMapping)!=AAC_ENC_OK) { + return (-2); + } + + for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1; + + switch (channelMode) { + case MODE_1: /* mono */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_2: /* stereo */ + drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1]; + break; + case MODE_1_2: /* 3ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_1_2_1: /* 4ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0]; + break; + case MODE_1_2_2: /* 5ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_1: /* 5.1 ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_2_1: /* 7.1 ch */ + case MODE_7_1_FRONT_CENTER: + drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = channelMapping.elInfo[3].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = channelMapping.elInfo[3].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = channelMapping.elInfo[1].ChannelIndex[0]; /* lc */ + drcComp->channelIdx[RS2] = channelMapping.elInfo[1].ChannelIndex[1]; /* rc */ + break; + case MODE_7_1_REAR_SURROUND: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */ + drcComp->channelIdx[RS] = channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */ + drcComp->channelIdx[LS2] = channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS2] = channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + break; + case MODE_1_1: + case MODE_1_1_1_1: + case MODE_1_1_1_1_1_1: + case MODE_1_1_1_1_1_1_1_1: + case MODE_1_1_1_1_1_1_1_1_1_1_1_1: + case MODE_2_2: + case MODE_2_2_2: + case MODE_2_2_2_2: + case MODE_2_2_2_2_2_2: + default: + return (-1); + } + + drcComp->fullChannels = channelMapping.nChannelsEff; + drcComp->channels = channelMapping.nChannels; + + /* Init states. */ + drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = (FIXP_DBL)(int)((unsigned)-135<smoothGain, sizeof(drcComp->smoothGain)); + FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt)); + FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain)); + FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak)); + FDKmemclear(drcComp->filter, sizeof(drcComp->filter)); + + return (0); +} + + +INT FDK_DRC_Generator_setDrcProfile( + HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF + ) +{ + int profileIdx, i; + + drcComp->profile[0] = profileLine; + drcComp->profile[1] = profileRF; + + for (i = 0; i < 2; i++) { + /* get profile index */ + switch (drcComp->profile[i]) { + case DRC_NONE: + case DRC_FILMSTANDARD: profileIdx = 0; break; + case DRC_FILMLIGHT: profileIdx = 1; break; + case DRC_MUSICSTANDARD: profileIdx = 2; break; + case DRC_MUSICLIGHT: profileIdx = 3; break; + case DRC_SPEECH: profileIdx = 4; break; + case DRC_DELAY_TEST: profileIdx = 5; break; + default: return (-1); + } + + /* get parameters for selected profile */ + if (profileIdx >= 0) { + drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx]; + drcComp->boostThr[i] = tabBoostThr[profileIdx]; + drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx]; + drcComp->cutThr[i] = tabCutThr[profileIdx]; + drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx]; + + drcComp->boostFac[i] = tabBoostRatio[profileIdx]; + drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx]; + drcComp->cutFac[i] = tabCutRatio[profileIdx]; + + drcComp->maxBoost[i] = tabMaxBoost[profileIdx]; + drcComp->maxCut[i] = tabMaxCut[profileIdx]; + drcComp->maxEarlyCut[i] = - fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); /* no scaling after mult needed, earlyCutFac is in FIXP_DBL */ + + drcComp->fastAttack[i] = tc2Coeff(tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->fastDecay[i] = tc2Coeff(tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowAttack[i] = tc2Coeff(tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowDecay[i] = tc2Coeff(tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength; + + drcComp->attackThr[i] = tabAttackThr[profileIdx]; + drcComp->decayThr[i] = tabDecayThr[profileIdx]; + } + + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } + return (0); +} + + +INT FDK_DRC_Generator_Calc( + HDRC_COMP drcComp, + const INT_PCM * const inSamples, + const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, + FIXP_DBL clev, + FIXP_DBL slev, + INT * const pDynrng, + INT * const pCompr + ) +{ + int i, c; + FIXP_DBL peak[2]; + + + /************************************************************************** + * compressor + **************************************************************************/ + if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) { + /* Calc loudness level */ + FIXP_DBL level_b = FL2FXCONST_DBL(0.f); + int level_e = DFRACT_BITS-1; + + /* Increase energy time resolution with shorter processing blocks. 32 is an empiric value. */ + const int granuleLength = fixMin(32, drcComp->blockLength); + + if (drcComp->useWeighting) { + FIXP_DBL x1, x2, y, y1, y2; + /* sum of filter coefficients about 2.5 -> squared value is 6.25 + WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce granuleShift by 1. + */ + const int granuleShift = getShiftFactor(granuleLength)-1; + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = &inSamples[c]; + + if (c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + /* get filter states */ + x1 = drcComp->filter[c].x1; + x2 = drcComp->filter[c].x2; + y1 = drcComp->filter[c].y1; + y2 = drcComp->filter[c].y2; + + i = 0; + + do { + + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) { + /* apply weighting filter */ + FIXP_DBL x = FX_PCM2FX_DBL((FIXP_PCM)pSamples[i*drcComp->channels]) >> WEIGHTING_FILTER_SHIFT; + + /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */ + y = fMult(b0,x-x2) - fMult(a1,y1) - fMult(a2,y2); + + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + + accu += fPow2Div2(y)>>(granuleShift-1); /* partial energy */ + } /* i */ + + fixpAdd(accu, granuleShift+2*WEIGHTING_FILTER_SHIFT, &level_b, &level_e); /* sup up partial energies */ + + } while ( i < drcComp->blockLength ); + + + /* save filter states */ + drcComp->filter[c].x1 = x1; + drcComp->filter[c].x2 = x2; + drcComp->filter[c].y1 = y1; + drcComp->filter[c].y2 = y2; + } /* c */ + } /* weighting */ + else { + const int granuleShift = getShiftFactor(granuleLength); + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = &inSamples[c]; + + if ((int)c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i=offset; i < fixMin(offset+granuleLength,drcComp->blockLength); i++) { + /* partial energy */ + accu += fPow2Div2((FIXP_PCM)pSamples[i*drcComp->channels])>>(granuleShift-1); + } /* i */ + + fixpAdd(accu, granuleShift, &level_b, &level_e); /* sup up partial energies */ + + } while ( i < drcComp->blockLength ); + } + } /* weighting */ + + /* + * Convert to dBFS, apply dialnorm + */ + /* level scaling */ + + /* descaled level in ld64 representation */ + FIXP_DBL ldLevel = CalcLdData(level_b) + (FIXP_DBL)((level_e-12)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) - CalcLdData((FIXP_DBL)(drcComp->blockLength<<(DFRACT_BITS-1-12))); + + /* if (level < 1e-10) level = 1e-10f; */ + ldLevel = FDKmax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f)); + + /* level = 10 * log(level)/log(10) + 3; + * = 10*log(2)/log(10) * ld(level) + 3; + * = 10 * 0.30102999566398119521373889472449 * ld(level) + 3 + * = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3) + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 + * + * additional scaling with METADATA_FRACT_BITS: + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 64 * 2^(METADATA_FRACT_BITS) + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) + * = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 ) + * */ + FIXP_DBL level = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + (FIXP_DBL)(FL2FXCONST_DBL(0.3f)>>LD_DATA_SHIFT) ); + + /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as compressor profiles are defined relative to this */ + level -= ((FIXP_DBL)(dialnorm<<(METADATA_FRACT_BITS-16)) + (FIXP_DBL)(31<profile[i] == DRC_NONE) { + /* no compression */ + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } + else { + FIXP_DBL gain, alpha, lvl2smthlvl; + + /* calc static gain */ + if (level <= drcComp->maxBoostThr[i]) { + /* max boost */ + gain = drcComp->maxBoost[i]; + } + else if (level < drcComp->boostThr[i]) { + /* boost range */ + gain = fMult((level - drcComp->boostThr[i]),drcComp->boostFac[i]); + } + else if (level <= drcComp->earlyCutThr[i]) { + /* null band */ + gain = FL2FXCONST_DBL(0.f); + } + else if (level <= drcComp->cutThr[i]) { + /* early cut range */ + gain = fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); + } + else if (level < drcComp->maxCutThr[i]) { + /* cut range */ + gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - drcComp->maxEarlyCut[i]; + } + else { + /* max cut */ + gain = -drcComp->maxCut[i]; + } + + /* choose time constant */ + lvl2smthlvl = level - drcComp->smoothLevel[i]; + if (gain < drcComp->smoothGain[i]) { + /* attack */ + if (lvl2smthlvl > drcComp->attackThr[i]) { + /* fast attack */ + alpha = drcComp->fastAttack[i]; + } + else { + /* slow attack */ + alpha = drcComp->slowAttack[i]; + } + } + else { + /* release */ + if (lvl2smthlvl < -drcComp->decayThr[i]) { + /* fast release */ + alpha = drcComp->fastDecay[i]; + } + else { + /* slow release */ + alpha = drcComp->slowDecay[i]; + } + } + + /* smooth gain & level */ + if ((gain < drcComp->smoothGain[i]) || (drcComp->holdCnt[i] == 0)) { /* hold gain unless we have an attack or hold period is over */ + FIXP_DBL accu; + + /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + alpha * level; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothLevel[i]); + accu += fMult(alpha,level); + drcComp->smoothLevel[i] = accu; + + /* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + alpha * gain; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL-alpha), drcComp->smoothGain[i]); + accu += fMult(alpha,gain); + drcComp->smoothGain[i] = accu; + } + + /* hold counter */ + if (drcComp->holdCnt[i]) { + drcComp->holdCnt[i]--; + } + if (gain < drcComp->smoothGain[i]) { + drcComp->holdCnt[i] = drcComp->holdOff[i]; + } + } /* profile != DRC_NONE */ + } /* for i=1..2 */ + } else { + /* no compression */ + drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f); + drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f); + } + + /************************************************************************** + * limiter + **************************************************************************/ + + /* find peak level */ + peak[0] = peak[1] = FL2FXCONST_DBL(0.f); + for (i = 0; i < drcComp->blockLength; i++) { + FIXP_DBL tmp; + const INT_PCM* pSamples = &inSamples[i*drcComp->channels]; + INT_PCM maxSample = 0; + + /* single channels */ + for (c = 0; c < (int)drcComp->channels; c++) { + maxSample = FDKmax(maxSample, fAbs(pSamples[c])); + } + peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample)>>DOWNMIX_SHIFT); + + /* Lt/Rt downmix */ + if (drcComp->fullChannels > 2) { + /* Lt */ + tmp = FL2FXCONST_DBL(0.f); + + if (drcComp->channelIdx[LS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */ + if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ + + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Rt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]])>>(DOWNMIX_SHIFT-1); /* S */ + if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ + + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + + /* Lo/Ro downmix */ + if (drcComp->fullChannels > 2) { + /* Lo */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ + if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ + + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Ro */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ + if (drcComp->channelIdx[C] >= 0) tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ + + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + + peak[1] = fixMax(peak[0], peak[1]); + + /* Mono Downmix - for comp_val only */ + if (drcComp->fullChannels > 1) { + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]])>>(DOWNMIX_SHIFT-1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]])>>(DOWNMIX_SHIFT-1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]])>>(DOWNMIX_SHIFT-1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]])>>(DOWNMIX_SHIFT-1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) tmp += fMultDiv2(slev, fMult(FL2FXCONST_DBL(0.7f), (FIXP_PCM)pSamples[drcComp->channelIdx[S]]))>>(DOWNMIX_SHIFT-1); /* S */ + if (drcComp->channelIdx[C] >= 0) tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]])>>(DOWNMIX_SHIFT-1); /* C (2*clev) */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]])>>DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]])>>DOWNMIX_SHIFT); /* R */ + + peak[1] = fixMax(peak[1], fixp_abs(tmp)); + } + } + + for (i=0; i<2; i++) { + FIXP_DBL tmp = drcComp->prevPeak[i]; + drcComp->prevPeak[i] = peak[i]; + peak[i] = fixMax(peak[i], tmp); + + /* + * Convert to dBFS, apply dialnorm + */ + /* descaled peak in ld64 representation */ + FIXP_DBL ld_peak = CalcLdData(peak[i]) + (FIXP_DBL)((LONG)DOWNMIX_SHIFT<<(DFRACT_BITS-1-LD_DATA_SHIFT)); + + /* if (peak < 1e-6) level = 1e-6f; */ + ld_peak = FDKmax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f)); + + /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * peak[i] = 20 * log(2)/log(10) * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * peak[i] = 10 * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * + * additional scaling with METADATA_FRACT_BITS: + * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + 0.2f + (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS) + * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * 2*0.30102999566398119521373889472449 * ld64(peak[i]) + * + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i] + */ + peak[i] = fMult((FIXP_DBL)(10<<(METADATA_FRACT_BITS+LD_DATA_SHIFT)), fMult( FL2FX_DBL(2*0.30102999566398119521373889472449f), ld_peak)); + peak[i] += (FL2FX_DBL(0.5f)>>METADATA_INT_BITS); /* add a little bit headroom */ + peak[i] += drcComp->smoothGain[i]; + } + + /* peak -= dialnorm + 31; */ /* this is Dolby style only */ + peak[0] -= (FIXP_DBL)((dialnorm-drc_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */ + + /* peak += 11; */ /* this is Dolby style only */ /* RF mode output is 11dB higher */ + /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/ + peak[1] -= (FIXP_DBL)((dialnorm-comp_TargetRefLevel)<<(METADATA_FRACT_BITS-16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */ + + /* limiter gain */ + drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]); + + drcComp->limGain[1] += 2*drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]); + + /*************************************************************************/ + + /* apply limiting, return DRC gains*/ + { + FIXP_DBL tmp; + + tmp = drcComp->smoothGain[0]; + if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[0]; + } + *pDynrng = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16)); + + tmp = drcComp->smoothGain[1]; + if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[1]; + } + *pCompr = (LONG) scaleValue(tmp, -(METADATA_FRACT_BITS-16)); + } + + return 0; +} + + +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) +{ + return drcComp->profile[0]; +} + +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) +{ + return drcComp->profile[1]; +} + + diff --git a/libAACenc/src/metadata_compressor.h b/libAACenc/src/metadata_compressor.h new file mode 100644 index 00000000..ff639b5d --- /dev/null +++ b/libAACenc/src/metadata_compressor.h @@ -0,0 +1,252 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/********************** Fraunhofer IIS FDK AAC Encoder lib ****************** + + Author(s): M. Neusinger + Description: Compressor for AAC Metadata Generator + +******************************************************************************/ + +#ifndef _METADATA_COMPRESSOR_H +#define _METADATA_COMPRESSOR_H + + +#include "FDK_audio.h" +#include "common_fix.h" + +#include "aacenc.h" + + +/** + * DRC compression profiles. + */ +typedef enum DRC_PROFILE { + DRC_NONE = 0, + DRC_FILMSTANDARD = 1, + DRC_FILMLIGHT = 2, + DRC_MUSICSTANDARD = 3, + DRC_MUSICLIGHT = 4, + DRC_SPEECH = 5, + DRC_DELAY_TEST = 6 + +} DRC_PROFILE; + + +/** + * DRC Compressor handle. + */ +typedef struct DRC_COMP DRC_COMP, *HDRC_COMP; + +/** + * \brief Open a DRC Compressor instance. + * + * Allocate memory for a compressor instance. + * + * \param phDrcComp A pointer to a compressor handle. Initialized on return. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Open( + HDRC_COMP *phDrcComp + ); + + +/** + * \brief Close the DRC Compressor instance. + * + * Deallocate instance and free whole memory. + * + * \param phDrcComp Pointer to the compressor handle to be deallocated. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Close( + HDRC_COMP *phDrcComp + ); + +/** + * \brief Configure DRC Compressor. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * \param blockLength Length of processing block in samples per channel. + * \param sampleRate Sampling rate in Hz. + * \param channelMode Channel configuration. + * \param channelOrder Channel order, MPEG or WAV. + * \param useWeighting Use weighting filter for loudness calculation + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Initialize( + HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, + const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting + ); + +/** + * \brief Calculate DRC Compressor Gain. + * + * \param drcComp Compressor handle. + * \param inSamples Pointer to interleaved input audio samples. + * \param dialnorm Dialog Level in dB (typically -31...-1). + * \param drc_TargetRefLevel + * \param comp_TargetRefLevel + * \param clev Downmix center mix factor (typically 0.707, 0.595 or 0.5) + * \param slev Downmix surround mix factor (typically 0.707, 0.5, or 0) + * \param dynrng Pointer to variable receiving line mode DRC gain in dB + * \param compr Pointer to variable receiving RF mode DRC gain in dB + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Calc( + HDRC_COMP drcComp, + const INT_PCM * const inSamples, + const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, + FIXP_DBL clev, + FIXP_DBL slev, + INT * const dynrng, + INT * const compr + ); + + +/** + * \brief Configure DRC Compressor Profile. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_setDrcProfile( + HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF + ); + + +/** + * \brief Get DRC profile for line mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getDrcProfile( + const HDRC_COMP drcComp + ); + + +/** + * \brief Get DRC profile for RF mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getCompProfile( + const HDRC_COMP drcComp + ); + + +#endif /* _METADATA_COMPRESSOR_H */ + diff --git a/libAACenc/src/metadata_main.cpp b/libAACenc/src/metadata_main.cpp new file mode 100644 index 00000000..90f8f4e6 --- /dev/null +++ b/libAACenc/src/metadata_main.cpp @@ -0,0 +1,869 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/********************** Fraunhofer IIS FDK AAC Encoder lib ****************** + + Author(s): V. Bacigalupo + Description: Metadata Encoder library interface functions + +******************************************************************************/ + + +#include "metadata_main.h" +#include "metadata_compressor.h" +#include "FDK_bitstream.h" +#include "FDK_audio.h" +#include "genericStds.h" + +/*----------------- defines ----------------------*/ +#define MAX_DRC_BANDS (1<<4) +#define MAX_DRC_CHANNELS (8) +#define MAX_DRC_FRAMELEN (2*1024) + +/*--------------- structure definitions --------------------*/ + +typedef struct AAC_METADATA +{ + /* MPEG: Dynamic Range Control */ + struct { + UCHAR prog_ref_level_present; + SCHAR prog_ref_level; + + UCHAR dyn_rng_sgn[MAX_DRC_BANDS]; + UCHAR dyn_rng_ctl[MAX_DRC_BANDS]; + + UCHAR drc_bands_present; + UCHAR drc_band_incr; + UCHAR drc_band_top[MAX_DRC_BANDS]; + UCHAR drc_interpolation_scheme; + AACENC_METADATA_DRC_PROFILE drc_profile; + INT drc_TargetRefLevel; /* used for Limiter */ + + /* excluded channels */ + UCHAR excluded_chns_present; + UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */ + } mpegDrc; + + /* ETSI: addtl ancillary data */ + struct { + /* Heavy Compression */ + UCHAR compression_on; /* flag, if compression value should be written */ + UCHAR compression_value; /* compression value */ + AACENC_METADATA_DRC_PROFILE comp_profile; + INT comp_TargetRefLevel; /* used for Limiter */ + INT timecode_coarse_status; + INT timecode_fine_status; + } etsiAncData; + + SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */ + SCHAR surroundMixLevel; /* surround downmix level (0...7, according to table) */ + UCHAR WritePCEMixDwnIdx; /* flag */ + UCHAR DmxLvl_On; /* flag */ + + UCHAR dolbySurroundMode; + + UCHAR metadataMode; /* indicate meta data mode in current frame (delay line) */ + +} AAC_METADATA; + +struct FDK_METADATA_ENCODER +{ + INT metadataMode; + HDRC_COMP hDrcComp; + AACENC_MetaData submittedMetaData; + + INT nAudioDataDelay; + INT nMetaDataDelay; + INT nChannels; + + INT_PCM audioDelayBuffer[MAX_DRC_CHANNELS*MAX_DRC_FRAMELEN]; + int audioDelayIdx; + + AAC_METADATA metaDataBuffer[3]; + int metaDataDelayIdx; + + UCHAR drcInfoPayload[12]; + UCHAR drcDsePayload[8]; + + INT matrix_mixdown_idx; + AACENC_EXT_PAYLOAD exPayload[2]; + INT nExtensions; + + INT finalizeMetaData; /* Delay switch off by one frame and write default configuration to + finalize the metadata setup. */ +}; + + +/*---------------- constants -----------------------*/ +static const AACENC_MetaData defaultMetaDataSetup = { + AACENC_METADATA_DRC_NONE, + AACENC_METADATA_DRC_NONE, + -(31<<16), + -(31<<16), + 0, + -(31<<16), + 0, + 0, + 0, + 0, + 0 +}; + +static const FIXP_DBL dmxTable[8] = { + ((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f), FL2FXCONST_DBL(0.596f), + FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f), FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f) +}; + +static const UCHAR surmix2matrix_mixdown_idx[8] = { + 0, 0, 0, 1, 1, 2, 2, 3 +}; + + +/*--------------- function declarations --------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA * const pMetadata + ); + +static INT WriteDynamicRangeInfoPayload( + const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload + ); + +static INT WriteEtsiAncillaryDataPayload( + const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload + ); + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, + INT_PCM * const pAudioSamples, + const INT nAudioSamples + ); + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData * const hMetadata, + const INT nChannels, + const INT metadataMode, + AAC_METADATA * const pAacMetaData + ); + +static FDK_METADATA_ERROR ProcessCompressor( + AAC_METADATA *pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM * const pSamples, + const INT nSamples + ); + +/*------------- function definitions ----------------*/ + +static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile) +{ + DRC_PROFILE drcProfile = DRC_NONE; + + switch(aacProfile) { + case AACENC_METADATA_DRC_NONE: drcProfile = DRC_NONE; break; + case AACENC_METADATA_DRC_FILMSTANDARD: drcProfile = DRC_FILMSTANDARD; break; + case AACENC_METADATA_DRC_FILMLIGHT: drcProfile = DRC_FILMLIGHT; break; + case AACENC_METADATA_DRC_MUSICSTANDARD: drcProfile = DRC_MUSICSTANDARD; break; + case AACENC_METADATA_DRC_MUSICLIGHT: drcProfile = DRC_MUSICLIGHT; break; + case AACENC_METADATA_DRC_SPEECH: drcProfile = DRC_SPEECH; break; + default: drcProfile = DRC_NONE; break; + } + return drcProfile; +} + + +/* convert dialog normalization to program reference level */ +/* NOTE: this only is correct, if the decoder target level is set to -31dB for line mode / -20dB for RF mode */ +static UCHAR dialnorm2progreflvl(const INT d) +{ + return ((UCHAR)FDKmax(0, FDKmin((-d + (1<<13)) >> 14, 127))); +} + +/* convert program reference level to dialog normalization */ +static INT progreflvl2dialnorm(const UCHAR p) +{ + return -((INT)(p<<(16-2))); +} + +/* encode downmix levels to Downmixing_levels_MPEG4 */ +static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev) +{ + SCHAR dmxLvls = 0; + dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */ + dmxLvls |= 0x08 | surmixlev; /* surround_mix_level_on */ + + return dmxLvls; +} + +/* encode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl, UCHAR* const dyn_rng_sgn ) +{ + if(gain < 0) + { + *dyn_rng_sgn = 1; + gain = -gain; + } + else + { + *dyn_rng_sgn = 0; + } + gain = FDKmin(gain,(127<<14)); + + *dyn_rng_ctl = (UCHAR)((gain + (1<<13)) >> 14); +} + +/* decode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn) +{ + INT tmp = ((INT)dyn_rng_ctl << (16-2)); + if (dyn_rng_sgn) tmp = -tmp; + + return tmp; +} + +/* encode AAC compression value (ETSI TS 101 154 page 99) */ +static UCHAR encodeCompr(INT gain) +{ + UCHAR x, y; + INT tmp; + + /* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */ + tmp = ((3156476 - gain) * 15 + 197283) / 394566; + + if (tmp >= 240) { + return 0xFF; + } + else if (tmp < 0) { + return 0; + } + else { + x = tmp / 15; + y = tmp % 15; + } + + return (x << 4) | y; +} + +/* decode AAC compression value (ETSI TS 101 154 page 99) */ +static INT decodeCompr(const UCHAR compr) +{ + INT gain; + SCHAR x = compr >> 4; /* 4 MSB of compr */ + UCHAR y = (compr & 0x0F); /* 4 LSB of compr */ + + /* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */ + gain = (INT)( scaleValue(((LONG)FL2FXCONST_DBL(6.0206f/128.f)*(8-x) - (LONG)FL2FXCONST_DBL(0.4014f/128.f)*y), -(DFRACT_BITS-1-7-16)) ); + + return gain; +} + + +FDK_METADATA_ERROR FDK_MetadataEnc_Open( + HANDLE_FDK_METADATA_ENCODER *phMetaData + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + HANDLE_FDK_METADATA_ENCODER hMetaData = NULL; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + hMetaData = (HANDLE_FDK_METADATA_ENCODER) FDKcalloc(1, sizeof(FDK_METADATA_ENCODER) ); + + if (hMetaData == NULL) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + + FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER)); + + /* Allocate DRC Compressor. */ + if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp)!=0) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + + /* Return metadata instance */ + *phMetaData = hMetaData; + + return err; + +bail: + FDK_MetadataEnc_Close(&hMetaData); + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER *phMetaData + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + if (*phMetaData != NULL) { + FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp); + FDKfree(*phMetaData); + *phMetaData = NULL; + } +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetaData, + const INT resetStates, + const INT metadataMode, + const INT audioDelay, + const UINT frameLength, + const UINT sampleRate, + const UINT nChannels, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + int i, nFrames, delay; + + if (hMetaData==NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* Determine values for delay compensation. */ + for (nFrames=0, delay=audioDelay-frameLength; delay>0; delay-=frameLength, nFrames++); + + if ( (hMetaData->nChannels>MAX_DRC_CHANNELS) || ((-delay)>MAX_DRC_FRAMELEN) ) { + err = METADATA_INIT_ERROR; + goto bail; + } + + /* Initialize with default setup. */ + FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup, sizeof(AACENC_MetaData)); + + hMetaData->finalizeMetaData = 0; /* finalize meta data only while on/off switching, else disabled */ + + /* Reset delay lines. */ + if ( resetStates || (hMetaData->nAudioDataDelay!=-delay) || (hMetaData->nChannels!=(INT)nChannels) ) + { + FDKmemclear(hMetaData->audioDelayBuffer, sizeof(hMetaData->audioDelayBuffer)); + FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer)); + hMetaData->audioDelayIdx = 0; + hMetaData->metaDataDelayIdx = 0; + } + else { + /* Enable meta data. */ + if ( (hMetaData->metadataMode==0) && (metadataMode!=0) ) { + /* disable meta data in all delay lines */ + for (i=0; i<(int)(sizeof(hMetaData->metaDataBuffer)/sizeof(AAC_METADATA)); i++) { + LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0, &hMetaData->metaDataBuffer[i]); + } + } + + /* Disable meta data.*/ + if ( (hMetaData->metadataMode!=0) && (metadataMode==0) ) { + hMetaData->finalizeMetaData = hMetaData->metadataMode; + } + } + + /* Initialize delay. */ + hMetaData->nAudioDataDelay = -delay; + hMetaData->nMetaDataDelay = nFrames; + hMetaData->nChannels = nChannels; + hMetaData->metadataMode = metadataMode; + + /* Initialize compressor. */ + if (metadataMode != 0) { + if ( FDK_DRC_Generator_Initialize( + hMetaData->hDrcComp, + DRC_NONE, + DRC_NONE, + frameLength, + sampleRate, + channelMode, + channelOrder, + 1) != 0) + { + err = METADATA_INIT_ERROR; + } + } +bail: + return err; +} + +static FDK_METADATA_ERROR ProcessCompressor( + AAC_METADATA *pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM * const pSamples, + const INT nSamples + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + + if ( (pMetadata==NULL) || (hDrcComp==NULL) ) { + err = METADATA_INVALID_HANDLE; + return err; + } + DRC_PROFILE profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile); + DRC_PROFILE profileComp = convertProfile(pMetadata->etsiAncData.comp_profile); + + /* first, check if profile is same as last frame + * otherwise, update setup */ + if ( (profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) + || (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp)) ) + { + FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp); + } + + /* Sanity check */ + if (profileComp == DRC_NONE) { + pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external values will be written if not configured */ + } + + /* in case of embedding external values, copy this now (limiter may overwrite them) */ + INT dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0], pMetadata->mpegDrc.dyn_rng_sgn[0]); + INT compr = decodeCompr(pMetadata->etsiAncData.compression_value); + + /* Call compressor */ + if (FDK_DRC_Generator_Calc(hDrcComp, + pSamples, + progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level), + pMetadata->mpegDrc.drc_TargetRefLevel, + pMetadata->etsiAncData.comp_TargetRefLevel, + dmxTable[pMetadata->centerMixLevel], + dmxTable[pMetadata->surroundMixLevel], + &dynrng, + &compr) != 0) + { + err = METADATA_ENCODE_ERROR; + goto bail; + } + + /* Write DRC values */ + pMetadata->mpegDrc.drc_band_incr = 0; + encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl, pMetadata->mpegDrc.dyn_rng_sgn); + pMetadata->etsiAncData.compression_value = encodeCompr(compr); + +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, + INT_PCM * const pAudioSamples, + const INT nAudioSamples, + const AACENC_MetaData * const pMetadata, + AACENC_EXT_PAYLOAD ** ppMetaDataExtPayload, + UINT * nMetaDataExtensions, + INT * matrix_mixdown_idx + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode; + + /* Where to write new meta data info */ + metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx; + + /* How to write the data */ + metadataMode = hMetaDataEnc->metadataMode; + + /* Compensate meta data delay. */ + hMetaDataEnc->metaDataDelayIdx++; + if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay) hMetaDataEnc->metaDataDelayIdx = 0; + + /* Where to read pending meta data info from. */ + metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx; + + /* Submit new data if available. */ + if (pMetadata!=NULL) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata, sizeof(AACENC_MetaData)); + } + + /* Write one additional frame with default configuration of meta data. Ensure defined behaviour on decoder side. */ + if ( (hMetaDataEnc->finalizeMetaData!=0) && (hMetaDataEnc->metadataMode==0)) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup, sizeof(AACENC_MetaData)); + metadataMode = hMetaDataEnc->finalizeMetaData; + hMetaDataEnc->finalizeMetaData = 0; + } + + /* Get last submitted data. */ + if ( (err = LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, + hMetaDataEnc->nChannels, + metadataMode, + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) != METADATA_OK ) + { + goto bail; + } + + /* Calculate compressor if necessary and updata meta data info */ + if (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode != 0) { + if ( (err = ProcessCompressor( + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], + hMetaDataEnc->hDrcComp, + pAudioSamples, + nAudioSamples)) != METADATA_OK) + { + /* Get last submitted data again. */ + LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, + hMetaDataEnc->nChannels, + metadataMode, + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]); + } + } + + /* Convert Meta Data side info to bitstream data. */ + if ( (err = WriteMetadataPayload(hMetaDataEnc, &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) != METADATA_OK ) { + goto bail; + } + + /* Assign meta data to output */ + *ppMetaDataExtPayload = hMetaDataEnc->exPayload; + *nMetaDataExtensions = hMetaDataEnc->nExtensions; + *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx; + +bail: + /* Compensate audio delay, reset err status. */ + err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, nAudioSamples); + + return err; +} + + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, + INT_PCM * const pAudioSamples, + const INT nAudioSamples + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + + if (hMetaDataEnc->nAudioDataDelay) { + int i, delaySamples = hMetaDataEnc->nAudioDataDelay*hMetaDataEnc->nChannels; + + for (i = 0; i < nAudioSamples; i++) { + INT_PCM tmp = pAudioSamples[i]; + pAudioSamples[i] = hMetaDataEnc->audioDelayBuffer[hMetaDataEnc->audioDelayIdx]; + hMetaDataEnc->audioDelayBuffer[hMetaDataEnc->audioDelayIdx] = tmp; + + hMetaDataEnc->audioDelayIdx++; + if (hMetaDataEnc->audioDelayIdx >= delaySamples) hMetaDataEnc->audioDelayIdx = 0; + } + } + + return err; +} + +/*----------------------------------------------------------------------------- + + functionname: WriteMetadataPayload + description: fills anc data and extension payload + returns: Error status + + ------------------------------------------------------------------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA * const pMetadata + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + + if ( (hMetaData==NULL) || (pMetadata==NULL) ) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + hMetaData->nExtensions = 0; + hMetaData->matrix_mixdown_idx = -1; + + /* AAC-DRC */ + if (pMetadata->metadataMode != 0) + { + hMetaData->exPayload[hMetaData->nExtensions].pData = hMetaData->drcInfoPayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteDynamicRangeInfoPayload(pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + + /* Matrix Mixdown Coefficient in PCE */ + if (pMetadata->WritePCEMixDwnIdx) { + hMetaData->matrix_mixdown_idx = surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel]; + } + + /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */ + if (pMetadata->metadataMode == 2) /* MP4_METADATA_MPEG_ETSI */ + { + hMetaData->exPayload[hMetaData->nExtensions].pData = hMetaData->drcDsePayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteEtsiAncillaryDataPayload(pMetadata,hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + } /* metadataMode == 2 */ + + } /* metadataMode != 0 */ + +bail: + return err; +} + +static INT WriteDynamicRangeInfoPayload( + const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload + ) +{ + const INT pce_tag_present = 0; /* yet fixed setting! */ + const INT prog_ref_lev_res_bits = 0; + INT i, drc_num_bands = 1; + + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* dynamic_range_info() */ + FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */ + if (pce_tag_present) { + FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */ + FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */ + } + + /* Exclude channels */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0, 1); /* excluded_chns_present*/ + + /* Multiband DRC */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0, 1); /* drc_bands_present */ + if (pMetadata->mpegDrc.drc_bands_present) + { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr, 4); /* drc_band_incr */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme, 4); /* drc_interpolation_scheme */ + drc_num_bands += pMetadata->mpegDrc.drc_band_incr; + for (i=0; impegDrc.drc_band_top[i], 8); /* drc_band_top */ + } + } + + /* Program Reference Level */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present, 1); /* prog_ref_level_present */ + if (pMetadata->mpegDrc.prog_ref_level_present) + { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level, 7); /* prog_ref_level */ + FDKwriteBits(&bsWriter, prog_ref_lev_res_bits, 1); /* prog_ref_level_reserved_bits */ + } + + /* DRC Values */ + for (i=0; impegDrc.dyn_rng_sgn[i]) ? 1 : 0, 1); /* dyn_rng_sgn[ */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i], 7); /* dyn_rng_ctl */ + } + + /* return number of valid bits in extension payload. */ + return FDKgetValidBits(&bsWriter); +} + +static INT WriteEtsiAncillaryDataPayload( + const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload + ) +{ + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* ancillary_data_sync */ + FDKwriteBits(&bsWriter, 0xBC, 8); + + /* bs_info */ + FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */ + FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode, 2); /* dolby_surround_mode */ + FDKwriteBits(&bsWriter, 0x0, 4); /* reserved */ + + /* ancillary_data_status */ + FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */ + FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0, 1); /* downmixing_levels_MPEG4_status */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0, 1); /* audio_coding_mode_and_compression status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0, 1); /* coarse_grain_timecode_status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0, 1); /* fine_grain_timecode_status */ + + /* downmixing_levels_MPEG4_status */ + if (pMetadata->DmxLvl_On) { + FDKwriteBits(&bsWriter, encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel), 8); + } + + /* audio_coding_mode_and_compression_status */ + if (pMetadata->etsiAncData.compression_on) { + FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value, 8); /* compression value */ + } + + /* grain-timecode coarse/fine */ + if (pMetadata->etsiAncData.timecode_coarse_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + if (pMetadata->etsiAncData.timecode_fine_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + return FDKgetValidBits(&bsWriter); +} + + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData * const hMetadata, + const INT nChannels, + const INT metadataMode, + AAC_METADATA * const pAacMetaData + ) +{ + FDK_METADATA_ERROR err = METADATA_OK; + + if (pAacMetaData==NULL) { + err = METADATA_INVALID_HANDLE; + } + else { + /* init struct */ + FDKmemclear(pAacMetaData, sizeof(AAC_METADATA)); + + if (hMetadata!=NULL) { + /* convert data */ + pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile; + pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile; + pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel; + pAacMetaData->etsiAncData.comp_TargetRefLevel= hMetadata->comp_TargetRefLevel; + pAacMetaData->mpegDrc.prog_ref_level_present = hMetadata->prog_ref_level_present; + pAacMetaData->mpegDrc.prog_ref_level = dialnorm2progreflvl(hMetadata->prog_ref_level); + + pAacMetaData->centerMixLevel = hMetadata->centerMixLevel; + pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel; + pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present; + pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present; + + pAacMetaData->etsiAncData.compression_on = 1; + + + if (nChannels == 2) { + pAacMetaData->dolbySurroundMode = hMetadata->dolbySurroundMode; /* dolby_surround_mode */ + } else { + pAacMetaData->dolbySurroundMode = 0; + } + + pAacMetaData->etsiAncData.timecode_coarse_status = 0; /* not yet supported - attention: Update GetEstMetadataBytesPerFrame() if enable this! */ + pAacMetaData->etsiAncData.timecode_fine_status = 0; /* not yet supported - attention: Update GetEstMetadataBytesPerFrame() if enable this! */ + + pAacMetaData->metadataMode = metadataMode; + } + else { + pAacMetaData->metadataMode = 0; /* there is no configuration available */ + } + } + + return err; +} + +INT FDK_MetadataEnc_GetDelay( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc + ) +{ + INT delay = 0; + + if (hMetadataEnc!=NULL) { + delay = hMetadataEnc->nAudioDataDelay; + } + + return delay; +} + + diff --git a/libAACenc/src/metadata_main.h b/libAACenc/src/metadata_main.h new file mode 100644 index 00000000..bfc8ae11 --- /dev/null +++ b/libAACenc/src/metadata_main.h @@ -0,0 +1,224 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/********************** Fraunhofer IIS FDK AAC Encoder lib ****************** + + Author(s): V. Bacigalupo + Description: Metadata Encoder library interface functions + +******************************************************************************/ + +#ifndef _METADATA_MAIN_H +#define _METADATA_MAIN_H + + +/* Includes ******************************************************************/ +#include "aacenc_lib.h" +#include "aacenc.h" + + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +typedef enum { + METADATA_OK = 0x0000, /*!< No error happened. All fine. */ + METADATA_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */ + METADATA_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + METADATA_INIT_ERROR = 0x0040, /*!< General initialization error. */ + METADATA_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an unexpected error. */ + +} FDK_METADATA_ERROR; + +/** + * Meta Data handle. + */ +typedef struct FDK_METADATA_ENCODER *HANDLE_FDK_METADATA_ENCODER; + + +/** + * \brief Open a Meta Data instance. + * + * \param phMetadataEnc A pointer to a Meta Data handle to be allocated. Initialized on return. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_MEMORY_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Open( + HANDLE_FDK_METADATA_ENCODER *phMetadataEnc + ); + + +/** + * \brief Initialize a Meta Data instance. + * + * \param hMetadataEnc Meta Data handle. + * \param resetStates Indication for full reset of all states. + * \param metadataMode Configures metat data output format (0,1,2). + * \param audioDelay Delay cause by the audio encoder. + * \param frameLength Number of samples to be processes within one frame. + * \param sampleRate Sampling rat in Hz of audio input signal. + * \param nChannels Number of audio input channels. + * \param channelMode Channel configuration which is used by the encoder. + * \param channelOrder Channel order of the input data. (WAV, MPEG) + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_INIT_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, + const INT resetStates, + const INT metadataMode, + const INT audioDelay, + const UINT frameLength, + const UINT sampleRate, + const UINT nChannels, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder + ); + + +/** + * \brief Calculate Meta Data processing. + * + * This function treats all step necessary for meta data processing. + * - Receive new meta data and make usable. + * - Calculate DRC compressor and extract meta data info. + * - Make meta data available for extern use. + * - Apply audio data and meta data delay compensation. + * + * \param hMetadataEnc Meta Data handle. + * \param pAudioSamples Pointer to audio input data. Existing function overwrites audio data with delayed audio samples. + * \param nAudioSamples Number of input audio samples to be prcessed. + * \param pMetadata Pointer to Metat Data input. + * \param ppMetaDataExtPayload Pointer to extension payload array. Filled on return. + * \param nMetaDataExtensions Pointer to variable to describe number of available extension payloads. Filled on return. + * \param matrix_mixdown_idx Pointer to variable for matrix mixdown coefficient. Filled on return. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_ENCODE_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, + INT_PCM * const pAudioSamples, + const INT nAudioSamples, + const AACENC_MetaData * const pMetadata, + AACENC_EXT_PAYLOAD ** ppMetaDataExtPayload, + UINT * nMetaDataExtensions, + INT * matrix_mixdown_idx + ); + + +/** + * \brief Close the Meta Data instance. + * + * Deallocate instance and free whole memory. + * + * \param phMetaData Pointer to the Meta Data handle to be deallocated. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER *phMetaData + ); + + +/** + * \brief Get Meta Data Encoder delay. + * + * \param hMetadataEnc Meta Data Encoder handle. + * + * \return Delay caused by Meta Data module. + */ +INT FDK_MetadataEnc_GetDelay( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc + ); + + +#endif /* _METADATA_MAIN_H */ + diff --git a/libAACenc/src/ms_stereo.cpp b/libAACenc/src/ms_stereo.cpp new file mode 100644 index 00000000..306d490c --- /dev/null +++ b/libAACenc/src/ms_stereo.cpp @@ -0,0 +1,251 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: MS stereo processing + +******************************************************************************/ +#include "ms_stereo.h" + +#include "psy_const.h" + +/* static const float scaleMinThres = 1.0f; */ /* 0.75f for 3db boost */ + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL* psyOutChannel[2], + const INT *isBook, + INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset) +{ + FIXP_DBL *sfbEnergyLeft = psyData[0]->sfbEnergy.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRight = psyData[1]->sfbEnergy.Long; /* modified where msMask==1 */ + const FIXP_DBL *sfbEnergyMid = psyData[0]->sfbEnergyMS.Long; + const FIXP_DBL *sfbEnergySide = psyData[1]->sfbEnergyMS.Long; + FIXP_DBL *sfbThresholdLeft = psyData[0]->sfbThreshold.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRight = psyData[1]->sfbThreshold.Long; /* modified where msMask==1 */ + + FIXP_DBL *sfbSpreadEnLeft = psyData[0]->sfbSpreadEnergy.Long; + FIXP_DBL *sfbSpreadEnRight = psyData[1]->sfbSpreadEnergy.Long; + + FIXP_DBL *sfbEnergyLeftLdData = psyOutChannel[0]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRightLdData = psyOutChannel[1]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyMidLdData = psyData[0]->sfbEnergyMSLdData; + FIXP_DBL *sfbEnergySideLdData = psyData[1]->sfbEnergyMSLdData; + FIXP_DBL *sfbThresholdLeftLdData = psyOutChannel[0]->sfbThresholdLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRightLdData = psyOutChannel[1]->sfbThresholdLdData; /* modified where msMask==1 */ + + FIXP_DBL *mdctSpectrumLeft = psyData[0]->mdctSpectrum; /* modified where msMask==1 */ + FIXP_DBL *mdctSpectrumRight = psyData[1]->mdctSpectrum; /* modified where msMask==1 */ + + INT sfb,sfboffs, j; /* loop counters */ + FIXP_DBL pnlrLdData, pnmsLdData; + FIXP_DBL minThresholdLdData; + FIXP_DBL minThreshold; + INT useMS; + + INT msMaskTrueSomewhere = 0; /* to determine msDigest */ + INT numMsMaskFalse = 0; /* number of non-intensity bands where L/R coding is used */ + + for(sfb=0; sfb pnlr); +*/ + + /* we assume that scaleMinThres == 1.0f and we can drop it */ + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); + + /* pnlrLdData = sfbThresholdLeftLdData[sfb+sfboffs] - + max(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]) + + sfbThresholdRightLdData[sfb+sfboffs] - + max(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); */ + tmp = fixMax(sfbEnergyLeftLdData[sfb+sfboffs], sfbThresholdLeftLdData[sfb+sfboffs]); + pnlrLdData = (sfbThresholdLeftLdData[sfb+sfboffs]>>1) - (tmp>>1); + pnlrLdData = pnlrLdData + (sfbThresholdRightLdData[sfb+sfboffs]>>1); + tmp = fixMax(sfbEnergyRightLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); + pnlrLdData = pnlrLdData - (tmp>>1); + + /* pnmsLdData = minThresholdLdData - max(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData) + + minThresholdLdData - max(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData); */ + tmp = fixMax(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData); + pnmsLdData = minThresholdLdData - (tmp>>1); + tmp = fixMax(sfbEnergySideLdData[sfb+sfboffs], minThresholdLdData); + pnmsLdData = pnmsLdData - (tmp>>1); + useMS = (pnmsLdData > (pnlrLdData)); + + + if (useMS) { + msMask[sfb+sfboffs] = 1; + msMaskTrueSomewhere = 1; + for(j=sfbOffset[sfb+sfboffs]; j>1; + specR = mdctSpectrumRight[j]>>1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]); + sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold; + sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs]; + sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs]; + sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs]; + sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs]; + + sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] = + fixMin( sfbSpreadEnLeft[sfb+sfboffs], + sfbSpreadEnRight[sfb+sfboffs] ) >> 1; + + } + else { + msMask[sfb+sfboffs] = 0; + numMsMaskFalse++; + } /* useMS */ + } /* isBook */ + else { + /* keep mDigest from IS module */ + if (msMask[sfb+sfboffs]) { + msMaskTrueSomewhere = 1; + } + /* prohibit MS_MASK_ALL in combination with IS */ + numMsMaskFalse = 9; + } /* isBook */ + } /* sfboffs */ + } /* sfb */ + + + if(msMaskTrueSomewhere == 1) { + if ((numMsMaskFalse == 0) || ((numMsMaskFalse < maxSfbPerGroup) && (numMsMaskFalse < 9))) { + *msDigest = SI_MS_MASK_ALL; + /* loop through M/S bands; if msMask==0, set it to 1 and apply M/S */ + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + if (( (isBook == NULL) ? 1 : (isBook[sfb+sfboffs] == 0) ) && (msMask[sfb+sfboffs] == 0)) { + msMask[sfb+sfboffs] = 1; + /* apply M/S coding */ + for(j=sfbOffset[sfb+sfboffs]; j>1; + specR = mdctSpectrumRight[j]>>1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb+sfboffs], sfbThresholdRight[sfb+sfboffs]); + sfbThresholdLeft[sfb+sfboffs] = sfbThresholdRight[sfb+sfboffs] = minThreshold; + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb+sfboffs], sfbThresholdRightLdData[sfb+sfboffs]); + sfbThresholdLeftLdData[sfb+sfboffs] = sfbThresholdRightLdData[sfb+sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb+sfboffs] = sfbEnergyMid[sfb+sfboffs]; + sfbEnergyRight[sfb+sfboffs] = sfbEnergySide[sfb+sfboffs]; + sfbEnergyLeftLdData[sfb+sfboffs] = sfbEnergyMidLdData[sfb+sfboffs]; + sfbEnergyRightLdData[sfb+sfboffs] = sfbEnergySideLdData[sfb+sfboffs]; + + sfbSpreadEnLeft[sfb+sfboffs] = sfbSpreadEnRight[sfb+sfboffs] = + fixMin( sfbSpreadEnLeft[sfb+sfboffs], + sfbSpreadEnRight[sfb+sfboffs] ) >> 1; + } + } + } + } else { + *msDigest = SI_MS_MASK_SOME; + } + } else { + *msDigest = SI_MS_MASK_NONE; + } +} diff --git a/libAACenc/src/ms_stereo.h b/libAACenc/src/ms_stereo.h new file mode 100644 index 00000000..2f3addbe --- /dev/null +++ b/libAACenc/src/ms_stereo.h @@ -0,0 +1,107 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: MS stereo processing + +******************************************************************************/ + +#ifndef __MS_STEREO_H__ +#define __MS_STEREO_H__ + + +#include "interface.h" + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL* psyOutChannel[2], + const INT *isBook, + INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset); + +#endif diff --git a/libAACenc/src/noisedet.cpp b/libAACenc/src/noisedet.cpp new file mode 100644 index 00000000..f3c51deb --- /dev/null +++ b/libAACenc/src/noisedet.cpp @@ -0,0 +1,228 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: noisedet.c + Routines for Noise Detection + +******************************************************************************/ + +#include "noisedet.h" + +#include "aacenc_pns.h" +#include "pnsparam.h" + + +/***************************************************************************** + + functionname: FDKaacEnc_fuzzyIsSmaller + description: Fuzzy value calculation for "testVal is smaller than refVal" + returns: fuzzy value + input: test and ref Value, + low and high Lim + output: return fuzzy value + +*****************************************************************************/ +static FIXP_SGL FDKaacEnc_fuzzyIsSmaller( FIXP_DBL testVal, + FIXP_DBL refVal, + FIXP_DBL loLim, + FIXP_DBL hiLim ) +{ + if (refVal <= FL2FXCONST_DBL(0.0)) + return( FL2FXCONST_SGL(0.0f) ); + else if (testVal >= fMult((hiLim>>1)+(loLim>>1), refVal)) + return( FL2FXCONST_SGL(0.0f) ); + else return( (FIXP_SGL)MAXVAL_SGL ); +} + + + +/***************************************************************************** + + functionname: FDKaacEnc_noiseDetect + description: detect tonal sfb's; two tests + Powerdistribution: + sfb splittet in four regions, + compare the energy in all sections + PsychTonality: + compare tonality from chaosmeasure with reftonality + returns: + input: spectrum of one large mdct + number of sfb's + pointer to offset of sfb's + pointer to noiseFuzzyMeasure (modified) + noiseparams struct + pointer to sfb energies + pointer to tonality calculated in chaosmeasure + output: noiseFuzzy Measure + +*****************************************************************************/ + +void FDKaacEnc_noiseDetect(FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + INT sfbActive, + const INT *RESTRICT sfbOffset, + FIXP_SGL *RESTRICT noiseFuzzyMeasure, + NOISEPARAMS *np, + FIXP_SGL *RESTRICT sfbtonality ) + +{ + int i, k, sfb, sfbWidth; + FIXP_SGL fuzzy, fuzzyTotal; + FIXP_DBL refVal, testVal; + + /***** Start detection phase *****/ + /* Start noise detection for each band based on a number of checks */ + for (sfb=0; sfbstartSfb || sfbWidth < np->minSfbWidth) { + noiseFuzzyMeasure[sfb] = FL2FXCONST_SGL(0.0f); + continue; + } + + if ( (np->detectionAlgorithmFlags & USE_POWER_DISTRIBUTION) && (fuzzyTotal > FL2FXCONST_SGL(0.5f)) ) { + FIXP_DBL fhelp1, fhelp2, fhelp3, fhelp4, maxVal, minVal; + INT leadingBits = fixMax(0,(sfbMaxScaleSpec[sfb] - 3)); /* max sfbWidth = 96/4 ; 2^5=32 => 5/2 = 3 (spc*spc) */ + + /* check power distribution in four regions */ + fhelp1 = fhelp2 = fhelp3 = fhelp4 = FL2FXCONST_DBL(0.0f); + k = sfbWidth >>2; /* Width of a quarter band */ + + for (i=sfbOffset[sfb]; ipowDistPSDcurve[sfb]); + + fuzzy = FDKaacEnc_fuzzyIsSmaller(testVal, /* 1/2 * maxValue * PSDcurve */ + refVal, /* 1 * minValue */ + FL2FXCONST_DBL(0.495), /* 1/2 * loLim (0.99f/2) */ + FL2FXCONST_DBL(0.505)); /* 1/2 * hiLim (1.01f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + if ( (np->detectionAlgorithmFlags & USE_PSYCH_TONALITY) && (fuzzyTotal > FL2FXCONST_SGL(0.5f)) ) { + /* Detection with tonality-value of psych. acoustic (here: 1 is tonal!)*/ + + testVal = FX_SGL2FX_DBL(sfbtonality[sfb])>>1; /* 1/2 * sfbTonality */ + refVal = np->refTonality; + + fuzzy = FDKaacEnc_fuzzyIsSmaller(testVal, + refVal, + FL2FXCONST_DBL(0.45f), /* 1/2 * loLim (0.9f/2) */ + FL2FXCONST_DBL(0.55f)); /* 1/2 * hiLim (1.1f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + + /* Output of final result */ + noiseFuzzyMeasure[sfb] = fuzzyTotal; + } +} diff --git a/libAACenc/src/noisedet.h b/libAACenc/src/noisedet.h new file mode 100644 index 00000000..8d5e365a --- /dev/null +++ b/libAACenc/src/noisedet.h @@ -0,0 +1,108 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: noisedet.h + +******************************************************************************/ + +#ifndef __NOISEDET_H +#define __NOISEDET_H + +#include "common_fix.h" + +#include "pnsparam.h" +#include "psy_data.h" + + +void FDKaacEnc_noiseDetect( FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + INT sfbActive, + const INT *sfbOffset, + FIXP_SGL noiseFuzzyMeasure[], + NOISEPARAMS *np, + FIXP_SGL *sfbtonality ); + +#endif diff --git a/libAACenc/src/pns_func.h b/libAACenc/src/pns_func.h new file mode 100644 index 00000000..efa44efa --- /dev/null +++ b/libAACenc/src/pns_func.h @@ -0,0 +1,150 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: pns_func.h + +******************************************************************************/ + +#ifndef _PNS_FUNC_H +#define _PNS_FUNC_H + +#include "common_fix.h" + +#include "aacenc_pns.h" +#include "psy_data.h" + + + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf, + INT bitRate, + INT sampleRate, + INT usePns, + INT sfbCnt, + const INT *sfbOffset, + const INT numChan, + const INT isLC ); + +void FDKaacEnc_PnsDetect( PNS_CONFIG *pnsConf, + PNS_DATA *pnsData, + const INT lastWindowSequence, + const INT sfbActive, + const INT maxSfbPerGroup, + FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, + FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + FIXP_SGL *sfbtonality, + int tnsOrder, + INT tnsPredictionGain, + INT tnsActive, + FIXP_DBL *sfbEnergyLdData, + INT *noiseNrg ); + +void FDKaacEnc_CodePnsChannel( const INT sfbActive, + PNS_CONFIG *pnsConf, + INT *pnsFlag, + FIXP_DBL *sfbEnergy, + INT *noiseNrg, + FIXP_DBL *sfbThreshold ); + +void FDKaacEnc_PreProcessPnsChannelPair( const INT sfbActive, + FIXP_DBL *sfbEnergyLeft, + FIXP_DBL *sfbEnergyRight, + FIXP_DBL *sfbEnergyLeftLD, + FIXP_DBL *sfbEnergyRightLD, + FIXP_DBL *sfbEnergyMid, + PNS_CONFIG *pnsConfLeft, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight ); + +void FDKaacEnc_PostProcessPnsChannelPair( const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, + INT *msMask, + INT *msDigest ); + +#endif /* _PNS_FUNC_H */ diff --git a/libAACenc/src/pnsparam.cpp b/libAACenc/src/pnsparam.cpp new file mode 100644 index 00000000..9d59ddcc --- /dev/null +++ b/libAACenc/src/pnsparam.cpp @@ -0,0 +1,311 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Lohwasser + contents/description: PNS parameters depending on bitrate and bandwidth + +******************************************************************************/ + +#include "pnsparam.h" +#include "psy_configuration.h" + +typedef struct { + SHORT startFreq; + /* Parameters for detection */ + FIXP_SGL refPower; + FIXP_SGL refTonality; + SHORT tnsGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + SHORT tnsPNSGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + FIXP_SGL gapFillThr; + SHORT minSfbWidth; + USHORT detectionAlgorithmFlags; +} PNS_INFO_TAB; + + +typedef struct { + ULONG brFrom; + ULONG brTo; + UCHAR S16000; + UCHAR S22050; + UCHAR S24000; + UCHAR S32000; + UCHAR S44100; + UCHAR S48000; +} AUTO_PNS_TAB; + +static const AUTO_PNS_TAB levelTable_mono[]= { + {0, 11999, 0, 1, 1, 1, 1, 1,}, + {12000, 19999, 0, 1, 1, 1, 1, 1,}, + {20000, 28999, 0, 2, 1, 1, 1, 1,}, + {29000, 40999, 0, 4, 4, 4, 2, 2,}, + {41000, 55999, 0, 9, 9, 7, 7, 7,}, + {56000, 61999, 0, 0, 0, 0, 9, 9,}, + {62000, 75999, 0, 0, 0, 0, 0, 0,}, + {76000, 92999, 0, 0, 0, 0, 0, 0,}, + {93000, 999999, 0, 0, 0, 0, 0, 0,}, +}; + +static const AUTO_PNS_TAB levelTable_stereo[]= { + {0, 11999, 0, 1, 1, 1, 1, 1,}, + {12000, 19999, 0, 3, 1, 1, 1, 1,}, + {20000, 28999, 0, 3, 3, 3, 2, 2,}, + {29000, 40999, 0, 7, 6, 6, 5, 5,}, + {41000, 55999, 0, 9, 9, 7, 7, 7,}, + {56000, 79999, 0, 0, 0, 0, 0, 0,}, + {80000, 99999, 0, 0, 0, 0, 0, 0,}, + {100000,999999, 0, 0, 0, 0, 0, 0,}, +}; + + +static const PNS_INFO_TAB pnsInfoTab[] = { +/*0 pns off */ +/*1*/ { 4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.06), 1150, 1200, FL2FXCONST_SGL(0.02), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS /*| JUST_LONG_WINDOW*/ }, +/*2*/ { 4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1130, 1300, FL2FXCONST_SGL(0.05), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS /*| JUST_LONG_WINDOW*/ }, +/*3*/ { 4100, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1100, 1400, FL2FXCONST_SGL(0.10), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS /*| JUST_LONG_WINDOW*/ }, +/*4*/ { 4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS /*| JUST_LONG_WINDOW*/ }, +/*5*/ { 4300, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*6*/ { 5000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, FL2FXCONST_SGL(0.25), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*7*/ { 5500, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1100, 1400, FL2FXCONST_SGL(0.35), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*8*/ { 6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1080, 1400, FL2FXCONST_SGL(0.40), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*9*/ { 6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.14), 1070, 1400, FL2FXCONST_SGL(0.45), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +}; + +static const AUTO_PNS_TAB levelTable_lowComplexity[]= { + {0, 27999, 0, 0, 0, 0, 0, 0,}, + {28000, 31999, 0, 2, 2, 2, 2, 2,}, + {32000, 47999, 0, 3, 3, 3, 3, 3,}, + {48000, 48000, 0, 4, 4, 4, 4, 4,}, + {48001, 999999, 0, 0, 0, 0, 0, 0,}, +}; + +/* conversion of old LC tuning tables to new (LD enc) structure (only entries which are actually used were converted) */ +static const PNS_INFO_TAB pnsInfoTab_lowComplexity[] = { +/*0 pns off */ + /* DEFAULT parameter set */ +/*1*/ { 4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.16), 1100, 1400, FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*2*/ { 4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1410, 1400, FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +/*3*/ { 4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1100, 1400, FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, + /* LOWSUBST -> PNS is used less often than with DEFAULT parameter set (for br: 48000 - 79999) */ +/*4*/ { 4100, FL2FXCONST_SGL(0.20), FL2FXCONST_SGL(0.10), 1410, 1400, FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | USE_TNS_PNS | JUST_LONG_WINDOW }, +}; + +/**************************************************************************** + function to look up used pns level +****************************************************************************/ +int FDKaacEnc_lookUpPnsUse (int bitRate, int sampleRate, int numChan, const int isLC) { + + int hUsePns=0, size, i; + const AUTO_PNS_TAB *levelTable; + + if (isLC) { + levelTable = &levelTable_lowComplexity[0]; + size = sizeof(levelTable_lowComplexity); + } else + { /* (E)LD */ + levelTable = (numChan > 1) ? &levelTable_stereo[0] : &levelTable_mono[0]; + size = (numChan > 1) ? sizeof(levelTable_stereo) : sizeof(levelTable_mono); + } + + for(i = 0; i < (int) (size/sizeof(AUTO_PNS_TAB)); i++) { + if(((ULONG)bitRate >= levelTable[i].brFrom) && + ((ULONG)bitRate <= levelTable[i].brTo) ) + break; + } + + /* sanity check */ + if ((int)(sizeof(pnsInfoTab)/sizeof(PNS_INFO_TAB)) < i ) { + return (PNS_TABLE_ERROR); + } + + switch (sampleRate) { + case 16000: hUsePns = levelTable[i].S16000; break; + case 22050: hUsePns = levelTable[i].S22050; break; + case 24000: hUsePns = levelTable[i].S24000; break; + case 32000: hUsePns = levelTable[i].S32000; break; + case 44100: hUsePns = levelTable[i].S44100; break; + case 48000: hUsePns = levelTable[i].S48000; break; + default: + if (isLC) { + hUsePns = levelTable[i].S48000; + } + break; + } + + return (hUsePns); +} + + +/***************************************************************************** + + functionname: FDKaacEnc_GetPnsParam + description: Gets PNS parameters depending on bitrate and bandwidth + returns: error status + input: Noiseparams struct, bitrate, sampling rate, + number of sfb's, pointer to sfb offset + output: PNS parameters + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, + INT bitRate, + INT sampleRate, + INT sfbCnt, + const INT *sfbOffset, + INT *usePns, + INT numChan, + const int isLC) + +{ + int i, hUsePns; + const PNS_INFO_TAB *pnsInfo; + + if (isLC) { + np->detectionAlgorithmFlags = IS_LOW_COMLEXITY; + pnsInfo = pnsInfoTab_lowComplexity; + } + else + { + np->detectionAlgorithmFlags = 0; + pnsInfo = pnsInfoTab; + } + + if (*usePns<=0) + return AAC_ENC_OK; + + /* new pns params */ + hUsePns = FDKaacEnc_lookUpPnsUse (bitRate, sampleRate, numChan, isLC); + if (hUsePns == 0) { + *usePns = 0; + return AAC_ENC_OK; + } + if (hUsePns == PNS_TABLE_ERROR) + return AAC_ENC_PNS_TABLE_ERROR; + + /* select correct row of tuning table */ + pnsInfo += hUsePns-1; + + np->startSfb = FDKaacEnc_FreqToBandWithRounding( pnsInfo->startFreq, + sampleRate, + sfbCnt, + sfbOffset ); + + np->detectionAlgorithmFlags |= pnsInfo->detectionAlgorithmFlags; + + np->refPower = FX_SGL2FX_DBL(pnsInfo->refPower); + np->refTonality = FX_SGL2FX_DBL(pnsInfo->refTonality); + np->tnsGainThreshold = pnsInfo->tnsGainThreshold; + np->tnsPNSGainThreshold = pnsInfo->tnsPNSGainThreshold; + np->minSfbWidth = pnsInfo->minSfbWidth; + + np->gapFillThr = (FIXP_SGL)pnsInfo->gapFillThr; + + /* assuming a constant dB/Hz slope in the signal's PSD curve, + the detection threshold needs to be corrected for the width of the band */ + for ( i = 0; i < (sfbCnt-1); i++) + { + INT qtmp, sfbWidth; + FIXP_DBL tmp; + + sfbWidth = sfbOffset[i+1]-sfbOffset[i]; + + tmp = fPow(np->refPower, 0, sfbWidth, DFRACT_BITS-1-5, &qtmp); + np->powDistPSDcurve[i] = (FIXP_SGL)((LONG)(scaleValue(tmp, qtmp) >> 16)); + } + np->powDistPSDcurve[sfbCnt] = np->powDistPSDcurve[sfbCnt-1]; + + return AAC_ENC_OK; +} diff --git a/libAACenc/src/pnsparam.h b/libAACenc/src/pnsparam.h new file mode 100644 index 00000000..08bb83e6 --- /dev/null +++ b/libAACenc/src/pnsparam.h @@ -0,0 +1,141 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Lohwasser + contents/description: PNS parameters depending on bitrate and bandwidth + +******************************************************************************/ + +#ifndef __PNSPARAM_H +#define __PNSPARAM_H + +#include "aacenc.h" +#include "common_fix.h" +#include "psy_const.h" + +#define NUM_PNSINFOTAB 4 +#define PNS_TABLE_ERROR -1 + +/* detection algorithm flags */ +#define USE_POWER_DISTRIBUTION (1<<0) +#define USE_PSYCH_TONALITY (1<<1) +#define USE_TNS_GAIN_THR (1<<2) +#define USE_TNS_PNS (1<<3) +#define JUST_LONG_WINDOW (1<<4) +/* additional algorithm flags */ +#define IS_LOW_COMLEXITY (1<<5) + +typedef struct +{ + /* PNS start band */ + short startSfb; + + /* detection algorithm flags */ + USHORT detectionAlgorithmFlags; + + /* Parameters for detection */ + FIXP_DBL refPower; + FIXP_DBL refTonality; + INT tnsGainThreshold; + INT tnsPNSGainThreshold; + INT minSfbWidth; + FIXP_SGL powDistPSDcurve[MAX_GROUPED_SFB]; + FIXP_SGL gapFillThr; +} NOISEPARAMS; + +int FDKaacEnc_lookUpPnsUse (int bitRate, int sampleRate, int numChan, const int isLC); + +/****** Definition of prototypes ******/ + +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, + INT bitRate, + INT sampleRate, + INT sfbCnt, + const INT *sfbOffset, + INT *usePns, + INT numChan, + const INT isLC); + +#endif diff --git a/libAACenc/src/pre_echo_control.cpp b/libAACenc/src/pre_echo_control.cpp new file mode 100644 index 00000000..3dfd8ed0 --- /dev/null +++ b/libAACenc/src/pre_echo_control.cpp @@ -0,0 +1,170 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Pre echo control + +******************************************************************************/ + +#include "pre_echo_control.h" +#include "psy_configuration.h" + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT *calcPreEcho, + INT numPb, + FIXP_DBL *RESTRICT sfbPcmQuantThreshold, + INT *mdctScalenm1) +{ + *mdctScalenm1 = PCM_QUANT_THR_SCALE>>1; + + FDKmemcpy(pbThresholdNm1, sfbPcmQuantThreshold, numPb*sizeof(FIXP_DBL)); + + *calcPreEcho = 1; +} + + +void FDKaacEnc_PreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT calcPreEcho, + INT numPb, + INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *RESTRICT pbThreshold, + INT mdctScale, + INT *mdctScalenm1) +{ + int i; + FIXP_DBL tmpThreshold1, tmpThreshold2; + int scaling; + + /* If lastWindowSequence in previous frame was start- or stop-window, + skip preechocontrol calculation */ + if (calcPreEcho==0) { + /* copy thresholds to internal memory */ + FDKmemcpy(pbThresholdNm1, pbThreshold, numPb*sizeof(FIXP_DBL)); + *mdctScalenm1 = mdctScale; + return; + } + + if ( mdctScale > *mdctScalenm1 ) { + /* if current thresholds are downscaled more than the ones from the last block */ + scaling = 2*(mdctScale-*mdctScalenm1); + for(i = 0; i < numPb; i++) { + + /* multiplication with return data type fract ist equivalent to int multiplication */ + FDK_ASSERT(scaling>=0); + tmpThreshold1 = maxAllowedIncreaseFactor * (pbThresholdNm1[i]>>scaling); + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + FIXP_DBL tmp = pbThreshold[i]; + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = tmp; + + tmp = fixMin(tmp, tmpThreshold1); + pbThreshold[i] = fixMax(tmp, tmpThreshold2); + } + } + else { + /* if thresholds of last block are more downscaled than the current ones */ + scaling = 2*(*mdctScalenm1-mdctScale); + for(i = 0; i < numPb; i++) { + + /* multiplication with return data type fract ist equivalent to int multiplication */ + tmpThreshold1 = (maxAllowedIncreaseFactor>>1) * pbThresholdNm1[i]; + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = pbThreshold[i]; + + FDK_ASSERT(scaling>=0); + if((pbThreshold[i]>>(scaling+1)) > tmpThreshold1) { + pbThreshold[i] = tmpThreshold1<<(scaling+1); + } + pbThreshold[i] = fixMax(pbThreshold[i], tmpThreshold2); + } + } + + *mdctScalenm1 = mdctScale; +} diff --git a/libAACenc/src/pre_echo_control.h b/libAACenc/src/pre_echo_control.h new file mode 100644 index 00000000..9224db0c --- /dev/null +++ b/libAACenc/src/pre_echo_control.h @@ -0,0 +1,114 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Pre echo control + +******************************************************************************/ + +#ifndef __PRE_ECHO_CONTROL_H +#define __PRE_ECHO_CONTROL_H + +#include "common_fix.h" + + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *pbThresholdnm1, + INT *calcPreEcho, + INT numPb, + FIXP_DBL *sfbPcmQuantThreshold, + INT *mdctScalenm1); + + +void FDKaacEnc_PreEchoControl(FIXP_DBL *pbThresholdNm1, + INT calcPreEcho, + INT numPb, + INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *pbThreshold, + INT mdctScale, + INT *mdctScalenm1); + +#endif + diff --git a/libAACenc/src/psy_configuration.cpp b/libAACenc/src/psy_configuration.cpp new file mode 100644 index 00000000..45b7d130 --- /dev/null +++ b/libAACenc/src/psy_configuration.cpp @@ -0,0 +1,829 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Psychoaccoustic configuration + +******************************************************************************/ + +#include "psy_configuration.h" +#include "adj_thr.h" +#include "aacEnc_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + +typedef struct{ + LONG sampleRate; + const SFB_PARAM_LONG *paramLong; + const SFB_PARAM_SHORT *paramShort; +}SFB_INFO_TAB; + + +static const SFB_INFO_TAB sfbInfoTab[] = { + {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128}, + {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128}, + {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128}, + {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128}, + {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128}, + {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128}, + {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128}, + {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128}, + {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128}, + {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128}, + {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128}, + {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128} + +}; + + + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_960 = { + 40, + { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, + 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + + +static const SFB_INFO_TAB sfbInfoTab960[] = { + { 8000, &p_FDKaacEnc_8000_long_960, &p_FDKaacEnc_8000_short_120}, + {11025, &p_FDKaacEnc_11025_long_960, &p_FDKaacEnc_11025_short_120}, + {12000, &p_FDKaacEnc_12000_long_960, &p_FDKaacEnc_12000_short_120}, + {16000, &p_FDKaacEnc_16000_long_960, &p_FDKaacEnc_16000_short_120}, + {22050, &p_FDKaacEnc_22050_long_960, &p_FDKaacEnc_22050_short_120}, + {24000, &p_FDKaacEnc_24000_long_960, &p_FDKaacEnc_24000_short_120}, + {32000, &p_FDKaacEnc_32000_long_960, &p_FDKaacEnc_32000_short_120}, + {44100, &p_FDKaacEnc_44100_long_960, &p_FDKaacEnc_44100_short_120}, + {48000, &p_FDKaacEnc_48000_long_960, &p_FDKaacEnc_48000_short_120}, + {64000, &p_FDKaacEnc_64000_long_960, &p_FDKaacEnc_64000_short_120}, + {88200, &p_FDKaacEnc_88200_long_960, &p_FDKaacEnc_88200_short_120}, + {96000, &p_FDKaacEnc_96000_long_960, &p_FDKaacEnc_96000_short_120}, +}; + + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_512 = { + 31, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 8, 8, 8, 12, 12, 12, 16, 20, 24, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32} +}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_512 = { + 37, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, + 32, 32, 32, 32, 32, 32, 32} +}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_512 = { + 36, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, + 32, 32, 32, 32, 32, 52} +}; + +static const SFB_INFO_TAB sfbInfoTabLD512[] = { + { 8000, &p_22050_long_512, NULL}, + {11025, &p_22050_long_512, NULL}, + {12000, &p_22050_long_512, NULL}, + {16000, &p_22050_long_512, NULL}, + {22050, &p_22050_long_512, NULL}, + {24000, &p_22050_long_512, NULL}, + {32000, &p_32000_long_512, NULL}, + {44100, &p_44100_long_512, NULL}, + {48000, &p_44100_long_512, NULL}, + {64000, &p_44100_long_512, NULL}, + {88200, &p_44100_long_512, NULL}, + {96000, &p_44100_long_512, NULL}, + +}; + + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_480 = { + 30, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 8, 8, 8, 12, 12, 12, 16, 20, 24, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32} +}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_480 = { + 37, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, + 32, 32, 32, 32, 32, 32, 32} +}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_480 = { + 35, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, + 32, 32, 32, 32, 48} +}; + +static const SFB_INFO_TAB sfbInfoTabLD480[] = { + { 8000, &p_22050_long_480, NULL}, + {11025, &p_22050_long_480, NULL}, + {12000, &p_22050_long_480, NULL}, + {16000, &p_22050_long_480, NULL}, + {22050, &p_22050_long_480, NULL}, + {24000, &p_22050_long_480, NULL}, + {32000, &p_32000_long_480, NULL}, + {44100, &p_44100_long_480, NULL}, + {48000, &p_44100_long_480, NULL}, + {64000, &p_44100_long_480, NULL}, + {88200, &p_44100_long_480, NULL}, + {96000, &p_44100_long_480, NULL}, + +}; + +/* Fixed point precision definitions */ +#define Q_BARCVAL (25) + +static AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(LONG sampleRate, INT blockType, INT granuleLength, INT *sfbOffset, INT *sfbCnt) +{ + INT i, specStartOffset = 0; + const UCHAR* sfbWidth = NULL; + const SFB_INFO_TAB *sfbInfo = NULL; + int size; + + /* + select table + */ + switch(granuleLength) { + case 1024: + sfbInfo = sfbInfoTab; + size = (INT)(sizeof(sfbInfoTab)/sizeof(SFB_INFO_TAB)); + break; + case 960: + sfbInfo = sfbInfoTab960; + size = (INT)(sizeof(sfbInfoTab960)/sizeof(SFB_INFO_TAB)); + break; + case 512: + sfbInfo = sfbInfoTabLD512; + size = sizeof(sfbInfoTabLD512); + break; + case 480: + sfbInfo = sfbInfoTabLD480; + size = sizeof(sfbInfoTabLD480); + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + for(i = 0; i < size; i++){ + if(sfbInfo[i].sampleRate == sampleRate){ + switch(blockType){ + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sfbWidth = sfbInfo[i].paramLong->sfbWidth; + *sfbCnt = sfbInfo[i].paramLong->sfbCnt; + break; + case SHORT_WINDOW: + sfbWidth = sfbInfo[i].paramShort->sfbWidth; + *sfbCnt = sfbInfo[i].paramShort->sfbCnt; + granuleLength /= TRANS_FAC; + break; + } + break; + } + } + if (i == size) { + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* + calc sfb offsets + */ + for(i = 0; i < *sfbCnt; i++){ + sfbOffset[i] = specStartOffset; + specStartOffset += sfbWidth[i]; + if (specStartOffset >= granuleLength) { + i++; + break; + } + } + *sfbCnt = fixMin(i,*sfbCnt); + sfbOffset[*sfbCnt] = fixMin(specStartOffset,granuleLength); + + return AAC_ENC_OK; +} + + +/***************************************************************************** + + functionname: FDKaacEnc_BarcLineValue + description: Calculates barc value for one frequency line + returns: barc value of line + input: number of lines in transform, index of line to check, Fs + output: + +*****************************************************************************/ +static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine, LONG samplingFreq) +{ + + FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */ + FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a; /* 0.00076 in q41 */ + FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333; /* 13.3 in q26 */ + FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000; /* 3.5 in q27 */ + FIXP_DBL INV480 = (FIXP_DBL)0x44444444; // 1/480 in q39 + + FIXP_DBL center_freq, x1, x2; + FIXP_DBL bvalFFTLine, atan1, atan2; + + /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000 */ + /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in q28 */ + /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in q25 */ + + center_freq = fftLine * samplingFreq; /* q11 or q8 */ + + switch (noOfLines) { + case 1024: + center_freq = center_freq << 2; /* q13 */ + break; + case 960: + center_freq = fMult(center_freq, INV480) << 3; + break; + case 128: + center_freq = center_freq << 5; /* q13 */ + break; + case 120: + center_freq = fMult(center_freq, INV480) << 6; + break; + case 512: + center_freq = (fftLine * samplingFreq) << 3; // q13 + break; + case 480: + center_freq = fMult(center_freq, INV480) << 4; // q13 + break; + default: + center_freq = (FIXP_DBL)0; + } + + x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */ + x2 = fMult(center_freq, PZZZ76) << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */ + + atan1 = fixp_atan(x1); + atan2 = fixp_atan(x2); + + /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */ + bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1)); + return(bvalFFTLine); + +} + +/* + do not consider energies below a certain input signal level, + i.e. of -96dB or 1 bit at 16 bit PCM resolution, + might need to be configurable to e.g. 24 bit PCM Input or a lower + resolution for low bit rates +*/ +static void FDKaacEnc_InitMinPCMResolution(int numPb, + int *pbOffset, + FIXP_DBL *sfbPCMquantThreshold) +{ + /* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY * FDKpow(2,PCM_QUANT_THR_SCALE) */ + #define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062) + + for( int i = 0; i < numPb; i++ ) { + sfbPCMquantThreshold[i] = (pbOffset[i+1] - pbOffset[i]) * PCM_QUANT_NOISE; + } +} + +static FIXP_DBL getMaskFactor( + const FIXP_DBL dbVal_fix, + const INT dbVal_e, + const FIXP_DBL ten_fix, + const INT ten_e + ) +{ + INT q_msk; + FIXP_DBL mask_factor; + + mask_factor = fPow(ten_fix, DFRACT_BITS-1-ten_e, -dbVal_fix, DFRACT_BITS-1-dbVal_e, &q_msk); + q_msk = fixMin(DFRACT_BITS-1,fixMax(-(DFRACT_BITS-1),q_msk)); + + if ( (q_msk>0) && (mask_factor>(FIXP_DBL)MAXVAL_DBL>>q_msk) ) { + mask_factor = (FIXP_DBL)MAXVAL_DBL; + } + else { + mask_factor = scaleValue(mask_factor, q_msk); + } + + return (mask_factor); +} + +static void FDKaacEnc_initSpreading(INT numPb, + FIXP_DBL *pbBarcValue, + FIXP_DBL *pbMaskLoFactor, + FIXP_DBL *pbMaskHiFactor, + FIXP_DBL *pbMaskLoFactorSprEn, + FIXP_DBL *pbMaskHiFactorSprEn, + const LONG bitrate, + const INT blockType) + +{ + INT i; + FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN; + + FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL TEN = (FIXP_DBL)0x50000000; /* 10.0 in q27 */ + + if (blockType != SHORT_WINDOW) + { + MASKLOWSPREN = MASKLOWSPRENLONG; + MASKHIGHSPREN = (bitrate>20000)?MASKHIGHSPRENLONG:MASKHIGHSPRENLONGLOWBR; + } + else + { + MASKLOWSPREN = MASKLOWSPRENSHORT; + MASKHIGHSPREN = MASKHIGHSPRENSHORT; + } + + for(i=0; i 0) + { + pbMaskHiFactor[i] = getMaskFactor( + fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i-1])), 23, + TEN, 27); + + pbMaskLoFactor[i-1] = getMaskFactor( + fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i-1])), 23, + TEN, 27); + + pbMaskHiFactorSprEn[i] = getMaskFactor( + fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i-1])), 23, + TEN, 27); + + pbMaskLoFactorSprEn[i-1] = getMaskFactor( + fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i-1])), 23, + TEN, 27); + } + else + { + pbMaskHiFactor[i] = (FIXP_DBL)0; + pbMaskLoFactor[numPb-1] = (FIXP_DBL)0; + pbMaskHiFactorSprEn[i] = (FIXP_DBL)0; + pbMaskLoFactorSprEn[numPb-1] = (FIXP_DBL)0; + } + } +} + +static void FDKaacEnc_initBarcValues(INT numPb, + INT *pbOffset, + INT numLines, + INT samplingFrequency, + FIXP_DBL *pbBval) +{ + INT i; + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + + for(i=0; i> 1) + (v2 >> 1); + pbBval[i] = fixMin(cur_bark, MAX_BARC); + } +} + +static void FDKaacEnc_initMinSnr(const LONG bitrate, + const LONG samplerate, + const INT numLines, + const INT *sfbOffset, + const INT sfbActive, + const INT blockType, + FIXP_DBL *sfbMinSnrLdData) +{ + INT sfb; + + /* Fix conversion variables */ + INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt; + INT qtmp, qsnr, sfbWidth; + + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */ + FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */ + FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2; /* 0.024 in q36 */ + FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000; /* 1.5 in q30 */ + FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333; /* 0.8 in q30 */ + FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9; /* 0.003 in q30 */ + + FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth; + FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5; + + /* relative number of active barks */ + barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfbActive], samplerate), MAX_BARC), + MAX_BARCP1, &qbfac); + + qbfac = DFRACT_BITS-1-qbfac; + + pePerWindow = fDivNorm(bitrate, samplerate, &qperwin); + qperwin = DFRACT_BITS-1-qperwin; + pePerWindow = fMult(pePerWindow, BITS2PEFAC); qperwin = qperwin + 30 - (DFRACT_BITS-1); + pePerWindow = fMult(pePerWindow, PERS2P4); qperwin = qperwin + 36 - (DFRACT_BITS-1); + + switch (numLines) { + case 1024: + qperwin = qperwin - 10; + break; + case 128: + qperwin = qperwin - 7; + break; + case 512: + qperwin = qperwin - 9; + break; + case 480: + qperwin = qperwin - 9; + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f/512.f)); + break; + case 960: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(960.f/1024.f)); + qperwin = qperwin - 10; + break; + case 120: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(120.f/128.f)); + qperwin = qperwin - 7; + break; + } + + /* for short blocks it is assumed that more bits are available */ + if (blockType == SHORT_WINDOW) + { + pePerWindow = fMult(pePerWindow, ONEP5); + qperwin = qperwin + 30 - (DFRACT_BITS-1); + } + pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv); qpeprt_const = qperwin - qbfac + DFRACT_BITS-1-qdiv; + + for (sfb = 0; sfb < sfbActive; sfb++) + { + barcWidth = FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb+1], samplerate) - + FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate); + + /* adapt to sfb bands */ + pePart = fMult(pePart_const, barcWidth); qpeprt = qpeprt_const + 25 - (DFRACT_BITS-1); + + /* pe -> snr calculation */ + sfbWidth = (sfbOffset[sfb+1] - sfbOffset[sfb]); + pePart = fDivNorm(pePart, sfbWidth, &qdiv); qpeprt += DFRACT_BITS-1-qdiv; + + tmp = f2Pow(pePart, DFRACT_BITS-1-qpeprt, &qtmp); + qtmp = DFRACT_BITS-1-qtmp; + + /* Subtract 1.5 */ + qsnr = fixMin(qtmp, 30); + tmp = tmp >> (qtmp - qsnr); + + if((30+1-qsnr) > (DFRACT_BITS-1)) + one_point5 = (FIXP_DBL)0; + else + one_point5 = (FIXP_DBL)(ONEP5 >> (30+1-qsnr)); + + snr = (tmp>>1) - (one_point5); qsnr -= 1; + + /* max(snr, 1.0) */ + if(qsnr > 0) + one_qsnr = (FIXP_DBL)(1 << qsnr); + else + one_qsnr = (FIXP_DBL)0; + + snr = fixMax(one_qsnr, snr); + + /* 1/snr */ + snr = fDivNorm(one_qsnr, snr, &qsnr); + qsnr = DFRACT_BITS-1-qsnr; + snr = (qsnr > 30)? (snr>>(qsnr-30)):snr; + + /* upper limit is -1 dB */ + snr = (snr > MAX_SNR) ? MAX_SNR : snr; + + /* lower limit is -25 dB */ + snr = (snr < MIN_SNR) ? MIN_SNR : snr; + snr = snr << 1; + + sfbMinSnrLdData[sfb] = CalcLdData(snr); + } +} + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, + INT samplerate, + INT bandwidth, + INT blocktype, + INT granuleLength, + INT useIS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank) +{ + AAC_ENCODER_ERROR ErrorStatus; + INT sfb; + FIXP_DBL sfbBarcVal[MAX_SFB]; + const INT frameLengthLong = granuleLength; + const INT frameLengthShort = granuleLength/TRANS_FAC; + + FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION)); + psyConf->granuleLength = granuleLength; + psyConf->filterbank = filterbank; + + psyConf->allowIS = (useIS) && ( (bitrate/bandwidth) < 5 ); + + /* init sfb table */ + ErrorStatus = FDKaacEnc_initSfbTable(samplerate,blocktype,granuleLength,psyConf->sfbOffset,&psyConf->sfbCnt); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + /* calculate barc values for each pb */ + FDKaacEnc_initBarcValues(psyConf->sfbCnt, + psyConf->sfbOffset, + psyConf->sfbOffset[psyConf->sfbCnt], + samplerate, + sfbBarcVal); + + FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, + psyConf->sfbOffset, + psyConf->sfbPcmQuantThreshold); + + /* calculate spreading function */ + FDKaacEnc_initSpreading(psyConf->sfbCnt, + sfbBarcVal, + psyConf->sfbMaskLowFactor, + psyConf->sfbMaskHighFactor, + psyConf->sfbMaskLowFactorSprEn, + psyConf->sfbMaskHighFactorSprEn, + bitrate, + blocktype); + + /* init ratio */ + + psyConf->maxAllowedIncreaseFactor = 2; /* integer */ + psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148; /* FL2FXCONST_SGL(0.01f); */ /* fract */ + + psyConf->clipEnergy = (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */ + + if (blocktype!=SHORT_WINDOW) { + psyConf->lowpassLine = (INT)((2*bandwidth*frameLengthLong)/samplerate); + psyConf->lowpassLineLFE = LFE_LOWPASS_LINE; + } + else { + psyConf->lowpassLine = (INT)((2*bandwidth*frameLengthShort)/samplerate); + psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */ + /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */ + psyConf->clipEnergy >>= 6; + } + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++){ + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) + break; + } + psyConf->sfbActive = FDKmax(sfb, 1); + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++){ + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) + break; + } + psyConf->sfbActiveLFE = sfb; + psyConf->sfbActive = FDKmax(psyConf->sfbActive, psyConf->sfbActiveLFE); + + /* calculate minSnr */ + FDKaacEnc_initMinSnr(bitrate, + samplerate, + psyConf->sfbOffset[psyConf->sfbCnt], + psyConf->sfbOffset, + psyConf->sfbActive, + blocktype, + psyConf->sfbMinSnrLdData); + + return AAC_ENC_OK; +} + diff --git a/libAACenc/src/psy_configuration.h b/libAACenc/src/psy_configuration.h new file mode 100644 index 00000000..36292469 --- /dev/null +++ b/libAACenc/src/psy_configuration.h @@ -0,0 +1,165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Psychoaccoustic configuration + +******************************************************************************/ + +#ifndef _PSY_CONFIGURATION_H +#define _PSY_CONFIGURATION_H + + +#include "aacenc.h" +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" +#include "aacenc_pns.h" + +#define THR_SHIFTBITS 4 +#define PCM_QUANT_THR_SCALE 16 + +#define C_RATIO (FIXP_DBL)0x02940a10 /* FL2FXCONST_DBL(0.001258925f) << THR_SHIFTBITS; */ /* pow(10.0f, -(29.0f/10.0f)) */ + +typedef struct{ + + INT sfbCnt; /* number of existing sf bands */ + INT sfbActive; /* number of sf bands containing energy after lowpass */ + INT sfbActiveLFE; + INT sfbOffset[MAX_SFB+1]; + + INT filterbank; /* LC, LD or ELD */ + + FIXP_DBL sfbPcmQuantThreshold[MAX_SFB]; + + INT maxAllowedIncreaseFactor; /* preecho control */ + FIXP_SGL minRemainingThresholdFactor; + + INT lowpassLine; + INT lowpassLineLFE; + FIXP_DBL clipEnergy; /* for level dependend tmn */ + + FIXP_DBL sfbMaskLowFactor[MAX_SFB]; + FIXP_DBL sfbMaskHighFactor[MAX_SFB]; + + FIXP_DBL sfbMaskLowFactorSprEn[MAX_SFB]; + FIXP_DBL sfbMaskHighFactorSprEn[MAX_SFB]; + + FIXP_DBL sfbMinSnrLdData[MAX_SFB]; /* minimum snr (formerly known as bmax) */ + + TNS_CONFIG tnsConf; + PNS_CONFIG pnsConf; + + INT granuleLength; + INT allowIS; + +}PSY_CONFIGURATION; + + +typedef struct{ + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR sfbWidth[MAX_SFB_LONG]; /* Width of scalefactor bands for long blocks */ +}SFB_PARAM_LONG; + +typedef struct{ + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR sfbWidth[MAX_SFB_SHORT]; /* Width of scalefactor bands for short blocks */ +}SFB_PARAM_SHORT; + + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, + INT samplerate, + INT bandwidth, + INT blocktype, + INT granuleLength, + INT useIS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank); + +#endif /* _PSY_CONFIGURATION_H */ + + + diff --git a/libAACenc/src/psy_const.h b/libAACenc/src/psy_const.h new file mode 100644 index 00000000..15a69c97 --- /dev/null +++ b/libAACenc/src/psy_const.h @@ -0,0 +1,161 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Global psychoaccoustic constants + +******************************************************************************/ +#ifndef _PSYCONST_H +#define _PSYCONST_H + + +#define TRUE 1 +#define FALSE 0 + + #define TRANS_FAC 8 /* encoder short long ratio */ + +#define FRAME_LEN_LONG_960 (960) +#define FRAME_MAXLEN_SHORT ((1024)/TRANS_FAC) +#define FRAME_LEN_SHORT_128 ((1024)/TRANS_FAC) + +/* Filterbank type*/ +enum FB_TYPE { + FB_LC = 0, + FB_LD = 1, + FB_ELD = 2 +}; + +/* Block types */ +#define N_BLOCKTYPES 6 +enum +{ + LONG_WINDOW = 0, + START_WINDOW, + SHORT_WINDOW, + STOP_WINDOW, + _LOWOV_WINDOW, /* Do not use this block type out side of block_switch.cpp */ + WRONG_WINDOW +}; + +/* Window shapes */ +enum +{ + SINE_WINDOW = 0, + KBD_WINDOW = 1, + LOL_WINDOW = 2 /* Low OverLap window shape for AAC-LD */ +}; + +/* + MS stuff +*/ +enum +{ + SI_MS_MASK_NONE = 0, + SI_MS_MASK_SOME = 1, + SI_MS_MASK_ALL = 2 +}; + + + #define MAX_NO_OF_GROUPS 4 + #define MAX_SFB_LONG 51 /* 51 for a memory optimized implementation, maybe 64 for convenient debugging */ + #define MAX_SFB_SHORT 15 /* 15 for a memory optimized implementation, maybe 16 for convenient debugging */ + +#define MAX_SFB (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = 51 */ +#define MAX_GROUPED_SFB (MAX_NO_OF_GROUPS*MAX_SFB_SHORT > MAX_SFB_LONG ? \ + MAX_NO_OF_GROUPS*MAX_SFB_SHORT : MAX_SFB_LONG) /* = 60 */ + +#define MAX_INPUT_BUFFER_SIZE (2*(1024)) /* 2048 */ + + +#define PCM_LEVEL 1.0f +#define NORM_PCM (PCM_LEVEL/32768.0f) +#define NORM_PCM_ENERGY (NORM_PCM*NORM_PCM) +#define LOG_NORM_PCM -15 + +#define TNS_PREDGAIN_SCALE (1000) + +#define LFE_LOWPASS_LINE 12 + +#endif /* _PSYCONST_H */ diff --git a/libAACenc/src/psy_data.h b/libAACenc/src/psy_data.h new file mode 100644 index 00000000..7183955f --- /dev/null +++ b/libAACenc/src/psy_data.h @@ -0,0 +1,152 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Psychoaccoustic data + +******************************************************************************/ + +#ifndef _PSY_DATA_H +#define _PSY_DATA_H + + +#include "block_switch.h" + +/* Be careful with MAX_SFB_LONG as length of the .Long arrays. + * sfbEnergy.Long and sfbEnergyMS.Long and sfbThreshold.Long are used as a temporary storage for the regrouped + * short energies and thresholds between FDKaacEnc_groupShortData() and BuildInterface() in FDKaacEnc_psyMain(). + * The space required for this is MAX_GROUPED_SFB ( = MAX_NO_OF_GROUPS*MAX_SFB_SHORT ). + * However, this is not important if unions are used (which is not possible with pfloat). */ + +typedef shouldBeUnion{ + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_THRESHOLD; + +typedef shouldBeUnion{ + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_ENERGY; + +typedef shouldBeUnion{ + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_LD_ENERGY; + +typedef shouldBeUnion{ + INT Long[MAX_GROUPED_SFB]; + INT Short[TRANS_FAC][MAX_SFB_SHORT]; +}SFB_MAX_SCALE; + + +typedef struct{ + INT_PCM* psyInputBuffer; + FIXP_DBL overlapAddBuffer[1024]; + + BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */ + FIXP_DBL sfbThresholdnm1[MAX_SFB]; /* FDKaacEnc_PreEchoControl */ + INT mdctScalenm1; /* scale of last block's mdct (FDKaacEnc_PreEchoControl) */ + INT calcPreEcho; + INT isLFE; +}PSY_STATIC; + + +typedef struct{ + FIXP_DBL *mdctSpectrum; + SFB_THRESHOLD sfbThreshold; /* adapt */ + SFB_ENERGY sfbEnergy; /* sfb energies */ + SFB_LD_ENERGY sfbEnergyLdData; /* sfb energies in ldData format */ + SFB_MAX_SCALE sfbMaxScaleSpec; + SFB_ENERGY sfbEnergyMS; /* mid/side sfb energies */ + FIXP_DBL sfbEnergyMSLdData[MAX_GROUPED_SFB]; /* mid/side sfb energies in ldData format */ + SFB_ENERGY sfbSpreadEnergy; + INT mdctScale; /* exponent of data in mdctSpectrum */ + INT groupedSfbOffset[MAX_GROUPED_SFB+1]; + INT sfbActive; + INT lowpassLine; +}PSY_DATA; + + +#endif /* _PSY_DATA_H */ diff --git a/libAACenc/src/psy_main.cpp b/libAACenc/src/psy_main.cpp new file mode 100644 index 00000000..eeb0fa26 --- /dev/null +++ b/libAACenc/src/psy_main.cpp @@ -0,0 +1,1387 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Psychoaccoustic major function block + +******************************************************************************/ + +#include "psy_const.h" + +#include "block_switch.h" +#include "transform.h" +#include "spreading.h" +#include "pre_echo_control.h" +#include "band_nrg.h" +#include "psy_configuration.h" +#include "psy_data.h" +#include "ms_stereo.h" +#include "interface.h" +#include "psy_main.h" +#include "grp_data.h" +#include "tns_func.h" +#include "pns_func.h" +#include "tonality.h" +#include "aacEnc_ram.h" +#include "intensity.h" + + + +/* blending to reduce gibbs artifacts */ +#define FADE_OUT_LEN 6 +static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016}; + +/* forward definitions */ + + +/***************************************************************************** + + functionname: FDKaacEnc_PsyNew + description: allocates memory for psychoacoustic + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, + const INT nElements, + const INT nChannels + ,UCHAR *dynamic_RAM + ) +{ + AAC_ENCODER_ERROR ErrorStatus; + PSY_INTERNAL *hPsy; + INT i; + + hPsy = GetRam_aacEnc_PsyInternal(); + *phpsy = hPsy; + if (hPsy == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + + for (i=0; ipsyElement[i] = GetRam_aacEnc_PsyElement(i); + if (hPsy->psyElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + for (i=0; ipStaticChannels[i] = GetRam_aacEnc_PsyStatic(i); + if (hPsy->pStaticChannels[i]==NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + /* AUDIO INPUT BUFFER */ + hPsy->pStaticChannels[i]->psyInputBuffer = GetRam_aacEnc_PsyInputBuffer(i); + if (hPsy->pStaticChannels[i]->psyInputBuffer==NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + /* reusable psych memory */ + hPsy->psyDynamic = GetRam_aacEnc_PsyDynamic(0, dynamic_RAM); + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(phpsy, NULL); + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_PsyOutNew + description: allocates memory for psyOut struc + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, + const INT nElements, + const INT nChannels, + const INT nSubFrames + ,UCHAR *dynamic_RAM + ) +{ + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n=0; npPsyOutChannels[i] = GetRam_aacEnc_PsyOutChannel(chInc++); + } + + for (i=0; ipsyOutElement[i] = GetRam_aacEnc_PsyOutElements(elInc++); + if (phpsyOut[n]->psyOutElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + } /* nSubFrames */ + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(NULL, phpsyOut); + return ErrorStatus; +} + + +AAC_ENCODER_ERROR FDKaacEnc_psyInitStates(PSY_INTERNAL *hPsy, + PSY_STATIC* psyStatic, + AUDIO_OBJECT_TYPE audioObjectType) +{ + /* init input buffer */ + FDKmemclear(psyStatic->psyInputBuffer, MAX_INPUT_BUFFER_SIZE*sizeof(INT_PCM)); + + FDKaacEnc_InitBlockSwitching(&psyStatic->blockSwitchingControl, + isLowDelay(audioObjectType) + ); + + return AAC_ENC_OK; +} + + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, + PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm) +{ + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, ch, n, chInc = 0, resetChannels = 3; + + if ( (nMaxChannels>2) && (cm->nChannels==2) ) { + chInc = 1; + FDKaacEnc_psyInitStates(hPsy, hPsy->pStaticChannels[0], audioObjectType); + } + + if ( (nMaxChannels==2) ) { + resetChannels = 0; + } + + for (i=0; inElements; i++) { + for (ch=0; chelInfo[i].nChannelsInEl; ch++) { + if (cm->elInfo[i].elType!=ID_LFE) { + hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[chInc]; + if (chInc>=resetChannels) { + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], audioObjectType); + } + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 0; + } + else { + hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[nMaxChannels-1]; + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 1; + } + chInc++; + } + } + + for (n=0; nnElements; i++) { + for (ch=0; chelInfo[i].nChannelsInEl; ch++) { + phpsyOut[n]->psyOutElement[i]->psyOutChannel[ch] = phpsyOut[n]->pPsyOutChannels[chInc++]; + } + } + } + + return ErrorStatus; +} + + +/***************************************************************************** + + functionname: FDKaacEnc_psyMainInit + description: initializes psychoacoustic + returns: an error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy, + AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm, + INT sampleRate, + INT granuleLength, + INT bitRate, + INT tnsMask, + INT bandwidth, + INT usePns, + INT useIS, + UINT syntaxFlags, + ULONG initFlags) +{ + AAC_ENCODER_ERROR ErrorStatus; + int i, ch; + int channelsEff = cm->nChannelsEff; + int tnsChannels = 0; + FB_TYPE filterBank; + + + switch(FDKaacEnc_GetMonoStereoMode(cm->encMode)) { + /* ... and map to tnsChannels */ + case EL_MODE_MONO: tnsChannels = 1; break; + case EL_MODE_STEREO: tnsChannels = 2; break; + default: tnsChannels = 0; + } + + switch (audioObjectType) + { + default: filterBank = FB_LC; break; + case AOT_ER_AAC_LD: filterBank = FB_LD; break; + case AOT_ER_AAC_ELD: filterBank = FB_ELD; break; + } + + hPsy->granuleLength = granuleLength; + + ErrorStatus = FDKaacEnc_InitPsyConfiguration(bitRate/channelsEff, sampleRate, bandwidth, LONG_WINDOW, hPsy->granuleLength, useIS, &(hPsy->psyConf[0]), filterBank); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate*tnsChannels)/channelsEff, + sampleRate, + tnsChannels, + LONG_WINDOW, + hPsy->granuleLength, + isLowDelay(audioObjectType), + (syntaxFlags&AC_SBR_PRESENT)?1:0, + &(hPsy->psyConf[0].tnsConf), + &hPsy->psyConf[0], + (INT)(tnsMask&2), + (INT)(tnsMask&8) ); + + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + if (granuleLength > 512) { + ErrorStatus = FDKaacEnc_InitPsyConfiguration(bitRate/channelsEff, sampleRate, bandwidth, SHORT_WINDOW, hPsy->granuleLength, useIS, &hPsy->psyConf[1], filterBank); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate*tnsChannels)/channelsEff, + sampleRate, + tnsChannels, + SHORT_WINDOW, + hPsy->granuleLength, + isLowDelay(audioObjectType), + (syntaxFlags&AC_SBR_PRESENT)?1:0, + &hPsy->psyConf[1].tnsConf, + &hPsy->psyConf[1], + (INT)(tnsMask&1), + (INT)(tnsMask&4) ); + + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + } + + + for (i=0; inElements; i++) { + for (ch=0; chelInfo[i].nChannelsInEl; ch++) { + if (initFlags) { + /* reset states */ + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], audioObjectType); + } + + FDKaacEnc_InitPreEchoControl(hPsy->psyElement[i]->psyStatic[ch]->sfbThresholdnm1, + &hPsy->psyElement[i]->psyStatic[ch]->calcPreEcho, + hPsy->psyConf[0].sfbCnt, + hPsy->psyConf[0].sfbPcmQuantThreshold, + &hPsy->psyElement[i]->psyStatic[ch]->mdctScalenm1); + } + } + + ErrorStatus = FDKaacEnc_InitPnsConfiguration(&hPsy->psyConf[0].pnsConf, + bitRate/channelsEff, + sampleRate, + usePns, + hPsy->psyConf[0].sfbCnt, + hPsy->psyConf[0].sfbOffset, + cm->elInfo[0].nChannelsInEl, + (hPsy->psyConf[0].filterbank == FB_LC)); + if (ErrorStatus != AAC_ENC_OK) + return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitPnsConfiguration(&hPsy->psyConf[1].pnsConf, + bitRate/channelsEff, + sampleRate, + usePns, + hPsy->psyConf[1].sfbCnt, + hPsy->psyConf[1].sfbOffset, + cm->elInfo[1].nChannelsInEl, + (hPsy->psyConf[1].filterbank == FB_LC)); + return ErrorStatus; +} + + +static +void FDKaacEnc_deinterleaveInputBuffer(INT_PCM *pOutputSamples, + INT_PCM *pInputSamples, + INT nSamples, + INT nChannels) +{ + INT k; + /* deinterlave input samples and write to output buffer */ + for (k=0; kpsyOutChannel; + FIXP_SGL sfbTonality[(2)][MAX_SFB_LONG]; + + PSY_STATIC **RESTRICT psyStatic = psyElement->psyStatic; + + PSY_DATA *RESTRICT psyData[(2)]; + TNS_DATA *RESTRICT tnsData[(2)]; + PNS_DATA *RESTRICT pnsData[(2)]; + + INT zeroSpec = TRUE; /* means all spectral lines are zero */ + + INT blockSwitchingOffset; + + PSY_CONFIGURATION *RESTRICT hThisPsyConf[(2)]; + INT windowLength[(2)]; + INT nWindows[(2)]; + INT wOffset; + + INT maxSfb[(2)]; + INT *pSfbMaxScaleSpec[(2)]; + FIXP_DBL *pSfbEnergy[(2)]; + FIXP_DBL *pSfbSpreadEnergy[(2)]; + FIXP_DBL *pSfbEnergyLdData[(2)]; + FIXP_DBL *pSfbEnergyMS[(2)]; + FIXP_DBL *pSfbThreshold[(2)]; + + INT isShortWindow[(2)]; + + + if (hPsyConfLong->filterbank == FB_LC) { + blockSwitchingOffset = psyConf->granuleLength + (9*psyConf->granuleLength/(2*TRANS_FAC)); + } else { + blockSwitchingOffset = psyConf->granuleLength; + } + + for(ch = 0; ch < channels; ch++) + { + psyData[ch] = &psyDynamic->psyData[ch]; + tnsData[ch] = &psyDynamic->tnsData[ch]; + pnsData[ch] = &psyDynamic->pnsData[ch]; + + psyData[ch]->mdctSpectrum = psyOutChannel[ch]->mdctSpectrum; + } + + /* block switching */ + if (hPsyConfLong->filterbank != FB_ELD) + { + int err; + + for(ch = 0; ch < channels; ch++) + { + C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024)) + + /* deinterleave input data and use for block switching */ + FDKaacEnc_deinterleaveInputBuffer( pTimeSignal, + &pInput[chIdx[ch]], + psyConf->granuleLength, + totalChannels); + + + FDKaacEnc_BlockSwitching (&psyStatic[ch]->blockSwitchingControl, + psyConf->granuleLength, + psyStatic[ch]->isLFE, + pTimeSignal + ); + + + /* fill up internal input buffer, to 2xframelength samples */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer+blockSwitchingOffset, + pTimeSignal, + (2*psyConf->granuleLength-blockSwitchingOffset)*sizeof(INT_PCM)); + + C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024)) + } + + /* synch left and right block type */ + err = FDKaacEnc_SyncBlockSwitching(&psyStatic[0]->blockSwitchingControl, + &psyStatic[1]->blockSwitchingControl, + channels, + commonWindow); + + if (err) { + return AAC_ENC_UNSUPPORTED_AOT; /* mixed up LC and LD */ + } + + } + else { + for(ch = 0; ch < channels; ch++) + { + /* deinterleave input data and use for block switching */ + FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->psyInputBuffer + blockSwitchingOffset, + &pInput[chIdx[ch]], + psyConf->granuleLength, + totalChannels); + } + } + + for(ch = 0; ch < channels; ch++) + isShortWindow[ch]=(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == SHORT_WINDOW); + + /* set parameters according to window length */ + for(ch = 0; ch < channels; ch++) + { + if(isShortWindow[ch]) { + hThisPsyConf[ch] = hPsyConfShort; + windowLength[ch] = psyConf->granuleLength/TRANS_FAC; + nWindows[ch] = TRANS_FAC; + maxSfb[ch] = MAX_SFB_SHORT; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Short[0]; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Short[0]; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Short[0]; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Short[0]; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Short[0]; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Short[0]; + + } else + { + hThisPsyConf[ch] = hPsyConfLong; + windowLength[ch] = psyConf->granuleLength; + nWindows[ch] = 1; + maxSfb[ch] = MAX_GROUPED_SFB; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Long; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Long; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Long; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Long; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Long; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Long; + } + } + + /* Transform and get mdctScaling for all channels and windows. */ + for(ch = 0; ch < channels; ch++) + { + /* update number of active bands */ + if (psyStatic[ch]->isLFE) { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActiveLFE; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLineLFE; + } else + { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActive; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLine; + } + + for(w = 0; w < nWindows[ch]; w++) { + + wOffset = w*windowLength[ch]; + + FDKaacEnc_Transform_Real( psyStatic[ch]->psyInputBuffer + wOffset, + psyData[ch]->mdctSpectrum+wOffset, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyStatic[ch]->blockSwitchingControl.windowShape, + &psyStatic[ch]->blockSwitchingControl.lastWindowShape, + psyConf->granuleLength, + &mdctSpectrum_e, + hThisPsyConf[ch]->filterbank + ,psyStatic[ch]->overlapAddBuffer + ); + + /* Low pass / highest sfb */ + FDKmemclear(&psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset], + (windowLength[ch]-psyData[ch]->lowpassLine)*sizeof(FIXP_DBL)); + + if ( (hPsyConfLong->filterbank != FB_LC) && (psyData[ch]->lowpassLine >= FADE_OUT_LEN) ) { + /* Do blending to reduce gibbs artifacts */ + for (int i=0; imdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i] = fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i], fadeOutFactor[i]); + } + } + + + /* Check for zero spectrum. These loops will usually terminate very, very early. */ + for(line=0; (linelowpassLine) && (zeroSpec==TRUE); line++) { + if (psyData[ch]->mdctSpectrum[line+wOffset] != (FIXP_DBL)0) { + zeroSpec = FALSE; + break; + } + } + + } /* w loop */ + + psyData[ch]->mdctScale = mdctSpectrum_e; + + /* rotate internal time samples */ + FDKmemmove(psyStatic[ch]->psyInputBuffer, + psyStatic[ch]->psyInputBuffer+psyConf->granuleLength, + psyConf->granuleLength*sizeof(INT_PCM)); + + + /* ... and get remaining samples from input buffer */ + FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->psyInputBuffer+psyConf->granuleLength, + &pInput[ (2*psyConf->granuleLength-blockSwitchingOffset)*totalChannels + chIdx[ch] ], + blockSwitchingOffset-psyConf->granuleLength, + totalChannels); + + } /* ch */ + + /* Do some rescaling to get maximum possible accuracy for energies */ + if ( zeroSpec == FALSE) { + + /* Calc possible spectrum leftshift for each sfb (1 means: 1 bit left shift is possible without overflow) */ + INT minSpecShift = MAX_SHIFT_DBL; + INT nrgShift = MAX_SHIFT_DBL; + INT finalShift = MAX_SHIFT_DBL; + FIXP_DBL currNrg = 0; + FIXP_DBL maxNrg = 0; + + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + wOffset = w*windowLength[ch]; + FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum+wOffset, + hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch]+w*maxSfb[ch], + psyData[ch]->sfbActive); + + for (sfb = 0; sfbsfbActive; sfb++) + minSpecShift = fixMin(minSpecShift, (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb]); + } + + } + + /* Calc possible energy leftshift for each sfb (1 means: 1 bit left shift is possible without overflow) */ + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + wOffset = w*windowLength[ch]; + currNrg = FDKaacEnc_CheckBandEnergyOptim(psyData[ch]->mdctSpectrum+wOffset, + pSfbMaxScaleSpec[ch]+w*maxSfb[ch], + hThisPsyConf[ch]->sfbOffset, + psyData[ch]->sfbActive, + pSfbEnergy[ch]+w*maxSfb[ch], + pSfbEnergyLdData[ch]+w*maxSfb[ch], + minSpecShift-4); + + maxNrg = fixMax(maxNrg, currNrg); + } + } + + if ( maxNrg != (FIXP_DBL)0 ) { + nrgShift = (CountLeadingBits(maxNrg)>>1) + (minSpecShift-4); + } + + /* 2check: Hasn't this decision to be made for both channels? */ + /* For short windows 1 additional bit headroom is necessary to prevent overflows when summing up energies in FDKaacEnc_groupShortData() */ + if(isShortWindow[0]) nrgShift--; + + /* both spectrum and energies mustn't overflow */ + finalShift = fixMin(minSpecShift, nrgShift); + + /* do not shift more than 3 bits more to the left than signal without blockfloating point + * would be to avoid overflow of scaled PCM quantization thresholds */ + if (finalShift > psyData[0]->mdctScale + 3 ) + finalShift = psyData[0]->mdctScale + 3; + + FDK_ASSERT(finalShift >= 0); /* right shift is not allowed */ + + /* correct sfbEnergy and sfbEnergyLdData with new finalShift */ + FIXP_DBL ldShift = finalShift * FL2FXCONST_DBL(2.0/64); + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + for(sfb=0; sfbsfbActive; sfb++) { + INT scale = fixMax(0, (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb]-4); + scale = fixMin((scale-finalShift)<<1, DFRACT_BITS-1); + if (scale >= 0) (pSfbEnergy[ch]+w*maxSfb[ch])[sfb] >>= (scale); + else (pSfbEnergy[ch]+w*maxSfb[ch])[sfb] <<= (-scale); + (pSfbThreshold[ch]+w*maxSfb[ch])[sfb] = fMult((pSfbEnergy[ch]+w*maxSfb[ch])[sfb], C_RATIO); + (pSfbEnergyLdData[ch]+w*maxSfb[ch])[sfb] += ldShift; + } + } + } + + if ( finalShift != 0 ) { + for (ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + wOffset = w*windowLength[ch]; + for(line=0; linelowpassLine; line++) { + psyData[ch]->mdctSpectrum[line+wOffset] <<= finalShift; + } + /* update sfbMaxScaleSpec */ + for (sfb = 0; sfbsfbActive; sfb++) + (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb] -= finalShift; + } + /* update mdctScale */ + psyData[ch]->mdctScale -= finalShift; + } + } + + } else { + /* all spectral lines are zero */ + for (ch = 0; ch < channels; ch++) { + psyData[ch]->mdctScale = 0; /* otherwise mdctScale would be for example 7 and PCM quantization thresholds would be shifted + * 14 bits to the right causing some of them to become 0 (which causes problems later) */ + /* clear sfbMaxScaleSpec */ + for(w = 0; w < nWindows[ch]; w++) { + for (sfb = 0; sfbsfbActive; sfb++) { + (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb] = 0; + (pSfbEnergy[ch]+w*maxSfb[ch])[sfb] = (FIXP_DBL)0; + (pSfbEnergyLdData[ch]+w*maxSfb[ch])[sfb] = FL2FXCONST_DBL(-1.0f); + (pSfbThreshold[ch]+w*maxSfb[ch])[sfb] = (FIXP_DBL)0; + } + } + } + } + + /* Advance psychoacoustics: Tonality and TNS */ + if (psyStatic[0]->isLFE) { + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0; + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0; + } + else + { + + for(ch = 0; ch < channels; ch++) { + if (!isShortWindow[ch]) { + /* tonality */ + FDKaacEnc_CalculateFullTonality( psyData[ch]->mdctSpectrum, + pSfbMaxScaleSpec[ch], + pSfbEnergyLdData[ch], + sfbTonality[ch], + psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbOffset, + hThisPsyConf[ch]->pnsConf.usePns); + } + } + + if (hPsyConfLong->tnsConf.tnsActive || hPsyConfShort->tnsConf.tnsActive) { + INT tnsActive[TRANS_FAC]; + INT nrgScaling[2] = {0,0}; + INT tnsSpecShift = 0; + + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + + wOffset = w*windowLength[ch]; + /* TNS */ + FDKaacEnc_TnsDetect( + tnsData[ch], + &hThisPsyConf[ch]->tnsConf, + &psyOutChannel[ch]->tnsInfo, + hThisPsyConf[ch]->sfbCnt, + psyData[ch]->mdctSpectrum+wOffset, + w, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence + ); + } + } + + if (channels == 2) { + FDKaacEnc_TnsSync( + tnsData[1], + tnsData[0], + &psyOutChannel[1]->tnsInfo, + &psyOutChannel[0]->tnsInfo, + + psyStatic[1]->blockSwitchingControl.lastWindowSequence, + psyStatic[0]->blockSwitchingControl.lastWindowSequence, + &hThisPsyConf[1]->tnsConf); + } + + FDK_ASSERT(commonWindow==1); /* all checks for TNS do only work for common windows (which is always set)*/ + for(w = 0; w < nWindows[0]; w++) + { + if (isShortWindow[0]) + tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] || + tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT]; + else + tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] || + tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT]; + } + + for(ch = 0; ch < channels; ch++) { + if (tnsActive[0] && !isShortWindow[ch]) { + /* Scale down spectrum if tns is active in one of the two channels with same lastWindowSequence */ + /* first part of threshold calculation; it's not necessary to update sfbMaxScaleSpec */ + INT shift = 1; + for(sfb=0; sfblowpassLine; sfb++) { + psyData[ch]->mdctSpectrum[sfb] = psyData[ch]->mdctSpectrum[sfb] >> shift; + } + + /* update thresholds */ + for (sfb=0; sfbsfbActive; sfb++) { + pSfbThreshold[ch][sfb] >>= (2*shift); + } + + psyData[ch]->mdctScale += shift; /* update mdctScale */ + + /* calc sfbEnergies after tnsEncode again ! */ + + } + } + + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) + { + wOffset = w*windowLength[ch]; + FDKaacEnc_TnsEncode( + &psyOutChannel[ch]->tnsInfo, + tnsData[ch], + hThisPsyConf[ch]->sfbCnt, + &hThisPsyConf[ch]->tnsConf, + hThisPsyConf[ch]->sfbOffset[psyData[ch]->sfbActive],/*hThisPsyConf[ch]->lowpassLine*/ /* filter stops before that line ! */ + psyData[ch]->mdctSpectrum+wOffset, + w, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence); + + if(tnsActive[w]) { + /* Calc sfb-bandwise mdct-energies for left and right channel again, */ + /* if tns active in current channel or in one channel with same lastWindowSequence left and right */ + FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum+wOffset, + hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch]+w*maxSfb[ch], + psyData[ch]->sfbActive); + } + } + } + + for(ch = 0; ch < channels; ch++) { + for(w = 0; w < nWindows[ch]; w++) { + + if (tnsActive[w]) { + + if (isShortWindow[ch]) { + FDKaacEnc_CalcBandEnergyOptimShort(psyData[ch]->mdctSpectrum+w*windowLength[ch], + pSfbMaxScaleSpec[ch]+w*maxSfb[ch], + hThisPsyConf[ch]->sfbOffset, + psyData[ch]->sfbActive, + pSfbEnergy[ch]+w*maxSfb[ch]); + } + else { + nrgScaling[ch] = /* with tns, energy calculation can overflow; -> scaling */ + FDKaacEnc_CalcBandEnergyOptimLong(psyData[ch]->mdctSpectrum, + pSfbMaxScaleSpec[ch], + hThisPsyConf[ch]->sfbOffset, + psyData[ch]->sfbActive, + pSfbEnergy[ch], + pSfbEnergyLdData[ch]); + tnsSpecShift = fixMax(tnsSpecShift, nrgScaling[ch]); /* nrgScaling is set only if nrg would have an overflow */ + } + } /* if tnsActive */ + } + } /* end channel loop */ + + /* adapt scaling to prevent nrg overflow, only for long blocks */ + for(ch = 0; ch < channels; ch++) { + if ( (tnsSpecShift!=0) && !isShortWindow[ch] ) { + /* scale down spectrum, nrg's and thresholds, if there was an overflow in sfbNrg calculation after tns */ + for(line=0; linelowpassLine; line++) { + psyData[ch]->mdctSpectrum[line] >>= tnsSpecShift; + } + INT scale = (tnsSpecShift-nrgScaling[ch])<<1; + for(sfb=0; sfbsfbActive; sfb++) { + pSfbEnergyLdData[ch][sfb] -= scale*FL2FXCONST_DBL(1.0/LD_DATA_SCALING); + pSfbEnergy[ch][sfb] >>= scale; + pSfbThreshold[ch][sfb] >>= (tnsSpecShift<<1); + } + psyData[ch]->mdctScale += tnsSpecShift; /* update mdctScale; not necessary to update sfbMaxScaleSpec */ + + } + } /* end channel loop */ + + } /* TNS active */ + } /* !isLFE */ + + + + + + + /* Advance thresholds */ + for(ch = 0; ch < channels; ch++) { + INT headroom; + + FIXP_DBL clipEnergy; + INT energyShift = psyData[ch]->mdctScale*2 ; + INT clipNrgShift = energyShift - THR_SHIFTBITS ; + + if(isShortWindow[ch]) + headroom = 6; + else + headroom = 0; + + if (clipNrgShift >= 0) + clipEnergy = hThisPsyConf[ch]->clipEnergy >> clipNrgShift ; + else if (clipNrgShift>=-headroom) + clipEnergy = hThisPsyConf[ch]->clipEnergy << -clipNrgShift ; + else + clipEnergy = (FIXP_DBL)MAXVAL_DBL ; + + for(w = 0; w < nWindows[ch]; w++) + { + INT i; + /* limit threshold to avoid clipping */ + for (i=0; isfbActive; i++) { + *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMin(*(pSfbThreshold[ch]+w*maxSfb[ch]+i), clipEnergy); + } + + /* spreading */ + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactor, + hThisPsyConf[ch]->sfbMaskHighFactor, + pSfbThreshold[ch]+w*maxSfb[ch]); + + + /* PCM quantization threshold */ + energyShift += PCM_QUANT_THR_SCALE; + if (energyShift>=0) { + energyShift = fixMin(DFRACT_BITS-1,energyShift); + for (i=0; isfbActive;i++) { + *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMax(*(pSfbThreshold[ch]+w*maxSfb[ch]+i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] >> energyShift)); + } + } else { + energyShift = fixMin(DFRACT_BITS-1,-energyShift); + for (i=0; isfbActive;i++) { + *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMax(*(pSfbThreshold[ch]+w*maxSfb[ch]+i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] << energyShift)); + } + } + + if (!psyStatic[ch]->isLFE) + { + /* preecho control */ + if(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == STOP_WINDOW) { + /* prevent FDKaacEnc_PreEchoControl from comparing stop + thresholds with short thresholds */ + for (i=0; isfbActive;i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + + FDKaacEnc_PreEchoControl( psyStatic[ch]->sfbThresholdnm1, + psyStatic[ch]->calcPreEcho, + psyData[ch]->sfbActive, + hThisPsyConf[ch]->maxAllowedIncreaseFactor, + hThisPsyConf[ch]->minRemainingThresholdFactor, + pSfbThreshold[ch]+w*maxSfb[ch], + psyData[ch]->mdctScale, + &psyStatic[ch]->mdctScalenm1); + + psyStatic[ch]->calcPreEcho = 1; + + if(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == START_WINDOW) + { + /* prevent FDKaacEnc_PreEchoControl in next frame to compare start + thresholds with short thresholds */ + for (i=0; isfbActive;i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + + } + + /* spread energy to avoid hole detection */ + FDKmemcpy(pSfbSpreadEnergy[ch]+w*maxSfb[ch], pSfbEnergy[ch]+w*maxSfb[ch], psyData[ch]->sfbActive*sizeof(FIXP_DBL)); + + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactorSprEn, + hThisPsyConf[ch]->sfbMaskHighFactorSprEn, + pSfbSpreadEnergy[ch]+w*maxSfb[ch]); + } + } + + /* Calc bandwise energies for mid and side channel. Do it only if 2 channels exist */ + if (channels==2) { + for(w = 0; w < nWindows[1]; w++) { + wOffset = w*windowLength[1]; + FDKaacEnc_CalcBandNrgMSOpt(psyData[0]->mdctSpectrum+wOffset, + psyData[1]->mdctSpectrum+wOffset, + pSfbMaxScaleSpec[0]+w*maxSfb[0], + pSfbMaxScaleSpec[1]+w*maxSfb[1], + hThisPsyConf[1]->sfbOffset, + psyData[0]->sfbActive, + pSfbEnergyMS[0]+w*maxSfb[0], + pSfbEnergyMS[1]+w*maxSfb[1], + (psyStatic[1]->blockSwitchingControl.lastWindowSequence != SHORT_WINDOW), + psyData[0]->sfbEnergyMSLdData, + psyData[1]->sfbEnergyMSLdData); + } + } + + /* group short data (maxSfb[ch] for short blocks is determined here) */ + for(ch=0;chblockSwitchingControl.noOfGroups * hPsyConfShort->sfbCnt; + /* At this point, energies and thresholds are copied/regrouped from the ".Short" to the ".Long" arrays */ + FDKaacEnc_groupShortData( psyData[ch]->mdctSpectrum, + &psyData[ch]->sfbThreshold, + &psyData[ch]->sfbEnergy, + &psyData[ch]->sfbEnergyMS, + &psyData[ch]->sfbSpreadEnergy, + hPsyConfShort->sfbCnt, + psyData[ch]->sfbActive, + hPsyConfShort->sfbOffset, + hPsyConfShort->sfbMinSnrLdData, + psyData[ch]->groupedSfbOffset, + &maxSfbPerGroup[ch], + psyOutChannel[ch]->sfbMinSnrLdData, + psyStatic[ch]->blockSwitchingControl.noOfGroups, + psyStatic[ch]->blockSwitchingControl.groupLen, + psyConf[1].granuleLength); + + + /* calculate ldData arrays (short values are in .Long-arrays after FDKaacEnc_groupShortData) */ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergy.Long[sfbGrp], &psyOutChannel[ch]->sfbEnergyLdData[sfbGrp], psyData[ch]->sfbActive); + } + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbThreshold.Long[sfbGrp], &psyOutChannel[ch]->sfbThresholdLdData[sfbGrp], psyData[ch]->sfbActive); + for (sfb=0;sfbsfbActive;sfb++) { + psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb], FL2FXCONST_DBL(-0.515625f)); + } + } + + if ( channels==2 ) { + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergyMS.Long[sfbGrp], &psyData[ch]->sfbEnergyMSLdData[sfbGrp], psyData[ch]->sfbActive); + } + } + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, psyData[ch]->groupedSfbOffset, (MAX_GROUPED_SFB+1)*sizeof(INT)); + + } else { + /* maxSfb[ch] for long blocks */ + for (sfb = psyData[ch]->sfbActive-1; sfb >= 0; sfb--) { + for (line = hPsyConfLong->sfbOffset[sfb+1]-1; line >= hPsyConfLong->sfbOffset[sfb]; line--) { + if (psyData[ch]->mdctSpectrum[line] != FL2FXCONST_SGL(0.0f)) break; + } + if (line > hPsyConfLong->sfbOffset[sfb]) break; + } + maxSfbPerGroup[ch] = sfb + 1; + /* ensure at least one section in ICS; workaround for existing decoder crc implementation */ + maxSfbPerGroup[ch] = fixMax(fixMin(5,psyData[ch]->sfbActive),maxSfbPerGroup[ch]); + + /* sfbNrgLdData is calculated in FDKaacEnc_advancePsychLong, copy in psyOut structure */ + FDKmemcpy(psyOutChannel[ch]->sfbEnergyLdData, psyData[ch]->sfbEnergyLdData.Long, psyData[ch]->sfbActive*sizeof(FIXP_DBL)); + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, hPsyConfLong->sfbOffset, (MAX_GROUPED_SFB+1)*sizeof(INT)); + + /* sfbMinSnrLdData modified in adjust threshold, copy necessary */ + FDKmemcpy(psyOutChannel[ch]->sfbMinSnrLdData, hPsyConfLong->sfbMinSnrLdData, psyData[ch]->sfbActive*sizeof(FIXP_DBL)); + + /* sfbEnergyMSLdData ist already calculated in FDKaacEnc_CalcBandNrgMSOpt; only in long case */ + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + LdDataVector(psyData[ch]->sfbThreshold.Long, psyOutChannel[ch]->sfbThresholdLdData, psyData[ch]->sfbActive); + for (i=0;isfbActive;i++) { + psyOutChannel[ch]->sfbThresholdLdData[i] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[i], FL2FXCONST_DBL(-0.515625f)); + } + + + } + + + } + + + /* + Intensity parameter intialization. + */ + for(ch=0;chisBook, MAX_GROUPED_SFB*sizeof(INT)); + FDKmemclear(psyOutChannel[ch]->isScale, MAX_GROUPED_SFB*sizeof(INT)); + } + + for(ch=0;chisLFE) + { + /* PNS Decision */ + FDKaacEnc_PnsDetect( &(psyConf[0].pnsConf), + pnsData[ch], + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyData[ch]->sfbActive, + maxSfbPerGroup[ch], /* count of Sfb which are not zero. */ + psyOutChannel[ch]->sfbThresholdLdData, + psyConf[win].sfbOffset, + psyData[ch]->mdctSpectrum, + psyData[ch]->sfbMaxScaleSpec.Long, + sfbTonality[ch], + psyOutChannel[ch]->tnsInfo.order[0][0], + tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT], + tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT], + psyOutChannel[ch]->sfbEnergyLdData, + psyOutChannel[ch]->noiseNrg ); + } /* !isLFE */ + } + + /* + stereo Processing + */ + if(channels == 2) + { + psyOutElement->toolsInfo.msDigest = MS_NONE; + psyOutElement->commonWindow = commonWindow; + if (psyOutElement->commonWindow) + maxSfbPerGroup[0] = maxSfbPerGroup[1] = + fixMax(maxSfbPerGroup[0], maxSfbPerGroup[1]); + + if(psyStatic[0]->blockSwitchingControl.lastWindowSequence != SHORT_WINDOW) + { + /* PNS preprocessing depending on ms processing: PNS not in Short Window! */ + FDKaacEnc_PreProcessPnsChannelPair( + psyData[0]->sfbActive, + (&psyData[0]->sfbEnergy)->Long, + (&psyData[1]->sfbEnergy)->Long, + psyOutChannel[0]->sfbEnergyLdData, + psyOutChannel[1]->sfbEnergyLdData, + psyData[0]->sfbEnergyMS.Long, + &(psyConf[0].pnsConf), + pnsData[0], + pnsData[1]); + + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, + psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, + psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, + psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, + psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, + psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, + psyOutElement->toolsInfo.msMask, + psyConf[0].sfbCnt, + psyConf[0].sfbCnt, + maxSfbPerGroup[0], + psyConf[0].sfbOffset, + psyConf[0].allowIS && commonWindow, + psyOutChannel[1]->isBook, + psyOutChannel[1]->isScale, + pnsData); + + FDKaacEnc_MsStereoProcessing( + psyData, + psyOutChannel, + psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, + psyOutElement->toolsInfo.msMask, + psyData[0]->sfbActive, + psyData[0]->sfbActive, + maxSfbPerGroup[0], + psyOutChannel[0]->sfbOffsets); + + /* PNS postprocessing */ + FDKaacEnc_PostProcessPnsChannelPair(psyData[0]->sfbActive, + &(psyConf[0].pnsConf), + pnsData[0], + pnsData[1], + psyOutElement->toolsInfo.msMask, + &psyOutElement->toolsInfo.msDigest); + + } else { + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, + psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, + psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, + psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, + psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, + psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, + psyOutElement->toolsInfo.msMask, + psyStatic[0]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, + psyConf[1].sfbCnt, + maxSfbPerGroup[0], + psyData[0]->groupedSfbOffset, + psyConf[0].allowIS && commonWindow, + psyOutChannel[1]->isBook, + psyOutChannel[1]->isScale, + pnsData); + + /* it's OK to pass the ".Long" arrays here. They contain grouped short data since FDKaacEnc_groupShortData() */ + FDKaacEnc_MsStereoProcessing( psyData, + psyOutChannel, + psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, + psyOutElement->toolsInfo.msMask, + psyStatic[0]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt, + hPsyConfShort->sfbCnt, + maxSfbPerGroup[0], + psyOutChannel[0]->sfbOffsets); + } + } + + /* + PNS Coding + */ + for(ch=0;chisLFE) { + /* no PNS coding */ + for(sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + psyOutChannel[ch]->noiseNrg[sfb] = NO_NOISE_PNS; + } + } else + { + FDKaacEnc_CodePnsChannel(psyData[ch]->sfbActive, + &(psyConf[ch].pnsConf), + pnsData[ch]->pnsFlag, + psyData[ch]->sfbEnergyLdData.Long, + psyOutChannel[ch]->noiseNrg, /* this is the energy that will be written to the bitstream */ + psyOutChannel[ch]->sfbThresholdLdData); + } + } + + /* + build output + */ + for(ch=0;chmaxSfbPerGroup = maxSfbPerGroup[ch]; + psyOutChannel[ch]->mdctScale = psyData[ch]->mdctScale; + + if(isShortWindow[ch]==0) { + + psyOutChannel[ch]->sfbCnt = hPsyConfLong->sfbActive; + psyOutChannel[ch]->sfbPerGroup = hPsyConfLong->sfbActive; + psyOutChannel[ch]->lastWindowSequence = psyStatic[ch]->blockSwitchingControl.lastWindowSequence; + psyOutChannel[ch]->windowShape = psyStatic[ch]->blockSwitchingControl.windowShape; + } + else { + INT sfbCnt = psyStatic[ch]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt; + + psyOutChannel[ch]->sfbCnt = sfbCnt; + psyOutChannel[ch]->sfbPerGroup = hPsyConfShort->sfbCnt; + psyOutChannel[ch]->lastWindowSequence = SHORT_WINDOW; + psyOutChannel[ch]->windowShape = SINE_WINDOW; + } + + /* generate grouping mask */ + mask = 0; + for (grp = 0; grp < psyStatic[ch]->blockSwitchingControl.noOfGroups; grp++) + { + mask <<= 1; + for (j=1; jblockSwitchingControl.groupLen[grp]; j++) { + mask = (mask<<1) | 1 ; + } + } + psyOutChannel[ch]->groupingMask = mask; + + /* build interface */ + FDKmemcpy(psyOutChannel[ch]->groupLen,psyStatic[ch]->blockSwitchingControl.groupLen,MAX_NO_OF_GROUPS*sizeof(INT)); + FDKmemcpy(psyOutChannel[ch]->sfbEnergy,(&psyData[ch]->sfbEnergy)->Long, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); + FDKmemcpy(psyOutChannel[ch]->sfbSpreadEnergy,(&psyData[ch]->sfbSpreadEnergy)->Long, MAX_GROUPED_SFB*sizeof(FIXP_DBL)); +// FDKmemcpy(psyOutChannel[ch]->mdctSpectrum, psyData[ch]->mdctSpectrum, (1024)*sizeof(FIXP_DBL)); + } + + return AAC_ENC_OK; +} + + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, + PSY_OUT **phPsyOut) +{ + int n, i; + + + if(phPsyInternal!=NULL) { + PSY_INTERNAL *hPsyInternal = *phPsyInternal; + + if (hPsyInternal) + { + for (i=0; i<(8); i++) { + if (hPsyInternal->pStaticChannels[i]) { + if (hPsyInternal->pStaticChannels[i]->psyInputBuffer) + FreeRam_aacEnc_PsyInputBuffer(&hPsyInternal->pStaticChannels[i]->psyInputBuffer); /* AUDIO INPUT BUFFER */ + + FreeRam_aacEnc_PsyStatic(&hPsyInternal->pStaticChannels[i]); /* PSY_STATIC */ + } + } + + for (i=0; i<(8); i++) { + if (hPsyInternal->psyElement[i]) + FreeRam_aacEnc_PsyElement(&hPsyInternal->psyElement[i]); /* PSY_ELEMENT */ + } + + + FreeRam_aacEnc_PsyInternal(phPsyInternal); + } + } + + if (phPsyOut!=NULL) { + for (n=0; n<(1); n++) { + if (phPsyOut[n]) + { + for (i=0; i<(8); i++) { + if (phPsyOut[n]->pPsyOutChannels[i]) + FreeRam_aacEnc_PsyOutChannel(&phPsyOut[n]->pPsyOutChannels[i]); /* PSY_OUT_CHANNEL */ + } + + for (i=0; i<(8); i++) { + if (phPsyOut[n]->psyOutElement[i]) + FreeRam_aacEnc_PsyOutElements(&phPsyOut[n]->psyOutElement[i]); /* PSY_OUT_ELEMENTS */ + } + + FreeRam_aacEnc_PsyOut(&phPsyOut[n]); + } + } + } +} diff --git a/libAACenc/src/psy_main.h b/libAACenc/src/psy_main.h new file mode 100644 index 00000000..7bdcc38a --- /dev/null +++ b/libAACenc/src/psy_main.h @@ -0,0 +1,174 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Psychoaccoustic major function block + +******************************************************************************/ + +#ifndef _PSYMAIN_H +#define _PSYMAIN_H + + +#include "psy_configuration.h" +#include "qc_data.h" +#include "aacenc_pns.h" + +/* + psych internal +*/ +typedef struct { + + PSY_STATIC* psyStatic[(2)]; + +}PSY_ELEMENT; + +typedef struct { + + PSY_DATA psyData[(2)]; + TNS_DATA tnsData[(2)]; + PNS_DATA pnsData[(2)]; + +}PSY_DYNAMIC; + + +typedef struct { + + PSY_CONFIGURATION psyConf[2]; /* LONG / SHORT */ + PSY_ELEMENT* psyElement[(8)]; + PSY_STATIC* pStaticChannels[(8)]; + PSY_DYNAMIC* psyDynamic; + INT granuleLength; + +}PSY_INTERNAL; + + +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, + const INT nElements, + const INT nChannels + ,UCHAR *dynamic_RAM + ); + +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, + const INT nElements, + const INT nChannels, + const INT nSubFrames + ,UCHAR *dynamic_RAM + ); + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, + PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy, + AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm, + INT sampleRate, + INT granuleLength, + INT bitRate, + INT tnsMask, + INT bandwidth, + INT usePns, + INT useIS, + UINT syntaxFlags, + ULONG initFlags); + +AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, + PSY_ELEMENT *psyElement, + PSY_DYNAMIC *psyDynamic, + PSY_CONFIGURATION *psyConf, + PSY_OUT_ELEMENT *psyOutElement, + INT_PCM *pInput, + INT *chIdx, + INT totalChannels + ); + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, + PSY_OUT **phPsyOut); + +#endif /* _PSYMAIN_H */ diff --git a/libAACenc/src/qc_data.h b/libAACenc/src/qc_data.h new file mode 100644 index 00000000..00d6090c --- /dev/null +++ b/libAACenc/src/qc_data.h @@ -0,0 +1,280 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Quantizing & coding data + +******************************************************************************/ + +#ifndef _QC_DATA_H +#define _QC_DATA_H + + +#include "psy_const.h" +#include "dyn_bits.h" +#include "adj_thr_data.h" +#include "line_pe.h" +#include "FDK_audio.h" +#include "interface.h" + + +typedef enum { + QCDATA_BR_MODE_INVALID = -1, + QCDATA_BR_MODE_CBR = 0, + QCDATA_BR_MODE_VBR_1 = 1, /* 32 kbps/channel */ + QCDATA_BR_MODE_VBR_2 = 2, /* 40 kbps/channel */ + QCDATA_BR_MODE_VBR_3 = 3, /* 48 kbps/channel */ + QCDATA_BR_MODE_VBR_4 = 4, /* 64 kbps/channel */ + QCDATA_BR_MODE_VBR_5 = 5, /* 96 kbps/channel */ + QCDATA_BR_MODE_FF = 6, /* Fixed frame mode. */ + QCDATA_BR_MODE_SFR = 7 /* Superframe mode. */ + + +} QCDATA_BR_MODE; + +typedef struct { + MP4_ELEMENT_ID elType; + INT instanceTag; + INT nChannelsInEl; + INT ChannelIndex[2]; + FIXP_DBL relativeBits; +} ELEMENT_INFO; + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; + ELEMENT_INFO elInfo[(8)]; +} CHANNEL_MAPPING; + +typedef struct { + INT paddingRest; +} PADDING; + + +/* Quantizing & coding stage */ + +struct QC_INIT{ + CHANNEL_MAPPING* channelMapping; + INT sceCpe; /* not used yet */ + INT maxBits; /* maximum number of bits in reservoir */ + INT averageBits; /* average number of bits we should use */ + INT bitRes; + INT sampleRate; /* output sample rate */ + INT advancedBitsToPe; /* if set, calc bits2PE factor depending on samplerate */ + INT staticBits; /* Bits per frame consumed by transport layers. */ + QCDATA_BR_MODE bitrateMode; + INT meanPe; + INT chBitrate; + INT invQuant; + INT maxIterations; /* Maximum number of allowed iterations before FDKaacEnc_crashRecovery() is applied. */ + FIXP_DBL maxBitFac; + INT bitrate; + INT nSubFrames; /* helper variable */ + INT minBits; /* minimal number of bits in one frame*/ + + PADDING padding; +}; + +typedef struct +{ + FIXP_DBL mdctSpectrum[(1024)]; + + SHORT quantSpec[(1024)]; + + UINT maxValueInSfb[MAX_GROUPED_SFB]; + INT scf[MAX_GROUPED_SFB]; + INT globalGain; + SECTION_DATA sectionData; + + FIXP_DBL sfbFormFactorLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbThresholdLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbMinSnrLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergyLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergy[MAX_GROUPED_SFB]; + FIXP_DBL sfbWeightedEnergyLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbEnFacLd[MAX_GROUPED_SFB]; + + FIXP_DBL sfbSpreadEnergy[MAX_GROUPED_SFB]; + +} QC_OUT_CHANNEL; + + +typedef struct +{ + EXT_PAYLOAD_TYPE type; /* type of the extension payload */ + INT nPayloadBits; /* size of the payload */ + UCHAR *pPayload; /* pointer to payload */ + +} QC_OUT_EXTENSION; + + +typedef struct +{ + INT staticBitsUsed; /* for verification purposes */ + INT dynBitsUsed; /* for verification purposes */ + + INT extBitsUsed; /* bit consumption of extended fill elements */ + INT nExtensions; /* number of extension payloads for this element */ + QC_OUT_EXTENSION extension[(1)]; /* reffering extension payload */ + + INT grantedDynBits; + + INT grantedPe; + INT grantedPeCorr; + + PE_DATA peData; + + QC_OUT_CHANNEL *qcOutChannel[(2)]; + + +} QC_OUT_ELEMENT; + +typedef struct +{ + QC_OUT_ELEMENT *qcElement[(8)]; + QC_OUT_CHANNEL *pQcOutChannels[(8)]; + QC_OUT_EXTENSION extension[(2+2)]; /* global extension payload */ + INT nExtensions; /* number of extension payloads for this AU */ + INT maxDynBits; /* maximal allowed dynamic bits in frame */ + INT grantedDynBits; /* granted dynamic bits in frame */ + INT totFillBits; /* fill bits */ + INT elementExtBits; /* element associated extension payload bits, e.g. sbr, drc ... */ + INT globalExtBits; /* frame/au associated extension payload bits (anc data ...) */ + INT staticBits; /* aac side info bits */ + + INT totalNoRedPe; + INT totalGrantedPeCorr; + + INT usedDynBits; /* number of dynamic bits in use */ + INT alignBits; /* AU alignment bits */ + INT totalBits; /* sum of static, dyn, sbr, fill, align and dse bits */ + +} QC_OUT; + +typedef struct { + INT chBitrateEl; /* channel bitrate in element (totalbitrate*el_relativeBits/el_channels) */ + INT maxBitsEl; /* used in crash recovery */ + INT bitResLevelEl; /* update bitreservoir level in each call of FDKaacEnc_QCMain */ + INT maxBitResBitsEl; /* nEffChannels*6144 - averageBitsInFrame */ + FIXP_DBL relativeBitsEl; /* Bits relative to total Bits*/ +} ELEMENT_BITS; + +typedef struct +{ + /* this is basically struct QC_INIT */ + + INT globHdrBits; + INT maxBitsPerFrame; /* maximal allowed bits per frame, 6144*nChannelsEff */ + INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */ + INT nElements; + QCDATA_BR_MODE bitrateMode; + INT bitDistributionMode; /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ + INT bitResTot; + INT bitResTotMax; + INT maxIterations; /* Maximum number of allowed iterations before FDKaacEnc_crashRecovery() is applied. */ + INT invQuant; + + FIXP_DBL vbrQualFactor; + FIXP_DBL maxBitFac; + + PADDING padding; + + ELEMENT_BITS *elementBits[(8)]; + BITCNTR_STATE *hBitCounter; + ADJ_THR_STATE *hAdjThr; + + INT dZoneQuantEnable; /* enable dead zone quantizer */ + +} QC_STATE; + +#endif /* _QC_DATA_H */ + + + + diff --git a/libAACenc/src/qc_main.cpp b/libAACenc/src/qc_main.cpp new file mode 100644 index 00000000..10258945 --- /dev/null +++ b/libAACenc/src/qc_main.cpp @@ -0,0 +1,1647 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Quantizing & coding + +******************************************************************************/ +#include +#include "qc_main.h" +#include "quantize.h" +#include "interface.h" +#include "adj_thr.h" +#include "sf_estim.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "channel_map.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + + +typedef struct { + QCDATA_BR_MODE bitrateMode; + LONG vbrQualFactor; +} TAB_VBR_QUAL_FACTOR; + +static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = { + {QCDATA_BR_MODE_VBR_1, FL2FXCONST_DBL(0.160f)}, /* 32 kbps mono AAC-LC + SBR + PS */ + {QCDATA_BR_MODE_VBR_2, FL2FXCONST_DBL(0.148f)}, /* 64 kbps stereo AAC-LC + SBR */ + {QCDATA_BR_MODE_VBR_3, FL2FXCONST_DBL(0.135f)}, /* 80 - 96 kbps stereo AAC-LC */ + {QCDATA_BR_MODE_VBR_4, FL2FXCONST_DBL(0.111f)}, /* 128 kbps stereo AAC-LC */ + {QCDATA_BR_MODE_VBR_5, FL2FXCONST_DBL(0.070f)} /* 192 kbps stereo AAC-LC */ +}; + +static INT isConstantBitrateMode( + const QCDATA_BR_MODE bitrateMode + ) +{ + return ( ((bitrateMode==QCDATA_BR_MODE_CBR) || (bitrateMode==QCDATA_BR_MODE_SFR) || (bitrateMode==QCDATA_BR_MODE_FF)) ? 1 : 0 ); +} + + + +typedef enum{ + FRAME_LEN_BYTES_MODULO = 1, + FRAME_LEN_BYTES_INT = 2 +}FRAME_LEN_RESULT_MODE; + +/* forward declarations */ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, + INT maxSfbPerGroup, + INT sfbPerGroup, + INT *RESTRICT sfbOffset, + SHORT *RESTRICT quantSpectrum, + UINT *RESTRICT maxValue); + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, + QC_OUT_ELEMENT *qcElement, + INT bitsToSave, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig); + +static +AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption(int* iterations, + const int maxIterations, + int gainAdjustment, + int* chConstraintsFulfilled, + int* calculateQuant, + int nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, + QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig); + + +void FDKaacEnc_QCClose (QC_STATE **phQCstate, QC_OUT **phQC); + +/***************************************************************************** + + functionname: FDKaacEnc_calcFrameLen + description: + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_calcFrameLen(INT bitRate, + INT sampleRate, + INT granuleLength, + FRAME_LEN_RESULT_MODE mode) +{ + + INT result; + + result = ((granuleLength)>>3)*(bitRate); + + switch(mode) { + case FRAME_LEN_BYTES_MODULO: + result %= sampleRate; + break; + case FRAME_LEN_BYTES_INT: + result /= sampleRate; + break; + } + return(result); +} + +/***************************************************************************** + + functionname:FDKaacEnc_framePadding + description: Calculates if padding is needed for actual frame + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_framePadding(INT bitRate, + INT sampleRate, + INT granuleLength, + INT *paddingRest) +{ + INT paddingOn; + INT difference; + + paddingOn = 0; + + difference = FDKaacEnc_calcFrameLen( bitRate, + sampleRate, + granuleLength, + FRAME_LEN_BYTES_MODULO ); + *paddingRest-=difference; + + if (*paddingRest <= 0 ) { + paddingOn = 1; + *paddingRest += sampleRate; + } + + return( paddingOn ); +} + + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT **phQC, + const INT nElements, + const INT nChannels, + const INT nSubFrames + ,UCHAR *dynamic_RAM + ) +{ + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n=0; npQcOutChannels[i] = GetRam_aacEnc_QCchannel(chInc, dynamic_RAM); + if ( phQC[n]->pQcOutChannels[i] == NULL + ) + { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + chInc++; + } /* nChannels */ + + for (i=0; iqcElement[i] = GetRam_aacEnc_QCelement(elInc); + if (phQC[n]->qcElement[i] == NULL) + { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + elInc++; + } /* nElements */ + + } /* nSubFrames */ + + + return AAC_ENC_OK; + +QCOutNew_bail: + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT *phQC[(1)], + const INT nSubFrames, + const CHANNEL_MAPPING *cm) +{ + INT n,i,ch; + + for (n=0; nnElements; i++) { + for (ch=0; chelInfo[i].nChannelsInEl; ch++) { + phQC[n]->qcElement[i]->qcOutChannel[ch] = phQC[n]->pQcOutChannels[chInc]; + chInc++; + } /* chInEl */ + } /* nElements */ + } /* nSubFrames */ + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE **phQC, + INT nElements + ,UCHAR* dynamic_RAM + ) +{ + AAC_ENCODER_ERROR ErrorStatus; + int i; + + QC_STATE* hQC = GetRam_aacEnc_QCstate(); + *phQC = hQC; + if (hQC == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_AdjThrNew(&hQC->hAdjThr, nElements)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_BCNew(&(hQC->hBitCounter), dynamic_RAM)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + for (i=0; ielementBits[i] = GetRam_aacEnc_ElementBits(i); + if (hQC->elementBits[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + } + + return AAC_ENC_OK; + +QCNew_bail: + FDKaacEnc_QCClose(phQC, NULL); + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, + struct QC_INIT *init) +{ + int i; + hQC->maxBitsPerFrame = init->maxBits; + hQC->minBitsPerFrame = init->minBits; + hQC->nElements = init->channelMapping->nElements; + hQC->bitResTotMax = init->bitRes; + hQC->bitResTot = init->bitRes; + hQC->maxBitFac = init->maxBitFac; + hQC->bitrateMode = init->bitrateMode; + hQC->invQuant = init->invQuant; + hQC->maxIterations = init->maxIterations; + + if ( isConstantBitrateMode(hQC->bitrateMode) ) { + INT bitresPerChannel = (hQC->bitResTotMax / init->channelMapping->nChannelsEff); + /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */ + hQC->bitDistributionMode = (bitresPerChannel>BITRES_MIN_LD) ? 0 : (bitresPerChannel>0) ? 1 : 2; + } + else { + hQC->bitDistributionMode = 0; /* full bitreservoir */ + } + + + hQC->padding.paddingRest = init->padding.paddingRest; + + hQC->globHdrBits = init->staticBits; /* Bit overhead due to transport */ + + FDKaacEnc_InitElementBits(hQC, + init->channelMapping, + init->bitrate, + (init->averageBits/init->nSubFrames) - hQC->globHdrBits, + hQC->maxBitsPerFrame/init->channelMapping->nChannelsEff); + + hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); + for (i=0; i<(int)(sizeof(tableVbrQualFactor)/sizeof(TAB_VBR_QUAL_FACTOR)); i++) { + if (hQC->bitrateMode==tableVbrQualFactor[i].bitrateMode) { + hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[i].vbrQualFactor; + break; + } + } + + if (init->channelMapping->nChannelsEff == 1 && + (init->bitrate / init->channelMapping->nChannelsEff) < 32000 && + init->advancedBitsToPe != 0 + ) + { + hQC->dZoneQuantEnable = 1; + } else { + hQC->dZoneQuantEnable = 0; + } + + FDKaacEnc_AdjThrInit( + hQC->hAdjThr, + init->meanPe, + hQC->elementBits, /* or channelBitrates, was: channelBitrate */ + hQC->invQuant, + init->channelMapping->nElements, + init->channelMapping->nChannelsEff, + init->sampleRate, /* output sample rate */ + init->advancedBitsToPe, /* if set, calc bits2PE factor depending on samplerate */ + hQC->vbrQualFactor, + hQC->dZoneQuantEnable + ); + + return AAC_ENC_OK; +} + + + +/********************************************************************************* + + functionname: FDKaacEnc_QCMainPrepare + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare(ELEMENT_INFO *elInfo, + ATS_ELEMENT* RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT* RESTRICT psyOutElement, + QC_OUT_ELEMENT* RESTRICT qcOutElement, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ) +{ + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT nChannels = elInfo->nChannelsInEl; + + PSY_OUT_CHANNEL** RESTRICT psyOutChannel = psyOutElement->psyOutChannel; /* may be modified in-place */ + + FDKaacEnc_CalcFormFactor(qcOutElement->qcOutChannel, psyOutChannel, nChannels); + + /* prepare and calculate PE without reduction */ + FDKaacEnc_peCalculation(&qcOutElement->peData, psyOutChannel, qcOutElement->qcOutChannel, &psyOutElement->toolsInfo, adjThrStateElement, nChannels); + + ErrorStatus = FDKaacEnc_ChannelElementWrite( NULL, elInfo, NULL, + psyOutElement, + psyOutElement->psyOutChannel, + syntaxFlags, + aot, + epConfig, + &qcOutElement->staticBitsUsed, + 0 ); + + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_AdjustBitrate + description: adjusts framelength via padding on a frame to frame basis, + to achieve a bitrate that demands a non byte aligned + framelength + return: errorcode + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate(QC_STATE *RESTRICT hQC, + CHANNEL_MAPPING *RESTRICT cm, + INT *avgTotalBits, + INT bitRate, /* total bitrate */ + INT sampleRate, /* output sampling rate */ + INT granuleLength) /* frame length */ +{ + INT paddingOn=0; + INT frameLen; + //fprintf(stderr, "hQC->padding.paddingRest=%d bytes! (before)\n", hQC->padding.paddingRest); + + /* Do we need an extra padding byte? */ + paddingOn = FDKaacEnc_framePadding(bitRate, + sampleRate, + granuleLength, + &hQC->padding.paddingRest); + //fprintf(stderr, "hQC->padding.paddingRest=%d bytes! (after)\n", hQC->padding.paddingRest); + + frameLen = paddingOn + FDKaacEnc_calcFrameLen(bitRate, + sampleRate, + granuleLength, + FRAME_LEN_BYTES_INT); + + //fprintf(stderr, "frameLen=%d bytes!\n", frameLen); + + *avgTotalBits = frameLen<<3; + + return AAC_ENC_OK; +} + +static AAC_ENCODER_ERROR FDKaacEnc_distributeElementDynBits(QC_STATE* hQC, + QC_OUT_ELEMENT* qcElement[(8)], + CHANNEL_MAPPING* cm, + INT codeBits) +{ + + INT i, firstEl = cm->nElements-1; + INT totalBits = 0; + + for (i=(cm->nElements-1); i>=0; i--) { + if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) + { + qcElement[i]->grantedDynBits = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)codeBits); + totalBits += qcElement[i]->grantedDynBits; + firstEl = i; + } + } + qcElement[firstEl]->grantedDynBits += codeBits - totalBits; + + return AAC_ENC_OK; +} + +/** + * \brief Verify whether minBitsPerFrame criterion can be satisfied. + * + * This function evaluates the bit consumption only if minBitsPerFrame parameter is not 0. + * In hyperframing mode the difference between grantedDynBits and usedDynBits of all sub frames + * results the number of fillbits to be written. + * This bits can be distrubitued in superframe to reach minBitsPerFrame bit consumption in single AU's. + * The return value denotes if enough desired fill bits are available to achieve minBitsPerFrame in all frames. + * This check can only be used within superframes. + * + * \param qcOut Pointer to coding data struct. + * \param minBitsPerFrame Minimal number of bits to be consumed in each frame. + * \param nSubFrames Number of frames in superframe + * + * \return + * - 1: all fine + * - 0: criterion not fulfilled + */ +static int checkMinFrameBitsDemand( + QC_OUT** qcOut, + const INT minBitsPerFrame, + const INT nSubFrames + ) +{ + int result = 1; /* all fine*/ + return result; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/********************************************************************************* + + functionname: FDKaacEnc_getMinimalStaticBitdemand + description: calculate minmal size of static bits by reduction , + to zero spectrum and deactivating tns and MS + return: number of static bits + +**********************************************************************************/ +static int FDKaacEnc_getMinimalStaticBitdemand(CHANNEL_MAPPING* cm, + PSY_OUT** psyOut) +{ + AUDIO_OBJECT_TYPE aot = AOT_AAC_LC; + UINT syntaxFlags = 0; + SCHAR epConfig = -1; + int i, bitcount = 0; + + for (i=0; inElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ( (elInfo.elType == ID_SCE) + || (elInfo.elType == ID_CPE) + || (elInfo.elType == ID_LFE) ) + { + INT minElBits = 0; + + FDKaacEnc_ChannelElementWrite( NULL, &elInfo, NULL, + psyOut[0]->psyOutElement[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, + syntaxFlags, + aot, + epConfig, + &minElBits, + 1 ); + bitcount += minElBits; + } + } + + return bitcount; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution(QC_STATE* hQC, + PSY_OUT** psyOut, + QC_OUT** qcOut, + CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(1)][(8)], + INT avgTotalBits, + INT *totalAvailableBits, + INT *avgTotalDynBits) +{ + int i; + /* get maximal allowed dynamic bits */ + qcOut[0]->grantedDynBits = (fixMin(hQC->maxBitsPerFrame, avgTotalBits) - hQC->globHdrBits)&~7; + qcOut[0]->grantedDynBits -= (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits); + qcOut[0]->maxDynBits = ((hQC->maxBitsPerFrame)&~7) - (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits); + /* assure that enough bits are available */ + if ((qcOut[0]->grantedDynBits+hQC->bitResTot) < 0) { + /* crash recovery allows to reduce static bits to a minimum */ + if ( (qcOut[0]->grantedDynBits+hQC->bitResTot) < (FDKaacEnc_getMinimalStaticBitdemand(cm, psyOut)-qcOut[0]->staticBits) ) + return AAC_ENC_BITRES_TOO_LOW; + } + + /* distribute dynamic bits to each element */ + FDKaacEnc_distributeElementDynBits(hQC, + qcElement[0], + cm, + qcOut[0]->grantedDynBits); + + *avgTotalDynBits = 0; /*frameDynBits;*/ + + *totalAvailableBits = avgTotalBits; + + /* sum up corrected granted PE */ + qcOut[0]->totalGrantedPeCorr = 0; + + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + int nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* for ( all sub frames ) ... */ + FDKaacEnc_DistributeBits(hQC->hAdjThr, + hQC->hAdjThr->adjThrStateElem[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, + &qcElement[0][i]->peData, + &qcElement[0][i]->grantedPe, + &qcElement[0][i]->grantedPeCorr, + nChannels, + psyOut[0]->psyOutElement[i]->commonWindow, + qcElement[0][i]->grantedDynBits, + hQC->elementBits[i]->bitResLevelEl, + hQC->elementBits[i]->maxBitResBitsEl, + hQC->maxBitFac, + hQC->bitDistributionMode); + + *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl; + /* get total corrected granted PE */ + qcOut[0]->totalGrantedPeCorr += qcElement[0][i]->grantedPeCorr; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + *totalAvailableBits = FDKmin(hQC->maxBitsPerFrame, (*totalAvailableBits)); + + return AAC_ENC_OK; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static AAC_ENCODER_ERROR FDKaacEnc_updateUsedDynBits(INT* sumDynBitsConsumed, + QC_OUT_ELEMENT* qcElement[(8)], + CHANNEL_MAPPING* cm) +{ + INT i; + + *sumDynBitsConsumed = 0; + + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* sum up bits consumed */ + *sumDynBitsConsumed += qcElement[i]->dynBitsUsed; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + return AAC_ENC_OK; +} + + +static INT FDKaacEnc_getTotalConsumedDynBits(QC_OUT** qcOut, + INT nSubFrames) +{ + INT c, totalBits=0; + + /* sum up bit consumption for all sub frames */ + for (c=0; cusedDynBits==-1) return -1; + totalBits += qcOut[c]->usedDynBits; + } + + return totalBits; + +} + +static INT FDKaacEnc_getTotalConsumedBits(QC_OUT** qcOut, + QC_OUT_ELEMENT* qcElement[(1)][(8)], + CHANNEL_MAPPING* cm, + INT globHdrBits, + INT nSubFrames) +{ + int c, i; + int totalUsedBits = 0; + + for (c = 0 ; c < nSubFrames ; c++ ) + { + int dataBits = 0; + for (i=0; inElements; i++) + { + if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) + { + dataBits += qcElement[c][i]->dynBitsUsed + qcElement[c][i]->staticBitsUsed + qcElement[c][i]->extBitsUsed; + } + } + dataBits += qcOut[c]->globalExtBits; + + totalUsedBits += (8 - (dataBits) % 8) % 8; + totalUsedBits += dataBits + globHdrBits; /* header bits for every frame */ + } + return totalUsedBits; +} + +static AAC_ENCODER_ERROR FDKaacEnc_BitResRedistribution( + QC_STATE *const hQC, + const CHANNEL_MAPPING *const cm, + const INT avgTotalBits + ) +{ + /* check bitreservoir fill level */ + if (hQC->bitResTot < 0) { + return AAC_ENC_BITRES_TOO_LOW; + } + else if (hQC->bitResTot > hQC->bitResTotMax) { + return AAC_ENC_BITRES_TOO_HIGH; + } + else { + INT i, firstEl = cm->nElements-1; + INT totalBits = 0, totalBits_max = 0; + + int totalBitreservoir = FDKmin(hQC->bitResTot, (hQC->maxBitsPerFrame-avgTotalBits)); + int totalBitreservoirMax = FDKmin(hQC->bitResTotMax, (hQC->maxBitsPerFrame-avgTotalBits)); + + int sc_bitResTot = CountLeadingBits(totalBitreservoir); + int sc_bitResTotMax = CountLeadingBits(totalBitreservoirMax); + + for (i=(cm->nElements-1); i>=0; i--) { + if ((cm->elInfo[i].elType == ID_SCE) || (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) + { + hQC->elementBits[i]->bitResLevelEl = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)(totalBitreservoir<>sc_bitResTot; + totalBits += hQC->elementBits[i]->bitResLevelEl; + + hQC->elementBits[i]->maxBitResBitsEl = (INT)fMult(hQC->elementBits[i]->relativeBitsEl, (FIXP_DBL)(totalBitreservoirMax<>sc_bitResTotMax; + totalBits_max += hQC->elementBits[i]->maxBitResBitsEl; + + firstEl = i; + } + } + hQC->elementBits[firstEl]->bitResLevelEl += totalBitreservoir - totalBits; + hQC->elementBits[firstEl]->maxBitResBitsEl += totalBitreservoirMax - totalBits_max; + } + + return AAC_ENC_OK; +} + + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, + PSY_OUT** psyOut, + QC_OUT** qcOut, + INT avgTotalBits, + CHANNEL_MAPPING* cm + ,AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ) +{ + int i, c; + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */ + INT totalAvailableBits = 0; + INT nSubFrames = 1; + + /*-------------------------------------------- */ + /* redistribute total bitreservoir to elements */ + ErrorStatus = FDKaacEnc_BitResRedistribution(hQC, cm, avgTotalBits); + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + + /*-------------------------------------------- */ + /* fastenc needs one time threshold simulation, + in case of multiple frames, one more guess has to be calculated */ + + /*-------------------------------------------- */ + /* helper pointer */ + QC_OUT_ELEMENT* qcElement[(1)][(8)]; + + /* work on a copy of qcChannel and qcElement */ + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* for ( all sub frames ) ... */ + for (c = 0 ; c < nSubFrames ; c++ ) + { + { + qcElement[c][i] = qcOut[c]->qcElement[i]; + } + } + } + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + if ( isConstantBitrateMode(hQC->bitrateMode) ) + { + /* calc granted dynamic bits for sub frame and + distribute it to each element */ + ErrorStatus = FDKaacEnc_prepareBitDistribution( + hQC, + psyOut, + qcOut, + cm, + qcElement, + avgTotalBits, + &totalAvailableBits, + &avgTotalDynBits); + + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + } + else { + qcOut[0]->grantedDynBits = ((hQC->maxBitsPerFrame - (hQC->globHdrBits))&~7) + - (qcOut[0]->globalExtBits + qcOut[0]->staticBits + qcOut[0]->elementExtBits); + qcOut[0]->maxDynBits = qcOut[0]->grantedDynBits; + + totalAvailableBits = hQC->maxBitsPerFrame; + avgTotalDynBits = 0; + } + +#ifdef PNS_PRECOUNT_ENABLE + /* Calculate estimated pns bits and substract them from grantedDynBits to get a more accurate number of available bits. */ + if (syntaxFlags & (AC_LD|AC_ELD)) + { + int estimatedPnsBits = 0, ch; + + for (ch=0; chnChannels; ch++) { + qcOut[0]->pQcOutChannels[ch]->sectionData.noiseNrgBits = noisePreCount(psyOut[0]->pPsyOutChannels[ch]->noiseNrg, psyOut[0]->pPsyOutChannels[ch]->maxSfbPerGroup); + estimatedPnsBits += qcOut[0]->pQcOutChannels[ch]->sectionData.noiseNrgBits; + } + qcOut[0]->grantedDynBits -= estimatedPnsBits; + } +#endif + + /* for ( all sub frames ) ... */ + for (c = 0 ; c < nSubFrames ; c++ ) + { + /* for CBR and VBR mode */ + FDKaacEnc_AdjustThresholds(hQC->hAdjThr->adjThrStateElem, + qcElement[c], + qcOut[c], + psyOut[c]->psyOutElement, + isConstantBitrateMode(hQC->bitrateMode), + hQC->hAdjThr->maxIter2ndGuess, + cm); + + } /* -end- sub frame counter */ + + /*-------------------------------------------- */ + INT iterations[(1)][(8)]; + INT chConstraintsFulfilled[(1)][(8)][(2)]; + INT calculateQuant[(1)][(8)][(2)]; + INT constraintsFulfilled[(1)][(8)]; + /*-------------------------------------------- */ + + + /* for ( all sub frames ) ... */ + for (c = 0 ; c < nSubFrames ; c++ ) + { + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* Turn thresholds into scalefactors, optimize bit consumption and verify conformance */ + FDKaacEnc_EstimateScaleFactors(psyOut[c]->psyOutElement[i]->psyOutChannel, + qcElement[c][i]->qcOutChannel, + hQC->invQuant, + hQC->dZoneQuantEnable, + cm->elInfo[i].nChannelsInEl); + + + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1; + iterations[c][i] = 0 ; + + for (ch = 0; ch < nChannels; ch++) + { + chConstraintsFulfilled[c][i][ch] = 1; + calculateQuant[c][i][ch] = 1; + } + + /*-------------------------------------------- */ + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + qcOut[c]->usedDynBits = -1; + + } /* -end- sub frame counter */ + + + + INT quantizationDone = 0; + INT sumDynBitsConsumedTotal = 0; + INT decreaseBitConsumption = -1; /* no direction yet! */ + + /*-------------------------------------------- */ + /* -start- Quantization loop ... */ + /*-------------------------------------------- */ + do /* until max allowed bits per frame and maxDynBits!=-1*/ + { + quantizationDone = 0; + + c = 0; /* get frame to process */ + + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + do /* until spectral values < MAX_QUANT */ + { + /*-------------------------------------------- */ + if (!constraintsFulfilled[c][i]) + { + FDKaacEnc_reduceBitConsumption(&iterations[c][i], + hQC->maxIterations, + (decreaseBitConsumption) ? 1 : -1, + chConstraintsFulfilled[c][i], + calculateQuant[c][i], + nChannels, + psyOut[c]->psyOutElement[i], + qcOut[c], + qcElement[c][i], + hQC->elementBits[i], + aot, + syntaxFlags, + epConfig); + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1 ; + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + for (ch = 0; ch < nChannels; ch++) + { + /*-------------------------------------------- */ + chConstraintsFulfilled[c][i][ch] = 1; + + /*-------------------------------------------- */ + + if (calculateQuant[c][i][ch]) + { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL* psyOutCh = psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + calculateQuant[c][i][ch] = 0; /* calculate quantization only if necessary */ + + /*-------------------------------------------- */ + FDKaacEnc_QuantizeSpectrum(psyOutCh->sfbCnt, + psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, + psyOutCh->sfbOffsets, + qcOutCh->mdctSpectrum, + qcOutCh->globalGain, + qcOutCh->scf, + qcOutCh->quantSpec, + hQC->dZoneQuantEnable); + + /*-------------------------------------------- */ + if (FDKaacEnc_calcMaxValueInSfb(psyOutCh->sfbCnt, + psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, + psyOutCh->sfbOffsets, + qcOutCh->quantSpec, + qcOutCh->maxValueInSfb) > MAX_QUANT) + { + chConstraintsFulfilled[c][i][ch] = 0; + constraintsFulfilled[c][i] = 0 ; + /* if quanizted value out of range; increase global gain! */ + decreaseBitConsumption = 1; + } + + /*-------------------------------------------- */ + + } /* if calculateQuant[c][i][ch] */ + + } /* channel loop */ + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + + /*-------------------------------------------- */ + + } while (!constraintsFulfilled[c][i]) ; /* does not regard bit consumption */ + + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + qcElement[c][i]->dynBitsUsed = 0 ; /* reset dynamic bits */ + + /* quantization valid in current channel! */ + for (ch = 0; ch < nChannels; ch++) + { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL *psyOutCh = psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + /* count dynamic bits */ + INT chDynBits = FDKaacEnc_dynBitCount(hQC->hBitCounter, + qcOutCh->quantSpec, + qcOutCh->maxValueInSfb, + qcOutCh->scf, + psyOutCh->lastWindowSequence, + psyOutCh->sfbCnt, + psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, + psyOutCh->sfbOffsets, + &qcOutCh->sectionData, + psyOutCh->noiseNrg, + psyOutCh->isBook, + psyOutCh->isScale, + syntaxFlags) ; + + /* sum up dynamic channel bits */ + qcElement[c][i]->dynBitsUsed += chDynBits; + } + + /* save dynBitsUsed for correction of bits2pe relation */ + if(hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast==-1) { + hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast = qcElement[c][i]->dynBitsUsed; + } + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + /* update dynBits of current subFrame */ + FDKaacEnc_updateUsedDynBits(&qcOut[c]->usedDynBits, + qcElement[c], + cm); + + /* get total consumed bits, dyn bits in all sub frames have to be valid */ + sumDynBitsConsumedTotal = FDKaacEnc_getTotalConsumedDynBits(qcOut, nSubFrames); + + if (sumDynBitsConsumedTotal==-1) + { + quantizationDone = 0; /* bit consumption not valid in all sub frames */ + } + else + { + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits(qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + /* in all frames are valid dynamic bits */ + if ( ((sumBitsConsumedTotal < totalAvailableBits) || qcOut[c]->usedDynBits==0) && (decreaseBitConsumption==1) && checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames) + /*()*/ ) + { + quantizationDone = 1; /* exit bit adjustment */ + } + if (sumBitsConsumedTotal > totalAvailableBits && (decreaseBitConsumption==0) ) +// /*()*/ ) + { + quantizationDone = 0; /* reset! */ + break; + } + } + + + /*-------------------------------------------- */ + + int emergencyIterations = 1; + int dynBitsOvershoot = 0; + + for (c = 0 ; c < nSubFrames ; c++ ) + { + for (i=0; inElements; i++) + { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) + { + /* iteration limitation */ + emergencyIterations &= ((iterations[c][i] < hQC->maxIterations) ? 0 : 1); + } + } + /* detection if used dyn bits exceeds the maximal allowed criterion */ + dynBitsOvershoot |= ((qcOut[c]->usedDynBits > qcOut[c]->maxDynBits) ? 1 : 0); + } + + if (quantizationDone==0 || dynBitsOvershoot) + { + + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits(qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + if ( (sumDynBitsConsumedTotal >= avgTotalDynBits) || (sumDynBitsConsumedTotal==0) ) { + quantizationDone = 1; + } + if (emergencyIterations && (sumBitsConsumedTotal < totalAvailableBits)) { + quantizationDone = 1; + } + if ((sumBitsConsumedTotal > totalAvailableBits) || !checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames)) { + quantizationDone = 0; + } + if ((sumBitsConsumedTotal < totalAvailableBits) && checkMinFrameBitsDemand(qcOut,hQC->minBitsPerFrame,nSubFrames)) { + decreaseBitConsumption = 0; + } + else { + decreaseBitConsumption = 1; + } + + if (dynBitsOvershoot) { + quantizationDone = 0; + decreaseBitConsumption = 1; + } + + /* reset constraints fullfilled flags */ + FDKmemclear(constraintsFulfilled, sizeof(constraintsFulfilled)); + FDKmemclear(chConstraintsFulfilled, sizeof(chConstraintsFulfilled)); + + + }/* quantizationDone */ + + } while (!quantizationDone) ; + + /*-------------------------------------------- */ + /* ... -end- Quantization loop */ + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + return AAC_ENC_OK; +} + + +static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption(int* iterations, + const int maxIterations, + int gainAdjustment, + int* chConstraintsFulfilled, + int* calculateQuant, + int nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, + QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig) +{ + int ch; + + /** SOLVING PROBLEM **/ + if ((*iterations)++ >= maxIterations) + { + if (qcOutElement->dynBitsUsed==0) { + } + /* crash recovery */ + else { + INT bitsToSave = 0; + if ( (bitsToSave = fixMax((qcOutElement->dynBitsUsed + 8) - (elBits->bitResLevelEl + qcOutElement->grantedDynBits), + (qcOutElement->dynBitsUsed + qcOutElement->staticBitsUsed + 8) - (elBits->maxBitsEl))) > 0 ) + { + FDKaacEnc_crashRecovery(nChannels, + psyOutElement, + qcOut, + qcOutElement, + bitsToSave, + aot, + syntaxFlags, + epConfig) ; + } + else + { + for (ch = 0; ch < nChannels; ch++) + { + qcOutElement->qcOutChannel[ch]->globalGain += 1; + } + } + for (ch = 0; ch < nChannels; ch++) + { + calculateQuant[ch] = 1; + } + } + } + else /* iterations >= maxIterations */ + { + /* increase gain (+ next iteration) */ + for (ch = 0; ch < nChannels; ch++) + { + if(!chConstraintsFulfilled[ch]) + { + qcOutElement->qcOutChannel[ch]->globalGain += gainAdjustment ; + calculateQuant[ch] = 1; /* global gain has changed, recalculate quantization in next iteration! */ + } + } + } + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, + QC_STATE* qcKernel, + ELEMENT_BITS* RESTRICT elBits[(8)], + QC_OUT** qcOut) +{ + switch (qcKernel->bitrateMode) { + case QCDATA_BR_MODE_SFR: + break; + + case QCDATA_BR_MODE_FF: + break; + + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + qcOut[0]->totFillBits = (qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits)&7; /* precalculate alignment bits */ + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += ( fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_INVALID: + default: + INT bitResSpace = qcKernel->bitResTotMax - qcKernel->bitResTot ; + /* processing fill-bits */ + INT deltaBitRes = qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits ; + qcOut[0]->totFillBits = fixMax((deltaBitRes&7), (deltaBitRes - (fixMax(0,bitResSpace-7)&~7))); + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += ( fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + } /* switch (qcKernel->bitrateMode) */ + + return AAC_ENC_OK; +} + + + + +/********************************************************************************* + + functionname: FDKaacEnc_calcMaxValueInSfb + description: + return: + +**********************************************************************************/ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, + INT maxSfbPerGroup, + INT sfbPerGroup, + INT *RESTRICT sfbOffset, + SHORT *RESTRICT quantSpectrum, + UINT *RESTRICT maxValue) +{ + INT sfbOffs,sfb; + INT maxValueAll = 0; + + for (sfbOffs=0;sfbOffsbitrateMode) { + case QCDATA_BR_MODE_FF: + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + /* variable bitrate */ + qcKernel->bitResTot = FDKmin(qcKernel->maxBitsPerFrame, qcKernel->bitResTotMax); + break; + + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_SFR: + case QCDATA_BR_MODE_INVALID: + default: + int c = 0; + /* constant bitrate */ + { + qcKernel->bitResTot += qcOut[c]->grantedDynBits - (qcOut[c]->usedDynBits + qcOut[c]->totFillBits + qcOut[c]->alignBits); + } + break; + } +} + +/********************************************************************************* + + functionname: FDKaacEnc_FinalizeBitConsumption + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption(CHANNEL_MAPPING *cm, + QC_STATE *qcKernel, + QC_OUT *qcOut, + QC_OUT_ELEMENT** qcElement, + HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig) +{ + QC_OUT_EXTENSION fillExtPayload; + INT totFillBits, alignBits; + + /* Get total consumed bits in AU */ + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + qcOut->totFillBits + + qcOut->elementExtBits + qcOut->globalExtBits; +#if 1 + if (qcKernel->bitrateMode==QCDATA_BR_MODE_CBR) { + + /* Now we can get the exact transport bit amount, and hopefully it is equal to the estimated value */ + INT exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (exactTpBits != qcKernel->globHdrBits) { + INT diffFillBits = 0; + + /* How many bits can be taken by bitreservoir */ + const INT bitresSpace = qcKernel->bitResTotMax - (qcKernel->bitResTot + (qcOut->grantedDynBits - (qcOut->usedDynBits + qcOut->totFillBits) ) ); + + /* Number of bits which can be moved to bitreservoir. */ + const INT bitsToBitres = qcKernel->globHdrBits - exactTpBits; + FDK_ASSERT(bitsToBitres>=0); /* is always positive */ + + /* If bitreservoir can not take all bits, move ramaining bits to fillbits */ + diffFillBits = FDKmax(0, bitsToBitres - bitresSpace); + + /* Assure previous alignment */ + diffFillBits = (diffFillBits+7)&~7; + + /* Move as many bits as possible to bitreservoir */ + qcKernel->bitResTot += (bitsToBitres-diffFillBits); + + /* Write remaing bits as fill bits */ + qcOut->totFillBits += diffFillBits; + qcOut->totalBits += diffFillBits; + qcOut->grantedDynBits += diffFillBits; + + /* Get new header bits */ + qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (qcKernel->globHdrBits != exactTpBits) { + /* In previous step, fill bits and corresponding total bits were changed when bitreservoir was completely filled. + Now we can take the too much taken bits caused by header overhead from bitreservoir. + */ + qcKernel->bitResTot -= (qcKernel->globHdrBits - exactTpBits); + } + } + + } /* MODE_CBR */ +#endif + /* Update exact number of consumed header bits. */ + qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + /* Save total fill bits and distribut to alignment and fill bits */ + totFillBits = qcOut->totFillBits; + + /* fake a fill extension payload */ + FDKmemclear(&fillExtPayload, sizeof(QC_OUT_EXTENSION)); + + fillExtPayload.type = EXT_FILL_DATA; + fillExtPayload.nPayloadBits = totFillBits; + + /* ask bitstream encoder how many of that bits can be written in a fill extension data entity */ + qcOut->totFillBits = FDKaacEnc_writeExtensionData( NULL, + &fillExtPayload, + 0, 0, + syntaxFlags, + aot, + epConfig ); + + //fprintf(stderr, "FinalizeBitConsumption(): totFillBits=%d, qcOut->totFillBits=%d \n", totFillBits, qcOut->totFillBits); + + /* now distribute extra fillbits and alignbits */ + alignBits = 7 - (qcOut->staticBits + qcOut->usedDynBits + qcOut->elementExtBits + + qcOut->totFillBits + qcOut->globalExtBits -1)%8; + + /* Maybe we could remove this */ + if( ((alignBits + qcOut->totFillBits - totFillBits)==8) && (qcOut->totFillBits>8) ) + qcOut->totFillBits -= 8; + + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + qcOut->totFillBits + + alignBits + qcOut->elementExtBits + qcOut->globalExtBits; + + if ( (qcOut->totalBits>qcKernel->maxBitsPerFrame) || (qcOut->totalBitsminBitsPerFrame) ) { + return AAC_ENC_QUANT_ERROR; + } + + qcOut->alignBits = alignBits; + + return AAC_ENC_OK; +} + + + +/********************************************************************************* + + functionname: FDKaacEnc_crashRecovery + description: fulfills constraints by means of brute force... + => bits are saved by cancelling out spectral lines!! + (beginning at the highest frequencies) + return: errorcode + +**********************************************************************************/ + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, + QC_OUT_ELEMENT *qcElement, + INT bitsToSave, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig) +{ + INT ch ; + INT savedBits = 0 ; + INT sfb, sfbGrp ; + INT bitsPerScf[(2)][MAX_GROUPED_SFB] ; + INT sectionToScf[(2)][MAX_GROUPED_SFB] ; + INT *sfbOffset ; + INT sect, statBitsNew ; + QC_OUT_CHANNEL **qcChannel = qcElement->qcOutChannel; + PSY_OUT_CHANNEL **psyChannel = psyOutElement->psyOutChannel; + + /* create a table which converts frq-bins to bit-demand... [bitsPerScf] */ + /* ...and another one which holds the corresponding sections [sectionToScf] */ + for (ch = 0; ch < nChannels; ch++) + { + sfbOffset = psyChannel[ch]->sfbOffsets ; + + for (sect = 0; sect < qcChannel[ch]->sectionData.noOfSections; sect++) + { + INT sfb ; + INT codeBook = qcChannel[ch]->sectionData.huffsection[sect].codeBook ; + + for (sfb = qcChannel[ch]->sectionData.huffsection[sect].sfbStart; + sfb < qcChannel[ch]->sectionData.huffsection[sect].sfbStart + + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt; + sfb++) + { + bitsPerScf[ch][sfb] = 0; + if ( (codeBook != CODE_BOOK_PNS_NO) /*&& + (sfb < (qcChannel[ch]->sectionData.noOfGroups*qcChannel[ch]->sectionData.maxSfbPerGroup))*/ ) + { + INT sfbStartLine = sfbOffset[sfb] ; + INT noOfLines = sfbOffset[sfb+1] - sfbStartLine ; + bitsPerScf[ch][sfb] = FDKaacEnc_countValues(&(qcChannel[ch]->quantSpec[sfbStartLine]), noOfLines, codeBook) ; + } + sectionToScf[ch][sfb] = sect ; + } + + } + } + + /* LOWER [maxSfb] IN BOTH CHANNELS!! */ + /* Attention: in case of stereo: maxSfbL == maxSfbR, GroupingL == GroupingR ; */ + + for (sfb = qcChannel[0]->sectionData.maxSfbPerGroup-1; sfb >= 0; sfb--) + { + for (sfbGrp = 0; sfbGrp < psyChannel[0]->sfbCnt; sfbGrp += psyChannel[0]->sfbPerGroup) + { + for (ch = 0; ch < nChannels; ch++) + { + int sect = sectionToScf[ch][sfbGrp+sfb]; + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt-- ; + savedBits += bitsPerScf[ch][sfbGrp+sfb] ; + + if (qcChannel[ch]->sectionData.huffsection[sect].sfbCnt == 0) { + savedBits += (psyChannel[ch]->lastWindowSequence!=SHORT_WINDOW) ? FDKaacEnc_sideInfoTabLong[0] + : FDKaacEnc_sideInfoTabShort[0]; + } + } + } + + /* ...have enough bits been saved? */ + if (savedBits >= bitsToSave) + break ; + + } /* sfb loop */ + + /* if not enough bits saved, + clean whole spectrum and remove side info overhead */ + if (sfb == -1) { + sfb = 0 ; + } + + for (ch = 0; ch < nChannels; ch++) + { + qcChannel[ch]->sectionData.maxSfbPerGroup = sfb ; + psyChannel[ch]->maxSfbPerGroup = sfb ; + /* when no spectrum is coded save tools info in bitstream */ + if(sfb==0) { + FDKmemclear(&psyChannel[ch]->tnsInfo, sizeof(TNS_INFO)); + FDKmemclear(&psyOutElement->toolsInfo, sizeof(TOOLSINFO)); + } + } + /* dynamic bits will be updated in iteration loop */ + + { /* if stop sfb has changed save bits in side info, e.g. MS or TNS coding */ + ELEMENT_INFO elInfo; + + FDKmemclear(&elInfo, sizeof(ELEMENT_INFO)); + elInfo.nChannelsInEl = nChannels; + elInfo.elType = (nChannels == 2) ? ID_CPE : ID_SCE; + + FDKaacEnc_ChannelElementWrite( NULL, &elInfo, NULL, + psyOutElement, + psyChannel, + syntaxFlags, + aot, + epConfig, + &statBitsNew, + 0 ); + } + + savedBits = qcElement->staticBitsUsed - statBitsNew; + + /* update static and dynamic bits */ + qcElement->staticBitsUsed -= savedBits; + qcElement->grantedDynBits += savedBits; + + qcOut->staticBits -= savedBits; + qcOut->grantedDynBits += savedBits; + qcOut->maxDynBits += savedBits; + + +} + + + +void FDKaacEnc_QCClose (QC_STATE **phQCstate, QC_OUT **phQC) +{ + int n, i; + + if (phQC!=NULL) { + + for (n=0;n<(1);n++) { + if (phQC[n] != NULL) { + QC_OUT *hQC = phQC[n]; + for (i=0; i<(8); i++) { + } + + for (i=0; i<(8); i++) { + if (hQC->qcElement[i]) + FreeRam_aacEnc_QCelement(&hQC->qcElement[i]); + } + + FreeRam_aacEnc_QCout(&phQC[n]); + } + } + } + + if (phQCstate!=NULL) { + if (*phQCstate != NULL) { + QC_STATE *hQCstate = *phQCstate; + + if (hQCstate->hAdjThr != NULL) + FDKaacEnc_AdjThrClose(&hQCstate->hAdjThr); + + if (hQCstate->hBitCounter != NULL) + FDKaacEnc_BCClose(&hQCstate->hBitCounter); + + for (i=0; i<(8); i++) { + if (hQCstate->elementBits[i]!=NULL) { + FreeRam_aacEnc_ElementBits(&hQCstate->elementBits[i]); + } + } + FreeRam_aacEnc_QCstate(phQCstate); + } + } +} + diff --git a/libAACenc/src/qc_main.h b/libAACenc/src/qc_main.h new file mode 100644 index 00000000..4e8c042a --- /dev/null +++ b/libAACenc/src/qc_main.h @@ -0,0 +1,170 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Quantizing & coding + +******************************************************************************/ +#ifndef _QC_MAIN_H +#define _QC_MAIN_H + + +#include "aacenc.h" +#include "qc_data.h" +#include "interface.h" +#include "psy_main.h" +#include "tpenc_lib.h" + +/* Quantizing & coding stage */ + +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT **phQC, + const INT nElements, + const INT nChannels, + const INT nSubFrames + ,UCHAR *dynamic_RAM + ); + +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT *phQC[(1)], + const INT nSubFrames, + const CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE **phQC, + INT nElements + ,UCHAR* dynamic_RAM + ); + +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, struct QC_INIT *init); + +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare( + ELEMENT_INFO *elInfo, + ATS_ELEMENT* RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT* RESTRICT psyOutElement, + QC_OUT_ELEMENT* RESTRICT qcOutElement, /* returns error code */ + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ); + + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, + PSY_OUT** psyOut, + QC_OUT** qcOut, + INT avgTotalBits, + CHANNEL_MAPPING* cm + ,AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ); + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, + QC_STATE* qcKernel, + ELEMENT_BITS* RESTRICT elBits[(8)], + QC_OUT** qcOut); + + +void FDKaacEnc_updateBitres( CHANNEL_MAPPING *cm, + QC_STATE *qcKernel, + QC_OUT **qcOut); + +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( CHANNEL_MAPPING *cm, + QC_STATE *hQC, + QC_OUT *qcOut, + QC_OUT_ELEMENT** qcElement, + HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, + SCHAR epConfig + ); + +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate(QC_STATE *RESTRICT hQC, + CHANNEL_MAPPING *RESTRICT cm, + INT *avgTotalBits, + INT bitRate, + INT sampleRate, + INT granuleLength); + +void FDKaacEnc_QCClose (QC_STATE **phQCstate, QC_OUT **phQC); + +#endif /* _QC_MAIN_H */ diff --git a/libAACenc/src/quantize.cpp b/libAACenc/src/quantize.cpp new file mode 100644 index 00000000..a74da0ea --- /dev/null +++ b/libAACenc/src/quantize.cpp @@ -0,0 +1,405 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Quantization + +******************************************************************************/ + +#include "quantize.h" + +#include "aacEnc_rom.h" + +/***************************************************************************** + + functionname: FDKaacEnc_quantizeLines + description: quantizes spectrum lines + returns: + input: global gain, number of lines to process, spectral data + output: quantized spectrum + +*****************************************************************************/ +static void FDKaacEnc_quantizeLines(INT gain, + INT noOfLines, + FIXP_DBL *mdctSpectrum, + SHORT *quaSpectrum, + INT dZoneQuantEnable) +{ + int line; + FIXP_DBL k = FL2FXCONST_DBL(0.0f); + FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain)&3]; + INT quantizershift = ((-gain)>>2)+1; + const INT kShift=16; + + if (dZoneQuantEnable) + k = FL2FXCONST_DBL(0.23f)>>kShift; + else + k = FL2FXCONST_DBL(-0.0946f + 0.5f)>>kShift; + + for (line = 0; line < noOfLines; line++) + { + FIXP_DBL accu = fMultDiv2(mdctSpectrum[line],quantizer); + + if (accu < FL2FXCONST_DBL(0.0f)) + { + accu=-accu; + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not necessary here since test value is always > 0 */ + accu <<= accuShift; + INT tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); + INT totalShift = quantizershift-accuShift+1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],FDKaacEnc_quantTableE[totalShift&3]); + totalShift = (16-4)-(3*(totalShift>>2)); + FDK_ASSERT(totalShift >=0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift,DFRACT_BITS-1); + quaSpectrum[line] = (SHORT)(-((LONG)(k + accu) >> (DFRACT_BITS-1-16))); + } + else if(accu > FL2FXCONST_DBL(0.0f)) + { + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not necessary here since test value is always > 0 */ + accu <<= accuShift; + INT tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); + INT totalShift = quantizershift-accuShift+1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex],FDKaacEnc_quantTableE[totalShift&3]); + totalShift = (16-4)-(3*(totalShift>>2)); + FDK_ASSERT(totalShift >=0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift,DFRACT_BITS-1); + quaSpectrum[line] = (SHORT)((LONG)(k + accu) >> (DFRACT_BITS-1-16)); + } + else + quaSpectrum[line]=0; + } +} + + +/***************************************************************************** + + functionname:iFDKaacEnc_quantizeLines + description: iquantizes spectrum lines + mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) + input: global gain, number of lines to process,quantized spectrum + output: spectral data + +*****************************************************************************/ +static void FDKaacEnc_invQuantizeLines(INT gain, + INT noOfLines, + SHORT *quantSpectrum, + FIXP_DBL *mdctSpectrum) + +{ + INT iquantizermod; + INT iquantizershift; + INT line; + + iquantizermod = gain&3; + iquantizershift = gain>>2; + + for (line = 0; line < noOfLines; line++) { + + if(quantSpectrum[line] < 0) { + FIXP_DBL accu; + INT ex,specExp,tabIndex; + FIXP_DBL s,t; + + accu = (FIXP_DBL) -quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS-1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s,t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp]-1; /* -1 to avoid overflows in accu */ + + if ((-iquantizershift-specExp) < 0) + accu <<= -(-iquantizershift-specExp); + else + accu >>= -iquantizershift-specExp; + + mdctSpectrum[line] = -accu; + } + else if (quantSpectrum[line] > 0) { + FIXP_DBL accu; + INT ex,specExp,tabIndex; + FIXP_DBL s,t; + + accu = (FIXP_DBL)(INT)quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS-1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu>>(DFRACT_BITS-2-MANT_DIGITS))&(~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s,t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp]-1; /* -1 to avoid overflows in accu */ + + if (( -iquantizershift-specExp) < 0) + accu <<= -(-iquantizershift-specExp); + else + accu >>= -iquantizershift-specExp; + + mdctSpectrum[line] = accu; + } + else { + mdctSpectrum[line] = FL2FXCONST_DBL(0.0f); + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_QuantizeSpectrum + description: quantizes the entire spectrum + returns: + input: number of scalefactor bands to be quantized, ... + output: quantized spectrum + +*****************************************************************************/ +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, + INT maxSfbPerGroup, + INT sfbPerGroup, + INT *sfbOffset, + FIXP_DBL *mdctSpectrum, + INT globalGain, + INT *scalefactors, + SHORT *quantizedSpectrum, + INT dZoneQuantEnable) +{ + INT sfbOffs,sfb; + + /* in FDKaacEnc_quantizeLines quaSpectrum is calculated with: + spec^(3/4) * 2^(-3/16*QSS) * 2^(3/4*scale) + k + simplify scaling calculation and reduce QSS before: + spec^(3/4) * 2^(-3/16*(QSS - 4*scale)) */ + + for(sfbOffs=0;sfbOffsMAX_QUANT) { + return FL2FXCONST_DBL(0.0f); + } + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain,1,&quantSpectrum[i],&invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i]>>1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + scale = fixMin(2*(scale-1), DFRACT_BITS-1); + + diff = scaleValue(diff, -scale); + + xfsf = xfsf + diff; + } + + xfsf = CalcLdData(xfsf); + + return xfsf; +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcSfbQuantEnergyAndDist + description: calculates energy and distortion of quantized values + returns: + input: gain, number of lines to process, quantized spectral data, + spectral data + output: energy, distortion + +*****************************************************************************/ +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, + INT noOfLines, + INT gain, + FIXP_DBL *en, + FIXP_DBL *dist) +{ + INT i,scale; + FIXP_DBL invQuantSpec; + FIXP_DBL diff; + + FIXP_DBL energy = FL2FXCONST_DBL(0.0f); + FIXP_DBL distortion = FL2FXCONST_DBL(0.0f); + + for (i=0; iMAX_QUANT) { + *en = FL2FXCONST_DBL(0.0f); + *dist = FL2FXCONST_DBL(0.0f); + return; + } + + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain,1,&quantSpectrum[i],&invQuantSpec); + + /* energy */ + energy += fPow2(invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i]>>1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + + scale = fixMin(2*(scale-1), DFRACT_BITS-1); + + diff = scaleValue(diff, -scale); + + distortion += diff; + } + + *en = CalcLdData(energy)+FL2FXCONST_DBL(0.03125f); + *dist = CalcLdData(distortion); +} + diff --git a/libAACenc/src/quantize.h b/libAACenc/src/quantize.h new file mode 100644 index 00000000..16d3d4e4 --- /dev/null +++ b/libAACenc/src/quantize.h @@ -0,0 +1,121 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Quantization + +******************************************************************************/ + +#ifndef _QUANTIZE_H_ +#define _QUANTIZE_H_ + +#include "common_fix.h" + +/* quantizing */ + +#define MAX_QUANT 8191 + +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, + INT maxSfbPerGroup, + INT sfbPerGroup, + INT *sfbOffset, FIXP_DBL *mdctSpectrum, + INT globalGain, INT *scalefactors, + SHORT *quantizedSpectrum, + INT dZoneQuantEnable); + +FIXP_DBL FDKaacEnc_calcSfbDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, + INT noOfLines, + INT gain, + INT dZoneQuantEnable); + +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, + INT noOfLines, + INT gain, + FIXP_DBL *en, + FIXP_DBL *dist); + +#endif /* _QUANTIZE_H_ */ diff --git a/libAACenc/src/sf_estim.cpp b/libAACenc/src/sf_estim.cpp new file mode 100644 index 00000000..1cb243b9 --- /dev/null +++ b/libAACenc/src/sf_estim.cpp @@ -0,0 +1,1330 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Scale factor estimation + +******************************************************************************/ + +#include "sf_estim.h" +#include "aacEnc_rom.h" +#include "quantize.h" +#include "bit_cnt.h" + + + + +#define AS_PE_FAC_SHIFT 7 +#define DIST_FAC_SHIFT 3 +#define AS_PE_FAC_FLOAT (float)(1 << AS_PE_FAC_SHIFT) +static const INT MAX_SCF_DELTA = 60; + + +static const FIXP_DBL PE_C1 = FL2FXCONST_DBL(3.0f/AS_PE_FAC_FLOAT); /* (log(8.0)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C2 = FL2FXCONST_DBL(1.3219281f/AS_PE_FAC_FLOAT); /* (log(2.5)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C3 = FL2FXCONST_DBL(0.5593573f); /* 1-C2/C1 */ + + +/* + Function; FDKaacEnc_FDKaacEnc_CalcFormFactorChannel + + Description: Calculates the formfactor + + sf: scale factor of the mdct spectrum + sfbFormFactorLdData is scaled with the factor 1/(((2^sf)^0.5) * (2^FORM_FAC_SHIFT)) +*/ +static void +FDKaacEnc_FDKaacEnc_CalcFormFactorChannel(FIXP_DBL *RESTRICT sfbFormFactorLdData, + PSY_OUT_CHANNEL *RESTRICT psyOutChan) +{ + INT j, sfb, sfbGrp; + FIXP_DBL formFactor; + + int tmp0 = psyOutChan->sfbCnt; + int tmp1 = psyOutChan->maxSfbPerGroup; + int step = psyOutChan->sfbPerGroup; + for(sfbGrp = 0; sfbGrp < tmp0; sfbGrp += step) { + for (sfb = 0; sfb < tmp1; sfb++) { + formFactor = FL2FXCONST_DBL(0.0f); + /* calc sum of sqrt(spec) */ + for(j=psyOutChan->sfbOffsets[sfbGrp+sfb]; jsfbOffsets[sfbGrp+sfb+1]; j++ ) { + formFactor += sqrtFixp(fixp_abs(psyOutChan->mdctSpectrum[j]))>>FORM_FAC_SHIFT; + } + sfbFormFactorLdData[sfbGrp+sfb] = CalcLdData(formFactor); + } + /* set sfbFormFactor for sfbs with zero spec to zero. Just for debugging. */ + for ( ; sfb < psyOutChan->sfbPerGroup; sfb++) { + sfbFormFactorLdData[sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f); + } + } +} + +/* + Function: FDKaacEnc_CalcFormFactor + + Description: Calls FDKaacEnc_FDKaacEnc_CalcFormFactorChannel() for each channel +*/ + +void +FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels) +{ + INT j; + for (j=0; jsfbFormFactorLdData, psyOutChannel[j]); + } +} + +/* + Function: FDKaacEnc_calcSfbRelevantLines + + Description: Calculates sfbNRelevantLines + + sfbNRelevantLines is scaled with the factor 1/((2^FORM_FAC_SHIFT) * 2.0) +*/ +static void +FDKaacEnc_calcSfbRelevantLines( const FIXP_DBL *const sfbFormFactorLdData, + const FIXP_DBL *const sfbEnergyLdData, + const FIXP_DBL *const sfbThresholdLdData, + const INT *const sfbOffsets, + const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + FIXP_DBL *sfbNRelevantLines) +{ + INT sfbOffs, sfb; + FIXP_DBL sfbWidthLdData; + FIXP_DBL asPeFacLdData = FL2FXCONST_DBL(0.109375); /* AS_PE_FAC_SHIFT*ld64(2) */ + FIXP_DBL accu; + + /* sfbNRelevantLines[i] = 2^( (sfbFormFactorLdData[i] - 0.25 * (sfbEnergyLdData[i] - ld64(sfbWidth[i]/(2^7)) - AS_PE_FAC_SHIFT*ld64(2)) * 64); */ + + FDKmemclear(sfbNRelevantLines, sfbCnt * sizeof(FIXP_DBL)); + + for (sfbOffs=0; sfbOffs (FIXP_DBL)sfbThresholdLdData[sfbOffs+sfb]) { + INT sfbWidth = sfbOffsets[sfbOffs+sfb+1] - sfbOffsets[sfbOffs+sfb]; + + /* avgFormFactorLdData = sqrtFixp(sqrtFixp(sfbEnergyLdData[sfbOffs+sfb]/sfbWidth)); */ + /* sfbNRelevantLines[sfbOffs+sfb] = sfbFormFactor[sfbOffs+sfb] / avgFormFactorLdData; */ + sfbWidthLdData = (FIXP_DBL)(sfbWidth << (DFRACT_BITS-1-AS_PE_FAC_SHIFT)); + sfbWidthLdData = CalcLdData(sfbWidthLdData); + + accu = sfbEnergyLdData[sfbOffs+sfb] - sfbWidthLdData - asPeFacLdData; + accu = sfbFormFactorLdData[sfbOffs+sfb] - (accu >> 2); + + sfbNRelevantLines[sfbOffs+sfb] = CalcInvLdData(accu) >> 1; + } + } + } +} + +/* + Function: FDKaacEnc_countSingleScfBits + + Description: + + scfBitsFract is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countSingleScfBits(INT scf, INT scfLeft, INT scfRight) +{ + FIXP_DBL scfBitsFract; + + scfBitsFract = (FIXP_DBL) ( FDKaacEnc_bitCountScalefactorDelta(scfLeft-scf) + + FDKaacEnc_bitCountScalefactorDelta(scf-scfRight) ); + + scfBitsFract = scfBitsFract << (DFRACT_BITS-1-(2*AS_PE_FAC_SHIFT)); + + return scfBitsFract; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_calcSingleSpecPe + + specPe is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_calcSingleSpecPe(INT scf, FIXP_DBL sfbConstPePart, FIXP_DBL nLines) +{ + FIXP_DBL specPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL ldRatio; + FIXP_DBL scfFract; + + scfFract = (FIXP_DBL)(scf << (DFRACT_BITS-1-AS_PE_FAC_SHIFT)); + + ldRatio = sfbConstPePart - fMult(FL2FXCONST_DBL(0.375f),scfFract); + + if (ldRatio >= PE_C1) { + specPe = fMult(FL2FXCONST_DBL(0.7f),fMult(nLines,ldRatio)); + } + else { + specPe = fMult(FL2FXCONST_DBL(0.7f),fMult(nLines,(PE_C2 + fMult(PE_C3,ldRatio)))); + } + + return specPe; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_countScfBitsDiff + + scfBitsDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countScfBitsDiff(INT *scfOld, + INT *scfNew, + INT sfbCnt, + INT startSfb, + INT stopSfb) +{ + FIXP_DBL scfBitsFract; + INT scfBitsDiff = 0; + INT sfb = 0, sfbLast; + INT sfbPrev, sfbNext; + + /* search for first relevant sfb */ + sfbLast = startSfb; + while ((sfbLast=0) && (scfOld[sfbPrev]==FDK_INT_MIN)) + sfbPrev--; + if (sfbPrev>=0) + scfBitsDiff += FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbPrev]-scfNew[sfbLast]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbPrev]-scfOld[sfbLast]); + /* now loop through all sfbs and count diffs of relevant sfbs */ + for (sfb=sfbLast+1; sfbsfbEnergy[sfb] * 6.75f / sfbFormFactor[sfb]) * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfb] == (FIXP_DBL)FDK_INT_MIN) + sfbConstPePart[sfb] = ((psyOutChan->sfbEnergyLdData[sfb] - sfbFormFactorLdData[sfb] - FL2FXCONST_DBL(0.09375f)) >> 1) + FL2FXCONST_DBL(0.02152255861f); + + scfFract = (FIXP_DBL) (scfOld[sfb] << (DFRACT_BITS-1-AS_PE_FAC_SHIFT)); + ldRatioOld = sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f),scfFract); + + scfFract = (FIXP_DBL) (scfNew[sfb] << (DFRACT_BITS-1-AS_PE_FAC_SHIFT)); + ldRatioNew = sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f),scfFract); + + if (ldRatioOld >= PE_C1) + pOld = ldRatioOld; + else + pOld = PE_C2 + fMult(PE_C3,ldRatioOld); + + if (ldRatioNew >= PE_C1) + pNew = ldRatioNew; + else + pNew = PE_C2 + fMult(PE_C3,ldRatioNew); + + specPeDiff += fMult(FL2FXCONST_DBL(0.7f),fMult(sfbNRelevantLines[sfb],(pNew - pOld))); + } + } + + return specPeDiff; +} + +/* + Function: FDKaacEnc_improveScf + + Description: Calculate the distortion by quantization and inverse quantization of the spectrum with + various scalefactors. The scalefactor which provides the best results will be used. +*/ +static INT FDKaacEnc_improveScf(FIXP_DBL *spec, + SHORT *quantSpec, + SHORT *quantSpecTmp, + INT sfbWidth, + FIXP_DBL threshLdData, + INT scf, + INT minScf, + FIXP_DBL *distLdData, + INT *minScfCalculated, + INT dZoneQuantEnable + ) +{ + FIXP_DBL sfbDistLdData; + INT scfBest = scf; + INT k; + FIXP_DBL distFactorLdData = FL2FXCONST_DBL(-0.0050301265); /* ld64(1/1.25) */ + + /* calc real distortion */ + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, + quantSpec, + sfbWidth, + scf, + dZoneQuantEnable); + *minScfCalculated = scf; + /* nmr > 1.25 -> try to improve nmr */ + if (sfbDistLdData > (threshLdData-distFactorLdData)) { + INT scfEstimated = scf; + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + INT cnt; + /* improve by bigger scf ? */ + cnt = 0; + + while ((sfbDistLdData > (threshLdData-distFactorLdData)) && (cnt++ < 3)) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, + quantSpecTmp, + sfbWidth, + scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k=0; k (threshLdData-distFactorLdData)) && (cnt++ < 1) && (scf > minScf)) { + scf--; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, + quantSpecTmp, + sfbWidth, + scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k=0; k try to find bigger scf to use less bits */ + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + FIXP_DBL sfbDistAllowedLdData = fixMin(sfbDistLdData-distFactorLdData,threshLdData); + int cnt; + for (cnt=0; cnt<3; cnt++) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, + quantSpecTmp, + sfbWidth, + scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistAllowedLdData) { + *minScfCalculated = scfBest+1; + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k=0; ksfbCnt; i++) { + prevScfLast[i] = FDK_INT_MAX; + prevScfNext[i] = FDK_INT_MAX; + deltaPeLast[i] = (FIXP_DBL)FDK_INT_MAX; + } + + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + do { + /* search for new relevant sfb */ + sfbNext++; + while ((sfbNext < psyOutChan->sfbCnt) && (scf[sfbNext] == FDK_INT_MIN)) + sfbNext++; + if ((sfbLast>=0) && (sfbAct>=0) && (sfbNextsfbCnt)) { + /* relevant scfs to the left and to the right */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = scf + sfbNext; + scfMin = fixMin(*scfLast, *scfNext); + scfMax = fixMax(*scfLast, *scfNext); + } + else if ((sfbLast==-1) && (sfbAct>=0) && (sfbNextsfbCnt)) { + /* first relevant scf */ + scfAct = scf[sfbAct]; + scfLast = &scfAct; + scfNext = scf + sfbNext; + scfMin = *scfNext; + scfMax = *scfNext; + } + else if ((sfbLast>=0) && (sfbAct>=0) && (sfbNext==psyOutChan->sfbCnt)) { + /* last relevant scf */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = &scfAct; + scfMin = *scfLast; + scfMax = *scfLast; + } + if (sfbAct>=0) + scfMin = fixMax(scfMin, minScf[sfbAct]); + + if ((sfbAct >= 0) && + (sfbLast>=0 || sfbNextsfbCnt) && + (scfAct > scfMin) && + (scfAct <= scfMin+MAX_SCF_DELTA) && + (scfAct >= scfMax-MAX_SCF_DELTA) && + (*scfLast != prevScfLast[sfbAct] || + *scfNext != prevScfNext[sfbAct] || + deltaPe < deltaPeLast[sfbAct])) { + /* bigger than neighbouring scf found, try to use smaller scf */ + success = 0; + + sfbWidth = psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct]; + sfbOffs = psyOutChan->sfbOffsets[sfbAct]; + + /* estimate required bits for actual scf */ + enLdData = qcOutChannel->sfbEnergyLdData[sfbAct]; + + /* sfbConstPePart[sfbAct] = (float)log(6.75f*en/sfbFormFactor[sfbAct]) * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfbAct] == (FIXP_DBL)FDK_INT_MIN) { + sfbConstPePart[sfbAct] = ((enLdData - sfbFormFactorLdData[sfbAct] - FL2FXCONST_DBL(0.09375f)) >> 1) + FL2FXCONST_DBL(0.02152255861f); + } + + sfbPeOld = FDKaacEnc_calcSingleSpecPe(scfAct,sfbConstPePart[sfbAct],sfbNRelevantLines[sfbAct]) + +FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext); + + deltaPeNew = deltaPe; + updateMinScfCalculated = 1; + + do { + /* estimate required bits for smaller scf */ + scfAct--; + /* check only if the same check was not done before */ + if (scfAct < minScfCalculated[sfbAct] && scfAct>=scfMax-MAX_SCF_DELTA){ + /* estimate required bits for new scf */ + sfbPeNew = FDKaacEnc_calcSingleSpecPe(scfAct,sfbConstPePart[sfbAct],sfbNRelevantLines[sfbAct]) + +FDKaacEnc_countSingleScfBits(scfAct,*scfLast, *scfNext); + + /* use new scf if no increase in pe and + quantization error is smaller */ + deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld; + /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */ + if (deltaPeTmp < FL2FXCONST_DBL(0.0006103515625f)) { + /* distortion of new scf */ + sfbDistNew = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, + quantSpecTmp+sfbOffs, + sfbWidth, + scfAct, + dZoneQuantEnable); + + if (sfbDistNew < sfbDist[sfbAct]) { + /* success, replace scf by new one */ + scf[sfbAct] = scfAct; + sfbDist[sfbAct] = sfbDistNew; + + for (k=0; k scfMin); + + deltaPe = deltaPeNew; + + /* save parameters to avoid multiple computations of the same sfb */ + prevScfLast[sfbAct] = *scfLast; + prevScfNext[sfbAct] = *scfNext; + deltaPeLast[sfbAct] = deltaPe; + } + + if (success && restartOnSuccess) { + /* start again at first sfb */ + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + success = 0; + } + else { + /* shift sfbs for next band */ + sfbLast = sfbAct; + sfbAct = sfbNext; + } + } while (sfbNext < psyOutChan->sfbCnt); +} + +/* + Function: FDKaacEnc_assimilateMultipleScf + +*/ +static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan, + QC_OUT_CHANNEL *qcOutChannel, + SHORT *quantSpec, + SHORT *quantSpecTmp, + INT dZoneQuantEnable, + INT *scf, + INT *minScf, + FIXP_DBL *sfbDist, + FIXP_DBL *sfbConstPePart, + FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) +{ + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfMin, scfMax, scfAct; + INT possibleRegionFound; + INT sfbWidth, sfbOffs, i, k; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew; + INT sfbCnt = psyOutChan->sfbCnt; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb=0; sfb scfAct)) + sfb++; + stopSfb = sfb; + + /* check if in all sfb of a valid region scfAct >= minScf[sfb] */ + possibleRegionFound = 0; + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb=startSfb; sfb> DIST_FAC_SHIFT; + + sfbWidth = psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs, + quantSpecTmp+sfbOffs, + sfbWidth, + scfAct, + dZoneQuantEnable); + + if (sfbDistNew[sfb] >qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum) { + deltaPe = deltaPeNew; + for (sfb=startSfb; sfbsfbOffsets[sfb+1] - + psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + scf[sfb] = scfAct; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k=0; k scfMin); + } +} + +/* + Function: FDKaacEnc_FDKaacEnc_assimilateMultipleScf2 + +*/ +static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutChan, + QC_OUT_CHANNEL *qcOutChannel, + SHORT *quantSpec, + SHORT *quantSpecTmp, + INT dZoneQuantEnable, + INT *scf, + INT *minScf, + FIXP_DBL *sfbDist, + FIXP_DBL *sfbConstPePart, + FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) +{ + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfAct, scfNew; + INT scfPrev, scfNext, scfPrevNextMin, scfPrevNextMax, scfLo, scfHi; + INT scfMin, scfMax; + INT *sfbOffs = psyOutChan->sfbOffsets; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], sfbDistMax[MAX_GROUPED_SFB]; + FIXP_DBL distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew = FL2FXCONST_DBL(0.0f); + INT sfbCnt = psyOutChan->sfbCnt; + INT bSuccess, bCheckScf; + INT i,k; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb=0; sfb= scfAct) + scfLo = fixMin(scfAct, scfPrevNextMin); + else + scfLo = scfPrevNextMax; + + if (startSfb < sfbCnt && scfHi-scfLo <= MAX_SCF_DELTA) { /* region found */ + /* 1. try to save bits by coarser quantization */ + if (scfHi > scf[startSfb]) { + /* calculate the allowed distortion */ + for (sfb=startSfb; sfbsfbThreshold[sfb]*sfbDist[sfb]*sfbDist[sfb],1.0f/3.0f); */ + /* sfbDistMax[sfb] = fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergy[sfb]*FL2FXCONST_DBL(1.e-3f)); */ + /* -0.15571537944 = ld64(1.e-3f)*/ + sfbDistMax[sfb] = fMult(FL2FXCONST_DBL(1.0f/3.0f),qcOutChannel->sfbThresholdLdData[sfb])+fMult(FL2FXCONST_DBL(1.0f/3.0f),sfbDist[sfb])+fMult(FL2FXCONST_DBL(1.0f/3.0f),sfbDist[sfb]); + sfbDistMax[sfb] = fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergyLdData[sfb]-FL2FXCONST_DBL(0.15571537944)); + sfbDistMax[sfb] = fixMin(sfbDistMax[sfb],qcOutChannel->sfbThresholdLdData[sfb]); + } + } + + /* loop over all possible scf values for this region */ + bCheckScf = 1; + for (scfNew=scf[startSfb]+1; scfNew<=scfHi; scfNew++) { + for (k=0; kmdctSpectrum+sfbOffs[sfb], + quantSpecTmp+sfbOffs[sfb], + sfbOffs[sfb+1]-sfbOffs[sfb], + scfNew, + dZoneQuantEnable); + + if (sfbDistNew[sfb] > sfbDistMax[sfb]) { + /* no improvement, skip further dist. calculations */ + bSuccess = 0; + if (sfbDistNew[sfb] == qcOutChannel->sfbEnergyLdData[sfb]) { + /* if whole sfb is already quantized to 0, further + checks with even coarser quant. are useless*/ + bCheckScf = 0; + } + break; + } + } + } + if (bCheckScf==0) /* further calculations useless ? */ + break; + /* distortion small enough ? -> use new scalefactors */ + if (bSuccess) { + deltaPe = deltaPeNew; + for (sfb=startSfb; sfb= minScf[sfb] */ + for (sfb=startSfb; sfb> DIST_FAC_SHIFT; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb], + quantSpecTmp+sfbOffs[sfb], + sfbOffs[sfb+1]-sfbOffs[sfb], + scfNew, + dZoneQuantEnable); + + if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < fMult(FL2FXCONST_DBL(0.8f),distOldSum)) { + deltaPe = deltaPeNew; + for (sfb=startSfb; sfbmdctSpectrum+sfbOffs[sfb], + quantSpec+sfbOffs[sfb], + sfbOffs[sfb+1]-sfbOffs[sfb], scfNew, + &sfbEnQ, &sfbDistNew[sfb]); + + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + + /* 0.00259488556167 = ld64(1.122f) */ + /* -0.00778722686652 = ld64(0.7079f) */ + if ((sfbDistNew[sfb] > (sfbDist[sfb]+FL2FXCONST_DBL(0.00259488556167f))) || (sfbEnQ < (qcOutChannel->sfbEnergyLdData[sfb] - FL2FXCONST_DBL(0.00778722686652f)))){ + bSuccess = 0; + break; + } + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum && bSuccess) { + deltaPe = deltaPeNew; + for (sfb=startSfb; sfb C1/2^8 */ + + + + if (invQuant>0) { + FDKmemclear(quantSpec, (1024)*sizeof(SHORT)); + } + + /* scfs without energy or with thresh>energy are marked with FDK_INT_MIN */ + for(i=0; isfbCnt; i++) { + scf[i] = FDK_INT_MIN; + } + + for (i=0; isfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for(sfb=0; sfbmaxSfbPerGroup; sfb++) { + + threshLdData = qcOutChannel->sfbThresholdLdData[sfbOffs+sfb]; + energyLdData = qcOutChannel->sfbEnergyLdData[sfbOffs+sfb]; + + sfbDistLdData[sfbOffs+sfb] = energyLdData; + + + if (energyLdData > threshLdData) { + FIXP_DBL tmp; + + /* energyPart = (float)log10(sfbFormFactor[sfbOffs+sfb]); */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + energyPartLdData = sfbFormFactorLdData[sfbOffs+sfb] + FL2FXCONST_DBL(0.09375f); + + /* influence of allowed distortion */ + /* thresholdPart = (float)log10(6.75*thresh+FLT_MIN); */ + thresholdPartLdData = threshConstLdData + threshLdData; + + /* scf calc */ + /* scfFloat = 8.8585f * (thresholdPart - energyPart); */ + scfFract = thresholdPartLdData - energyPartLdData; + /* conversion from log2 to log10 */ + scfFract = fMult(convConst,scfFract); + /* (8.8585f * scfFract)/8 = 8/8 * scfFract + 0.8585 * scfFract/8 */ + scfFract = scfFract + fMult(FL2FXCONST_DBL(0.8585f),scfFract >> 3); + + /* integer scalefactor */ + /* scfInt = (int)floor(scfFloat); */ + scfInt = (INT)(scfFract>>((DFRACT_BITS-1)-3-LD_DATA_SHIFT)); /* 3 bits => scfFract/8.0; 6 bits => ld64 */ + + /* maximum of spectrum */ + maxSpec = FL2FXCONST_DBL(0.0f); + + for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; jsfbOffsets[sfbOffs+sfb+1]; j++ ){ + absSpec = fixp_abs(qcOutChannel->mdctSpectrum[j]); + maxSpec = (absSpec > maxSpec) ? absSpec : maxSpec; + } + + /* lower scf limit to avoid quantized values bigger than MAX_QUANT */ + /* C1 = -69.33295f, C2 = 5.77078f = 4/log(2) */ + /* minSfMaxQuant[sfbOffs+sfb] = (int)ceil(C1 + C2*log(maxSpec)); */ + /* C1/2^8 + 4/log(2.0)*log(maxSpec)/2^8 => C1/2^8 + log(maxSpec)/log(2.0)*4/2^8 => C1/2^8 + log(maxSpec)/log(2.0)/64.0 */ + + //minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + CalcLdData(maxSpec)) >> ((DFRACT_BITS-1)-8))) + 1; + tmp = CalcLdData(maxSpec); + if (c1Const>FL2FXCONST_DBL(-1.f)-tmp) { + minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + tmp) >> ((DFRACT_BITS-1)-8))) + 1; + } + else { + minSfMaxQuant[sfbOffs+sfb] = ((INT) (FL2FXCONST_DBL(-1.f) >> ((DFRACT_BITS-1)-8))) + 1; + } + + scfInt = fixMax(scfInt, minSfMaxQuant[sfbOffs+sfb]); + + + /* find better scalefactor with analysis by synthesis */ + if (invQuant>0) { + scfInt = FDKaacEnc_improveScf(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb], + quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb], + quantSpecTmp+psyOutChannel->sfbOffsets[sfbOffs+sfb], + psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], + threshLdData, scfInt, minSfMaxQuant[sfbOffs+sfb], + &sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb], + dZoneQuantEnable + ); + } + scf[sfbOffs+sfb] = scfInt; + } + } + } + + + if (invQuant>1) { + /* try to decrease scf differences */ + FIXP_DBL sfbConstPePart[MAX_GROUPED_SFB]; + FIXP_DBL sfbNRelevantLines[MAX_GROUPED_SFB]; + + for (i=0; isfbCnt; i++) + sfbConstPePart[i] = (FIXP_DBL)FDK_INT_MIN; + + FDKaacEnc_calcSfbRelevantLines( sfbFormFactorLdData, + qcOutChannel->sfbEnergyLdData, + qcOutChannel->sfbThresholdLdData, + psyOutChannel->sfbOffsets, + psyOutChannel->sfbCnt, + psyOutChannel->sfbPerGroup, + psyOutChannel->maxSfbPerGroup, + sfbNRelevantLines); + + + FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, minScfCalculated, 1); + + if(invQuant > 1) { + FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + + FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + + + FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, + scf, + minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + } + } + + + /* get min scalefac */ + minSf = FDK_INT_MAX; + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (scf[sfbOffs+sfb]!=FDK_INT_MIN) + minSf = fixMin(minSf,scf[sfbOffs+sfb]); + } + } + + /* limit scf delta */ + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if ((scf[sfbOffs+sfb] != FDK_INT_MIN) && (minSf+MAX_SCF_DELTA) < scf[sfbOffs+sfb]) { + scf[sfbOffs+sfb] = minSf + MAX_SCF_DELTA; + if (invQuant > 0) { /* changed bands need to be quantized again */ + sfbDistLdData[sfbOffs+sfb] = + FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb], + quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb], + psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb], + scf[sfbOffs+sfb], + dZoneQuantEnable + ); + } + } + } + } + + + /* get max scalefac for global gain */ + maxSf = FDK_INT_MIN; + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + maxSf = fixMax(maxSf,scf[sfbOffs+sfb]); + } + } + + /* calc loop scalefactors, if spec is not all zero (i.e. maxSf == -99) */ + if( maxSf > FDK_INT_MIN ) { + *globalGain = maxSf; + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if( scf[sfbOffs+sfb] == FDK_INT_MIN ) { + scf[sfbOffs+sfb] = 0; + /* set band explicitely to zero */ + for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; jsfbOffsets[sfbOffs+sfb+1]; j++ ) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } + else { + scf[sfbOffs+sfb] = maxSf - scf[sfbOffs+sfb]; + } + } + } + } + else{ + *globalGain = 0; + /* set spectrum explicitely to zero */ + for (sfbOffs=0; sfbOffssfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + scf[sfbOffs+sfb] = 0; + /* set band explicitely to zero */ + for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; jsfbOffsets[sfbOffs+sfb+1]; j++ ) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } + } + } + + /* free quantSpecTmp from scratch */ + C_ALLOC_SCRATCH_END(quantSpecTmp, SHORT, (1024)); + + +} + +void +FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL* qcOutChannel[], + const int invQuant, + const INT dZoneQuantEnable, + const int nChannels) +{ + int ch; + + for (ch = 0; ch < nChannels; ch++) + { + FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(qcOutChannel[ch], + psyOutChannel[ch], + qcOutChannel[ch]->scf, + &qcOutChannel[ch]->globalGain, + qcOutChannel[ch]->sfbFormFactorLdData + ,invQuant, + qcOutChannel[ch]->quantSpec, + dZoneQuantEnable + ); + } + +} + diff --git a/libAACenc/src/sf_estim.h b/libAACenc/src/sf_estim.h new file mode 100644 index 00000000..ef8d366d --- /dev/null +++ b/libAACenc/src/sf_estim.h @@ -0,0 +1,118 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: Scale factor estimation + +******************************************************************************/ + +#ifndef _SF_ESTIM_H +#define _SF_ESTIM_H + +#include "common_fix.h" + + +#include "psy_const.h" +#include "qc_data.h" +#include "interface.h" + +#define FORM_FAC_SHIFT 6 + + +void +FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels); + +void +FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL* qcOutChannel[], + const int invQuant, + const INT dZoneQuantEnable, + const int nChannels); + + + +#endif diff --git a/libAACenc/src/spreading.cpp b/libAACenc/src/spreading.cpp new file mode 100644 index 00000000..852da1e1 --- /dev/null +++ b/libAACenc/src/spreading.cpp @@ -0,0 +1,114 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Spreading of energy + +******************************************************************************/ + +#include "spreading.h" + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy) +{ + int i; + FIXP_DBL delay; + + /* slope to higher frequencies */ + delay = pbSpreadEnergy[0]; + for (i=1; i=0; i--) { + delay = fixMax(pbSpreadEnergy[i], fMult(maskLowFactor[i],delay)); + pbSpreadEnergy[i] = delay; + } +} diff --git a/libAACenc/src/spreading.h b/libAACenc/src/spreading.h new file mode 100644 index 00000000..e1b506c8 --- /dev/null +++ b/libAACenc/src/spreading.h @@ -0,0 +1,102 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M.Werner + contents/description: Spreading of energy and weighted tonality + +******************************************************************************/ + +#ifndef _SPREADING_H +#define _SPREADING_H + +#include "common_fix.h" + + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy); + +#endif /* #ifndef _SPREADING_H */ diff --git a/libAACenc/src/tns_func.h b/libAACenc/src/tns_func.h new file mode 100644 index 00000000..5e5265df --- /dev/null +++ b/libAACenc/src/tns_func.h @@ -0,0 +1,145 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: Alex Goeschel + contents/description: Temporal noise shaping + +******************************************************************************/ + +#ifndef _TNS_FUNC_H +#define _TNS_FUNC_H + +#include "common_fix.h" + +#include "psy_configuration.h" + +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration(INT bitrate, + INT samplerate, + INT channels, + INT blocktype, + INT granuleLength, + INT isLowDelay, + INT ldSbrPresent, + TNS_CONFIG *tnsConfig, + PSY_CONFIGURATION *psyConfig, + INT active, + INT useTnsPeak ); + +INT FDKaacEnc_TnsDetect( + TNS_DATA *tnsData, + const TNS_CONFIG *tC, + TNS_INFO* tnsInfo, + INT sfbCnt, + FIXP_DBL *spectrum, + INT subBlockNumber, + INT blockType + ); + + + +void FDKaacEnc_TnsSync( + TNS_DATA *tnsDataDest, + const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, + TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, + const INT blockTypeSrc, + const TNS_CONFIG *tC + ); + +INT FDKaacEnc_TnsEncode( + TNS_INFO* tnsInfo, + TNS_DATA* tnsData, + const INT numOfSfb, + const TNS_CONFIG *tC, + const INT lowPassLine, + FIXP_DBL* spectrum, + const INT subBlockNumber, + const INT blockType + ); + + + +#endif /* _TNS_FUNC_H */ diff --git a/libAACenc/src/tonality.cpp b/libAACenc/src/tonality.cpp new file mode 100644 index 00000000..7246a34f --- /dev/null +++ b/libAACenc/src/tonality.cpp @@ -0,0 +1,204 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + author: M. Werner + contents/description: Convert chaos measure to the tonality index + +******************************************************************************/ + +#include "tonality.h" +#include "chaosmeasure.h" + +static const FIXP_DBL normlog = (FIXP_DBL)0xd977d949; /*FL2FXCONST_DBL(-0.4342944819f * FDKlog(2.0)/FDKlog(2.7182818)); */ + +static void FDKaacEnc_CalcSfbTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT chaosMeasure, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, + const INT *RESTRICT sfbOffset, + FIXP_DBL *RESTRICT sfbEnergyLD64 ); + + +void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, + const INT *sfbOffset, + INT usePns) +{ + INT j; +#if defined(ARCH_PREFER_MULT_32x16) + FIXP_SGL alpha_0 = FL2FXCONST_SGL(0.25f); /* used in smooth ChaosMeasure */ + FIXP_SGL alpha_1 = FL2FXCONST_SGL(1.0f-0.25f); /* used in smooth ChaosMeasure */ +#else + FIXP_DBL alpha_0 = FL2FXCONST_DBL(0.25f); /* used in smooth ChaosMeasure */ + FIXP_DBL alpha_1 = FL2FXCONST_DBL(1.0f-0.25f); /* used in smooth ChaosMeasure */ +#endif + INT numberOfLines = sfbOffset[sfbCnt]; + + if (!usePns) + return; + + C_ALLOC_SCRATCH_START(chaosMeasurePerLine, FIXP_DBL, (1024)); + /* calculate chaos measure */ + FDKaacEnc_CalculateChaosMeasure(spectrum, + numberOfLines, + chaosMeasurePerLine); + + /* smooth ChaosMeasure */ + for (j=1;j 7/2 = 4 (spc*spc) */ + + FIXP_DBL chaosMeasureSfb = FL2FXCONST_DBL(0.0); + + /* calc chaosMeasurePerSfb */ + for (j=(sfbOffset[i+1]-sfbOffset[i])-1; j>=0; j--) { + FIXP_DBL tmp = (*spectrum++)< FL2FXCONST_DBL(-0.0519051) ) /* > ld(0.05)+ld(2) */ + { + if (chaosMeasureSfbLD64 <= FL2FXCONST_DBL(0.0) ) + sfbTonality[i] = FX_DBL2FX_SGL(fMultDiv2( chaosMeasureSfbLD64 , normlog ) << 7); + else + sfbTonality[i] = FL2FXCONST_SGL(0.0); + } + else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } + else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } +} diff --git a/libAACenc/src/tonality.h b/libAACenc/src/tonality.h new file mode 100644 index 00000000..fbe78ee2 --- /dev/null +++ b/libAACenc/src/tonality.h @@ -0,0 +1,108 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + author: M. Lohwasser + contents/description: Calculate tonality index + +******************************************************************************/ + +#ifndef __TONALITY_H +#define __TONALITY_H + +#include "common_fix.h" + + +#include "chaosmeasure.h" + + +void FDKaacEnc_CalculateFullTonality( FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, + const INT *sfbOffset, + INT usePns); + +#endif diff --git a/libAACenc/src/transform.cpp b/libAACenc/src/transform.cpp new file mode 100644 index 00000000..690b82e1 --- /dev/null +++ b/libAACenc/src/transform.cpp @@ -0,0 +1,264 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************************************************************** + + Description: FDKaacLdEnc_MdctTransform480: + The module FDKaacLdEnc_MdctTransform will perform the MDCT. + The MDCT supports the sine window and + the zero padded window. The algorithm of the MDCT + can be divided in Windowing, PreModulation, Fft and + PostModulation. + +******************************************************************************/ + +#include "transform.h" + +#include "dct.h" +#include "psy_const.h" +#include "aacEnc_rom.h" +#include "FDK_tools_rom.h" + +INT FDKaacEnc_Transform_Real (const INT_PCM * pTimeData, + FIXP_DBL *RESTRICT mdctData, + const INT blockType, + const INT windowShape, + INT *prevWindowShape, + const INT frameLength, + INT *mdctData_e, + INT filterType + ,FIXP_DBL * RESTRICT overlapAddBuffer + ) +{ + const INT_PCM * RESTRICT timeData; + + INT i; + /* tl: transform length + fl: left window slope length + nl: left window slope offset + fr: right window slope length + nr: right window slope offset + See FDK_tools/doc/intern/mdct.tex for more detail. */ + int tl, fl, nl, fr, nr; + + const FIXP_WTP * RESTRICT pLeftWindowPart; + const FIXP_WTP * RESTRICT pRightWindowPart; + + /* + * MDCT scale: + * + 1: fMultDiv2() in windowing. + * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC. + */ + *mdctData_e = 1+1; + + tl = frameLength; + timeData = pTimeData; + + switch( blockType ) { + case LONG_WINDOW: + { + int offset = (windowShape == LOL_WINDOW) ? ((frameLength * 3)>>2) : 0; + fl = frameLength - offset; + fr = frameLength - offset; + } + break; + case STOP_WINDOW: + fl = frameLength >> 3; + fr = frameLength; + break; + case START_WINDOW: /* or StopStartSequence */ + fl = frameLength; + fr = frameLength >> 3; + break; + case SHORT_WINDOW: + fl = fr = frameLength >> 3; + tl >>= 3; + timeData = pTimeData + 3*fl + (fl/2); + break; + default: + FDK_ASSERT(0); + return -1; + break; + } + + /* Taken from FDK_tools/src/mdct.cpp Derive NR and NL */ + nr = (tl - fr)>>1; + nl = (tl - fl)>>1; + + pLeftWindowPart = FDKgetWindowSlope(fl, *prevWindowShape); + pRightWindowPart = FDKgetWindowSlope(fr, windowShape); + + /* windowing */ + if (filterType != FB_ELD) + { + /* Left window slope offset */ + for (i=0; i> ( 1 ); +#else + mdctData[(tl/2)+i] = - (FIXP_DBL) timeData[tl-i-1] << (DFRACT_BITS - SAMPLE_BITS - 1); +#endif + } + /* Left window slope */ + for (i=0; i> (1); +#else + mdctData[(tl/2)-1-i] = - (FIXP_DBL) timeData[tl+i] << (DFRACT_BITS - SAMPLE_BITS - 1); +#endif + } + /* Right window slope */ + for (i=0; i> (-WTS1)); + outval += (fMultDiv2((FIXP_PCM)timeData[L+N*3/4+i], pWindowELD[N+N/2+i]) >> (-WTS1) ); + outval += (fMultDiv2(overlapAddBuffer[N/2+i], pWindowELD[2*N+i])>> (-WTS2-1)); + + overlapAddBuffer[N/2+i] = overlapAddBuffer[i]; + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N/2+i] + (fMultDiv2(overlapAddBuffer[N+N/2-1-i], pWindowELD[2*N+N/2+i]) >> (-WTS2-1)); + + mdctData[N-1-i] = outval; + overlapAddBuffer[N+N/2-1-i] = outval; + } + + for(i=N/4;i> (-WTS1)) ; + outval += (fMultDiv2(overlapAddBuffer[N/2+i], pWindowELD[2*N+i]) >> (-WTS2-1)); + + overlapAddBuffer[N/2+i] = overlapAddBuffer[i] + (fMult((FIXP_PCM)timeData[L-N/4+i], pWindowELD[N/2+i])<< (WTS0-1) ); + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N/2+i] + (fMultDiv2(overlapAddBuffer[N+N/2-1-i], pWindowELD[2*N+N/2+i]) >> (-WTS2-1)); + + mdctData[N-1-i] = outval; + overlapAddBuffer[N+N/2-1-i] = outval; + } + } + + dct_IV(mdctData, tl, mdctData_e); + + *prevWindowShape = windowShape; + + return 0; +} + diff --git a/libAACenc/src/transform.h b/libAACenc/src/transform.h new file mode 100644 index 00000000..50531746 --- /dev/null +++ b/libAACenc/src/transform.h @@ -0,0 +1,123 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: M. Werner + contents/description: MDCT Transform + +******************************************************************************/ + +#ifndef _TRANSFORM_H +#define _TRANSFORM_H + +#include "common_fix.h" + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +/** + * \brief: Performe MDCT transform of time domain data. + * \param timeData pointer to time domain input signal. + * \param mdctData pointer to store frequency domain output data. + * \param blockType index indicating the type of block. Either + * LONG_WINDOW, START_WINDOW, SHORT_WINDOW or STOP_WINDOW. + * \param windowShape index indicating the window slope type to be used. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param frameLength length of the block. + * \param mdctData_e pointer to an INT where the exponent of the frequency + * domain output data is stored into. + * \return 0 in case of success, non-zero in case of error (inconsistent parameters). + */ +INT FDKaacEnc_Transform_Real (const INT_PCM *timeData, + FIXP_DBL *RESTRICT mdctData, + const INT blockType, + const INT windowShape, + INT *prevWindowShape, + const INT frameLength, + INT *mdctData_e, + INT filterType + ,FIXP_DBL * RESTRICT overlapAddBuffer + ); +#endif diff --git a/libFDK/include/FDK_archdef.h b/libFDK/include/FDK_archdef.h new file mode 100644 index 00000000..23224d5b --- /dev/null +++ b/libFDK/include/FDK_archdef.h @@ -0,0 +1,264 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): + Description: + +******************************************************************************/ + +#ifndef __ARCH_H__ +#define __ARCH_H__ + +/* Performance / Quality profile selector */ + #define FDK_HIGH_PERFORMANCE + +/* Unify some few toolchain specific defines to avoid having large "or" macro contraptions all over the source code. */ + +/* Take action against VisualStudio 2005 crosscompile problems. */ + +/* Use single macro (the GCC built in macro) for architecture identification independent of the particular toolchain */ +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || (defined(_MSC_VER) && defined(_M_IX86)) || defined (__x86_64__) || (defined(_MSC_VER) && defined(_M_X64)) +#define __x86__ +#endif + +#if (defined(_M_ARM) || defined(__CC_ARM)) && !defined(__arm__) || defined(__TI_TMS470_V5__) && !defined(__arm__) +#define __arm__ +#endif + +#if defined(_ARCH_PPC) && !defined(__powerpc__) +#define __powerpc__ 1 +#endif + + + +/* Define __ARM_ARCH_5TE__ if armv5te features are supported */ +#if (__TARGET_ARCH_ARM == 5) || defined(__TARGET_FEATURE_DSPMUL) || (_M_ARM == 5) || defined(__ARM_ARCH_5TEJ__) || defined(__TI_TMS470_V5__) || defined(__ARM_ARCH_7EM__) +#define __ARM_ARCH_5TE__ +#endif + +/* Define __ARM_ARCH_6__ if the armv6 intructions are being supported. */ +#if (__TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6ZK__) +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#endif + +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#if defined(__TARGET_ARCH_7_R) || defined(__ARM_ARCH_7R__) +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_R__ +#endif + +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#if defined(__TARGET_ARCH_7_A) || defined(__ARM_ARCH_7A__) +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_A__ +#endif + +/* Define __ARM_ARCH_7M__ if the ARMv7-M instructions are being supported, e.g. Cortex-M3. */ +#if defined(__TARGET_ARCH_7_M) || defined(__ARM_ARCH_7_M__) +#define __ARM_ARCH_7M__ +#endif + +/* Define __ARM_ARCH_7EM__ if the ARMv7-ME instructions are being supported, e.g. Cortex-M4. */ +#if defined(__TARGET_ARCH_7E_M) || defined(__ARM_ARCH_7E_M__) +#define __ARM_ARCH_7EM__ +#endif + +/* Detect and unify macros for neon feature. */ +#if defined(__TARGET_FEATURE_NEON) && !defined(__ARM_NEON__) +#define __ARM_NEON__ +#endif + +#ifdef _M_ARM +#include "armintr.h" +#endif + + +/* Define preferred Multiplication type */ +#if defined(FDK_HIGH_PERFORMANCE) && !defined(FDK_HIGH_QUALITY) /* FDK_HIGH_PERFORMANCE */ + +#if defined(__mips__) || defined(__sh__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT +#undef WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_5TE__) /* cppp replaced: elif */ /* cppp replaced: elif */ +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7M__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7EM__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && !defined(__ARM_ARCH_5TE__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef WINDOWTABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT + +#elif defined(__aarch64__) || defined(__AARCH64EL__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__x86__) /* cppp replaced: elif */ +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define WINDOWTABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT + +#elif defined(__powerpc__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#else + + #warning >>>> Please set architecture characterization defines for your platform (FDK_HIGH_PERFORMANCE)! <<<< + +#endif /* Architecture switches */ + +#else /* neither FDK_HIGH_QUALITY or FDK_HIGH_PERFORMANCE */ + +#error Either set FDK_HIGH_QUALITY or FDK_HIGH_PERFORMANCE, but not both nor none of them. + +#endif /* End of quality/complexity tradeoff */ + +#define FDKTOOLS_PACKED_TABLES + + +#ifdef SINETABLE_16BIT + #define FIXP_STB FIXP_SGL /* STB sinus Tab used in transformation */ + #define FIXP_STP FIXP_SPK + #define STC(a) (FX_DBL2FXCONST_SGL(a)) +#else + #define FIXP_STB FIXP_DBL + #define FIXP_STP FIXP_DPK + #define STC(a) ((FIXP_DBL)(LONG)(a)) +#endif /* defined(SINETABLE_16BIT) */ + +#define STCP(cos,sin) { { STC(cos), STC(sin) } } + + +#ifdef WINDOWTABLE_16BIT + #define FIXP_WTB FIXP_SGL /* single FIXP_SGL values */ + #define FIXP_WTP FIXP_SPK /* packed FIXP_SGL values */ + #define WTC(a) FX_DBL2FXCONST_SGL(a) +#else /* SINETABLE_16BIT */ + #define FIXP_WTB FIXP_DBL + #define FIXP_WTP FIXP_DPK + #define WTC(a) (FIXP_DBL)(a) +#endif /* SINETABLE_16BIT */ + +#define WTCP(a,b) { { WTC(a), WTC(b) } } + + +#endif /* __ARCH_H__ */ diff --git a/libFDK/include/FDK_bitbuffer.h b/libFDK/include/FDK_bitbuffer.h new file mode 100644 index 00000000..65fa04b9 --- /dev/null +++ b/libFDK/include/FDK_bitbuffer.h @@ -0,0 +1,166 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: common bitbuffer read/write routines + +******************************************************************************/ + +#ifndef __FDK_BITBUFFER_H__ +#define __FDK_BITBUFFER_H__ + + + +#include "machine_type.h" + +typedef struct +{ + UINT ValidBits; + UINT ReadOffset; + UINT WriteOffset; + UINT BitCnt; + UINT BitNdx; + + UCHAR *Buffer; + UINT bufSize; + UINT bufBits; +} FDK_BITBUF; + +typedef FDK_BITBUF *HANDLE_FDK_BITBUF; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern const UINT BitMask [32+1]; + +/** The BitBuffer Functions are called straight from FDK_bitstream Interface. + For Functions functional survey look there. +*/ + +void FDK_CreateBitBuffer (HANDLE_FDK_BITBUF *hBitBuffer, UCHAR *pBuffer, UINT bufSize) ; + +void FDK_InitBitBuffer (HANDLE_FDK_BITBUF hBitBuffer, UCHAR *pBuffer, + UINT bufSize, UINT validBits) ; + +void FDK_ResetBitBuffer (HANDLE_FDK_BITBUF hBitBuffer) ; + +void FDK_DeleteBitBuffer (HANDLE_FDK_BITBUF hBitBuffer) ; + +INT FDK_get (HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits) ; + +INT FDK_get32 (HANDLE_FDK_BITBUF hBitBuffer) ; + +void FDK_put (HANDLE_FDK_BITBUF hBitBuffer, UINT value, const UINT numberOfBits) ; + +INT FDK_getBwd (HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits); +void FDK_putBwd (HANDLE_FDK_BITBUF hBitBuffer, UINT value, const UINT numberOfBits) ; + +void FDK_pushBack (HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, UCHAR config) ; +void FDK_pushForward (HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, UCHAR config) ; + +void FDK_byteAlign (HANDLE_FDK_BITBUF hBitBuffer, UCHAR config) ; + +UINT FDK_getValidBits (HANDLE_FDK_BITBUF hBitBuffer) ; +INT FDK_getFreeBits (HANDLE_FDK_BITBUF hBitBuffer) ; + +void FDK_setBitCnt (HANDLE_FDK_BITBUF hBitBuffer, const UINT value) ; +INT FDK_getBitCnt (HANDLE_FDK_BITBUF hBitBuffer) ; + +void FDK_Feed (HANDLE_FDK_BITBUF hBitBuffer, UCHAR inputBuffer [], + const UINT bufferSize, UINT *bytesValid) ; + +void FDK_Copy (HANDLE_FDK_BITBUF hBitBufDst, HANDLE_FDK_BITBUF hBitBufSrc, UINT *bytesValid) ; + +void FDK_Fetch (HANDLE_FDK_BITBUF hBitBuffer, UCHAR outBuf[], UINT *writeBytes); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/libFDK/include/FDK_bitstream.h b/libFDK/include/FDK_bitstream.h new file mode 100644 index 00000000..d47a750e --- /dev/null +++ b/libFDK/include/FDK_bitstream.h @@ -0,0 +1,657 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: bitstream interface to bitbuffer routines + +******************************************************************************/ + +#ifndef __FDK_BITSTREAM_H__ +#define __FDK_BITSTREAM_H__ + + + +#include "FDK_bitbuffer.h" +#include "machine_type.h" + +#include "genericStds.h" + +#define CACHE_BITS 32 + +typedef enum { + BS_READER, + BS_WRITER +} FDK_BS_CFG; + + +typedef struct +{ + UINT CacheWord ; + UINT BitsInCache ; + FDK_BITBUF hBitBuf; + UINT ConfigCache ; +} FDK_BITSTREAM; + +typedef FDK_BITSTREAM* HANDLE_FDK_BITSTREAM; + +/** + * \brief CreateBitStream Function. + * + * Create and initialize bitstream with extern allocated buffer. + * + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array. (awaits size 2^n) + * \param config Initialize BitStream as Reader or Writer. + */ +FDK_INLINE +HANDLE_FDK_BITSTREAM FDKcreateBitStream (UCHAR *pBuffer, + UINT bufSize, + FDK_BS_CFG config = BS_READER) +{ + HANDLE_FDK_BITSTREAM hBitStream = (HANDLE_FDK_BITSTREAM) FDKcalloc(1, sizeof(FDK_BITSTREAM)); + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, 0) ; + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0 ; + hBitStream->ConfigCache = config ; + + return hBitStream ; +} + + +/** + * \brief Initialize BistreamBuffer. BitBuffer can point to filled BitBuffer array . + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array. (awaits size 2^n) + * \param validBits Number of valid BitBuffer filled Bits. + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE +void FDKinitBitStream (HANDLE_FDK_BITSTREAM hBitStream, + UCHAR *pBuffer, + UINT bufSize, + UINT validBits, + FDK_BS_CFG config = BS_READER) +{ + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, validBits) ; + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0 ; + hBitStream->ConfigCache = config ; +} + + +/** + * \brief ResetBitbuffer Function. Reset states in BitBuffer and Cache. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE void FDKresetBitbuffer( HANDLE_FDK_BITSTREAM hBitStream, FDK_BS_CFG config = BS_READER) +{ + FDK_ResetBitBuffer( &hBitStream->hBitBuf ) ; + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0 ; + hBitStream->ConfigCache = config ; +} + + +/** DeleteBitStream. + + Deletes the in Create Bitstream allocated BitStream and BitBuffer. +*/ +FDK_INLINE void FDKdeleteBitStream (HANDLE_FDK_BITSTREAM hBitStream) +{ + FDK_DeleteBitBuffer(&hBitStream->hBitBuf) ; + FDKfree(hBitStream) ; +} + + +/** + * \brief ReadBits Function (forward). This function returns a number of sequential + * bits from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. + * \return the requested bits, right aligned + * \return + */ +#define OPTIMIZE_FDKREADBITS + +FDK_INLINE UINT FDKreadBits(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) +{ +#ifdef noOPTIMIZE_FDKREADBITS + INT missingBits = numberOfBits - hBitStream->BitsInCache; + if (missingBits > 0) + { + const UINT bits = hBitStream->CacheWord << missingBits; + const UINT validBits = FDK_getValidBits (&hBitStream->hBitBuf); + + if (validBits >= 32) + { + hBitStream->CacheWord = FDK_get32 (&hBitStream->hBitBuf) ; + hBitStream->BitsInCache = CACHE_BITS - missingBits; + } + else + { + hBitStream->CacheWord = FDK_get (&hBitStream->hBitBuf,validBits) ; + if (validBits >= missingBits) + { + hBitStream->BitsInCache = validBits - missingBits; + } + else + { + hBitStream->BitsInCache = 0; + hBitStream->CacheWord <<= missingBits - validBits; + } + } + + return ( bits | (hBitStream->CacheWord >> hBitStream->BitsInCache)) & BitMask[numberOfBits]; + } + + hBitStream->BitsInCache -= numberOfBits; + return ( hBitStream->CacheWord >> hBitStream->BitsInCache) & BitMask[numberOfBits]; + +#else + const UINT validMask = BitMask [numberOfBits] ; + + if (hBitStream->BitsInCache <= numberOfBits) + { + const UINT validBits = FDK_getValidBits (&hBitStream->hBitBuf) ; + const INT freeBits = (CACHE_BITS-1) - hBitStream->BitsInCache ; + const INT bitsToRead = (freeBits <= validBits) ? freeBits : validBits ; + + hBitStream->CacheWord = (hBitStream->CacheWord << bitsToRead) | FDK_get (&hBitStream->hBitBuf,bitsToRead) ; + hBitStream->BitsInCache += bitsToRead ; + if (hBitStream->BitsInCache < numberOfBits) + { + hBitStream->CacheWord <<= numberOfBits - hBitStream->BitsInCache; + hBitStream->BitsInCache = 0; + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & validMask ; + } + } + + hBitStream->BitsInCache -= numberOfBits ; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & validMask ; +#endif +} + +FDK_INLINE UINT FDKreadBit(HANDLE_FDK_BITSTREAM hBitStream) +{ +#ifdef OPTIMIZE_FDKREADBITS + if (!hBitStream->BitsInCache) + { + const UINT validBits = FDK_getValidBits (&hBitStream->hBitBuf); + + if (validBits >= 32) + { + hBitStream->CacheWord = FDK_get32 (&hBitStream->hBitBuf); + hBitStream->BitsInCache = CACHE_BITS; + } + else + { + hBitStream->CacheWord = FDK_get (&hBitStream->hBitBuf,validBits); + hBitStream->BitsInCache = validBits; + } + } + hBitStream->BitsInCache--; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & 1; +#else + return FDKreadBits(hBitStream,1); +#endif +} + +/** + * \brief Read2Bits Function (forward). This function 2 sequential + * bits from the input bitstream. It is the optimized version + of FDKreadBits() for readign 2 bits. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return the requested bits, right aligned + * \return + */ +inline UINT FDKread2Bits(HANDLE_FDK_BITSTREAM hBitStream) +{ + UINT BitsInCache = hBitStream->BitsInCache; + if (BitsInCache < 2) /* Comparison changed from 'less-equal' to 'less' */ + { + const UINT validBits = FDK_getValidBits (&hBitStream->hBitBuf) ; + const INT freeBits = (CACHE_BITS-1) - BitsInCache ; + const INT bitsToRead = (freeBits <= validBits) ? freeBits : validBits ; + + hBitStream->CacheWord = (hBitStream->CacheWord << bitsToRead) | FDK_get (&hBitStream->hBitBuf,bitsToRead) ; + BitsInCache += bitsToRead; + } + hBitStream->BitsInCache = BitsInCache - 2; + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & 0x3; +} + +/** + * \brief ReadBits Function (backward). This function returns a number of sequential bits + * from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKreadBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) +{ + const UINT validMask = BitMask [numberOfBits] ; + + if (hBitStream->BitsInCache <= numberOfBits) + { + const INT freeBits = (CACHE_BITS-1) - hBitStream->BitsInCache ; + + hBitStream->CacheWord = (hBitStream->CacheWord << freeBits) | FDK_getBwd (&hBitStream->hBitBuf,freeBits) ; + hBitStream->BitsInCache += freeBits ; + } + + hBitStream->BitsInCache -= numberOfBits ; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & validMask ; +} + + +/** + * \brief return a number of bits from the bitBuffer. + * You have to know what you do! Cache has to be synchronized before using this + * function. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKgetBits (HANDLE_FDK_BITSTREAM hBitStream, UINT numBits) +{ + return FDK_get (&hBitStream->hBitBuf, numBits) ; +} + + +/** + * \brief WriteBits Function. This function writes numberOfBits of value into bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value Variable holds data to be written. + * \param numberOfBits The number of bits to be written. + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteBits(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) +{ + const UINT validMask = BitMask [numberOfBits] ; + + if ((hBitStream->BitsInCache+numberOfBits) < CACHE_BITS) + { + hBitStream->BitsInCache += numberOfBits ; + hBitStream->CacheWord = (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } + else + { + FDK_put(&hBitStream->hBitBuf, hBitStream->CacheWord, hBitStream->BitsInCache) ; + hBitStream->BitsInCache = numberOfBits ; + hBitStream->CacheWord = (value & validMask) ; + } + + return numberOfBits; +} + + +/** + * \brief WriteBits Function (backward). This function writes numberOfBits of value into bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value Variable holds data to be written. + * \param numberOfBits The number of bits to be written. + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) +{ + const UINT validMask = BitMask [numberOfBits] ; + + if ((hBitStream->BitsInCache+numberOfBits) <= CACHE_BITS) + { + hBitStream->BitsInCache += numberOfBits ; + hBitStream->CacheWord = (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } + else + { + FDK_putBwd(&hBitStream->hBitBuf, hBitStream->CacheWord, hBitStream->BitsInCache) ; + hBitStream->BitsInCache = numberOfBits ; + hBitStream->CacheWord = (value & validMask) ; + } + + return numberOfBits; +} + + +/** + * \brief SyncCache Function. Clear cache after read forward. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCache (HANDLE_FDK_BITSTREAM hBitStream) +{ + if (hBitStream->ConfigCache == BS_READER) + FDK_pushBack (&hBitStream->hBitBuf,hBitStream->BitsInCache,hBitStream->ConfigCache) ; + else /* BS_WRITER */ + FDK_put(&hBitStream->hBitBuf, hBitStream->CacheWord, hBitStream->BitsInCache) ; + + hBitStream->BitsInCache = 0 ; + hBitStream->CacheWord = 0 ; +} + + +/** + * \brief SyncCache Function. Clear cache after read backwards. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCacheBwd (HANDLE_FDK_BITSTREAM hBitStream) +{ + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward (&hBitStream->hBitBuf,hBitStream->BitsInCache,hBitStream->ConfigCache) ; + } else { /* BS_WRITER */ + FDK_putBwd (&hBitStream->hBitBuf, hBitStream->CacheWord, hBitStream->BitsInCache) ; + } + + hBitStream->BitsInCache = 0 ; + hBitStream->CacheWord = 0 ; +} + + +/** + * \brief Byte Alignment Function. + * This function performs the byte_alignment() syntactic function on the input stream, + * i.e. some bits will be discarded/padded so that the next bits to be read/written will + * be aligned on a byte boundary with respect to the bit position 0. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKbyteAlign (HANDLE_FDK_BITSTREAM hBitStream) +{ + FDKsyncCache (hBitStream) ; + FDK_byteAlign (&hBitStream->hBitBuf, (UCHAR)hBitStream->ConfigCache) ; +} + + +/** + * \brief Byte Alignment Function with anchor + * This function performs the byte_alignment() syntactic function on the input stream, + * i.e. some bits will be discarded so that the next bits to be read/written would be aligned + * on a byte boundary with respect to the given alignment anchor. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param alignmentAnchor bit position to be considered as origin for byte alignment + * \return void + */ +FDK_INLINE void FDKbyteAlign (HANDLE_FDK_BITSTREAM hBitStream, UINT alignmentAnchor) +{ + FDKsyncCache (hBitStream) ; + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward (&hBitStream->hBitBuf, + (8 - ((alignmentAnchor - FDK_getValidBits(&hBitStream->hBitBuf)) & 0x07)) & 0x07, + hBitStream->ConfigCache) ; + } + else { + FDK_put (&hBitStream->hBitBuf, + 0, + (8 - ((FDK_getValidBits(&hBitStream->hBitBuf)-alignmentAnchor) & 0x07)) & 0x07 ); + } +} + + +/** + * \brief Push Back(Cache) / For / BiDirectional Function. + * PushBackCache function ungets a number of bits erroneously read/written by the last Get() call. + * NB: The number of bits to be stuffed back into the stream may never exceed the + * number of bits returned by the immediately preceding Get() call. + * + * PushBack function ungets a number of bits (combines cache and bitbuffer indices) + * PushFor function gets a number of bits (combines cache and bitbuffer indices) + * PushBiDirectional gets/ungets number of bits as defined in PusBack/For function + * NB: The sign of bits is not known, so the function checks direction and calls + * appropriate function. (positive sign pushFor, negative sign pushBack ) + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be pushed back/for. + * \return void + */ +FDK_INLINE void FDKpushBackCache (HANDLE_FDK_BITSTREAM hBitStream, const UINT numberOfBits) +{ + FDK_ASSERT ((hBitStream->BitsInCache+numberOfBits)<=CACHE_BITS); + hBitStream->BitsInCache += numberOfBits ; +} + +FDK_INLINE void FDKpushBack (HANDLE_FDK_BITSTREAM hBitStream, const UINT numberOfBits) +{ + if ((hBitStream->BitsInCache+numberOfBits)ConfigCache == BS_READER) ) { + hBitStream->BitsInCache += numberOfBits ; + FDKsyncCache(hBitStream) ; /* sync cache to avoid invalid cache */ + } + else { + FDKsyncCache(hBitStream) ; + FDK_pushBack(&hBitStream->hBitBuf,numberOfBits,hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushFor (HANDLE_FDK_BITSTREAM hBitStream, const UINT numberOfBits) +{ + if ( (hBitStream->BitsInCache>numberOfBits) && (hBitStream->ConfigCache == BS_READER) ) { + hBitStream->BitsInCache -= numberOfBits; + } + else { + FDKsyncCache(hBitStream) ; + FDK_pushForward(&hBitStream->hBitBuf,numberOfBits,hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushBiDirectional (HANDLE_FDK_BITSTREAM hBitStream, const INT numberOfBits) +{ + if(numberOfBits>=0) FDKpushFor(hBitStream, numberOfBits) ; + else FDKpushBack(hBitStream, -numberOfBits) ; +} + + +/** + * \brief GetValidBits Function. Clear cache and return valid Bits from Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of valid bits that still can be read or were already written. + * + */ +FDK_INLINE UINT FDKgetValidBits (HANDLE_FDK_BITSTREAM hBitStream) +{ + FDKsyncCache(hBitStream) ; + return FDK_getValidBits(&hBitStream->hBitBuf) ; +} + + +/** + * \brief return amount of unused Bits from Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of free bits that still can be written into the bitstream + */ +FDK_INLINE INT FDKgetFreeBits (HANDLE_FDK_BITSTREAM hBitStream) +{ + return FDK_getFreeBits (&hBitStream->hBitBuf) ; +} + +/** + * \brief reset bitcounter in bitBuffer to zero. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKresetBitCnt (HANDLE_FDK_BITSTREAM hBitStream) +{ + FDKsyncCache (hBitStream) ; + FDK_setBitCnt (&hBitStream->hBitBuf, 0) ; +} + +/** + * \brief set bitcoutner in bitBuffer to given value. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value new value to be assigned to the bit counter + * \return void + */ +FDK_INLINE void FDKsetBitCnt (HANDLE_FDK_BITSTREAM hBitStream, UINT value) +{ + FDKsyncCache (hBitStream) ; + FDK_setBitCnt (&hBitStream->hBitBuf, value) ; +} + +/** + * \brief get bitcounter state from bitBuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return current bit counter value + */ +FDK_INLINE INT FDKgetBitCnt (HANDLE_FDK_BITSTREAM hBitStream) +{ + FDKsyncCache(hBitStream) ; + return FDK_getBitCnt(&hBitStream->hBitBuf) ; +} + + +/** + * \brief Fill the BitBuffer with a number of input bytes from external source. + * The bytesValid variable returns the number of ramaining valid bytes in extern inputBuffer. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param inputBuffer Pointer to input buffer with bitstream data. + * \param bufferSize Total size of inputBuffer array. + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: bytes still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKfeedBuffer (HANDLE_FDK_BITSTREAM hBitStream, const UCHAR inputBuffer [], const UINT bufferSize, UINT *bytesValid) +{ + FDKsyncCache (hBitStream) ; + FDK_Feed(&hBitStream->hBitBuf, (UCHAR*)inputBuffer, bufferSize, bytesValid ) ; +} + + +/** + * \brief fill destination BitBuffer with a number of bytes from source BitBuffer. The + * bytesValid variable returns the number of ramaining valid bytes in source BitBuffer. + * + * \param hBSDst HANDLE_FDK_BITSTREAM handle to write data into + * \param hBSSrc HANDLE_FDK_BITSTREAM handle to read data from + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: bytes still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKcopyBuffer (HANDLE_FDK_BITSTREAM hBSDst, HANDLE_FDK_BITSTREAM hBSSrc, UINT *bytesValid) +{ + FDKsyncCache (hBSSrc) ; + FDK_Copy (&hBSDst->hBitBuf, &hBSSrc->hBitBuf, bytesValid) ; +} + + +/** + * \brief fill the outputBuffer with all valid bytes hold in BitBuffer. The WriteBytes + * variable returns the number of written Bytes. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param outputBuffer Pointer to output buffer. + * \param writeBytes Number of bytes write to output buffer. + * \return void + */ +FDK_INLINE void FDKfetchBuffer(HANDLE_FDK_BITSTREAM hBitStream, UCHAR *outputBuffer, UINT *writeBytes) +{ + FDKsyncCache (hBitStream) ; + FDK_Fetch(&hBitStream->hBitBuf, outputBuffer, writeBytes); +} + + +#endif diff --git a/libFDK/include/FDK_core.h b/libFDK/include/FDK_core.h new file mode 100644 index 00000000..10a6a8e1 --- /dev/null +++ b/libFDK/include/FDK_core.h @@ -0,0 +1,109 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Manuel Jander + Description: FDK tools versioning support + +******************************************************************************/ + +#ifndef FDK_CORE_H +#define FDK_CORE_H + +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Get FDK_tools library information. + * @return Return 0 on success and a negative errorcode on failure (see errorcodes.h). + */ +int FDK_toolsGetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libFDK/include/FDK_crc.h b/libFDK/include/FDK_crc.h new file mode 100644 index 00000000..b1fed886 --- /dev/null +++ b/libFDK/include/FDK_crc.h @@ -0,0 +1,231 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: + contents/description: CRC calculation + +******************************************************************************/ + +#ifndef FDK_CRC_H +#define FDK_CRC_H + + + +#include "FDK_bitstream.h" + + +#define MAX_CRC_REGS 3 /*!< Maximal number of overlapping crc region in ADTS channel pair element is two. + Select three independent regions preventively. */ + +/** + * This structure describes single crc region used for crc calculation. + */ +typedef struct +{ + UCHAR isActive; + INT maxBits; + UINT bitBufCntBits; + UINT validBits; + +} CCrcRegData; + +/** + * CRC info structure. + */ +typedef struct +{ + CCrcRegData crcRegData[MAX_CRC_REGS]; /*!< Multiple crc region description. */ + const USHORT *pCrcLookup; /*!< Pointer to lookup table filled in FDK_crcInit(). */ + + USHORT crcPoly; /*!< CRC generator polynom. */ + USHORT crcMask; /*!< CRC mask. */ + USHORT startValue; /*!< CRC start value. */ + UCHAR crcLen; /*!< CRC length. */ + + UINT regStart; /*!< Start region marker for synchronization. */ + UINT regStop; /*!< Stop region marker for synchronization. */ + + USHORT crcValue; /*!< Crc value to be calculated. */ + +} FDK_CRCINFO; + +/** + * CRC info handle. + */ +typedef FDK_CRCINFO* HANDLE_FDK_CRCINFO; + + +/** + * \brief Initialize CRC structure. + * + * The function initializes existing crc info structure with denoted configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info structure. + * \param crcPoly Configure crc polynom. + * \param crcStartValue Configure crc start value. + * \param crcLen Configure crc length. + * + * \return none + */ +void FDKcrcInit( + HANDLE_FDK_CRCINFO hCrcInfo, + const UINT crcPoly, + const UINT crcStartValue, + const UINT crcLen + ); + +/** + * \brief Reset CRC info structure. + * + * This function clears all intern states of the crc structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return none + */ +void FDKcrcReset( + HANDLE_FDK_CRCINFO hCrcInfo + ); + + +/** + * \brief Start CRC region with maximum number of bits. + * + * This function marks position in bitstream to be used as start point for crc calculation. + * Bitstream range for crc calculation can be limited or kept dynamic depending on mBits parameter. + * The crc region has to be terminated with FDKcrcEndReg() in each case. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param mBits Number of bits in crc region to be calculated. + * - mBits > 0: Zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * - mBits < 0: No zero padding is done. + * - mBits = 0: The number of bits used in crc calculation is dynamically, + * depending on bitstream position between FDKcrcStartReg() and + * FDKcrcEndReg() call. + * + * \return ID for the created region, -1 in case of an error + */ +INT FDKcrcStartReg( + HANDLE_FDK_CRCINFO hCrcInfo, + const HANDLE_FDK_BITSTREAM hBs, + const INT mBits + ); + + +/** + * \brief Ends CRC region. + * + * This function terminates crc region specified with FDKcrcStartReg(). The number of bits in crc region depends + * on mBits parameter of FDKcrcStartReg(). + * This function calculates and updates crc in info structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID created in FDKcrcStartReg(). + * + * \return 0 on success + */ +INT FDKcrcEndReg( + HANDLE_FDK_CRCINFO hCrcInfo, + const HANDLE_FDK_BITSTREAM hBs, + const INT reg + ); + + +/** + * \brief This function returns crc value from info struct. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return CRC value masked with crc length. + */ +USHORT FDKcrcGetCRC( + const HANDLE_FDK_CRCINFO hCrcInfo + ); + + +#endif /* FDK_CRC_H */ diff --git a/libFDK/include/FDK_hybrid.h b/libFDK/include/FDK_hybrid.h new file mode 100644 index 00000000..63f2d704 --- /dev/null +++ b/libFDK/include/FDK_hybrid.h @@ -0,0 +1,273 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Markus Lohwasser + Description: FDK Tools Hybrid Filterbank + +******************************************************************************/ + +#ifndef __FDK_HYBRID_H +#define __FDK_HYBRID_H + + + +#include "common_fix.h" + +/*--------------- enums -------------------------------*/ + +/** + * Hybrid Filterband modes. + */ +typedef enum { + THREE_TO_TEN, + THREE_TO_TWELVE, + THREE_TO_SIXTEEN + +} FDK_HYBRID_MODE; + + +/*--------------- structure definitions ---------------*/ +typedef struct FDK_HYBRID_SETUP *HANDLE_FDK_HYBRID_SETUP; + +typedef struct +{ + FIXP_DBL *bufferLFReal[3]; /*!< LF real filter states. */ + FIXP_DBL *bufferLFImag[3]; /*!< LF imag filter states. */ + FIXP_DBL *bufferHFReal[13]; /*!< HF real delay lines. */ + FIXP_DBL *bufferHFImag[13]; /*!< HF imag delay lines. */ + + INT bufferLFpos; /*!< Position to write incoming data into ringbuffer. */ + INT bufferHFpos; /*!< Delay line positioning. */ + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + UCHAR hfMode; /*!< Flag signalizes treatment of HF bands. */ + + FIXP_DBL *pLFmemory; /*!< Pointer to LF states buffer. */ + FIXP_DBL *pHFmemory; /*!< Pointer to HF states buffer. */ + + UINT LFmemorySize; /*!< Size of LF states buffer. */ + UINT HFmemorySize; /*!< Size of HF states buffer. */ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_ANA_HYB_FILTER; + + +typedef struct +{ + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_SYN_HYB_FILTER; + +typedef FDK_ANA_HYB_FILTER *HANDLE_FDK_ANA_HYB_FILTER; +typedef FDK_SYN_HYB_FILTER *HANDLE_FDK_SYN_HYB_FILTER; + + +/** + * \brief Create one instance of Hybrid Analyis Filterbank. + * + * \param hAnalysisHybFilter Pointer to an outlying allocated Hybrid Analysis Filterbank structure. + * \param pLFmemory Pointer to outlying buffer used LF filtering. + * \param LFmemorySize Size of pLFmemory in bytes. + * \param pHFmemory Pointer to outlying buffer used HF delay line. + * \param HFmemorySize Size of pLFmemory in bytes. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisOpen( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, + const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, + const UINT HFmemorySize + ); + + +/** + * \brief Initialize and configure Hybrdid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * \param initStatesFlag Indicates whether the states buffer has to be cleared. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisInit( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, + const INT qmfBands, + const INT cplxBands, + const INT initStatesFlag + ); + + +/** + * \brief Adjust Hybrdid Analysis Filterbank states. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param scalingValue Scaling value to be applied on filter states. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisScaleStates( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue + ); + + +/** + * \brief Apply Hybrid Analysis Filterbank on Qmf input data. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param pQmfReal Qmf input data. + * \param pQmfImag Qmf input data. + * \param pHybridReal Hybrid output data. + * \param pHybridImag Hybrid output data. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisApply( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag + ); + + +/** + * \brief Close a Hybrid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter Pointer to a Hybrid Analysis Filterbank instance. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisClose( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter + ); + +/** + * \brief Initialize and configure Hybrdid Synthesis Filterbank instance. + * + * \param hSynthesisHybFilter A Hybrid Synthesis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * + * \return 0 on success. + */ +INT FDKhybridSynthesisInit( + HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, + const INT qmfBands, + const INT cplxBands + ); + +/** + * \brief Apply Hybrid Analysis Filterbank on Hybrid data. + * + * \param hSynthesisHybFilter A Hybrid Analysis Filterbandk handle. + * \param pHybridReal Hybrid input data. + * \param pHybridImag Hybrid input data. + * \param pQmfReal Qmf output data. + * \param pQmfImag Qmf output data. + * + * \return 0 on success. + */ +INT FDKhybridSynthesisApply( + HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag + ); + + +#endif /* __FDK_HYBRID_H */ diff --git a/libFDK/include/FDK_tools_rom.h b/libFDK/include/FDK_tools_rom.h new file mode 100644 index 00000000..9361c816 --- /dev/null +++ b/libFDK/include/FDK_tools_rom.h @@ -0,0 +1,270 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Oliver Moser + Description: ROM tables used by FDK tools + +******************************************************************************/ + +#ifndef __FDK_TOOLS_ROM_H__ +#define __FDK_TOOLS_ROM_H__ + +#include "common_fix.h" +#include "FDK_audio.h" + + +/* None radix2 rotation vectors */ +extern const FIXP_STB RotVectorReal60[60]; +extern const FIXP_STB RotVectorImag60[60]; +extern const FIXP_STB RotVectorReal240[240]; +extern const FIXP_STB RotVectorImag240[240]; +extern const FIXP_STB RotVectorReal480[480]; +extern const FIXP_STB RotVectorImag480[480]; + + +/* Regular sine tables */ +extern const FIXP_STP SineTable512[]; +extern const FIXP_STP SineTable480[]; + +/* AAC-LC windows */ +extern const FIXP_WTP SineWindow1024[]; +extern const FIXP_WTP KBDWindow1024[]; +extern const FIXP_WTP SineWindow128[]; +extern const FIXP_WTP KBDWindow128[]; + +extern const FIXP_WTP SineWindow960[]; +extern const FIXP_WTP KBDWindow960[]; +extern const FIXP_WTP SineWindow120[]; +extern const FIXP_WTP KBDWindow120[]; + +/* AAC-LD windows */ +extern const FIXP_WTP SineWindow512[]; +#define LowOverlapWindow512 SineWindow128 +extern const FIXP_WTP SineWindow480[]; +#define LowOverlapWindow480 SineWindow120 + + + +extern const FIXP_WTP SineWindow64[]; +extern const FIXP_WTP SineWindow32[]; + +/** + * \brief Helper table for window slope mapping. You should prefer the usage of the + * function FDKgetWindowSlope(), this table is only made public for some optimized + * access inside dct.cpp. + */ +extern const FIXP_WTP *const windowSlopes[2][3][9]; + +/** + * \brief Window slope access helper. Obtain a window of given length and shape. + * \param length Length of the window slope. + * \param shape Shape index of the window slope. 0: sine window, 1: Kaiser-Bessel. Any other + * value is applied a mask of 1 to, mapping it to either 0 or 1. + * \param Pointer to window slope or NULL if the requested window slope is not available. + */ +const FIXP_WTP * FDKgetWindowSlope(int length, int shape); + +extern const FIXP_WTP sin_twiddle_L64[]; + +/* + * Filter coefficient type definition + */ + +#if defined(ARCH_PREFER_MULT_16x16) || defined(ARCH_PREFER_MULT_32x16) + #define QMF_COEFF_16BIT +#endif + +#define QMF_FILTER_PROTOTYPE_SIZE 640 +#define QMF_NO_POLY 5 + +#ifdef QMF_COEFF_16BIT + #define FIXP_PFT FIXP_SGL + #define FIXP_QTW FIXP_SGL +#else + #define FIXP_PFT FIXP_DBL + #define FIXP_QTW FIXP_DBL +#endif + +#define QMF640_PFT_TABLE_SIZE (640/2 + QMF_NO_POLY) + +extern const FIXP_QTW qmf_phaseshift_cos32[32]; +extern const FIXP_QTW qmf_phaseshift_sin32[32]; +/* Adapted analysis post-twiddles for down-sampled HQ SBR */ +extern const FIXP_QTW qmf_phaseshift_cos_downsamp32[32]; +extern const FIXP_QTW qmf_phaseshift_sin_downsamp32[32]; +extern const FIXP_QTW qmf_phaseshift_cos64[64]; +extern const FIXP_QTW qmf_phaseshift_sin64[64]; + +extern const FIXP_PFT qmf_64[QMF640_PFT_TABLE_SIZE+QMF_NO_POLY]; + + + + + +#define QMF640_CLDFB_PFT_TABLE_SIZE (640) +#define QMF320_CLDFB_PFT_TABLE_SIZE (320) +#define QMF_CLDFB_PFT_SCALE 1 + +extern const FIXP_QTW qmf_phaseshift_cos32_cldfb[32]; +extern const FIXP_QTW qmf_phaseshift_sin32_cldfb[32]; +extern const FIXP_QTW qmf_phaseshift_cos64_cldfb[64]; +extern const FIXP_QTW qmf_phaseshift_sin64_cldfb[64]; + +extern const FIXP_PFT qmf_cldfb_640[QMF640_CLDFB_PFT_TABLE_SIZE]; +extern const FIXP_PFT qmf_cldfb_320[QMF320_CLDFB_PFT_TABLE_SIZE]; + + + + + +/* + * Raw Data Block list stuff. + */ +typedef enum { + element_instance_tag, + common_window, + global_gain, + ics_info, /* ics_reserved_bit, window_sequence, window_shape, max_sfb, scale_factor_grouping, predictor_data_present, ltp_data_present, ltp_data */ + max_sfb, + ms, /* ms_mask_present, ms_used */ + /*predictor_data_present,*/ /* part of ics_info */ + ltp_data_present, + ltp_data, + section_data, + scale_factor_data, + pulse, /* pulse_data_present, pulse_data */ + tns_data_present, + tns_data, + gain_control_data_present, + gain_control_data, + esc1_hcr, + esc2_rvlc, + spectral_data, + + scale_factor_data_usac, + core_mode, + common_tw, + lpd_channel_stream, + tw_data, + noise, + ac_spectral_data, + fac_data, + tns_active, /* introduced in MPEG-D usac CD */ + tns_data_present_usac, + common_max_sfb, + + + /* Non data list items */ + adtscrc_start_reg1, + adtscrc_start_reg2, + adtscrc_end_reg1, + adtscrc_end_reg2, + drmcrc_start_reg, + drmcrc_end_reg, + next_channel, + next_channel_loop, + link_sequence, + end_of_sequence +} rbd_id_t; + +struct element_list { + const rbd_id_t *id; + const struct element_list *next[2]; +}; + +typedef struct element_list element_list_t; +/** + * \brief get elementary stream pieces list for given parameters. + * \param aot audio object type + * \param epConfig the epConfig value from the current Audio Specific Config + * \param nChannels amount of channels contained in the current element. + * \param layer the layer of the current element. + * \return element_list_t parser guidance structure. + */ +const element_list_t * getBitstreamElementList(AUDIO_OBJECT_TYPE aot, SCHAR epConfig, UCHAR nChannels, UCHAR layer); + + +#endif + diff --git a/libFDK/include/FDK_trigFcts.h b/libFDK/include/FDK_trigFcts.h new file mode 100644 index 00000000..c32c0f25 --- /dev/null +++ b/libFDK/include/FDK_trigFcts.h @@ -0,0 +1,229 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Haricharan Lakshman, Manuel Jander + Description: Trigonometric functions fixed point fractional implementation. + +******************************************************************************/ + + + +#include "common_fix.h" + +#include "FDK_tools_rom.h" + +/* Fixed point precision definitions */ +#define Q(format) ((FIXP_DBL)(((LONG)1) << (format))) + +#ifndef M_PI +#define M_PI (3.14159265358979323846f) +#endif + +/*! + * Inverse tangent function. + */ + +// --- fixp_atan() ---- +#define Q_ATANINP (25) // Input in q25, Output in q30 +#define Q_ATANOUT (30) +#define ATI_SF ((DFRACT_BITS-1)-Q_ATANINP) // 6 +#define ATI_SCALE ((float)(1<> shift; + + residual &= ( (1< (1< (1<<(LD-1))) { + FIXP_STP tmp; + /* Cosine/Sine simetry for angles greater than PI/4 */ + s = (1<>32; + return result ; +} + +#endif /* defined(__GNUC__) */ + +#endif /* __aarch64__ */ + diff --git a/libFDK/include/abs.h b/libFDK/include/abs.h new file mode 100644 index 00000000..0837e3c0 --- /dev/null +++ b/libFDK/include/abs.h @@ -0,0 +1,121 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: fixed point abs definitions + +******************************************************************************/ + +#if !defined(__ABS_H__) +#define __ABS_H__ + + +#if defined(__mips__) /* cppp replaced: elif */ +#include "mips/abs_mips.h" + +#elif defined(__x86__) /* cppp replaced: elif */ +#include "x86/abs_x86.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixabs_D) +inline FIXP_DBL fixabs_D(FIXP_DBL x) { return ((x) > (FIXP_DBL)(0)) ? (x) : -(x) ; } +#endif + +#if !defined(FUNCTION_fixabs_I) +inline INT fixabs_I(INT x) { return ((x) > (INT)(0)) ? (x) : -(x) ; } +#endif + +#if !defined(FUNCTION_fixabs_S) +inline FIXP_SGL fixabs_S(FIXP_SGL x) { return ((x) > (FIXP_SGL)(0)) ? (x) : -(x) ; } +#endif + +#endif /* __ABS_H__ */ diff --git a/libFDK/include/arm/clz_arm.h b/libFDK/include/arm/clz_arm.h new file mode 100644 index 00000000..f43a7b1d --- /dev/null +++ b/libFDK/include/arm/clz_arm.h @@ -0,0 +1,122 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__arm__) + +#if defined(__GNUC__) && defined(__ARM_ARCH_5TE__) /* cppp replaced: elif */ + /* ARM gcc*/ + + #define FUNCTION_fixnormz_D + #define FUNCTION_fixnorm_D + + inline INT fixnormz_D(LONG value) + { + INT result; + asm("clz %0, %1 ": "=r"(result) : "r"(value) ); + return result; + } + + inline INT fixnorm_D(LONG value) + { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; + } + +#endif /* arm toolchain */ + +#endif /* __arm__ */ + diff --git a/libFDK/include/arm/cplx_mul.h b/libFDK/include/arm/cplx_mul.h new file mode 100644 index 00000000..8b480311 --- /dev/null +++ b/libFDK/include/arm/cplx_mul.h @@ -0,0 +1,214 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__arm__) && defined(__GNUC__) /* cppp replaced: elif */ + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) + #define FUNCTION_cplxMultDiv2_32x16 + #define FUNCTION_cplxMultDiv2_32x16X2 + //#define FUNCTION_cplxMult_32x16 + //#define FUNCTION_cplxMult_32x16X2 +#endif + +#define FUNCTION_cplxMultDiv2_32x32X2 +//#define FUNCTION_cplxMult_32x32X2 + +#ifdef FUNCTION_cplxMultDiv2_32x16 +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SPK wpk ) +{ + LONG tmp1,tmp2; + const LONG w = wpk.w; + + asm("smulwt %0, %3, %4;\n" + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" + "smulwt %1, %2, %4;\n" + "smlawb %1, %3, %4, %1;\n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(w) + ); + + *c_Re = tmp1; + *c_Im = tmp2; +} +#endif /* FUNCTION_cplxMultDiv2_32x16 */ + +#ifdef FUNCTION_cplxMultDiv2_32x16X2 +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + LONG tmp1, tmp2; + + asm("smulwb %0, %3, %5;\n" /* %7 = -a_Im * b_Im */ + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" /* tmp1 = a_Re * b_Re - a_Im * b_Im */ + "smulwb %1, %2, %5;\n" /* %7 = a_Re * b_Im */ + "smlawb %1, %3, %4, %1;\n" /* tmp2 = a_Im * b_Re + a_Re * b_Im */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im) + ); + + *c_Re = tmp1; + *c_Im = tmp2; +} +#endif /* FUNCTION_cplxMultDiv2_32x16X2 */ + +#ifdef FUNCTION_cplxMultAddDiv2_32x16X2 +inline void cplxMultAddDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + LONG tmp1, tmp2; + + asm("smulwb %0, %3, %5;\n" + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" + "smulwb %1, %2, %5;\n" + "smlawb %1, %3, %4, %1;\n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im) + ); + + *c_Re += tmp1; + *c_Im += tmp2; +} +#endif /* FUNCTION_cplxMultAddDiv2_32x16X2 */ + + +#ifdef FUNCTION_cplxMultDiv2_32x32X2 +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DBL b_Re, + const FIXP_DBL b_Im) +{ + LONG tmp1, tmp2; + +#ifdef __ARM_ARCH_6__ + asm( + "smmul %0, %2, %4;\n" /* tmp1 = a_Re * b_Re */ + "smmls %0, %3, %5, %0;\n" /* tmp1 -= a_Im * b_Im */ + "smmul %1, %2, %5;\n" /* tmp2 = a_Re * b_Im */ + "smmla %1, %3, %4, %1;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im) + : "r0" + ); +#else + LONG discard; + asm( + "smull %2, %0, %7, %6;\n" /* tmp1 = -a_Im * b_Im */ + "smlal %2, %0, %3, %5;\n" /* tmp1 += a_Re * b_Re */ + "smull %2, %1, %3, %6;\n" /* tmp2 = a_Re * b_Im */ + "smlal %2, %1, %4, %5;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2), "=&r"(discard) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im), "r"(-a_Im) + ); + #endif + *c_Re = tmp1; + *c_Im = tmp2; +} +#endif /* FUNCTION_cplxMultDiv2_32x32X2 */ + + +#endif + diff --git a/libFDK/include/arm/fixmadd_arm.h b/libFDK/include/arm/fixmadd_arm.h new file mode 100644 index 00000000..111147bf --- /dev/null +++ b/libFDK/include/arm/fixmadd_arm.h @@ -0,0 +1,160 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__arm__) + + /* ############################################################################# */ + #if defined(__GNUC__) && defined(__arm__) && !defined(__SYMBIAN32__) /* cppp replaced: elif */ + /* ############################################################################# */ + /* ARM GNU GCC */ + + #define FUNCTION_fixmadddiv2_DD + + #ifdef __ARM_ARCH_6__ + inline FIXP_DBL fixmadddiv2_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm ("smmla %0, %1, %2, %3;\n" + : "=r" (result) + : "r" (a), "r" (b), "r"(x) ); + return result ; + } + #define FUNCTION_fixmsubdiv2_DD + inline FIXP_DBL fixmsubdiv2_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm ("smmls %0, %1, %2, %3;\n" + : "=r" (result) + : "r" (a), "r" (b), "r"(x) ); + return result ; + } + #else /* __ARM_ARCH_6__ */ + inline FIXP_DBL fixmadddiv2_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT discard, result = x; + asm ("smlal %0, %1, %2, %3;\n" + : "=r" (discard), "+r" (result) + : "r" (a), "r" (b) ); + return result ; + } + #endif /* __ARM_ARCH_6__ */ + + #if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) + + #define FUNCTION_fixmadddiv2_DS + + inline FIXP_DBL fixmadddiv2_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { + INT result; + asm("smlawb %0, %1, %2, %3 " + : "=r" (result) + : "r" (a), "r" (b), "r" (x) ); + return result ; + } + + #endif /* defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) */ + + #define FUNCTION_fixmadddiv2BitExact_DD + #define fixmadddiv2BitExact_DD(a, b, c) fixmadddiv2_DD(a, b, c) + + #define FUNCTION_fixmsubdiv2BitExact_DD + inline FIXP_DBL fixmsubdiv2BitExact_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return x - fixmuldiv2BitExact_DD(a, b); + } + + #define FUNCTION_fixmadddiv2BitExact_DS + #define fixmadddiv2BitExact_DS(a, b, c) fixmadddiv2_DS(a, b, c) + + #define FUNCTION_fixmsubdiv2BitExact_DS + inline FIXP_DBL fixmsubdiv2BitExact_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { + return x - fixmuldiv2BitExact_DS(a, b); + } + /* ############################################################################# */ + #endif /* toolchain */ + /* ############################################################################# */ + +#endif /* __arm__ */ + diff --git a/libFDK/include/arm/fixmul_arm.h b/libFDK/include/arm/fixmul_arm.h new file mode 100644 index 00000000..2f047055 --- /dev/null +++ b/libFDK/include/arm/fixmul_arm.h @@ -0,0 +1,142 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__arm__) + +#if defined(__GNUC__) && defined(__arm__) /* cppp replaced: elif */ +/* ARM with GNU compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + +#if defined(__ARM_ARCH_6__) || defined(__TARGET_ARCH_7E_M) +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT result ; + __asm__ ("smmul %0, %1, %2" : "=r" (result) + : "r" (a), "r" (b)) ; + return result ; +} +#else +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT discard, result ; + __asm__ ("smull %0, %1, %2, %3" : "=&r" (discard), "=r" (result) + : "r" (a), "r" (b)) ; + return result ; +} +#endif + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) +#define FUNCTION_fixmuldiv2_SD +inline INT fixmuldiv2_SD (const SHORT a, const INT b) +{ + INT result ; + __asm__ ("smulwb %0, %1, %2" + : "=r" (result) + : "r" (b), "r" (a)) ; + return result ; +} +#endif + +#endif /* defined(__GNUC__) && defined(__arm__) */ + +#endif /* __arm__ */ + diff --git a/libFDK/include/arm/scale.h b/libFDK/include/arm/scale.h new file mode 100644 index 00000000..cbb81dc0 --- /dev/null +++ b/libFDK/include/arm/scale.h @@ -0,0 +1,152 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** Fraunhofer IIS *************************** + + Author(s): + Description: ARM scaling operations + +******************************************************************************/ + +#if defined(__GNUC__) /* GCC Compiler */ /* cppp replaced: elif */ + +#if defined(__ARM_ARCH_6__) + +inline static INT shiftRightSat(INT src, int scale) +{ + INT result; + asm( + "ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src>>scale), "M"(SAMPLE_BITS) + ); + + return result; +} + + #define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) shiftRightSat(src, scale) + +inline static INT shiftLeftSat(INT src, int scale) +{ + INT result; + asm( + "ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src<= 0) + *value <<= newscale; + else + *value >>= -newscale; +} + + + #define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ( (((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS-1)))>>(scale)) > (LONG)(((1U)<<((dBits)-1))-1)) \ + ? ((LONG)(src) >> (DFRACT_BITS-1)) ^ (LONG)(((1U)<<((dBits)-1))-1) \ + : ((LONG)(src) >> (scale)) + + #define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + ( ((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS-1))) > ((LONG)(((1U)<<((dBits)-1))-1) >> (scale)) ) \ + ? ((LONG)(src) >> (DFRACT_BITS-1)) ^ (LONG)(((1U)<<((dBits)-1))-1) \ + : ((LONG)(src) << (scale)) + diff --git a/libFDK/include/arm/scramble.h b/libFDK/include/arm/scramble.h new file mode 100644 index 00000000..82d03381 --- /dev/null +++ b/libFDK/include/arm/scramble.h @@ -0,0 +1,158 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: bitreversal of input data + +******************************************************************************/ + +#if defined(FUNCTION_scramble) +#if defined(__GNUC__) /* cppp replaced: elif */ + +#define FUNCTION_scramble + +#if defined(__ARM_ARCH_5TE__) +#define USE_LDRD_STRD /* LDRD requires 8 byte data alignment. */ +#endif + +inline void scramble(FIXP_DBL x [], INT n) { + FDK_ASSERT(!(((INT)x)&(ALIGNMENT_DEFAULT-1))); + asm("mov r2, #1;\n" /* r2(m) = 1; */ + "sub r3, %1, #1;\n" /* r3 = n-1; */ + "mov r4, #0;\n" /* r4(j) = 0; */ + +"scramble_m_loop%=:\n" /* { */ + "mov r5, %1;\n" /* r5(k) = 1; */ + +"scramble_k_loop%=:\n" /* { */ + "mov r5, r5, lsr #1;\n" /* k >>= 1; */ + "eor r4, r4, r5;\n" /* j ^=k; */ + "ands r10, r4, r5;\n" /* r10 = r4 & r5; */ + "beq scramble_k_loop%=;\n" /* } while (r10 == 0); */ + + "cmp r4, r2;\n" /* if (r4 < r2) break; */ + "bcc scramble_m_loop_end%=;\n" + +#ifdef USE_LDRD_STRD + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldrd r10, [%0, r5];\n" /* r10 = x[r5], x7 = x[r5+1] */ + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldrd r8, [%0, r6];\n" /* r8 = x[r6], r9 = x[r6+1]; */ + "strd r10, [%0, r6];\n" /* x[r6,r6+1] = r10,r11; */ + "strd r8, [%0, r5];\n" /* x[r5,r5+1] = r8,r9; */ +#else + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldr r10, [%0, r5];\n" + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldr r11, [%0, r6];\n" + + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" + + "add r5, r5, #4;" + "ldr r10, [%0, r5];\n" + "add r6, r6, #4;" + "ldr r11, [%0, r6];\n" + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" +#endif +"scramble_m_loop_end%=:\n" + "add r2, r2, #1;\n" /* r2++; */ + "cmp r2, r3;\n" + "bcc scramble_m_loop%=;\n" /* } while (r2(m) < r3(n-1)); */ + : + : "r"(x), "r"(n) +#ifdef USE_LDRD_STRD + : "r2","r3", "r4","r5", "r10","r11", "r8","r9", "r6" ); +#else + : "r2","r3", "r4","r5", "r10","r11", "r6" ); +#endif +} +#else +/* Force C implementation if no assembler version available. */ +#undef FUNCTION_scramble +#endif /* Toolchain selection. */ + +#endif /* defined(FUNCTION_scramble) */ diff --git a/libFDK/include/autocorr2nd.h b/libFDK/include/autocorr2nd.h new file mode 100644 index 00000000..c2e95956 --- /dev/null +++ b/libFDK/include/autocorr2nd.h @@ -0,0 +1,128 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: fixed point abs definitions + +******************************************************************************/ + +#ifndef _AUTOCORR_2ND_H +#define _AUTOCORR_2ND_H + + + +#include "common_fix.h" + +typedef struct { + FIXP_DBL r00r; + FIXP_DBL r11r; + FIXP_DBL r22r; + FIXP_DBL r01r; + FIXP_DBL r02r; + FIXP_DBL r12r; + FIXP_DBL r01i; + FIXP_DBL r02i; + FIXP_DBL r12i; + FIXP_DBL det; + int det_scale; +} ACORR_COEFS; + +#define LPC_ORDER 2 + + +INT +autoCorr2nd_real (ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const int len /*!< Number of qmf slots */ + ); +INT +autoCorr2nd_cplx (ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of spectrum */ + const int len /*!< Number of qmf slots */ + ); + + +#endif /* _AUTOCORR_2ND_H */ diff --git a/libFDK/include/clz.h b/libFDK/include/clz.h new file mode 100644 index 00000000..3a3ead5f --- /dev/null +++ b/libFDK/include/clz.h @@ -0,0 +1,198 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Marc Gayer + Description: fixed point intrinsics + +******************************************************************************/ + +#if !defined(__CLZ_H__) +#define __CLZ_H__ + +#include "FDK_archdef.h" +#include "machine_type.h" + +#if defined(__arm__) +#include "arm/clz_arm.h" + +#elif defined(__aarch64__) || defined(__AARCH64EL__) +#include "aarch64/clz_aarch64.h" + +#elif defined(__mips__) /* cppp replaced: elif */ +#include "mips/clz_mips.h" + +#elif defined(__x86__) /* cppp replaced: elif */ +#include "x86/clz_x86.h" + +#elif defined(__powerpc__) +#include "ppc/clz_ppc.h" + +#endif /* all cores */ + + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixnormz_S) +#ifdef FUNCTION_fixnormz_D +inline INT fixnormz_S (SHORT a) +{ + return fixnormz_D((INT)(a)); +} +#else +inline INT fixnormz_S (SHORT a) +{ + int leadingBits = 0; + a = ~a; + while(a & 0x8000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnormz_D) +inline INT fixnormz_D (LONG a) +{ + INT leadingBits = 0; + a = ~a; + while(a & 0x80000000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif + + +/***************************************************************************** + + functionname: fixnorm_D + description: Count leading ones or zeros of operand val for dfract/LONG INT values. + Return this value minus 1. Return 0 if operand==0. +*****************************************************************************/ +#if !defined(FUNCTION_fixnorm_S) +#ifdef FUNCTION_fixnorm_D +inline INT fixnorm_S(FIXP_SGL val) +{ + return fixnorm_D((INT)(val)); +} +#else +inline INT fixnorm_S(FIXP_SGL val) +{ + INT leadingBits = 0; + if ( val != (FIXP_SGL)0 ) { + if ( val < (FIXP_SGL)0 ) { + val = ~val; + } + leadingBits = fixnormz_S(val) - 1; + } + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnorm_D) +inline INT fixnorm_D(FIXP_DBL val) +{ + INT leadingBits = 0; + if ( val != (FIXP_DBL)0 ) { + if ( val < (FIXP_DBL)0 ) { + val = ~val; + } + leadingBits = fixnormz_D(val) - 1; + } + return (leadingBits); +} +#endif + +#endif /* __CLZ_H__ */ diff --git a/libFDK/include/common_fix.h b/libFDK/include/common_fix.h new file mode 100644 index 00000000..d2d11f4c --- /dev/null +++ b/libFDK/include/common_fix.h @@ -0,0 +1,378 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Lohwasser, M. Gayer + Description: Flexible fixpoint library configuration + +******************************************************************************/ + +#ifndef _COMMON_FIX_H +#define _COMMON_FIX_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* ***** Start of former fix.h ****** */ + +/* Configure fractional or integer arithmetic */ + #define FIX_FRACT 0 /* Define this to "1" to use fractional arithmetic simulation in class fract instead of integer arithmetic */ + /* 1 for debug with extra runtime overflow checking. */ + +/* Define bit sizes of integer fixpoint fractional data types */ +#define FRACT_BITS 16 /* single precision */ +#define DFRACT_BITS 32 /* double precision */ +#define ACCU_BITS 40 /* double precision plus overflow */ + +/* Fixpoint equivalent type fot PCM audio time domain data. */ +#if defined(SAMPLE_BITS) +#if (SAMPLE_BITS == DFRACT_BITS) + #define FIXP_PCM FIXP_DBL + #define FX_PCM2FX_DBL(x) ((FIXP_DBL)(x)) + #define FX_DBL2FX_PCM(x) ((INT_PCM)(x)) +#elif (SAMPLE_BITS == FRACT_BITS) + #define FIXP_PCM FIXP_SGL + #define FX_PCM2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) + #define FX_DBL2FX_PCM(x) FX_DBL2FX_SGL(x) +#else + #error SAMPLE_BITS different from FRACT_BITS or DFRACT_BITS not implemented! +#endif +#endif + +/* ****** End of former fix.h ****** */ + +#define SGL_MASK ((1UL<> (DFRACT_BITS-FRACT_BITS-1)) + 1) > (((LONG)1< 0) ) ? \ + (FIXP_SGL)(SHORT)(((LONG)1<<(FRACT_BITS-1))-1):(FIXP_SGL)(SHORT)((((val) >> (DFRACT_BITS-FRACT_BITS-1)) + 1) >> 1) ) + + + +#define shouldBeUnion union /* unions are possible */ + + typedef SHORT FIXP_SGL; + typedef LONG FIXP_DBL; + +/* macros for compile-time conversion of constant float values to fixedpoint */ +#define FL2FXCONST_SPC FL2FXCONST_DBL + +#define MINVAL_DBL_CONST MINVAL_DBL +#define MINVAL_SGL_CONST MINVAL_SGL + +#define FL2FXCONST_SGL(val) \ +(FIXP_SGL)( ( (val) >= 0) ? \ +((( (double)(val) * (FRACT_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_SGL) ) ? (SHORT)(MAXVAL_SGL) : (SHORT)( (double)(val) * (double)(FRACT_FIX_SCALE) + 0.5)) : \ +((( (double)(val) * (FRACT_FIX_SCALE) - 0.5) <= (double)(MINVAL_SGL_CONST) ) ? (SHORT)(MINVAL_SGL_CONST) : (SHORT)( (double)(val) * (double)(FRACT_FIX_SCALE) - 0.5)) ) + +#define FL2FXCONST_DBL(val) \ +(FIXP_DBL)( ( (val) >= 0) ? \ +((( (double)(val) * (DFRACT_FIX_SCALE) + 0.5 ) >= (double)(MAXVAL_DBL) ) ? (LONG)(MAXVAL_DBL) : (LONG)( (double)(val) * (double)(DFRACT_FIX_SCALE) + 0.5)) : \ +((( (double)(val) * (DFRACT_FIX_SCALE) - 0.5) <= (double)(MINVAL_DBL_CONST) ) ? (LONG)(MINVAL_DBL_CONST) : (LONG)( (double)(val) * (double)(DFRACT_FIX_SCALE) - 0.5)) ) + +/* macros for runtime conversion of float values to integer fixedpoint. NO OVERFLOW CHECK!!! */ +#define FL2FX_SPC FL2FX_DBL +#define FL2FX_SGL(val) ( (val)>0.0f ? (SHORT)( (val)*(float)(FRACT_FIX_SCALE)+0.5f ) : (SHORT)( (val)*(float)(FRACT_FIX_SCALE)-0.5f ) ) +#define FL2FX_DBL(val) ( (val)>0.0f ? (LONG)( (val)*(float)(DFRACT_FIX_SCALE)+0.5f ) : (LONG)( (val)*(float)(DFRACT_FIX_SCALE)-0.5f ) ) + +/* macros for runtime conversion of fixedpoint values to other fixedpoint. NO ROUNDING!!! */ +#define FX_ACC2FX_SGL(val) ((FIXP_SGL)((val)>>(ACCU_BITS-FRACT_BITS))) +#define FX_ACC2FX_DBL(val) ((FIXP_DBL)((val)>>(ACCU_BITS-DFRACT_BITS))) +#define FX_SGL2FX_ACC(val) ((FIXP_ACC)((LONG)(val)<<(ACCU_BITS-FRACT_BITS))) +#define FX_SGL2FX_DBL(val) ((FIXP_DBL)((LONG)(val)<<(DFRACT_BITS-FRACT_BITS))) +#define FX_DBL2FX_SGL(val) ((FIXP_SGL)((val)>>(DFRACT_BITS-FRACT_BITS))) + +/* ############################################################# */ + +/* macros for runtime conversion of integer fixedpoint values to float. */ +/* This is just for temporary use and should not be required in a final version! */ + +/* #define FX_DBL2FL(val) ((float)(pow(2.,-31.)*(float)val)) */ /* version #1 */ +#define FX_DBL2FL(val) ((float)((double)(val)/(double)DFRACT_FIX_SCALE)) /* version #2 - identical to class dfract cast from dfract to float */ + +/* ############################################################# */ +#include "fixmul.h" + +FDK_INLINE LONG fMult(SHORT a, SHORT b) { return fixmul_SS(a, b); } +FDK_INLINE LONG fMult(SHORT a, LONG b) { return fixmul_SD(a, b); } +FDK_INLINE LONG fMult(LONG a, SHORT b) { return fixmul_DS(a, b); } +FDK_INLINE LONG fMult(LONG a, LONG b) { return fixmul_DD(a, b); } +FDK_INLINE LONG fPow2(LONG a) { return fixpow2_D(a); } +FDK_INLINE LONG fPow2(SHORT a) { return fixpow2_S(a); } + +FDK_INLINE INT fMultI(LONG a, SHORT b) { return ( (INT)(((1<<(FRACT_BITS-2)) + + fixmuldiv2_DD(a,((INT)b<>(FRACT_BITS-1)) ); } + +FDK_INLINE INT fMultIfloor(LONG a, INT b) { return ( (INT)((1 + + fixmuldiv2_DD(a,(b<> (FRACT_BITS-1)) ); } + +FDK_INLINE INT fMultIceil(LONG a, INT b) { return ( (INT)(((INT)0x7fff + + fixmuldiv2_DD(a,(b<> (FRACT_BITS-1)) ); } + +FDK_INLINE LONG fMultDiv2(SHORT a, SHORT b) { return fixmuldiv2_SS(a, b); } +FDK_INLINE LONG fMultDiv2(SHORT a, LONG b) { return fixmuldiv2_SD(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, SHORT b) { return fixmuldiv2_DS(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, LONG b) { return fixmuldiv2_DD(a, b); } +FDK_INLINE LONG fPow2Div2(LONG a) { return fixpow2div2_D(a); } +FDK_INLINE LONG fPow2Div2(SHORT a) { return fixpow2div2_S(a); } + +FDK_INLINE LONG fMultDiv2BitExact(LONG a, LONG b) { return fixmuldiv2BitExact_DD(a, b); } +FDK_INLINE LONG fMultDiv2BitExact(SHORT a, LONG b) { return fixmuldiv2BitExact_SD(a, b); } +FDK_INLINE LONG fMultDiv2BitExact(LONG a, SHORT b) { return fixmuldiv2BitExact_DS(a, b); } +FDK_INLINE LONG fMultBitExact(LONG a, LONG b) { return fixmulBitExact_DD(a, b); } +FDK_INLINE LONG fMultBitExact(SHORT a, LONG b) { return fixmulBitExact_SD(a, b); } +FDK_INLINE LONG fMultBitExact(LONG a, SHORT b) { return fixmulBitExact_DS(a, b); } + +/* ******************************************************************************** */ +#include "abs.h" + +FDK_INLINE FIXP_DBL fAbs(FIXP_DBL x) + { return fixabs_D(x); } +FDK_INLINE FIXP_SGL fAbs(FIXP_SGL x) + { return fixabs_S(x); } + +/* workaround for TI C6x compiler but not for TI ARM9E compiler */ +#if (!defined(__TI_COMPILER_VERSION__) || defined(__TI_TMS470_V5__)) && !defined(__LP64__) +FDK_INLINE INT fAbs(INT x) + { return fixabs_I(x); } +#endif + +/* ******************************************************************************** */ + +#include "clz.h" + +FDK_INLINE INT fNormz(FIXP_DBL x) + { return fixnormz_D(x); } +FDK_INLINE INT fNormz(FIXP_SGL x) + { return fixnormz_S(x); } +FDK_INLINE INT fNorm(FIXP_DBL x) + { return fixnorm_D(x); } +FDK_INLINE INT fNorm(FIXP_SGL x) + { return fixnorm_S(x); } + + +/* ******************************************************************************** */ +/* ******************************************************************************** */ +/* ******************************************************************************** */ + +#include "clz.h" +#define fixp_abs(x) fAbs(x) +#define fixMin(a,b) fMin(a,b) +#define fixMax(a,b) fMax(a,b) +#define CntLeadingZeros(x) fixnormz_D(x) +#define CountLeadingBits(x) fixnorm_D(x) + +#include "fixmadd.h" + +/* y = (x+0.5*a*b) */ +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmadddiv2_DD(x, a, b); } +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmadddiv2_SD(x, a, b); } +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmadddiv2_DS(x, a, b); } +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) + { return fixmadddiv2_SS(x, a, b); } + +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_DBL a) + { return fixpadddiv2_D(x, a); } +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_SGL a) + { return fixpadddiv2_S(x, a); } + + +/* y = 2*(x+0.5*a*b) = (2x+a*b) */ +FDK_INLINE FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmadd_DD(x, a, b); } +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmadd_SD(x, a, b); } +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmadd_DS(x, a, b); } +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) + { return fixmadd_SS(x, a, b); } + +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_DBL a) + { return fixpadd_D(x, a); } +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_SGL a) + { return fixpadd_S(x, a); } + + +/* y = (x-0.5*a*b) */ +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmsubdiv2_DD(x, a, b); } +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmsubdiv2_SD(x, a, b); } +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmsubdiv2_DS(x, a, b); } +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) + { return fixmsubdiv2_SS(x, a, b); } + +/* y = 2*(x-0.5*a*b) = (2*x-a*b) */ +FDK_INLINE FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmsub_DD(x, a, b); } +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmsub_SD(x, a, b); } +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmsub_DS(x, a, b); } +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) + { return fixmsub_SS(x, a, b); } + +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmadddiv2BitExact_DD(x, a, b); } +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmadddiv2BitExact_SD(x, a, b); } +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmadddiv2BitExact_DS(x, a, b); } +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) + { return fixmsubdiv2BitExact_DD(x, a, b); } +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) + { return fixmsubdiv2BitExact_SD(x, a, b); } +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) + { return fixmsubdiv2BitExact_DS(x, a, b); } + +#include "fixminmax.h" + +FDK_INLINE FIXP_DBL fMin(FIXP_DBL a, FIXP_DBL b) + { return fixmin_D(a,b); } +FDK_INLINE FIXP_DBL fMax(FIXP_DBL a, FIXP_DBL b) + { return fixmax_D(a,b); } + +FDK_INLINE FIXP_SGL fMin(FIXP_SGL a, FIXP_SGL b) + { return fixmin_S(a,b); } +FDK_INLINE FIXP_SGL fMax(FIXP_SGL a, FIXP_SGL b) + { return fixmax_S(a,b); } + +/* workaround for TI C6x compiler but not for TI ARM9E */ +#if ((!defined(__TI_COMPILER_VERSION__) || defined(__TI_TMS470_V5__)) && !defined(__LP64__)) || (FIX_FRACT == 1) +FDK_INLINE INT fMax(INT a, INT b) + { return fixmax_I(a,b); } +FDK_INLINE INT fMin(INT a, INT b) + { return fixmin_I(a,b); } +#endif + +inline UINT fMax(UINT a, UINT b) + { return fixmax_UI(a,b); } +inline UINT fMin(UINT a, UINT b) + { return fixmin_UI(a,b); } + +/* Complex data types */ +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_SGL re; + FIXP_SGL im; + } v; + /* word representation for memory move */ + LONG w; +} FIXP_SPK; + +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_DBL re; + FIXP_DBL im; + } v; + /* word representation for memory move */ + INT64 w; +} FIXP_DPK; + +#include "fixmul.h" +#include "fixmadd.h" +#include "cplx_mul.h" +#include "scale.h" +#include "fixpoint_math.h" + +#endif diff --git a/libFDK/include/cplx_mul.h b/libFDK/include/cplx_mul.h new file mode 100644 index 00000000..ce5c9f73 --- /dev/null +++ b/libFDK/include/cplx_mul.h @@ -0,0 +1,269 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#include "common_fix.h" + +#if !defined(__CPLX_Mult_H__) +#define __CPLX_Mult_H__ + +#if defined(__CC_ARM) || defined(__arm__) || defined(_M_ARM) /* cppp replaced: elif */ +#include "arm/cplx_mul.h" + +#elif defined(__GNUC__) && defined(__mips__) && __mips_isa_rev < 6 +#include "mips/cplx_mul.h" + +#endif /* #if defined all cores: bfin, arm, etc. */ + +/* ############################################################################# */ + +/* Fallback generic implementations */ + +#if !defined(FUNCTION_cplxMultDiv2_32x16X2) +#define FUNCTION_cplxMultDiv2_32x16X2 + +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + *c_Re = fMultDiv2(a_Re,b_Re) - fMultDiv2(a_Im,b_Im); + *c_Im = fMultDiv2(a_Re,b_Im) + fMultDiv2(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x16) +#define FUNCTION_cplxMultDiv2_32x16 + +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SPK w ) +{ + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultAddDiv2_32x16X2) +#define FUNCTION_cplxMultAddDiv2_32x16X2 + +inline void cplxMultAddDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + *c_Re += fMultDiv2(a_Re,b_Re) - fMultDiv2(a_Im,b_Im); + *c_Im += fMultDiv2(a_Re,b_Im) + fMultDiv2(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x16X2) +#define FUNCTION_cplxMultSubDiv2_32x16X2 + +inline void cplxMultSubDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + *c_Re -= fMultDiv2(a_Re,b_Re) - fMultDiv2(a_Im,b_Im); + *c_Im -= fMultDiv2(a_Re,b_Im) + fMultDiv2(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32X2) +#define FUNCTION_cplxMultDiv2_32x32X2 + +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DBL b_Re, + const FIXP_DBL b_Im) +{ + *c_Re = fMultDiv2(a_Re,b_Re) - fMultDiv2(a_Im,b_Im); + *c_Im = fMultDiv2(a_Re,b_Im) + fMultDiv2(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32) +#define FUNCTION_cplxMultDiv2_32x32 + +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DPK w) +{ + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x32X2) +#define FUNCTION_cplxMultSubDiv2_32x32X2 + +inline void cplxMultSubDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DBL b_Re, + const FIXP_DBL b_Im) +{ + *c_Re -= fMultDiv2(a_Re,b_Re) - fMultDiv2(a_Im,b_Im); + *c_Im -= fMultDiv2(a_Re,b_Im) + fMultDiv2(a_Im,b_Re); +} +#endif + +/* ############################################################################# */ + +#if !defined(FUNCTION_cplxMult_32x16X2) +#define FUNCTION_cplxMult_32x16X2 + +inline void cplxMult( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SGL b_Re, + const FIXP_SGL b_Im) +{ + *c_Re = fMult(a_Re,b_Re) - fMult(a_Im,b_Im); + *c_Im = fMult(a_Re,b_Im) + fMult(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x16) +#define FUNCTION_cplxMult_32x16 + +inline void cplxMult( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_SPK w ) +{ + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32X2) +#define FUNCTION_cplxMult_32x32X2 + +inline void cplxMult( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DBL b_Re, + const FIXP_DBL b_Im) +{ + *c_Re = fMult(a_Re,b_Re) - fMult(a_Im,b_Im); + *c_Im = fMult(a_Re,b_Im) + fMult(a_Im,b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32) +#define FUNCTION_cplxMult_32x32 +inline void cplxMult( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + const FIXP_DBL a_Re, + const FIXP_DBL a_Im, + const FIXP_DPK w) +{ + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +/* ############################################################################# */ + +#endif /* __CPLX_Mult_H__ */ + diff --git a/libFDK/include/dct.h b/libFDK/include/dct.h new file mode 100644 index 00000000..af1edd38 --- /dev/null +++ b/libFDK/include/dct.h @@ -0,0 +1,147 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: Library functions to calculate standard DCTs. This will most + likely be replaced by hand-optimized functions for the specific + target processor. + +******************************************************************************/ + +#ifndef __dct_H +#define __dct_H + + + +#include "common_fix.h" + +/** + * \brief Calculate DCT type II of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/(N-1)) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_II(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type III of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * Note that the factor 0.5 for the sum term x[0] is 1.0 instead of 0.5. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_III(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type IV of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_IV(FIXP_DBL *pDat,int size, int *pDat_e); + +/** + * \brief Calculate DST type IV of given length. The DST IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dst_IV(FIXP_DBL *pDat,int size, int *pDat_e); + + + +#endif diff --git a/libFDK/include/fft.h b/libFDK/include/fft.h new file mode 100644 index 00000000..49f389d5 --- /dev/null +++ b/libFDK/include/fft.h @@ -0,0 +1,253 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Josef Hoepfl, DSP Solutions + Description: Fix point FFT + +******************************************************************************/ + +#ifndef __FFT_H__ +#define __FFT_H__ + +#include "common_fix.h" + +/** + * \brief Perform an inplace complex valued FFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 bit scale headroom. + * The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the input data, + * which is updated according to the FFT scale. + */ +void fft(int length, FIXP_DBL *pInput, INT *scalefactor); + +/** + * \brief Perform an inplace complex valued IFFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 bit scale headroom. + * The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the input data, + * which is updated according to the IFFT scale. + */ +void ifft(int length, FIXP_DBL *pInput, INT *scalefactor); + + +/* + * Frequently used and fixed short length FFTs. + */ + +LNK_SECTION_CODE_L1 +static FORCEINLINE void fft_4(FIXP_DBL *x) +{ + FIXP_DBL a00, a10, a20, a30, tmp0, tmp1; + + a00 = (x[0] + x[4])>>1; /* Re A + Re B */ + a10 = (x[2] + x[6])>>1; /* Re C + Re D */ + a20 = (x[1] + x[5])>>1; /* Im A + Im B */ + a30 = (x[3] + x[7])>>1; /* Im C + Im D */ + + x[0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + + tmp0 = a00 - x[4]; /* Re A - Re B */ + tmp1 = a20 - x[5]; /* Im A - Im B */ + + x[4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a10 = a10 - x[6]; /* Re C - Re D */ + a30 = a30 - x[7]; /* Im C - Im D */ + + x[2] = tmp0 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[6] = tmp0 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[3] = tmp1 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[7] = tmp1 + a10; /* Im D' = Im A - Im B + Re C - Re D */ +} + +LNK_SECTION_CODE_L1 +static FORCEINLINE void fft_8(FIXP_DBL *x) +{ + #define W_PiFOURTH STC(0x5a82799a) + + FIXP_DBL a00, a10, a20, a30; + FIXP_DBL y[16]; + + a00 = (x[0] + x[8])>>1; + a10 = x[4] + x[12]; + a20 = (x[1] + x[9])>>1; + a30 = x[5] + x[13]; + + y[0] = a00 + (a10>>1); + y[4] = a00 - (a10>>1); + y[1] = a20 + (a30>>1); + y[5] = a20 - (a30>>1); + + a00 = a00 - x[8]; + a10 = (a10>>1) - x[12]; + a20 = a20 - x[9]; + a30 = (a30>>1) - x[13]; + + y[2] = a00 + a30; + y[6] = a00 - a30; + y[3] = a20 - a10; + y[7] = a20 + a10; + + a00 = (x[2] + x[10])>>1; + a10 = x[6] + x[14]; + a20 = (x[3] + x[11])>>1; + a30 = x[7] + x[15]; + + y[8] = a00 + (a10>>1); + y[12] = a00 - (a10>>1); + y[9] = a20 + (a30>>1); + y[13] = a20 - (a30>>1); + + a00 = a00 - x[10]; + a10 = (a10>>1) - x[14]; + a20 = a20 - x[11]; + a30 = (a30>>1) - x[15]; + + y[10] = a00 + a30; + y[14] = a00 - a30; + y[11] = a20 - a10; + y[15] = a20 + a10; + + FIXP_DBL vr, vi, ur, ui; + + ur = y[0]>>1; + ui = y[1]>>1; + vr = y[8]; + vi = y[9]; + x[0] = ur + (vr>>1); + x[1] = ui + (vi>>1); + x[8] = ur - (vr>>1); + x[9] = ui - (vi>>1); + + ur = y[4]>>1; + ui = y[5]>>1; + vi = y[12]; + vr = y[13]; + x[4] = ur + (vr>>1); + x[5] = ui - (vi>>1); + x[12] = ur - (vr>>1); + x[13] = ui + (vi>>1); + + ur = y[10]; + ui = y[11]; + vr = fMultDiv2(ui+ur,W_PiFOURTH); + vi = fMultDiv2(ui-ur,W_PiFOURTH); + ur = y[2]; + ui = y[3]; + x[2] = (ur>>1) + vr; + x[3] = (ui>>1) + vi; + x[10] = (ur>>1) - vr; + x[11] = (ui>>1) - vi; + + ur = y[14]; + ui = y[15]; + vr = fMultDiv2(ui-ur,W_PiFOURTH); + vi = fMultDiv2(ui+ur,W_PiFOURTH); + ur = y[6]; + ui = y[7]; + x[6] = (ur>>1) + vr; + x[7] = (ui>>1) - vi; + x[14] = (ur>>1) - vr; + x[15] = (ui>>1) + vi; +} + +/** + * \brief FFT of fixed length 16 + */ +inline void fft_16(FIXP_DBL *x); + +/** + * \brief FFT of fixed length 32 + */ +inline void fft_32(FIXP_DBL *x); + + +#endif diff --git a/libFDK/include/fft_rad2.h b/libFDK/include/fft_rad2.h new file mode 100644 index 00000000..90d14da5 --- /dev/null +++ b/libFDK/include/fft_rad2.h @@ -0,0 +1,134 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Lohwasser, M. Gayer + Description: + +******************************************************************************/ + +#ifndef _FFT_RAD2_H +#define _FFT_RAD2_H + + +#include "common_fix.h" + +/** + * \brief Performe an inplace complex valued FFT of 2^n length + * + * \param x Input/Output data buffer. The input data must have at least 1 bit scale headroom. + * The values are interleaved, real/imag pairs. + * \param ldn log2 of FFT length + * \param trigdata Pointer to a sinetable of a length of at least (2^ldn)/2 sine values. + * \param trigDataSize length of the sinetable "trigdata". + */ +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, const INT trigDataSize) ; + +/** + * \brief Performe an inplace complex valued inverse FFT of 2^n length + * + * \param x Input/Output data buffer. The input data must have at least 1 bit scale headroom. + * The values are interleaved, real/imag pairs. + * \param ldn log2 of FFT length + * \param trigdata Pointer to a sinetable of a length of at least (2^ldn)/2 sine values. + * \param trigDataSize length of the sinetable "trigdata". + */ +void dit_ifft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, const INT trigDataSize) ; + +/* Rest of the world. */ + +#define SCALEFACTOR2048 10 +#define SCALEFACTOR1024 9 +#define SCALEFACTOR512 8 +#define SCALEFACTOR256 7 +#define SCALEFACTOR128 6 +#define SCALEFACTOR64 5 +#define SCALEFACTOR32 4 +#define SCALEFACTOR16 3 +#define SCALEFACTOR8 2 +#define SCALEFACTOR4 1 +#define SCALEFACTOR2 1 + +#endif /* _FFT_RAD2_H */ + diff --git a/libFDK/include/fixmadd.h b/libFDK/include/fixmadd.h new file mode 100644 index 00000000..851b7a27 --- /dev/null +++ b/libFDK/include/fixmadd.h @@ -0,0 +1,306 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Lohwasser, M. Gayer + Description: fixed point intrinsics + +******************************************************************************/ + +#if !defined(__FIXMADD_H__) +#define __FIXMADD_H__ + +#include "FDK_archdef.h" +#include "machine_type.h" +#include "fixmul.h" + +#if defined(__arm__) +#include "arm/fixmadd_arm.h" + +#elif defined(__mips__) /* cppp replaced: elif */ +#include "mips/fixmadd_mips.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +/* Divide by two versions. */ + +#if !defined(FUNCTION_fixmadddiv2_DD) +inline FIXP_DBL fixmadddiv2_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) + { return (x + fMultDiv2 (a, b)); } +#endif + +#if !defined(FUNCTION_fixmadddiv2_SD) +inline FIXP_DBL fixmadddiv2_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2_DS + return fixmadddiv2_DS(x, b, a); +#else + return fixmadddiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_DS) +inline FIXP_DBL fixmadddiv2_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2_SD + return fixmadddiv2_SD(x, b, a); +#else + return fixmadddiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_SS) +inline FIXP_DBL fixmadddiv2_SS (FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) + { return x + fMultDiv2(a,b); } +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DD) +inline FIXP_DBL fixmsubdiv2_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) + { return (x - fMultDiv2 (a, b)); } +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SD) +inline FIXP_DBL fixmsubdiv2_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2_DS + return fixmsubdiv2_DS(x, b, a); +#else + return fixmsubdiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DS) +inline FIXP_DBL fixmsubdiv2_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2_SD + return fixmsubdiv2_SD(x, b, a); +#else + return fixmsubdiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SS) +inline FIXP_DBL fixmsubdiv2_SS (FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) + { return x - fMultDiv2(a,b); } +#endif + + +#if !defined(FUNCTION_fixmadddiv2BitExact_DD) +#define FUNCTION_fixmadddiv2BitExact_DD +inline FIXP_DBL fixmadddiv2BitExact_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return x + fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_SD) +#define FUNCTION_fixmadddiv2BitExact_SD +inline FIXP_DBL fixmadddiv2BitExact_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_DS + return fixmadddiv2BitExact_DS(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_DS) +#define FUNCTION_fixmadddiv2BitExact_DS +inline FIXP_DBL fixmadddiv2BitExact_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_SD + return fixmadddiv2BitExact_SD(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2BitExact_DD) +#define FUNCTION_fixmsubdiv2BitExact_DD +inline FIXP_DBL fixmsubdiv2BitExact_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return x - fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_SD) +#define FUNCTION_fixmsubdiv2BitExact_SD +inline FIXP_DBL fixmsubdiv2BitExact_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_DS + return fixmsubdiv2BitExact_DS(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_DS) +#define FUNCTION_fixmsubdiv2BitExact_DS +inline FIXP_DBL fixmsubdiv2BitExact_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_SD + return fixmsubdiv2BitExact_SD(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif + +/* Normal versions */ + +#if !defined(FUNCTION_fixmadd_DD) +inline FIXP_DBL fixmadd_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) + { return fixmadddiv2_DD(x,a,b)<<1; } +#endif +#if !defined(FUNCTION_fixmadd_SD) +inline FIXP_DBL fixmadd_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadd_DS + return fixmadd_DS(x, b, a); +#else + return fixmadd_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_DS) +inline FIXP_DBL fixmadd_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadd_SD + return fixmadd_SD(x, b, a); +#else + return fixmadd_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_SS) +inline FIXP_DBL fixmadd_SS (FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) + { return (x + fMultDiv2(a,b))<<1; } +#endif + +#if !defined(FUNCTION_fixmsub_DD) +inline FIXP_DBL fixmsub_DD (FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) + { return fixmsubdiv2_DD(x,a,b)<<1; } +#endif +#if !defined(FUNCTION_fixmsub_SD) +inline FIXP_DBL fixmsub_SD (FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsub_DS + return fixmsub_DS(x, b, a); +#else + return fixmsub_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_DS) +inline FIXP_DBL fixmsub_DS (FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsub_SD + return fixmsub_SD(x, b, a); +#else + return fixmsub_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_SS) +inline FIXP_DBL fixmsub_SS (FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) + { return (x - fMultDiv2(a,b))<<1; } +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_D) +inline INT fixpadddiv2_D (FIXP_DBL x, const FIXP_DBL a) + { return (x + fPow2Div2(a)); } +#endif +#if !defined(FUNCTION_fixpow2add_D) +inline INT fixpadd_D (FIXP_DBL x, const FIXP_DBL a) + { return (x + fPow2(a)); } +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_S) +inline INT fixpadddiv2_S (FIXP_DBL x, const FIXP_SGL a) + { return (x + fPow2Div2(a)); } +#endif +#if !defined(FUNCTION_fixpow2add_S) +inline INT fixpadd_S (FIXP_DBL x, const FIXP_SGL a) + { return (x + fPow2(a)); } +#endif + + + +#endif // __FIXMADD_H__ + diff --git a/libFDK/include/fixminmax.h b/libFDK/include/fixminmax.h new file mode 100644 index 00000000..5a528246 --- /dev/null +++ b/libFDK/include/fixminmax.h @@ -0,0 +1,120 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Lohwasser, M. Gayer + Description: min/max inline functions and defines + +******************************************************************************/ + +#ifndef FIXMINMAX__H +#define FIXMINMAX__H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* Inline Function to determine the smaller/bigger value of two values with same type. */ + + +template inline T fixmin (T a, T b) +{ + return (a < b ? a : b); +} + +template inline T fixmax (T a, T b) +{ + return (a > b ? a : b); +} + +#define fixmax_D(a,b) fixmax(a,b) +#define fixmin_D(a,b) fixmin(a,b) +#define fixmax_S(a,b) fixmax(a,b) +#define fixmin_S(a,b) fixmin(a,b) +#define fixmax_I(a,b) fixmax(a,b) +#define fixmin_I(a,b) fixmin(a,b) +#define fixmax_UI(a,b) fixmax(a,b) +#define fixmin_UI(a,b) fixmin(a,b) + + +#endif diff --git a/libFDK/include/fixmul.h b/libFDK/include/fixmul.h new file mode 100644 index 00000000..ab978c9a --- /dev/null +++ b/libFDK/include/fixmul.h @@ -0,0 +1,292 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Stefan Gewinner + Description: fixed point multiplication + +******************************************************************************/ + +#if !defined(__FIXMUL_H__) +#define __FIXMUL_H__ + +#include "FDK_archdef.h" +#include "machine_type.h" + + +#if defined(__arm__) +#include "arm/fixmul_arm.h" + +#elif defined(__aarch64__) || defined(__AARCH64EL__) +#include "aarch64/fixmul_aarch64.h" + +#elif defined(__mips__) /* cppp replaced: elif */ +#include "mips/fixmul_mips.h" + +#elif defined(__x86__) /* cppp replaced: elif */ +#include "x86/fixmul_x86.h" + +#elif defined(__powerpc__) +#include "ppc/fixmul_ppc.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixmuldiv2_DD) +#define FUNCTION_fixmuldiv2_DD +#if defined(_MSC_VER) || defined(__CC_ARM) || defined(__ANALOG_EXTENSIONS__) || defined(__TI_COMPILER_VERSION__) +#pragma message ("Extremely slow implementation of fixmuldiv2_DD !!") +#else +#warning Extremely slow implementation of fixmuldiv2_DD !! +#endif +inline LONG fixmuldiv2_DD (const LONG a, const LONG b) +{ + return (LONG) ((((INT64)a) * b) >> 32) ; +} +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DD) +#define FUNCTION_fixmuldiv2BitExact_DD +#if defined(_MSC_VER) || defined(__CC_ARM) || defined(__ANALOG_EXTENSIONS__) || defined(__TI_COMPILER_VERSION__) +#pragma message ("Extremely slow implementation of fixmuldiv2BitExact_DD !!") +#else +#warning Extremely slow implementation of fixmuldiv2BitExact_DD !! +#endif +inline LONG fixmuldiv2BitExact_DD (const LONG a, const LONG b) +{ + return (LONG) ((((INT64)a) * b) >> 32) ; +} +#endif + +#if !defined(FUNCTION_fixmul_DD) +#define FUNCTION_fixmul_DD +inline LONG fixmul_DD (const LONG a, const LONG b) + { return fixmuldiv2_DD (a, b) << 1 ; } +#endif + +#if !defined(FUNCTION_fixmulBitExact_DD) +#define FUNCTION_fixmulBitExact_DD +#if defined(_MSC_VER) || defined(__CC_ARM) || defined(__ANALOG_EXTENSIONS__) || defined(__TI_COMPILER_VERSION__) || defined(__XTENSA__) +#pragma message ("Extremely slow implementation of fixmulBitExact_DD !!") +#else +#warning Extremely slow implementation of fixmulBitExact_DD !! +#endif +inline LONG fixmulBitExact_DD (const LONG a, const LONG b) +{ + return ( (LONG) ((((INT64)a) * b) >> 32) ) << 1; +} +#endif + +#if !defined(FUNCTION_fixmuldiv2_SS) +#define FUNCTION_fixmuldiv2_SS +inline LONG fixmuldiv2_SS (const SHORT a, const SHORT b) + { return ((LONG)a*b); } +#endif + +#if !defined(FUNCTION_fixmul_SS) +#define FUNCTION_fixmul_SS +inline LONG fixmul_SS (const SHORT a, const SHORT b) + { return (a*b) <<1; } +#endif + +#if !defined(FUNCTION_fixmuldiv2_SD) +#define FUNCTION_fixmuldiv2_SD +inline LONG fixmuldiv2_SD (const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2_DS + { return fixmuldiv2_DS(b, a); } +#else + { return fixmuldiv2_DD(FX_SGL2FX_DBL(a), b); } +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2_DS) +#define FUNCTION_fixmuldiv2_DS +inline LONG fixmuldiv2_DS (const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2_SD + { return fixmuldiv2_SD(b, a); } +#else + { return fixmuldiv2_DD(a, FX_SGL2FX_DBL(b)); } +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_SD) +#define FUNCTION_fixmuldiv2BitExact_SD +inline LONG fixmuldiv2BitExact_SD (const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2BitExact_DS + { return fixmuldiv2BitExact_DS(b, a); } +#else + { return (LONG) ((((INT64)a) * b) >> 16) ; } +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DS) +#define FUNCTION_fixmuldiv2BitExact_DS +inline LONG fixmuldiv2BitExact_DS (const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2BitExact_SD + { return fixmuldiv2BitExact_SD(b, a); } +#else + { return (LONG) ((((INT64)a) * b) >> 16) ; } +#endif +#endif + +#if !defined(FUNCTION_fixmul_SD) +#define FUNCTION_fixmul_SD +inline LONG fixmul_SD (const SHORT a, const LONG b) { +#ifdef FUNCTION_fixmul_DS + return fixmul_SD(b, a); +#else + return fixmuldiv2_SD (a, b) << 1 ; +#endif +} +#endif + +#if !defined(FUNCTION_fixmul_DS) +#define FUNCTION_fixmul_DS +inline LONG fixmul_DS (const LONG a, const SHORT b) { +#ifdef FUNCTION_fixmul_SD + return fixmul_SD(b, a); +#else + return fixmuldiv2_DS(a, b) << 1 ; +#endif +} +#endif + +#if !defined(FUNCTION_fixmulBitExact_SD) +#define FUNCTION_fixmulBitExact_SD +inline LONG fixmulBitExact_SD (const SHORT a, const LONG b) +#ifdef FUNCTION_fixmulBitExact_DS + { return fixmulBitExact_DS(b, a); } +#else + { return (LONG) (((((INT64)a) * b) >> 16) << 1); } +#endif +#endif + +#if !defined(FUNCTION_fixmulBitExact_DS) +#define FUNCTION_fixmulBitExact_DS +inline LONG fixmulBitExact_DS (const LONG a, const SHORT b) +#ifdef FUNCTION_fixmulBitExact_SD + { return fixmulBitExact_SD(b, a); } +#else + { return (LONG) (((((INT64)a) * b) >> 16) << 1); } +#endif +#endif + + +#if !defined(FUNCTION_fixpow2div2_D) +#ifdef ARCH_WA_16BITMULT +#error Fallback for fixpow2div2_D is not 16 bit safe ! +#endif +#define FUNCTION_fixpow2div2_D +inline LONG fixpow2div2_D (const LONG a) + { return fixmuldiv2_DD(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_D) +#ifdef ARCH_WA_16BITMULT +#error Fallback for fixpow2_D is not 16 bit safe ! +#endif +#define FUNCTION_fixpow2_D +inline LONG fixpow2_D (const LONG a) + { return fixpow2div2_D(a)<<1; } +#endif + +#if !defined(FUNCTION_fixpow2div2_S) +#define FUNCTION_fixpow2div2_S +inline LONG fixpow2div2_S (const SHORT a) + { return fixmuldiv2_SS(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_S) +#define FUNCTION_fixpow2_S +inline LONG fixpow2_S (const SHORT a) + { return fixpow2div2_S(a)<<1; } +#endif + + +#endif /* __FIXMUL_H__ */ diff --git a/libFDK/include/fixpoint_math.h b/libFDK/include/fixpoint_math.h new file mode 100644 index 00000000..0d50f0aa --- /dev/null +++ b/libFDK/include/fixpoint_math.h @@ -0,0 +1,495 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Gayer + Description: Fixed point specific mathematical functions + +******************************************************************************/ + +#ifndef __fixpoint_math_H +#define __fixpoint_math_H + + +#include "common_fix.h" + +#if !defined(FUNCTION_fIsLessThan) +/** + * \brief Compares two fixpoint values incl. scaling. + * \param a_m mantissa of the first input value. + * \param a_e exponent of the first input value. + * \param b_m mantissa of the second input value. + * \param b_e exponent of the second input value. + * \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise + */ +FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) +{ + if (a_e > b_e) { + return (b_m >> fMin(a_e-b_e, DFRACT_BITS-1) > a_m); + } else { + return (a_m >> fMin(b_e-a_e, DFRACT_BITS-1) < b_m); + } +} + +FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) +{ + if (a_e > b_e) { + return (b_m >> fMin(a_e-b_e, FRACT_BITS-1) > a_m); + } else { + return (a_m >> fMin(b_e-a_e, FRACT_BITS-1) < b_m); + } +} +#endif + + + +#define LD_DATA_SCALING (64.0f) +#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */ + +/** + * \brief deprecated. Use fLog2() instead. + */ +FIXP_DBL CalcLdData(FIXP_DBL op); + +void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT number); + +FIXP_DBL CalcInvLdData(FIXP_DBL op); + + +void InitLdInt(); +FIXP_DBL CalcLdInt(INT i); + +extern const USHORT sqrt_tab[49]; + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x) +{ + UINT y = (INT)x; + UCHAR is_zero=(y==0); + INT zeros=fixnormz_D(y) & 0x1e; + y<<=zeros; + UINT idx=(y>>26)-16; + USHORT frac=(y>>10)&0xffff; + USHORT nfrac=0xffff^frac; + UINT t=nfrac*sqrt_tab[idx]+frac*sqrt_tab[idx+1]; + t=t>>(zeros>>1); + return(is_zero ? 0 : t); +} + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e) +{ + UINT y = (INT)x; + INT e; + + if (x == (FIXP_DBL)0) { + return x; + } + + /* Normalize */ + e=fixnormz_D(y); + y<<=e; + e = *x_e - e + 2; + + /* Correct odd exponent. */ + if (e & 1) { + y >>= 1; + e ++; + } + /* Get square root */ + UINT idx=(y>>26)-16; + USHORT frac=(y>>10)&0xffff; + USHORT nfrac=0xffff^frac; + UINT t=nfrac*sqrt_tab[idx]+frac*sqrt_tab[idx+1]; + + /* Write back exponent */ + *x_e = e >> 1; + return (FIXP_DBL)(LONG)(t>>1); +} + + + +FIXP_DBL sqrtFixp(FIXP_DBL op); + +void InitInvSqrtTab(); + +FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift); + +/***************************************************************************** + + functionname: invFixp + description: delivers 1/(op) + +*****************************************************************************/ +inline FIXP_DBL invFixp(FIXP_DBL op) +{ + INT tmp_exp ; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp) ; + FDK_ASSERT((31-(2*tmp_exp+1))>=0) ; + return ( fPow2Div2( (FIXP_DBL)tmp_inv ) >> (31-(2*tmp_exp+1)) ) ; +} + + + +#if defined(__mips__) && (__GNUC__==2) + +#define FUNCTION_schur_div +inline FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count) +{ + INT result, tmp ; + __asm__ ("srl %1, %2, 15\n" + "div %3, %1\n" : "=lo" (result) + : "%d" (tmp), "d" (denum) , "d" (num) + : "hi" ) ; + return result<<16 ; +} + +/*###########################################################################################*/ +#elif defined(__mips__) && (__GNUC__==3) + +#define FUNCTION_schur_div +inline FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count) +{ + INT result, tmp; + + __asm__ ("srl %[tmp], %[denum], 15\n" + "div %[result], %[num], %[tmp]\n" + : [tmp] "+r" (tmp), [result]"=r"(result) + : [denum]"r"(denum), [num]"r"(num) + : "hi", "lo"); + return result << (DFRACT_BITS-16); +} + +/*###########################################################################################*/ +#elif defined(SIMULATE_MIPS_DIV) + +#define FUNCTION_schur_div +inline FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) +{ + FDK_ASSERT (count<=DFRACT_BITS-1); + FDK_ASSERT (num>=(FIXP_DBL)0); + FDK_ASSERT (denum>(FIXP_DBL)0); + FDK_ASSERT (num <= denum); + + INT tmp = denum >> (count-1); + INT result = 0; + + while (num > tmp) + { + num -= tmp; + result++; + } + + return result << (DFRACT_BITS-count); +} + +/*###########################################################################################*/ +#endif /* target architecture selector */ + +#if !defined(FUNCTION_schur_div) +/** + * \brief Divide two FIXP_DBL values with given precision. + * \param num dividend + * \param denum divisor + * \param count amount of significant bits of the result (starting to the MSB) + * \return num/divisor + */ +FIXP_DBL schur_div(FIXP_DBL num,FIXP_DBL denum, INT count); +#endif + + + +FIXP_DBL mul_dbl_sgl_rnd (const FIXP_DBL op1, + const FIXP_SGL op2); + +/** + * \brief multiply two values with normalization, thus max precision. + * Author: Robert Weidner + * + * \param f1 first factor + * \param f2 secod factor + * \param result_e pointer to an INT where the exponent of the result is stored into + * \return mantissa of the product f1*f2 + */ +FIXP_DBL fMultNorm( + FIXP_DBL f1, + FIXP_DBL f2, + INT *result_e + ); + +inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2) +{ + FIXP_DBL m; + INT e; + + m = fMultNorm(f1, f2, &e); + + m = scaleValueSaturate(m, e); + + return m; +} + +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denomintator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom, INT *result_e); + +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denomintator + * \param result_e pointer to an INT where the exponent of the result is stored into + * \return num/denum with exponent = *result_e + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom); + +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denomintator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNormHighPrec(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e); + +/** + * \brief Calculate log(argument)/log(2) (logarithm with base 2). deprecated. Use fLog2() instead. + * \param arg mantissa of the argument + * \param arg_e exponent of the argument + * \param result_e pointer to an INT to store the exponent of the result + * \return the mantissa of the result. + * \param + */ +FIXP_DBL CalcLog2(FIXP_DBL arg, INT arg_e, INT *result_e); + +/** + * \brief return 2 ^ (exp * 2^exp_e) + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be stored into + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e); + +/** + * \brief return 2 ^ (exp_m * 2^exp_e). This version returns only the mantissa with implicit exponent of zero. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e); + +/** + * \brief return x ^ (exp * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). This saves + * the need to compute log2() of constant values (when x is a constant). + * \param ldx_m mantissa of log2() of x. + * \param ldx_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be stored into + * \return mantissa of the result + */ +FIXP_DBL fLdPow( + FIXP_DBL baseLd_m, + INT baseLd_e, + FIXP_DBL exp_m, INT exp_e, + INT *result_e + ); + +/** + * \brief return x ^ (exp * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). This saves + * the need to compute log2() of constant values (when x is a constant). This version + * does not return an exponent, which is implicitly 0. + * \param ldx_m mantissa of log2() of x. + * \param ldx_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL fLdPow( + FIXP_DBL baseLd_m, INT baseLd_e, + FIXP_DBL exp_m, INT exp_e + ); + +/** + * \brief return (base * 2^base_e) ^ (exp * 2^exp_e). Use fLdPow() instead whenever possible. + * \param base_m mantissa of the base. + * \param base_e exponent of the base. + * \param exp_m mantissa of power to be calculated of the base. + * \param exp_e exponent of power to be calculated of the base. + * \param result_e pointer to a INT where the exponent of the result will be stored into. + * \return mantissa of the result. + */ +FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, INT *result_e); + +/** + * \brief return (base * 2^base_e) ^ N + * \param base mantissa of the base + * \param base_e exponent of the base + * \param power to be calculated of the base + * \param result_e pointer to a INT where the exponent of the result will be stored into + * \return mantissa of the result + */ +FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT N, INT *result_e); + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \param pointer to an INT where the exponent of the result is returned into. + * \return mantissa of the result. + */ +FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e); + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \return mantissa of the result with implicit exponent of LD_DATA_SHIFT. + */ +FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e); + +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b) +{ + LONG sum; + + sum = (LONG)(SHORT)a + (LONG)(SHORT)b; + sum = fMax(fMin((INT)sum, (INT)MAXVAL_SGL), (INT)MINVAL_SGL); + return (FIXP_SGL)(SHORT)sum; +} + +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) +{ + LONG sum; + + sum = (LONG)(a>>1) + (LONG)(b>>1); + sum = fMax(fMin((INT)sum, (INT)(MAXVAL_DBL>>1)), (INT)(MINVAL_DBL>>1)); + return (FIXP_DBL)(LONG)(sum<<1); +} + +//#define TEST_ROUNDING + + + + +/***************************************************************************** + + array for 1/n, n=1..80 + +****************************************************************************/ + + extern const FIXP_DBL invCount[80]; + + LNK_SECTION_INITCODE + inline void InitInvInt(void) {} + + +/** + * \brief Calculate the value of 1/i where i is a integer value. It supports + * input values from 1 upto 80. + * \param intValue Integer input value. + * \param FIXP_DBL representation of 1/intValue + */ +inline FIXP_DBL GetInvInt(int intValue) +{ + FDK_ASSERT((intValue > 0) && (intValue < 80)); + FDK_ASSERT(intValue<80); + return invCount[intValue]; +} + + +#endif + diff --git a/libFDK/include/mdct.h b/libFDK/include/mdct.h new file mode 100644 index 00000000..e1c2d743 --- /dev/null +++ b/libFDK/include/mdct.h @@ -0,0 +1,243 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Manuel Jander, Josef Hoepfl + Description: MDCT routines + +******************************************************************************/ + +#ifndef __MDCT_H__ +#define __MDCT_H__ + + + +#include "common_fix.h" + +#define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ +#define MDCT_OUTPUT_SCALE (DFRACT_BITS-SAMPLE_BITS-MDCT_OUT_HEADROOM) +/* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */ +#define MDCT_OUTPUT_GAIN 16 + +#if (SAMPLE_BITS == DFRACT_BITS) +#define IMDCT_SCALE(x) (INT_PCM)SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, SAMPLE_BITS) +#else +#define IMDCT_SCALE(x) (INT_PCM)SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, SAMPLE_BITS) +#endif +#define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x) + +/** + * \brief MDCT persistent data + */ +typedef struct { + union { + FIXP_DBL *freq; + FIXP_DBL *time; + } overlap; /**< Pointer to overlap memory */ + + const FIXP_WTP *prev_wrs; /**< pointer to previous right window slope */ + int prev_tl; /**< previous tranform length */ + int prev_nr; /**< previous right window offset */ + int prev_fr; /**< previous right window slope length */ + int ov_offset; /**< overlap time data fill level */ + int ov_size; /**< Overlap buffer size in words */ + +} mdct_t; + +typedef mdct_t* H_MDCT; + +/** + * \brief Initialize as valid MDCT handle + * + * \param hMdct handle of an allocated MDCT handle. + * \param overlap pointer to FIXP_DBL overlap buffer. + * \param overlapBufferSize size in FIXP_DBLs of the given overlap buffer. + * \return void + */ +void mdct_init( H_MDCT hMdct, + FIXP_DBL *overlap, + INT overlapBufferSize ); + +/** + * \brief perform MDCT transform (time domain to frequency domain) with given parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param spectrum pointer to where the resulting MDCT spectrum will be stored into. + * \param scalefactor pointer to the input scale shift value. Updated accordingly on return. + * \param input pointer to input time domain signal + * \param tl transformation length. + * \param nr right window slope offset (amount of window coefficients assumed to be 1.0) + * \param fr right overlap window slope length + * \param wrs pointer to the right side overlap window coefficients. + * \return number of input samples processed. + */ +INT mdct_block( + H_MDCT hMdct, + FIXP_DBL *spectrum, + INT *scalefactor, + INT_PCM *input, + INT tl, + INT nr, + INT fr, + const FIXP_WTB *wrs ); + + +/** + * \brief add/multiply 2/N transform gain and MPEG4 part 3 defined output gain (see definition + * of MDCT_OUTPUT_GAIN) to given mantissa factor and exponent. + * \param pGain pointer to the mantissa of a gain factor to be applied to IMDCT data. + * \param pExponent pointer to the exponent of a gain factor to be applied to IMDCT data. + * \param tl length of the IMDCT where the gain *pGain * (2 ^ *pExponent) will be applied to. + */ +void imdct_gain( + FIXP_DBL *pGain, + int *pExponent, + int tl + ); + +/** + * \brief drain buffered output samples into given buffer. Changes the MDCT state. + */ +INT imdct_drain( + H_MDCT hMdct, + FIXP_DBL * pTimeData, + INT nrSamplesRoom + ); + + +/** + * \brief Copy overlap time domain data to given buffer. Does not change the MDCT state. + * \return number of actually copied samples (ov + nr). + */ +INT imdct_copy_ov_and_nr( + H_MDCT hMdct, + FIXP_DBL * pTimeData, + INT nrSamples + ); + +/** + * \brief Adapt MDCT parameters for non-matching window slopes. + * \param hMdct handle of an allocated MDCT handle. + * \param pfl pointer to left overlap window side length. + * \param pnl pointer to length of the left n part of the window. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param noOutSamples desired number of output samples. + */ +void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl, const FIXP_WTP *wls, int noOutSamples); + +/** + * \brief perform several inverse MDCT transforms (frequency domain to time domain) with given parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param output pointer to where the output time domain signal will be stored into. + * \param stride the stride factor for accessing time domain samples in output. + * \param spectrum pointer to the input MDCT spectra. + * \param scalefactors scale shift values of the input spectrum. + * \param nSpec number of MDCT spectrums. + * \param noOutSamples desired number of output samples. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param fl left overlap window side length. + * \param wrs pointer to the right side overlap window coefficients of all individual IMDCTs. + * \param fr right overlap window side length of all individual IMDCTs. + * \param gain factor to apply to output samples (if != 0). + * \return number of output samples returned. + */ +INT imdct_block( + H_MDCT hMdct, + FIXP_DBL *output, + FIXP_DBL *spectrum, + const SHORT scalefactor[], + const INT nSpec, + const INT noOutSamples, + const INT tl, + const FIXP_WTP *wls, + INT fl, + const FIXP_WTP *wrs, + const INT fr, + FIXP_DBL gain ); + + +#endif /* __MDCT_H__ */ diff --git a/libFDK/include/mips/abs_mips.h b/libFDK/include/mips/abs_mips.h new file mode 100644 index 00000000..3b9f8767 --- /dev/null +++ b/libFDK/include/mips/abs_mips.h @@ -0,0 +1,107 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__mips__) + +#if defined(__GNUC__) && defined(__mips__) + + #if defined(__mips_dsp) + #define FUNCTION_fixabs_D + #define FUNCTION_fixabs_I + #define FUNCTION_fixabs_S + inline FIXP_DBL fixabs_D(FIXP_DBL x) { return __builtin_mips_absq_s_w(x); } + inline FIXP_SGL fixabs_S(FIXP_SGL x) { return ((x) > (FIXP_SGL)(0)) ? (x) : -(x) ; } + inline INT fixabs_I(INT x) { return __builtin_mips_absq_s_w(x); } + #endif /* __mips_dsp */ + +#endif /* defined(__GNUC__) && defined(__mips__) */ + +#endif /*__mips__ */ + diff --git a/libFDK/include/mips/clz_mips.h b/libFDK/include/mips/clz_mips.h new file mode 100644 index 00000000..ff40a09a --- /dev/null +++ b/libFDK/include/mips/clz_mips.h @@ -0,0 +1,118 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__mips__) + +#if defined(__mips__) && (__GNUC__==2) && (mips>=32) + + #define FUNCTION_fixnormz_D + inline INT fixnormz_D(LONG value) + { + INT result; + __asm__ ("clz %0,%1" : "=d" (result) : "d" (value)); + + return result; + } + +#elif defined(__mips__) && (__GNUC__==3) && (__mips>=32) + + #define FUNCTION_fixnormz_D + INT inline fixnormz_D(LONG value) + { + INT result; + __asm__ ("clz %[result], %[value]" : [result] "=r" (result) : [value] "r" (value)) ; + + return result; + } + +#endif + +#endif /* __mips__ */ + diff --git a/libFDK/include/mips/cplx_mul.h b/libFDK/include/mips/cplx_mul.h new file mode 100644 index 00000000..e921d210 --- /dev/null +++ b/libFDK/include/mips/cplx_mul.h @@ -0,0 +1,129 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + + +#if defined(__GNUC__) && defined(__mips__) + + +//#define FUNCTION_cplxMultDiv2_32x16 +//#define FUNCTION_cplxMultDiv2_32x16X2 +#define FUNCTION_cplxMultDiv2_32x32X2 +//#define FUNCTION_cplxMult_32x16 +//#define FUNCTION_cplxMult_32x16X2 +#define FUNCTION_cplxMult_32x32X2 + +#if defined(FUNCTION_cplxMultDiv2_32x32X2) +inline void cplxMultDiv2( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + FIXP_DBL a_Re, + FIXP_DBL a_Im, + FIXP_DBL b_Re, + FIXP_DBL b_Im) +{ + *c_Re = (((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32; + *c_Im = (((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32; +} +#endif + +#if defined(FUNCTION_cplxMult_32x32X2) +inline void cplxMult( FIXP_DBL *c_Re, + FIXP_DBL *c_Im, + FIXP_DBL a_Re, + FIXP_DBL a_Im, + FIXP_DBL b_Re, + FIXP_DBL b_Im) +{ + *c_Re = ((((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32)<<1; + *c_Im = ((((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32)<<1; +} +#endif + +#endif /* defined(__GNUC__) && defined(__mips__) */ + diff --git a/libFDK/include/mips/fixmadd_mips.h b/libFDK/include/mips/fixmadd_mips.h new file mode 100644 index 00000000..a9575fb9 --- /dev/null +++ b/libFDK/include/mips/fixmadd_mips.h @@ -0,0 +1,95 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__mips__) + + +#endif /* __mips__ */ + diff --git a/libFDK/include/mips/fixmul_mips.h b/libFDK/include/mips/fixmul_mips.h new file mode 100644 index 00000000..73693e2c --- /dev/null +++ b/libFDK/include/mips/fixmul_mips.h @@ -0,0 +1,113 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__mips__) + +#if (__GNUC__) && defined(__mips__) /* cppp replaced: elif */ +/* MIPS GCC based compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) + +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT result ; + result = ((long long)a * b)>>32; + return result ; +} + +#endif /* (__GNUC__) && defined(__mips__) */ + +#endif /* __mips__ */ + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD fixmul_DD diff --git a/libFDK/include/mips/scale.h b/libFDK/include/mips/scale.h new file mode 100644 index 00000000..edf29da0 --- /dev/null +++ b/libFDK/include/mips/scale.h @@ -0,0 +1,110 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: + +******************************************************************************/ + +#ifndef MIPS_SCALE_H +#define MIPS_SCALE_H + +#if defined(__mips_dsp) + +/*! +* +* \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} +* \return scaled and saturated value +* +* This macro scales src value right or left and applies saturation to (2^dBits)-1 +* maxima output. +*/ +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + (__builtin_mips_shll_s_w((src)>>scale,(DFRACT_BITS-(dBits)))>>(DFRACT_BITS-(dBits))) + + +#endif /*__mips_dsp */ + +#endif /* MIPS_SCALE_H */ diff --git a/libFDK/include/mips/scramble.h b/libFDK/include/mips/scramble.h new file mode 100644 index 00000000..3f2fe6e6 --- /dev/null +++ b/libFDK/include/mips/scramble.h @@ -0,0 +1,121 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: + +******************************************************************************/ + +#ifndef MIPS_SCRAMBLE_H +#define MIPS_SCRAMBLE_H + +#define FUNCTION_scramble + +#if defined(FUNCTION_scramble) +inline void scramble(FIXP_DBL *x, INT n) { + INT m,j; + int ldn=1; + do {ldn++;} while((1<> (16-ldn); + + if (j>m) + { + FIXP_DBL tmp; + tmp=x[2*m]; + x[2*m]=x[2*j]; + x[2*j]=tmp; + + tmp=x[2*m+1]; + x[2*m+1]=x[2*j+1]; + x[2*j+1]=tmp; + } + } +} +#endif + +#endif /* MIPS_SCRAMBLE_H */ diff --git a/libFDK/include/ppc/clz_ppc.h b/libFDK/include/ppc/clz_ppc.h new file mode 100644 index 00000000..bfd23c66 --- /dev/null +++ b/libFDK/include/ppc/clz_ppc.h @@ -0,0 +1,102 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixnormz_D + +inline INT fixnormz_D(LONG value) +{ + INT result; + __asm__ ("cntlzw %0, %1" : "=r" (result) : "r" (value)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/libFDK/include/ppc/fixmul_ppc.h b/libFDK/include/ppc/fixmul_ppc.h new file mode 100644 index 00000000..9e2745cc --- /dev/null +++ b/libFDK/include/ppc/fixmul_ppc.h @@ -0,0 +1,115 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + + +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT result; + __asm__ ("mulhw %0, %1, %2" : "=r" (result) : "r" (a), "r" (b)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/libFDK/include/qmf.h b/libFDK/include/qmf.h new file mode 100644 index 00000000..be694772 --- /dev/null +++ b/libFDK/include/qmf.h @@ -0,0 +1,248 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file qmf.h + \brief Complex qmf analysis/synthesis + \author Markus Werner + +*/ +#ifndef __QMF_H +#define __QMF_H + + + +#include "common_fix.h" +#include "FDK_tools_rom.h" +#include "dct.h" + +/* + * Filter coefficient type definition + */ +#ifdef QMF_DATA_16BIT +#define FIXP_QMF FIXP_SGL +#define FX_DBL2FX_QMF FX_DBL2FX_SGL +#define FX_QMF2FX_DBL FX_SGL2FX_DBL +#define QFRACT_BITS FRACT_BITS +#else +#define FIXP_QMF FIXP_DBL +#define FX_DBL2FX_QMF +#define FX_QMF2FX_DBL +#define QFRACT_BITS DFRACT_BITS +#endif + +/* ARM neon optimized QMF analysis filter requires 32 bit input. + Implemented for RVCT only, currently disabled. See src/arm/qmf_arm.cpp:45 */ +#define FIXP_QAS FIXP_PCM +#define QAS_BITS SAMPLE_BITS + +#ifdef QMFSYN_STATES_16BIT +#define FIXP_QSS FIXP_SGL +#define QSS_BITS FRACT_BITS +#else +#define FIXP_QSS FIXP_DBL +#define QSS_BITS DFRACT_BITS +#endif + +/* Flags for QMF intialization */ +/* Low Power mode flag */ +#define QMF_FLAG_LP 1 +/* Filter is not symetric. This flag is set internally in the QMF initialization as required. */ +#define QMF_FLAG_NONSYMMETRIC 2 +/* Complex Low Delay Filter Bank (or std symmetric filter bank) */ +#define QMF_FLAG_CLDFB 4 +/* Flag indicating that the states should be kept. */ +#define QMF_FLAG_KEEP_STATES 8 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder */ +#define QMF_FLAG_MPSLDFB 16 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder allows a optimized calculation of the modulation in qmfForwardModulationHQ() */ +#define QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION 32 +/* Flag to indicate HE-AAC down-sampled SBR mode (decoder) -> adapt analysis post twiddling */ +#define QMF_FLAG_DOWNSAMPLED 64 + + +typedef struct +{ + int lb_scale; /*!< Scale of low band area */ + int ov_lb_scale; /*!< Scale of adjusted overlap low band area */ + int hb_scale; /*!< Scale of high band area */ + int ov_hb_scale; /*!< Scale of adjusted overlap high band area */ +} QMF_SCALE_FACTOR; + +struct QMF_FILTER_BANK +{ + const FIXP_PFT *p_filter; /*!< Pointer to filter coefficients */ + + void *FilterStates; /*!< Pointer to buffer of filter states + FIXP_PCM in analyse and + FIXP_DBL in synthesis filter */ + int FilterSize; /*!< Size of prototype filter. */ + const FIXP_QTW *t_cos; /*!< Modulation tables. */ + const FIXP_QTW *t_sin; + int filterScale; /*!< filter scale */ + + int no_channels; /*!< Total number of channels (subbands) */ + int no_col; /*!< Number of time slots */ + int lsb; /*!< Top of low subbands */ + int usb; /*!< Top of high subbands */ + + int outScalefactor; /*!< Scale factor of output data (syn only) */ + FIXP_DBL outGain; /*!< Gain output data (syn only) (init with 0x80000000 to ignore) */ + + UINT flags; /*!< flags */ + UCHAR p_stride; /*!< Stride Factor of polyphase filters */ + +}; + +typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK; + +void +qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_QMF **qmfReal, /*!< Pointer to real subband slots */ + FIXP_QMF **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const INT_PCM *timeIn, /*!< Time signal */ + const int stride, /*!< Stride factor of audio data */ + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +void +qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_QMF **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_QMF **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + INT_PCM *timeOut, /*!< Time signal */ + const int stride, /*!< Stride factor of audio data */ + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +int +qmfInitAnalysisFilterBank( HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ + +void +qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_QMF *qmfReal, /*!< Low and High band, real */ + FIXP_QMF *qmfImag, /*!< Low and High band, imag */ + const INT_PCM *timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +int +qmfInitSynthesisFilterBank( HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QSS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ + +void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_QMF *realSlot, + const FIXP_QMF *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, + INT_PCM *timeOut, + const int stride, + FIXP_QMF *pWorkBuffer); + +void +qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ + ); + +void +qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain /*!< New gain for output data */ + ); + + + +#endif /* __QMF_H */ diff --git a/libFDK/include/scale.h b/libFDK/include/scale.h new file mode 100644 index 00000000..1587f9f5 --- /dev/null +++ b/libFDK/include/scale.h @@ -0,0 +1,250 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: Scaling operations + +******************************************************************************/ + +#ifndef SCALE_H +#define SCALE_H + +#include "common_fix.h" +#include "genericStds.h" +#include "fixminmax.h" + + #define SCALE_INLINE inline + + +#if defined(__arm__) /* cppp replaced: elif */ +#include "arm/scale.h" + +#elif defined(__mips__) /* cppp replaced: elif */ +#include "mips/scale.h" + +#endif + + +#include "../src/scale.cpp" + +#ifndef FUNCTION_scaleValue +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * + * \return Scaled input + * + */ +#define FUNCTION_scaleValue +inline +FIXP_DBL scaleValue(const FIXP_DBL value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ + ) +{ + if(scalefactor > 0) + return (value<>(-scalefactor)); +} +#endif + +#ifndef FUNCTION_scaleValueSaturate +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * \param value The value to be scaled. + * \param the shift amount + * \return \f$ value * 2^scalefactor \f$ + * + */ +#define FUNCTION_scaleValueSaturate +inline +FIXP_DBL scaleValueSaturate( + const FIXP_DBL value, + INT scalefactor + ) +{ + if(scalefactor > 0) { + if (fNorm(value) < scalefactor && value != (FIXP_DBL)0) { + if (value > (FIXP_DBL)0) { + return (FIXP_DBL)MAXVAL_DBL; + } else { + return (FIXP_DBL)MINVAL_DBL; + } + } else { + return (value< scalefactor) { + return (FIXP_DBL)0; + } else { + return (value>>(-scalefactor)); + } + } +} +#endif + +#ifndef FUNCTION_scaleValueInPlace +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ in place + * + * \return void + * + */ +#define FUNCTION_scaleValueInPlace +inline +void scaleValueInPlace( + FIXP_DBL *value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ + ) +{ + INT newscale; + /* Note: The assignment inside the if conditional allows combining a load with the compare to zero (on ARM and maybe others) */ + if ((newscale = (scalefactor)) >= 0) { + *(value) <<= newscale; + } else { + *(value) >>= -newscale; + } +} +#endif + +/*! + * + * \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} + * \return scaled and saturated value + * + * This macro scales src value right or left and applies saturation to (2^dBits)-1 + * maxima output. + */ + +#ifndef SATURATE_RIGHT_SHIFT + #define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ( (((LONG)(src)>>(scale)) > (LONG)(((1U)<<((dBits)-1))-1)) ? (LONG)(((1U)<<((dBits)-1))-1) \ + : (((LONG)(src)>>(scale)) < ~((LONG)(((1U)<<((dBits)-1))-1))) ? ~((LONG)(((1U)<<((dBits)-1))-1)) \ + : ((LONG)(src) >> (scale)) ) +#endif + +#ifndef SATURATE_LEFT_SHIFT + #define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + ( ((LONG)(src) > ((LONG)(((1U)<<((dBits)-1))-1)>>(scale))) ? (LONG)(((1U)<<((dBits)-1))-1) \ + : ((LONG)(src) < ~((LONG)(((1U)<<((dBits)-1))-1)>>(scale))) ? ~((LONG)(((1U)<<((dBits)-1))-1)) \ + : ((LONG)(src) << (scale)) ) +#endif + +#ifndef SATURATE_SHIFT +#define SATURATE_SHIFT(src, scale, dBits) \ + ( ((scale) < 0) \ + ? SATURATE_LEFT_SHIFT((src), -(scale), (dBits)) \ + : SATURATE_RIGHT_SHIFT((src), (scale), (dBits)) ) +#endif + +/* + * Alternative shift and saturate left, saturates to -0.99999 instead of -1.0000 + * to avoid problems when inverting the sign of the result. + */ +#ifndef SATURATE_LEFT_SHIFT_ALT +#define SATURATE_LEFT_SHIFT_ALT(src, scale, dBits) \ + ( ((LONG)(src) > ((LONG)(((1U)<<((dBits)-1))-1)>>(scale))) ? (LONG)(((1U)<<((dBits)-1))-1) \ + : ((LONG)(src) < ~((LONG)(((1U)<<((dBits)-1))-2)>>(scale))) ? ~((LONG)(((1U)<<((dBits)-1))-2)) \ + : ((LONG)(src) << (scale)) ) +#endif + +#ifndef SATURATE_RIGHT_SHIFT_ALT + #define SATURATE_RIGHT_SHIFT_ALT(src, scale, dBits) \ + ( (((LONG)(src)>>(scale)) > (LONG)(((1U)<<((dBits)-1))-1)) ? (LONG)(((1U)<<((dBits)-1))-1) \ + : (((LONG)(src)>>(scale)) < ~((LONG)(((1U)<<((dBits)-1))-2))) ? ~((LONG)(((1U)<<((dBits)-1))-2)) \ + : ((LONG)(src) >> (scale)) ) +#endif + +#ifndef SATURATE_INT_PCM_RIGHT_SHIFT +#define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) SATURATE_RIGHT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#ifndef SATURATE_INT_PCM_LEFT_SHIFT +#define SATURATE_INT_PCM_LEFT_SHIFT(src, scale) SATURATE_LEFT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#endif /* #ifndef SCALE_H */ diff --git a/libFDK/include/scramble.h b/libFDK/include/scramble.h new file mode 100644 index 00000000..ceaf527d --- /dev/null +++ b/libFDK/include/scramble.h @@ -0,0 +1,165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: + +******************************************************************************/ + +#ifndef SCRAMBLE_H +#define SCRAMBLE_H + +#include "common_fix.h" + +#if defined(__arm__) +#include "arm/scramble.h" + +#elif defined(__mips__) && defined(__mips_dsp) /* cppp replaced: elif */ +#include "mips/scramble.h" + +#endif + +/***************************************************************************** + + functionname: scramble + description: bitreversal of input data + returns: + input: + output: + +*****************************************************************************/ +#if !defined(FUNCTION_scramble_sgl) + +inline void scramble_sgl(FIXP_SGL *x, INT n) +{ + INT m,k,j; + + for (m=1,j=0; m>1; (!((j^=k)&k)); k>>=1);} + + if (j>m) + { + FIXP_SGL tmp; + tmp=x[2*m]; + x[2*m]=x[2*j]; + x[2*j]=tmp; + + tmp=x[2*m+1]; + x[2*m+1]=x[2*j+1]; + x[2*j+1]=tmp; + } + } +} +#endif + +#if !defined(FUNCTION_scramble) + +/* default scramble functionality */ +inline void scramble(FIXP_DBL *x, INT n) +{ + INT m,k,j; + FDK_ASSERT(!(((UINT64)x)&(ALIGNMENT_DEFAULT-1))); + + for (m=1,j=0; m>1; (!((j^=k)&k)); k>>=1);} + + if (j>m) + { + FIXP_DBL tmp; + tmp=x[2*m]; + x[2*m]=x[2*j]; + x[2*j]=tmp; + + tmp=x[2*m+1]; + x[2*m+1]=x[2*j+1]; + x[2*j+1]=tmp; + } + } +} +#endif /* !defined(FUNCTION_scramble) */ + +#endif /* SCRAMBLE_H */ diff --git a/libFDK/include/x86/abs_x86.h b/libFDK/include/x86/abs_x86.h new file mode 100644 index 00000000..96374ec5 --- /dev/null +++ b/libFDK/include/x86/abs_x86.h @@ -0,0 +1,106 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ +#if defined(__x86__) + + #if defined(__x86_64__) + + inline INT fixabs_D(INT x) { return ((x) > (INT)(0)) ? (x) : -(x) ; } + inline INT fixabs_S(INT x) { return ((x) > (INT)(0)) ? (x) : -(x) ; } + + #define fixabs_I(x) fixabs_D(x) + + #define FUNCTION_fixabs_S + #define FUNCTION_fixabs_D + #define FUNCTION_fixabs_I + + #endif /* __x86_64__ */ + +#endif /*__x86__ */ + diff --git a/libFDK/include/x86/clz_x86.h b/libFDK/include/x86/clz_x86.h new file mode 100644 index 00000000..1bc43e51 --- /dev/null +++ b/libFDK/include/x86/clz_x86.h @@ -0,0 +1,154 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__GNUC__) && (defined(__x86__) || defined(__x86_64__)) + + #define FUNCTION_fixnormz_D + #define FUNCTION_fixnorm_D + + inline INT fixnormz_D(LONG value) + { + INT result; + + if (value != 0) { + result = __builtin_clz(value); + } else { + result = 32; + } + return result; + } + + inline INT fixnorm_D(LONG value) + { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; + } + + +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + +#include + + #define FUNCTION_fixnormz_D + #define FUNCTION_fixnorm_D + + inline INT fixnormz_D(LONG value) + { + unsigned long result = 0; + unsigned char err; + err = _BitScanReverse(&result, value); + if (err) { + return 31 - result; + } else { + return 32; + } + } + + inline INT fixnorm_D(LONG value) + { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; + } + +#endif /* toolchain */ diff --git a/libFDK/include/x86/fixmul_x86.h b/libFDK/include/x86/fixmul_x86.h new file mode 100644 index 00000000..7b74cc73 --- /dev/null +++ b/libFDK/include/x86/fixmul_x86.h @@ -0,0 +1,178 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__x86__) + +#if defined(_MSC_VER) && defined(_M_IX86) +/* Intel x86 */ + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + +inline INT fixmul_DD (INT a, const INT b) +{ + __asm + { + mov eax, a + imul b + shl edx, 1 + mov a, edx + } + return a ; +} + + +inline INT fixmuldiv2_DD (INT a, const INT b) +{ + __asm + { + mov eax, a + imul b + mov a, edx + } + return a ; +} + +/* ############################################################################# */ +#elif (defined(__GNUC__)||defined(__gnu_linux__)) && defined(__x86__) + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + +inline INT fixmul_DD (INT a, const INT b) +{ + INT result; + + asm( "imul %2;\n" + "shl $1, %0;\n" + : "=d"(result), "+a"(a) + : "r"(b) ); + + return result; +} + + +inline INT fixmuldiv2_DD (INT a, const INT b) +{ + INT result; + + asm ( "imul %2;" + : "=d"(result), "+a"(a) + : "r"(b) ); + + return result; +} + +#endif /* (defined(__GNUC__)||defined(__gnu_linux__)) && defined(__x86__) */ + +#endif /* __x86__ */ + diff --git a/libFDK/src/FDK_bitbuffer.cpp b/libFDK/src/FDK_bitbuffer.cpp new file mode 100644 index 00000000..9076d846 --- /dev/null +++ b/libFDK/src/FDK_bitbuffer.cpp @@ -0,0 +1,480 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: common bitbuffer read/write routines + +******************************************************************************/ + +#include "FDK_bitbuffer.h" + + + + +#include "genericStds.h" +#include "common_fix.h" +#include "fixminmax.h" + +const UINT BitMask [32+1] = +{ + 0x0, 0x1, 0x3, 0x7, + 0xf, 0x1f, 0x3f, 0x7f, + 0xff, 0x1ff, 0x3ff, 0x7ff, + 0xfff, 0x1fff, 0x3fff, 0x7fff, + 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, + 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, + 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, + 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +const UINT *const RESTRICT pBitMask = BitMask; + +void FDK_CreateBitBuffer (HANDLE_FDK_BITBUF *hBitBuf, UCHAR *pBuffer, + UINT bufSize) +{ + FDK_InitBitBuffer (*hBitBuf, pBuffer, bufSize, 0); + + FDKmemclear((*hBitBuf)->Buffer, bufSize*sizeof(UCHAR)); +} + +void FDK_DeleteBitBuffer (HANDLE_FDK_BITBUF hBitBuf) { ; } + +void FDK_InitBitBuffer (HANDLE_FDK_BITBUF hBitBuf, UCHAR *pBuffer, + UINT bufSize, UINT validBits) +{ + hBitBuf->ValidBits = validBits ; + hBitBuf->ReadOffset = 0 ; + hBitBuf->WriteOffset = 0 ; + hBitBuf->BitCnt = 0 ; + hBitBuf->BitNdx = 0 ; + + hBitBuf->Buffer = pBuffer ; + hBitBuf->bufSize = bufSize ; + hBitBuf->bufBits = (bufSize << 3) ; +#if defined(FDK_DEBUG) || defined(DEBUG) + /*assure bufsize (2^n) */ + if (bufSize!=0) { + UINT x = 0, n=bufSize; + for (x=0; n>0; x++,n>>=1) {} + if ( bufSize != (1<<(x-1)) ) { + FDKprintfErr("Error: bufSizein FDK_InitBitBuffer() != (2^n), %d\n", bufSize); + } + } +#endif +} + +void FDK_ResetBitBuffer ( HANDLE_FDK_BITBUF hBitBuf ) +{ + hBitBuf->ValidBits = 0 ; + hBitBuf->ReadOffset = 0 ; + hBitBuf->WriteOffset = 0 ; + hBitBuf->BitCnt = 0 ; + hBitBuf->BitNdx = 0 ; +} + +INT FDK_get (HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) +{ + if (numberOfBits == 0 || numberOfBits > hBitBuf->ValidBits) return 0; + + UINT byteOffset = hBitBuf->BitNdx >> 3 ; + UINT bitOffset = hBitBuf->BitNdx & 0x07 ; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1) ; + hBitBuf->BitCnt += numberOfBits ; + hBitBuf->ValidBits -= numberOfBits ; + + UINT byteMask = hBitBuf->bufSize - 1 ; + + UINT tx = hBitBuf->Buffer [ byteOffset & byteMask] << 24 << bitOffset; + + if (numberOfBits + bitOffset > 8) tx |= hBitBuf->Buffer [(byteOffset+1) & byteMask] << 16 << bitOffset; + if (numberOfBits + bitOffset > 16) tx |= hBitBuf->Buffer [(byteOffset+2) & byteMask] << 8 << bitOffset; + if (numberOfBits + bitOffset > 24) tx |= hBitBuf->Buffer [(byteOffset+3) & byteMask] << bitOffset; + if (numberOfBits + bitOffset > 32) tx |= hBitBuf->Buffer [(byteOffset+4) & byteMask] >> (8 - bitOffset); + + return (tx >> (32 - numberOfBits)) ; +} + +INT FDK_get32 (HANDLE_FDK_BITBUF hBitBuf) +{ + if (hBitBuf->ValidBits < 32) return 0; + + UINT BitNdx = hBitBuf->BitNdx + 32; + if (BitNdx <= hBitBuf->bufBits) + { + hBitBuf->BitNdx = BitNdx; + hBitBuf->BitCnt += 32; + hBitBuf->ValidBits -= 32; + + UINT byteOffset = (BitNdx-1) >> 3; + UINT cache = (hBitBuf->Buffer[(byteOffset-3)] << 24) | + (hBitBuf->Buffer[(byteOffset-2)] << 16) | + (hBitBuf->Buffer[(byteOffset-1)] << 8) | + hBitBuf->Buffer[(byteOffset-0)]; + + if ( (BitNdx = (BitNdx&7)) != 0 ) { + cache = (cache >> (8-BitNdx)) | ((UINT)hBitBuf->Buffer [byteOffset-4] << (24+BitNdx)); + } + return (cache) ; + } + else + { + /* exotic path, used only at the end of the buffer, when wrapping around */ + int nBits = (INT)hBitBuf->bufBits-(INT)hBitBuf->BitNdx; + + UINT cache = FDK_get (hBitBuf,nBits)<< (32-nBits); + cache |= (FDK_get (hBitBuf,32-nBits)); + return (cache); + } +} + +INT FDK_getBwd (HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) +{ + UINT byteOffset = hBitBuf->BitNdx >> 3 ; + UINT bitOffset = hBitBuf->BitNdx & 0x07 ; + UINT byteMask = hBitBuf->bufSize - 1 ; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1) ; + hBitBuf->BitCnt -= numberOfBits ; + hBitBuf->ValidBits += numberOfBits ; + + UINT tx = hBitBuf->Buffer [(byteOffset-3) & byteMask] << 24 | + hBitBuf->Buffer [(byteOffset-2) & byteMask] << 16 | + hBitBuf->Buffer [(byteOffset-1) & byteMask] << 8 | + hBitBuf->Buffer [ byteOffset & byteMask] ; + UINT txa = 0x0; + + tx >>= (8 - bitOffset) ; + + if (bitOffset && numberOfBits > 24) + { + tx |= hBitBuf->Buffer [(byteOffset-4) & byteMask] << (24 + bitOffset) ; + } + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + txa |= (tx & bitMaskR) << (31 - (i<<1)); + txa |= (tx & bitMaskL) >> (31 - (i<<1)); + } + + return (txa >> (32 - numberOfBits)) ; +} + +void FDK_put (HANDLE_FDK_BITBUF hBitBuf, UINT value, const UINT numberOfBits) +{ + UINT byteOffset = hBitBuf->BitNdx >> 3 ; + UINT bitOffset = hBitBuf->BitNdx & 0x07 ; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1) ; + hBitBuf->BitCnt += numberOfBits ; + hBitBuf->ValidBits += numberOfBits ; + + UINT byteMask = hBitBuf->bufSize - 1 ; + + UINT tmp = value<<(32-numberOfBits)>>bitOffset; + UINT mask = ~BitMask[(32-bitOffset)] | (BitMask [(32-numberOfBits)] >> bitOffset) ; + + hBitBuf->Buffer [ byteOffset & byteMask] = (hBitBuf->Buffer [ byteOffset & byteMask]&(mask>>24)) | (UCHAR)(tmp>>24); + hBitBuf->Buffer [(byteOffset+1) & byteMask] = (hBitBuf->Buffer [(byteOffset+1) & byteMask]&(mask>>16)) | (UCHAR)(tmp>>16); + hBitBuf->Buffer [(byteOffset+2) & byteMask] = (hBitBuf->Buffer [(byteOffset+2) & byteMask]&(mask>>8)) | (UCHAR)(tmp>>8); + hBitBuf->Buffer [(byteOffset+3) & byteMask] = (hBitBuf->Buffer [(byteOffset+3) & byteMask]&(mask)) | (UCHAR)(tmp); + + if (bitOffset && numberOfBits > 24) + { + hBitBuf->Buffer [(byteOffset+4) & byteMask] = (UCHAR)(value<<(40-numberOfBits)>>bitOffset) | + ( hBitBuf->Buffer [(byteOffset+4) & byteMask] & BitMask[(40-numberOfBits-bitOffset)] ) ; + } +} + +void FDK_putBwd (HANDLE_FDK_BITBUF hBitBuf, UINT value, const UINT numberOfBits) +{ + UINT byteOffset = hBitBuf->BitNdx >> 3 ; + UINT bitOffset = 7 - (hBitBuf->BitNdx & 0x07) ; + UINT byteMask = hBitBuf->bufSize - 1 ; + + UINT mask = ~(BitMask[numberOfBits] << bitOffset) ; + UINT tmp = 0x0000; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1) ; + hBitBuf->BitCnt -= numberOfBits ; + hBitBuf->ValidBits -= numberOfBits ; + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + tmp |= (value & bitMaskR) << (31 - (i<<1)); + tmp |= (value & bitMaskL) >> (31 - (i<<1)); + } + value = tmp; + tmp = value>>(32-numberOfBits)<Buffer [ byteOffset & byteMask] = (hBitBuf->Buffer [ byteOffset & byteMask]&(mask)) | (UCHAR)(tmp); + hBitBuf->Buffer [(byteOffset-1) & byteMask] = (hBitBuf->Buffer [(byteOffset-1) & byteMask]&(mask>>8)) | (UCHAR)(tmp>>8); + hBitBuf->Buffer [(byteOffset-2) & byteMask] = (hBitBuf->Buffer [(byteOffset-2) & byteMask]&(mask>>16)) | (UCHAR)(tmp>>16); + hBitBuf->Buffer [(byteOffset-3) & byteMask] = (hBitBuf->Buffer [(byteOffset-3) & byteMask]&(mask>>24)) | (UCHAR)(tmp>>24); + + if ((bitOffset + numberOfBits) > 32) + { + hBitBuf->Buffer [(byteOffset-4) & byteMask] = (UCHAR)(value>>(64-numberOfBits-bitOffset)) | + ( hBitBuf->Buffer [(byteOffset-4) & byteMask] & ~(BitMask[bitOffset] >> (32-numberOfBits)) ) ; + } +} + + +void FDK_pushBack (HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, UCHAR config) +{ + hBitBuf->BitCnt -= numberOfBits ; + hBitBuf->ValidBits += (config==0) ? numberOfBits : (-(INT)numberOfBits) ; + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1) ; +} + +void FDK_pushForward (HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, UCHAR config) +{ + hBitBuf->BitCnt += numberOfBits ; + hBitBuf->ValidBits -= (config==0) ? numberOfBits : (-(INT)numberOfBits) ; + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1) ; +} + + +void FDK_byteAlign (HANDLE_FDK_BITBUF hBitBuf, UCHAR config) +{ + INT alignment = hBitBuf->BitCnt & 0x07 ; + + if (alignment) + { + if (config==0) + FDK_pushForward (hBitBuf, 8 - alignment, config) ; /* BS_READER */ + else + FDK_put (hBitBuf,0 , 8 - alignment) ; /* BS_WRITER */ + } + + hBitBuf->BitCnt = 0 ; +} + +UINT FDK_getValidBits (HANDLE_FDK_BITBUF hBitBuf) +{ + return hBitBuf->ValidBits; +} + +INT FDK_getFreeBits (HANDLE_FDK_BITBUF hBitBuf) +{ + return (hBitBuf->bufBits - hBitBuf->ValidBits) ; +} + +void FDK_setBitCnt (HANDLE_FDK_BITBUF hBitBuf, const UINT value) +{ + hBitBuf->BitCnt = value ; +} + +INT FDK_getBitCnt (HANDLE_FDK_BITBUF hBitBuf) +{ + return hBitBuf->BitCnt ; +} + +void FDK_Feed(HANDLE_FDK_BITBUF hBitBuf, + UCHAR *RESTRICT inputBuffer, + const UINT bufferSize, + UINT *bytesValid) +{ + inputBuffer = &inputBuffer [bufferSize - *bytesValid] ; + + UINT bTotal = 0 ; + + UINT bToRead = (hBitBuf->bufBits - hBitBuf->ValidBits) >> 3 ; + UINT noOfBytes = fMin(bToRead, *bytesValid); //(bToRead < *bytesValid) ? bToRead : *bytesValid ; + + while (noOfBytes > 0) + { + /* split read to buffer size */ + bToRead = hBitBuf->bufSize - hBitBuf->ReadOffset ; + bToRead = fMin(bToRead, noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes ; + + /* copy 'bToRead' bytes from 'ptr' to inputbuffer */ + FDKmemcpy(&hBitBuf->Buffer[hBitBuf->ReadOffset], inputBuffer, bToRead*sizeof(UCHAR)); + + /* add noOfBits to number of valid bits in buffer */ + hBitBuf->ValidBits += bToRead << 3 ; + bTotal += bToRead ; + inputBuffer += bToRead ; + + hBitBuf->ReadOffset = (hBitBuf->ReadOffset + bToRead) & (hBitBuf->bufSize - 1) ; + noOfBytes -= bToRead ; + } + + *bytesValid -= bTotal ; +} + +void CopyAlignedBlock (HANDLE_FDK_BITBUF h_BitBufSrc, UCHAR *RESTRICT dstBuffer, UINT bToRead) +{ + UINT byteOffset = h_BitBufSrc->BitNdx >> 3 ; + const UINT byteMask = h_BitBufSrc->bufSize - 1 ; + + UCHAR *RESTRICT pBBB = h_BitBufSrc->Buffer; + for (UINT i = 0 ; i < bToRead ; i++) + { + dstBuffer[i] = pBBB[(byteOffset+i) & byteMask] ; + } + + bToRead <<= 3 ; + + h_BitBufSrc->BitNdx = (h_BitBufSrc->BitNdx + bToRead) & (h_BitBufSrc->bufBits - 1) ; + h_BitBufSrc->BitCnt += bToRead ; + h_BitBufSrc->ValidBits -= bToRead ; +} + +void FDK_Copy (HANDLE_FDK_BITBUF h_BitBufDst, HANDLE_FDK_BITBUF h_BitBufSrc, UINT *bytesValid) +{ + INT bTotal = 0; + + /* limit noOfBytes to valid bytes in src buffer and available bytes in dst buffer */ + UINT bToRead = h_BitBufSrc->ValidBits >> 3 ; + UINT noOfBytes = fMin(bToRead, *bytesValid); //(*bytesValid < bToRead) ? *bytesValid : bToRead ; + bToRead = FDK_getFreeBits(h_BitBufDst); + noOfBytes = fMin(bToRead, noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes; + + while (noOfBytes > 0) + { + /* Split Read to buffer size */ + bToRead = h_BitBufDst->bufSize - h_BitBufDst->ReadOffset ; + bToRead = fMin(noOfBytes, bToRead); //(noOfBytes < bToRead) ? noOfBytes : bToRead ; + + /* copy 'bToRead' bytes from buffer to buffer */ + if (!(h_BitBufSrc->BitNdx & 0x07)) { + CopyAlignedBlock (h_BitBufSrc, h_BitBufDst->Buffer + h_BitBufDst->ReadOffset, bToRead) ; + } else { + for (UINT i = 0; i < bToRead; i++) + { + h_BitBufDst->Buffer [h_BitBufDst->ReadOffset + i] = (UCHAR)FDK_get(h_BitBufSrc,8); + } + } + + /* add noOfBits to number of valid bits in buffer */ + h_BitBufDst->ValidBits += bToRead << 3 ; + bTotal += bToRead; + + h_BitBufDst->ReadOffset = (h_BitBufDst->ReadOffset + bToRead) & (h_BitBufDst->bufSize-1); + noOfBytes -= bToRead; + } + + *bytesValid -=bTotal; +} + +void FDK_Fetch (HANDLE_FDK_BITBUF hBitBuf, UCHAR *outBuf, UINT *writeBytes) +{ + UCHAR *RESTRICT outputBuffer = outBuf; + UINT bTotal = 0 ; + + UINT bToWrite = (hBitBuf->ValidBits) >> 3 ; + UINT noOfBytes = fMin(bToWrite, *writeBytes); //(bToWrite < *writeBytes) ? bToWrite : *writeBytes ; + + while (noOfBytes > 0) + { + /* split write to buffer size */ + bToWrite = hBitBuf->bufSize - hBitBuf->WriteOffset ; + bToWrite = fMin(bToWrite, noOfBytes); //(bToWrite < noOfBytes) ? bToWrite : noOfBytes ; + + /* copy 'bToWrite' bytes from bitbuffer to outputbuffer */ + FDKmemcpy(outputBuffer, &hBitBuf->Buffer[hBitBuf->WriteOffset], bToWrite*sizeof(UCHAR)); + + /* sub noOfBits from number of valid bits in buffer */ + hBitBuf->ValidBits -= bToWrite << 3 ; + bTotal += bToWrite ; + outputBuffer += bToWrite ; + + hBitBuf->WriteOffset = (hBitBuf->WriteOffset + bToWrite) & (hBitBuf->bufSize - 1) ; + noOfBytes -= bToWrite ; + } + + *writeBytes = bTotal ; +} + diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp new file mode 100644 index 00000000..1d8ac7ba --- /dev/null +++ b/libFDK/src/FDK_core.cpp @@ -0,0 +1,133 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Manuel Jander + Description: FDK tools versioning support + +******************************************************************************/ + +#include "FDK_core.h" + +/* FDK tools library info */ +#define FDK_TOOLS_LIB_VL0 2 +#define FDK_TOOLS_LIB_VL1 3 +#define FDK_TOOLS_LIB_VL2 6 +#define FDK_TOOLS_LIB_TITLE "FDK Tools" +#ifdef __ANDROID__ +#define FDK_TOOLS_LIB_BUILD_DATE "" +#define FDK_TOOLS_LIB_BUILD_TIME "" +#else +#define FDK_TOOLS_LIB_BUILD_DATE __DATE__ +#define FDK_TOOLS_LIB_BUILD_TIME __TIME__ +#endif + +int FDK_toolsGetLibInfo(LIB_INFO *info) +{ + UINT v; + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + i = FDKlibInfo_lookup(info, FDK_TOOLS); + if (i<0) return -1; + + info += i; + + v = LIB_VERSION(FDK_TOOLS_LIB_VL0, FDK_TOOLS_LIB_VL1, FDK_TOOLS_LIB_VL2); + + FDKsprintf(info->versionStr, "%d.%d.%d", ((v >> 24) & 0xff), ((v >> 16) & 0xff), ((v >> 8 ) & 0xff)); + + info->module_id = FDK_TOOLS; + info->version = v; + info->build_date = (char *)FDK_TOOLS_LIB_BUILD_DATE; + info->build_time = (char *)FDK_TOOLS_LIB_BUILD_TIME; + info->title = (char *)FDK_TOOLS_LIB_TITLE; + info->flags = 0; + + return 0; +} diff --git a/libFDK/src/FDK_crc.cpp b/libFDK/src/FDK_crc.cpp new file mode 100644 index 00000000..a4c6900d --- /dev/null +++ b/libFDK/src/FDK_crc.cpp @@ -0,0 +1,543 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: + contents/description: CRC calculation + +******************************************************************************/ +#include +#include "FDK_crc.h" + + + +/*---------------- constants -----------------------*/ + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + x^15 + x^2 + x^0. + */ +static const USHORT crcLookup_16_15_2_0[256] = +{ + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; +#if 1 +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + x^12 + x^5 + x^0. + */ +static const USHORT crcLookup_16_12_5_0[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; +#else +static const USHORT crcLookup_16_12_5_0[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; +#endif + + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0. + */ +static const USHORT crcLookup_16_14_13_12_11_5_3_2_0[256] = +{ + 0x0000, 0x782f, 0xf05e, 0x8871, 0x9893, 0xe0bc, 0x68cd, 0x10e2, + 0x4909, 0x3126, 0xb957, 0xc178, 0xd19a, 0xa9b5, 0x21c4, 0x59eb, + 0x9212, 0xea3d, 0x624c, 0x1a63, 0x0a81, 0x72ae, 0xfadf, 0x82f0, + 0xdb1b, 0xa334, 0x2b45, 0x536a, 0x4388, 0x3ba7, 0xb3d6, 0xcbf9, + 0x5c0b, 0x2424, 0xac55, 0xd47a, 0xc498, 0xbcb7, 0x34c6, 0x4ce9, + 0x1502, 0x6d2d, 0xe55c, 0x9d73, 0x8d91, 0xf5be, 0x7dcf, 0x05e0, + 0xce19, 0xb636, 0x3e47, 0x4668, 0x568a, 0x2ea5, 0xa6d4, 0xdefb, + 0x8710, 0xff3f, 0x774e, 0x0f61, 0x1f83, 0x67ac, 0xefdd, 0x97f2, + 0xb816, 0xc039, 0x4848, 0x3067, 0x2085, 0x58aa, 0xd0db, 0xa8f4, + 0xf11f, 0x8930, 0x0141, 0x796e, 0x698c, 0x11a3, 0x99d2, 0xe1fd, + 0x2a04, 0x522b, 0xda5a, 0xa275, 0xb297, 0xcab8, 0x42c9, 0x3ae6, + 0x630d, 0x1b22, 0x9353, 0xeb7c, 0xfb9e, 0x83b1, 0x0bc0, 0x73ef, + 0xe41d, 0x9c32, 0x1443, 0x6c6c, 0x7c8e, 0x04a1, 0x8cd0, 0xf4ff, + 0xad14, 0xd53b, 0x5d4a, 0x2565, 0x3587, 0x4da8, 0xc5d9, 0xbdf6, + 0x760f, 0x0e20, 0x8651, 0xfe7e, 0xee9c, 0x96b3, 0x1ec2, 0x66ed, + 0x3f06, 0x4729, 0xcf58, 0xb777, 0xa795, 0xdfba, 0x57cb, 0x2fe4, + 0x0803, 0x702c, 0xf85d, 0x8072, 0x9090, 0xe8bf, 0x60ce, 0x18e1, + 0x410a, 0x3925, 0xb154, 0xc97b, 0xd999, 0xa1b6, 0x29c7, 0x51e8, + 0x9a11, 0xe23e, 0x6a4f, 0x1260, 0x0282, 0x7aad, 0xf2dc, 0x8af3, + 0xd318, 0xab37, 0x2346, 0x5b69, 0x4b8b, 0x33a4, 0xbbd5, 0xc3fa, + 0x5408, 0x2c27, 0xa456, 0xdc79, 0xcc9b, 0xb4b4, 0x3cc5, 0x44ea, + 0x1d01, 0x652e, 0xed5f, 0x9570, 0x8592, 0xfdbd, 0x75cc, 0x0de3, + 0xc61a, 0xbe35, 0x3644, 0x4e6b, 0x5e89, 0x26a6, 0xaed7, 0xd6f8, + 0x8f13, 0xf73c, 0x7f4d, 0x0762, 0x1780, 0x6faf, 0xe7de, 0x9ff1, + 0xb015, 0xc83a, 0x404b, 0x3864, 0x2886, 0x50a9, 0xd8d8, 0xa0f7, + 0xf91c, 0x8133, 0x0942, 0x716d, 0x618f, 0x19a0, 0x91d1, 0xe9fe, + 0x2207, 0x5a28, 0xd259, 0xaa76, 0xba94, 0xc2bb, 0x4aca, 0x32e5, + 0x6b0e, 0x1321, 0x9b50, 0xe37f, 0xf39d, 0x8bb2, 0x03c3, 0x7bec, + 0xec1e, 0x9431, 0x1c40, 0x646f, 0x748d, 0x0ca2, 0x84d3, 0xfcfc, + 0xa517, 0xdd38, 0x5549, 0x2d66, 0x3d84, 0x45ab, 0xcdda, 0xb5f5, + 0x7e0c, 0x0623, 0x8e52, 0xf67d, 0xe69f, 0x9eb0, 0x16c1, 0x6eee, + 0x3705, 0x4f2a, 0xc75b, 0xbf74, 0xaf96, 0xd7b9, 0x5fc8, 0x27e7, +}; + +/*--------------- function declarations --------------------*/ + +static inline INT calcCrc_Bits( + USHORT * const pCrc, + USHORT crcMask, + USHORT crcPoly, + HANDLE_FDK_BITSTREAM hBs, + INT nBits + ); + +static inline INT calcCrc_Bytes( + USHORT * const pCrc, + const USHORT * pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, + INT nBytes + ); + +static void crcCalc( + HANDLE_FDK_CRCINFO hCrcInfo, + HANDLE_FDK_BITSTREAM hBs, + const INT reg + ); + + +/*------------- function definitions ----------------*/ + +void FDKcrcInit( + HANDLE_FDK_CRCINFO hCrcInfo, + const UINT crcPoly, + const UINT crcStartValue, + const UINT crcLen + ) +{ + /* crc polynom example: + DAB+ FireCode: + x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0 + (1) 0111 1000 0010 1101 -> 0x782d + + x^16 + x^15 + x^2 + x^0 (1) 1000 0000 0000 0101 -> 0x8005 + x^16 + x^12 + x^5 + x^0 (1) 0001 0000 0010 0001 -> 0x1021 + x^8 + x^4 + x^3 + x^2 + x^0 (1) 0001 1101 -> 0x001d */ + + hCrcInfo->crcLen = crcLen; + hCrcInfo->crcPoly = crcPoly; + hCrcInfo->startValue = crcStartValue; + hCrcInfo->crcMask = (crcLen) ? (1<<(crcLen-1)) : 0; + + FDKcrcReset(hCrcInfo); + + hCrcInfo->pCrcLookup = 0; + + if (hCrcInfo->crcLen==16) { + switch ( crcPoly ) { + case 0x8005: + hCrcInfo->pCrcLookup = crcLookup_16_15_2_0; + break; + case 0x1021: + hCrcInfo->pCrcLookup = crcLookup_16_12_5_0; + break; + case 0x782d: + hCrcInfo->pCrcLookup = crcLookup_16_14_13_12_11_5_3_2_0; + break; + case 0x001d: + default: + /* no lookup table */ + hCrcInfo->pCrcLookup = 0; + } + } + + +} + +void FDKcrcReset(HANDLE_FDK_CRCINFO hCrcInfo) +{ + int i; + + hCrcInfo->crcValue = hCrcInfo->startValue; + + for(i=0;icrcRegData[i].isActive = 0; + } + hCrcInfo->regStart = 0; + hCrcInfo->regStop = 0; +} + +INT FDKcrcStartReg( + HANDLE_FDK_CRCINFO hCrcInfo, + const HANDLE_FDK_BITSTREAM hBs, + const INT mBits + ) +{ + int reg = hCrcInfo->regStart; + + FDK_ASSERT(hCrcInfo->crcRegData[reg].isActive==0); + hCrcInfo->crcRegData[reg].isActive = 1; + hCrcInfo->crcRegData[reg].maxBits = mBits; + hCrcInfo->crcRegData[reg].validBits = FDKgetValidBits(hBs) ; + hCrcInfo->crcRegData[reg].bitBufCntBits = 0; + + hCrcInfo->regStart = (hCrcInfo->regStart+1)%MAX_CRC_REGS; + + return (reg); +} + +INT FDKcrcEndReg( + HANDLE_FDK_CRCINFO hCrcInfo, + const HANDLE_FDK_BITSTREAM hBs, + const INT reg + ) +{ + FDK_ASSERT((reg==(INT)hCrcInfo->regStop)&&(hCrcInfo->crcRegData[reg].isActive==1)); + + if (hBs->ConfigCache==BS_WRITER) { + hCrcInfo->crcRegData[reg].bitBufCntBits = FDKgetValidBits(hBs) - hCrcInfo->crcRegData[reg].validBits; + } + else { + hCrcInfo->crcRegData[reg].bitBufCntBits = hCrcInfo->crcRegData[reg].validBits - FDKgetValidBits(hBs); + } + + if (hCrcInfo->crcRegData[reg].maxBits == 0) { + hCrcInfo->crcRegData[reg].maxBits = hCrcInfo->crcRegData[reg].bitBufCntBits; + } + + crcCalc( hCrcInfo, hBs, reg); + + hCrcInfo->crcRegData[reg].isActive = 0; + hCrcInfo->regStop = (hCrcInfo->regStop+1)%MAX_CRC_REGS; + + return 0; +} + +USHORT FDKcrcGetCRC( + const HANDLE_FDK_CRCINFO hCrcInfo + ) +{ + return ( hCrcInfo->crcValue & (((hCrcInfo->crcMask-1)<<1)+1) ); +} + +/** + * \brief Calculate crc bits. + * + * Calculate crc starting at current bitstream postion over nBits. + * + * \param pCrc Pointer to an outlying allocated crc info structure. + * \param crcMask CrcMask in use. + * \param crcPoly Crc polynom in use. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bits. + * + * \return Number of processed bits. + */ +static inline INT calcCrc_Bits( + USHORT * const pCrc, + USHORT crcMask, + USHORT crcPoly, + HANDLE_FDK_BITSTREAM hBs, + INT nBits + ) +{ + int i; + USHORT crc = *pCrc; /* get crc value */ + + if (hBs!=NULL) { + for (i = 0; (i < nBits); i++) { + USHORT tmp = FDKreadBits(hBs,1); // process single bit + tmp ^= ( (crc & crcMask) ? 1 : 0 ); + tmp *= crcPoly; + crc <<= 1; + crc ^= tmp; + } + } + else { + for (i = 0; (i < nBits); i++) { + USHORT tmp = 0; // process single bit + tmp ^= ( (crc & crcMask) ? 1 : 0 ); + tmp *= crcPoly; + crc <<= 1; + crc ^= tmp; + } + } + *pCrc = crc; /* update crc value */ + + return nBits; +} + +/** + * \brief Calculate crc bytes. + * + * Calculate crc starting at current bitstream postion over nBytes. + * + * \param pCrc Pointer to an outlying allocated crc info structure. + * \param pCrcLookup Pointer to lookup table used for fast crc calculation. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bytes. + * + * \return Number of processed bits. + */ +static inline INT calcCrc_Bytes( + USHORT * const pCrc, + const USHORT * pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, + INT nBytes + ) +{ + int i; + USHORT crc = *pCrc; /* get crc value */ + if (hBs!=NULL) { + for (i=0; i>8)^(FDKreadBits(hBs,8)))&0xFF]; + } + } + else { + for (i=0; i>8)^((UCHAR)0))&0xFF]; + } + } + + *pCrc = crc; /* update crc value */ + //fprintf(stderr, "\n\n crc[%d]=%04x\n", i, crc); + + return (i); +} + +/** + * \brief Calculate crc. + * + * Calculate crc. Lenght depends on mBits parameter in FDKcrcStartReg() configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info structure. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID. + * + * \return Number of processed bits. + */ +static void crcCalc( + HANDLE_FDK_CRCINFO hCrcInfo, + HANDLE_FDK_BITSTREAM hBs, + const INT reg + ) +{ + USHORT crc = hCrcInfo->crcValue; + CCrcRegData *rD = &hCrcInfo->crcRegData[reg]; + FDK_BITSTREAM bsReader; + + if (hBs->ConfigCache==BS_READER) { + bsReader = *hBs; + FDKpushBiDirectional(&bsReader, -(INT)(rD->validBits-FDKgetValidBits(&bsReader))); + } + else { + FDKinitBitStream(&bsReader, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, hBs->hBitBuf.ValidBits, BS_READER); + FDKpushBiDirectional(&bsReader, rD->validBits); + } + + int bits, rBits; + rBits = (rD->maxBits>=0) ? rD->maxBits : -rD->maxBits; /* remaining bits */ + if ((rD->maxBits>0) && (((INT)rD->bitBufCntBits>>3<<3)bitBufCntBits; + } + else { + bits = rBits; + } + + int words = bits >> 3; /* processing bytes */ + int mBits = bits & 0x7; /* modulo bits */ + + if(hCrcInfo->pCrcLookup) { + rBits -= (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, &bsReader, words)<<3); + } + else { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, words<<3 ); + } + + /* remaining valid bits*/ + if(mBits!=0) { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, mBits ); + } + + if (rBits!=0) { + /* zero bytes */ + if ( (hCrcInfo->pCrcLookup) && (rBits>8) ) { + rBits -= (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, NULL, rBits>>3)<<3); + } + /* remaining zero bits */ + if (rBits!=0) { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, NULL, rBits ); + } + } + + //fprintf(stderr, "\n\n crc=%04x\n", crc); + hCrcInfo->crcValue = crc; +} + diff --git a/libFDK/src/FDK_hybrid.cpp b/libFDK/src/FDK_hybrid.cpp new file mode 100644 index 00000000..20816f5a --- /dev/null +++ b/libFDK/src/FDK_hybrid.cpp @@ -0,0 +1,709 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Markus Lohwasser + Description: FDK Tools Hybrid Filterbank + +******************************************************************************/ + +#include "FDK_hybrid.h" + + +#include "fft.h" + +/*--------------- defines -----------------------------*/ +#define FFT_IDX_R(a) (2*a) +#define FFT_IDX_I(a) (2*a+1) + +#define HYB_COEF8_0 ( 0.00746082949812f ) +#define HYB_COEF8_1 ( 0.02270420949825f ) +#define HYB_COEF8_2 ( 0.04546865930473f ) +#define HYB_COEF8_3 ( 0.07266113929591f ) +#define HYB_COEF8_4 ( 0.09885108575264f ) +#define HYB_COEF8_5 ( 0.11793710567217f ) +#define HYB_COEF8_6 ( 0.12500000000000f ) +#define HYB_COEF8_7 ( HYB_COEF8_5 ) +#define HYB_COEF8_8 ( HYB_COEF8_4 ) +#define HYB_COEF8_9 ( HYB_COEF8_3 ) +#define HYB_COEF8_10 ( HYB_COEF8_2 ) +#define HYB_COEF8_11 ( HYB_COEF8_1 ) +#define HYB_COEF8_12 ( HYB_COEF8_0 ) + + +/*--------------- structure definitions ---------------*/ + +#if defined(ARCH_PREFER_MULT_32x16) + #define FIXP_HTB FIXP_SGL /* SGL data type. */ + #define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ + #define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ + #define FL2FXCONST_HTB FL2FXCONST_SGL +#else + #define FIXP_HTB FIXP_DBL /* SGL data type. */ + #define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ + #define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ + #define FL2FXCONST_HTB FL2FXCONST_DBL +#endif + +#define HTCP(real,imag) { { HTC(real), HTC(imag) } } /* How to arrange the packed values. */ + + +struct FDK_HYBRID_SETUP +{ + UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ + UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ + SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ + UCHAR protoLen; /*!< Prototype filter length. */ + UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ + const INT *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ + +}; + +/*--------------- constants ---------------------------*/ +static const INT ringbuffIdxTab[2*13] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; + +static const FDK_HYBRID_SETUP setup_3_16 = { 3, { 8, 4, 4}, { 8, 4, 4}, 13, (13-1)/2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_12 = { 3, { 8, 2, 2}, { 8, 2, 2}, 13, (13-1)/2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_10 = { 3, { 6, 2, 2}, { -8, -2, 2}, 13, (13-1)/2, ringbuffIdxTab}; + + +static const FIXP_HTP HybFilterCoef8[] = { + HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), + HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), + HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), + HTCP(0x0df26407, 0x05c6e77e) +}; + +static const FIXP_HTB HybFilterCoef2[13] = { + FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.30596630545168f), + FL2FXCONST_HTB( 0.50000000000000f), FL2FXCONST_HTB( 0.30596630545168f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB(-0.07293139167538f), FL2FXCONST_HTB( 0.00000000000000f), FL2FXCONST_HTB( 0.01899487526049f), + FL2FXCONST_HTB( 0.00000000000000f) +}; + +static const FIXP_HTB HybFilterCoef4[13] = { + FL2FXCONST_HTB(-0.00305151927305f), FL2FXCONST_HTB(-0.00794862316203f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.21227807049160f), + FL2FXCONST_HTB( 0.25f), FL2FXCONST_HTB( 0.21227807049160f), FL2FXCONST_HTB( 0.12542448210445f), FL2FXCONST_HTB( 0.04318924038756f), FL2FXCONST_HTB( 0.0f), FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(-0.00305151927305f) +}; + +/*--------------- function declarations ---------------*/ +static INT kChannelFiltering( + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig + ); + + +/*--------------- function definitions ----------------*/ + +INT FDKhybridAnalysisOpen( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, + const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, + const UINT HFmemorySize + ) +{ + INT err = 0; + + /* Save pointer to extern memory. */ + hAnalysisHybFilter->pLFmemory = pLFmemory; + hAnalysisHybFilter->LFmemorySize = LFmemorySize; + + hAnalysisHybFilter->pHFmemory = pHFmemory; + hAnalysisHybFilter->HFmemorySize = HFmemorySize; + + return err; +} + +INT FDKhybridAnalysisInit( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, + const INT qmfBands, + const INT cplxBands, + const INT initStatesFlag + ) +{ + int k; + INT err = 0; + FIXP_DBL *pMem = NULL; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; + case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; + case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; + default: err = -1; goto bail; + } + + /* Initialize handle. */ + hAnalysisHybFilter->pSetup = setup; + hAnalysisHybFilter->bufferLFpos = setup->protoLen-1; + hAnalysisHybFilter->bufferHFpos = 0; + hAnalysisHybFilter->nrBands = qmfBands; + hAnalysisHybFilter->cplxBands = cplxBands; + hAnalysisHybFilter->hfMode = 0; + + /* Check available memory. */ + if ( ((2*setup->nrQmfBands*setup->protoLen*sizeof(FIXP_DBL)) > hAnalysisHybFilter->LFmemorySize) + || ((setup->filterDelay*((qmfBands-setup->nrQmfBands)+(cplxBands-setup->nrQmfBands))*sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize) ) + { + err = -2; + goto bail; + } + + /* Distribut LF memory. */ + pMem = hAnalysisHybFilter->pLFmemory; + for (k=0; knrQmfBands; k++) { + hAnalysisHybFilter->bufferLFReal[k] = pMem; pMem += setup->protoLen; + hAnalysisHybFilter->bufferLFImag[k] = pMem; pMem += setup->protoLen; + } + + /* Distribut HF memory. */ + pMem = hAnalysisHybFilter->pHFmemory; + for (k=0; kfilterDelay; k++) { + hAnalysisHybFilter->bufferHFReal[k] = pMem; pMem += (qmfBands-setup->nrQmfBands); + hAnalysisHybFilter->bufferHFImag[k] = pMem; pMem += (cplxBands-setup->nrQmfBands); + } + + if (initStatesFlag) { + /* Clear LF buffer */ + for (k=0; knrQmfBands; k++) { + FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen*sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen*sizeof(FIXP_DBL)); + } + + if (qmfBands > setup->nrQmfBands) { + /* Clear HF buffer */ + for (k=0; kfilterDelay; k++) { + FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], (qmfBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], (cplxBands-setup->nrQmfBands)*sizeof(FIXP_DBL)); + } + } + } + +bail: + return err; +} + +INT FDKhybridAnalysisScaleStates( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue + ) +{ + INT err = 0; + + if (hAnalysisHybFilter==NULL) { + err = 1; /* invalid handle */ + } + else { + int k; + HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; + + /* Scale LF buffer */ + for (k=0; knrQmfBands; k++) { + scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, scalingValue); + scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, scalingValue); + } + if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { + /* Scale HF buffer */ + for (k=0; kfilterDelay; k++) { + scaleValues(hAnalysisHybFilter->bufferHFReal[k], (hAnalysisHybFilter->nrBands-setup->nrQmfBands), scalingValue); + scaleValues(hAnalysisHybFilter->bufferHFImag[k], (hAnalysisHybFilter->cplxBands-setup->nrQmfBands), scalingValue); + } + } + } + return err; +} + +INT FDKhybridAnalysisApply( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag) +{ + int k, hybOffset = 0; + INT err = 0; + const int nrQmfBandsLF = hAnalysisHybFilter->pSetup->nrQmfBands; /* number of QMF bands to be converted to hybrid */ + + const int writIndex = hAnalysisHybFilter->bufferLFpos; + int readIndex = hAnalysisHybFilter->bufferLFpos; + + if (++readIndex>=hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; + const INT* pBufferLFreadIdx = &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; + + /* + * LF buffer. + */ + for (k=0; kbufferLFReal[k][writIndex] = pQmfReal[k]; + hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; + + /* Perform hybrid filtering. */ + kChannelFiltering( + hAnalysisHybFilter->bufferLFReal[k], + hAnalysisHybFilter->bufferLFImag[k], + pBufferLFreadIdx, + pHybridReal+hybOffset, + pHybridImag+hybOffset, + hAnalysisHybFilter->pSetup->kHybrid[k]); + + hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; + } + + hAnalysisHybFilter->bufferLFpos = readIndex; /* Index where to write next input sample. */ + + if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + if (hAnalysisHybFilter->hfMode!=0) { + /* HF delay compensation was applied outside. */ + FDKmemcpy(pHybridReal+hybOffset, &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + FDKmemcpy(pHybridImag+hybOffset, &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + } + else { + /* HF delay compensation, filterlength/2. */ + FDKmemcpy(pHybridReal+hybOffset, hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + FDKmemcpy(pHybridImag+hybOffset, hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + + FDKmemcpy(hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], &pQmfReal[nrQmfBandsLF], (hAnalysisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + FDKmemcpy(hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], &pQmfImag[nrQmfBandsLF], (hAnalysisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + + if (++hAnalysisHybFilter->bufferHFpos>=hAnalysisHybFilter->pSetup->filterDelay) hAnalysisHybFilter->bufferHFpos = 0; + } + } /* process HF part*/ + + return err; +} + +INT FDKhybridAnalysisClose( + HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter + ) +{ + INT err = 0; + + if (hAnalysisHybFilter != NULL) { + hAnalysisHybFilter->pLFmemory = NULL; + hAnalysisHybFilter->pHFmemory = NULL; + hAnalysisHybFilter->LFmemorySize = 0; + hAnalysisHybFilter->HFmemorySize = 0; + } + + return err; +} + +INT FDKhybridSynthesisInit( + HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, + const INT qmfBands, + const INT cplxBands + ) +{ + INT err = 0; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_10; break; + case THREE_TO_TWELVE: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_12; break; + case THREE_TO_SIXTEEN: setup = (HANDLE_FDK_HYBRID_SETUP)&setup_3_16; break; + default: err = -1; goto bail; + } + + hSynthesisHybFilter->pSetup = setup; + hSynthesisHybFilter->nrBands = qmfBands; + hSynthesisHybFilter->cplxBands = cplxBands; + +bail: + return err; +} + + +INT FDKhybridSynthesisApply( + HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag + ) +{ + int k, n, hybOffset=0; + INT err = 0; + const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; + + /* + * LF buffer. + */ + for (k=0; kpSetup->nHybBands[k]; + + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); + + /* Perform hybrid filtering. */ + for (n=0; nnrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], (hSynthesisHybFilter->nrBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + FDKmemcpy(&pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], (hSynthesisHybFilter->cplxBands-nrQmfBandsLF)*sizeof(FIXP_DBL)); + } + + return err; +} + +static void dualChannelFiltering( + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert + ) +{ + const FIXP_HTB *p = HybFilterCoef2; + + FIXP_DBL r1, r6; + FIXP_DBL i1, i6; + + /* symmetric filter coefficients */ + r1 = fMultDiv2(p[1], pQmfReal[pReadIdx[1]]) + fMultDiv2(p[1], pQmfReal[pReadIdx[11]]) ; + i1 = fMultDiv2(p[1], pQmfImag[pReadIdx[1]]) + fMultDiv2(p[1], pQmfImag[pReadIdx[11]]) ; + r1 += fMultDiv2(p[3], pQmfReal[pReadIdx[3]]) + fMultDiv2(p[3], pQmfReal[pReadIdx[ 9]]) ; + i1 += fMultDiv2(p[3], pQmfImag[pReadIdx[3]]) + fMultDiv2(p[3], pQmfImag[pReadIdx[ 9]]) ; + r1 += fMultDiv2(p[5], pQmfReal[pReadIdx[5]]) + fMultDiv2(p[5], pQmfReal[pReadIdx[ 7]]) ; + i1 += fMultDiv2(p[5], pQmfImag[pReadIdx[5]]) + fMultDiv2(p[5], pQmfImag[pReadIdx[ 7]]) ; + r6 = fMultDiv2(p[6], pQmfReal[pReadIdx[6]]) ; + i6 = fMultDiv2(p[6], pQmfImag[pReadIdx[6]]) ; + + if (invert) { + mHybridReal[1] = (r1 + r6) << 1; + mHybridImag[1] = (i1 + i6) << 1; + + mHybridReal[0] = (r6 - r1) << 1; + mHybridImag[0] = (i6 - i1) << 1; + } + else { + mHybridReal[0] = (r1 + r6) << 1; + mHybridImag[0] = (i1 + i6) << 1; + + mHybridReal[1] = (r6 - r1) << 1; + mHybridImag[1] = (i6 - i1) << 1; + } +} + +static void fourChannelFiltering( + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert + ) +{ + const FIXP_HTB *p = HybFilterCoef4; + + FIXP_DBL fft[8]; + + static const FIXP_DBL cr[13] = { + FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), + FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), + FL2FXCONST_DBL( 1.f), + FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f) + }; + static const FIXP_DBL ci[13] = { + FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( 0.f), + FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f), FL2FXCONST_DBL( 0.70710678118655f), + FL2FXCONST_DBL( 0.f), + FL2FXCONST_DBL(-0.70710678118655f), FL2FXCONST_DBL( -1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL( 0.f), FL2FXCONST_DBL( 0.70710678118655f), FL2FXCONST_DBL( 1.f) + }; + + + /* FIR filter. */ + /* pre twiddeling with pre-twiddling coefficients c[n] */ + /* multiplication with filter coefficients p[n] */ + /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ + /* write to fft coefficient n' */ + fft[FFT_IDX_R(0)] = ( fMult(p[10], ( fMultSub(fMultDiv2(cr[ 2], pQmfReal[pReadIdx[ 2]]), ci[ 2], pQmfImag[pReadIdx[ 2]]))) + + fMult(p[ 6], ( fMultSub(fMultDiv2(cr[ 6], pQmfReal[pReadIdx[ 6]]), ci[ 6], pQmfImag[pReadIdx[ 6]]))) + + fMult(p[ 2], ( fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], pQmfImag[pReadIdx[10]]))) ); + fft[FFT_IDX_I(0)] = ( fMult(p[10], ( fMultAdd(fMultDiv2(ci[ 2], pQmfReal[pReadIdx[ 2]]), cr[ 2], pQmfImag[pReadIdx[ 2]]))) + + fMult(p[ 6], ( fMultAdd(fMultDiv2(ci[ 6], pQmfReal[pReadIdx[ 6]]), cr[ 6], pQmfImag[pReadIdx[ 6]]))) + + fMult(p[ 2], ( fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], pQmfImag[pReadIdx[10]]))) ); + + /* twiddle dee dum */ + fft[FFT_IDX_R(1)] = ( fMult(p[ 9], ( fMultSub(fMultDiv2(cr[ 3], pQmfReal[pReadIdx[ 3]]), ci[ 3], pQmfImag[pReadIdx[ 3]]))) + + fMult(p[ 5], ( fMultSub(fMultDiv2(cr[ 7], pQmfReal[pReadIdx[ 7]]), ci[ 7], pQmfImag[pReadIdx[ 7]]))) + + fMult(p[ 1], ( fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], pQmfImag[pReadIdx[11]]))) ); + fft[FFT_IDX_I(1)] = ( fMult(p[ 9], ( fMultAdd(fMultDiv2(ci[ 3], pQmfReal[pReadIdx[ 3]]), cr[ 3], pQmfImag[pReadIdx[ 3]]))) + + fMult(p[ 5], ( fMultAdd(fMultDiv2(ci[ 7], pQmfReal[pReadIdx[ 7]]), cr[ 7], pQmfImag[pReadIdx[ 7]]))) + + fMult(p[ 1], ( fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], pQmfImag[pReadIdx[11]]))) ); + + /* twiddle dee dee */ + fft[FFT_IDX_R(2)] = ( fMult(p[12], ( fMultSub(fMultDiv2(cr[ 0], pQmfReal[pReadIdx[ 0]]), ci[ 0], pQmfImag[pReadIdx[ 0]]))) + + fMult(p[ 8], ( fMultSub(fMultDiv2(cr[ 4], pQmfReal[pReadIdx[ 4]]), ci[ 4], pQmfImag[pReadIdx[ 4]]))) + + fMult(p[ 4], ( fMultSub(fMultDiv2(cr[ 8], pQmfReal[pReadIdx[ 8]]), ci[ 8], pQmfImag[pReadIdx[ 8]]))) + + fMult(p[ 0], ( fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], pQmfImag[pReadIdx[12]]))) ); + fft[FFT_IDX_I(2)] = ( fMult(p[12], ( fMultAdd(fMultDiv2(ci[ 0], pQmfReal[pReadIdx[ 0]]), cr[ 0], pQmfImag[pReadIdx[ 0]]))) + + fMult(p[ 8], ( fMultAdd(fMultDiv2(ci[ 4], pQmfReal[pReadIdx[ 4]]), cr[ 4], pQmfImag[pReadIdx[ 4]]))) + + fMult(p[ 4], ( fMultAdd(fMultDiv2(ci[ 8], pQmfReal[pReadIdx[ 8]]), cr[ 8], pQmfImag[pReadIdx[ 8]]))) + + fMult(p[ 0], ( fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], pQmfImag[pReadIdx[12]]))) ); + + fft[FFT_IDX_R(3)] = ( fMult(p[11], ( fMultSub(fMultDiv2(cr[ 1], pQmfReal[pReadIdx[ 1]]), ci[ 1], pQmfImag[pReadIdx[ 1]]))) + + fMult(p[ 7], ( fMultSub(fMultDiv2(cr[ 5], pQmfReal[pReadIdx[ 5]]), ci[ 5], pQmfImag[pReadIdx[ 5]]))) + + fMult(p[ 3], ( fMultSub(fMultDiv2(cr[ 9], pQmfReal[pReadIdx[ 9]]), ci[ 9], pQmfImag[pReadIdx[ 9]]))) ); + fft[FFT_IDX_I(3)] = ( fMult(p[11], ( fMultAdd(fMultDiv2(ci[ 1], pQmfReal[pReadIdx[ 1]]), cr[ 1], pQmfImag[pReadIdx[ 1]]))) + + fMult(p[ 7], ( fMultAdd(fMultDiv2(ci[ 5], pQmfReal[pReadIdx[ 5]]), cr[ 5], pQmfImag[pReadIdx[ 5]]))) + + fMult(p[ 3], ( fMultAdd(fMultDiv2(ci[ 9], pQmfReal[pReadIdx[ 9]]), cr[ 9], pQmfImag[pReadIdx[ 9]]))) ); + + /* fft modulation */ + /* here: fast manual fft modulation for a fft of length M=4 */ + /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + + x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ + + /* + fft bin m=0: + X[0, n] = x[0] + x[1] + x[2] + x[3] + */ + mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + fft[FFT_IDX_R(3)]; + mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + fft[FFT_IDX_I(3)]; + + /* + fft bin m=1: + X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] + */ + mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - fft[FFT_IDX_I(3)]; + mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + fft[FFT_IDX_R(3)]; + + /* + fft bin m=2: + X[2, n] = x[0] - x[1] + x[2] - x[3] + */ + mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - fft[FFT_IDX_R(3)]; + mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - fft[FFT_IDX_I(3)]; + + /* + fft bin m=3: + X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] + */ + mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + fft[FFT_IDX_I(3)]; + mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - fft[FFT_IDX_R(3)]; +} + + +static void eightChannelFiltering( + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert + ) +{ + const FIXP_HTP *p = HybFilterCoef8; + INT k, sc; + + FIXP_DBL mfft[16+ALIGNMENT_DEFAULT]; + FIXP_DBL *pfft = (FIXP_DBL*)ALIGN_PTR(mfft); + + FIXP_DBL accu1, accu2, accu3, accu4; + + /* pre twiddeling */ + pfft[FFT_IDX_R(0)] = fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); + pfft[FFT_IDX_I(0)] = fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], p[1]); + pfft[FFT_IDX_R(1)] = accu1; + pfft[FFT_IDX_I(1)] = accu2; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], p[2]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], p[3]); + pfft[FFT_IDX_R(2)] = accu1 + accu3; + pfft[FFT_IDX_I(2)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], p[4]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], p[5]); + pfft[FFT_IDX_R(3)] = accu1 + accu3; + pfft[FFT_IDX_I(3)] = accu2 + accu4; + + pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - fMultDiv2(pQmfImag[pReadIdx[ 2]], p[6].v.im); + pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[ 2]], p[6].v.im) - fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 3]], pQmfImag[pReadIdx[ 3]], p[8]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], p[9]); + pfft[FFT_IDX_R(5)] = accu1 + accu3; + pfft[FFT_IDX_I(5)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 4]], pQmfImag[pReadIdx[ 4]], p[10]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], p[11]); + pfft[FFT_IDX_R(6)] = accu1 + accu3; + pfft[FFT_IDX_I(6)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[ 5]], pQmfImag[pReadIdx[ 5]], p[12]); + pfft[FFT_IDX_R(7)] = accu1; + pfft[FFT_IDX_I(7)] = accu2; + + /* fft modulation */ + fft_8 (pfft); + sc = 1 + 2; + + if (invert) { + mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; + mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; + mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; + mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; + + mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; + mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; + mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; + mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; + + mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc; + mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc; + mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc; + mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc; + + mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc; + mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc; + mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc; + mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc; + } + else { + for(k=0; k<8;k++ ) { + mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; + mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; + } + } +} + +static INT kChannelFiltering( + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig + ) +{ + INT err = 0; + + switch (hybridConfig) { + case 2: + case -2: + dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); + break; + case 4: + case -4: + fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); + break; + case 8: + case -8: + eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, mHybridImag, (hybridConfig<0) ? 1 : 0 ); + break; + default: + err = -1; + } + + return err; +} + + + diff --git a/libFDK/src/FDK_tools_rom.cpp b/libFDK/src/FDK_tools_rom.cpp new file mode 100644 index 00000000..a829485f --- /dev/null +++ b/libFDK/src/FDK_tools_rom.cpp @@ -0,0 +1,2623 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Oliver Moser + Description: ROM tables used by FDK tools + +******************************************************************************/ + +#include "FDK_tools_rom.h" + + + + + + + + + + + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable480[] = +{ + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd315, 0x006b3b9b), STCP(0x7fff4c54, 0x00d676eb), STCP(0x7ffe6bbf, 0x0141b1a5), + STCP(0x7ffd3154, 0x01aceb7c), STCP(0x7ffb9d15, 0x02182427), STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff76721, 0x02ee90c8), + STCP(0x7ff4c56f, 0x0359c428), STCP(0x7ff1c9ef, 0x03c4f52f), STCP(0x7fee74a2, 0x0430238f), STCP(0x7feac58d, 0x049b4f00), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fe25a0f, 0x05719be2), STCP(0x7fdd9dad, 0x05dcbcbe), STCP(0x7fd8878e, 0x0647d97c), + STCP(0x7fd317b4, 0x06b2f1d2), STCP(0x7fcd4e24, 0x071e0575), STCP(0x7fc72ae2, 0x07891418), STCP(0x7fc0adf2, 0x07f41d72), + STCP(0x7fb9d759, 0x085f2137), STCP(0x7fb2a71b, 0x08ca1f1b), STCP(0x7fab1d3d, 0x093516d4), STCP(0x7fa339c5, 0x09a00817), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f92661d, 0x0a75d60e), STCP(0x7f8975f9, 0x0ae0b22c), STCP(0x7f802c52, 0x0b4b86a8), + STCP(0x7f76892f, 0x0bb65336), STCP(0x7f6c8c96, 0x0c21178c), STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f578721, 0x0cf68662), + STCP(0x7f4c7e54, 0x0d61304e), STCP(0x7f411c2f, 0x0dcbd0d5), STCP(0x7f3560b9, 0x0e3667ad), STCP(0x7f294bfd, 0x0ea0f48c), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f1016ce, 0x0f75ef33), STCP(0x7f02f66f, 0x0fe05c64), STCP(0x7ef57cea, 0x104abe71), + STCP(0x7ee7aa4c, 0x10b5150f), STCP(0x7ed97e9c, 0x111f5ff4), STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7ebc1c31, 0x11f3d164), + STCP(0x7eace58a, 0x125df75b), STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8d6d91, 0x13321c53), STCP(0x7e7d2c54, 0x139c1abf), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e5b9f93, 0x146fee03), STCP(0x7e4a5426, 0x14d9c245), STCP(0x7e38b017, 0x154387e6), + STCP(0x7e26b371, 0x15ad3e9a), STCP(0x7e145e42, 0x1616e618), STCP(0x7e01b096, 0x16807e15), STCP(0x7deeaa7a, 0x16ea0646), + STCP(0x7ddb4bfc, 0x17537e63), STCP(0x7dc79529, 0x17bce621), STCP(0x7db3860f, 0x18263d36), STCP(0x7d9f1ebd, 0x188f8357), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d7547a7, 0x1961db9b), STCP(0x7d5fd801, 0x19caed29), STCP(0x7d4a105d, 0x1a33ec9c), + STCP(0x7d33f0ca, 0x1a9cd9ac), STCP(0x7d1d7958, 0x1b05b40f), STCP(0x7d06aa16, 0x1b6e7b7a), STCP(0x7cef8315, 0x1bd72fa4), + STCP(0x7cd80464, 0x1c3fd045), STCP(0x7cc02e15, 0x1ca85d12), STCP(0x7ca80038, 0x1d10d5c2), STCP(0x7c8f7ade, 0x1d793a0b), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7c5d69f7, 0x1e49c447), STCP(0x7c43de8e, 0x1eb1e9a7), STCP(0x7c29fbee, 0x1f19f97b), + STCP(0x7c0fc22a, 0x1f81f37c), STCP(0x7bf53153, 0x1fe9d75f), STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bbf0aba, 0x20b95bac), + STCP(0x7ba3751d, 0x2120fb83), STCP(0x7b8788ba, 0x2188841a), STCP(0x7b6b45a5, 0x21eff528), STCP(0x7b4eabf1, 0x22574e65), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7b1474fd, 0x2325b847), STCP(0x7af6d7e6, 0x238cc85d), STCP(0x7ad8e482, 0x23f3bf7e), + STCP(0x7aba9ae6, 0x245a9d65), STCP(0x7a9bfb27, 0x24c161c7), STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5db997, 0x258e9ce0), + STCP(0x7a3e17f2, 0x25f51307), STCP(0x7a1e2082, 0x265b6e8a), STCP(0x79fdd35c, 0x26c1af22), STCP(0x79dd3098, 0x2727d486), + STCP(0x79bc384d, 0x278dde6e), STCP(0x799aea92, 0x27f3cc94), STCP(0x7979477d, 0x28599eb0), STCP(0x79574f28, 0x28bf547b), + STCP(0x793501a9, 0x2924edac), STCP(0x79125f19, 0x298a69fc), STCP(0x78ef678f, 0x29efc925), STCP(0x78cc1b26, 0x2a550adf), + STCP(0x78a879f4, 0x2aba2ee4), STCP(0x78848414, 0x2b1f34eb), STCP(0x7860399e, 0x2b841caf), STCP(0x783b9aad, 0x2be8e5e8), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77f15fbc, 0x2cb21ba0), STCP(0x77cbc3f2, 0x2d168792), STCP(0x77a5d413, 0x2d7ad3de), + STCP(0x777f903c, 0x2ddf0040), STCP(0x7758f886, 0x2e430c6f), STCP(0x77320d0d, 0x2ea6f827), STCP(0x770acdec, 0x2f0ac320), + STCP(0x76e33b3f, 0x2f6e6d16), STCP(0x76bb5521, 0x2fd1f5c1), STCP(0x76931bae, 0x30355cdd), STCP(0x766a8f04, 0x3098a223), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x76187c77, 0x315ec617), STCP(0x75eef6ce, 0x31c1a43b), STCP(0x75c51e61, 0x32245f72), + STCP(0x759af34c, 0x3286f779), STCP(0x757075ac, 0x32e96c09), STCP(0x7545a5a0, 0x334bbcde), STCP(0x751a8346, 0x33ade9b3), + STCP(0x74ef0ebc, 0x340ff242), STCP(0x74c34820, 0x3471d647), STCP(0x74972f92, 0x34d3957e), STCP(0x746ac52f, 0x35352fa1), + STCP(0x743e0918, 0x3596a46c), STCP(0x7410fb6b, 0x35f7f39c), STCP(0x73e39c49, 0x36591cea), STCP(0x73b5ebd1, 0x36ba2014), + STCP(0x7387ea23, 0x371afcd5), STCP(0x73599760, 0x377bb2e9), STCP(0x732af3a7, 0x37dc420c), STCP(0x72fbff1b, 0x383ca9fb), + STCP(0x72ccb9db, 0x389cea72), STCP(0x729d2409, 0x38fd032d), STCP(0x726d3dc6, 0x395cf3e9), STCP(0x723d0734, 0x39bcbc63), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x71dba9ab, 0x3a7bd382), STCP(0x71aa82f7, 0x3adb21a1), STCP(0x71790c7e, 0x3b3a4672), + STCP(0x71474660, 0x3b9941b1), STCP(0x711530c2, 0x3bf8131c), STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b01790, 0x3cb5376b), + STCP(0x707d1443, 0x3d1389cb), STCP(0x7049c203, 0x3d71b14d), STCP(0x701620f5, 0x3dcfadb0), STCP(0x6fe2313c, 0x3e2d7eb1), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6f79665b, 0x3ee89d86), STCP(0x6f448b7e, 0x3f45ead8), STCP(0x6f0f6289, 0x3fa30bc1), + STCP(0x6ed9eba1, 0x40000000), STCP(0x6ea426ed, 0x405cc754), STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e37b4b6, 0x4115ce38), + STCP(0x6e010780, 0x41720d46), STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d92c59b, 0x422a0154), STCP(0x6d5b313b, 0x4285b5d4), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6ceb2261, 0x433c9283), STCP(0x6cb2a837, 0x4397ba32), STCP(0x6c79e1c2, 0x43f2b271), + STCP(0x6c40cf2c, 0x444d7aff), STCP(0x6c07709b, 0x44a8139e), STCP(0x6bcdc639, 0x45027c0c), STCP(0x6b93d02e, 0x455cb40c), + STCP(0x6b598ea3, 0x45b6bb5e), STCP(0x6b1f01c0, 0x461091c2), STCP(0x6ae429ae, 0x466a36f9), STCP(0x6aa90697, 0x46c3aac5), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a31e000, 0x4775fd1f), STCP(0x69f5dcd3, 0x47cedb31), STCP(0x69b98f48, 0x482786dc), + STCP(0x697cf78a, 0x487fffe4), STCP(0x694015c3, 0x48d84609), STCP(0x6902ea1d, 0x4930590f), STCP(0x68c574c4, 0x498838b6), + STCP(0x6887b5e2, 0x49dfe4c2), STCP(0x6849ada3, 0x4a375cf5), STCP(0x680b5c33, 0x4a8ea111), STCP(0x67ccc1be, 0x4ae5b0da), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x674eb271, 0x4b93327c), STCP(0x670f3df3, 0x4be9a3db), STCP(0x66cf8120, 0x4c3fdff4), + STCP(0x668f7c25, 0x4c95e688), STCP(0x664f2f2e, 0x4cebb75c), STCP(0x660e9a6a, 0x4d415234), STCP(0x65cdbe05, 0x4d96b6d3), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x654b2f10, 0x4e40dc79), STCP(0x65097cdb, 0x4e959d08), STCP(0x64c783bd, 0x4eea2670), + STCP(0x648543e4, 0x4f3e7875), STCP(0x6442bd7e, 0x4f9292dc), STCP(0x63fff0ba, 0x4fe6756a), STCP(0x63bcddc7, 0x503a1fe5), + STCP(0x637984d4, 0x508d9211), STCP(0x6335e611, 0x50e0cbb4), STCP(0x62f201ac, 0x5133cc94), STCP(0x62add7d6, 0x51869476), + STCP(0x626968be, 0x51d92321), STCP(0x6224b495, 0x522b7859), STCP(0x61dfbb8a, 0x527d93e6), STCP(0x619a7dce, 0x52cf758f), + STCP(0x6154fb91, 0x53211d18), STCP(0x610f3505, 0x53728a4a), STCP(0x60c92a5a, 0x53c3bcea), STCP(0x6082dbc1, 0x5414b4c1), + STCP(0x603c496c, 0x54657194), STCP(0x5ff5738d, 0x54b5f32c), STCP(0x5fae5a55, 0x55063951), STCP(0x5f66fdf5, 0x555643c8), + STCP(0x5f1f5ea1, 0x55a6125c), STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e8f57e2, 0x5644faf4), STCP(0x5e46f0dd, 0x5694148b), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5db55c86, 0x57319135), STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d22c11c, 0x57ce1917), + STCP(0x5cd91140, 0x581c00b3), STCP(0x5c8f203b, 0x5869aa79), STCP(0x5c44ee40, 0x58b71632), STCP(0x5bfa7b82, 0x590443a7), + STCP(0x5bafc837, 0x595132a2), STCP(0x5b64d492, 0x599de2ee), STCP(0x5b19a0c8, 0x59ea5454), STCP(0x5ace2d0f, 0x5a36869f), + STCP(0x5a82799a, 0x5a82799a) +}; + + +RAM_ALIGN +LNK_SECTION_CONSTDATA +LNK_SECTION_CONSTDATA_L1 +const FIXP_STP SineTable512[] = +{ + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd886, 0x006487e3), STCP(0x7fff6216, 0x00c90f88), STCP(0x7ffe9cb2, 0x012d96b1), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffc250f, 0x01f6a297), STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff871a2, 0x02bfa9a4), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff38274, 0x0388a9ea), STCP(0x7ff09478, 0x03ed26e6), STCP(0x7fed5791, 0x0451a177), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe5f108, 0x051a8e5c), STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdd4eec, 0x05e36ea9), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd37153, 0x06ac406f), STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fc85854, 0x077501be), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbc040a, 0x083db0a7), STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fae7495, 0x09064b3a), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9faa15, 0x09cecf89), STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f8fa4b0, 0x0a973ba5), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f7e648c, 0x0b5f8d9f), STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f6be9d4, 0x0c27c389), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5834b7, 0x0cefdb76), STCP(0x7f4de451, 0x0d53db92), STCP(0x7f434563, 0x0db7d376), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f2d1c0e, 0x0e7fa99e), STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f15b8ee, 0x0f475bff), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7efd1c3c, 0x100ee8ad), STCP(0x7ef05860, 0x1072a048), STCP(0x7ee34636, 0x10d64dbd), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ec8371a, 0x119d8941), STCP(0x7eba3a39, 0x120116d5), STCP(0x7eabef2c, 0x1264994e), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8e6eb2, 0x132b7bf9), STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e6fb5f4, 0x13f22f58), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e4fc53e, 0x14b8b17f), STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e2e9cdf, 0x157f0086), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e0c3d29, 0x16451a83), STCP(0x7dfa98a8, 0x16a81305), STCP(0x7de8a670, 0x170afd8d), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dc3d90d, 0x17d0a7bc), STCP(0x7db0fdf8, 0x183366e9), STCP(0x7d9dd55a, 0x18961728), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d769bb5, 0x195b49ea), STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d4e2c7f, 0x1a203e1b), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d24881b, 0x1ae4f1d6), STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7cf9aef0, 0x1ba96335), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7ccda169, 0x1c6d9053), STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7ca05ff1, 0x1d31774d), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c71eaf9, 0x1df5163f), STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4242f2, 0x1eb86b46), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c116853, 0x1f7b7481), STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bdf5b94, 0x203e300d), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bac1d31, 0x21009c0c), STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b77ada8, 0x21c2b69c), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b420d7a, 0x22847de0), STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b0b3d2c, 0x2345eff8), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ad33d45, 0x24070b08), STCP(0x7ab6cba4, 0x24677758), STCP(0x7a9a0e50, 0x24c7cd33), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5fb0d8, 0x2588349d), STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a24256f, 0x26483f6c), + STCP(0x7a05eead, 0x26a82186), STCP(0x79e76ca7, 0x2707ebc7), STCP(0x79c89f6e, 0x27679df4), STCP(0x79a98715, 0x27c737d3), + STCP(0x798a23b1, 0x2826b928), STCP(0x796a7554, 0x288621b9), STCP(0x794a7c12, 0x28e5714b), STCP(0x792a37fe, 0x2944a7a2), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78e8cfb2, 0x2a02c7b8), STCP(0x78c7aba2, 0x2a61b101), STCP(0x78a63d11, 0x2ac08026), + STCP(0x78848414, 0x2b1f34eb), STCP(0x786280bf, 0x2b7dcf17), STCP(0x78403329, 0x2bdc4e6f), STCP(0x781d9b65, 0x2c3ab2b9), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77d78daa, 0x2cf72939), STCP(0x77b417df, 0x2d553afc), STCP(0x7790583e, 0x2db330c7), + STCP(0x776c4edb, 0x2e110a62), STCP(0x7747fbce, 0x2e6ec792), STCP(0x77235f2d, 0x2ecc681e), STCP(0x76fe790e, 0x2f29ebcc), + STCP(0x76d94989, 0x2f875262), STCP(0x76b3d0b4, 0x2fe49ba7), STCP(0x768e0ea6, 0x3041c761), STCP(0x76680376, 0x309ed556), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x761b1211, 0x3158970e), STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75ccfd42, 0x3211df04), + STCP(0x75a585cf, 0x326e54c7), STCP(0x757dc5ca, 0x32caab6f), STCP(0x7555bd4c, 0x3326e2c3), STCP(0x752d6c6c, 0x3382fa88), + STCP(0x7504d345, 0x33def287), STCP(0x74dbf1ef, 0x343aca87), STCP(0x74b2c884, 0x34968250), STCP(0x7489571c, 0x34f219a8), + STCP(0x745f9dd1, 0x354d9057), STCP(0x74359cbd, 0x35a8e625), STCP(0x740b53fb, 0x36041ad9), STCP(0x73e0c3a3, 0x365f2e3b), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x738acc9e, 0x3714f02a), STCP(0x735f6626, 0x376f9e46), STCP(0x7333b883, 0x37ca2a30), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72db8828, 0x387eda8e), STCP(0x72af05a7, 0x38d8fe93), STCP(0x72823c67, 0x3932ff87), + STCP(0x72552c85, 0x398cdd32), STCP(0x7227d61c, 0x39e6975e), STCP(0x71fa3949, 0x3a402dd2), STCP(0x71cc5626, 0x3a99a057), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x716fbd68, 0x3b4c18ba), STCP(0x71410805, 0x3ba51e29), STCP(0x71120cc5, 0x3bfdfecd), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b34525, 0x3caf50da), STCP(0x708378ff, 0x3d07c1d6), STCP(0x70536771, 0x3d600d2c), + STCP(0x7023109a, 0x3db832a6), STCP(0x6ff27497, 0x3e10320d), STCP(0x6fc19385, 0x3e680b2c), STCP(0x6f906d84, 0x3ebfbdcd), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f2d532c, 0x3f6eaeb8), STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ec92683, 0x401d0321), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e63e87f, 0x40cab958), STCP(0x6e30e34a, 0x4121589b), STCP(0x6dfd9a1c, 0x4177cfb1), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d963c54, 0x42244481), STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d2dd027, 0x42d0161e), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cc45698, 0x437b42e1), STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c59d0a9, 0x4425c923), + STCP(0x6c242960, 0x447acd50), STCP(0x6bee3f62, 0x44cfa740), STCP(0x6bb812d1, 0x452456bd), STCP(0x6b81a3cd, 0x4578db93), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b13fef5, 0x4621647d), STCP(0x6adcc964, 0x46756828), STCP(0x6aa551e9, 0x46c9405c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a359db9, 0x47706d93), STCP(0x69fd614a, 0x47c3c22f), STCP(0x69c4e37a, 0x4816ea86), + STCP(0x698c246c, 0x4869e665), STCP(0x69532442, 0x48bcb599), STCP(0x6919e320, 0x490f57ee), STCP(0x68e06129, 0x4961cd33), + STCP(0x68a69e81, 0x49b41533), STCP(0x686c9b4b, 0x4a062fbd), STCP(0x683257ab, 0x4a581c9e), STCP(0x67f7d3c5, 0x4aa9dba2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x67820bb7, 0x4b4ccf4d), STCP(0x6746c7d8, 0x4b9e0390), STCP(0x670b4444, 0x4bef092d), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66937e91, 0x4c9087b1), STCP(0x66573cbb, 0x4ce10034), STCP(0x661abbc5, 0x4d31494b), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65a0fd0b, 0x4dd14c6e), STCP(0x6563bf92, 0x4e210617), STCP(0x6526438f, 0x4e708f8f), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64aa907f, 0x4f0f1126), STCP(0x646c59bf, 0x4f5e08e3), STCP(0x642de50d, 0x4faccfab), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63b0426d, 0x5049c999), STCP(0x637114cc, 0x5097fc5e), STCP(0x6331a9d4, 0x50e5fd6d), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62b21c7b, 0x518169a5), STCP(0x6271fa69, 0x51ced46e), STCP(0x62319b9d, 0x521c0cc2), + STCP(0x61f1003f, 0x5269126e), STCP(0x61b02876, 0x52b5e546), STCP(0x616f146c, 0x53028518), STCP(0x612dc447, 0x534ef1b5), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60aa7050, 0x53e73097), STCP(0x60686ccf, 0x5433027d), STCP(0x60262dd6, 0x547ea073), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fa0fe1f, 0x55153fd4), STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f1ae274, 0x55ab0d46), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e93dc1f, 0x56400758), STCP(0x5e50015d, 0x568a34a9), STCP(0x5e0bec6e, 0x56d42c99), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5d8314b1, 0x57677b9d), STCP(0x5d3e5237, 0x57b0d256), STCP(0x5cf95638, 0x57f9f2f8), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c6eb258, 0x588b9140), STCP(0x5c290acc, 0x58d40e8c), STCP(0x5be32a67, 0x591c550e), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b56bfbd, 0x59ac3cfd), STCP(0x5b1035cf, 0x59f3de12), STCP(0x5ac973b5, 0x5a3b47ab), + STCP(0x5a82799a, 0x5a82799a) +}; + + + + + + + + + + + + + + + + + + + + + +/* generate_fft_tables.m 4 15 */ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal60[] = +{ + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), + STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), + STC(0x74ef0ebc), STC(0x55a6125c), STC(0x278dde6e), + STC(0x6ed9eba1), STC(0x40000000), STC(0x00000000), + STC(0x678dde6e), STC(0x278dde6e), STC(0xd8722191), + STC(0x5f1f5ea1), STC(0x0d61304e), STC(0xb4c373ed), + STC(0x55a6125c), STC(0xf29ecfb1), STC(0x98722191), + STC(0x4b3c8c12), STC(0xd8722191), STC(0x8643c7b2), + STC(0x40000000), STC(0xbfffffff), STC(0x80000000), + STC(0x340ff242), STC(0xaa59eda3), STC(0x8643c7b2), + STC(0x278dde6e), STC(0x98722191), STC(0x98722191), + STC(0x1a9cd9ac), STC(0x8b10f143), STC(0xb4c373ed), + STC(0x0d61304e), STC(0x82cc0f35), STC(0xd8722191), +}; +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag60[] = +{ + STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), + STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), + STC(0x340ff242), STC(0x5f1f5ea1), STC(0x79bc384d), + STC(0x40000000), STC(0x6ed9eba1), STC(0x7fffffff), + STC(0x4b3c8c12), STC(0x79bc384d), STC(0x79bc384d), + STC(0x55a6125c), STC(0x7f4c7e54), STC(0x678dde6e), + STC(0x5f1f5ea1), STC(0x7f4c7e54), STC(0x4b3c8c12), + STC(0x678dde6e), STC(0x79bc384d), STC(0x278dde6e), + STC(0x6ed9eba1), STC(0x6ed9eba1), STC(0x00000000), + STC(0x74ef0ebc), STC(0x5f1f5ea1), STC(0xd8722191), + STC(0x79bc384d), STC(0x4b3c8c12), STC(0xb4c373ed), + STC(0x7d33f0ca), STC(0x340ff242), STC(0x98722191), + STC(0x7f4c7e54), STC(0x1a9cd9ac), STC(0x8643c7b2), +}; + + + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal240[] = +{ + STC(0x7ff4c56f), STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), STC(0x7ee7aa4c), STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), STC(0x7c769e18), STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), STC(0x78a879f4), STC(0x777f903c), STC(0x7641af3d), + STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), STC(0x74ef0ebc), STC(0x720c8075), STC(0x6ed9eba1), STC(0x6b598ea3), STC(0x678dde6e), STC(0x637984d4), STC(0x5f1f5ea1), STC(0x5a82799a), + STC(0x7f9afcb9), STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), STC(0x5a82799a), STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), STC(0x3a1c5c57), STC(0x30fbc54d), + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf0), STC(0xdedf047c), STC(0xcf043ab2), + STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), STC(0x00000000), STC(0xebf9f497), STC(0xd8722191), STC(0xc5e3a3a8), STC(0xb4c373ed), STC(0xa57d8665), + STC(0x7ddb4bfc), STC(0x777f903c), STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), STC(0x3a1c5c57), STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d66), STC(0xdedf047c), STC(0xc8e5032a), STC(0xb4c373ed), STC(0xa326eebf), STC(0x94a6715c), STC(0x89be50c2), + STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), STC(0x55a6125c), STC(0x40000000), STC(0x278dde6e), STC(0x0d61304e), STC(0xf29ecfb1), STC(0xd8722191), STC(0xbfffffff), STC(0xaa59eda3), STC(0x98722191), STC(0x8b10f143), STC(0x82cc0f35), STC(0x80000000), + STC(0x7c769e18), STC(0x720c8075), STC(0x6154fb91), STC(0x4b3c8c12), STC(0x30fbc54d), STC(0x14060b68), STC(0xf5f50d66), STC(0xd8722191), STC(0xbd1ec45b), STC(0xa57d8665), STC(0x92dcafe4), STC(0x8643c7b2), STC(0x80650346), STC(0x81936dae), STC(0x89be50c2), + STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047c), STC(0xbfffffff), STC(0xa57d8665), STC(0x9126145e), STC(0x845c8ae2), STC(0x80000000), STC(0x845c8ae2), STC(0x9126145e), STC(0xa57d8665), + STC(0x7aba9ae6), STC(0x6b598ea3), STC(0x53211d18), STC(0x340ff242), STC(0x10b5150f), STC(0xebf9f497), STC(0xc8e5032a), STC(0xaa59eda3), STC(0x92dcafe4), STC(0x845c8ae2), STC(0x800b3a90), STC(0x8643c7b2), STC(0x96830875), STC(0xaf726dee), STC(0xcf043ab2), + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), STC(0xd8722191), STC(0xb4c373ed), STC(0x98722191), STC(0x8643c7b2), STC(0x80000000), STC(0x8643c7b2), STC(0x98722191), STC(0xb4c373ed), STC(0xd8722191), STC(0xffffffff), + STC(0x78a879f4), STC(0x637984d4), STC(0x42e13ba4), STC(0x1a9cd9ac), STC(0xef4aeaf0), STC(0xc5e3a3a8), STC(0xa326eebf), STC(0x8b10f143), STC(0x80650346), STC(0x845c8ae2), STC(0x96830875), STC(0xb4c373ed), STC(0xdba5629a), STC(0x06b2f1d2), STC(0x30fbc54d), + STC(0x777f903c), STC(0x5f1f5ea1), STC(0x3a1c5c57), STC(0x0d61304e), STC(0xdedf047c), STC(0xb4c373ed), STC(0x94a6715c), STC(0x82cc0f35), STC(0x81936dae), STC(0x9126145e), STC(0xaf726dee), STC(0xd8722191), STC(0x06b2f1d2), STC(0x340ff242), STC(0x5a82799a), +}; +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag240[] = +{ + STC(0x0359c428), STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), STC(0x10b5150f), STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), STC(0x1de189a6), STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), STC(0x2aba2ee4), STC(0x2ddf0040), STC(0x30fbc54d), + STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), STC(0x340ff242), STC(0x3a1c5c57), STC(0x40000000), STC(0x45b6bb5e), STC(0x4b3c8c12), STC(0x508d9211), STC(0x55a6125c), STC(0x5a82799a), + STC(0x0a0af299), STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), STC(0x3a1c5c57), STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), STC(0x5a82799a), STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), STC(0x720c8075), STC(0x7641af3d), + STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), STC(0x720c8075), STC(0x79bc384d), STC(0x7e6c9251), STC(0x7fffffff), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), + STC(0x17537e63), STC(0x2ddf0040), STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), STC(0x720c8075), STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), STC(0x7ba3751d), STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), STC(0x45b6bb5e), STC(0x30fbc54d), + STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), STC(0x5f1f5ea1), STC(0x6ed9eba1), STC(0x79bc384d), STC(0x7f4c7e54), STC(0x7f4c7e54), STC(0x79bc384d), STC(0x6ed9eba1), STC(0x5f1f5ea1), STC(0x4b3c8c12), STC(0x340ff242), STC(0x1a9cd9ac), STC(0x00000000), + STC(0x1de189a6), STC(0x3a1c5c57), STC(0x53211d18), STC(0x678dde6e), STC(0x7641af3d), STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x79bc384d), STC(0x6d23501b), STC(0x5a82799a), STC(0x42e13ba4), STC(0x278dde6e), STC(0x0a0af299), STC(0xebf9f497), STC(0xcf043ab2), + STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047c), STC(0xbfffffff), STC(0xa57d8665), + STC(0x245a9d65), STC(0x45b6bb5e), STC(0x6154fb91), STC(0x74ef0ebc), STC(0x7ee7aa4c), STC(0x7e6c9251), STC(0x7387ea23), STC(0x5f1f5ea1), STC(0x42e13ba4), STC(0x2120fb83), STC(0xfca63bd7), STC(0xd8722191), STC(0xb780001b), STC(0x9c867b2b), STC(0x89be50c2), + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), STC(0x79bc384d), STC(0x7fffffff), STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), STC(0xd8722191), STC(0xb4c373ed), STC(0x98722191), STC(0x8643c7b2), STC(0x80000000), + STC(0x2aba2ee4), STC(0x508d9211), STC(0x6d23501b), STC(0x7d33f0ca), STC(0x7ee7aa4c), STC(0x720c8075), STC(0x581c00b3), STC(0x340ff242), STC(0x0a0af299), STC(0xdedf047c), STC(0xb780001b), STC(0x98722191), STC(0x85456519), STC(0x802ce84b), STC(0x89be50c2), + STC(0x2ddf0040), STC(0x55a6125c), STC(0x720c8075), STC(0x7f4c7e54), STC(0x7ba3751d), STC(0x678dde6e), STC(0x45b6bb5e), STC(0x1a9cd9ac), STC(0xebf9f497), STC(0xbfffffff), STC(0x9c867b2b), STC(0x8643c7b2), STC(0x802ce84b), STC(0x8b10f143), STC(0xa57d8665), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal480[] = +{ + STC(0x7ffd3154), STC(0x7ff4c56f), STC(0x7fe6bcb0), STC(0x7fd317b4), STC(0x7fb9d759), STC(0x7f9afcb9), STC(0x7f76892f), STC(0x7f4c7e54), STC(0x7f1cde01), STC(0x7ee7aa4c), STC(0x7eace58a), STC(0x7e6c9251), STC(0x7e26b371), STC(0x7ddb4bfc), STC(0x7d8a5f40), STC(0x7d33f0ca), STC(0x7cd80464), STC(0x7c769e18), STC(0x7c0fc22a), STC(0x7ba3751d), STC(0x7b31bbb2), STC(0x7aba9ae6), STC(0x7a3e17f2), STC(0x79bc384d), STC(0x793501a9), STC(0x78a879f4), STC(0x7816a759), STC(0x777f903c), STC(0x76e33b3f), STC(0x7641af3d), STC(0x759af34c), + STC(0x7ff4c56f), STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), STC(0x7ee7aa4c), STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), STC(0x7c769e18), STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), STC(0x78a879f4), STC(0x777f903c), STC(0x7641af3d), STC(0x74ef0ebc), STC(0x7387ea23), STC(0x720c8075), STC(0x707d1443), STC(0x6ed9eba1), STC(0x6d23501b), STC(0x6b598ea3), STC(0x697cf78a), STC(0x678dde6e), STC(0x658c9a2d), STC(0x637984d4), STC(0x6154fb91), STC(0x5f1f5ea1), STC(0x5cd91140), STC(0x5a82799a), STC(0x581c00b3), + STC(0x7fe6bcb0), STC(0x7f9afcb9), STC(0x7f1cde01), STC(0x7e6c9251), STC(0x7d8a5f40), STC(0x7c769e18), STC(0x7b31bbb2), STC(0x79bc384d), STC(0x7816a759), STC(0x7641af3d), STC(0x743e0918), STC(0x720c8075), STC(0x6fadf2fc), STC(0x6d23501b), STC(0x6a6d98a4), STC(0x678dde6e), STC(0x648543e4), STC(0x6154fb91), STC(0x5dfe47ad), STC(0x5a82799a), STC(0x56e2f15d), STC(0x53211d18), STC(0x4f3e7875), STC(0x4b3c8c12), STC(0x471cece7), STC(0x42e13ba4), STC(0x3e8b240e), STC(0x3a1c5c57), STC(0x3596a46c), STC(0x30fbc54d), STC(0x2c4d9050), + STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), STC(0x74ef0ebc), STC(0x720c8075), STC(0x6ed9eba1), STC(0x6b598ea3), STC(0x678dde6e), STC(0x637984d4), STC(0x5f1f5ea1), STC(0x5a82799a), STC(0x55a6125c), STC(0x508d9211), STC(0x4b3c8c12), STC(0x45b6bb5e), STC(0x40000000), STC(0x3a1c5c57), STC(0x340ff242), STC(0x2ddf0040), STC(0x278dde6e), STC(0x2120fb83), STC(0x1a9cd9ac), STC(0x14060b68), STC(0x0d61304e), STC(0x06b2f1d2), STC(0x00000000), STC(0xf94d0e2d), + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), STC(0x6ed9eba1), STC(0x6a6d98a4), STC(0x658c9a2d), STC(0x603c496c), STC(0x5a82799a), STC(0x54657194), STC(0x4debe4fe), STC(0x471cece7), STC(0x40000000), STC(0x389cea72), STC(0x30fbc54d), STC(0x2924edac), STC(0x2120fb83), STC(0x18f8b83c), STC(0x10b5150f), STC(0x085f2137), STC(0x00000000), STC(0xf7a0dec8), STC(0xef4aeaf0), STC(0xe70747c3), STC(0xdedf047c), STC(0xd6db1253), STC(0xcf043ab2), STC(0xc763158d), + STC(0x7f9afcb9), STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), STC(0x5a82799a), STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), STC(0x3a1c5c57), STC(0x30fbc54d), STC(0x278dde6e), STC(0x1de189a6), STC(0x14060b68), STC(0x0a0af299), STC(0x00000000), STC(0xf5f50d66), STC(0xebf9f497), STC(0xe21e7659), STC(0xd8722191), STC(0xcf043ab2), STC(0xc5e3a3a8), STC(0xbd1ec45b), STC(0xb4c373ed), STC(0xacdee2e7), STC(0xa57d8665), STC(0x9eab046e), + STC(0x7f76892f), STC(0x7ddb4bfc), STC(0x7b31bbb2), STC(0x777f903c), STC(0x72ccb9db), STC(0x6d23501b), STC(0x668f7c25), STC(0x5f1f5ea1), STC(0x56e2f15d), STC(0x4debe4fe), STC(0x444d7aff), STC(0x3a1c5c57), STC(0x2f6e6d16), STC(0x245a9d65), STC(0x18f8b83c), STC(0x0d61304e), STC(0x01aceb7c), STC(0xf5f50d66), STC(0xea52c165), STC(0xdedf047c), STC(0xd3b26faf), STC(0xc8e5032a), STC(0xbe8df2b9), STC(0xb4c373ed), STC(0xab9a8e6b), STC(0xa326eebf), STC(0x9b7abc1b), STC(0x94a6715c), STC(0x8eb8b99f), STC(0x89be50c2), STC(0x85c1e80d), + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), STC(0xf29ecfb1), STC(0xe5632653), STC(0xd8722191), STC(0xcbf00dbd), STC(0xbfffffff), STC(0xb4c373ed), STC(0xaa59eda3), STC(0xa0e0a15e), STC(0x98722191), STC(0x9126145e), STC(0x8b10f143), STC(0x8643c7b2), STC(0x82cc0f35), STC(0x80b381ab), STC(0x80000000), STC(0x80b381ab), + STC(0x7f1cde01), STC(0x7c769e18), STC(0x7816a759), STC(0x720c8075), STC(0x6a6d98a4), STC(0x6154fb91), STC(0x56e2f15d), STC(0x4b3c8c12), STC(0x3e8b240e), STC(0x30fbc54d), STC(0x22be8f87), STC(0x14060b68), STC(0x05067734), STC(0xf5f50d66), STC(0xe70747c3), STC(0xd8722191), STC(0xca695b93), STC(0xbd1ec45b), STC(0xb0c1878a), STC(0xa57d8665), STC(0x9b7abc1b), STC(0x92dcafe4), STC(0x8bc1f6e7), STC(0x8643c7b2), STC(0x8275a0bf), STC(0x80650346), STC(0x8019434f), STC(0x81936dae), STC(0x84ce444d), STC(0x89be50c2), STC(0x90520d03), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf0), STC(0xdedf047c), STC(0xcf043ab2), STC(0xbfffffff), STC(0xb2141b01), STC(0xa57d8665), STC(0x9a7365d2), STC(0x9126145e), STC(0x89be50c2), STC(0x845c8ae2), STC(0x811855b3), STC(0x80000000), STC(0x811855b3), STC(0x845c8ae2), STC(0x89be50c2), STC(0x9126145e), STC(0x9a7365d2), STC(0xa57d8665), STC(0xb2141b01), + STC(0x7eace58a), STC(0x7aba9ae6), STC(0x743e0918), STC(0x6b598ea3), STC(0x603c496c), STC(0x53211d18), STC(0x444d7aff), STC(0x340ff242), STC(0x22be8f87), STC(0x10b5150f), STC(0xfe531483), STC(0xebf9f497), STC(0xda0aecf8), STC(0xc8e5032a), STC(0xb8e31318), STC(0xaa59eda3), STC(0x9d969741), STC(0x92dcafe4), STC(0x8a650cb3), STC(0x845c8ae2), STC(0x80e321fe), STC(0x800b3a90), STC(0x81d94c8e), STC(0x8643c7b2), STC(0x8d334624), STC(0x96830875), STC(0xa201b852), STC(0xaf726dee), STC(0xbe8df2b9), STC(0xcf043ab2), STC(0xe07e0c83), + STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), STC(0x00000000), STC(0xebf9f497), STC(0xd8722191), STC(0xc5e3a3a8), STC(0xb4c373ed), STC(0xa57d8665), STC(0x98722191), STC(0x8df37f8a), STC(0x8643c7b2), STC(0x81936dae), STC(0x80000000), STC(0x81936dae), STC(0x8643c7b2), STC(0x8df37f8a), STC(0x98722191), STC(0xa57d8665), STC(0xb4c373ed), STC(0xc5e3a3a8), STC(0xd8722191), STC(0xebf9f497), STC(0xffffffff), STC(0x14060b68), + STC(0x7e26b371), STC(0x78a879f4), STC(0x6fadf2fc), STC(0x637984d4), STC(0x54657194), STC(0x42e13ba4), STC(0x2f6e6d16), STC(0x1a9cd9ac), STC(0x05067734), STC(0xef4aeaf0), STC(0xda0aecf8), STC(0xc5e3a3a8), STC(0xb36a1977), STC(0xa326eebf), STC(0x9592675b), STC(0x8b10f143), STC(0x83f03dd5), STC(0x80650346), STC(0x808976d0), STC(0x845c8ae2), STC(0x8bc1f6e7), STC(0x96830875), STC(0xa45037c8), STC(0xb4c373ed), STC(0xc763158d), STC(0xdba5629a), STC(0xf0f488d8), STC(0x06b2f1d2), STC(0x1c3fd045), STC(0x30fbc54d), STC(0x444d7aff), + STC(0x7ddb4bfc), STC(0x777f903c), STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), STC(0x3a1c5c57), STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d66), STC(0xdedf047c), STC(0xc8e5032a), STC(0xb4c373ed), STC(0xa326eebf), STC(0x94a6715c), STC(0x89be50c2), STC(0x82cc0f35), STC(0x800b3a90), STC(0x81936dae), STC(0x8757860b), STC(0x9126145e), STC(0x9eab046e), STC(0xaf726dee), STC(0xc2ec7634), STC(0xd8722191), STC(0xef4aeaf0), STC(0x06b2f1d2), STC(0x1de189a6), STC(0x340ff242), STC(0x487fffe4), STC(0x5a82799a), STC(0x697cf78a), +}; +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag480[] = +{ + STC(0x01aceb7c), STC(0x0359c428), STC(0x05067734), STC(0x06b2f1d2), STC(0x085f2137), STC(0x0a0af299), STC(0x0bb65336), STC(0x0d61304e), STC(0x0f0b7727), STC(0x10b5150f), STC(0x125df75b), STC(0x14060b68), STC(0x15ad3e9a), STC(0x17537e63), STC(0x18f8b83c), STC(0x1a9cd9ac), STC(0x1c3fd045), STC(0x1de189a6), STC(0x1f81f37c), STC(0x2120fb83), STC(0x22be8f87), STC(0x245a9d65), STC(0x25f51307), STC(0x278dde6e), STC(0x2924edac), STC(0x2aba2ee4), STC(0x2c4d9050), STC(0x2ddf0040), STC(0x2f6e6d16), STC(0x30fbc54d), STC(0x3286f779), + STC(0x0359c428), STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), STC(0x10b5150f), STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), STC(0x1de189a6), STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), STC(0x2aba2ee4), STC(0x2ddf0040), STC(0x30fbc54d), STC(0x340ff242), STC(0x371afcd5), STC(0x3a1c5c57), STC(0x3d1389cb), STC(0x40000000), STC(0x42e13ba4), STC(0x45b6bb5e), STC(0x487fffe4), STC(0x4b3c8c12), STC(0x4debe4fe), STC(0x508d9211), STC(0x53211d18), STC(0x55a6125c), STC(0x581c00b3), STC(0x5a82799a), STC(0x5cd91140), + STC(0x05067734), STC(0x0a0af299), STC(0x0f0b7727), STC(0x14060b68), STC(0x18f8b83c), STC(0x1de189a6), STC(0x22be8f87), STC(0x278dde6e), STC(0x2c4d9050), STC(0x30fbc54d), STC(0x3596a46c), STC(0x3a1c5c57), STC(0x3e8b240e), STC(0x42e13ba4), STC(0x471cece7), STC(0x4b3c8c12), STC(0x4f3e7875), STC(0x53211d18), STC(0x56e2f15d), STC(0x5a82799a), STC(0x5dfe47ad), STC(0x6154fb91), STC(0x648543e4), STC(0x678dde6e), STC(0x6a6d98a4), STC(0x6d23501b), STC(0x6fadf2fc), STC(0x720c8075), STC(0x743e0918), STC(0x7641af3d), STC(0x7816a759), + STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), STC(0x340ff242), STC(0x3a1c5c57), STC(0x40000000), STC(0x45b6bb5e), STC(0x4b3c8c12), STC(0x508d9211), STC(0x55a6125c), STC(0x5a82799a), STC(0x5f1f5ea1), STC(0x637984d4), STC(0x678dde6e), STC(0x6b598ea3), STC(0x6ed9eba1), STC(0x720c8075), STC(0x74ef0ebc), STC(0x777f903c), STC(0x79bc384d), STC(0x7ba3751d), STC(0x7d33f0ca), STC(0x7e6c9251), STC(0x7f4c7e54), STC(0x7fd317b4), STC(0x7fffffff), STC(0x7fd317b4), + STC(0x085f2137), STC(0x10b5150f), STC(0x18f8b83c), STC(0x2120fb83), STC(0x2924edac), STC(0x30fbc54d), STC(0x389cea72), STC(0x40000000), STC(0x471cece7), STC(0x4debe4fe), STC(0x54657194), STC(0x5a82799a), STC(0x603c496c), STC(0x658c9a2d), STC(0x6a6d98a4), STC(0x6ed9eba1), STC(0x72ccb9db), STC(0x7641af3d), STC(0x793501a9), STC(0x7ba3751d), STC(0x7d8a5f40), STC(0x7ee7aa4c), STC(0x7fb9d759), STC(0x7fffffff), STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), + STC(0x0a0af299), STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), STC(0x3a1c5c57), STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), STC(0x5a82799a), STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), STC(0x720c8075), STC(0x7641af3d), STC(0x79bc384d), STC(0x7c769e18), STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x7fffffff), STC(0x7f9afcb9), STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), STC(0x5a82799a), STC(0x53211d18), + STC(0x0bb65336), STC(0x17537e63), STC(0x22be8f87), STC(0x2ddf0040), STC(0x389cea72), STC(0x42e13ba4), STC(0x4c95e688), STC(0x55a6125c), STC(0x5dfe47ad), STC(0x658c9a2d), STC(0x6c40cf2c), STC(0x720c8075), STC(0x76e33b3f), STC(0x7aba9ae6), STC(0x7d8a5f40), STC(0x7f4c7e54), STC(0x7ffd3154), STC(0x7f9afcb9), STC(0x7e26b371), STC(0x7ba3751d), STC(0x7816a759), STC(0x7387ea23), STC(0x6e010780), STC(0x678dde6e), STC(0x603c496c), STC(0x581c00b3), STC(0x4f3e7875), STC(0x45b6bb5e), STC(0x3b9941b1), STC(0x30fbc54d), STC(0x25f51307), + STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), STC(0xf29ecfb1), + STC(0x0f0b7727), STC(0x1de189a6), STC(0x2c4d9050), STC(0x3a1c5c57), STC(0x471cece7), STC(0x53211d18), STC(0x5dfe47ad), STC(0x678dde6e), STC(0x6fadf2fc), STC(0x7641af3d), STC(0x7b31bbb2), STC(0x7e6c9251), STC(0x7fe6bcb0), STC(0x7f9afcb9), STC(0x7d8a5f40), STC(0x79bc384d), STC(0x743e0918), STC(0x6d23501b), STC(0x648543e4), STC(0x5a82799a), STC(0x4f3e7875), STC(0x42e13ba4), STC(0x3596a46c), STC(0x278dde6e), STC(0x18f8b83c), STC(0x0a0af299), STC(0xfaf988cb), STC(0xebf9f497), STC(0xdd417078), STC(0xcf043ab2), STC(0xc174dbf1), + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf0), STC(0xdedf047c), STC(0xcf043ab2), STC(0xbfffffff), STC(0xb2141b01), STC(0xa57d8665), STC(0x9a7365d2), + STC(0x125df75b), STC(0x245a9d65), STC(0x3596a46c), STC(0x45b6bb5e), STC(0x54657194), STC(0x6154fb91), STC(0x6c40cf2c), STC(0x74ef0ebc), STC(0x7b31bbb2), STC(0x7ee7aa4c), STC(0x7ffd3154), STC(0x7e6c9251), STC(0x7a3e17f2), STC(0x7387ea23), STC(0x6a6d98a4), STC(0x5f1f5ea1), STC(0x51d92321), STC(0x42e13ba4), STC(0x3286f779), STC(0x2120fb83), STC(0x0f0b7727), STC(0xfca63bd7), STC(0xea52c165), STC(0xd8722191), STC(0xc763158d), STC(0xb780001b), STC(0xa91d0ea2), STC(0x9c867b2b), STC(0x91fef87f), STC(0x89be50c2), STC(0x83f03dd5), + STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), STC(0x720c8075), STC(0x79bc384d), STC(0x7e6c9251), STC(0x7fffffff), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), STC(0x00000000), STC(0xebf9f497), STC(0xd8722191), STC(0xc5e3a3a8), STC(0xb4c373ed), STC(0xa57d8665), STC(0x98722191), STC(0x8df37f8a), STC(0x8643c7b2), STC(0x81936dae), STC(0x80000000), STC(0x81936dae), + STC(0x15ad3e9a), STC(0x2aba2ee4), STC(0x3e8b240e), STC(0x508d9211), STC(0x603c496c), STC(0x6d23501b), STC(0x76e33b3f), STC(0x7d33f0ca), STC(0x7fe6bcb0), STC(0x7ee7aa4c), STC(0x7a3e17f2), STC(0x720c8075), STC(0x668f7c25), STC(0x581c00b3), STC(0x471cece7), STC(0x340ff242), STC(0x1f81f37c), STC(0x0a0af299), STC(0xf449acc9), STC(0xdedf047c), STC(0xca695b93), STC(0xb780001b), STC(0xa6aecd5d), STC(0x98722191), STC(0x8d334624), STC(0x85456519), STC(0x80e321fe), STC(0x802ce84b), STC(0x8327fb9b), STC(0x89be50c2), STC(0x93bf30d3), + STC(0x17537e63), STC(0x2ddf0040), STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), STC(0x720c8075), STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), STC(0x7ba3751d), STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), STC(0x45b6bb5e), STC(0x30fbc54d), STC(0x1a9cd9ac), STC(0x0359c428), STC(0xebf9f497), STC(0xd545d11b), STC(0xbfffffff), STC(0xacdee2e7), STC(0x9c867b2b), STC(0x8f82ebbc), STC(0x8643c7b2), STC(0x811855b3), STC(0x802ce84b), STC(0x838961e7), STC(0x8b10f143), STC(0x96830875), STC(0xa57d8665), STC(0xb780001b), +}; + + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow1024[] = +{ + WTCP(0x7ffffd88, 0x001921fb), WTCP(0x7fffe9cb, 0x004b65ee), WTCP(0x7fffc251, 0x007da9d4), WTCP(0x7fff8719, 0x00afeda8), + WTCP(0x7fff3824, 0x00e23160), WTCP(0x7ffed572, 0x011474f6), WTCP(0x7ffe5f03, 0x0146b860), WTCP(0x7ffdd4d7, 0x0178fb99), + WTCP(0x7ffd36ee, 0x01ab3e97), WTCP(0x7ffc8549, 0x01dd8154), WTCP(0x7ffbbfe6, 0x020fc3c6), WTCP(0x7ffae6c7, 0x024205e8), + WTCP(0x7ff9f9ec, 0x027447b0), WTCP(0x7ff8f954, 0x02a68917), WTCP(0x7ff7e500, 0x02d8ca16), WTCP(0x7ff6bcf0, 0x030b0aa4), + WTCP(0x7ff58125, 0x033d4abb), WTCP(0x7ff4319d, 0x036f8a51), WTCP(0x7ff2ce5b, 0x03a1c960), WTCP(0x7ff1575d, 0x03d407df), + WTCP(0x7fefcca4, 0x040645c7), WTCP(0x7fee2e30, 0x04388310), WTCP(0x7fec7c02, 0x046abfb3), WTCP(0x7feab61a, 0x049cfba7), + WTCP(0x7fe8dc78, 0x04cf36e5), WTCP(0x7fe6ef1c, 0x05017165), WTCP(0x7fe4ee06, 0x0533ab20), WTCP(0x7fe2d938, 0x0565e40d), + WTCP(0x7fe0b0b1, 0x05981c26), WTCP(0x7fde7471, 0x05ca5361), WTCP(0x7fdc247a, 0x05fc89b8), WTCP(0x7fd9c0ca, 0x062ebf22), + WTCP(0x7fd74964, 0x0660f398), WTCP(0x7fd4be46, 0x06932713), WTCP(0x7fd21f72, 0x06c5598a), WTCP(0x7fcf6ce8, 0x06f78af6), + WTCP(0x7fcca6a7, 0x0729bb4e), WTCP(0x7fc9ccb2, 0x075bea8c), WTCP(0x7fc6df08, 0x078e18a7), WTCP(0x7fc3dda9, 0x07c04598), + WTCP(0x7fc0c896, 0x07f27157), WTCP(0x7fbd9fd0, 0x08249bdd), WTCP(0x7fba6357, 0x0856c520), WTCP(0x7fb7132b, 0x0888ed1b), + WTCP(0x7fb3af4e, 0x08bb13c5), WTCP(0x7fb037bf, 0x08ed3916), WTCP(0x7facac7f, 0x091f5d06), WTCP(0x7fa90d8e, 0x09517f8f), + WTCP(0x7fa55aee, 0x0983a0a7), WTCP(0x7fa1949e, 0x09b5c048), WTCP(0x7f9dbaa0, 0x09e7de6a), WTCP(0x7f99ccf4, 0x0a19fb04), + WTCP(0x7f95cb9a, 0x0a4c1610), WTCP(0x7f91b694, 0x0a7e2f85), WTCP(0x7f8d8de1, 0x0ab0475c), WTCP(0x7f895182, 0x0ae25d8d), + WTCP(0x7f850179, 0x0b147211), WTCP(0x7f809dc5, 0x0b4684df), WTCP(0x7f7c2668, 0x0b7895f0), WTCP(0x7f779b62, 0x0baaa53b), + WTCP(0x7f72fcb4, 0x0bdcb2bb), WTCP(0x7f6e4a5e, 0x0c0ebe66), WTCP(0x7f698461, 0x0c40c835), WTCP(0x7f64aabf, 0x0c72d020), + WTCP(0x7f5fbd77, 0x0ca4d620), WTCP(0x7f5abc8a, 0x0cd6da2d), WTCP(0x7f55a7fa, 0x0d08dc3f), WTCP(0x7f507fc7, 0x0d3adc4e), + WTCP(0x7f4b43f2, 0x0d6cda53), WTCP(0x7f45f47b, 0x0d9ed646), WTCP(0x7f409164, 0x0dd0d01f), WTCP(0x7f3b1aad, 0x0e02c7d7), + WTCP(0x7f359057, 0x0e34bd66), WTCP(0x7f2ff263, 0x0e66b0c3), WTCP(0x7f2a40d2, 0x0e98a1e9), WTCP(0x7f247ba5, 0x0eca90ce), + WTCP(0x7f1ea2dc, 0x0efc7d6b), WTCP(0x7f18b679, 0x0f2e67b8), WTCP(0x7f12b67c, 0x0f604faf), WTCP(0x7f0ca2e7, 0x0f923546), + WTCP(0x7f067bba, 0x0fc41876), WTCP(0x7f0040f6, 0x0ff5f938), WTCP(0x7ef9f29d, 0x1027d784), WTCP(0x7ef390ae, 0x1059b352), + WTCP(0x7eed1b2c, 0x108b8c9b), WTCP(0x7ee69217, 0x10bd6356), WTCP(0x7edff570, 0x10ef377d), WTCP(0x7ed94538, 0x11210907), + WTCP(0x7ed28171, 0x1152d7ed), WTCP(0x7ecbaa1a, 0x1184a427), WTCP(0x7ec4bf36, 0x11b66dad), WTCP(0x7ebdc0c6, 0x11e83478), + WTCP(0x7eb6aeca, 0x1219f880), WTCP(0x7eaf8943, 0x124bb9be), WTCP(0x7ea85033, 0x127d7829), WTCP(0x7ea1039b, 0x12af33ba), + WTCP(0x7e99a37c, 0x12e0ec6a), WTCP(0x7e922fd6, 0x1312a230), WTCP(0x7e8aa8ac, 0x13445505), WTCP(0x7e830dff, 0x137604e2), + WTCP(0x7e7b5fce, 0x13a7b1bf), WTCP(0x7e739e1d, 0x13d95b93), WTCP(0x7e6bc8eb, 0x140b0258), WTCP(0x7e63e03b, 0x143ca605), + WTCP(0x7e5be40c, 0x146e4694), WTCP(0x7e53d462, 0x149fe3fc), WTCP(0x7e4bb13c, 0x14d17e36), WTCP(0x7e437a9c, 0x1503153a), + WTCP(0x7e3b3083, 0x1534a901), WTCP(0x7e32d2f4, 0x15663982), WTCP(0x7e2a61ed, 0x1597c6b7), WTCP(0x7e21dd73, 0x15c95097), + WTCP(0x7e194584, 0x15fad71b), WTCP(0x7e109a24, 0x162c5a3b), WTCP(0x7e07db52, 0x165dd9f0), WTCP(0x7dff0911, 0x168f5632), + WTCP(0x7df62362, 0x16c0cef9), WTCP(0x7ded2a47, 0x16f2443e), WTCP(0x7de41dc0, 0x1723b5f9), WTCP(0x7ddafdce, 0x17552422), + WTCP(0x7dd1ca75, 0x17868eb3), WTCP(0x7dc883b4, 0x17b7f5a3), WTCP(0x7dbf298d, 0x17e958ea), WTCP(0x7db5bc02, 0x181ab881), + WTCP(0x7dac3b15, 0x184c1461), WTCP(0x7da2a6c6, 0x187d6c82), WTCP(0x7d98ff17, 0x18aec0db), WTCP(0x7d8f4409, 0x18e01167), + WTCP(0x7d85759f, 0x19115e1c), WTCP(0x7d7b93da, 0x1942a6f3), WTCP(0x7d719eba, 0x1973ebe6), WTCP(0x7d679642, 0x19a52ceb), + WTCP(0x7d5d7a74, 0x19d669fc), WTCP(0x7d534b50, 0x1a07a311), WTCP(0x7d4908d9, 0x1a38d823), WTCP(0x7d3eb30f, 0x1a6a0929), + WTCP(0x7d3449f5, 0x1a9b361d), WTCP(0x7d29cd8c, 0x1acc5ef6), WTCP(0x7d1f3dd6, 0x1afd83ad), WTCP(0x7d149ad5, 0x1b2ea43a), + WTCP(0x7d09e489, 0x1b5fc097), WTCP(0x7cff1af5, 0x1b90d8bb), WTCP(0x7cf43e1a, 0x1bc1ec9e), WTCP(0x7ce94dfb, 0x1bf2fc3a), + WTCP(0x7cde4a98, 0x1c240786), WTCP(0x7cd333f3, 0x1c550e7c), WTCP(0x7cc80a0f, 0x1c861113), WTCP(0x7cbcccec, 0x1cb70f43), + WTCP(0x7cb17c8d, 0x1ce80906), WTCP(0x7ca618f3, 0x1d18fe54), WTCP(0x7c9aa221, 0x1d49ef26), WTCP(0x7c8f1817, 0x1d7adb73), + WTCP(0x7c837ad8, 0x1dabc334), WTCP(0x7c77ca65, 0x1ddca662), WTCP(0x7c6c06c0, 0x1e0d84f5), WTCP(0x7c602fec, 0x1e3e5ee5), + WTCP(0x7c5445e9, 0x1e6f342c), WTCP(0x7c4848ba, 0x1ea004c1), WTCP(0x7c3c3860, 0x1ed0d09d), WTCP(0x7c3014de, 0x1f0197b8), + WTCP(0x7c23de35, 0x1f325a0b), WTCP(0x7c179467, 0x1f63178f), WTCP(0x7c0b3777, 0x1f93d03c), WTCP(0x7bfec765, 0x1fc4840a), + WTCP(0x7bf24434, 0x1ff532f2), WTCP(0x7be5ade6, 0x2025dcec), WTCP(0x7bd9047c, 0x205681f1), WTCP(0x7bcc47fa, 0x208721f9), + WTCP(0x7bbf7860, 0x20b7bcfe), WTCP(0x7bb295b0, 0x20e852f6), WTCP(0x7ba59fee, 0x2118e3dc), WTCP(0x7b989719, 0x21496fa7), + WTCP(0x7b8b7b36, 0x2179f64f), WTCP(0x7b7e4c45, 0x21aa77cf), WTCP(0x7b710a49, 0x21daf41d), WTCP(0x7b63b543, 0x220b6b32), + WTCP(0x7b564d36, 0x223bdd08), WTCP(0x7b48d225, 0x226c4996), WTCP(0x7b3b4410, 0x229cb0d5), WTCP(0x7b2da2fa, 0x22cd12bd), + WTCP(0x7b1feee5, 0x22fd6f48), WTCP(0x7b1227d3, 0x232dc66d), WTCP(0x7b044dc7, 0x235e1826), WTCP(0x7af660c2, 0x238e646a), + WTCP(0x7ae860c7, 0x23beab33), WTCP(0x7ada4dd8, 0x23eeec78), WTCP(0x7acc27f7, 0x241f2833), WTCP(0x7abdef25, 0x244f5e5c), + WTCP(0x7aafa367, 0x247f8eec), WTCP(0x7aa144bc, 0x24afb9da), WTCP(0x7a92d329, 0x24dfdf20), WTCP(0x7a844eae, 0x250ffeb7), + WTCP(0x7a75b74f, 0x25401896), WTCP(0x7a670d0d, 0x25702cb7), WTCP(0x7a584feb, 0x25a03b11), WTCP(0x7a497feb, 0x25d0439f), + WTCP(0x7a3a9d0f, 0x26004657), WTCP(0x7a2ba75a, 0x26304333), WTCP(0x7a1c9ece, 0x26603a2c), WTCP(0x7a0d836d, 0x26902b39), + WTCP(0x79fe5539, 0x26c01655), WTCP(0x79ef1436, 0x26effb76), WTCP(0x79dfc064, 0x271fda96), WTCP(0x79d059c8, 0x274fb3ae), + WTCP(0x79c0e062, 0x277f86b5), WTCP(0x79b15435, 0x27af53a6), WTCP(0x79a1b545, 0x27df1a77), WTCP(0x79920392, 0x280edb23), + WTCP(0x79823f20, 0x283e95a1), WTCP(0x797267f2, 0x286e49ea), WTCP(0x79627e08, 0x289df7f8), WTCP(0x79528167, 0x28cd9fc1), + WTCP(0x79427210, 0x28fd4140), WTCP(0x79325006, 0x292cdc6d), WTCP(0x79221b4b, 0x295c7140), WTCP(0x7911d3e2, 0x298bffb2), + WTCP(0x790179cd, 0x29bb87bc), WTCP(0x78f10d0f, 0x29eb0957), WTCP(0x78e08dab, 0x2a1a847b), WTCP(0x78cffba3, 0x2a49f920), + WTCP(0x78bf56f9, 0x2a796740), WTCP(0x78ae9fb0, 0x2aa8ced3), WTCP(0x789dd5cb, 0x2ad82fd2), WTCP(0x788cf94c, 0x2b078a36), + WTCP(0x787c0a36, 0x2b36ddf7), WTCP(0x786b088c, 0x2b662b0e), WTCP(0x7859f44f, 0x2b957173), WTCP(0x7848cd83, 0x2bc4b120), + WTCP(0x7837942b, 0x2bf3ea0d), WTCP(0x78264849, 0x2c231c33), WTCP(0x7814e9df, 0x2c52478a), WTCP(0x780378f1, 0x2c816c0c), + WTCP(0x77f1f581, 0x2cb089b1), WTCP(0x77e05f91, 0x2cdfa071), WTCP(0x77ceb725, 0x2d0eb046), WTCP(0x77bcfc3f, 0x2d3db928), + WTCP(0x77ab2ee2, 0x2d6cbb10), WTCP(0x77994f11, 0x2d9bb5f6), WTCP(0x77875cce, 0x2dcaa9d5), WTCP(0x7775581d, 0x2df996a3), + WTCP(0x776340ff, 0x2e287c5a), WTCP(0x77511778, 0x2e575af3), WTCP(0x773edb8b, 0x2e863267), WTCP(0x772c8d3a, 0x2eb502ae), + WTCP(0x771a2c88, 0x2ee3cbc1), WTCP(0x7707b979, 0x2f128d99), WTCP(0x76f5340e, 0x2f41482e), WTCP(0x76e29c4b, 0x2f6ffb7a), + WTCP(0x76cff232, 0x2f9ea775), WTCP(0x76bd35c7, 0x2fcd4c19), WTCP(0x76aa670d, 0x2ffbe95d), WTCP(0x76978605, 0x302a7f3a), + WTCP(0x768492b4, 0x30590dab), WTCP(0x76718d1c, 0x308794a6), WTCP(0x765e7540, 0x30b61426), WTCP(0x764b4b23, 0x30e48c22), + WTCP(0x76380ec8, 0x3112fc95), WTCP(0x7624c031, 0x31416576), WTCP(0x76115f63, 0x316fc6be), WTCP(0x75fdec60, 0x319e2067), + WTCP(0x75ea672a, 0x31cc7269), WTCP(0x75d6cfc5, 0x31fabcbd), WTCP(0x75c32634, 0x3228ff5c), WTCP(0x75af6a7b, 0x32573a3f), + WTCP(0x759b9c9b, 0x32856d5e), WTCP(0x7587bc98, 0x32b398b3), WTCP(0x7573ca75, 0x32e1bc36), WTCP(0x755fc635, 0x330fd7e1), + WTCP(0x754bafdc, 0x333debab), WTCP(0x7537876c, 0x336bf78f), WTCP(0x75234ce8, 0x3399fb85), WTCP(0x750f0054, 0x33c7f785), + WTCP(0x74faa1b3, 0x33f5eb89), WTCP(0x74e63108, 0x3423d78a), WTCP(0x74d1ae55, 0x3451bb81), WTCP(0x74bd199f, 0x347f9766), + WTCP(0x74a872e8, 0x34ad6b32), WTCP(0x7493ba34, 0x34db36df), WTCP(0x747eef85, 0x3508fa66), WTCP(0x746a12df, 0x3536b5be), + WTCP(0x74552446, 0x356468e2), WTCP(0x744023bc, 0x359213c9), WTCP(0x742b1144, 0x35bfb66e), WTCP(0x7415ece2, 0x35ed50c9), + WTCP(0x7400b69a, 0x361ae2d3), WTCP(0x73eb6e6e, 0x36486c86), WTCP(0x73d61461, 0x3675edd9), WTCP(0x73c0a878, 0x36a366c6), + WTCP(0x73ab2ab4, 0x36d0d746), WTCP(0x73959b1b, 0x36fe3f52), WTCP(0x737ff9ae, 0x372b9ee3), WTCP(0x736a4671, 0x3758f5f2), + WTCP(0x73548168, 0x37864477), WTCP(0x733eaa96, 0x37b38a6d), WTCP(0x7328c1ff, 0x37e0c7cc), WTCP(0x7312c7a5, 0x380dfc8d), + WTCP(0x72fcbb8c, 0x383b28a9), WTCP(0x72e69db7, 0x38684c19), WTCP(0x72d06e2b, 0x389566d6), WTCP(0x72ba2cea, 0x38c278d9), + WTCP(0x72a3d9f7, 0x38ef821c), WTCP(0x728d7557, 0x391c8297), WTCP(0x7276ff0d, 0x39497a43), WTCP(0x7260771b, 0x39766919), + WTCP(0x7249dd86, 0x39a34f13), WTCP(0x72333251, 0x39d02c2a), WTCP(0x721c7580, 0x39fd0056), WTCP(0x7205a716, 0x3a29cb91), + WTCP(0x71eec716, 0x3a568dd4), WTCP(0x71d7d585, 0x3a834717), WTCP(0x71c0d265, 0x3aaff755), WTCP(0x71a9bdba, 0x3adc9e86), + WTCP(0x71929789, 0x3b093ca3), WTCP(0x717b5fd3, 0x3b35d1a5), WTCP(0x7164169d, 0x3b625d86), WTCP(0x714cbbeb, 0x3b8ee03e), + WTCP(0x71354fc0, 0x3bbb59c7), WTCP(0x711dd220, 0x3be7ca1a), WTCP(0x7106430e, 0x3c143130), WTCP(0x70eea28e, 0x3c408f03), + WTCP(0x70d6f0a4, 0x3c6ce38a), WTCP(0x70bf2d53, 0x3c992ec0), WTCP(0x70a7589f, 0x3cc5709e), WTCP(0x708f728b, 0x3cf1a91c), + WTCP(0x70777b1c, 0x3d1dd835), WTCP(0x705f7255, 0x3d49fde1), WTCP(0x70475839, 0x3d761a19), WTCP(0x702f2ccd, 0x3da22cd7), + WTCP(0x7016f014, 0x3dce3614), WTCP(0x6ffea212, 0x3dfa35c8), WTCP(0x6fe642ca, 0x3e262bee), WTCP(0x6fcdd241, 0x3e52187f), + WTCP(0x6fb5507a, 0x3e7dfb73), WTCP(0x6f9cbd79, 0x3ea9d4c3), WTCP(0x6f841942, 0x3ed5a46b), WTCP(0x6f6b63d8, 0x3f016a61), + WTCP(0x6f529d40, 0x3f2d26a0), WTCP(0x6f39c57d, 0x3f58d921), WTCP(0x6f20dc92, 0x3f8481dd), WTCP(0x6f07e285, 0x3fb020ce), + WTCP(0x6eeed758, 0x3fdbb5ec), WTCP(0x6ed5bb10, 0x40074132), WTCP(0x6ebc8db0, 0x4032c297), WTCP(0x6ea34f3d, 0x405e3a16), + WTCP(0x6e89ffb9, 0x4089a7a8), WTCP(0x6e709f2a, 0x40b50b46), WTCP(0x6e572d93, 0x40e064ea), WTCP(0x6e3daaf8, 0x410bb48c), + WTCP(0x6e24175c, 0x4136fa27), WTCP(0x6e0a72c5, 0x416235b2), WTCP(0x6df0bd35, 0x418d6729), WTCP(0x6dd6f6b1, 0x41b88e84), + WTCP(0x6dbd1f3c, 0x41e3abbc), WTCP(0x6da336dc, 0x420ebecb), WTCP(0x6d893d93, 0x4239c7aa), WTCP(0x6d6f3365, 0x4264c653), + WTCP(0x6d551858, 0x428fbabe), WTCP(0x6d3aec6e, 0x42baa4e6), WTCP(0x6d20afac, 0x42e584c3), WTCP(0x6d066215, 0x43105a50), + WTCP(0x6cec03af, 0x433b2585), WTCP(0x6cd1947c, 0x4365e65b), WTCP(0x6cb71482, 0x43909ccd), WTCP(0x6c9c83c3, 0x43bb48d4), + WTCP(0x6c81e245, 0x43e5ea68), WTCP(0x6c67300b, 0x44108184), WTCP(0x6c4c6d1a, 0x443b0e21), WTCP(0x6c319975, 0x44659039), + WTCP(0x6c16b521, 0x449007c4), WTCP(0x6bfbc021, 0x44ba74bd), WTCP(0x6be0ba7b, 0x44e4d71c), WTCP(0x6bc5a431, 0x450f2edb), + WTCP(0x6baa7d49, 0x45397bf4), WTCP(0x6b8f45c7, 0x4563be60), WTCP(0x6b73fdae, 0x458df619), WTCP(0x6b58a503, 0x45b82318), + WTCP(0x6b3d3bcb, 0x45e24556), WTCP(0x6b21c208, 0x460c5cce), WTCP(0x6b0637c1, 0x46366978), WTCP(0x6aea9cf8, 0x46606b4e), + WTCP(0x6acef1b2, 0x468a624a), WTCP(0x6ab335f4, 0x46b44e65), WTCP(0x6a9769c1, 0x46de2f99), WTCP(0x6a7b8d1e, 0x470805df), + WTCP(0x6a5fa010, 0x4731d131), WTCP(0x6a43a29a, 0x475b9188), WTCP(0x6a2794c1, 0x478546de), WTCP(0x6a0b7689, 0x47aef12c), + WTCP(0x69ef47f6, 0x47d8906d), WTCP(0x69d3090e, 0x48022499), WTCP(0x69b6b9d3, 0x482badab), WTCP(0x699a5a4c, 0x48552b9b), + WTCP(0x697dea7b, 0x487e9e64), WTCP(0x69616a65, 0x48a805ff), WTCP(0x6944da10, 0x48d16265), WTCP(0x6928397e, 0x48fab391), + WTCP(0x690b88b5, 0x4923f97b), WTCP(0x68eec7b9, 0x494d341e), WTCP(0x68d1f68f, 0x49766373), WTCP(0x68b5153a, 0x499f8774), + WTCP(0x689823bf, 0x49c8a01b), WTCP(0x687b2224, 0x49f1ad61), WTCP(0x685e106c, 0x4a1aaf3f), WTCP(0x6840ee9b, 0x4a43a5b0), + WTCP(0x6823bcb7, 0x4a6c90ad), WTCP(0x68067ac3, 0x4a957030), WTCP(0x67e928c5, 0x4abe4433), WTCP(0x67cbc6c0, 0x4ae70caf), + WTCP(0x67ae54ba, 0x4b0fc99d), WTCP(0x6790d2b6, 0x4b387af9), WTCP(0x677340ba, 0x4b6120bb), WTCP(0x67559eca, 0x4b89badd), + WTCP(0x6737ecea, 0x4bb24958), WTCP(0x671a2b20, 0x4bdacc28), WTCP(0x66fc596f, 0x4c034345), WTCP(0x66de77dc, 0x4c2baea9), + WTCP(0x66c0866d, 0x4c540e4e), WTCP(0x66a28524, 0x4c7c622d), WTCP(0x66847408, 0x4ca4aa41), WTCP(0x6666531d, 0x4ccce684), + WTCP(0x66482267, 0x4cf516ee), WTCP(0x6629e1ec, 0x4d1d3b7a), WTCP(0x660b91af, 0x4d455422), WTCP(0x65ed31b5, 0x4d6d60df), + WTCP(0x65cec204, 0x4d9561ac), WTCP(0x65b0429f, 0x4dbd5682), WTCP(0x6591b38c, 0x4de53f5a), WTCP(0x657314cf, 0x4e0d1c30), + WTCP(0x6554666d, 0x4e34ecfc), WTCP(0x6535a86b, 0x4e5cb1b9), WTCP(0x6516dacd, 0x4e846a60), WTCP(0x64f7fd98, 0x4eac16eb), + WTCP(0x64d910d1, 0x4ed3b755), WTCP(0x64ba147d, 0x4efb4b96), WTCP(0x649b08a0, 0x4f22d3aa), WTCP(0x647bed3f, 0x4f4a4f89), + WTCP(0x645cc260, 0x4f71bf2e), WTCP(0x643d8806, 0x4f992293), WTCP(0x641e3e38, 0x4fc079b1), WTCP(0x63fee4f8, 0x4fe7c483), + WTCP(0x63df7c4d, 0x500f0302), WTCP(0x63c0043b, 0x50363529), WTCP(0x63a07cc7, 0x505d5af1), WTCP(0x6380e5f6, 0x50847454), + WTCP(0x63613fcd, 0x50ab814d), WTCP(0x63418a50, 0x50d281d5), WTCP(0x6321c585, 0x50f975e6), WTCP(0x6301f171, 0x51205d7b), + WTCP(0x62e20e17, 0x5147388c), WTCP(0x62c21b7e, 0x516e0715), WTCP(0x62a219aa, 0x5194c910), WTCP(0x628208a1, 0x51bb7e75), + WTCP(0x6261e866, 0x51e22740), WTCP(0x6241b8ff, 0x5208c36a), WTCP(0x62217a72, 0x522f52ee), WTCP(0x62012cc2, 0x5255d5c5), + WTCP(0x61e0cff5, 0x527c4bea), WTCP(0x61c06410, 0x52a2b556), WTCP(0x619fe918, 0x52c91204), WTCP(0x617f5f12, 0x52ef61ee), + WTCP(0x615ec603, 0x5315a50e), WTCP(0x613e1df0, 0x533bdb5d), WTCP(0x611d66de, 0x536204d7), WTCP(0x60fca0d2, 0x53882175), + WTCP(0x60dbcbd1, 0x53ae3131), WTCP(0x60bae7e1, 0x53d43406), WTCP(0x6099f505, 0x53fa29ed), WTCP(0x6078f344, 0x542012e1), + WTCP(0x6057e2a2, 0x5445eedb), WTCP(0x6036c325, 0x546bbdd7), WTCP(0x601594d1, 0x54917fce), WTCP(0x5ff457ad, 0x54b734ba), + WTCP(0x5fd30bbc, 0x54dcdc96), WTCP(0x5fb1b104, 0x5502775c), WTCP(0x5f90478a, 0x55280505), WTCP(0x5f6ecf53, 0x554d858d), + WTCP(0x5f4d4865, 0x5572f8ed), WTCP(0x5f2bb2c5, 0x55985f20), WTCP(0x5f0a0e77, 0x55bdb81f), WTCP(0x5ee85b82, 0x55e303e6), + WTCP(0x5ec699e9, 0x5608426e), WTCP(0x5ea4c9b3, 0x562d73b2), WTCP(0x5e82eae5, 0x565297ab), WTCP(0x5e60fd84, 0x5677ae54), + WTCP(0x5e3f0194, 0x569cb7a8), WTCP(0x5e1cf71c, 0x56c1b3a1), WTCP(0x5dfade20, 0x56e6a239), WTCP(0x5dd8b6a7, 0x570b8369), + WTCP(0x5db680b4, 0x5730572e), WTCP(0x5d943c4e, 0x57551d80), WTCP(0x5d71e979, 0x5779d65b), WTCP(0x5d4f883b, 0x579e81b8), + WTCP(0x5d2d189a, 0x57c31f92), WTCP(0x5d0a9a9a, 0x57e7afe4), WTCP(0x5ce80e41, 0x580c32a7), WTCP(0x5cc57394, 0x5830a7d6), + WTCP(0x5ca2ca99, 0x58550f6c), WTCP(0x5c801354, 0x58796962), WTCP(0x5c5d4dcc, 0x589db5b3), WTCP(0x5c3a7a05, 0x58c1f45b), + WTCP(0x5c179806, 0x58e62552), WTCP(0x5bf4a7d2, 0x590a4893), WTCP(0x5bd1a971, 0x592e5e19), WTCP(0x5bae9ce7, 0x595265df), + WTCP(0x5b8b8239, 0x59765fde), WTCP(0x5b68596d, 0x599a4c12), WTCP(0x5b452288, 0x59be2a74), WTCP(0x5b21dd90, 0x59e1faff), + WTCP(0x5afe8a8b, 0x5a05bdae), WTCP(0x5adb297d, 0x5a29727b), WTCP(0x5ab7ba6c, 0x5a4d1960), WTCP(0x5a943d5e, 0x5a70b258), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow1024[] = +{ + WTCP(0x7fffffa4, 0x0009962f), WTCP(0x7fffff39, 0x000e16fb), WTCP(0x7ffffebf, 0x0011ea65), WTCP(0x7ffffe34, 0x0015750e), + WTCP(0x7ffffd96, 0x0018dc74), WTCP(0x7ffffce5, 0x001c332e), WTCP(0x7ffffc1f, 0x001f83f5), WTCP(0x7ffffb43, 0x0022d59a), + WTCP(0x7ffffa4f, 0x00262cc2), WTCP(0x7ffff942, 0x00298cc4), WTCP(0x7ffff81a, 0x002cf81f), WTCP(0x7ffff6d6, 0x003070c4), + WTCP(0x7ffff573, 0x0033f840), WTCP(0x7ffff3f1, 0x00378fd9), WTCP(0x7ffff24d, 0x003b38a1), WTCP(0x7ffff085, 0x003ef381), + WTCP(0x7fffee98, 0x0042c147), WTCP(0x7fffec83, 0x0046a2a8), WTCP(0x7fffea44, 0x004a9847), WTCP(0x7fffe7d8, 0x004ea2b7), + WTCP(0x7fffe53f, 0x0052c283), WTCP(0x7fffe274, 0x0056f829), WTCP(0x7fffdf76, 0x005b4422), WTCP(0x7fffdc43, 0x005fa6dd), + WTCP(0x7fffd8d6, 0x006420c8), WTCP(0x7fffd52f, 0x0068b249), WTCP(0x7fffd149, 0x006d5bc4), WTCP(0x7fffcd22, 0x00721d9a), + WTCP(0x7fffc8b6, 0x0076f828), WTCP(0x7fffc404, 0x007bebca), WTCP(0x7fffbf06, 0x0080f8d9), WTCP(0x7fffb9bb, 0x00861fae), + WTCP(0x7fffb41e, 0x008b609e), WTCP(0x7fffae2c, 0x0090bbff), WTCP(0x7fffa7e1, 0x00963224), WTCP(0x7fffa13a, 0x009bc362), + WTCP(0x7fff9a32, 0x00a17009), WTCP(0x7fff92c5, 0x00a7386c), WTCP(0x7fff8af0, 0x00ad1cdc), WTCP(0x7fff82ad, 0x00b31da8), + WTCP(0x7fff79f9, 0x00b93b21), WTCP(0x7fff70cf, 0x00bf7596), WTCP(0x7fff672a, 0x00c5cd57), WTCP(0x7fff5d05, 0x00cc42b1), + WTCP(0x7fff525c, 0x00d2d5f3), WTCP(0x7fff4729, 0x00d9876c), WTCP(0x7fff3b66, 0x00e05769), WTCP(0x7fff2f10, 0x00e74638), + WTCP(0x7fff221f, 0x00ee5426), WTCP(0x7fff148e, 0x00f58182), WTCP(0x7fff0658, 0x00fcce97), WTCP(0x7ffef776, 0x01043bb3), + WTCP(0x7ffee7e2, 0x010bc923), WTCP(0x7ffed795, 0x01137733), WTCP(0x7ffec68a, 0x011b4631), WTCP(0x7ffeb4ba, 0x01233669), + WTCP(0x7ffea21d, 0x012b4827), WTCP(0x7ffe8eac, 0x01337bb8), WTCP(0x7ffe7a61, 0x013bd167), WTCP(0x7ffe6533, 0x01444982), + WTCP(0x7ffe4f1c, 0x014ce454), WTCP(0x7ffe3813, 0x0155a229), WTCP(0x7ffe2011, 0x015e834d), WTCP(0x7ffe070d, 0x0167880c), + WTCP(0x7ffdecff, 0x0170b0b2), WTCP(0x7ffdd1df, 0x0179fd8b), WTCP(0x7ffdb5a2, 0x01836ee1), WTCP(0x7ffd9842, 0x018d0500), + WTCP(0x7ffd79b3, 0x0196c035), WTCP(0x7ffd59ee, 0x01a0a0ca), WTCP(0x7ffd38e8, 0x01aaa70a), WTCP(0x7ffd1697, 0x01b4d341), + WTCP(0x7ffcf2f2, 0x01bf25b9), WTCP(0x7ffccdee, 0x01c99ebd), WTCP(0x7ffca780, 0x01d43e99), WTCP(0x7ffc7f9e, 0x01df0597), + WTCP(0x7ffc563d, 0x01e9f401), WTCP(0x7ffc2b51, 0x01f50a22), WTCP(0x7ffbfecf, 0x02004844), WTCP(0x7ffbd0ab, 0x020baeb1), + WTCP(0x7ffba0da, 0x02173db4), WTCP(0x7ffb6f4f, 0x0222f596), WTCP(0x7ffb3bfd, 0x022ed6a1), WTCP(0x7ffb06d8, 0x023ae11f), + WTCP(0x7ffacfd3, 0x02471558), WTCP(0x7ffa96e0, 0x02537397), WTCP(0x7ffa5bf2, 0x025ffc25), WTCP(0x7ffa1efc, 0x026caf4a), + WTCP(0x7ff9dfee, 0x02798d4f), WTCP(0x7ff99ebb, 0x0286967c), WTCP(0x7ff95b55, 0x0293cb1b), WTCP(0x7ff915ab, 0x02a12b72), + WTCP(0x7ff8cdaf, 0x02aeb7cb), WTCP(0x7ff88351, 0x02bc706d), WTCP(0x7ff83682, 0x02ca559f), WTCP(0x7ff7e731, 0x02d867a9), + WTCP(0x7ff7954e, 0x02e6a6d2), WTCP(0x7ff740c8, 0x02f51361), WTCP(0x7ff6e98e, 0x0303ad9c), WTCP(0x7ff68f8f, 0x031275ca), + WTCP(0x7ff632ba, 0x03216c30), WTCP(0x7ff5d2fb, 0x03309116), WTCP(0x7ff57042, 0x033fe4bf), WTCP(0x7ff50a7a, 0x034f6773), + WTCP(0x7ff4a192, 0x035f1975), WTCP(0x7ff43576, 0x036efb0a), WTCP(0x7ff3c612, 0x037f0c78), WTCP(0x7ff35353, 0x038f4e02), + WTCP(0x7ff2dd24, 0x039fbfeb), WTCP(0x7ff26370, 0x03b06279), WTCP(0x7ff1e623, 0x03c135ed), WTCP(0x7ff16527, 0x03d23a8b), + WTCP(0x7ff0e067, 0x03e37095), WTCP(0x7ff057cc, 0x03f4d84e), WTCP(0x7fefcb40, 0x040671f7), WTCP(0x7fef3aad, 0x04183dd3), + WTCP(0x7feea5fa, 0x042a3c22), WTCP(0x7fee0d11, 0x043c6d25), WTCP(0x7fed6fda, 0x044ed11d), WTCP(0x7fecce3d, 0x04616849), + WTCP(0x7fec2821, 0x047432eb), WTCP(0x7feb7d6c, 0x04873140), WTCP(0x7feace07, 0x049a6388), WTCP(0x7fea19d6, 0x04adca01), + WTCP(0x7fe960c0, 0x04c164ea), WTCP(0x7fe8a2aa, 0x04d53481), WTCP(0x7fe7df79, 0x04e93902), WTCP(0x7fe71712, 0x04fd72aa), + WTCP(0x7fe6495a, 0x0511e1b6), WTCP(0x7fe57634, 0x05268663), WTCP(0x7fe49d83, 0x053b60eb), WTCP(0x7fe3bf2b, 0x05507189), + WTCP(0x7fe2db0f, 0x0565b879), WTCP(0x7fe1f110, 0x057b35f4), WTCP(0x7fe10111, 0x0590ea35), WTCP(0x7fe00af3, 0x05a6d574), + WTCP(0x7fdf0e97, 0x05bcf7ea), WTCP(0x7fde0bdd, 0x05d351cf), WTCP(0x7fdd02a6, 0x05e9e35c), WTCP(0x7fdbf2d2, 0x0600acc8), + WTCP(0x7fdadc40, 0x0617ae48), WTCP(0x7fd9becf, 0x062ee814), WTCP(0x7fd89a5e, 0x06465a62), WTCP(0x7fd76eca, 0x065e0565), + WTCP(0x7fd63bf1, 0x0675e954), WTCP(0x7fd501b0, 0x068e0662), WTCP(0x7fd3bfe4, 0x06a65cc3), WTCP(0x7fd2766a, 0x06beecaa), + WTCP(0x7fd1251e, 0x06d7b648), WTCP(0x7fcfcbda, 0x06f0b9d1), WTCP(0x7fce6a7a, 0x0709f775), WTCP(0x7fcd00d8, 0x07236f65), + WTCP(0x7fcb8ecf, 0x073d21d2), WTCP(0x7fca1439, 0x07570eea), WTCP(0x7fc890ed, 0x077136dd), WTCP(0x7fc704c7, 0x078b99da), + WTCP(0x7fc56f9d, 0x07a6380d), WTCP(0x7fc3d147, 0x07c111a4), WTCP(0x7fc2299e, 0x07dc26cc), WTCP(0x7fc07878, 0x07f777b1), + WTCP(0x7fbebdac, 0x0813047d), WTCP(0x7fbcf90f, 0x082ecd5b), WTCP(0x7fbb2a78, 0x084ad276), WTCP(0x7fb951bc, 0x086713f7), + WTCP(0x7fb76eaf, 0x08839206), WTCP(0x7fb58126, 0x08a04ccb), WTCP(0x7fb388f4, 0x08bd446e), WTCP(0x7fb185ee, 0x08da7915), + WTCP(0x7faf77e5, 0x08f7eae7), WTCP(0x7fad5ead, 0x09159a09), WTCP(0x7fab3a17, 0x0933869f), WTCP(0x7fa909f6, 0x0951b0cd), + WTCP(0x7fa6ce1a, 0x097018b7), WTCP(0x7fa48653, 0x098ebe7f), WTCP(0x7fa23273, 0x09ada248), WTCP(0x7f9fd249, 0x09ccc431), + WTCP(0x7f9d65a4, 0x09ec245b), WTCP(0x7f9aec53, 0x0a0bc2e7), WTCP(0x7f986625, 0x0a2b9ff3), WTCP(0x7f95d2e7, 0x0a4bbb9e), + WTCP(0x7f933267, 0x0a6c1604), WTCP(0x7f908472, 0x0a8caf43), WTCP(0x7f8dc8d5, 0x0aad8776), WTCP(0x7f8aff5c, 0x0ace9eb9), + WTCP(0x7f8827d3, 0x0aeff526), WTCP(0x7f854204, 0x0b118ad8), WTCP(0x7f824dbb, 0x0b335fe6), WTCP(0x7f7f4ac3, 0x0b557469), + WTCP(0x7f7c38e4, 0x0b77c879), WTCP(0x7f7917e9, 0x0b9a5c2b), WTCP(0x7f75e79b, 0x0bbd2f97), WTCP(0x7f72a7c3, 0x0be042d0), + WTCP(0x7f6f5828, 0x0c0395ec), WTCP(0x7f6bf892, 0x0c2728fd), WTCP(0x7f6888c9, 0x0c4afc16), WTCP(0x7f650894, 0x0c6f0f4a), + WTCP(0x7f6177b9, 0x0c9362a8), WTCP(0x7f5dd5ff, 0x0cb7f642), WTCP(0x7f5a232a, 0x0cdcca26), WTCP(0x7f565f00, 0x0d01de63), + WTCP(0x7f528947, 0x0d273307), WTCP(0x7f4ea1c2, 0x0d4cc81f), WTCP(0x7f4aa835, 0x0d729db7), WTCP(0x7f469c65, 0x0d98b3da), + WTCP(0x7f427e13, 0x0dbf0a92), WTCP(0x7f3e4d04, 0x0de5a1e9), WTCP(0x7f3a08f9, 0x0e0c79e7), WTCP(0x7f35b1b4, 0x0e339295), + WTCP(0x7f3146f8, 0x0e5aebfa), WTCP(0x7f2cc884, 0x0e82861a), WTCP(0x7f28361b, 0x0eaa60fd), WTCP(0x7f238f7c, 0x0ed27ca5), + WTCP(0x7f1ed467, 0x0efad917), WTCP(0x7f1a049d, 0x0f237656), WTCP(0x7f151fdc, 0x0f4c5462), WTCP(0x7f1025e3, 0x0f75733d), + WTCP(0x7f0b1672, 0x0f9ed2e6), WTCP(0x7f05f146, 0x0fc8735e), WTCP(0x7f00b61d, 0x0ff254a1), WTCP(0x7efb64b4, 0x101c76ae), + WTCP(0x7ef5fcca, 0x1046d981), WTCP(0x7ef07e19, 0x10717d15), WTCP(0x7eeae860, 0x109c6165), WTCP(0x7ee53b5b, 0x10c7866a), + WTCP(0x7edf76c4, 0x10f2ec1e), WTCP(0x7ed99a58, 0x111e9279), WTCP(0x7ed3a5d1, 0x114a7971), WTCP(0x7ecd98eb, 0x1176a0fc), + WTCP(0x7ec77360, 0x11a30910), WTCP(0x7ec134eb, 0x11cfb1a1), WTCP(0x7ebadd44, 0x11fc9aa2), WTCP(0x7eb46c27, 0x1229c406), + WTCP(0x7eade14c, 0x12572dbf), WTCP(0x7ea73c6c, 0x1284d7bc), WTCP(0x7ea07d41, 0x12b2c1ed), WTCP(0x7e99a382, 0x12e0ec42), + WTCP(0x7e92aee7, 0x130f56a8), WTCP(0x7e8b9f2a, 0x133e010b), WTCP(0x7e847402, 0x136ceb59), WTCP(0x7e7d2d25, 0x139c157b), + WTCP(0x7e75ca4c, 0x13cb7f5d), WTCP(0x7e6e4b2d, 0x13fb28e6), WTCP(0x7e66af7f, 0x142b1200), WTCP(0x7e5ef6f8, 0x145b3a92), + WTCP(0x7e572150, 0x148ba281), WTCP(0x7e4f2e3b, 0x14bc49b4), WTCP(0x7e471d70, 0x14ed300f), WTCP(0x7e3eeea5, 0x151e5575), + WTCP(0x7e36a18e, 0x154fb9c9), WTCP(0x7e2e35e2, 0x15815ced), WTCP(0x7e25ab56, 0x15b33ec1), WTCP(0x7e1d019e, 0x15e55f25), + WTCP(0x7e14386e, 0x1617bdf9), WTCP(0x7e0b4f7d, 0x164a5b19), WTCP(0x7e02467e, 0x167d3662), WTCP(0x7df91d25, 0x16b04fb2), + WTCP(0x7defd327, 0x16e3a6e2), WTCP(0x7de66837, 0x17173bce), WTCP(0x7ddcdc0a, 0x174b0e4d), WTCP(0x7dd32e53, 0x177f1e39), + WTCP(0x7dc95ec6, 0x17b36b69), WTCP(0x7dbf6d17, 0x17e7f5b3), WTCP(0x7db558f9, 0x181cbcec), WTCP(0x7dab221f, 0x1851c0e9), + WTCP(0x7da0c83c, 0x1887017d), WTCP(0x7d964b05, 0x18bc7e7c), WTCP(0x7d8baa2b, 0x18f237b6), WTCP(0x7d80e563, 0x19282cfd), + WTCP(0x7d75fc5e, 0x195e5e20), WTCP(0x7d6aeed0, 0x1994caee), WTCP(0x7d5fbc6d, 0x19cb7335), WTCP(0x7d5464e6, 0x1a0256c2), + WTCP(0x7d48e7ef, 0x1a397561), WTCP(0x7d3d453b, 0x1a70cede), WTCP(0x7d317c7c, 0x1aa86301), WTCP(0x7d258d65, 0x1ae03195), + WTCP(0x7d1977aa, 0x1b183a63), WTCP(0x7d0d3afc, 0x1b507d30), WTCP(0x7d00d710, 0x1b88f9c5), WTCP(0x7cf44b97, 0x1bc1afe6), + WTCP(0x7ce79846, 0x1bfa9f58), WTCP(0x7cdabcce, 0x1c33c7e0), WTCP(0x7ccdb8e4, 0x1c6d293f), WTCP(0x7cc08c39, 0x1ca6c337), + WTCP(0x7cb33682, 0x1ce0958a), WTCP(0x7ca5b772, 0x1d1a9ff8), WTCP(0x7c980ebd, 0x1d54e240), WTCP(0x7c8a3c14, 0x1d8f5c21), + WTCP(0x7c7c3f2e, 0x1dca0d56), WTCP(0x7c6e17bc, 0x1e04f59f), WTCP(0x7c5fc573, 0x1e4014b4), WTCP(0x7c514807, 0x1e7b6a53), + WTCP(0x7c429f2c, 0x1eb6f633), WTCP(0x7c33ca96, 0x1ef2b80f), WTCP(0x7c24c9fa, 0x1f2eaf9e), WTCP(0x7c159d0d, 0x1f6adc98), + WTCP(0x7c064383, 0x1fa73eb2), WTCP(0x7bf6bd11, 0x1fe3d5a3), WTCP(0x7be7096c, 0x2020a11e), WTCP(0x7bd7284a, 0x205da0d8), + WTCP(0x7bc71960, 0x209ad483), WTCP(0x7bb6dc65, 0x20d83bd1), WTCP(0x7ba6710d, 0x2115d674), WTCP(0x7b95d710, 0x2153a41b), + WTCP(0x7b850e24, 0x2191a476), WTCP(0x7b7415ff, 0x21cfd734), WTCP(0x7b62ee59, 0x220e3c02), WTCP(0x7b5196e9, 0x224cd28d), + WTCP(0x7b400f67, 0x228b9a82), WTCP(0x7b2e578a, 0x22ca938a), WTCP(0x7b1c6f0b, 0x2309bd52), WTCP(0x7b0a55a1, 0x23491783), + WTCP(0x7af80b07, 0x2388a1c4), WTCP(0x7ae58ef5, 0x23c85bbf), WTCP(0x7ad2e124, 0x2408451a), WTCP(0x7ac0014e, 0x24485d7c), + WTCP(0x7aacef2e, 0x2488a48a), WTCP(0x7a99aa7e, 0x24c919e9), WTCP(0x7a8632f8, 0x2509bd3d), WTCP(0x7a728858, 0x254a8e29), + WTCP(0x7a5eaa5a, 0x258b8c50), WTCP(0x7a4a98b9, 0x25ccb753), WTCP(0x7a365333, 0x260e0ed3), WTCP(0x7a21d983, 0x264f9271), + WTCP(0x7a0d2b68, 0x269141cb), WTCP(0x79f8489e, 0x26d31c80), WTCP(0x79e330e4, 0x2715222f), WTCP(0x79cde3f8, 0x27575273), + WTCP(0x79b8619a, 0x2799acea), WTCP(0x79a2a989, 0x27dc3130), WTCP(0x798cbb85, 0x281ededf), WTCP(0x7976974e, 0x2861b591), + WTCP(0x79603ca5, 0x28a4b4e0), WTCP(0x7949ab4c, 0x28e7dc65), WTCP(0x7932e304, 0x292b2bb8), WTCP(0x791be390, 0x296ea270), + WTCP(0x7904acb3, 0x29b24024), WTCP(0x78ed3e30, 0x29f6046b), WTCP(0x78d597cc, 0x2a39eed8), WTCP(0x78bdb94a, 0x2a7dff02), + WTCP(0x78a5a270, 0x2ac2347c), WTCP(0x788d5304, 0x2b068eda), WTCP(0x7874cacb, 0x2b4b0dae), WTCP(0x785c098d, 0x2b8fb08a), + WTCP(0x78430f11, 0x2bd47700), WTCP(0x7829db1f, 0x2c1960a1), WTCP(0x78106d7f, 0x2c5e6cfd), WTCP(0x77f6c5fb, 0x2ca39ba3), + WTCP(0x77dce45c, 0x2ce8ec23), WTCP(0x77c2c86e, 0x2d2e5e0b), WTCP(0x77a871fa, 0x2d73f0e8), WTCP(0x778de0cd, 0x2db9a449), + WTCP(0x777314b2, 0x2dff77b8), WTCP(0x77580d78, 0x2e456ac4), WTCP(0x773ccaeb, 0x2e8b7cf6), WTCP(0x77214cdb, 0x2ed1addb), + WTCP(0x77059315, 0x2f17fcfb), WTCP(0x76e99d69, 0x2f5e69e2), WTCP(0x76cd6ba9, 0x2fa4f419), WTCP(0x76b0fda4, 0x2feb9b27), + WTCP(0x7694532e, 0x30325e96), WTCP(0x76776c17, 0x30793dee), WTCP(0x765a4834, 0x30c038b5), WTCP(0x763ce759, 0x31074e72), + WTCP(0x761f4959, 0x314e7eab), WTCP(0x76016e0b, 0x3195c8e6), WTCP(0x75e35545, 0x31dd2ca9), WTCP(0x75c4fedc, 0x3224a979), + WTCP(0x75a66aab, 0x326c3ed8), WTCP(0x75879887, 0x32b3ec4d), WTCP(0x7568884b, 0x32fbb159), WTCP(0x754939d1, 0x33438d81), + WTCP(0x7529acf4, 0x338b8045), WTCP(0x7509e18e, 0x33d3892a), WTCP(0x74e9d77d, 0x341ba7b1), WTCP(0x74c98e9e, 0x3463db5a), + WTCP(0x74a906cd, 0x34ac23a7), WTCP(0x74883fec, 0x34f48019), WTCP(0x746739d8, 0x353cf02f), WTCP(0x7445f472, 0x3585736a), + WTCP(0x74246f9c, 0x35ce0949), WTCP(0x7402ab37, 0x3616b14c), WTCP(0x73e0a727, 0x365f6af0), WTCP(0x73be6350, 0x36a835b5), + WTCP(0x739bdf95, 0x36f11118), WTCP(0x73791bdd, 0x3739fc98), WTCP(0x7356180e, 0x3782f7b2), WTCP(0x7332d410, 0x37cc01e3), + WTCP(0x730f4fc9, 0x38151aa8), WTCP(0x72eb8b24, 0x385e417e), WTCP(0x72c7860a, 0x38a775e1), WTCP(0x72a34066, 0x38f0b74d), + WTCP(0x727eba24, 0x393a053e), WTCP(0x7259f331, 0x39835f30), WTCP(0x7234eb79, 0x39ccc49e), WTCP(0x720fa2eb, 0x3a163503), + WTCP(0x71ea1977, 0x3a5fafda), WTCP(0x71c44f0c, 0x3aa9349e), WTCP(0x719e439d, 0x3af2c2ca), WTCP(0x7177f71a, 0x3b3c59d7), + WTCP(0x71516978, 0x3b85f940), WTCP(0x712a9aaa, 0x3bcfa07e), WTCP(0x71038aa4, 0x3c194f0d), WTCP(0x70dc395e, 0x3c630464), + WTCP(0x70b4a6cd, 0x3cacbfff), WTCP(0x708cd2e9, 0x3cf68155), WTCP(0x7064bdab, 0x3d4047e1), WTCP(0x703c670d, 0x3d8a131c), + WTCP(0x7013cf0a, 0x3dd3e27e), WTCP(0x6feaf59c, 0x3e1db580), WTCP(0x6fc1dac1, 0x3e678b9b), WTCP(0x6f987e76, 0x3eb16449), + WTCP(0x6f6ee0b9, 0x3efb3f01), WTCP(0x6f45018b, 0x3f451b3d), WTCP(0x6f1ae0eb, 0x3f8ef874), WTCP(0x6ef07edb, 0x3fd8d620), + WTCP(0x6ec5db5d, 0x4022b3b9), WTCP(0x6e9af675, 0x406c90b7), WTCP(0x6e6fd027, 0x40b66c93), WTCP(0x6e446879, 0x410046c5), + WTCP(0x6e18bf71, 0x414a1ec6), WTCP(0x6decd517, 0x4193f40d), WTCP(0x6dc0a972, 0x41ddc615), WTCP(0x6d943c8d, 0x42279455), + WTCP(0x6d678e71, 0x42715e45), WTCP(0x6d3a9f2a, 0x42bb235f), WTCP(0x6d0d6ec5, 0x4304e31a), WTCP(0x6cdffd4f, 0x434e9cf1), + WTCP(0x6cb24ad6, 0x4398505b), WTCP(0x6c84576b, 0x43e1fcd1), WTCP(0x6c56231c, 0x442ba1cd), WTCP(0x6c27adfd, 0x44753ec7), + WTCP(0x6bf8f81e, 0x44bed33a), WTCP(0x6bca0195, 0x45085e9d), WTCP(0x6b9aca75, 0x4551e06b), WTCP(0x6b6b52d5, 0x459b581e), + WTCP(0x6b3b9ac9, 0x45e4c52f), WTCP(0x6b0ba26b, 0x462e2717), WTCP(0x6adb69d3, 0x46777d52), WTCP(0x6aaaf11b, 0x46c0c75a), + WTCP(0x6a7a385c, 0x470a04a9), WTCP(0x6a493fb3, 0x475334b9), WTCP(0x6a18073d, 0x479c5707), WTCP(0x69e68f17, 0x47e56b0c), + WTCP(0x69b4d761, 0x482e7045), WTCP(0x6982e039, 0x4877662c), WTCP(0x6950a9c0, 0x48c04c3f), WTCP(0x691e341a, 0x490921f8), + WTCP(0x68eb7f67, 0x4951e6d5), WTCP(0x68b88bcd, 0x499a9a51), WTCP(0x68855970, 0x49e33beb), WTCP(0x6851e875, 0x4a2bcb1f), + WTCP(0x681e3905, 0x4a74476b), WTCP(0x67ea4b47, 0x4abcb04c), WTCP(0x67b61f63, 0x4b050541), WTCP(0x6781b585, 0x4b4d45c9), + WTCP(0x674d0dd6, 0x4b957162), WTCP(0x67182883, 0x4bdd878c), WTCP(0x66e305b8, 0x4c2587c6), WTCP(0x66ada5a5, 0x4c6d7190), + WTCP(0x66780878, 0x4cb5446a), WTCP(0x66422e60, 0x4cfcffd5), WTCP(0x660c1790, 0x4d44a353), WTCP(0x65d5c439, 0x4d8c2e64), + WTCP(0x659f348e, 0x4dd3a08c), WTCP(0x656868c3, 0x4e1af94b), WTCP(0x6531610d, 0x4e623825), WTCP(0x64fa1da3, 0x4ea95c9d), + WTCP(0x64c29ebb, 0x4ef06637), WTCP(0x648ae48d, 0x4f375477), WTCP(0x6452ef53, 0x4f7e26e1), WTCP(0x641abf46, 0x4fc4dcfb), + WTCP(0x63e254a2, 0x500b7649), WTCP(0x63a9afa2, 0x5051f253), WTCP(0x6370d083, 0x5098509f), WTCP(0x6337b784, 0x50de90b3), + WTCP(0x62fe64e3, 0x5124b218), WTCP(0x62c4d8e0, 0x516ab455), WTCP(0x628b13bc, 0x51b096f3), WTCP(0x625115b8, 0x51f6597b), + WTCP(0x6216df18, 0x523bfb78), WTCP(0x61dc701f, 0x52817c72), WTCP(0x61a1c912, 0x52c6dbf5), WTCP(0x6166ea36, 0x530c198d), + WTCP(0x612bd3d2, 0x535134c5), WTCP(0x60f0862d, 0x53962d2a), WTCP(0x60b50190, 0x53db024a), WTCP(0x60794644, 0x541fb3b1), + WTCP(0x603d5494, 0x546440ef), WTCP(0x60012cca, 0x54a8a992), WTCP(0x5fc4cf33, 0x54eced2b), WTCP(0x5f883c1c, 0x55310b48), + WTCP(0x5f4b73d2, 0x5575037c), WTCP(0x5f0e76a5, 0x55b8d558), WTCP(0x5ed144e5, 0x55fc806f), WTCP(0x5e93dee1, 0x56400452), + WTCP(0x5e5644ec, 0x56836096), WTCP(0x5e187757, 0x56c694cf), WTCP(0x5dda7677, 0x5709a092), WTCP(0x5d9c429f, 0x574c8374), + WTCP(0x5d5ddc24, 0x578f3d0d), WTCP(0x5d1f435d, 0x57d1ccf2), WTCP(0x5ce078a0, 0x581432bd), WTCP(0x5ca17c45, 0x58566e04), + WTCP(0x5c624ea4, 0x58987e63), WTCP(0x5c22f016, 0x58da6372), WTCP(0x5be360f6, 0x591c1ccc), WTCP(0x5ba3a19f, 0x595daa0d), + WTCP(0x5b63b26c, 0x599f0ad1), WTCP(0x5b2393ba, 0x59e03eb6), WTCP(0x5ae345e7, 0x5a214558), WTCP(0x5aa2c951, 0x5a621e56), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow128[] = +{ + WTCP(0x7fff6216, 0x00c90f88), WTCP(0x7ffa72d1, 0x025b26d7), WTCP(0x7ff09478, 0x03ed26e6), WTCP(0x7fe1c76b, 0x057f0035), + WTCP(0x7fce0c3e, 0x0710a345), WTCP(0x7fb563b3, 0x08a2009a), WTCP(0x7f97cebd, 0x0a3308bd), WTCP(0x7f754e80, 0x0bc3ac35), + WTCP(0x7f4de451, 0x0d53db92), WTCP(0x7f2191b4, 0x0ee38766), WTCP(0x7ef05860, 0x1072a048), WTCP(0x7eba3a39, 0x120116d5), + WTCP(0x7e7f3957, 0x138edbb1), WTCP(0x7e3f57ff, 0x151bdf86), WTCP(0x7dfa98a8, 0x16a81305), WTCP(0x7db0fdf8, 0x183366e9), + WTCP(0x7d628ac6, 0x19bdcbf3), WTCP(0x7d0f4218, 0x1b4732ef), WTCP(0x7cb72724, 0x1ccf8cb3), WTCP(0x7c5a3d50, 0x1e56ca1e), + WTCP(0x7bf88830, 0x1fdcdc1b), WTCP(0x7b920b89, 0x2161b3a0), WTCP(0x7b26cb4f, 0x22e541af), WTCP(0x7ab6cba4, 0x24677758), + WTCP(0x7a4210d8, 0x25e845b6), WTCP(0x79c89f6e, 0x27679df4), WTCP(0x794a7c12, 0x28e5714b), WTCP(0x78c7aba2, 0x2a61b101), + WTCP(0x78403329, 0x2bdc4e6f), WTCP(0x77b417df, 0x2d553afc), WTCP(0x77235f2d, 0x2ecc681e), WTCP(0x768e0ea6, 0x3041c761), + WTCP(0x75f42c0b, 0x31b54a5e), WTCP(0x7555bd4c, 0x3326e2c3), WTCP(0x74b2c884, 0x34968250), WTCP(0x740b53fb, 0x36041ad9), + WTCP(0x735f6626, 0x376f9e46), WTCP(0x72af05a7, 0x38d8fe93), WTCP(0x71fa3949, 0x3a402dd2), WTCP(0x71410805, 0x3ba51e29), + WTCP(0x708378ff, 0x3d07c1d6), WTCP(0x6fc19385, 0x3e680b2c), WTCP(0x6efb5f12, 0x3fc5ec98), WTCP(0x6e30e34a, 0x4121589b), + WTCP(0x6d6227fa, 0x427a41d0), WTCP(0x6c8f351c, 0x43d09aed), WTCP(0x6bb812d1, 0x452456bd), WTCP(0x6adcc964, 0x46756828), + WTCP(0x69fd614a, 0x47c3c22f), WTCP(0x6919e320, 0x490f57ee), WTCP(0x683257ab, 0x4a581c9e), WTCP(0x6746c7d8, 0x4b9e0390), + WTCP(0x66573cbb, 0x4ce10034), WTCP(0x6563bf92, 0x4e210617), WTCP(0x646c59bf, 0x4f5e08e3), WTCP(0x637114cc, 0x5097fc5e), + WTCP(0x6271fa69, 0x51ced46e), WTCP(0x616f146c, 0x53028518), WTCP(0x60686ccf, 0x5433027d), WTCP(0x5f5e0db3, 0x556040e2), + WTCP(0x5e50015d, 0x568a34a9), WTCP(0x5d3e5237, 0x57b0d256), WTCP(0x5c290acc, 0x58d40e8c), WTCP(0x5b1035cf, 0x59f3de12), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow128[] = +{ + WTCP(0x7ffffffe, 0x00016f63), WTCP(0x7ffffff1, 0x0003e382), WTCP(0x7fffffc7, 0x00078f64), WTCP(0x7fffff5d, 0x000cc323), + WTCP(0x7ffffe76, 0x0013d9ed), WTCP(0x7ffffcaa, 0x001d3a9d), WTCP(0x7ffff953, 0x0029581f), WTCP(0x7ffff372, 0x0038b1bd), + WTCP(0x7fffe98b, 0x004bd34d), WTCP(0x7fffd975, 0x00635538), WTCP(0x7fffc024, 0x007fdc64), WTCP(0x7fff995b, 0x00a219f1), + WTCP(0x7fff5f5b, 0x00cacad0), WTCP(0x7fff0a75, 0x00fab72d), WTCP(0x7ffe9091, 0x0132b1af), WTCP(0x7ffde49e, 0x01739689), + WTCP(0x7ffcf5ef, 0x01be4a63), WTCP(0x7ffbaf84, 0x0213b910), WTCP(0x7ff9f73a, 0x0274d41e), WTCP(0x7ff7acf1, 0x02e2913a), + WTCP(0x7ff4a99a, 0x035de86c), WTCP(0x7ff0be3d, 0x03e7d233), WTCP(0x7febb2f1, 0x0481457c), WTCP(0x7fe545d4, 0x052b357c), + WTCP(0x7fdd2a02, 0x05e68f77), WTCP(0x7fd30695, 0x06b4386f), WTCP(0x7fc675b4, 0x07950acb), WTCP(0x7fb703be, 0x0889d3ef), + WTCP(0x7fa42e89, 0x099351e0), WTCP(0x7f8d64d8, 0x0ab230e0), WTCP(0x7f7205f8, 0x0be70923), WTCP(0x7f516195, 0x0d325c93), + WTCP(0x7f2ab7d0, 0x0e9494ae), WTCP(0x7efd3997, 0x100e0085), WTCP(0x7ec8094a, 0x119ed2ef), WTCP(0x7e8a3ba7, 0x134720d8), + WTCP(0x7e42d906, 0x1506dfdc), WTCP(0x7df0dee4, 0x16dde50b), WTCP(0x7d9341b4, 0x18cbe3f7), WTCP(0x7d28ef02, 0x1ad06e07), + WTCP(0x7cb0cfcc, 0x1ceaf215), WTCP(0x7c29cb20, 0x1f1abc4f), WTCP(0x7b92c8eb, 0x215ef677), WTCP(0x7aeab4ec, 0x23b6a867), + WTCP(0x7a3081d0, 0x2620b8ec), WTCP(0x79632c5a, 0x289beef5), WTCP(0x7881be95, 0x2b26f30b), WTCP(0x778b5304, 0x2dc0511f), + WTCP(0x767f17c0, 0x30667aa2), WTCP(0x755c5178, 0x3317c8dd), WTCP(0x74225e50, 0x35d27f98), WTCP(0x72d0b887, 0x3894cff3), + WTCP(0x7166f8e7, 0x3b5cdb7b), WTCP(0x6fe4d8e8, 0x3e28b770), WTCP(0x6e4a3491, 0x40f6702a), WTCP(0x6c970bfc, 0x43c40caa), + WTCP(0x6acb8483, 0x468f9231), WTCP(0x68e7e994, 0x495707f5), WTCP(0x66ecad1c, 0x4c187ac7), WTCP(0x64da6797, 0x4ed200c5), + WTCP(0x62b1d7b7, 0x5181bcea), WTCP(0x6073e1ae, 0x5425e28e), WTCP(0x5e218e16, 0x56bcb8c2), WTCP(0x5bbc0875, 0x59449d76), +}; + + + + + + + + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow960[] = +{ + WTCP(0x7ffffd31, 0x001aceea), WTCP(0x7fffe6bc, 0x00506cb9), WTCP(0x7fffb9d1, 0x00860a79), WTCP(0x7fff7671, 0x00bba822), + WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffeac50, 0x0126e309), WTCP(0x7ffe2590, 0x015c8033), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ffcd4b0, 0x01c7b9c6), WTCP(0x7ffc0a91, 0x01fd561d), WTCP(0x7ffb29fd, 0x0232f21a), WTCP(0x7ffa32f4, 0x02688db4), + WTCP(0x7ff92577, 0x029e28e2), WTCP(0x7ff80186, 0x02d3c39b), WTCP(0x7ff6c720, 0x03095dd5), WTCP(0x7ff57647, 0x033ef786), + WTCP(0x7ff40efa, 0x037490a5), WTCP(0x7ff2913a, 0x03aa292a), WTCP(0x7ff0fd07, 0x03dfc109), WTCP(0x7fef5260, 0x0415583b), + WTCP(0x7fed9148, 0x044aeeb5), WTCP(0x7febb9bd, 0x0480846e), WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fe7c752, 0x04ebad79), + WTCP(0x7fe5ac72, 0x052140b7), WTCP(0x7fe37b22, 0x0556d30f), WTCP(0x7fe13361, 0x058c6478), WTCP(0x7fded530, 0x05c1f4e7), + WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd9d57f, 0x062d12b4), WTCP(0x7fd73401, 0x06629ffe), WTCP(0x7fd47c14, 0x06982c2b), + WTCP(0x7fd1adb9, 0x06cdb72f), WTCP(0x7fcec8f1, 0x07034101), WTCP(0x7fcbcdbc, 0x0738c998), WTCP(0x7fc8bc1b, 0x076e50eb), + WTCP(0x7fc5940e, 0x07a3d6f0), WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7fbf00b3, 0x080edeec), WTCP(0x7fbb9567, 0x084460cf), + WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fb47b91, 0x08af6033), WTCP(0x7fb0cd0a, 0x08e4dda0), WTCP(0x7fad081b, 0x091a597e), + WTCP(0x7fa92cc5, 0x094fd3c3), WTCP(0x7fa53b09, 0x09854c66), WTCP(0x7fa132e8, 0x09bac35d), WTCP(0x7f9d1461, 0x09f0389f), + WTCP(0x7f98df77, 0x0a25ac23), WTCP(0x7f949429, 0x0a5b1dde), WTCP(0x7f903279, 0x0a908dc9), WTCP(0x7f8bba66, 0x0ac5fbd9), + WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f82871f, 0x0b30d244), WTCP(0x7f7dcbec, 0x0b663a8c), WTCP(0x7f78fa5b, 0x0b9ba0d5), + WTCP(0x7f74126b, 0x0bd10513), WTCP(0x7f6f141f, 0x0c066740), WTCP(0x7f69ff76, 0x0c3bc74f), WTCP(0x7f64d473, 0x0c71253a), + WTCP(0x7f5f9315, 0x0ca680f5), WTCP(0x7f5a3b5e, 0x0cdbda79), WTCP(0x7f54cd4f, 0x0d1131ba), WTCP(0x7f4f48e8, 0x0d4686b1), + WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f43fd18, 0x0db12999), WTCP(0x7f3e35b0, 0x0de67776), WTCP(0x7f3857f6, 0x0e1bc2e4), + WTCP(0x7f3263e9, 0x0e510bd8), WTCP(0x7f2c598a, 0x0e865248), WTCP(0x7f2638db, 0x0ebb962c), WTCP(0x7f2001dd, 0x0ef0d77b), + WTCP(0x7f19b491, 0x0f26162a), WTCP(0x7f1350f8, 0x0f5b5231), WTCP(0x7f0cd712, 0x0f908b86), WTCP(0x7f0646e2, 0x0fc5c220), + WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7ef8e3a6, 0x103026fe), WTCP(0x7ef2109d, 0x1065552e), WTCP(0x7eeb274d, 0x109a807e), + WTCP(0x7ee427b9, 0x10cfa8e5), WTCP(0x7edd11e1, 0x1104ce58), WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7ecea36b, 0x116f1040), + WTCP(0x7ec74acf, 0x11a42ca2), WTCP(0x7ebfdbf5, 0x11d945eb), WTCP(0x7eb856de, 0x120e5c13), WTCP(0x7eb0bb8a, 0x12436f10), + WTCP(0x7ea909fc, 0x12787ed8), WTCP(0x7ea14235, 0x12ad8b63), WTCP(0x7e996436, 0x12e294a7), WTCP(0x7e917000, 0x13179a9b), + WTCP(0x7e896595, 0x134c9d34), WTCP(0x7e8144f6, 0x13819c6c), WTCP(0x7e790e25, 0x13b69836), WTCP(0x7e70c124, 0x13eb908c), + WTCP(0x7e685df2, 0x14208563), WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7e575508, 0x148a646e), WTCP(0x7e4eaf51, 0x14bf4e91), + WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e3d2169, 0x152917e1), WTCP(0x7e34393b, 0x155df6fc), WTCP(0x7e2b3ae8, 0x1592d257), + WTCP(0x7e222672, 0x15c7a9ea), WTCP(0x7e18fbda, 0x15fc7daa), WTCP(0x7e0fbb22, 0x16314d8e), WTCP(0x7e06644c, 0x1666198d), + WTCP(0x7dfcf759, 0x169ae19f), WTCP(0x7df3744b, 0x16cfa5b9), WTCP(0x7de9db23, 0x170465d2), WTCP(0x7de02be4, 0x173921e2), + WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7dcc8b25, 0x17a28dbe), WTCP(0x7dc299a9, 0x17d73d79), WTCP(0x7db8921c, 0x180be904), + WTCP(0x7dae747f, 0x18409058), WTCP(0x7da440d6, 0x1875336a), WTCP(0x7d99f721, 0x18a9d231), WTCP(0x7d8f9762, 0x18de6ca5), + WTCP(0x7d85219c, 0x191302bc), WTCP(0x7d7a95cf, 0x1947946c), WTCP(0x7d6ff3fe, 0x197c21ad), WTCP(0x7d653c2b, 0x19b0aa75), + WTCP(0x7d5a6e57, 0x19e52ebb), WTCP(0x7d4f8a85, 0x1a19ae76), WTCP(0x7d4490b6, 0x1a4e299d), WTCP(0x7d3980ec, 0x1a82a026), + WTCP(0x7d2e5b2a, 0x1ab71208), WTCP(0x7d231f70, 0x1aeb7f3a), WTCP(0x7d17cdc2, 0x1b1fe7b3), WTCP(0x7d0c6621, 0x1b544b6a), + WTCP(0x7d00e88f, 0x1b88aa55), WTCP(0x7cf5550e, 0x1bbd046c), WTCP(0x7ce9aba1, 0x1bf159a4), WTCP(0x7cddec48, 0x1c25a9f6), + WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cc62bdf, 0x1c8e3bbe), WTCP(0x7cba2ad3, 0x1cc27d23), WTCP(0x7cae13e4, 0x1cf6b97c), + WTCP(0x7ca1e715, 0x1d2af0c1), WTCP(0x7c95a467, 0x1d5f22e7), WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7c7cdd7b, 0x1dc777b3), + WTCP(0x7c705940, 0x1dfb9a48), WTCP(0x7c63bf2f, 0x1e2fb79a), WTCP(0x7c570f4b, 0x1e63cfa0), WTCP(0x7c4a4996, 0x1e97e251), + WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c307cc2, 0x1efff78f), WTCP(0x7c2375a8, 0x1f33fa0a), WTCP(0x7c1658c5, 0x1f67f70b), + WTCP(0x7c09261d, 0x1f9bee8a), WTCP(0x7bfbddb1, 0x1fcfe07d), WTCP(0x7bee7f85, 0x2003ccdb), WTCP(0x7be10b99, 0x2037b39b), + WTCP(0x7bd381f1, 0x206b94b4), WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7bb82d76, 0x20d345cc), WTCP(0x7baa62a8, 0x210715b8), + WTCP(0x7b9c8226, 0x213adfda), WTCP(0x7b8e8bf5, 0x216ea426), WTCP(0x7b808015, 0x21a26295), WTCP(0x7b725e8a, 0x21d61b1e), + WTCP(0x7b642756, 0x2209cdb6), WTCP(0x7b55da7c, 0x223d7a55), WTCP(0x7b4777fe, 0x227120f3), WTCP(0x7b38ffde, 0x22a4c185), + WTCP(0x7b2a721f, 0x22d85c04), WTCP(0x7b1bcec4, 0x230bf065), WTCP(0x7b0d15d0, 0x233f7ea0), WTCP(0x7afe4744, 0x237306ab), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ae06971, 0x23da0411), WTCP(0x7ad15a2f, 0x240d7958), WTCP(0x7ac23561, 0x2440e84d), + WTCP(0x7ab2fb09, 0x247450e4), WTCP(0x7aa3ab29, 0x24a7b317), WTCP(0x7a9445c5, 0x24db0edb), WTCP(0x7a84cade, 0x250e6427), + WTCP(0x7a753a79, 0x2541b2f3), WTCP(0x7a659496, 0x2574fb36), WTCP(0x7a55d93a, 0x25a83ce6), WTCP(0x7a460867, 0x25db77fa), + WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a262668, 0x2641da2d), WTCP(0x7a161540, 0x26750139), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79f5b2b1, 0x26db3b0a), WTCP(0x79e5614f, 0x270e4dbd), WTCP(0x79d4fa89, 0x27415996), WTCP(0x79c47e63, 0x27745e8c), + WTCP(0x79b3ece0, 0x27a75c95), WTCP(0x79a34602, 0x27da53a9), WTCP(0x799289cc, 0x280d43bf), WTCP(0x7981b841, 0x28402cce), + WTCP(0x7970d165, 0x28730ecd), WTCP(0x795fd53a, 0x28a5e9b4), WTCP(0x794ec3c3, 0x28d8bd78), WTCP(0x793d9d03, 0x290b8a12), + WTCP(0x792c60fe, 0x293e4f78), WTCP(0x791b0fb5, 0x29710da1), WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78f82d68, 0x29d6741b), + WTCP(0x78e69c69, 0x2a091c59), WTCP(0x78d4f634, 0x2a3bbd37), WTCP(0x78c33acb, 0x2a6e56ac), WTCP(0x78b16a32, 0x2aa0e8b0), + WTCP(0x789f846b, 0x2ad37338), WTCP(0x788d897b, 0x2b05f63d), WTCP(0x787b7963, 0x2b3871b5), WTCP(0x78695428, 0x2b6ae598), + WTCP(0x785719cc, 0x2b9d51dd), WTCP(0x7844ca53, 0x2bcfb67b), WTCP(0x783265c0, 0x2c021369), WTCP(0x781fec15, 0x2c34689e), + WTCP(0x780d5d57, 0x2c66b611), WTCP(0x77fab989, 0x2c98fbba), WTCP(0x77e800ad, 0x2ccb3990), WTCP(0x77d532c7, 0x2cfd6f8a), + WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77af57eb, 0x2d61c3c7), WTCP(0x779c4afc, 0x2d93e1f8), WTCP(0x77892910, 0x2dc5f829), + WTCP(0x7775f22a, 0x2df80653), WTCP(0x7762a64f, 0x2e2a0c6c), WTCP(0x774f4581, 0x2e5c0a6b), WTCP(0x773bcfc4, 0x2e8e0048), + WTCP(0x7728451c, 0x2ebfedfa), WTCP(0x7714a58b, 0x2ef1d377), WTCP(0x7700f115, 0x2f23b0b9), WTCP(0x76ed27be, 0x2f5585b5), + WTCP(0x76d94989, 0x2f875262), WTCP(0x76c55679, 0x2fb916b9), WTCP(0x76b14e93, 0x2fead2b0), WTCP(0x769d31d9, 0x301c863f), + WTCP(0x76890050, 0x304e315d), WTCP(0x7674b9fa, 0x307fd401), WTCP(0x76605edb, 0x30b16e23), WTCP(0x764beef8, 0x30e2ffb9), + WTCP(0x76376a52, 0x311488bc), WTCP(0x7622d0ef, 0x31460922), WTCP(0x760e22d1, 0x317780e2), WTCP(0x75f95ffc, 0x31a8eff5), + WTCP(0x75e48874, 0x31da5651), WTCP(0x75cf9c3d, 0x320bb3ee), WTCP(0x75ba9b5a, 0x323d08c3), WTCP(0x75a585cf, 0x326e54c7), + WTCP(0x75905ba0, 0x329f97f3), WTCP(0x757b1ccf, 0x32d0d23c), WTCP(0x7565c962, 0x3302039b), WTCP(0x7550615c, 0x33332c06), + WTCP(0x753ae4c0, 0x33644b76), WTCP(0x75255392, 0x339561e1), WTCP(0x750fadd7, 0x33c66f40), WTCP(0x74f9f391, 0x33f77388), + WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74ce4177, 0x345960b7), WTCP(0x74b849aa, 0x348a498b), WTCP(0x74a23d62, 0x34bb2927), + WTCP(0x748c1ca4, 0x34ebff83), WTCP(0x7475e772, 0x351ccc96), WTCP(0x745f9dd1, 0x354d9057), WTCP(0x74493fc5, 0x357e4abe), + WTCP(0x7432cd51, 0x35aefbc2), WTCP(0x741c467b, 0x35dfa35a), WTCP(0x7405ab45, 0x3610417f), WTCP(0x73eefbb3, 0x3640d627), + WTCP(0x73d837ca, 0x3671614b), WTCP(0x73c15f8d, 0x36a1e2e0), WTCP(0x73aa7301, 0x36d25ae0), WTCP(0x7393722a, 0x3702c942), + WTCP(0x737c5d0b, 0x37332dfd), WTCP(0x736533a9, 0x37638908), WTCP(0x734df607, 0x3793da5b), WTCP(0x7336a42b, 0x37c421ee), + WTCP(0x731f3e17, 0x37f45fb7), WTCP(0x7307c3d0, 0x382493b0), WTCP(0x72f0355a, 0x3854bdcf), WTCP(0x72d892ba, 0x3884de0b), + WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72a91109, 0x38e500bc), WTCP(0x72913201, 0x3915031f), WTCP(0x72793edf, 0x3944fb7e), + WTCP(0x726137a8, 0x3974e9d0), WTCP(0x72491c5e, 0x39a4ce0e), WTCP(0x7230ed07, 0x39d4a82f), WTCP(0x7218a9a7, 0x3a04782a), + WTCP(0x72005242, 0x3a343df7), WTCP(0x71e7e6dc, 0x3a63f98d), WTCP(0x71cf677a, 0x3a93aae5), WTCP(0x71b6d420, 0x3ac351f6), + WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x71857195, 0x3b228120), WTCP(0x716ca26c, 0x3b52092a), WTCP(0x7153bf5d, 0x3b8186ca), + WTCP(0x713ac86b, 0x3bb0f9fa), WTCP(0x7121bd9c, 0x3be062b0), WTCP(0x71089ef2, 0x3c0fc0e6), WTCP(0x70ef6c74, 0x3c3f1491), + WTCP(0x70d62625, 0x3c6e5daa), WTCP(0x70bccc09, 0x3c9d9c28), WTCP(0x70a35e25, 0x3cccd004), WTCP(0x7089dc7e, 0x3cfbf935), + WTCP(0x70704718, 0x3d2b17b3), WTCP(0x70569df8, 0x3d5a2b75), WTCP(0x703ce122, 0x3d893474), WTCP(0x7023109a, 0x3db832a6), + WTCP(0x70092c65, 0x3de72604), WTCP(0x6fef3488, 0x3e160e85), WTCP(0x6fd52907, 0x3e44ec22), WTCP(0x6fbb09e7, 0x3e73bed2), + WTCP(0x6fa0d72c, 0x3ea2868c), WTCP(0x6f8690db, 0x3ed14349), WTCP(0x6f6c36f8, 0x3efff501), WTCP(0x6f51c989, 0x3f2e9bab), + WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6f1cb416, 0x3f8bc7b4), WTCP(0x6f020c1c, 0x3fba4d03), WTCP(0x6ee750a8, 0x3fe8c724), + WTCP(0x6ecc81be, 0x4017360e), WTCP(0x6eb19f64, 0x404599b9), WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6e7ba06f, 0x40a23f32), + WTCP(0x6e6083de, 0x40d080f0), WTCP(0x6e4553ef, 0x40feb74f), WTCP(0x6e2a10a8, 0x412ce246), WTCP(0x6e0eba0c, 0x415b01ce), + WTCP(0x6df35020, 0x418915de), WTCP(0x6dd7d2ea, 0x41b71e6f), WTCP(0x6dbc426e, 0x41e51b77), WTCP(0x6da09eb1, 0x42130cf0), + WTCP(0x6d84e7b7, 0x4240f2d1), WTCP(0x6d691d87, 0x426ecd12), WTCP(0x6d4d4023, 0x429c9bab), WTCP(0x6d314f93, 0x42ca5e94), + WTCP(0x6d154bd9, 0x42f815c5), WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6cdd0b00, 0x435360de), WTCP(0x6cc0cdea, 0x4380f4b7), + WTCP(0x6ca47dbf, 0x43ae7cb7), WTCP(0x6c881a84, 0x43dbf8d7), WTCP(0x6c6ba43e, 0x44096910), WTCP(0x6c4f1af2, 0x4436cd58), + WTCP(0x6c327ea6, 0x446425a8), WTCP(0x6c15cf5d, 0x449171f8), WTCP(0x6bf90d1d, 0x44beb240), WTCP(0x6bdc37eb, 0x44ebe679), + WTCP(0x6bbf4fcd, 0x45190e99), WTCP(0x6ba254c7, 0x45462a9a), WTCP(0x6b8546de, 0x45733a73), WTCP(0x6b682617, 0x45a03e1d), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6b2dac06, 0x45fa20c2), WTCP(0x6b1052c6, 0x4626ffae), WTCP(0x6af2e6bc, 0x4653d24b), + WTCP(0x6ad567ef, 0x46809891), WTCP(0x6ab7d663, 0x46ad5278), WTCP(0x6a9a321d, 0x46d9fff8), WTCP(0x6a7c7b23, 0x4706a10a), + WTCP(0x6a5eb17a, 0x473335a5), WTCP(0x6a40d527, 0x475fbdc3), WTCP(0x6a22e630, 0x478c395a), WTCP(0x6a04e499, 0x47b8a864), + WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x69c8a9a1, 0x481160ae), WTCP(0x69aa704c, 0x483da9e0), WTCP(0x698c246c, 0x4869e665), + WTCP(0x696dc607, 0x48961635), WTCP(0x694f5523, 0x48c23949), WTCP(0x6930d1c4, 0x48ee4f98), WTCP(0x69123bf1, 0x491a591c), + WTCP(0x68f393ae, 0x494655cc), WTCP(0x68d4d900, 0x497245a1), WTCP(0x68b60bee, 0x499e2892), WTCP(0x68972c7d, 0x49c9fe99), + WTCP(0x68783ab1, 0x49f5c7ae), WTCP(0x68593691, 0x4a2183c8), WTCP(0x683a2022, 0x4a4d32e1), WTCP(0x681af76a, 0x4a78d4f0), + WTCP(0x67fbbc6d, 0x4aa469ee), WTCP(0x67dc6f31, 0x4acff1d3), WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x679d9e14, 0x4b26da35), + WTCP(0x677e1a3e, 0x4b523aa2), WTCP(0x675e843e, 0x4b7d8dd8), WTCP(0x673edc1c, 0x4ba8d3cf), WTCP(0x671f21dc, 0x4bd40c80), + WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x66df771a, 0x4c2a55ef), WTCP(0x66bf86a3, 0x4c55669f), WTCP(0x669f8425, 0x4c8069ea), + WTCP(0x667f6fa5, 0x4cab5fc9), WTCP(0x665f4929, 0x4cd64834), WTCP(0x663f10b7, 0x4d012324), WTCP(0x661ec654, 0x4d2bf091), + WTCP(0x65fe6a06, 0x4d56b073), WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x65bd7bc0, 0x4dac077b), WTCP(0x659ce9d4, 0x4dd69e92), + WTCP(0x657c4613, 0x4e012800), WTCP(0x655b9083, 0x4e2ba3be), WTCP(0x653ac92b, 0x4e5611c5), WTCP(0x6519f010, 0x4e80720e), + WTCP(0x64f90538, 0x4eaac490), WTCP(0x64d808a8, 0x4ed50945), WTCP(0x64b6fa66, 0x4eff4025), WTCP(0x6495da79, 0x4f296928), + WTCP(0x6474a8e5, 0x4f538448), WTCP(0x645365b2, 0x4f7d917c), WTCP(0x643210e4, 0x4fa790be), WTCP(0x6410aa81, 0x4fd18206), + WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x63cda916, 0x50253a8b), WTCP(0x63ac0e19, 0x504f01ba), WTCP(0x638a619e, 0x5078bad1), + WTCP(0x6368a3ad, 0x50a265c9), WTCP(0x6346d44b, 0x50cc029c), WTCP(0x6324f37d, 0x50f59141), WTCP(0x6303014a, 0x511f11b2), + WTCP(0x62e0fdb8, 0x514883e7), WTCP(0x62bee8cc, 0x5171e7d9), WTCP(0x629cc28c, 0x519b3d80), WTCP(0x627a8b00, 0x51c484d6), + WTCP(0x6258422c, 0x51edbdd4), WTCP(0x6235e816, 0x5216e871), WTCP(0x62137cc5, 0x524004a7), WTCP(0x61f1003f, 0x5269126e), + WTCP(0x61ce7289, 0x529211c0), WTCP(0x61abd3ab, 0x52bb0295), WTCP(0x618923a9, 0x52e3e4e6), WTCP(0x61666289, 0x530cb8ac), + WTCP(0x61439053, 0x53357ddf), WTCP(0x6120ad0d, 0x535e3479), WTCP(0x60fdb8bb, 0x5386dc72), WTCP(0x60dab365, 0x53af75c3), + WTCP(0x60b79d10, 0x53d80065), WTCP(0x609475c3, 0x54007c51), WTCP(0x60713d84, 0x5428e980), WTCP(0x604df459, 0x545147eb), + WTCP(0x602a9a48, 0x5479978a), WTCP(0x60072f57, 0x54a1d857), WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5fc026f0, 0x54f22d5d), + WTCP(0x5f9c8987, 0x551a4189), WTCP(0x5f78db56, 0x554246c6), WTCP(0x5f551c65, 0x556a3d0d), WTCP(0x5f314cba, 0x55922457), + WTCP(0x5f0d6c5b, 0x55b9fc9e), WTCP(0x5ee97b4f, 0x55e1c5da), WTCP(0x5ec5799b, 0x56098005), WTCP(0x5ea16747, 0x56312b17), + WTCP(0x5e7d4458, 0x5658c709), WTCP(0x5e5910d4, 0x568053d5), WTCP(0x5e34ccc3, 0x56a7d174), WTCP(0x5e10782b, 0x56cf3fde), + WTCP(0x5dec1311, 0x56f69f0d), WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5da31773, 0x57452f9d), WTCP(0x5d7e80fc, 0x576c60f1), + WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5d3522de, 0x57ba958d), WTCP(0x5d105b44, 0x57e198c7), WTCP(0x5ceb8355, 0x58088c96), + WTCP(0x5cc69b19, 0x582f70f3), WTCP(0x5ca1a295, 0x585645d7), WTCP(0x5c7c99d1, 0x587d0b3b), WTCP(0x5c5780d3, 0x58a3c118), + WTCP(0x5c3257a0, 0x58ca6767), WTCP(0x5c0d1e41, 0x58f0fe23), WTCP(0x5be7d4ba, 0x59178543), WTCP(0x5bc27b14, 0x593dfcc2), + WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b779780, 0x598abcbe), WTCP(0x5b520da1, 0x59b1052f), WTCP(0x5b2c73bb, 0x59d73de3), + WTCP(0x5b06c9d6, 0x59fd66d4), WTCP(0x5ae10ff9, 0x5a237ffa), WTCP(0x5abb4629, 0x5a498950), WTCP(0x5a956c6e, 0x5a6f82ce), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow960[] = +{ + WTCP(0x7fffff9e, 0x0009e6ac), WTCP(0x7fffff2b, 0x000e96d5), WTCP(0x7ffffea6, 0x0012987e), WTCP(0x7ffffe0e, 0x001652b6), + WTCP(0x7ffffd60, 0x0019ebce), WTCP(0x7ffffc9c, 0x001d76bf), WTCP(0x7ffffbbf, 0x0020fe79), WTCP(0x7ffffac9, 0x002489ef), + WTCP(0x7ffff9b7, 0x00281de2), WTCP(0x7ffff887, 0x002bbdbb), WTCP(0x7ffff737, 0x002f6c0d), WTCP(0x7ffff5c6, 0x00332ad8), + WTCP(0x7ffff431, 0x0036fbb9), WTCP(0x7ffff276, 0x003ae004), WTCP(0x7ffff092, 0x003ed8d8), WTCP(0x7fffee84, 0x0042e72f), + WTCP(0x7fffec48, 0x00470be3), WTCP(0x7fffe9dd, 0x004b47b8), WTCP(0x7fffe73f, 0x004f9b5f), WTCP(0x7fffe46b, 0x0054077a), + WTCP(0x7fffe15f, 0x00588ca1), WTCP(0x7fffde17, 0x005d2b61), WTCP(0x7fffda91, 0x0061e442), WTCP(0x7fffd6c9, 0x0066b7c2), + WTCP(0x7fffd2bb, 0x006ba65c), WTCP(0x7fffce65, 0x0070b087), WTCP(0x7fffc9c2, 0x0075d6b5), WTCP(0x7fffc4cf, 0x007b1955), + WTCP(0x7fffbf87, 0x008078d5), WTCP(0x7fffb9e7, 0x0085f5a0), WTCP(0x7fffb3ea, 0x008b901d), WTCP(0x7fffad8c, 0x009148b4), + WTCP(0x7fffa6c9, 0x00971fcb), WTCP(0x7fff9f9c, 0x009d15c7), WTCP(0x7fff9800, 0x00a32b0b), WTCP(0x7fff8ff0, 0x00a95ff9), + WTCP(0x7fff8767, 0x00afb4f4), WTCP(0x7fff7e5f, 0x00b62a5c), WTCP(0x7fff74d4, 0x00bcc093), WTCP(0x7fff6ac0, 0x00c377f8), + WTCP(0x7fff601c, 0x00ca50eb), WTCP(0x7fff54e3, 0x00d14bcb), WTCP(0x7fff490e, 0x00d868f7), WTCP(0x7fff3c98, 0x00dfa8ce), + WTCP(0x7fff2f79, 0x00e70bad), WTCP(0x7fff21ac, 0x00ee91f3), WTCP(0x7fff1328, 0x00f63bfe), WTCP(0x7fff03e7, 0x00fe0a2c), + WTCP(0x7ffef3e1, 0x0105fcd9), WTCP(0x7ffee310, 0x010e1462), WTCP(0x7ffed16a, 0x01165126), WTCP(0x7ffebee9, 0x011eb381), + WTCP(0x7ffeab83, 0x01273bd0), WTCP(0x7ffe9731, 0x012fea6f), WTCP(0x7ffe81ea, 0x0138bfbc), WTCP(0x7ffe6ba4, 0x0141bc12), + WTCP(0x7ffe5457, 0x014adfce), WTCP(0x7ffe3bfa, 0x01542b4d), WTCP(0x7ffe2282, 0x015d9ee9), WTCP(0x7ffe07e6, 0x01673b01), + WTCP(0x7ffdec1b, 0x0170ffee), WTCP(0x7ffdcf17, 0x017aee0e), WTCP(0x7ffdb0d0, 0x018505bc), WTCP(0x7ffd913b, 0x018f4754), + WTCP(0x7ffd704b, 0x0199b330), WTCP(0x7ffd4df7, 0x01a449ad), WTCP(0x7ffd2a31, 0x01af0b25), WTCP(0x7ffd04ef, 0x01b9f7f4), + WTCP(0x7ffcde23, 0x01c51074), WTCP(0x7ffcb5c1, 0x01d05501), WTCP(0x7ffc8bbc, 0x01dbc5f5), WTCP(0x7ffc6006, 0x01e763ab), + WTCP(0x7ffc3293, 0x01f32e7d), WTCP(0x7ffc0354, 0x01ff26c5), WTCP(0x7ffbd23b, 0x020b4cde), WTCP(0x7ffb9f3a, 0x0217a120), + WTCP(0x7ffb6a41, 0x022423e6), WTCP(0x7ffb3342, 0x0230d58a), WTCP(0x7ffafa2d, 0x023db664), WTCP(0x7ffabef2, 0x024ac6ce), + WTCP(0x7ffa8180, 0x02580720), WTCP(0x7ffa41c9, 0x026577b3), WTCP(0x7ff9ffb9, 0x027318e0), WTCP(0x7ff9bb41, 0x0280eaff), + WTCP(0x7ff9744e, 0x028eee68), WTCP(0x7ff92acf, 0x029d2371), WTCP(0x7ff8deb1, 0x02ab8a74), WTCP(0x7ff88fe2, 0x02ba23c7), + WTCP(0x7ff83e4d, 0x02c8efc0), WTCP(0x7ff7e9e1, 0x02d7eeb7), WTCP(0x7ff79288, 0x02e72101), WTCP(0x7ff7382f, 0x02f686f5), + WTCP(0x7ff6dac1, 0x030620e9), WTCP(0x7ff67a29, 0x0315ef31), WTCP(0x7ff61651, 0x0325f224), WTCP(0x7ff5af23, 0x03362a14), + WTCP(0x7ff5448a, 0x03469758), WTCP(0x7ff4d66d, 0x03573a42), WTCP(0x7ff464b7, 0x03681327), WTCP(0x7ff3ef4f, 0x0379225a), + WTCP(0x7ff3761d, 0x038a682e), WTCP(0x7ff2f90a, 0x039be4f4), WTCP(0x7ff277fb, 0x03ad9900), WTCP(0x7ff1f2d8, 0x03bf84a3), + WTCP(0x7ff16986, 0x03d1a82e), WTCP(0x7ff0dbec, 0x03e403f3), WTCP(0x7ff049ef, 0x03f69840), WTCP(0x7fefb373, 0x04096568), + WTCP(0x7fef185d, 0x041c6bb8), WTCP(0x7fee7890, 0x042fab81), WTCP(0x7fedd3f1, 0x04432510), WTCP(0x7fed2a61, 0x0456d8b4), + WTCP(0x7fec7bc4, 0x046ac6ba), WTCP(0x7febc7fb, 0x047eef70), WTCP(0x7feb0ee8, 0x04935322), WTCP(0x7fea506b, 0x04a7f21d), + WTCP(0x7fe98c65, 0x04bcccab), WTCP(0x7fe8c2b7, 0x04d1e318), WTCP(0x7fe7f33e, 0x04e735af), WTCP(0x7fe71ddb, 0x04fcc4ba), + WTCP(0x7fe6426c, 0x05129081), WTCP(0x7fe560ce, 0x0528994d), WTCP(0x7fe478df, 0x053edf68), WTCP(0x7fe38a7c, 0x05556318), + WTCP(0x7fe29581, 0x056c24a5), WTCP(0x7fe199ca, 0x05832455), WTCP(0x7fe09733, 0x059a626e), WTCP(0x7fdf8d95, 0x05b1df35), + WTCP(0x7fde7ccb, 0x05c99aef), WTCP(0x7fdd64af, 0x05e195e0), WTCP(0x7fdc451a, 0x05f9d04b), WTCP(0x7fdb1de4, 0x06124a73), + WTCP(0x7fd9eee5, 0x062b0499), WTCP(0x7fd8b7f5, 0x0643ff00), WTCP(0x7fd778ec, 0x065d39e7), WTCP(0x7fd6319e, 0x0676b58f), + WTCP(0x7fd4e1e2, 0x06907237), WTCP(0x7fd3898d, 0x06aa701d), WTCP(0x7fd22873, 0x06c4af80), WTCP(0x7fd0be6a, 0x06df309c), + WTCP(0x7fcf4b44, 0x06f9f3ad), WTCP(0x7fcdced4, 0x0714f8f0), WTCP(0x7fcc48ed, 0x0730409f), WTCP(0x7fcab960, 0x074bcaf5), + WTCP(0x7fc91fff, 0x0767982a), WTCP(0x7fc77c9a, 0x0783a877), WTCP(0x7fc5cf02, 0x079ffc14), WTCP(0x7fc41705, 0x07bc9338), + WTCP(0x7fc25474, 0x07d96e19), WTCP(0x7fc0871b, 0x07f68ced), WTCP(0x7fbeaeca, 0x0813efe7), WTCP(0x7fbccb4c, 0x0831973d), + WTCP(0x7fbadc70, 0x084f8320), WTCP(0x7fb8e200, 0x086db3c3), WTCP(0x7fb6dbc8, 0x088c2957), WTCP(0x7fb4c993, 0x08aae40c), + WTCP(0x7fb2ab2b, 0x08c9e412), WTCP(0x7fb0805a, 0x08e92997), WTCP(0x7fae48e9, 0x0908b4c9), WTCP(0x7fac04a0, 0x092885d6), + WTCP(0x7fa9b347, 0x09489ce8), WTCP(0x7fa754a6, 0x0968fa2c), WTCP(0x7fa4e884, 0x09899dcb), WTCP(0x7fa26ea6, 0x09aa87ee), + WTCP(0x7f9fe6d1, 0x09cbb8be), WTCP(0x7f9d50cc, 0x09ed3062), WTCP(0x7f9aac5a, 0x0a0eef00), WTCP(0x7f97f93f, 0x0a30f4bf), + WTCP(0x7f95373e, 0x0a5341c2), WTCP(0x7f92661b, 0x0a75d62e), WTCP(0x7f8f8596, 0x0a98b224), WTCP(0x7f8c9572, 0x0abbd5c7), + WTCP(0x7f89956f, 0x0adf4137), WTCP(0x7f86854d, 0x0b02f494), WTCP(0x7f8364cd, 0x0b26effd), WTCP(0x7f8033ae, 0x0b4b338f), + WTCP(0x7f7cf1ae, 0x0b6fbf67), WTCP(0x7f799e8b, 0x0b9493a0), WTCP(0x7f763a03, 0x0bb9b056), WTCP(0x7f72c3d2, 0x0bdf15a2), + WTCP(0x7f6f3bb5, 0x0c04c39c), WTCP(0x7f6ba168, 0x0c2aba5d), WTCP(0x7f67f4a6, 0x0c50f9fa), WTCP(0x7f643529, 0x0c77828a), + WTCP(0x7f6062ac, 0x0c9e5420), WTCP(0x7f5c7ce8, 0x0cc56ed1), WTCP(0x7f588397, 0x0cecd2ae), WTCP(0x7f547670, 0x0d147fc8), + WTCP(0x7f50552c, 0x0d3c7630), WTCP(0x7f4c1f83, 0x0d64b5f6), WTCP(0x7f47d52a, 0x0d8d3f26), WTCP(0x7f4375d9, 0x0db611ce), + WTCP(0x7f3f0144, 0x0ddf2dfa), WTCP(0x7f3a7723, 0x0e0893b4), WTCP(0x7f35d729, 0x0e324306), WTCP(0x7f31210a, 0x0e5c3bf9), + WTCP(0x7f2c547b, 0x0e867e94), WTCP(0x7f27712e, 0x0eb10add), WTCP(0x7f2276d8, 0x0edbe0da), WTCP(0x7f1d6529, 0x0f07008e), + WTCP(0x7f183bd3, 0x0f3269fc), WTCP(0x7f12fa89, 0x0f5e1d27), WTCP(0x7f0da0fb, 0x0f8a1a0e), WTCP(0x7f082ed8, 0x0fb660b1), + WTCP(0x7f02a3d2, 0x0fe2f10f), WTCP(0x7efcff98, 0x100fcb25), WTCP(0x7ef741d9, 0x103ceeee), WTCP(0x7ef16a42, 0x106a5c66), + WTCP(0x7eeb7884, 0x10981386), WTCP(0x7ee56c4a, 0x10c61447), WTCP(0x7edf4543, 0x10f45ea0), WTCP(0x7ed9031b, 0x1122f288), + WTCP(0x7ed2a57f, 0x1151cff3), WTCP(0x7ecc2c1a, 0x1180f6d5), WTCP(0x7ec59699, 0x11b06720), WTCP(0x7ebee4a6, 0x11e020c8), + WTCP(0x7eb815ed, 0x121023ba), WTCP(0x7eb12a18, 0x12406fe8), WTCP(0x7eaa20d1, 0x1271053e), WTCP(0x7ea2f9c2, 0x12a1e3a9), + WTCP(0x7e9bb494, 0x12d30b15), WTCP(0x7e9450f0, 0x13047b6c), WTCP(0x7e8cce7f, 0x13363497), WTCP(0x7e852ce9, 0x1368367f), + WTCP(0x7e7d6bd6, 0x139a8109), WTCP(0x7e758aee, 0x13cd141b), WTCP(0x7e6d89d9, 0x13ffef99), WTCP(0x7e65683d, 0x14331368), + WTCP(0x7e5d25c1, 0x14667f67), WTCP(0x7e54c20b, 0x149a3379), WTCP(0x7e4c3cc3, 0x14ce2f7c), WTCP(0x7e43958e, 0x1502734f), + WTCP(0x7e3acc11, 0x1536fece), WTCP(0x7e31dff2, 0x156bd1d6), WTCP(0x7e28d0d7, 0x15a0ec41), WTCP(0x7e1f9e63, 0x15d64de9), + WTCP(0x7e16483d, 0x160bf6a5), WTCP(0x7e0cce08, 0x1641e64c), WTCP(0x7e032f6a, 0x16781cb4), WTCP(0x7df96c05, 0x16ae99b2), + WTCP(0x7def837e, 0x16e55d18), WTCP(0x7de57579, 0x171c66ba), WTCP(0x7ddb419a, 0x1753b667), WTCP(0x7dd0e784, 0x178b4bef), + WTCP(0x7dc666d9, 0x17c32721), WTCP(0x7dbbbf3e, 0x17fb47ca), WTCP(0x7db0f056, 0x1833adb5), WTCP(0x7da5f9c3, 0x186c58ae), + WTCP(0x7d9adb29, 0x18a5487d), WTCP(0x7d8f9429, 0x18de7cec), WTCP(0x7d842467, 0x1917f5c1), WTCP(0x7d788b86, 0x1951b2c2), + WTCP(0x7d6cc927, 0x198bb3b4), WTCP(0x7d60dced, 0x19c5f85a), WTCP(0x7d54c67c, 0x1a008077), WTCP(0x7d488574, 0x1a3b4bcb), + WTCP(0x7d3c1979, 0x1a765a17), WTCP(0x7d2f822d, 0x1ab1ab18), WTCP(0x7d22bf32, 0x1aed3e8d), WTCP(0x7d15d02b, 0x1b291432), + WTCP(0x7d08b4ba, 0x1b652bc1), WTCP(0x7cfb6c82, 0x1ba184f5), WTCP(0x7cedf725, 0x1bde1f86), WTCP(0x7ce05445, 0x1c1afb2c), + WTCP(0x7cd28386, 0x1c58179c), WTCP(0x7cc48489, 0x1c95748d), WTCP(0x7cb656f3, 0x1cd311b1), WTCP(0x7ca7fa65, 0x1d10eebd), + WTCP(0x7c996e83, 0x1d4f0b60), WTCP(0x7c8ab2f0, 0x1d8d674c), WTCP(0x7c7bc74f, 0x1dcc0230), WTCP(0x7c6cab44, 0x1e0adbbb), + WTCP(0x7c5d5e71, 0x1e49f398), WTCP(0x7c4de07c, 0x1e894973), WTCP(0x7c3e3108, 0x1ec8dcf8), WTCP(0x7c2e4fb9, 0x1f08add0), + WTCP(0x7c1e3c34, 0x1f48bba3), WTCP(0x7c0df61d, 0x1f890618), WTCP(0x7bfd7d18, 0x1fc98cd6), WTCP(0x7becd0cc, 0x200a4f80), + WTCP(0x7bdbf0dd, 0x204b4dbc), WTCP(0x7bcadcf1, 0x208c872c), WTCP(0x7bb994ae, 0x20cdfb71), WTCP(0x7ba817b9, 0x210faa2c), + WTCP(0x7b9665bb, 0x215192fc), WTCP(0x7b847e58, 0x2193b57f), WTCP(0x7b726139, 0x21d61153), WTCP(0x7b600e05, 0x2218a614), + WTCP(0x7b4d8463, 0x225b735d), WTCP(0x7b3ac3fc, 0x229e78c7), WTCP(0x7b27cc79, 0x22e1b5eb), WTCP(0x7b149d82, 0x23252a62), + WTCP(0x7b0136c1, 0x2368d5c2), WTCP(0x7aed97df, 0x23acb7a0), WTCP(0x7ad9c087, 0x23f0cf92), WTCP(0x7ac5b063, 0x24351d2a), + WTCP(0x7ab1671e, 0x24799ffc), WTCP(0x7a9ce464, 0x24be5799), WTCP(0x7a8827e1, 0x25034391), WTCP(0x7a733142, 0x25486375), + WTCP(0x7a5e0033, 0x258db6d2), WTCP(0x7a489461, 0x25d33d35), WTCP(0x7a32ed7c, 0x2618f62c), WTCP(0x7a1d0b31, 0x265ee143), + WTCP(0x7a06ed2f, 0x26a4fe02), WTCP(0x79f09327, 0x26eb4bf5), WTCP(0x79d9fcc8, 0x2731caa3), WTCP(0x79c329c2, 0x27787995), + WTCP(0x79ac19c9, 0x27bf5850), WTCP(0x7994cc8d, 0x2806665c), WTCP(0x797d41c1, 0x284da33c), WTCP(0x79657918, 0x28950e74), + WTCP(0x794d7247, 0x28dca788), WTCP(0x79352d01, 0x29246dfa), WTCP(0x791ca8fc, 0x296c614a), WTCP(0x7903e5ee, 0x29b480f9), + WTCP(0x78eae38d, 0x29fccc87), WTCP(0x78d1a191, 0x2a454372), WTCP(0x78b81fb1, 0x2a8de537), WTCP(0x789e5da6, 0x2ad6b155), + WTCP(0x78845b29, 0x2b1fa745), WTCP(0x786a17f5, 0x2b68c684), WTCP(0x784f93c4, 0x2bb20e8c), WTCP(0x7834ce53, 0x2bfb7ed7), + WTCP(0x7819c75c, 0x2c4516dc), WTCP(0x77fe7e9e, 0x2c8ed615), WTCP(0x77e2f3d7, 0x2cd8bbf7), WTCP(0x77c726c5, 0x2d22c7fa), + WTCP(0x77ab1728, 0x2d6cf993), WTCP(0x778ec4c0, 0x2db75037), WTCP(0x77722f4e, 0x2e01cb59), WTCP(0x77555695, 0x2e4c6a6d), + WTCP(0x77383a58, 0x2e972ce6), WTCP(0x771ada5a, 0x2ee21235), WTCP(0x76fd3660, 0x2f2d19cc), WTCP(0x76df4e30, 0x2f78431a), + WTCP(0x76c12190, 0x2fc38d91), WTCP(0x76a2b047, 0x300ef89d), WTCP(0x7683fa1e, 0x305a83af), WTCP(0x7664fede, 0x30a62e34), + WTCP(0x7645be51, 0x30f1f798), WTCP(0x76263842, 0x313ddf49), WTCP(0x76066c7e, 0x3189e4b1), WTCP(0x75e65ad1, 0x31d6073d), + WTCP(0x75c60309, 0x32224657), WTCP(0x75a564f6, 0x326ea168), WTCP(0x75848067, 0x32bb17da), WTCP(0x7563552d, 0x3307a917), + WTCP(0x7541e31a, 0x33545486), WTCP(0x75202a02, 0x33a1198e), WTCP(0x74fe29b8, 0x33edf798), WTCP(0x74dbe211, 0x343aee09), + WTCP(0x74b952e3, 0x3487fc48), WTCP(0x74967c06, 0x34d521bb), WTCP(0x74735d51, 0x35225dc7), WTCP(0x744ff69f, 0x356fafcf), + WTCP(0x742c47c9, 0x35bd173a), WTCP(0x740850ab, 0x360a9369), WTCP(0x73e41121, 0x365823c1), WTCP(0x73bf8909, 0x36a5c7a4), + WTCP(0x739ab842, 0x36f37e75), WTCP(0x73759eab, 0x37414796), WTCP(0x73503c26, 0x378f2268), WTCP(0x732a9095, 0x37dd0e4c), + WTCP(0x73049bda, 0x382b0aa4), WTCP(0x72de5ddb, 0x387916d0), WTCP(0x72b7d67d, 0x38c73230), WTCP(0x729105a6, 0x39155c24), + WTCP(0x7269eb3f, 0x3963940c), WTCP(0x72428730, 0x39b1d946), WTCP(0x721ad964, 0x3a002b31), WTCP(0x71f2e1c5, 0x3a4e892c), + WTCP(0x71caa042, 0x3a9cf296), WTCP(0x71a214c7, 0x3aeb66cc), WTCP(0x71793f43, 0x3b39e52c), WTCP(0x71501fa6, 0x3b886d14), + WTCP(0x7126b5e3, 0x3bd6fde1), WTCP(0x70fd01eb, 0x3c2596f1), WTCP(0x70d303b2, 0x3c74379f), WTCP(0x70a8bb2e, 0x3cc2df49), + WTCP(0x707e2855, 0x3d118d4c), WTCP(0x70534b1e, 0x3d604103), WTCP(0x70282381, 0x3daef9cc), WTCP(0x6ffcb17a, 0x3dfdb702), + WTCP(0x6fd0f504, 0x3e4c7800), WTCP(0x6fa4ee1a, 0x3e9b3c25), WTCP(0x6f789cbb, 0x3eea02ca), WTCP(0x6f4c00e5, 0x3f38cb4b), + WTCP(0x6f1f1a9a, 0x3f879505), WTCP(0x6ef1e9da, 0x3fd65f53), WTCP(0x6ec46ea9, 0x40252990), WTCP(0x6e96a90b, 0x4073f318), + WTCP(0x6e689905, 0x40c2bb46), WTCP(0x6e3a3e9d, 0x41118176), WTCP(0x6e0b99dd, 0x41604504), WTCP(0x6ddcaacc, 0x41af054a), + WTCP(0x6dad7177, 0x41fdc1a5), WTCP(0x6d7dede8, 0x424c7970), WTCP(0x6d4e202e, 0x429b2c06), WTCP(0x6d1e0855, 0x42e9d8c4), + WTCP(0x6ceda66f, 0x43387f05), WTCP(0x6cbcfa8d, 0x43871e26), WTCP(0x6c8c04c0, 0x43d5b581), WTCP(0x6c5ac51d, 0x44244474), + WTCP(0x6c293bb8, 0x4472ca5a), WTCP(0x6bf768a8, 0x44c14690), WTCP(0x6bc54c06, 0x450fb873), WTCP(0x6b92e5e9, 0x455e1f5f), + WTCP(0x6b60366c, 0x45ac7ab2), WTCP(0x6b2d3dab, 0x45fac9c8), WTCP(0x6af9fbc2, 0x46490bff), WTCP(0x6ac670d1, 0x469740b5), + WTCP(0x6a929cf6, 0x46e56747), WTCP(0x6a5e8053, 0x47337f13), WTCP(0x6a2a1b0a, 0x47818779), WTCP(0x69f56d3e, 0x47cf7fd6), + WTCP(0x69c07715, 0x481d678a), WTCP(0x698b38b4, 0x486b3df3), WTCP(0x6955b243, 0x48b90272), WTCP(0x691fe3ec, 0x4906b466), + WTCP(0x68e9cdd8, 0x49545330), WTCP(0x68b37033, 0x49a1de30), WTCP(0x687ccb29, 0x49ef54c8), WTCP(0x6845dee9, 0x4a3cb657), + WTCP(0x680eaba3, 0x4a8a0242), WTCP(0x67d73187, 0x4ad737e9), WTCP(0x679f70c7, 0x4b2456af), WTCP(0x67676997, 0x4b715df7), + WTCP(0x672f1c2b, 0x4bbe4d25), WTCP(0x66f688ba, 0x4c0b239c), WTCP(0x66bdaf7b, 0x4c57e0c2), WTCP(0x668490a6, 0x4ca483fa), + WTCP(0x664b2c76, 0x4cf10cac), WTCP(0x66118326, 0x4d3d7a3b), WTCP(0x65d794f3, 0x4d89cc0f), WTCP(0x659d621a, 0x4dd6018f), + WTCP(0x6562eada, 0x4e221a22), WTCP(0x65282f74, 0x4e6e1530), WTCP(0x64ed302b, 0x4eb9f222), WTCP(0x64b1ed40, 0x4f05b061), + WTCP(0x647666f8, 0x4f514f57), WTCP(0x643a9d99, 0x4f9cce6f), WTCP(0x63fe916a, 0x4fe82d13), WTCP(0x63c242b2, 0x50336aaf), + WTCP(0x6385b1bc, 0x507e86b0), WTCP(0x6348ded1, 0x50c98082), WTCP(0x630bca3f, 0x51145793), WTCP(0x62ce7451, 0x515f0b51), + WTCP(0x6290dd57, 0x51a99b2b), WTCP(0x625305a0, 0x51f40692), WTCP(0x6214ed7d, 0x523e4cf5), WTCP(0x61d69541, 0x52886dc5), + WTCP(0x6197fd3e, 0x52d26875), WTCP(0x615925c9, 0x531c3c77), WTCP(0x611a0f39, 0x5365e93e), WTCP(0x60dab9e3, 0x53af6e3e), + WTCP(0x609b2621, 0x53f8caed), WTCP(0x605b544c, 0x5441fec0), WTCP(0x601b44bf, 0x548b092e), WTCP(0x5fdaf7d5, 0x54d3e9ae), + WTCP(0x5f9a6deb, 0x551c9fb7), WTCP(0x5f59a761, 0x55652ac3), WTCP(0x5f18a494, 0x55ad8a4d), WTCP(0x5ed765e6, 0x55f5bdcd), + WTCP(0x5e95ebb8, 0x563dc4c1), WTCP(0x5e54366d, 0x56859ea3), WTCP(0x5e12466a, 0x56cd4af3), WTCP(0x5dd01c13, 0x5714c92d), + WTCP(0x5d8db7cf, 0x575c18d0), WTCP(0x5d4b1a05, 0x57a3395e), WTCP(0x5d08431e, 0x57ea2a56), WTCP(0x5cc53384, 0x5830eb3a), + WTCP(0x5c81eba0, 0x58777b8e), WTCP(0x5c3e6bdf, 0x58bddad5), WTCP(0x5bfab4af, 0x59040893), WTCP(0x5bb6c67c, 0x594a044f), + WTCP(0x5b72a1b6, 0x598fcd8e), WTCP(0x5b2e46ce, 0x59d563d9), WTCP(0x5ae9b634, 0x5a1ac6b8), WTCP(0x5aa4f05a, 0x5a5ff5b5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow120[] = +{ + WTCP(0x7fff4c54, 0x00d676eb), WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7fdd9dad, 0x05dcbcbe), + WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fab1d3d, 0x093516d4), WTCP(0x7f8975f9, 0x0ae0b22c), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7f3560b9, 0x0e3667ad), WTCP(0x7f02f66f, 0x0fe05c64), WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e8d6d91, 0x13321c53), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7e01b096, 0x16807e15), WTCP(0x7db3860f, 0x18263d36), WTCP(0x7d5fd801, 0x19caed29), + WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7ca80038, 0x1d10d5c2), WTCP(0x7c43de8e, 0x1eb1e9a7), WTCP(0x7bda497d, 0x2051a4dd), + WTCP(0x7b6b45a5, 0x21eff528), WTCP(0x7af6d7e6, 0x238cc85d), WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x79fdd35c, 0x26c1af22), + WTCP(0x7979477d, 0x28599eb0), WTCP(0x78ef678f, 0x29efc925), WTCP(0x7860399e, 0x2b841caf), WTCP(0x77cbc3f2, 0x2d168792), + WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76931bae, 0x30355cdd), WTCP(0x75eef6ce, 0x31c1a43b), WTCP(0x7545a5a0, 0x334bbcde), + WTCP(0x74972f92, 0x34d3957e), WTCP(0x73e39c49, 0x36591cea), WTCP(0x732af3a7, 0x37dc420c), WTCP(0x726d3dc6, 0x395cf3e9), + WTCP(0x71aa82f7, 0x3adb21a1), WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x701620f5, 0x3dcfadb0), WTCP(0x6f448b7e, 0x3f45ead8), + WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6d92c59b, 0x422a0154), WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x6bcdc639, 0x45027c0c), + WTCP(0x6ae429ae, 0x466a36f9), WTCP(0x69f5dcd3, 0x47cedb31), WTCP(0x6902ea1d, 0x4930590f), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x670f3df3, 0x4be9a3db), WTCP(0x660e9a6a, 0x4d415234), WTCP(0x65097cdb, 0x4e959d08), WTCP(0x63fff0ba, 0x4fe6756a), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x61dfbb8a, 0x527d93e6), WTCP(0x60c92a5a, 0x53c3bcea), WTCP(0x5fae5a55, 0x55063951), + WTCP(0x5e8f57e2, 0x5644faf4), WTCP(0x5d6c2f99, 0x577ff3da), WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5b19a0c8, 0x59ea5454), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow120[] = +{ + WTCP(0x7ffffffe, 0x00017b6f), WTCP(0x7fffffef, 0x00042d2f), WTCP(0x7fffffbb, 0x000849d0), WTCP(0x7fffff36, 0x000e3494), + WTCP(0x7ffffe0c, 0x00165efd), WTCP(0x7ffffbac, 0x002149be), WTCP(0x7ffff72e, 0x002f854c), WTCP(0x7fffef24, 0x0041b235), + WTCP(0x7fffe167, 0x0058814f), WTCP(0x7fffcacd, 0x0074b3af), WTCP(0x7fffa6d0, 0x00971a67), WTCP(0x7fff6f1e, 0x00c0960e), + WTCP(0x7fff1b12, 0x00f21602), WTCP(0x7ffe9f0b, 0x012c9775), WTCP(0x7ffdebb2, 0x01712428), WTCP(0x7ffced1b, 0x01c0d0f7), + WTCP(0x7ffb89c2, 0x021cbc12), WTCP(0x7ff9a17c, 0x02860b05), WTCP(0x7ff70c39, 0x02fde875), WTCP(0x7ff398bc, 0x038581b3), + WTCP(0x7fef0b3b, 0x041e040c), WTCP(0x7fe91bf3, 0x04c899f4), WTCP(0x7fe175ba, 0x05866803), WTCP(0x7fd7b493, 0x065889d5), + WTCP(0x7fcb6459, 0x07400ed4), WTCP(0x7fbbff82, 0x083df6e9), WTCP(0x7fa8ee09, 0x09532f37), WTCP(0x7f91849a, 0x0a808ed1), + WTCP(0x7f7503f2, 0x0bc6d381), WTCP(0x7f52989a, 0x0d269eb0), WTCP(0x7f295af4, 0x0ea07270), WTCP(0x7ef84fb6, 0x1034aeb6), + WTCP(0x7ebe68c5, 0x11e38ed2), WTCP(0x7e7a8686, 0x13ad2733), WTCP(0x7e2b79a3, 0x1591636d), WTCP(0x7dd0053c, 0x179004a7), + WTCP(0x7d66e18b, 0x19a8a05f), WTCP(0x7ceebef0, 0x1bda9fa2), WTCP(0x7c664953, 0x1e253ea1), WTCP(0x7bcc2be8, 0x20878cce), + WTCP(0x7b1f1526, 0x23006d5d), WTCP(0x7a5dbb01, 0x258e9848), WTCP(0x7986df3e, 0x28309bc6), WTCP(0x789953e0, 0x2ae4de3e), + WTCP(0x7793ff88, 0x2da9a0a8), WTCP(0x7675e1cc, 0x307d0163), WTCP(0x753e1763, 0x335cff72), WTCP(0x73ebde10, 0x36477e1f), + WTCP(0x727e984e, 0x393a48f1), WTCP(0x70f5d09b, 0x3c3317f9), WTCP(0x6f513c60, 0x3f2f945c), WTCP(0x6d90be61, 0x422d5d18), + WTCP(0x6bb468b1, 0x452a0bf3), WTCP(0x69bc7e1e, 0x48233a81), WTCP(0x67a97317, 0x4b16873e), WTCP(0x657bedfa, 0x4e019a9d), + WTCP(0x6334c6d2, 0x50e22c0b), WTCP(0x60d50689, 0x53b606cb), WTCP(0x5e5de588, 0x567b0ea7), WTCP(0x5bd0c9c6, 0x592f4460), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow512[] = +{ + WTCP(0x7ffff621, 0x003243f5), WTCP(0x7fffa72c, 0x0096cbc1), WTCP(0x7fff0943, 0x00fb5330), WTCP(0x7ffe1c65, 0x015fda03), + WTCP(0x7ffce093, 0x01c45ffe), WTCP(0x7ffb55ce, 0x0228e4e2), WTCP(0x7ff97c18, 0x028d6870), WTCP(0x7ff75370, 0x02f1ea6c), + WTCP(0x7ff4dbd9, 0x03566a96), WTCP(0x7ff21553, 0x03bae8b2), WTCP(0x7feeffe1, 0x041f6480), WTCP(0x7feb9b85, 0x0483ddc3), + WTCP(0x7fe7e841, 0x04e8543e), WTCP(0x7fe3e616, 0x054cc7b1), WTCP(0x7fdf9508, 0x05b137df), WTCP(0x7fdaf519, 0x0615a48b), + WTCP(0x7fd6064c, 0x067a0d76), WTCP(0x7fd0c8a3, 0x06de7262), WTCP(0x7fcb3c23, 0x0742d311), WTCP(0x7fc560cf, 0x07a72f45), + WTCP(0x7fbf36aa, 0x080b86c2), WTCP(0x7fb8bdb8, 0x086fd947), WTCP(0x7fb1f5fc, 0x08d42699), WTCP(0x7faadf7c, 0x09386e78), + WTCP(0x7fa37a3c, 0x099cb0a7), WTCP(0x7f9bc640, 0x0a00ece8), WTCP(0x7f93c38c, 0x0a6522fe), WTCP(0x7f8b7227, 0x0ac952aa), + WTCP(0x7f82d214, 0x0b2d7baf), WTCP(0x7f79e35a, 0x0b919dcf), WTCP(0x7f70a5fe, 0x0bf5b8cb), WTCP(0x7f671a05, 0x0c59cc68), + WTCP(0x7f5d3f75, 0x0cbdd865), WTCP(0x7f531655, 0x0d21dc87), WTCP(0x7f489eaa, 0x0d85d88f), WTCP(0x7f3dd87c, 0x0de9cc40), + WTCP(0x7f32c3d1, 0x0e4db75b), WTCP(0x7f2760af, 0x0eb199a4), WTCP(0x7f1baf1e, 0x0f1572dc), WTCP(0x7f0faf25, 0x0f7942c7), + WTCP(0x7f0360cb, 0x0fdd0926), WTCP(0x7ef6c418, 0x1040c5bb), WTCP(0x7ee9d914, 0x10a4784b), WTCP(0x7edc9fc6, 0x11082096), + WTCP(0x7ecf1837, 0x116bbe60), WTCP(0x7ec14270, 0x11cf516a), WTCP(0x7eb31e78, 0x1232d979), WTCP(0x7ea4ac58, 0x1296564d), + WTCP(0x7e95ec1a, 0x12f9c7aa), WTCP(0x7e86ddc6, 0x135d2d53), WTCP(0x7e778166, 0x13c0870a), WTCP(0x7e67d703, 0x1423d492), + WTCP(0x7e57dea7, 0x148715ae), WTCP(0x7e47985b, 0x14ea4a1f), WTCP(0x7e37042a, 0x154d71aa), WTCP(0x7e26221f, 0x15b08c12), + WTCP(0x7e14f242, 0x16139918), WTCP(0x7e0374a0, 0x1676987f), WTCP(0x7df1a942, 0x16d98a0c), WTCP(0x7ddf9034, 0x173c6d80), + WTCP(0x7dcd2981, 0x179f429f), WTCP(0x7dba7534, 0x1802092c), WTCP(0x7da77359, 0x1864c0ea), WTCP(0x7d9423fc, 0x18c7699b), + WTCP(0x7d808728, 0x192a0304), WTCP(0x7d6c9ce9, 0x198c8ce7), WTCP(0x7d58654d, 0x19ef0707), WTCP(0x7d43e05e, 0x1a517128), + WTCP(0x7d2f0e2b, 0x1ab3cb0d), WTCP(0x7d19eebf, 0x1b161479), WTCP(0x7d048228, 0x1b784d30), WTCP(0x7ceec873, 0x1bda74f6), + WTCP(0x7cd8c1ae, 0x1c3c8b8c), WTCP(0x7cc26de5, 0x1c9e90b8), WTCP(0x7cabcd28, 0x1d00843d), WTCP(0x7c94df83, 0x1d6265dd), + WTCP(0x7c7da505, 0x1dc4355e), WTCP(0x7c661dbc, 0x1e25f282), WTCP(0x7c4e49b7, 0x1e879d0d), WTCP(0x7c362904, 0x1ee934c3), + WTCP(0x7c1dbbb3, 0x1f4ab968), WTCP(0x7c0501d2, 0x1fac2abf), WTCP(0x7bebfb70, 0x200d888d), WTCP(0x7bd2a89e, 0x206ed295), + WTCP(0x7bb9096b, 0x20d0089c), WTCP(0x7b9f1de6, 0x21312a65), WTCP(0x7b84e61f, 0x219237b5), WTCP(0x7b6a6227, 0x21f3304f), + WTCP(0x7b4f920e, 0x225413f8), WTCP(0x7b3475e5, 0x22b4e274), WTCP(0x7b190dbc, 0x23159b88), WTCP(0x7afd59a4, 0x23763ef7), + WTCP(0x7ae159ae, 0x23d6cc87), WTCP(0x7ac50dec, 0x243743fa), WTCP(0x7aa8766f, 0x2497a517), WTCP(0x7a8b9348, 0x24f7efa2), + WTCP(0x7a6e648a, 0x2558235f), WTCP(0x7a50ea47, 0x25b84012), WTCP(0x7a332490, 0x26184581), WTCP(0x7a151378, 0x26783370), + WTCP(0x79f6b711, 0x26d809a5), WTCP(0x79d80f6f, 0x2737c7e3), WTCP(0x79b91ca4, 0x27976df1), WTCP(0x7999dec4, 0x27f6fb92), + WTCP(0x797a55e0, 0x2856708d), WTCP(0x795a820e, 0x28b5cca5), WTCP(0x793a6361, 0x29150fa1), WTCP(0x7919f9ec, 0x29743946), + WTCP(0x78f945c3, 0x29d34958), WTCP(0x78d846fb, 0x2a323f9e), WTCP(0x78b6fda8, 0x2a911bdc), WTCP(0x789569df, 0x2aefddd8), + WTCP(0x78738bb3, 0x2b4e8558), WTCP(0x7851633b, 0x2bad1221), WTCP(0x782ef08b, 0x2c0b83fa), WTCP(0x780c33b8, 0x2c69daa6), + WTCP(0x77e92cd9, 0x2cc815ee), WTCP(0x77c5dc01, 0x2d263596), WTCP(0x77a24148, 0x2d843964), WTCP(0x777e5cc3, 0x2de2211e), + WTCP(0x775a2e89, 0x2e3fec8b), WTCP(0x7735b6af, 0x2e9d9b70), WTCP(0x7710f54c, 0x2efb2d95), WTCP(0x76ebea77, 0x2f58a2be), + WTCP(0x76c69647, 0x2fb5fab2), WTCP(0x76a0f8d2, 0x30133539), WTCP(0x767b1231, 0x30705217), WTCP(0x7654e279, 0x30cd5115), + WTCP(0x762e69c4, 0x312a31f8), WTCP(0x7607a828, 0x3186f487), WTCP(0x75e09dbd, 0x31e39889), WTCP(0x75b94a9c, 0x32401dc6), + WTCP(0x7591aedd, 0x329c8402), WTCP(0x7569ca99, 0x32f8cb07), WTCP(0x75419de7, 0x3354f29b), WTCP(0x751928e0, 0x33b0fa84), + WTCP(0x74f06b9e, 0x340ce28b), WTCP(0x74c7663a, 0x3468aa76), WTCP(0x749e18cd, 0x34c4520d), WTCP(0x74748371, 0x351fd918), + WTCP(0x744aa63f, 0x357b3f5d), WTCP(0x74208150, 0x35d684a6), WTCP(0x73f614c0, 0x3631a8b8), WTCP(0x73cb60a8, 0x368cab5c), + WTCP(0x73a06522, 0x36e78c5b), WTCP(0x73752249, 0x37424b7b), WTCP(0x73499838, 0x379ce885), WTCP(0x731dc70a, 0x37f76341), + WTCP(0x72f1aed9, 0x3851bb77), WTCP(0x72c54fc1, 0x38abf0ef), WTCP(0x7298a9dd, 0x39060373), WTCP(0x726bbd48, 0x395ff2c9), + WTCP(0x723e8a20, 0x39b9bebc), WTCP(0x7211107e, 0x3a136712), WTCP(0x71e35080, 0x3a6ceb96), WTCP(0x71b54a41, 0x3ac64c0f), + WTCP(0x7186fdde, 0x3b1f8848), WTCP(0x71586b74, 0x3b78a007), WTCP(0x7129931f, 0x3bd19318), WTCP(0x70fa74fc, 0x3c2a6142), + WTCP(0x70cb1128, 0x3c830a50), WTCP(0x709b67c0, 0x3cdb8e09), WTCP(0x706b78e3, 0x3d33ec39), WTCP(0x703b44ad, 0x3d8c24a8), + WTCP(0x700acb3c, 0x3de4371f), WTCP(0x6fda0cae, 0x3e3c2369), WTCP(0x6fa90921, 0x3e93e950), WTCP(0x6f77c0b3, 0x3eeb889c), + WTCP(0x6f463383, 0x3f430119), WTCP(0x6f1461b0, 0x3f9a5290), WTCP(0x6ee24b57, 0x3ff17cca), WTCP(0x6eaff099, 0x40487f94), + WTCP(0x6e7d5193, 0x409f5ab6), WTCP(0x6e4a6e66, 0x40f60dfb), WTCP(0x6e174730, 0x414c992f), WTCP(0x6de3dc11, 0x41a2fc1a), + WTCP(0x6db02d29, 0x41f93689), WTCP(0x6d7c3a98, 0x424f4845), WTCP(0x6d48047e, 0x42a5311b), WTCP(0x6d138afb, 0x42faf0d4), + WTCP(0x6cdece2f, 0x4350873c), WTCP(0x6ca9ce3b, 0x43a5f41e), WTCP(0x6c748b3f, 0x43fb3746), WTCP(0x6c3f055d, 0x4450507e), + WTCP(0x6c093cb6, 0x44a53f93), WTCP(0x6bd3316a, 0x44fa0450), WTCP(0x6b9ce39b, 0x454e9e80), WTCP(0x6b66536b, 0x45a30df0), + WTCP(0x6b2f80fb, 0x45f7526b), WTCP(0x6af86c6c, 0x464b6bbe), WTCP(0x6ac115e2, 0x469f59b4), WTCP(0x6a897d7d, 0x46f31c1a), + WTCP(0x6a51a361, 0x4746b2bc), WTCP(0x6a1987b0, 0x479a1d67), WTCP(0x69e12a8c, 0x47ed5be6), WTCP(0x69a88c19, 0x48406e08), + WTCP(0x696fac78, 0x48935397), WTCP(0x69368bce, 0x48e60c62), WTCP(0x68fd2a3d, 0x49389836), WTCP(0x68c387e9, 0x498af6df), + WTCP(0x6889a4f6, 0x49dd282a), WTCP(0x684f8186, 0x4a2f2be6), WTCP(0x68151dbe, 0x4a8101de), WTCP(0x67da79c3, 0x4ad2a9e2), + WTCP(0x679f95b7, 0x4b2423be), WTCP(0x676471c0, 0x4b756f40), WTCP(0x67290e02, 0x4bc68c36), WTCP(0x66ed6aa1, 0x4c177a6e), + WTCP(0x66b187c3, 0x4c6839b7), WTCP(0x6675658c, 0x4cb8c9dd), WTCP(0x66390422, 0x4d092ab0), WTCP(0x65fc63a9, 0x4d595bfe), + WTCP(0x65bf8447, 0x4da95d96), WTCP(0x65826622, 0x4df92f46), WTCP(0x6545095f, 0x4e48d0dd), WTCP(0x65076e25, 0x4e984229), + WTCP(0x64c99498, 0x4ee782fb), WTCP(0x648b7ce0, 0x4f369320), WTCP(0x644d2722, 0x4f857269), WTCP(0x640e9386, 0x4fd420a4), + WTCP(0x63cfc231, 0x50229da1), WTCP(0x6390b34a, 0x5070e92f), WTCP(0x635166f9, 0x50bf031f), WTCP(0x6311dd64, 0x510ceb40), + WTCP(0x62d216b3, 0x515aa162), WTCP(0x6292130c, 0x51a82555), WTCP(0x6251d298, 0x51f576ea), WTCP(0x6211557e, 0x524295f0), + WTCP(0x61d09be5, 0x528f8238), WTCP(0x618fa5f7, 0x52dc3b92), WTCP(0x614e73da, 0x5328c1d0), WTCP(0x610d05b7, 0x537514c2), + WTCP(0x60cb5bb7, 0x53c13439), WTCP(0x60897601, 0x540d2005), WTCP(0x604754bf, 0x5458d7f9), WTCP(0x6004f819, 0x54a45be6), + WTCP(0x5fc26038, 0x54efab9c), WTCP(0x5f7f8d46, 0x553ac6ee), WTCP(0x5f3c7f6b, 0x5585adad), WTCP(0x5ef936d1, 0x55d05faa), + WTCP(0x5eb5b3a2, 0x561adcb9), WTCP(0x5e71f606, 0x566524aa), WTCP(0x5e2dfe29, 0x56af3750), WTCP(0x5de9cc33, 0x56f9147e), + WTCP(0x5da5604f, 0x5742bc06), WTCP(0x5d60baa7, 0x578c2dba), WTCP(0x5d1bdb65, 0x57d5696d), WTCP(0x5cd6c2b5, 0x581e6ef1), + WTCP(0x5c9170bf, 0x58673e1b), WTCP(0x5c4be5b0, 0x58afd6bd), WTCP(0x5c0621b2, 0x58f838a9), WTCP(0x5bc024f0, 0x594063b5), + WTCP(0x5b79ef96, 0x598857b2), WTCP(0x5b3381ce, 0x59d01475), WTCP(0x5aecdbc5, 0x5a1799d1), WTCP(0x5aa5fda5, 0x5a5ee79a), +}; + +/* The window coefficients are calculated according to the formula: + * N=FRAME_LEN_LONG_LD480 + * win[n]=sin(pi*(n+0.5)/(2*N)) for n=0,..,N-1 */ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow480[480] = +{ + WTCP(0x7ffff4c5, 0x00359dd2), WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ffdd9c4, 0x01774eb2), + WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ffab147, 0x024dbff4), WTCP(0x7ff8964d, 0x02b8f64e), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7ff352e8, 0x038f5cfb), WTCP(0x7ff02a82, 0x03fa8cb8), WTCP(0x7feca851, 0x0465b9aa), WTCP(0x7fe8cc57, 0x04d0e386), + WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fdb1dd5, 0x06124ba5), WTCP(0x7fd5dad8, 0x067d6639), + WTCP(0x7fd03e23, 0x06e87c3f), WTCP(0x7fca47b9, 0x07538d6b), WTCP(0x7fc3f7a0, 0x07be9973), WTCP(0x7fbd4dda, 0x0829a00c), + WTCP(0x7fb64a6e, 0x0894a0ea), WTCP(0x7faeed5f, 0x08ff9bc2), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f9f2671, 0x09d57e35), + WTCP(0x7f96bc9c, 0x0a40653a), WTCP(0x7f8df93c, 0x0aab450d), WTCP(0x7f84dc55, 0x0b161d63), WTCP(0x7f7b65ef, 0x0b80edf1), + WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f676cc0, 0x0c56768a), WTCP(0x7f5cea05, 0x0cc12dff), WTCP(0x7f520de6, 0x0d2bdc80), + WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f3b499d, 0x0e011d7c), WTCP(0x7f2f6183, 0x0e6baf61), WTCP(0x7f232026, 0x0ed63727), + WTCP(0x7f16858e, 0x0f40b483), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7efc44d0, 0x10158ed4), WTCP(0x7eee9ebe, 0x107feb33), + WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7ed24761, 0x115480e9), WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7eb48bfb, 0x1228e5f8), + WTCP(0x7ea528e0, 0x12930586), WTCP(0x7e956ce1, 0x12fd180b), WTCP(0x7e85580c, 0x13671d3d), WTCP(0x7e74ea6a, 0x13d114d0), + WTCP(0x7e642408, 0x143afe7b), WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e418d32, 0x150ea6ef), WTCP(0x7e2fbcd6, 0x15786522), + WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7e0b127a, 0x164bb40b), WTCP(0x7df83895, 0x16b5442b), WTCP(0x7de50646, 0x171ec45c), + WTCP(0x7dd17b9c, 0x17883452), WTCP(0x7dbd98a4, 0x17f193c5), WTCP(0x7da95d6c, 0x185ae269), WTCP(0x7d94ca03, 0x18c41ff6), + WTCP(0x7d7fde76, 0x192d4c21), WTCP(0x7d6a9ad5, 0x199666a0), WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7d3f0b90, 0x1a686575), + WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7d121cb0, 0x1b3a1a28), WTCP(0x7cfb218c, 0x1ba2d7fc), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7ccc2430, 0x1c74192a), WTCP(0x7cb42217, 0x1cdc9bf2), WTCP(0x7c9bc87a, 0x1d450a78), WTCP(0x7c831767, 0x1dad6473), + WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c36f824, 0x1ee5f447), WTCP(0x7c1ce9ef, 0x1f4df93a), + WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7be7c847, 0x201dc0ef), WTCP(0x7bccb4f8, 0x2085831f), WTCP(0x7bb14ac5, 0x20ed2e7b), + WTCP(0x7b9589c3, 0x2154c2bb), WTCP(0x7b797205, 0x21bc3f97), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b403ea2, 0x228af1fe), + WTCP(0x7b232325, 0x22f226f8), WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7ae7e8fc, 0x23c04710), WTCP(0x7ac9ca7a, 0x2427319d), + WTCP(0x7aab55ca, 0x248e02cb), WTCP(0x7a8c8b01, 0x24f4ba50), WTCP(0x7a6d6a37, 0x255b57e6), WTCP(0x7a4df380, 0x25c1db44), + WTCP(0x7a2e26f2, 0x26284422), WTCP(0x7a0e04a4, 0x268e9238), WTCP(0x79ed8cad, 0x26f4c53e), WTCP(0x79ccbf22, 0x275adcee), + WTCP(0x79ab9c1c, 0x27c0d8fe), WTCP(0x798a23b1, 0x2826b928), WTCP(0x796855f9, 0x288c7d24), WTCP(0x7946330c, 0x28f224ab), + WTCP(0x7923bb01, 0x2957af74), WTCP(0x7900edf2, 0x29bd1d3a), WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78ba5524, 0x2a87a09d), + WTCP(0x78968998, 0x2aecb5ac), WTCP(0x7872696a, 0x2b51ac9a), WTCP(0x784df4b3, 0x2bb68522), WTCP(0x78292b8d, 0x2c1b3efb), + WTCP(0x78040e12, 0x2c7fd9e0), WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x77b8d683, 0x2d48b1b1), WTCP(0x7792bca5, 0x2dacee11), + WTCP(0x776c4edb, 0x2e110a62), WTCP(0x77458d40, 0x2e75065e), WTCP(0x771e77f0, 0x2ed8e1c0), WTCP(0x76f70f05, 0x2f3c9c40), + WTCP(0x76cf529c, 0x2fa03599), WTCP(0x76a742d1, 0x3003ad85), WTCP(0x767edfbe, 0x306703bf), WTCP(0x76562982, 0x30ca3800), + WTCP(0x762d2038, 0x312d4a03), WTCP(0x7603c3fd, 0x31903982), WTCP(0x75da14ef, 0x31f30638), WTCP(0x75b01329, 0x3255afe0), + WTCP(0x7585becb, 0x32b83634), WTCP(0x755b17f2, 0x331a98ef), WTCP(0x75301ebb, 0x337cd7cd), WTCP(0x7504d345, 0x33def287), + WTCP(0x74d935ae, 0x3440e8da), WTCP(0x74ad4615, 0x34a2ba81), WTCP(0x74810499, 0x35046736), WTCP(0x74547158, 0x3565eeb6), + WTCP(0x74278c72, 0x35c750bc), WTCP(0x73fa5607, 0x36288d03), WTCP(0x73ccce36, 0x3689a348), WTCP(0x739ef51f, 0x36ea9346), + WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x73424fa0, 0x37abff5d), WTCP(0x73138379, 0x380c7aee), WTCP(0x72e4668f, 0x386ccf2a), + WTCP(0x72b4f902, 0x38ccfbcb), WTCP(0x72853af3, 0x392d008f), WTCP(0x72552c85, 0x398cdd32), WTCP(0x7224cdd8, 0x39ec9172), + WTCP(0x71f41f0f, 0x3a4c1d09), WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x7191d1b1, 0x3b0ab937), WTCP(0x71603361, 0x3b69c947), + WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70fc082d, 0x3c276c0d), WTCP(0x70c97b90, 0x3c85fe3d), WTCP(0x70969fca, 0x3ce465f3), + WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x702ffb54, 0x3da0b4e7), WTCP(0x6ffc32eb, 0x3dfe9ba1), WTCP(0x6fc81bea, 0x3e5c56d8), + WTCP(0x6f93b676, 0x3eb9e64b), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6f2a00c4, 0x3f7480dd), WTCP(0x6ef4b0d1, 0x3fd18b7a), + WTCP(0x6ebf12ff, 0x402e694c), WTCP(0x6e892772, 0x408b1a12), WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6e1c67c4, 0x4143f379), + WTCP(0x6de593ee, 0x41a01b97), WTCP(0x6dae72f7, 0x41fc15a6), WTCP(0x6d770506, 0x4257e166), WTCP(0x6d3f4a40, 0x42b37e96), + WTCP(0x6d0742cf, 0x430eecf6), WTCP(0x6cceeed8, 0x436a2c45), WTCP(0x6c964e83, 0x43c53c44), WTCP(0x6c5d61f9, 0x44201cb2), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6beaa4e2, 0x44d54ddf), WTCP(0x6bb0d4a7, 0x452f9e1e), WTCP(0x6b76b8d6, 0x4589bdcf), + WTCP(0x6b3c519a, 0x45e3acb1), WTCP(0x6b019f1a, 0x463d6a87), WTCP(0x6ac6a180, 0x4696f710), WTCP(0x6a8b58f6, 0x46f0520f), + WTCP(0x6a4fc5a6, 0x47497b44), WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x699b4cad, 0x4853c9b9), + WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x69218929, 0x490455f4), WTCP(0x68e438a4, 0x495c4f52), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x6868baec, 0x4a0ba75b), WTCP(0x682a8e0f, 0x4a63058a), WTCP(0x67ec1817, 0x4aba2f84), WTCP(0x67ad592f, 0x4b11250c), + WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x66ef6891, 0x4c14c894), WTCP(0x66af87a4, 0x4c6ae9f2), + WTCP(0x666f5ea6, 0x4cc0d5ae), WTCP(0x662eedc3, 0x4d168b8b), WTCP(0x65ee3529, 0x4d6c0b4e), WTCP(0x65ad3505, 0x4dc154bb), + WTCP(0x656bed84, 0x4e166795), WTCP(0x652a5ed6, 0x4e6b43a2), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x64a66ca5, 0x4f145662), + WTCP(0x6464097f, 0x4f688ca0), WTCP(0x64215fe5, 0x4fbc8b22), WTCP(0x63de7003, 0x501051ae), WTCP(0x639b3a0b, 0x5063e008), + WTCP(0x6357be2a, 0x50b735f8), WTCP(0x6313fc90, 0x510a5340), WTCP(0x62cff56c, 0x515d37a9), WTCP(0x628ba8ef, 0x51afe2f6), + WTCP(0x62471749, 0x520254ef), WTCP(0x620240a8, 0x52548d59), WTCP(0x61bd253f, 0x52a68bfb), WTCP(0x6177c53c, 0x52f8509b), + WTCP(0x613220d2, 0x5349daff), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x60a60b88, 0x53ec4032), WTCP(0x605f9b0b, 0x543d1a8e), + WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5fd1ef59, 0x54de1db1), WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5f4336a7, 0x557e3292), + WTCP(0x5efb75ea, 0x55cde31e), WTCP(0x5eb37285, 0x561d5771), WTCP(0x5e6b2ca8, 0x566c8f55), WTCP(0x5e22a487, 0x56bb8a90), + WTCP(0x5dd9da55, 0x570a48ec), WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5d47808a, 0x57a70e29), WTCP(0x5cfdf157, 0x57f5149d), + WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5c6a0f59, 0x5890681a), WTCP(0x5c1fbcf6, 0x58ddb4b8), WTCP(0x5bd529eb, 0x592ac2f7), + WTCP(0x5b8a566c, 0x597792a1), WTCP(0x5b3f42ae, 0x59c42381), WTCP(0x5af3eee6, 0x5a107561), WTCP(0x5aa85b48, 0x5a5c880a), +}; + + + + + + +/** + * \brief Helper table containing the length, rasterand shape mapping to individual window slope tables. + * [0: sine ][0: radix2 raster ][ceil(log2(length)) length 4 .. 1024 ] + * [1: 10ms raster ][ceil(log2(length)) length 3.25 .. 960 ] + * [2: 3/4 of radix 2 raster][ceil(log2(length)) length 3 .. 768 ] + * [1: KBD ][0: radix2 raster ][ceil(log2(length)) length 128 .. 1024 ] + * [1: 10ms raster ][ceil(log2(length)) length 120 .. 960 ] + * [2: 3/4 of radix 2 raster][ceil(log2(length)) length 96 .. 768 ] + */ +const FIXP_WTP *const windowSlopes[2][3][9] = +{ + { /* Sine */ + { /* Radix 2 */ + NULL, + NULL, + NULL, + SineWindow32, + SineWindow64, + SineWindow128, + NULL, + SineWindow512, + SineWindow1024 + }, + { /* 10ms raster */ + NULL, /* 3.25 */ + NULL, /* 7.5 */ + NULL, + NULL, + NULL, + SineWindow120, + NULL, + SineWindow480, + SineWindow960 + }, + { /* 3/4 radix2 raster */ + NULL, /* 3 */ + NULL, /* 6 */ +#ifdef INCLUDE_SineWindow12 + SineWindow12, +#else + NULL, +#endif + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + } + }, + { /* KBD */ + { /* Radix 2 */ + KBDWindow128, + NULL, + SineWindow512, + KBDWindow1024 + }, + { /* 10ms raster */ + KBDWindow120, + NULL, + SineWindow480, + KBDWindow960 + }, + { /* 3/4 radix2 raster */ + NULL, + NULL, + NULL, + NULL + } + } +}; + +const FIXP_WTP * FDKgetWindowSlope(int length, int shape) +{ + const FIXP_WTP * w = NULL; + int raster, ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS-1-fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ( (length) >> (ld2_length-2) ) { + case 0x8: /* radix 2 */ + raster = 0; + ld2_length--; /* revert + 1 because of ceil(log2(length)) from above. */ + break; + case 0xf: /* 10 ms */ + raster = 1; + break; + case 0xc: /* 3/4 of radix 2 */ + raster = 2; + break; + default: + raster = 0; + break; + } + + /* The table for sine windows (shape == 0) is 5 entries longer. */ + if (shape == 1) { + ld2_length-=5; + } + + /* Look up table */ + w = windowSlopes[shape&1][raster][ld2_length]; + + FDK_ASSERT(w != NULL); + + return w; +} + + +/* + * QMF filter and twiddle tables + */ + +#ifdef QMF_COEFF_16BIT +#define QFC(x) FX_DBL2FXCONST_SGL(x) +#define QTCFL(x) FL2FXCONST_SGL(x) +#define QTC(x) FX_DBL2FXCONST_SGL(x) +#else +#define QFC(x) ((FIXP_DBL)(x)) +#define QTCFL(x) FL2FXCONST_DBL(x) +#define QTC(x) ((FIXP_DBL)(x)) +#endif /* ARCH_PREFER_MULT_32x16 */ + +#ifndef LOW_POWER_SBR_ONLY +/*! + \name QMF-Twiddle + \brief QMF twiddle factors + + L=32, gain=2.0, angle = 0.75 +*/ + +const FIXP_QTW qmf_phaseshift_cos32[32] = +{ + QTCFL( 0.99932238458835f),QTCFL( 0.99390697000236f),QTCFL( 0.98310548743122f),QTCFL( 0.96697647104485f), + QTCFL( 0.94560732538052f),QTCFL( 0.91911385169006f),QTCFL( 0.88763962040285f),QTCFL( 0.85135519310527f), + QTCFL( 0.81045719825259f),QTCFL( 0.76516726562246f),QTCFL( 0.71573082528382f),QTCFL( 0.66241577759017f), + QTCFL( 0.60551104140433f),QTCFL( 0.54532498842205f),QTCFL( 0.48218377207912f),QTCFL( 0.41642956009764f), + QTCFL( 0.34841868024943f),QTCFL( 0.27851968938505f),QTCFL( 0.20711137619222f),QTCFL( 0.13458070850713f), + QTCFL( 0.06132073630221f),QTCFL(-0.01227153828572f),QTCFL(-0.08579731234444f),QTCFL(-0.15885814333386f), + QTCFL(-0.23105810828067f),QTCFL(-0.30200594931923f),QTCFL(-0.37131719395184f),QTCFL(-0.43861623853853f), + QTCFL(-0.50353838372572f),QTCFL(-0.56573181078361f),QTCFL(-0.62485948814239f),QTCFL(-0.68060099779545f) +}; + +const FIXP_QTW qmf_phaseshift_sin32[32] = +{ + QTCFL( 0.03680722294136f),QTCFL( 0.11022220729388f),QTCFL( 0.18303988795514f),QTCFL( 0.25486565960451f), + QTCFL( 0.32531029216226f),QTCFL( 0.39399204006105f),QTCFL( 0.46053871095824f),QTCFL( 0.52458968267847f), + QTCFL( 0.58579785745644f),QTCFL( 0.64383154288979f),QTCFL( 0.69837624940897f),QTCFL( 0.74913639452346f), + QTCFL( 0.79583690460888f),QTCFL( 0.83822470555484f),QTCFL( 0.87607009419541f),QTCFL( 0.90916798309052f), + QTCFL( 0.93733901191257f),QTCFL( 0.96043051941557f),QTCFL( 0.97831737071963f),QTCFL( 0.99090263542778f), + QTCFL( 0.99811811290015f),QTCFL( 0.99992470183914f),QTCFL( 0.99631261218278f),QTCFL( 0.98730141815786f), + QTCFL( 0.97293995220556f),QTCFL( 0.95330604035419f),QTCFL( 0.92850608047322f),QTCFL( 0.89867446569395f), + QTCFL( 0.86397285612159f),QTCFL( 0.82458930278503f),QTCFL( 0.78073722857209f),QTCFL( 0.73265427167241f) +}; +const FIXP_QTW qmf_phaseshift_cos64[64] = { + QTC(0x7ff62181), QTC(0x7fa736b3), QTC(0x7f0991c3), QTC(0x7e1d93e9), QTC(0x7ce3ceb1), QTC(0x7b5d039d), QTC(0x798a23b0), QTC(0x776c4eda), + QTC(0x7504d344), QTC(0x72552c84), QTC(0x6f5f02b1), QTC(0x6c24295f), QTC(0x68a69e80), QTC(0x64e88925), QTC(0x60ec382f), QTC(0x5cb420df), + QTC(0x5842dd54), QTC(0x539b2aef), QTC(0x4ebfe8a4), QTC(0x49b41533), QTC(0x447acd50), QTC(0x3f1749b7), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), QTC(0x15e21444), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf), + QTC(0xfcdbd541), QTC(0xf6956fb7), QTC(0xf054d8d5), QTC(0xea1debbc), QTC(0xe3f47d96), QTC(0xdddc5b3b), QTC(0xd7d946d8), QTC(0xd1eef59e), + QTC(0xcc210d79), QTC(0xc67322ce), QTC(0xc0e8b649), QTC(0xbb8532b0), QTC(0xb64beacd), QTC(0xb140175c), QTC(0xac64d511), QTC(0xa7bd22ac), + QTC(0xa34bdf21), QTC(0x9f13c7d1), QTC(0x9b1776db), QTC(0x97596180), QTC(0x93dbd6a1), QTC(0x90a0fd4f), QTC(0x8daad37c), QTC(0x8afb2cbc), + QTC(0x8893b126), QTC(0x8675dc50), QTC(0x84a2fc63), QTC(0x831c314f), QTC(0x81e26c17), QTC(0x80f66e3d), QTC(0x8058c94d), QTC(0x8009de7f) +}; + +const FIXP_QTW qmf_phaseshift_sin64[64] = { + QTC(0x03242abf), QTC(0x096a9049), QTC(0x0fab272b), QTC(0x15e21444), QTC(0x1c0b826a), QTC(0x2223a4c5), QTC(0x2826b928), QTC(0x2e110a62), + QTC(0x33def287), QTC(0x398cdd32), QTC(0x3f1749b7), QTC(0x447acd50), QTC(0x49b41533), QTC(0x4ebfe8a4), QTC(0x539b2aef), QTC(0x5842dd54), + QTC(0x5cb420df), QTC(0x60ec382f), QTC(0x64e88925), QTC(0x68a69e80), QTC(0x6c24295f), QTC(0x6f5f02b1), QTC(0x72552c84), QTC(0x7504d344), + QTC(0x776c4eda), QTC(0x798a23b0), QTC(0x7b5d039d), QTC(0x7ce3ceb1), QTC(0x7e1d93e9), QTC(0x7f0991c3), QTC(0x7fa736b3), QTC(0x7ff62181), + QTC(0x7ff62181), QTC(0x7fa736b3), QTC(0x7f0991c3), QTC(0x7e1d93e9), QTC(0x7ce3ceb1), QTC(0x7b5d039d), QTC(0x798a23b0), QTC(0x776c4eda), + QTC(0x7504d344), QTC(0x72552c84), QTC(0x6f5f02b1), QTC(0x6c24295f), QTC(0x68a69e80), QTC(0x64e88925), QTC(0x60ec382f), QTC(0x5cb420df), + QTC(0x5842dd54), QTC(0x539b2aef), QTC(0x4ebfe8a4), QTC(0x49b41533), QTC(0x447acd50), QTC(0x3f1749b7), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), QTC(0x15e21444), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf) +}; + +//@} + +#endif /* #ifdef LOW_POWER_SBR_ONLY */ + + + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, optimized by PE 010516 + + The coeffs are rearranged compared with the reference in the following + way, exploiting symmetry : + sbr_qmf_64[5] = p_64_640_qmf[0]; + sbr_qmf_64[6] = p_64_640_qmf[128]; + sbr_qmf_64[7] = p_64_640_qmf[256]; + sbr_qmf_64[8] = p_64_640_qmf[384]; + sbr_qmf_64[9] = p_64_640_qmf[512]; + + sbr_qmf_64[10] = p_64_640_qmf[1]; + sbr_qmf_64[11] = p_64_640_qmf[129]; + sbr_qmf_64[12] = p_64_640_qmf[257]; + sbr_qmf_64[13] = p_64_640_qmf[385]; + sbr_qmf_64[14] = p_64_640_qmf[513]; + . + . + . + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[62]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[190]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[318]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[446]; + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[574]; + + sbr_qmf_64_640_qmf[320] = p_64_640_qmf[63]; + sbr_qmf_64_640_qmf[321] = p_64_640_qmf[191]; + sbr_qmf_64_640_qmf[322] = p_64_640_qmf[319]; + sbr_qmf_64_640_qmf[323] = p_64_640_qmf[447]; + sbr_qmf_64_640_qmf[324] = p_64_640_qmf[575]; + + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[64]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[192]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[320]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[448]; + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[576]; + + sbr_qmf_64_640_qmf[314] = p_64_640_qmf[65]; + sbr_qmf_64_640_qmf[313] = p_64_640_qmf[193]; + sbr_qmf_64_640_qmf[312] = p_64_640_qmf[321]; + sbr_qmf_64_640_qmf[311] = p_64_640_qmf[449]; + sbr_qmf_64_640_qmf[310] = p_64_640_qmf[577]; + . + . + . + sbr_qmf_64[9] = p_64_640_qmf[126] + sbr_qmf_64[8] = p_64_640_qmf[254]; + sbr_qmf_64[7] = p_64_640_qmf[382]; + sbr_qmf_64[6] = p_64_640_qmf[510]; + sbr_qmf_64[5] = p_64_640_qmf[638]; + + sbr_qmf_64[4] = p_64_640_qmf[127] + sbr_qmf_64[3] = p_64_640_qmf[255]; + sbr_qmf_64[2] = p_64_640_qmf[383]; + sbr_qmf_64[1] = p_64_640_qmf[511]; + sbr_qmf_64[0] = p_64_640_qmf[639]; + + Max sum of all FIR filter absolute coefficients is: 0x7FF5B201 + thus, the filter output is not required to be scaled. + + \showinitializer +*/ +//@{ +#if QMF_NO_POLY==5 +LNK_SECTION_CONSTDATA_L1 +RAM_ALIGN +const FIXP_PFT qmf_64[QMF640_PFT_TABLE_SIZE+QMF_NO_POLY] = +{ + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), QFC(0xfe4d1be3), + QFC(0xffede50e), QFC(0x01d78bfc), QFC(0x2faa221c), QFC(0xd3337b3e), QFC(0xfe70b8d1), + QFC(0xffed978a), QFC(0x01fd3ba0), QFC(0x311af3a4), QFC(0xd49fd55f), QFC(0xfe933dc0), + QFC(0xffefc9b9), QFC(0x02244a24), QFC(0x328cc6f0), QFC(0xd60a46e6), QFC(0xfeb48d0d), + QFC(0xfff0065d), QFC(0x024bf7a1), QFC(0x33ff670e), QFC(0xd7722f04), QFC(0xfed4bec3), + QFC(0xffeff6ca), QFC(0x0274ba43), QFC(0x3572ec70), QFC(0xd8d7f220), QFC(0xfef3f6ab), + QFC(0xffef7b8b), QFC(0x029e35b4), QFC(0x36e69691), QFC(0xda3b176a), QFC(0xff120d70), + QFC(0xffeedfa4), QFC(0x02c89901), QFC(0x385a49c3), QFC(0xdb9b5b12), QFC(0xff2ef725), + QFC(0xffee1650), QFC(0x02f3e48d), QFC(0x39ce0477), QFC(0xdcf898fb), QFC(0xff4aabc8), + QFC(0xffed651d), QFC(0x03201116), QFC(0x3b415115), QFC(0xde529087), QFC(0xff6542d1), + QFC(0xffecc31b), QFC(0x034d01f1), QFC(0x3cb41219), QFC(0xdfa93ab5), QFC(0xff7ee3f1), + QFC(0xffebe77b), QFC(0x037ad438), QFC(0x3e25b17e), QFC(0xe0fc421e), QFC(0xff975c01), + QFC(0xffeb50b2), QFC(0x03a966bb), QFC(0x3f962fb8), QFC(0xe24b8f67), QFC(0xffaea5d6), + QFC(0xffea9192), QFC(0x03d8afe6), QFC(0x41058bc5), QFC(0xe396a45d), QFC(0xffc4e365), + QFC(0xffe9ca76), QFC(0x04083fec), QFC(0x4272a385), QFC(0xe4de0cb0), QFC(0xffda17f2), + QFC(0xffe940f4), QFC(0x043889c6), QFC(0x43de620a), QFC(0xe620c476), QFC(0xffee183b), + QFC(0xffe88ba8), QFC(0x04694101), QFC(0x4547daea), QFC(0xe75f8bb8), QFC(0x0000e790), + QFC(0xffe83a07), QFC(0x049aa82f), QFC(0x46aea856), QFC(0xe89971b7), QFC(0x00131c75), + QFC(0xffe79e16), QFC(0x04cc2fcf), QFC(0x4812f848), QFC(0xe9cea84a), QFC(0x0023b989), + QFC(0xffe7746e), QFC(0x04fe20be), QFC(0x4973fef1), QFC(0xeafee7f1), QFC(0x0033b927), + QFC(0xffe6d466), QFC(0x05303f88), QFC(0x4ad237a2), QFC(0xec2a3f60), QFC(0x00426f36), + QFC(0xffe6afed), QFC(0x05626209), QFC(0x4c2ca3df), QFC(0xed50a31d), QFC(0x00504f41), + QFC(0xffe65416), QFC(0x05950122), QFC(0x4d83976c), QFC(0xee71b2fe), QFC(0x005d36df), + QFC(0xffe681c6), QFC(0x05c76fed), QFC(0x4ed62be2), QFC(0xef8d4d7b), QFC(0x006928a0), + QFC(0xffe66dd0), QFC(0x05f9c051), QFC(0x5024d70e), QFC(0xf0a3959f), QFC(0x007400b8), + QFC(0xffe66fab), QFC(0x062bf5ec), QFC(0x516eefb8), QFC(0xf1b461ab), QFC(0x007e0393), + QFC(0xffe69423), QFC(0x065dd56a), QFC(0x52b449dd), QFC(0xf2bf6ea4), QFC(0x00872c63), + QFC(0xffe6fed4), QFC(0x068f8b44), QFC(0x53f495a9), QFC(0xf3c4e887), QFC(0x008f87aa), + QFC(0xffe75361), QFC(0x06c0f0c0), QFC(0x552f8ff6), QFC(0xf4c473c6), QFC(0x0096dcc2), + QFC(0xffe80414), QFC(0x06f1825d), QFC(0x56654bdc), QFC(0xf5be0fa9), QFC(0x009da526), + QFC(0xffe85b4a), QFC(0x0721bf22), QFC(0x579505f4), QFC(0xf6b1f3c3), QFC(0x00a3508f), + QFC(0xffe954d0), QFC(0x075112a2), QFC(0x58befacc), QFC(0xf79fa13a), QFC(0x00a85e94), + QFC(0xffea353a), QFC(0x077fedb3), QFC(0x59e2f69e), QFC(0xf887507c), QFC(0x00acbd2f), + QFC(0xffeb3849), QFC(0x07ad8c26), QFC(0x5b001db7), QFC(0xf96916f5), QFC(0x00b06b68), + QFC(0xffec8409), QFC(0x07da2b7f), QFC(0x5c16d0ae), QFC(0xfa44a069), QFC(0x00b36acd), + QFC(0xffedc418), QFC(0x08061671), QFC(0x5d26be9b), QFC(0xfb19b7bd), QFC(0x00b58c8d), + QFC(0xffef2395), QFC(0x08303897), QFC(0x5e2f6366), QFC(0xfbe8f5bd), QFC(0x00b73ab0), + QFC(0xfff0e7ef), QFC(0x08594887), QFC(0x5f30ff5e), QFC(0xfcb1d740), QFC(0x00b85f70), + QFC(0xfff294c3), QFC(0x0880ffdd), QFC(0x602b0c7e), QFC(0xfd7475d8), QFC(0x00b8c6b0), + QFC(0xfff48700), QFC(0x08a75da4), QFC(0x611d58a2), QFC(0xfe310657), QFC(0x00b8fe0d), + QFC(0xfff681d6), QFC(0x08cb4e23), QFC(0x6207f21f), QFC(0xfee723c6), QFC(0x00b8394b), + QFC(0xfff91fc9), QFC(0x08edfeaa), QFC(0x62ea6473), QFC(0xff96db8f), QFC(0x00b74c37), + QFC(0xfffb42b0), QFC(0x090ec1fc), QFC(0x63c45243), QFC(0x0040c497), QFC(0x00b5c867), + QFC(0xfffdfa24), QFC(0x092d7970), QFC(0x64964062), QFC(0x00e42fa2), QFC(0x00b3d15c), + QFC(0x00007134), QFC(0x0949eaac), QFC(0x655f63f1), QFC(0x01816e06), QFC(0x00b1978d), + QFC(0x00039609), QFC(0x0963ed46), QFC(0x661fd6b7), QFC(0x02186a92), QFC(0x00af374c), + QFC(0x0006b1cf), QFC(0x097c1ee8), QFC(0x66d76724), QFC(0x02a99097), QFC(0x00abe79e), + QFC(0x0009aa3f), QFC(0x099140a7), QFC(0x6785c24c), QFC(0x03343534), QFC(0x00a8739d), + QFC(0x000d31b5), QFC(0x09a3e163), QFC(0x682b39a3), QFC(0x03b8f8dc), QFC(0x00a520bb), + QFC(0x0010bc63), QFC(0x09b3d77f), QFC(0x68c7269b), QFC(0x0437fb0a), QFC(0x00a1039c), + QFC(0x001471f8), QFC(0x09c0e59f), QFC(0x6959709c), QFC(0x04b0adcb), QFC(0x009d10bf), + QFC(0x0018703f), QFC(0x09cab9f2), QFC(0x69e29783), QFC(0x05237f9d), QFC(0x0098b855), + QFC(0x001c3549), QFC(0x09d19ca9), QFC(0x6a619c5e), QFC(0x0590a67d), QFC(0x009424c6), + QFC(0x002064f8), QFC(0x09d52709), QFC(0x6ad73e8d), QFC(0x05f7fb90), QFC(0x008f4bfd), + QFC(0x0024dd50), QFC(0x09d5560b), QFC(0x6b42a863), QFC(0x06593912), QFC(0x008a7dd7), + QFC(0x00293718), QFC(0x09d1fa23), QFC(0x6ba4629e), QFC(0x06b559c3), QFC(0x0085c217), + QFC(0x002d8e42), QFC(0x09caeb0f), QFC(0x6bfbdd97), QFC(0x070bbf58), QFC(0x00807994), + QFC(0x00329ab6), QFC(0x09c018ce), QFC(0x6c492216), QFC(0x075ca90c), QFC(0x007b3875), + QFC(0x003745f9), QFC(0x09b18a1d), QFC(0x6c8c4c79), QFC(0x07a8127d), QFC(0x0075fded), + QFC(0x003c1fa4), QFC(0x099ec3dc), QFC(0x6cc59baa), QFC(0x07ee507c), QFC(0x0070c8a5), + QFC(0x004103f5), QFC(0x09881dc5), QFC(0x6cf4073d), QFC(0x082f552e), QFC(0x006b47fa), + QFC(0x00465348), QFC(0x096d0e21), QFC(0x6d18520d), QFC(0x086b1eec), QFC(0x0065fde5), + QFC(0x004b6c46), QFC(0x094d7ec2), QFC(0x6d32730e), QFC(0x08a24899), QFC(0x006090c4), + QFC(0x0050b177), QFC(0x09299ead), QFC(0x6d41d963), QFC(0x08d3e41b), QFC(0x005b5371), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), QFC(0x0055dba1), + QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), QFC(0x01b2e41d), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos_downsamp32[] = +{ + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), + QTC(0xf9b82684), QTC(0xed37ef91), QTC(0xe0e60685), QTC(0xd4e0cb15), QTC(0xc945dfec), QTC(0xbe31e19b), QTC(0xb3c0200c), QTC(0xaa0a5b2e), + QTC(0xa1288376), QTC(0x99307ee0), QTC(0x9235f2ec), QTC(0x8c4a142f), QTC(0x877b7bec), QTC(0x83d60412), QTC(0x8162aa04), QTC(0x80277872), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin_downsamp32[] = +{ + QTC(0x0647d97c), QTC(0x12c8106f), QTC(0x1f19f97b), QTC(0x2b1f34eb), QTC(0x36ba2014), QTC(0x41ce1e65), QTC(0x4c3fdff4), QTC(0x55f5a4d2), + QTC(0x5ed77c8a), QTC(0x66cf8120), QTC(0x6dca0d14), QTC(0x73b5ebd1), QTC(0x78848414), QTC(0x7c29fbee), QTC(0x7e9d55fc), QTC(0x7fd8878e), + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), +}; + +#else /* QMF_NO_POLY == 5 */ +#endif /* QMF_NO_POLY==5 */ + + + + + +/* + * Low Delay QMF aka CLDFB + */ + +#if defined(QMF_COEFF_16BIT) +#define QTCFLLD(x) FL2FXCONST_SGL(x/(float)(1< 59 dB SNR 1 --> 65 dB SNR +#define MINSFTAB 7 +#define MAXSFTAB 25 + +#if IMPROVE_ATAN2_ACCURACY +static const FIXP_DBL f_atan_expand_range[MAXSFTAB-(MINSFTAB-1)] = +{ + /***************************************************************************** + * + * Table holds fixp_atan() output values which are outside of input range + * of fixp_atan() to improve SNR of fixp_atan2(). + * + * This Table might also be used in fixp_atan() [todo] so there a wider input + * range can be covered, too. + * + * Matlab (generate table): + * for scl = 7:25 % MINSFTAB .. MAXSFTAB + * at=atan(0.5 *(2^scl)); % 0.5 because get in 'middle' area of current scale level 'scl' + * at/2 % div at by ATO_SCALE + * end + * + * Table divided by 2=ATO_SCALE <-- SF=ATO_SF + *****************************************************************************/ + FL2FXCONST_DBL(7.775862990872099e-001), FL2FXCONST_DBL(7.814919928673978e-001), FL2FXCONST_DBL(7.834450483314648e-001), + FL2FXCONST_DBL(7.844216021392089e-001), FL2FXCONST_DBL(7.849098823026687e-001), FL2FXCONST_DBL(7.851540227918509e-001), + FL2FXCONST_DBL(7.852760930873737e-001), FL2FXCONST_DBL(7.853371282415015e-001), FL2FXCONST_DBL(7.853676458193612e-001), + FL2FXCONST_DBL(7.853829046083906e-001), FL2FXCONST_DBL(7.853905340029177e-001), FL2FXCONST_DBL(7.853943487001828e-001), + FL2FXCONST_DBL(7.853962560488155e-001), FL2FXCONST_DBL(7.853972097231319e-001), FL2FXCONST_DBL(7.853976865602901e-001), + FL2FXCONST_DBL(7.853979249788692e-001), FL2FXCONST_DBL(7.853980441881587e-001), FL2FXCONST_DBL(7.853981037928035e-001), + FL2FXCONST_DBL(7.853981335951259e-001) + // pi/4 = 0.785398163397448 = pi/2/ATO_SCALE +}; +#endif + +FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x) +{ + FIXP_DBL q; + FIXP_DBL at; // atan out + FIXP_DBL at2; // atan2 out + FIXP_DBL ret = FL2FXCONST_DBL(-1.0f); + INT sf,sfo,stf; + + // --- division + + if (y > FL2FXCONST_DBL(0.0f)) + { + if (x > FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec( y, x, &sf); // both pos. + } + else if (x < FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec( y,-x, &sf); // x neg. + } + else {//(x ==FL2FXCONST_DBL(0.0f)) + q = FL2FXCONST_DBL(+1.0f); // y/x = pos/zero = +Inf + sf = 0; + } + } + else if (y < FL2FXCONST_DBL(0.0f)) + { + if (x > FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec(-y, x, &sf); // y neg. + } + else if (x < FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec(-y,-x, &sf); // both neg. + } + else {//(x ==FL2FXCONST_DBL(0.0f)) + q = FL2FXCONST_DBL(-1.0f); // y/x = neg/zero = -Inf + sf = 0; + } + } + else { // (y ==FL2FXCONST_DBL(0.0f)) + q = FL2FXCONST_DBL(0.0f); + sf = 0; + } + sfo = sf; + + // --- atan() + + if ( sfo > ATI_SF ) { + // --- could not calc fixp_atan() here bec of input data out of range + // ==> therefore give back boundary values + + #if IMPROVE_ATAN2_ACCURACY + if (sfo > MAXSFTAB) sfo = MAXSFTAB; + #endif + + if ( q > FL2FXCONST_DBL(0.0f) ) { + #if IMPROVE_ATAN2_ACCURACY + at = +f_atan_expand_range[sfo-ATI_SF-1]; + #else + at = FL2FXCONST_DBL( +M_PI/2 / ATO_SCALE); + #endif + } + else if ( q < FL2FXCONST_DBL(0.0f) ) { + #if IMPROVE_ATAN2_ACCURACY + at = -f_atan_expand_range[sfo-ATI_SF-1]; + #else + at = FL2FXCONST_DBL( -M_PI/2 / ATO_SCALE); + #endif + } + else { // q== FL2FXCONST_DBL(0.0f) + at = FL2FXCONST_DBL( 0.0f ); + } + }else{ + // --- calc of fixp_atan() is possible; input data within range + // ==> set q on fixed scale level as desired from fixp_atan() + stf = sfo - ATI_SF; + if (stf > 0) q = q << (INT)fMin( stf,DFRACT_BITS-1); + else q = q >> (INT)fMin(-stf,DFRACT_BITS-1); + at = fixp_atan(q); // ATO_SF + } + + // --- atan2() + + at2 = at >> (AT2O_SF - ATO_SF); // now AT2O_SF for atan2 + if ( x > FL2FXCONST_DBL(0.0f) ) { + ret = at2; + } + else if ( x < FL2FXCONST_DBL(0.0f) ) { + if ( y >= FL2FXCONST_DBL(0.0f) ) { + ret = at2 + FL2FXCONST_DBL( M_PI / AT2O_SCALE); + } else { + ret = at2 - FL2FXCONST_DBL( M_PI / AT2O_SCALE); + } + } + else { + // x == 0 + if ( y > FL2FXCONST_DBL(0.0f) ) { + ret = FL2FXCONST_DBL( +M_PI/2 / AT2O_SCALE); + } + else if ( y < FL2FXCONST_DBL(0.0f) ) { + ret = FL2FXCONST_DBL( -M_PI/2 / AT2O_SCALE); + } + else if ( y == FL2FXCONST_DBL(0.0f) ) { + ret = FL2FXCONST_DBL(0.0f); + } + } + return ret; +} + + +FIXP_DBL fixp_atan(FIXP_DBL x) +{ + INT sign; + FIXP_DBL result, temp; + + // SNR of fixp_atan() = 56 dB + FIXP_DBL ONEBY3P56 = (FIXP_DBL)0x26800000; // 1.0/3.56 in q31 + FIXP_DBL P281 = (FIXP_DBL)0x00013000; // 0.281 in q18 + FIXP_DBL ONEP571 = (FIXP_DBL)0x6487ef00; // 1.571 in q30 + + if (x < FIXP_DBL(0)) { + sign = 1; + x = - x ; + } else { + sign = 0; + } + + /* calc of arctan */ + if(x < ( Q(Q_ATANINP)-FL2FXCONST_DBL(0.00395)) ) + { + INT res_e; + + temp = fPow2(x); // q25 * q25 - (DFRACT_BITS-1) = q19 + temp = fMult(temp, ONEBY3P56); // q19 * q31 - (DFRACT_BITS-1) = q19 + temp = temp + Q(19); // q19 + q19 = q19 + result = fDivNorm(x, temp, &res_e); + result = scaleValue(result, (Q_ATANOUT-Q_ATANINP+19-DFRACT_BITS+1) + res_e ); + } + else if( x < FL2FXCONST_DBL(1.28/64.0) ) + { + FIXP_DBL delta_fix; + FIXP_DBL PI_BY_4 = FL2FXCONST_DBL(3.1415926/4.0) >> 1; /* pi/4 in q30 */ + + delta_fix = (x - FL2FXCONST_DBL(1.0/64.0)) << 5; /* q30 */ + result = PI_BY_4 + (delta_fix >> 1) - (fPow2Div2(delta_fix)); + } + else + { + INT res_e; + + temp = fPow2Div2(x); // q25 * q25 - (DFRACT_BITS-1) - 1 = q18 + temp = temp + P281; // q18 + q18 = q18 + result = fDivNorm(x, temp, &res_e); + result = scaleValue(result, (Q_ATANOUT-Q_ATANINP+18-DFRACT_BITS+1) + res_e ); + result = ONEP571 - result; // q30 + q30 = q30 + } + if (sign) { + result = -result; + } + + return(result); +} + + + +#include "FDK_tools_rom.h" + +FIXP_DBL fixp_cos(FIXP_DBL x, int scale) +{ + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(sine, residual); + + return cosine - error; +} + +FIXP_DBL fixp_sin(FIXP_DBL x, int scale) +{ + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(cosine, residual); + + return sine + error; +} + +void fixp_cos_sin (FIXP_DBL x, int scale, FIXP_DBL *cos, FIXP_DBL *sin) +{ + FIXP_DBL residual, error0, error1, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error0 = fMult(sine, residual); + error1 = fMult(cosine, residual); + *cos = cosine - error0; + *sin = sine + error1; +} + + + + + diff --git a/libFDK/src/arm/autocorr2nd.cpp b/libFDK/src/arm/autocorr2nd.cpp new file mode 100644 index 00000000..cc76e304 --- /dev/null +++ b/libFDK/src/arm/autocorr2nd.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + * + * \brief Calculate second order autocorrelation + * + */ + + diff --git a/libFDK/src/arm/dct_arm.cpp b/libFDK/src/arm/dct_arm.cpp new file mode 100644 index 00000000..59b773e2 --- /dev/null +++ b/libFDK/src/arm/dct_arm.cpp @@ -0,0 +1,456 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + + + +#ifdef FUNCTION_dct_IV_func1 + +/* + Note: This assembler routine is here, because the ARM926 compiler does + not encode the inline assembler with optimal speed. + With this version, we save 2 cycles per loop iteration. +*/ + +__asm void dct_IV_func1( + int i, + const FIXP_SPK *twiddle, + FIXP_DBL *RESTRICT pDat_0, + FIXP_DBL *RESTRICT pDat_1) +{ + /* Register map: + r0 i + r1 twiddle + r2 pDat_0 + r3 pDat_1 + r4 accu1 + r5 accu2 + r6 accu3 + r7 accu4 + r8 val_tw + r9 accuX + */ + PUSH {r4-r9} + + /* 44 cycles for 2 iterations = 22 cycles/iteration */ +dct_IV_loop1_start +/* First iteration */ + LDR r8, [r1], #4 // val_tw = *twiddle++; + LDR r5, [r2, #0] // accu2 = pDat_0[0] + LDR r4, [r3, #0] // accu1 = pDat_1[0] + + SMULWT r9, r5, r8 // accuX = accu2*val_tw.l + SMULWB r5, r5, r8 // accu2 = accu2*val_tw.h + RSB r9, r9, #0 // accuX =-accu2*val_tw.l + SMLAWT r5, r4, r8, r5 // accu2 = accu2*val_tw.h + accu1*val_tw.l + SMLAWB r4, r4, r8, r9 // accu1 = accu1*val_tw.h - accu2*val_tw.l + + LDR r8, [r1], #4 // val_tw = *twiddle++; + LDR r7, [r3, #-4] // accu4 = pDat_1[-1] + LDR r6, [r2, #4] // accu3 = pDat_0[1] + + SMULWB r9, r7, r8 // accuX = accu4*val_tw.h + SMULWT r7, r7, r8 // accu4 = accu4*val_tw.l + RSB r9, r9, #0 // accuX =-accu4*val_tw.h + SMLAWB r7, r6, r8, r7 // accu4 = accu4*val_tw.l+accu3*val_tw.h + SMLAWT r6, r6, r8, r9 // accu3 = accu3*val_tw.l-accu4*val_tw.h + + STR r5, [r2], #4 // *pDat_0++ = accu2 + STR r4, [r2], #4 // *pDat_0++ = accu1 + STR r6, [r3], #-4 // *pDat_1-- = accu3 + STR r7, [r3], #-4 // *pDat_1-- = accu4 + +/* Second iteration */ + LDR r8, [r1], #4 // val_tw = *twiddle++; + LDR r5, [r2, #0] // accu2 = pDat_0[0] + LDR r4, [r3, #0] // accu1 = pDat_1[0] + + SMULWT r9, r5, r8 // accuX = accu2*val_tw.l + SMULWB r5, r5, r8 // accu2 = accu2*val_tw.h + RSB r9, r9, #0 // accuX =-accu2*val_tw.l + SMLAWT r5, r4, r8, r5 // accu2 = accu2*val_tw.h + accu1*val_tw.l + SMLAWB r4, r4, r8, r9 // accu1 = accu1*val_tw.h - accu2*val_tw.l + + LDR r8, [r1], #4 // val_tw = *twiddle++; + LDR r7, [r3, #-4] // accu4 = pDat_1[-1] + LDR r6, [r2, #4] // accu3 = pDat_0[1] + + SMULWB r9, r7, r8 // accuX = accu4*val_tw.h + SMULWT r7, r7, r8 // accu4 = accu4*val_tw.l + RSB r9, r9, #0 // accuX =-accu4*val_tw.h + SMLAWB r7, r6, r8, r7 // accu4 = accu4*val_tw.l+accu3*val_tw.h + SMLAWT r6, r6, r8, r9 // accu3 = accu3*val_tw.l-accu4*val_tw.h + + STR r5, [r2], #4 // *pDat_0++ = accu2 + STR r4, [r2], #4 // *pDat_0++ = accu1 + STR r6, [r3], #-4 // *pDat_1-- = accu3 + STR r7, [r3], #-4 // *pDat_1-- = accu4 + + SUBS r0, r0, #1 + BNE dct_IV_loop1_start + + POP {r4-r9} + + BX lr +} + +#endif /* FUNCTION_dct_IV_func1 */ + + +#ifdef FUNCTION_dct_IV_func2 + +FDK_INLINE +/* __attribute__((noinline)) */ +static void dct_IV_func2( + int i, + const FIXP_SPK *twiddle, + FIXP_DBL *pDat_0, + FIXP_DBL *pDat_1, + int inc) +{ + FIXP_DBL accu1, accu2, accu3, accu4, accuX; + LONG val_tw; + + accu1 = pDat_1[-2]; + accu2 = pDat_1[-1]; + + *--pDat_1 = -(pDat_0[1]>>1); + *pDat_0++ = (pDat_0[0]>>1); + + twiddle += inc; + +__asm + { + LDR val_tw, [twiddle], inc, LSL #2 // val_tw = *twiddle; twiddle += inc + B dct_IV_loop2_2nd_part + + /* 42 cycles for 2 iterations = 21 cycles/iteration */ +dct_IV_loop2: + SMULWT accuX, accu2, val_tw + SMULWB accu2, accu2, val_tw + RSB accuX, accuX, #0 + SMLAWB accuX, accu1, val_tw, accuX + SMLAWT accu2, accu1, val_tw, accu2 + STR accuX, [pDat_0], #4 + STR accu2, [pDat_1, #-4] ! + + LDR accu4, [pDat_0, #4] + LDR accu3, [pDat_0] + SMULWB accuX, accu4, val_tw + SMULWT accu4, accu4, val_tw + RSB accuX, accuX, #0 + SMLAWT accuX, accu3, val_tw, accuX + SMLAWB accu4, accu3, val_tw, accu4 + + LDR accu1, [pDat_1, #-8] + LDR accu2, [pDat_1, #-4] + + LDR val_tw, [twiddle], inc, LSL #2 // val_tw = *twiddle; twiddle += inc + + STR accuX, [pDat_1, #-4] ! + STR accu4, [pDat_0], #4 + +dct_IV_loop2_2nd_part: + SMULWT accuX, accu2, val_tw + SMULWB accu2, accu2, val_tw + RSB accuX, accuX, #0 + SMLAWB accuX, accu1, val_tw, accuX + SMLAWT accu2, accu1, val_tw, accu2 + STR accuX, [pDat_0], #4 + STR accu2, [pDat_1, #-4] ! + + LDR accu4, [pDat_0, #4] + LDR accu3, [pDat_0] + SMULWB accuX, accu4, val_tw + SMULWT accu4, accu4, val_tw + RSB accuX, accuX, #0 + SMLAWT accuX, accu3, val_tw, accuX + SMLAWB accu4, accu3, val_tw, accu4 + + LDR accu1, [pDat_1, #-8] + LDR accu2, [pDat_1, #-4] + + STR accuX, [pDat_1, #-4] ! + STR accu4, [pDat_0], #4 + + LDR val_tw, [twiddle], inc, LSL #2 // val_tw = *twiddle; twiddle += inc + + SUBS i, i, #1 + BNE dct_IV_loop2 + } + + /* Last Sin and Cos value pair are the same */ + accu1 = fMultDiv2(accu1, WTC(0x5a82799a)); + accu2 = fMultDiv2(accu2, WTC(0x5a82799a)); + + *--pDat_1 = accu1 + accu2; + *pDat_0++ = accu1 - accu2; +} +#endif /* FUNCTION_dct_IV_func2 */ + + +#ifdef FUNCTION_dst_IV_func1 + +__asm void dst_IV_func1( + int i, + const FIXP_SPK *twiddle, + FIXP_DBL *pDat_0, + FIXP_DBL *pDat_1) +{ + /* Register map: + r0 i + r1 twiddle + r2 pDat_0 + r3 pDat_1 + r4 accu1 + r5 accu2 + r6 accu3 + r7 accu4 + r8 val_tw + r9 accuX + */ + PUSH {r4-r9} + +dst_IV_loop1 + LDR r8, [r1], #4 // val_tw = *twiddle++ + LDR r5, [r2] // accu2 = pDat_0[0] + LDR r6, [r2, #4] // accu3 = pDat_0[1] + RSB r5, r5, #0 // accu2 = -accu2 + SMULWT r9, r5, r8 // accuX = (-accu2)*val_tw.l + LDR r4, [r3, #-4] // accu1 = pDat_1[-1] + RSB r9, r9, #0 // accuX = -(-accu2)*val_tw.l + SMLAWB r9, r4, r8, r9 // accuX = accu1*val_tw.h-(-accu2)*val_tw.l + SMULWT r4, r4, r8 // accu1 = accu1*val_tw.l + LDR r7, [r3, #-8] // accu4 = pDat_1[-2] + SMLAWB r5, r5, r8, r4 // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l + LDR r8, [r1], #4 // val_tw = *twiddle++ + STR r5, [r2], #4 // *pDat_0++ = accu2 + STR r9, [r2], #4 // *pDat_0++ = accu1 (accuX) + RSB r7, r7, #0 // accu4 = -accu4 + SMULWB r5, r7, r8 // accu2 = (-accu4)*val_tw.h + SMULWB r4, r6, r8 // accu1 = (-accu4)*val_tw.l + RSB r5, r5, #0 // accu2 = -(-accu4)*val_tw.h + SMLAWT r6, r6, r8, r5 // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h + SMLAWT r7, r7, r8, r4 // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h + STR r6, [r3, #-4] ! // *--pDat_1 = accu3 + STR r7, [r3, #-4] ! // *--pDat_1 = accu4 + + LDR r8, [r1], #4 // val_tw = *twiddle++ + LDR r5, [r2] // accu2 = pDat_0[0] + LDR r6, [r2, #4] // accu3 = pDat_0[1] + RSB r5, r5, #0 // accu2 = -accu2 + SMULWT r9, r5, r8 // accuX = (-accu2)*val_tw.l + LDR r4, [r3, #-4] // accu1 = pDat_1[-1] + RSB r9, r9, #0 // accuX = -(-accu2)*val_tw.l + SMLAWB r9, r4, r8, r9 // accuX = accu1*val_tw.h-(-accu2)*val_tw.l + SMULWT r4, r4, r8 // accu1 = accu1*val_tw.l + LDR r7, [r3, #-8] // accu4 = pDat_1[-2] + SMLAWB r5, r5, r8, r4 // accu2 = (-accu2)*val_tw.t+accu1*val_tw.l + LDR r8, [r1], #4 // val_tw = *twiddle++ + STR r5, [r2], #4 // *pDat_0++ = accu2 + STR r9, [r2], #4 // *pDat_0++ = accu1 (accuX) + RSB r7, r7, #0 // accu4 = -accu4 + SMULWB r5, r7, r8 // accu2 = (-accu4)*val_tw.h + SMULWB r4, r6, r8 // accu1 = (-accu4)*val_tw.l + RSB r5, r5, #0 // accu2 = -(-accu4)*val_tw.h + SMLAWT r6, r6, r8, r5 // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h + SMLAWT r7, r7, r8, r4 // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h + STR r6, [r3, #-4] ! // *--pDat_1 = accu3 + STR r7, [r3, #-4] ! // *--pDat_1 = accu4 + + SUBS r0, r0, #4 // i-= 4 + BNE dst_IV_loop1 + + POP {r4-r9} + BX lr +} +#endif /* FUNCTION_dst_IV_func1 */ + +#ifdef FUNCTION_dst_IV_func2 + +FDK_INLINE +/* __attribute__((noinline)) */ +static void dst_IV_func2( + int i, + const FIXP_SPK *twiddle, + FIXP_DBL *RESTRICT pDat_0, + FIXP_DBL *RESTRICT pDat_1, + int inc) +{ + FIXP_DBL accu1,accu2,accu3,accu4; + LONG val_tw; + + accu4 = pDat_0[0]; + accu3 = pDat_0[1]; + accu4 >>= 1; + accu3 >>= 1; + accu4 = -accu4; + + accu1 = pDat_1[-1]; + accu2 = pDat_1[0]; + + *pDat_0++ = accu3; + *pDat_1-- = accu4; + + + __asm + { + B dst_IV_loop2_2nd_part + + /* 50 cycles for 2 iterations = 25 cycles/iteration */ + +dst_IV_loop2: + + LDR val_tw, [twiddle], inc, LSL #2 // val_tw = *twiddle; twiddle += inc + + RSB accu2, accu2, #0 // accu2 = -accu2 + RSB accu1, accu1, #0 // accu1 = -accu1 + SMULWT accu3, accu2, val_tw // accu3 = (-accu2)*val_tw.l + SMULWT accu4, accu1, val_tw // accu4 = (-accu1)*val_tw.l + RSB accu3, accu3, #0 // accu3 = -accu2*val_tw.l + SMLAWB accu1, accu1, val_tw, accu3 // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l + SMLAWB accu2, accu2, val_tw, accu4 // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h + STR accu1, [pDat_1], #-4 // *pDat_1-- = accu1 + STR accu2, [pDat_0], #4 // *pDat_0++ = accu2 + + LDR accu4, [pDat_0] // accu4 = pDat_0[0] + LDR accu3, [pDat_0, #4] // accu3 = pDat_0[1] + + RSB accu4, accu4, #0 // accu4 = -accu4 + RSB accu3, accu3, #0 // accu3 = -accu3 + + SMULWB accu1, accu3, val_tw // accu1 = (-accu3)*val_tw.h + SMULWT accu2, accu3, val_tw // accu2 = (-accu3)*val_tw.l + RSB accu1, accu1, #0 // accu1 = -(-accu3)*val_tw.h + SMLAWT accu3, accu4, val_tw, accu1 // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h + SMLAWB accu4, accu4, val_tw, accu2 // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h + + LDR accu1, [pDat_1, #-4] // accu1 = pDat_1[-1] + LDR accu2, [pDat_1] // accu2 = pDat_1[0] + + STR accu3, [pDat_0], #4 // *pDat_0++ = accu3 + STR accu4, [pDat_1], #-4 // *pDat_1-- = accu4 + +dst_IV_loop2_2nd_part: + + LDR val_tw, [twiddle], inc, LSL #2 // val_tw = *twiddle; twiddle += inc + + RSB accu2, accu2, #0 // accu2 = -accu2 + RSB accu1, accu1, #0 // accu1 = -accu1 + SMULWT accu3, accu2, val_tw // accu3 = (-accu2)*val_tw.l + SMULWT accu4, accu1, val_tw // accu4 = (-accu1)*val_tw.l + RSB accu3, accu3, #0 // accu3 = -accu2*val_tw.l + SMLAWB accu1, accu1, val_tw, accu3 // accu1 = -accu1*val_tw.h-(-accu2)*val_tw.l + SMLAWB accu2, accu2, val_tw, accu4 // accu2 = (-accu1)*val_tw.l+(-accu2)*val_tw.h + STR accu1, [pDat_1], #-4 // *pDat_1-- = accu1 + STR accu2, [pDat_0], #4 // *pDat_0++ = accu2 + + LDR accu4, [pDat_0] // accu4 = pDat_0[0] + LDR accu3, [pDat_0, #4] // accu3 = pDat_0[1] + + RSB accu4, accu4, #0 // accu4 = -accu4 + RSB accu3, accu3, #0 // accu3 = -accu3 + + SMULWB accu1, accu3, val_tw // accu1 = (-accu3)*val_tw.h + SMULWT accu2, accu3, val_tw // accu2 = (-accu3)*val_tw.l + RSB accu1, accu1, #0 // accu1 = -(-accu3)*val_tw.h + SMLAWT accu3, accu4, val_tw, accu1 // accu3 = (-accu4)*val_tw.l-(-accu3)*val_tw.h + SMLAWB accu4, accu4, val_tw, accu2 // accu4 = (-accu3)*val_tw.l+(-accu4)*val_tw.h + + LDR accu1, [pDat_1, #-4] // accu1 = pDat_1[-1] + LDR accu2, [pDat_1] // accu2 = pDat_1[0] + + STR accu3, [pDat_0], #4 // *pDat_0++ = accu3 + STR accu4, [pDat_1], #-4 // *pDat_1-- = accu4 + + SUBS i, i, #1 + BNE dst_IV_loop2 + } + + /* Last Sin and Cos value pair are the same */ + accu1 = fMultDiv2(-accu1, WTC(0x5a82799a)); + accu2 = fMultDiv2(-accu2, WTC(0x5a82799a)); + + *pDat_0 = accu1 + accu2; + *pDat_1 = accu1 - accu2; +} +#endif /* FUNCTION_dst_IV_func2 */ diff --git a/libFDK/src/arm/fft_rad2_arm.cpp b/libFDK/src/arm/fft_rad2_arm.cpp new file mode 100644 index 00000000..a6e2e42e --- /dev/null +++ b/libFDK/src/arm/fft_rad2_arm.cpp @@ -0,0 +1,321 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: dit_fft ARM assembler replacements. + +******************************************************************************/ + +/* NEON optimized FFT currently builds only with RVCT toolchain */ + +#ifndef FUNCTION_dit_fft + +/* If dit_fft was not yet defined by ARM-Cortex ... */ + +#if defined(SINETABLE_16BIT) + +#define FUNCTION_dit_fft + +/***************************************************************************** + + date: 28.07.2005 srl + + Contents/description: dit-tukey-FFT-algorithm + +******************************************************************************/ + +#if defined(FUNCTION_dit_fft) + + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, const INT trigDataSize) +{ + const INT n=1<>1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6])>>1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3])>>1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7])>>1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + INT mh = 1 << 1; + INT ldm = ldn - 2; + INT trigstep = trigDataSize; + + do + { + const FIXP_STP *pTrigData = trigdata; + INT j; + + mh <<= 1; + trigstep >>= 1; + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to much precision. + Beware: The impact on the overal FFT precision is rather large. */ + { + FIXP_DBL *xt1 = x; + int r = n; + + do { + FIXP_DBL *xt2 = xt1 + (mh<<1); + /* + FIXP_DBL *xt1 = x+ ((r)<<1); + FIXP_DBL *xt2 = xt1 + (mh<<1); + */ + FIXP_DBL vr,vi,ur,ui; + + //cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vi = xt2[1]>>1; + vr = xt2[0]>>1; + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui+vi; + + xt2[0] = ur-vr; + xt2[1] = ui-vi; + + xt1 += mh; + xt2 += mh; + + //cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = xt2[1]>>1; + vi = xt2[0]>>1; + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui-vi; + + xt2[0] = ur-vr; + xt2[1] = ui+vi; + + xt1 = xt2 + mh; + } while ((r=r-(mh<<1)) != 0); + } + for(j=4; j>1); + FIXP_SPK cs; + int r = n; + + pTrigData += trigstep; + cs = *pTrigData; + + do + { + FIXP_DBL *xt2 = xt1 + (mh<<1); + FIXP_DBL vr,vi,ur,ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], cs); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui+vi; + + xt2[0] = ur-vr; + xt2[1] = ui-vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], cs); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui-vi; + + xt2[0] = ur-vr; + xt2[1] = ui+vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + xt1 = xt1 - (j); + xt2 = xt1 + (mh<<1); + + cplxMultDiv2(&vi, &vr, xt2[0], xt2[1], cs); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui-vi; + + xt2[0] = ur-vr; + xt2[1] = ui+vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[0], xt2[1], cs); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur-vr; + xt1[1] = ui-vi; + + xt2[0] = ur+vr; + xt2[1] = ui+vi; + + xt1 = xt2 + (j); + } while ((r=r-(mh<<1)) != 0); + } + { + FIXP_DBL *xt1 = x + (mh>>1); + int r = n; + + do + { + FIXP_DBL *xt2 = xt1 + (mh<<1); + FIXP_DBL vr,vi,ur,ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], STC(0x5a82799a), STC(0x5a82799a)); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui+vi; + + xt2[0] = ur-vr; + xt2[1] = ui-vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], STC(0x5a82799a), STC(0x5a82799a)); + + ur = xt1[0]>>1; + ui = xt1[1]>>1; + + xt1[0] = ur+vr; + xt1[1] = ui-vi; + + xt2[0] = ur-vr; + xt2[1] = ui+vi; + + xt1 = xt2 + mh; + } while ((r=r-(mh<<1)) != 0); + } + } while (--ldm != 0); +} + +#endif /* if defined(FUNCTION_dit_fft) */ + +#endif /* if defined(SINETABLE_16BIT) */ + +#endif /* ifndef FUNCTION_dit_fft */ diff --git a/libFDK/src/arm/qmf_arm.cpp b/libFDK/src/arm/qmf_arm.cpp new file mode 100644 index 00000000..fbeebfb0 --- /dev/null +++ b/libFDK/src/arm/qmf_arm.cpp @@ -0,0 +1,766 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#if (QMF_NO_POLY==5) + +#define FUNCTION_qmfForwardModulationLP_odd + +#ifdef FUNCTION_qmfForwardModulationLP_odd +static void +qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_QMF *timeIn, /*!< Time Signal */ + FIXP_QMF *rSubband ) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L>>1; + int shift = (anaQmf->no_channels>>6) + 1; + int rSubband_e = 0; + + FIXP_QMF *rSubbandPtr0 = &rSubband[M+0]; /* runs with increment */ + FIXP_QMF *rSubbandPtr1 = &rSubband[M-1]; /* runs with decrement */ + FIXP_QMF *timeIn0 = (FIXP_DBL *) &timeIn[0]; /* runs with increment */ + FIXP_QMF *timeIn1 = (FIXP_DBL *) &timeIn[L]; /* runs with increment */ + FIXP_QMF *timeIn2 = (FIXP_DBL *) &timeIn[L-1]; /* runs with decrement */ + FIXP_QMF *timeIn3 = (FIXP_DBL *) &timeIn[2*L-1]; /* runs with decrement */ + + for (i = 0; i < M; i++) + { + *rSubbandPtr0++ = (*timeIn2-- >> 1) - (*timeIn0++ >> shift); + *rSubbandPtr1-- = (*timeIn1++ >> 1) + (*timeIn3-- >> shift); + } + + dct_IV(rSubband,L, &rSubband_e); +} +#endif /* FUNCTION_qmfForwardModulationLP_odd */ + + +/* NEON optimized QMF currently builts only with RVCT toolchain */ + +#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_5TE__) + +#if (SAMPLE_BITS == 16) +#define FUNCTION_qmfAnaPrototypeFirSlot +#endif + +#ifdef FUNCTION_qmfAnaPrototypeFirSlot + +#if defined(__GNUC__) /* cppp replaced: elif */ + +inline INT SMULBB (const SHORT a, const LONG b) +{ + INT result ; + __asm__ ("smulbb %0, %1, %2" + : "=r" (result) + : "r" (a), "r" (b)) ; + return result ; +} +inline INT SMULBT (const SHORT a, const LONG b) +{ + INT result ; + __asm__ ("smulbt %0, %1, %2" + : "=r" (result) + : "r" (a), "r" (b)) ; + return result ; +} + +inline INT SMLABB(const LONG accu, const SHORT a, const LONG b) +{ + INT result ; + __asm__ ("smlabb %0, %1, %2,%3" + : "=r" (result) + : "r" (a), "r" (b), "r" (accu)) ; + return result; +} +inline INT SMLABT(const LONG accu, const SHORT a, const LONG b) +{ + INT result ; + __asm__ ("smlabt %0, %1, %2,%3" + : "=r" (result) + : "r" (a), "r" (b), "r" (accu)) ; + return result; +} +#endif /* compiler selection */ + + +void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer, + int no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, + int p_stride, /*!< Stide of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates + ) +{ + LONG *p_flt = (LONG *) p_filter; + LONG flt; + FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1; + FIXP_QMF *RESTRICT pData_1 = analysisBuffer; + + FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; + FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1; + + FIXP_DBL accu0, accu1; + FIXP_QAS sta0, sta1; + + int staStep1 = no_channels<<1; + int staStep2 = (no_channels<<3) - 1; /* Rewind one less */ + + if (p_stride == 1) + { + /* FIR filter 0 */ + flt = *p_flt++; + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMULBB( sta1, flt); + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABB( accu1, sta1, flt); + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta1 = *sta_1; sta_1 += staStep2; + accu1 = SMLABB( accu1, sta1, flt); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + + /* FIR filters 1..63 127..65 or 1..31 63..33 */ + no_channels >>= 1; + for (; --no_channels; ) + { + sta0 = *sta_0; sta_0 += staStep1; /* 1,3,5, ... 29/61 */ + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMULBT( sta0, flt); + accu1 = SMULBT( sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 -= staStep2; + sta1 = *sta_1; sta_1 += staStep2; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + + /* Same sequence as above, but mix B=bottom with T=Top */ + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; /* 2,4,6, ... 30/62 */ + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMULBB( sta0, flt); + accu1 = SMULBB( sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 -= staStep2; + sta1 = *sta_1; sta_1 += staStep2; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + } + + /* FIR filter 31/63 and 33/65 */ + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMULBT( sta0, flt); + accu1 = SMULBT( sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 -= staStep2; + sta1 = *sta_1; sta_1 += staStep2; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + + /* FIR filter 32/64 */ + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMULBB( sta0, flt); + accu1 = SMULBB( sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt++; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = *p_flt; + sta0 = *sta_0; + sta1 = *sta_1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + } + else + { + int pfltStep = QMF_NO_POLY * (p_stride-1); + + flt = p_flt[0]; + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMULBB( sta1, flt); + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABT( accu1, sta1, flt); + + flt = p_flt[1]; + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABB( accu1, sta1, flt); + sta1 = *sta_1; sta_1 -= staStep1; + accu1 = SMLABT( accu1, sta1, flt); + + flt = p_flt[2]; p_flt += pfltStep; + sta1 = *sta_1; sta_1 += staStep2; + accu1 = SMLABB( accu1, sta1, flt); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + + /* FIR filters 1..63 127..65 or 1..31 63..33 */ + for (; --no_channels; ) + { + flt = p_flt[0]; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMULBB( sta0, flt); + accu1 = SMULBB( sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = p_flt[1]; + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + sta0 = *sta_0; sta_0 += staStep1; + sta1 = *sta_1; sta_1 -= staStep1; + accu0 = SMLABT( accu0, sta0, flt); + accu1 = SMLABT( accu1, sta1, flt); + + flt = p_flt[2]; p_flt += pfltStep; + sta0 = *sta_0; sta_0 -= staStep2; + sta1 = *sta_1; sta_1 += staStep2; + accu0 = SMLABB( accu0, sta0, flt); + accu1 = SMLABB( accu1, sta1, flt); + + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + *pData_1++ = FX_DBL2FX_QMF(accu1<<1); + } + + /* FIR filter 32/64 */ + flt = p_flt[0]; + sta0 = *sta_0; sta_0 += staStep1; + accu0 = SMULBB( sta0, flt); + sta0 = *sta_0; sta_0 += staStep1; + accu0 = SMLABT( accu0, sta0, flt); + + flt = p_flt[1]; + sta0 = *sta_0; sta_0 += staStep1; + accu0 = SMLABB( accu0, sta0, flt); + sta0 = *sta_0; sta_0 += staStep1; + accu0 = SMLABT( accu0, sta0, flt); + + flt = p_flt[2]; + sta0 = *sta_0; + accu0 = SMLABB( accu0, sta0, flt); + *pData_0-- = FX_DBL2FX_QMF(accu0<<1); + } +} +#endif /* FUNCTION_qmfAnaPrototypeFirSlot */ +#endif /* #if defined(__CC_ARM) && defined(__ARM_ARCH_6__) */ + +#if ( defined(__ARM_ARCH_5TE__) && (SAMPLE_BITS == 16) ) && !defined(QMF_TABLE_FULL) + +#define FUNCTION_qmfSynPrototypeFirSlot + +#if defined(FUNCTION_qmfSynPrototypeFirSlot) + +#if defined(__GNUC__) /* cppp replaced: elif */ + +inline INT SMULWB (const LONG a, const LONG b) +{ + INT result ; + __asm__ ("smulwb %0, %1, %2" + : "=r" (result) + : "r" (a), "r" (b)) ; + + return result ; +} +inline INT SMULWT (const LONG a, const LONG b) +{ + INT result ; + __asm__ ("smulwt %0, %1, %2" + : "=r" (result) + : "r" (a), "r" (b)) ; + + return result ; +} + +inline INT SMLAWB(const LONG accu, const LONG a, const LONG b) +{ + INT result; + asm("smlawb %0, %1, %2, %3 " + : "=r" (result) + : "r" (a), "r" (b), "r" (accu) ); + return result ; +} + +inline INT SMLAWT(const LONG accu, const LONG a, const LONG b) +{ + INT result; + asm("smlawt %0, %1, %2, %3 " + : "=r" (result) + : "r" (a), "r" (b), "r" (accu) ); + return result ; +} + +#endif /* ARM compiler selector */ + + +static void qmfSynPrototypeFirSlot1_filter(FIXP_QMF *RESTRICT realSlot, + FIXP_QMF *RESTRICT imagSlot, + const FIXP_DBL *RESTRICT p_flt, + FIXP_QSS *RESTRICT sta, + FIXP_DBL *pMyTimeOut, + int no_channels) +{ + /* This code was the base for the above listed assembler sequence */ + /* It can be used for debugging purpose or further optimizations */ + const FIXP_DBL *RESTRICT p_fltm = p_flt + 155; + + do + { + FIXP_DBL result; + FIXP_DBL A, B, real, imag, sta0; + + real = *--realSlot; + imag = *--imagSlot; + B = p_flt[4]; /* Bottom=[8] Top=[9] */ + A = p_fltm[3]; /* Bottom=[316] Top=[317] */ + sta0 = sta[0]; /* save state[0] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=9...........319 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=316...........6 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=8,18, ...318 */ + B = p_flt[3]; /* Bottom=[6] Top=[7] */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=317...........7 */ + A = p_fltm[4]; /* Bottom=[318] Top=[319] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=7...........317 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=318...........8 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=6...........316 */ + B = p_flt[2]; /* Bottom=[X] Top=[5] */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=9...........319 */ + A = p_fltm[2]; /* Bottom=[X] Top=[315] */ + sta[0] = SMULWT( imag, B ); sta++; /* index=5,15, ... 315 */ + result = SMLAWT( sta0, real, A ); /* index=315...........5 */ + + pMyTimeOut[0] = result; pMyTimeOut++; + + real = *--realSlot; + imag = *--imagSlot; + A = p_fltm[0]; /* Bottom=[310] Top=[311] */ + B = p_flt[7]; /* Bottom=[14] Top=[15] */ + result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=14..........324 */ + pMyTimeOut[0] = result; pMyTimeOut++; + B = p_flt[6]; /* Bottom=[12] Top=[13] */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=311...........1 */ + A = p_fltm[1]; /* Bottom=[312] Top=[313] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=13..........323 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=312...........2 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=12..........322 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=313...........3 */ + A = p_fltm[2]; /* Bottom=[314] Top=[315] */ + B = p_flt[5]; /* Bottom=[10] Top=[11] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=11..........321 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=314...........4 */ + sta[0] = SMULWB( imag, B ); sta++; /* index=10..........320 */ + + + p_flt += 5; + p_fltm -= 5; + } + while ((--no_channels) != 0); + +} + + + +INT qmfSynPrototypeFirSlot2( + HANDLE_QMF_FILTER_BANK qmf, + FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *RESTRICT timeOut, /*!< Time domain data */ + INT stride /*!< Time output buffer stride factor*/ + ) +{ + FIXP_QSS *RESTRICT sta = (FIXP_QSS*)qmf->FilterStates; + int no_channels = qmf->no_channels; + int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); + + /* We map an arry of 16-bit values upon an array of 2*16-bit values to read 2 values in one shot */ + const FIXP_DBL *RESTRICT p_flt = (FIXP_DBL *) qmf->p_filter; /* low=[0], high=[1] */ + const FIXP_DBL *RESTRICT p_fltm = (FIXP_DBL *) qmf->p_filter + 155; /* low=[310], high=[311] */ + + FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); + FDK_ASSERT(qmf->p_stride==2 && qmf->no_channels == 32); + + FDK_ASSERT((no_channels&3) == 0); /* should be a multiple of 4 */ + + realSlot += no_channels-1; // ~~"~~ + imagSlot += no_channels-1; // no_channels-1 .. 0 + + FIXP_DBL MyTimeOut[32]; + FIXP_DBL *pMyTimeOut = &MyTimeOut[0]; + + for (no_channels = no_channels; no_channels--;) + { + FIXP_DBL result; + FIXP_DBL A, B, real, imag; + + real = *realSlot--; + imag = *imagSlot--; + A = p_fltm[0]; /* Bottom=[310] Top=[311] */ + B = p_flt[7]; /* Bottom=[14] Top=[15] */ + result = SMLAWB( sta[0], real, A ); /* index=310...........0 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=14..........324 */ + B = p_flt[6]; /* Bottom=[12] Top=[13] */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=311...........1 */ + A = p_fltm[1]; /* Bottom=[312] Top=[313] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=13..........323 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=312...........2 */ + sta[0] = SMLAWB( sta[1], imag, B ); sta++; /* index=12..........322 */ + sta[0] = SMLAWT( sta[1], real, A ); sta++; /* index=313...........3 */ + A = p_fltm[2]; /* Bottom=[314] Top=[315] */ + B = p_flt[5]; /* Bottom=[10] Top=[11] */ + sta[0] = SMLAWT( sta[1], imag, B ); sta++; /* index=11..........321 */ + sta[0] = SMLAWB( sta[1], real, A ); sta++; /* index=314...........4 */ + sta[0] = SMULWB( imag, B ); sta++; /* index=10..........320 */ + + pMyTimeOut[0] = result; pMyTimeOut++; + + p_fltm -= 5; + p_flt += 5; + } + + pMyTimeOut = &MyTimeOut[0]; +#if (SAMPLE_BITS == 16) + const FIXP_DBL max_pos = (FIXP_DBL) 0x00007FFF << scale; + const FIXP_DBL max_neg = (FIXP_DBL) 0xFFFF8001 << scale; +#else + scale = -scale; + const FIXP_DBL max_pos = (FIXP_DBL) 0x7FFFFFFF >> scale; + const FIXP_DBL max_neg = (FIXP_DBL) 0x80000001 >> scale; +#endif + const FIXP_DBL add_neg = (1 << scale) - 1; + + no_channels = qmf->no_channels; + + timeOut += no_channels*stride; + + FDK_ASSERT(scale >= 0); + + if (qmf->outGain != 0x80000000) + { + FIXP_DBL gain = qmf->outGain; + for (no_channels>>=2; no_channels--;) + { + FIXP_DBL result1, result2; + + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; + + result1 = fMult(result1,gain); + timeOut -= stride; + if (result1 < 0) result1 += add_neg; + if (result1 < max_neg) result1 = max_neg; + if (result1 > max_pos) result1 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result1 >> scale; +#else + timeOut[0] = result1 << scale; +#endif + + result2 = fMult(result2,gain); + timeOut -= stride; + if (result2 < 0) result2 += add_neg; + if (result2 < max_neg) result2 = max_neg; + if (result2 > max_pos) result2 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result2 >> scale; +#else + timeOut[0] = result2 << scale; +#endif + + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; + + result1 = fMult(result1,gain); + timeOut -= stride; + if (result1 < 0) result1 += add_neg; + if (result1 < max_neg) result1 = max_neg; + if (result1 > max_pos) result1 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result1 >> scale; +#else + timeOut[0] = result1 << scale; +#endif + + result2 = fMult(result2,gain); + timeOut -= stride; + if (result2 < 0) result2 += add_neg; + if (result2 < max_neg) result2 = max_neg; + if (result2 > max_pos) result2 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result2 >> scale; +#else + timeOut[0] = result2 << scale; +#endif + } + } + else + { + for (no_channels>>=2; no_channels--;) + { + FIXP_DBL result1, result2; + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; + timeOut -= stride; + if (result1 < 0) result1 += add_neg; + if (result1 < max_neg) result1 = max_neg; + if (result1 > max_pos) result1 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result1 >> scale; +#else + timeOut[0] = result1 << scale; +#endif + + timeOut -= stride; + if (result2 < 0) result2 += add_neg; + if (result2 < max_neg) result2 = max_neg; + if (result2 > max_pos) result2 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result2 >> scale; +#else + timeOut[0] = result2 << scale; +#endif + + result1 = pMyTimeOut[0]; pMyTimeOut++; + result2 = pMyTimeOut[0]; pMyTimeOut++; + timeOut -= stride; + if (result1 < 0) result1 += add_neg; + if (result1 < max_neg) result1 = max_neg; + if (result1 > max_pos) result1 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result1 >> scale; +#else + timeOut[0] = result1 << scale; +#endif + + timeOut -= stride; + if (result2 < 0) result2 += add_neg; + if (result2 < max_neg) result2 = max_neg; + if (result2 > max_pos) result2 = max_pos; +#if (SAMPLE_BITS == 16) + timeOut[0] = result2 >> scale; +#else + timeOut[0] = result2 << scale; +#endif + } + } + return 0; +} + +static +void qmfSynPrototypeFirSlot_fallback( HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *timeOut, /*!< Time domain data */ + const int stride + ); + +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * #MAX_SYNTHESIS_CHANNELS of input data and + generates #MAX_SYNTHESIS_CHANNELS time domain output samples. +*/ + +static +void qmfSynPrototypeFirSlot( HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *timeOut, /*!< Time domain data */ + const int stride + ) +{ + INT err = -1; + + switch (qmf->p_stride) { + case 2: + err = qmfSynPrototypeFirSlot2(qmf, realSlot, imagSlot, timeOut, stride); + break; + default: + err = -1; + } + + /* fallback if configuration not available or failed */ + if(err!=0) { + qmfSynPrototypeFirSlot_fallback(qmf, realSlot, imagSlot, timeOut, stride); + } +} +#endif /* FUNCTION_qmfSynPrototypeFirSlot */ + +#endif /* ( defined(__CC_ARM) && defined(__ARM_ARCH_5TE__) && (SAMPLE_BITS == 16) ) && !defined(QMF_TABLE_FULL) */ + + + +/* #####################################################################################*/ + + + +#endif /* (QMF_NO_POLY==5) */ + diff --git a/libFDK/src/arm/scale_arm.cpp b/libFDK/src/arm/scale_arm.cpp new file mode 100644 index 00000000..e2837ef1 --- /dev/null +++ b/libFDK/src/arm/scale_arm.cpp @@ -0,0 +1,173 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Arthur Tritthart + Description: Scaling operations for ARM + +******************************************************************************/ + +/* prevent multiple inclusion with re-definitions */ +#ifndef __INCLUDE_SCALE_ARM__ +#define __INCLUDE_SCALE_ARM__ + +#define FUNCTION_scaleValuesWithFactor_DBL + +SCALE_INLINE +void scaleValuesWithFactor( + FIXP_DBL *vector, + FIXP_DBL factor, + INT len, + INT scalefactor + ) +{ + /* This code combines the fMult with the scaling */ + /* It performs a fMultDiv2 and increments shift by 1 */ + int shift = scalefactor + 1; + FIXP_DBL *mySpec = vector; + + shift = fixmin_I(shift,(INT)DFRACT_BITS-1); + + if (shift >= 0) + { + for (int i=0; i<(len>>2); i++) + { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 <<= shift; + tmp1 <<= shift; + tmp2 <<= shift; + tmp3 <<= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i=len&3; i--;) + { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 <<= shift; + *mySpec++ = tmp0; + } + } + else + { + shift = -shift; + for (int i=0; i<(len>>2); i++) + { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 >>= shift; + tmp1 >>= shift; + tmp2 >>= shift; + tmp3 >>= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i=len&3; i--;) + { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 >>= shift; + *mySpec++ = tmp0; + } + } +} + +#endif /* #ifndef __INCLUDE_SCALE_ARM__ */ diff --git a/libFDK/src/autocorr2nd.cpp b/libFDK/src/autocorr2nd.cpp new file mode 100644 index 00000000..b7eae7c0 --- /dev/null +++ b/libFDK/src/autocorr2nd.cpp @@ -0,0 +1,278 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): M. Lohwasser + Description: auto-correlation functions + +******************************************************************************/ + +#include "autocorr2nd.h" + + + +/* If the accumulator does not provide enough overflow bits, + products have to be shifted down in the autocorrelation below. */ +#define SHIFT_FACTOR (5) +#define SHIFT >> (SHIFT_FACTOR) + + +#if defined(__CC_ARM) || defined(__arm__) +#include "arm/autocorr2nd.cpp" +#endif + + +/*! + * + * \brief Calculate second order autocorrelation using 2 accumulators + * + */ +#if !defined(FUNCTION_autoCorr2nd_real) +INT +autoCorr2nd_real (ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of input samples */ + const int len /*!< Number input samples */ + ) +{ + int j, autoCorrScaling, mScale; + + FIXP_DBL accu1, accu2, accu3, accu4, accu5; + + const FIXP_DBL *pReBuf; + + const FIXP_DBL *realBuf = reBuffer; + + /* + r11r,r22r + r01r,r12r + r02r + */ + pReBuf = realBuf-2; + accu5 = ( (fMultDiv2(pReBuf[0], pReBuf[2]) + + fMultDiv2(pReBuf[1], pReBuf[3])) SHIFT); + pReBuf++; + + //len must be even + accu1 = fPow2Div2(pReBuf[0]) SHIFT; + accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) SHIFT; + pReBuf++; + + for ( j = (len - 2)>>1; j != 0; j--,pReBuf+=2 ) { + + accu1 += ( (fPow2Div2(pReBuf[0]) + + fPow2Div2(pReBuf[1])) SHIFT); + + accu3 += ( (fMultDiv2(pReBuf[0], pReBuf[1]) + + fMultDiv2(pReBuf[1], pReBuf[2])) SHIFT); + + accu5 += ( (fMultDiv2(pReBuf[0], pReBuf[2]) + + fMultDiv2(pReBuf[1], pReBuf[3])) SHIFT); + + } + + accu2 = (fPow2Div2(realBuf[-2]) SHIFT); + accu2 += accu1; + + accu1 += (fPow2Div2(realBuf[len - 2]) SHIFT); + + accu4 = (fMultDiv2(realBuf[-1],realBuf[-2]) SHIFT); + accu4 += accu3; + + accu3 += (fMultDiv2(realBuf[len - 1],realBuf[len - 2]) SHIFT); + + mScale = CntLeadingZeros( (accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5)) ) - 1; + autoCorrScaling = mScale - 1 - SHIFT_FACTOR; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r11r = accu1 << mScale; + ac->r22r = accu2 << mScale; + ac->r01r = accu3 << mScale; + ac->r12r = accu4 << mScale; + ac->r02r = accu5 << mScale; + + ac->det = (fMultDiv2(ac->r11r,ac->r22r) - fMultDiv2(ac->r12r,ac->r12r)) ; + mScale = CountLeadingBits(fAbs(ac->det)); + + ac->det <<= mScale; + ac->det_scale = mScale - 1; + + return autoCorrScaling; +} +#endif + +#ifndef LOW_POWER_SBR_ONLY +#if !defined(FUNCTION_autoCorr2nd_cplx) +INT +autoCorr2nd_cplx (ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to real part of input samples */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of input samples */ + const int len /*!< Number of input samples */ + ) +{ + + int j, autoCorrScaling, mScale, len_scale; + + FIXP_DBL accu0, accu1,accu2, accu3, accu4, accu5, accu6, accu7, accu8; + + const FIXP_DBL *pReBuf, *pImBuf; + + const FIXP_DBL *realBuf = reBuffer; + const FIXP_DBL *imagBuf = imBuffer; + + (len>64) ? (len_scale = 6) : (len_scale = 5); + /* + r00r, + r11r,r22r + r01r,r12r + r01i,r12i + r02r,r02i + */ + accu1 = accu3 = accu5 = accu7 = accu8 = FL2FXCONST_DBL(0.0f); + + pReBuf = realBuf-2, pImBuf = imagBuf-2; + accu7 += ( (fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> len_scale); + accu8 += ( (fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> len_scale); + + pReBuf = realBuf-1, pImBuf = imagBuf-1; + for ( j = (len - 1); j != 0; j--,pReBuf++,pImBuf++ ){ + accu1 += ( (fPow2Div2(pReBuf[0] ) + fPow2Div2(pImBuf[0] )) >> len_scale); + accu3 += ( (fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pImBuf[0], pImBuf[1])) >> len_scale); + accu5 += ( (fMultDiv2(pImBuf[1], pReBuf[0]) - fMultDiv2(pReBuf[1], pImBuf[0])) >> len_scale); + accu7 += ( (fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> len_scale); + accu8 += ( (fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> len_scale); + } + + accu2 = ( (fPow2Div2(realBuf[-2]) + fPow2Div2(imagBuf[-2])) >> len_scale); + accu2 += accu1; + + accu1 += ( (fPow2Div2(realBuf[len-2]) + + fPow2Div2(imagBuf[len-2])) >> len_scale); + accu0 = ( (fPow2Div2(realBuf[len-1]) + + fPow2Div2(imagBuf[len-1])) >> len_scale) - + ( (fPow2Div2(realBuf[-1]) + + fPow2Div2(imagBuf[-1])) >> len_scale); + accu0 += accu1; + + accu4 = ( (fMultDiv2(realBuf[-1], realBuf[-2]) + + fMultDiv2(imagBuf[-1], imagBuf[-2])) >> len_scale); + accu4 += accu3; + + accu3 += ( (fMultDiv2(realBuf[len-1], realBuf[len-2]) + + fMultDiv2(imagBuf[len-1], imagBuf[len-2])) >> len_scale); + + accu6 = ( (fMultDiv2(imagBuf[-1], realBuf[-2]) - + fMultDiv2(realBuf[-1], imagBuf[-2])) >> len_scale); + accu6 += accu5; + + accu5 += ( (fMultDiv2(imagBuf[len - 1], realBuf[len - 2]) - + fMultDiv2(realBuf[len - 1], imagBuf[len - 2])) >> len_scale); + + mScale = CntLeadingZeros( (accu0 | accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5) | + fAbs(accu6) | fAbs(accu7) | fAbs(accu8)) ) - 1; + autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r00r = (FIXP_DBL)accu0 << mScale; + ac->r11r = (FIXP_DBL)accu1 << mScale; + ac->r22r = (FIXP_DBL)accu2 << mScale; + ac->r01r = (FIXP_DBL)accu3 << mScale; + ac->r12r = (FIXP_DBL)accu4 << mScale; + ac->r01i = (FIXP_DBL)accu5 << mScale; + ac->r12i = (FIXP_DBL)accu6 << mScale; + ac->r02r = (FIXP_DBL)accu7 << mScale; + ac->r02i = (FIXP_DBL)accu8 << mScale; + + ac->det = ( fMultDiv2(ac->r11r,ac->r22r) >> 1 ) - + ( (fMultDiv2(ac->r12r,ac->r12r) + fMultDiv2(ac->r12i,ac->r12i)) >> 1 ); + mScale = CountLeadingBits(fAbs(ac->det)); + + ac->det <<= mScale; + ac->det_scale = mScale - 2; + + return autoCorrScaling; +} +#endif /* FUNCTION_autoCorr2nd_cplx */ +#endif /* LOW_POWER_SBR_ONLY */ + + diff --git a/libFDK/src/dct.cpp b/libFDK/src/dct.cpp new file mode 100644 index 00000000..1e5b93ec --- /dev/null +++ b/libFDK/src/dct.cpp @@ -0,0 +1,540 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file dct.cpp + \brief DCT Implementations + Library functions to calculate standard DCTs. This will most likely be replaced by hand-optimized + functions for the specific target processor. + + Three different implementations of the dct type II and the dct type III transforms are provided. + + By default implementations which are based on a single, standard complex FFT-kernel are used (dctII_f() and dctIII_f()). + These are specifically helpful in cases where optimized FFT libraries are already available. The FFT used in these + implementation is FFT rad2 from FDK_tools. + + Of course, one might also use DCT-libraries should they be available. The DCT and DST + type IV implementations are only available in a version based on a complex FFT kernel. +*/ + +#include "dct.h" + + +#include "FDK_tools_rom.h" +#include "fft.h" + + +#if defined(__arm__) +#include "arm/dct_arm.cpp" +#endif + + +#if !defined(FUNCTION_dct_III) +void dct_III(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e + ) +{ + FDK_ASSERT(L == 64 || L == 32); + int i; + FIXP_DBL xr, accu1, accu2; + int inc; + int M = L>>1; + int ld_M; + + if (L == 64) ld_M = 5; + else ld_M = 4; + + /* This loop performs multiplication for index i (i*inc) */ + inc = (64/2) >> ld_M; /* 64/L */ + + FIXP_DBL *pTmp_0 = &tmp[2]; + FIXP_DBL *pTmp_1 = &tmp[(M-1)*2]; + + for(i=1; i>1; i++,pTmp_0+=2,pTmp_1-=2) { + + FIXP_DBL accu3,accu4,accu5,accu6; + + cplxMultDiv2(&accu2, &accu1, pDat[L - i], pDat[i], sin_twiddle_L64[i*inc]); + cplxMultDiv2(&accu4, &accu3, pDat[M+i], pDat[M-i], sin_twiddle_L64[(M-i)*inc]); + accu3 >>= 1; accu4 >>= 1; + + /* This method is better for ARM926, that uses operand2 shifted right by 1 always */ + cplxMultDiv2(&accu6, &accu5, (accu3 - (accu1>>1)), ((accu2>>1) + accu4), sin_twiddle_L64[(4*i)*inc]); + xr = (accu1>>1) + accu3; + pTmp_0[0] = (xr>>1) - accu5; + pTmp_1[0] = (xr>>1) + accu5; + + xr = (accu2>>1) - accu4; + pTmp_0[1] = (xr>>1) - accu6; + pTmp_1[1] = -((xr>>1) + accu6); + + } + + xr = fMultDiv2(pDat[M], sin_twiddle_L64[64/2].v.re );/* cos((PI/(2*L))*M); */ + tmp[0] = ((pDat[0]>>1) + xr)>>1; + tmp[1] = ((pDat[0]>>1) - xr)>>1; + + cplxMultDiv2(&accu2, &accu1, pDat[L - (M/2)], pDat[M/2], sin_twiddle_L64[64/4]); + tmp[M] = accu1>>1; + tmp[M+1] = accu2>>1; + + /* dit_fft expects 1 bit scaled input values */ + fft(M, tmp, pDat_e); + + /* ARM926: 12 cycles per 2-iteration, no overhead code by compiler */ + pTmp_1 = &tmp[L]; + for (i = M>>1; i--;) + { + FIXP_DBL tmp1, tmp2, tmp3, tmp4; + tmp1 = *tmp++; + tmp2 = *tmp++; + tmp3 = *--pTmp_1; + tmp4 = *--pTmp_1; + *pDat++ = tmp1; + *pDat++ = tmp3; + *pDat++ = tmp2; + *pDat++ = tmp4; + } + + *pDat_e += 2; +} +#endif + +#if !defined(FUNCTION_dct_II) +void dct_II(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e + ) +{ + FDK_ASSERT(L == 64 || L == 32); + FIXP_DBL accu1,accu2; + FIXP_DBL *pTmp_0, *pTmp_1; + + int i; + int inc; + int M = L>>1; + int ld_M; + + FDK_ASSERT(L == 64 || L == 32); + ld_M = 4 + (L >> 6); /* L=64: 5, L=32: 4 */ + + inc = (64/2) >> ld_M; /* L=64: 1, L=32: 2 */ + + FIXP_DBL *pdat = &pDat[0]; + FIXP_DBL accu3, accu4; + pTmp_0 = &tmp[0]; + pTmp_1 = &tmp[L-1]; + for (i = M>>1; i--; ) + { + accu1 = *pdat++; + accu2 = *pdat++; + accu3 = *pdat++; + accu4 = *pdat++; + accu1 >>= 1; + accu2 >>= 1; + accu3 >>= 1; + accu4 >>= 1; + *pTmp_0++ = accu1; + *pTmp_0++ = accu3; + *pTmp_1-- = accu2; + *pTmp_1-- = accu4; + } + + + fft(M, tmp, pDat_e); + + pTmp_0 = &tmp[2]; + pTmp_1 = &tmp[(M-1)*2]; + + for (i=1; i>1; i++,pTmp_0+=2,pTmp_1-=2) { + + FIXP_DBL a1,a2; + FIXP_DBL accu3, accu4; + + a1 = ((pTmp_0[1]>>1) + (pTmp_1[1]>>1)); + a2 = ((pTmp_1[0]>>1) - (pTmp_0[0]>>1)); + + cplxMultDiv2(&accu1, &accu2, a2, a1, sin_twiddle_L64[(4*i)*inc]); + accu1<<=1; accu2<<=1; + + a1 = ((pTmp_0[0]>>1) + (pTmp_1[0]>>1)); + a2 = ((pTmp_0[1]>>1) - (pTmp_1[1]>>1)); + + cplxMultDiv2(&accu3, &accu4, (a1 + accu2), -(accu1 + a2), sin_twiddle_L64[i*inc]); + pDat[L - i] = accu4; + pDat[i] = accu3; + + cplxMultDiv2(&accu3, &accu4, (a1 - accu2), -(accu1 - a2), sin_twiddle_L64[(M-i)*inc]); + pDat[M + i] = accu4; + pDat[M - i] = accu3; + + } + + cplxMultDiv2(&accu1, &accu2, tmp[M], tmp[M+1], sin_twiddle_L64[(M/2)*inc]); + pDat[L - (M/2)] = accu2; + pDat[M/2] = accu1; + + pDat[0] = (tmp[0]>>1)+(tmp[1]>>1); + pDat[M] = fMult(((tmp[0]>>1)-(tmp[1]>>1)), sin_twiddle_L64[64/2].v.re);/* cos((PI/(2*L))*M); */ + + *pDat_e += 2; +} +#endif + +static +void getTables(const FIXP_WTP **twiddle, const FIXP_STP **sin_twiddle, int *sin_step, int length) +{ + int ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS-1-fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ( (length) >> (ld2_length-1) ) { + case 0x4: /* radix 2 */ + *sin_twiddle = SineTable512; + *sin_step = 1<<(9 - ld2_length); + *twiddle = windowSlopes[0][0][ld2_length-1]; + break; + case 0x7: /* 10 ms */ + *sin_twiddle = SineTable480; + *sin_step = 1<<(8 - ld2_length); + *twiddle = windowSlopes[0][1][ld2_length]; + break; + default: + *sin_twiddle = NULL; + *sin_step = 0; + *twiddle = NULL; + break; + } + + FDK_ASSERT(*twiddle != NULL); + + FDK_ASSERT(*sin_step > 0); + +} + +#if !defined(FUNCTION_dct_IV) + +void dct_IV(FIXP_DBL *pDat, + int L, + int *pDat_e) +{ + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + + FDK_ASSERT(L >= 4); + + getTables(&twiddle, &sin_twiddle, &sin_step, L); + +#ifdef FUNCTION_dct_IV_func1 + if (M>=4 && (M&3) == 0) { + /* ARM926: 44 cycles for 2 iterations = 22 cycles/iteration */ + dct_IV_func1(M>>2, twiddle, &pDat[0], &pDat[L-1]); + } else +#endif /* FUNCTION_dct_IV_func1 */ + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + int i; + + /* 29 cycles on ARM926 */ + for (i = 0; i < M-1; i+=2,pDat_0+=2,pDat_1-=2) + { + FIXP_DBL accu1,accu2,accu3,accu4; + + accu1 = pDat_1[1]; accu2 = pDat_0[0]; + accu3 = pDat_0[1]; accu4 = pDat_1[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i+1]); + + pDat_0[0] = accu2; pDat_0[1] = accu1; + pDat_1[0] = accu4; pDat_1[1] = -accu3; + } + if (M&1) + { + FIXP_DBL accu1,accu2; + + accu1 = pDat_1[1]; accu2 = pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2; pDat_0[1] = accu1; + } + } + + fft(M, pDat, pDat_e); + +#ifdef FUNCTION_dct_IV_func2 + if (M>=4 && (M&3) == 0) { + /* ARM926: 42 cycles for 2 iterations = 21 cycles/iteration */ + dct_IV_func2(M>>2, sin_twiddle, &pDat[0], &pDat[L], sin_step); + } else +#endif /* FUNCTION_dct_IV_func2 */ + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + FIXP_DBL accu1,accu2,accu3,accu4; + int idx, i; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -(pDat_0[1]>>1); + pDat_0[0] = (pDat_0[0]>>1); + + + /* 28 cycles for ARM926 */ + for (idx = sin_step,i=1; i<(M+1)>>1; i++, idx+=sin_step) + { + FIXP_STP twd = sin_twiddle[idx]; + cplxMultDiv2(&accu3, &accu4, accu1, accu2, twd); + pDat_0[1] = accu3; + pDat_1[0] = accu4; + + pDat_0+=2; + pDat_1-=2; + + cplxMultDiv2(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -accu3; + pDat_0[0] = accu4; + } + + if ( (M&1) == 0 ) + { + /* Last Sin and Cos value pair are the same */ + accu1 = fMultDiv2(accu1, WTC(0x5a82799a)); + accu2 = fMultDiv2(accu2, WTC(0x5a82799a)); + + pDat_1[0] = accu1 + accu2; + pDat_0[1] = accu1 - accu2; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* defined (FUNCTION_dct_IV) */ + +#if !defined(FUNCTION_dst_IV) +void dst_IV(FIXP_DBL *pDat, + int L, + int *pDat_e ) +{ + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + +#ifdef DSTIV2_ENABLE + if (L == 2) { + const FIXP_STP tab = STCP(0x7641AF3D, 0x30FB9452); + FIXP_DBL tmp1, tmp2; + + cplxMultDiv2(&tmp2, &tmp1, pDat[0], pDat[1], tab); + + pDat[0] = tmp1; + pDat[1] = tmp2; + + *pDat_e += 1; + + return; + } +#else + FDK_ASSERT(L >= 4); +#endif + + getTables(&twiddle, &sin_twiddle, &sin_step, L); + +#ifdef FUNCTION_dst_IV_func1 + if ( (M>=4) && ((M&3) == 0) ) { + dst_IV_func1(M, twiddle, &pDat[0], &pDat[L]); + } else +#endif + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + + int i; + + /* 34 cycles on ARM926 */ + for (i = 0; i < M-1; i+=2,pDat_0+=2,pDat_1-=2) + { + FIXP_DBL accu1,accu2,accu3,accu4; + + accu1 = pDat_1[1]; accu2 = -pDat_0[0]; + accu3 = pDat_0[1]; accu4 = -pDat_1[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i+1]); + + pDat_0[0] = accu2; pDat_0[1] = accu1; + pDat_1[0] = accu4; pDat_1[1] = -accu3; + } + if (M&1) + { + FIXP_DBL accu1,accu2; + + accu1 = pDat_1[1]; accu2 = -pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2; pDat_0[1] = accu1; + } + } + + fft(M, pDat, pDat_e); + +#ifdef FUNCTION_dst_IV_func2 + if ( (M>=4) && ((M&3) == 0) ) { + dst_IV_func2(M>>2, sin_twiddle + sin_step, &pDat[0], &pDat[L - 1], sin_step); + } else +#endif /* FUNCTION_dst_IV_func2 */ + { + FIXP_DBL *RESTRICT pDat_0; + FIXP_DBL *RESTRICT pDat_1; + FIXP_DBL accu1,accu2,accu3,accu4; + int idx, i; + + pDat_0 = &pDat[0]; + pDat_1 = &pDat[L - 2]; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -(pDat_0[0]>>1); + pDat_0[0] = (pDat_0[1]>>1); + + for (idx = sin_step,i=1; i<(M+1)>>1; i++, idx+=sin_step) + { + FIXP_STP twd = sin_twiddle[idx]; + + cplxMultDiv2(&accu3, &accu4, accu1, accu2, twd); + pDat_1[0] = -accu3; + pDat_0[1] = -accu4; + + pDat_0+=2; + pDat_1-=2; + + cplxMultDiv2(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_0[0] = accu3; + pDat_1[1] = -accu4; + } + + if ( (M&1) == 0 ) + { + /* Last Sin and Cos value pair are the same */ + accu1 = fMultDiv2(accu1, WTC(0x5a82799a)); + accu2 = fMultDiv2(accu2, WTC(0x5a82799a)); + + pDat_0[1] = - accu1 - accu2; + pDat_1[0] = accu2 - accu1; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* !defined(FUNCTION_dst_IV) */ + + diff --git a/libFDK/src/fft.cpp b/libFDK/src/fft.cpp new file mode 100644 index 00000000..ae3c98d0 --- /dev/null +++ b/libFDK/src/fft.cpp @@ -0,0 +1,1404 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Josef Hoepfl, DSP Solutions + Description: Fix point FFT + +******************************************************************************/ + +#include "fft.h" + +#include "fft_rad2.h" +#include "FDK_tools_rom.h" + + + + + +#define F3C(x) STC(x) + +#define C31 (F3C(0x91261468)) /* FL2FXCONST_DBL(-0.86602540) */ + +/* Performs the FFT of length 3 according to the algorithm after winograd. + No scaling of the input vector because the scaling is already done in the rotation vector. */ +static FORCEINLINE void fft3(FIXP_DBL *RESTRICT pDat) +{ + FIXP_DBL r1,r2; + FIXP_DBL s1,s2; + /* real part */ + r1 = pDat[2] + pDat[4]; + r2 = fMult((pDat[2] - pDat[4]), C31); + pDat[0] = pDat[0] + r1; + r1 = pDat[0] - r1 - (r1>>1); + + /* imaginary part */ + s1 = pDat[3] + pDat[5]; + s2 = fMult((pDat[3] - pDat[5]), C31); + pDat[1] = pDat[1] + s1; + s1 = pDat[1] - s1 - (s1>>1); + + /* combination */ + pDat[2] = r1 - s2; + pDat[4] = r1 + s2; + pDat[3] = s1 + r2; + pDat[5] = s1 - r2; +} + + +#define F5C(x) STC(x) + +#define C51 (F5C(0x79bc3854)) /* FL2FXCONST_DBL( 0.95105652) */ +#define C52 (F5C(0x9d839db0)) /* FL2FXCONST_DBL(-1.53884180/2) */ +#define C53 (F5C(0xd18053ce)) /* FL2FXCONST_DBL(-0.36327126) */ +#define C54 (F5C(0x478dde64)) /* FL2FXCONST_DBL( 0.55901699) */ +#define C55 (F5C(0xb0000001)) /* FL2FXCONST_DBL(-1.25/2) */ + +/* performs the FFT of length 5 according to the algorithm after winograd */ +static FORCEINLINE void fft5(FIXP_DBL *RESTRICT pDat) +{ + FIXP_DBL r1,r2,r3,r4; + FIXP_DBL s1,s2,s3,s4; + FIXP_DBL t; + + /* real part */ + r1 = pDat[2] + pDat[8]; + r4 = pDat[2] - pDat[8]; + r3 = pDat[4] + pDat[6]; + r2 = pDat[4] - pDat[6]; + t = fMult((r1-r3), C54); + r1 = r1 + r3; + pDat[0] = pDat[0] + r1; + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + r1 = pDat[0] + (fMultDiv2(r1, C55) <<(2)); + r3 = r1 - t; + r1 = r1 + t; + t = fMult((r4 + r2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + r4 = t + (fMultDiv2(r4, C52) <<(2)); + r2 = t + fMult(r2, C53); + + /* imaginary part */ + s1 = pDat[3] + pDat[9]; + s4 = pDat[3] - pDat[9]; + s3 = pDat[5] + pDat[7]; + s2 = pDat[5] - pDat[7]; + t = fMult((s1 - s3), C54); + s1 = s1 + s3; + pDat[1] = pDat[1] + s1; + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + s1 = pDat[1] + (fMultDiv2(s1, C55) <<(2)); + s3 = s1 - t; + s1 = s1 + t; + t = fMult((s4 + s2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + s4 = t + (fMultDiv2(s4, C52) <<(2)); + s2 = t + fMult(s2, C53); + + /* combination */ + pDat[2] = r1 + s2; + pDat[8] = r1 - s2; + pDat[4] = r3 - s4; + pDat[6] = r3 + s4; + + pDat[3] = s1 - r2; + pDat[9] = s1 + r2; + pDat[5] = s3 + r4; + pDat[7] = s3 - r4; +} + + + + +#define N3 3 +#define N5 5 +#define N6 6 +#define N15 15 + +/* Performs the FFT of length 15. It is split into FFTs of length 3 and length 5. */ +static inline void fft15(FIXP_DBL *pInput) +{ + FIXP_DBL aDst[2*N15]; + FIXP_DBL aDst1[2*N15]; + int i,k,l; + + /* Sort input vector for fft's of length 3 + input3(0:2) = [input(0) input(5) input(10)]; + input3(3:5) = [input(3) input(8) input(13)]; + input3(6:8) = [input(6) input(11) input(1)]; + input3(9:11) = [input(9) input(14) input(4)]; + input3(12:14) = [input(12) input(2) input(7)]; */ + { + const FIXP_DBL *pSrc = pInput; + FIXP_DBL *RESTRICT pDst = aDst; + /* Merge 3 loops into one, skip call of fft3 */ + for(i=0,l=0,k=0; i= (2*N15)) + l -= (2*N15); + + pDst[k+2] = pSrc[l]; + pDst[k+3] = pSrc[l+1]; + l += 2*N5; + if (l >= (2*N15)) + l -= (2*N15); + pDst[k+4] = pSrc[l]; + pDst[k+5] = pSrc[l+1]; + l += (2*N5) + (2*N3); + if (l >= (2*N15)) + l -= (2*N15); + + /* fft3 merged with shift right by 2 loop */ + FIXP_DBL r1,r2,r3; + FIXP_DBL s1,s2; + /* real part */ + r1 = pDst[k+2] + pDst[k+4]; + r2 = fMult((pDst[k+2] - pDst[k+4]), C31); + s1 = pDst[k+0]; + pDst[k+0] = (s1 + r1)>>2; + r1 = s1 - (r1>>1); + + /* imaginary part */ + s1 = pDst[k+3] + pDst[k+5]; + s2 = fMult((pDst[k+3] - pDst[k+5]), C31); + r3 = pDst[k+1]; + pDst[k+1] = (r3 + s1)>>2; + s1 = r3 - (s1>>1); + + /* combination */ + pDst[k+2] = (r1 - s2)>>2; + pDst[k+4] = (r1 + s2)>>2; + pDst[k+3] = (s1 + r2)>>2; + pDst[k+5] = (s1 - r2)>>2; + } + } + /* Sort input vector for fft's of length 5 + input5(0:4) = [output3(0) output3(3) output3(6) output3(9) output3(12)]; + input5(5:9) = [output3(1) output3(4) output3(7) output3(10) output3(13)]; + input5(10:14) = [output3(2) output3(5) output3(8) output3(11) output3(14)]; */ + /* Merge 2 loops into one, brings about 10% */ + { + const FIXP_DBL *pSrc = aDst; + FIXP_DBL *RESTRICT pDst = aDst1; + for(i=0,l=0,k=0; i= (2*N15)) + l -= (2*N15); + pDst[k+2] = pSrc[l]; + pDst[k+3] = pSrc[l+1]; + l += (2*N6); + if (l >= (2*N15)) + l -= (2*N15); + pDst[k+4] = pSrc[l]; + pDst[k+5] = pSrc[l+1]; + l += (2*N6); + if (l >= (2*N15)) + l -= (2*N15); + pDst[k+6] = pSrc[l]; + pDst[k+7] = pSrc[l+1]; + l += (2*N6); + if (l >= (2*N15)) + l -= (2*N15); + pDst[k+8] = pSrc[l]; + pDst[k+9] = pSrc[l+1]; + l += 2; /* no modulo check needed, it cannot occur */ + } + } +} + +#define W_PiFOURTH STC(0x5a82799a) +#ifndef SUMDIFF_PIFOURTH +#define SUMDIFF_PIFOURTH(diff,sum,a,b) \ + { \ + FIXP_DBL wa, wb;\ + wa = fMultDiv2(a, W_PiFOURTH);\ + wb = fMultDiv2(b, W_PiFOURTH);\ + diff = wb - wa;\ + sum = wb + wa;\ + } +#endif + +/* This version is more overflow save, but less cycle optimal. */ +#define SUMDIFF_EIGTH(x, y, ix, iy, vr, vi, ur, ui) \ + vr = (x[ 0 + ix]>>1) + (x[16 + ix]>>1); /* Re A + Re B */ \ + vi = (x[ 8 + ix]>>1) + (x[24 + ix]>>1); /* Re C + Re D */ \ + ur = (x[ 1 + ix]>>1) + (x[17 + ix]>>1); /* Im A + Im B */ \ + ui = (x[ 9 + ix]>>1) + (x[25 + ix]>>1); /* Im C + Im D */ \ + y[ 0 + iy] = vr + vi; /* Re A' = ReA + ReB +ReC + ReD */ \ + y[ 4 + iy] = vr - vi; /* Re C' = -(ReC+ReD) + (ReA+ReB) */ \ + y[ 1 + iy] = ur + ui; /* Im A' = sum of imag values */ \ + y[ 5 + iy] = ur - ui; /* Im C' = -Im C -Im D +Im A +Im B */ \ + vr -= x[16 + ix]; /* Re A - Re B */ \ + vi = vi - x[24 + ix]; /* Re C - Re D */ \ + ur -= x[17 + ix]; /* Im A - Im B */ \ + ui = ui - x[25 + ix]; /* Im C - Im D */ \ + y[ 2 + iy] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ \ + y[ 6 + iy] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ \ + y[ 3 + iy] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ \ + y[ 7 + iy] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + +static const FIXP_STP fft16_w16[2] = { STCP(0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d) }; + +LNK_SECTION_CODE_L1 +inline void fft_16(FIXP_DBL *RESTRICT x) +{ + FIXP_DBL vr, vi, ur, ui; + FIXP_DBL y[32]; + + SUMDIFF_EIGTH(x, y, 0, 0, vr, vi, ur, ui); + SUMDIFF_EIGTH(x, y, 4, 8, vr, vi, ur, ui); + SUMDIFF_EIGTH(x, y, 2, 16, vr, vi, ur, ui); + SUMDIFF_EIGTH(x, y, 6, 24, vr, vi, ur, ui); + +// xt1 = 0 +// xt2 = 8 + vr = y[ 8]; + vi = y[ 9]; + ur = y[ 0]>>1; + ui = y[ 1]>>1; + x[ 0] = ur + (vr>>1); + x[ 1] = ui + (vi>>1); + x[ 8] = ur - (vr>>1); + x[ 9] = ui - (vi>>1); + +// xt1 = 4 +// xt2 = 12 + vr = y[13]; + vi = y[12]; + ur = y[ 4]>>1; + ui = y[ 5]>>1; + x[ 4] = ur + (vr>>1); + x[ 5] = ui - (vi>>1); + x[12] = ur - (vr>>1); + x[13] = ui + (vi>>1); + +// xt1 = 16 +// xt2 = 24 + vr = y[24]; + vi = y[25]; + ur = y[16]>>1; + ui = y[17]>>1; + x[16] = ur + (vr>>1); + x[17] = ui + (vi>>1); + x[24] = ur - (vr>>1); + x[25] = ui - (vi>>1); + +// xt1 = 20 +// xt2 = 28 + vr = y[29]; + vi = y[28]; + ur = y[20]>>1; + ui = y[21]>>1; + x[20] = ur + (vr>>1); + x[21] = ui - (vi>>1); + x[28] = ur - (vr>>1); + x[29] = ui + (vi>>1); + + // xt1 = 2 +// xt2 = 10 + SUMDIFF_PIFOURTH(vi, vr, y[10], y[11]) + //vr = fMultDiv2((y[11] + y[10]),W_PiFOURTH); + //vi = fMultDiv2((y[11] - y[10]),W_PiFOURTH); + ur = y[ 2]; + ui = y[ 3]; + x[ 2] = (ur>>1) + vr; + x[ 3] = (ui>>1) + vi; + x[10] = (ur>>1) - vr; + x[11] = (ui>>1) - vi; + +// xt1 = 6 +// xt2 = 14 + SUMDIFF_PIFOURTH(vr, vi, y[14], y[15]) + ur = y[ 6]; + ui = y[ 7]; + x[ 6] = (ur>>1) + vr; + x[ 7] = (ui>>1) - vi; + x[14] = (ur>>1) - vr; + x[15] = (ui>>1) + vi; + +// xt1 = 18 +// xt2 = 26 + SUMDIFF_PIFOURTH(vi, vr, y[26], y[27]) + ur = y[18]; + ui = y[19]; + x[18] = (ur>>1) + vr; + x[19] = (ui>>1) + vi; + x[26] = (ur>>1) - vr; + x[27] = (ui>>1) - vi; + +// xt1 = 22 +// xt2 = 30 + SUMDIFF_PIFOURTH(vr, vi, y[30], y[31]) + ur = y[22]; + ui = y[23]; + x[22] = (ur>>1) + vr; + x[23] = (ui>>1) - vi; + x[30] = (ur>>1) - vr; + x[31] = (ui>>1) + vi; + +// xt1 = 0 +// xt2 = 16 + vr = x[16]; + vi = x[17]; + ur = x[ 0]>>1; + ui = x[ 1]>>1; + x[ 0] = ur + (vr>>1); + x[ 1] = ui + (vi>>1); + x[16] = ur - (vr>>1); + x[17] = ui - (vi>>1); + +// xt1 = 8 +// xt2 = 24 + vi = x[24]; + vr = x[25]; + ur = x[ 8]>>1; + ui = x[ 9]>>1; + x[ 8] = ur + (vr>>1); + x[ 9] = ui - (vi>>1); + x[24] = ur - (vr>>1); + x[25] = ui + (vi>>1); + +// xt1 = 2 +// xt2 = 18 + cplxMultDiv2(&vi, &vr, x[19], x[18], fft16_w16[0]); + ur = x[ 2]; + ui = x[ 3]; + x[ 2] = (ur>>1) + vr; + x[ 3] = (ui>>1) + vi; + x[18] = (ur>>1) - vr; + x[19] = (ui>>1) - vi; + +// xt1 = 10 +// xt2 = 26 + cplxMultDiv2(&vr, &vi, x[27], x[26], fft16_w16[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur>>1) + vr; + x[11] = (ui>>1) - vi; + x[26] = (ur>>1) - vr; + x[27] = (ui>>1) + vi; + +// xt1 = 4 +// xt2 = 20 + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[ 4]; + ui = x[ 5]; + x[ 4] = (ur>>1) + vr; + x[ 5] = (ui>>1) + vi; + x[20] = (ur>>1) - vr; + x[21] = (ui>>1) - vi; + +// xt1 = 12 +// xt2 = 28 + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur>>1) + vr; + x[13] = (ui>>1) - vi; + x[28] = (ur>>1) - vr; + x[29] = (ui>>1) + vi; + +// xt1 = 6 +// xt2 = 22 + cplxMultDiv2(&vi, &vr, x[23], x[22], fft16_w16[1]); + ur = x[ 6]; + ui = x[ 7]; + x[ 6] = (ur>>1) + vr; + x[ 7] = (ui>>1) + vi; + x[22] = (ur>>1) - vr; + x[23] = (ui>>1) - vi; + +// xt1 = 14 +// xt2 = 30 + cplxMultDiv2(&vr, &vi, x[31], x[30], fft16_w16[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur>>1) + vr; + x[15] = (ui>>1) - vi; + x[30] = (ur>>1) - vr; + x[31] = (ui>>1) + vi; +} + +#ifndef FUNCTION_fft_32 +static const FIXP_STP fft32_w32[6] = +{ + STCP (0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d), STCP(0x7d8a5f40, 0x18f8b83c), + STCP (0x6a6d98a4, 0x471cece7), STCP(0x471cece7, 0x6a6d98a4), STCP(0x18f8b83c, 0x7d8a5f40) +}; + +LNK_SECTION_CODE_L1 +inline void fft_32(FIXP_DBL *x) +{ + +#define W_PiFOURTH STC(0x5a82799a) + + FIXP_DBL vr,vi,ur,ui; + FIXP_DBL y[64]; + + /* + * 1+2 stage radix 4 + */ + +///////////////////////////////////////////////////////////////////////////////////////// + + // i = 0 + vr = (x[ 0] + x[32])>>1; /* Re A + Re B */ + vi = (x[16] + x[48]); /* Re C + Re D */ + ur = (x[ 1] + x[33])>>1; /* Im A + Im B */ + ui = (x[17] + x[49]); /* Im C + Im D */ + + y[ 0] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[ 4] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[ 1] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[ 5] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[32]; /* Re A - Re B */ + vi = (vi>>1) - x[48]; /* Re C - Re D */ + ur -= x[33]; /* Im A - Im B */ + ui = (ui>>1) - x[49]; /* Im C - Im D */ + + y[ 2] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[ 6] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[ 3] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[ 7] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=8 + vr = (x[ 8] + x[40])>>1; /* Re A + Re B */ + vi = (x[24] + x[56]); /* Re C + Re D */ + ur = (x[ 9] + x[41])>>1; /* Im A + Im B */ + ui = (x[25] + x[57]); /* Im C + Im D */ + + y[ 8] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[12] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[ 9] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[13] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[40]; /* Re A - Re B */ + vi = (vi>>1) - x[56]; /* Re C - Re D */ + ur -= x[41]; /* Im A - Im B */ + ui = (ui>>1) - x[57]; /* Im C - Im D */ + + y[10] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[14] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[11] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[15] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=16 + vr = (x[ 4] + x[36])>>1; /* Re A + Re B */ + vi = (x[20] + x[52]); /* Re C + Re D */ + ur = (x[ 5] + x[37])>>1; /* Im A + Im B */ + ui = (x[21] + x[53]); /* Im C + Im D */ + + y[16] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[20] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[17] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[21] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[36]; /* Re A - Re B */ + vi = (vi>>1) - x[52]; /* Re C - Re D */ + ur -= x[37]; /* Im A - Im B */ + ui = (ui>>1) - x[53]; /* Im C - Im D */ + + y[18] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[22] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[19] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[23] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=24 + vr = (x[12] + x[44])>>1; /* Re A + Re B */ + vi = (x[28] + x[60]); /* Re C + Re D */ + ur = (x[13] + x[45])>>1; /* Im A + Im B */ + ui = (x[29] + x[61]); /* Im C + Im D */ + + y[24] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[28] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[25] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[29] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[44]; /* Re A - Re B */ + vi = (vi>>1) - x[60]; /* Re C - Re D */ + ur -= x[45]; /* Im A - Im B */ + ui = (ui>>1) - x[61]; /* Im C - Im D */ + + y[26] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[30] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[27] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[31] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + // i = 32 + vr = (x[ 2] + x[34])>>1; /* Re A + Re B */ + vi = (x[18] + x[50]); /* Re C + Re D */ + ur = (x[ 3] + x[35])>>1; /* Im A + Im B */ + ui = (x[19] + x[51]); /* Im C + Im D */ + + y[32] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[36] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[33] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[37] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[34]; /* Re A - Re B */ + vi = (vi>>1) - x[50]; /* Re C - Re D */ + ur -= x[35]; /* Im A - Im B */ + ui = (ui>>1) - x[51]; /* Im C - Im D */ + + y[34] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[38] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[35] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[39] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=40 + vr = (x[10] + x[42])>>1; /* Re A + Re B */ + vi = (x[26] + x[58]); /* Re C + Re D */ + ur = (x[11] + x[43])>>1; /* Im A + Im B */ + ui = (x[27] + x[59]); /* Im C + Im D */ + + y[40] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[44] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[41] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[45] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[42]; /* Re A - Re B */ + vi = (vi>>1) - x[58]; /* Re C - Re D */ + ur -= x[43]; /* Im A - Im B */ + ui = (ui>>1) - x[59]; /* Im C - Im D */ + + y[42] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[46] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[43] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[47] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=48 + vr = (x[ 6] + x[38])>>1; /* Re A + Re B */ + vi = (x[22] + x[54]); /* Re C + Re D */ + ur = (x[ 7] + x[39])>>1; /* Im A + Im B */ + ui = (x[23] + x[55]); /* Im C + Im D */ + + y[48] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[52] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[49] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[53] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[38]; /* Re A - Re B */ + vi = (vi>>1) - x[54]; /* Re C - Re D */ + ur -= x[39]; /* Im A - Im B */ + ui = (ui>>1) - x[55]; /* Im C - Im D */ + + y[50] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[54] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[51] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[55] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + //i=56 + vr = (x[14] + x[46])>>1; /* Re A + Re B */ + vi = (x[30] + x[62]); /* Re C + Re D */ + ur = (x[15] + x[47])>>1; /* Im A + Im B */ + ui = (x[31] + x[63]); /* Im C + Im D */ + + y[56] = vr + (vi>>1); /* Re A' = ReA + ReB +ReC + ReD */ + y[60] = vr - (vi>>1); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + y[57] = ur + (ui>>1); /* Im A' = sum of imag values */ + y[61] = ur - (ui>>1); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[46]; /* Re A - Re B */ + vi = (vi>>1) - x[62]; /* Re C - Re D */ + ur -= x[47]; /* Im A - Im B */ + ui = (ui>>1) - x[63]; /* Im C - Im D */ + + y[58] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + y[62] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + y[59] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + y[63] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + + FIXP_DBL *xt = &x[0]; + FIXP_DBL *yt = &y[0]; + + int j = 4; + do + { + vr = yt[8]; + vi = yt[9]; + ur = yt[0]>>1; + ui = yt[1]>>1; + xt[ 0] = ur + (vr>>1); + xt[ 1] = ui + (vi>>1); + xt[ 8] = ur - (vr>>1); + xt[ 9] = ui - (vi>>1); + + vr = yt[13]; + vi = yt[12]; + ur = yt[4]>>1; + ui = yt[5]>>1; + xt[ 4] = ur + (vr>>1); + xt[ 5] = ui - (vi>>1); + xt[12] = ur - (vr>>1); + xt[13] = ui + (vi>>1); + + SUMDIFF_PIFOURTH(vi, vr, yt[10], yt[11]) + ur = yt[2]; + ui = yt[3]; + xt[ 2] = (ur>>1) + vr; + xt[ 3] = (ui>>1) + vi; + xt[10] = (ur>>1) - vr; + xt[11] = (ui>>1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, yt[14], yt[15]) + ur = yt[6]; + ui = yt[7]; + + xt[ 6] = (ur>>1) + vr; + xt[ 7] = (ui>>1) - vi; + xt[14] = (ur>>1) - vr; + xt[15] = (ui>>1) + vi; + xt += 16; + yt += 16; + } while (--j != 0); + + vr = x[16]; + vi = x[17]; + ur = x[ 0]>>1; + ui = x[ 1]>>1; + x[ 0] = ur + (vr>>1); + x[ 1] = ui + (vi>>1); + x[16] = ur - (vr>>1); + x[17] = ui - (vi>>1); + + vi = x[24]; + vr = x[25]; + ur = x[ 8]>>1; + ui = x[ 9]>>1; + x[ 8] = ur + (vr>>1); + x[ 9] = ui - (vi>>1); + x[24] = ur - (vr>>1); + x[25] = ui + (vi>>1); + + vr = x[48]; + vi = x[49]; + ur = x[32]>>1; + ui = x[33]>>1; + x[32] = ur + (vr>>1); + x[33] = ui + (vi>>1); + x[48] = ur - (vr>>1); + x[49] = ui - (vi>>1); + + vi = x[56]; + vr = x[57]; + ur = x[40]>>1; + ui = x[41]>>1; + x[40] = ur + (vr>>1); + x[41] = ui - (vi>>1); + x[56] = ur - (vr>>1); + x[57] = ui + (vi>>1); + + cplxMultDiv2(&vi, &vr, x[19], x[18], fft32_w32[0]); + ur = x[ 2]; + ui = x[ 3]; + x[ 2] = (ur>>1) + vr; + x[ 3] = (ui>>1) + vi; + x[18] = (ur>>1) - vr; + x[19] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[27], x[26], fft32_w32[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur>>1) + vr; + x[11] = (ui>>1) - vi; + x[26] = (ur>>1) - vr; + x[27] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[51], x[50], fft32_w32[0]); + ur = x[34]; + ui = x[35]; + x[34] = (ur>>1) + vr; + x[35] = (ui>>1) + vi; + x[50] = (ur>>1) - vr; + x[51] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[0]); + ur = x[42]; + ui = x[43]; + x[42] = (ur>>1) + vr; + x[43] = (ui>>1) - vi; + x[58] = (ur>>1) - vr; + x[59] = (ui>>1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[ 4]; + ui = x[ 5]; + x[ 4] = (ur>>1) + vr; + x[ 5] = (ui>>1) + vi; + x[20] = (ur>>1) - vr; + x[21] = (ui>>1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur>>1) + vr; + x[13] = (ui>>1) - vi; + x[28] = (ur>>1) - vr; + x[29] = (ui>>1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[52], x[53]) + ur = x[36]; + ui = x[37]; + x[36] = (ur>>1) + vr; + x[37] = (ui>>1) + vi; + x[52] = (ur>>1) - vr; + x[53] = (ui>>1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[60], x[61]) + ur = x[44]; + ui = x[45]; + x[44] = (ur>>1) + vr; + x[45] = (ui>>1) - vi; + x[60] = (ur>>1) - vr; + x[61] = (ui>>1) + vi; + + + cplxMultDiv2(&vi, &vr, x[23], x[22], fft32_w32[1]); + ur = x[ 6]; + ui = x[ 7]; + x[ 6] = (ur>>1) + vr; + x[ 7] = (ui>>1) + vi; + x[22] = (ur>>1) - vr; + x[23] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[31], x[30], fft32_w32[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur>>1) + vr; + x[15] = (ui>>1) - vi; + x[30] = (ur>>1) - vr; + x[31] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[55], x[54], fft32_w32[1]); + ur = x[38]; + ui = x[39]; + x[38] = (ur>>1) + vr; + x[39] = (ui>>1) + vi; + x[54] = (ur>>1) - vr; + x[55] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[1]); + ur = x[46]; + ui = x[47]; + + x[46] = (ur>>1) + vr; + x[47] = (ui>>1) - vi; + x[62] = (ur>>1) - vr; + x[63] = (ui>>1) + vi; + + vr = x[32]; + vi = x[33]; + ur = x[ 0]>>1; + ui = x[ 1]>>1; + x[ 0] = ur + (vr>>1); + x[ 1] = ui + (vi>>1); + x[32] = ur - (vr>>1); + x[33] = ui - (vi>>1); + + vi = x[48]; + vr = x[49]; + ur = x[16]>>1; + ui = x[17]>>1; + x[16] = ur + (vr>>1); + x[17] = ui - (vi>>1); + x[48] = ur - (vr>>1); + x[49] = ui + (vi>>1); + + cplxMultDiv2(&vi, &vr, x[35], x[34], fft32_w32[2]); + ur = x[ 2]; + ui = x[ 3]; + x[ 2] = (ur>>1) + vr; + x[ 3] = (ui>>1) + vi; + x[34] = (ur>>1) - vr; + x[35] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[51], x[50], fft32_w32[2]); + ur = x[18]; + ui = x[19]; + x[18] = (ur>>1) + vr; + x[19] = (ui>>1) - vi; + x[50] = (ur>>1) - vr; + x[51] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[37], x[36], fft32_w32[0]); + ur = x[ 4]; + ui = x[ 5]; + x[ 4] = (ur>>1) + vr; + x[ 5] = (ui>>1) + vi; + x[36] = (ur>>1) - vr; + x[37] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[53], x[52], fft32_w32[0]); + ur = x[20]; + ui = x[21]; + x[20] = (ur>>1) + vr; + x[21] = (ui>>1) - vi; + x[52] = (ur>>1) - vr; + x[53] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[39], x[38], fft32_w32[3]); + ur = x[ 6]; + ui = x[ 7]; + x[ 6] = (ur>>1) + vr; + x[ 7] = (ui>>1) + vi; + x[38] = (ur>>1) - vr; + x[39] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[55], x[54], fft32_w32[3]); + ur = x[22]; + ui = x[23]; + x[22] = (ur>>1) + vr; + x[23] = (ui>>1) - vi; + x[54] = (ur>>1) - vr; + x[55] = (ui>>1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[40], x[41]) + ur = x[ 8]; + ui = x[ 9]; + x[ 8] = (ur>>1) + vr; + x[ 9] = (ui>>1) + vi; + x[40] = (ur>>1) - vr; + x[41] = (ui>>1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[56], x[57]) + ur = x[24]; + ui = x[25]; + x[24] = (ur>>1) + vr; + x[25] = (ui>>1) - vi; + x[56] = (ur>>1) - vr; + x[57] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[43], x[42], fft32_w32[4]); + ur = x[10]; + ui = x[11]; + + x[10] = (ur>>1) + vr; + x[11] = (ui>>1) + vi; + x[42] = (ur>>1) - vr; + x[43] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[4]); + ur = x[26]; + ui = x[27]; + x[26] = (ur>>1) + vr; + x[27] = (ui>>1) - vi; + x[58] = (ur>>1) - vr; + x[59] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[45], x[44], fft32_w32[1]); + ur = x[12]; + ui = x[13]; + x[12] = (ur>>1) + vr; + x[13] = (ui>>1) + vi; + x[44] = (ur>>1) - vr; + x[45] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[61], x[60], fft32_w32[1]); + ur = x[28]; + ui = x[29]; + x[28] = (ur>>1) + vr; + x[29] = (ui>>1) - vi; + x[60] = (ur>>1) - vr; + x[61] = (ui>>1) + vi; + + cplxMultDiv2(&vi, &vr, x[47], x[46], fft32_w32[5]); + ur = x[14]; + ui = x[15]; + x[14] = (ur>>1) + vr; + x[15] = (ui>>1) + vi; + x[46] = (ur>>1) - vr; + x[47] = (ui>>1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[5]); + ur = x[30]; + ui = x[31]; + x[30] = (ur>>1) + vr; + x[31] = (ui>>1) - vi; + x[62] = (ur>>1) - vr; + x[63] = (ui>>1) + vi; +} +#endif /* #ifndef FUNCTION_fft_32 */ + + +/** + * \brief Apply rotation vectors to a data buffer. + * \param cl length of each row of input data. + * \param l total length of input data. + * \param pVecRe real part of rotation ceofficient vector. + * \param pVecIm imaginary part of rotation ceofficient vector. + */ +static inline void fft_apply_rot_vector(FIXP_DBL *RESTRICT pData, const int cl, const int l, const FIXP_STB *pVecRe, const FIXP_STB *pVecIm) +{ + FIXP_DBL re, im; + FIXP_STB vre, vim; + + int i, c; + + for(i=0; i>2; /* * 0.25 */ + pData[2*i+1] = im>>2; /* * 0.25 */ + } + for(; i>2; /* * 0.25 */ + pData[2*i+1] = im>>2; /* * 0.25 */ + + for (c=i+1; c>1; + im = pData[2*c+1]>>1; + vre = *pVecRe++; + vim = *pVecIm++; + + cplxMultDiv2(&pData[2*c+1], &pData[2*c], im, re, vre, vim); + } + } +} + +//FIXME:buggy for fft480 +//#define FFT_TWO_STAGE_MACRO_ENABLE + + +#ifdef FFT_TWO_STAGE_MACRO_ENABLE + +#define fftN2(pInput, length, dim1, dim2, fft_func1, fft_func2, RotVectorReal, RotVectorImag) \ +{ \ + int i, j; \ + \ + C_ALLOC_SCRATCH_START(aDst, FIXP_DBL, length*2); \ + C_ALLOC_SCRATCH_START(aDst2, FIXP_DBL, dim2*2); \ + \ + FDK_ASSERT(length == dim1*dim2); \ + \ + /* Perform dim2 times the fft of length dim1. The input samples are at the address of pSrc and the \ + output samples are at the address of pDst. The input vector for the fft of length dim1 is built \ + of the interleaved samples in pSrc, the output samples are stored consecutively. \ + */ \ + { \ + const FIXP_DBL* pSrc = pInput; \ + FIXP_DBL *RESTRICT pDst = aDst; \ + \ + for(i=0; i>1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6])>>1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3])>>1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7])>>1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + for(ldm=3; ldm<=ldn; ++ldm) + { + INT m=(1<>1); + INT j,r; + + trigstep=((trigDataSize << 2)>>ldm); + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to much precision. + Beware: The impact on the overal FFT precision is rather large. */ + { + j = 0; + + for(r=0; r>1; + vr = x[t2]>>1; + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + //cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = x[t2+1]>>1; + vi = x[t2]>>1; + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui-vi; + + x[t2] = ur-vr; + x[t2+1] = ui+vi; + } + } + for(j=1; j>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui-vi; + + x[t2] = ur-vr; + x[t2+1] = ui+vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + t1 = (r+mh/2-j)<<1; + t2 = t1 + (mh<<1); + + cplxMultDiv2(&vi, &vr, x[t2], x[t2+1], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui-vi; + + x[t2] = ur-vr; + x[t2+1] = ui+vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vr, &vi, x[t2], x[t2+1], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui-vi; + + x[t2] = ur+vr; + x[t2+1] = ui+vi; + } + } + { + j = mh/4; + + for(r=0; r>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], STC(0x5a82799a), STC(0x5a82799a)); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui-vi; + + x[t2] = ur-vr; + x[t2+1] = ui+vi; + } + } + } +} +#endif + + +/***************************************************************************** + + functionname: dit_ifft (synthesis) + description: dit-tukey-algorithm + scrambles data at entry + i.e. loop is made with scrambled data + returns: + input: + output: + +*****************************************************************************/ + +#if !defined(FUNCTION_dit_ifft) +void dit_ifft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, const INT trigDataSize) +{ + const INT n=1<>1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6])>>1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3])>>1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7])>>1; /* Im C + Im D */ + a0 = (x[i + 0] - x[i + 2])>>1; /* Re A - Re B */ + a2 = (x[i + 4] - x[i + 6])>>1; /* Re C - Re D */ + a3 = (x[i + 1] - x[i + 3])>>1; /* Im A - Im B */ + a1 = (x[i + 5] - x[i + 7])>>1; /* Im C - Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + x[i + 2] = a0 - a1; /* Re B' = Re A - Re B - Im C + Im D */ + x[i + 6] = a0 + a1; /* Re D' = Re A - Re B + Im C - Im D */ + x[i + 3] = a3 + a2; /* Im B' = Im A - Im B + Re C - Re D */ + x[i + 7] = a3 - a2; /* Im D' = Im A - Im B - Re C + Re D */ + } + + for(ldm=3; ldm<=ldn; ++ldm) + { + const INT m=(1<>1); + + INT j,r; + + trigstep=((trigDataSize << 2)>>ldm); + + { + j = 0; + + for(r=0; r>1; + vr = x[t2]>>1; + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + //cplxMultDiv2(&vi, &vr, x[t2], x[t2+1], FL2FXCONST_SGL(1.0), FL2FXCONST_SGL(0.0)); + vr = x[t2+1]>>1; + vi = x[t2]>>1; + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui+vi; + + x[t2] = ur+vr; + x[t2+1] = ui-vi; + } + } + for(j=1; j>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vi, &vr, x[t2], x[t2+1], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui+vi; + + x[t2] = ur+vr; + x[t2+1] = ui-vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + t1 = (r+mh/2-j)<<1; + t2 = t1 + (mh<<1); + + cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui+vi; + + x[t2] = ur+vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], cs); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui-vi; + + x[t2] = ur+vr; + x[t2+1] = ui+vi; + } + } + { + j = mh/4; + for(r=0; r>1; + ui = x[t1+1]>>1; + + x[t1] = ur+vr; + x[t1+1] = ui+vi; + + x[t2] = ur-vr; + x[t2+1] = ui-vi; + + t1 += mh; + t2 = t1+(mh<<1); + + cplxMultDiv2(&vi, &vr, x[t2], x[t2+1], STC(0x5a82799a), STC(0x5a82799a)); + + ur = x[t1]>>1; + ui = x[t1+1]>>1; + + x[t1] = ur-vr; + x[t1+1] = ui+vi; + + x[t2] = ur+vr; + x[t2+1] = ui-vi; + } + } + } +} +#endif + diff --git a/libFDK/src/fixpoint_math.cpp b/libFDK/src/fixpoint_math.cpp new file mode 100644 index 00000000..1bf93667 --- /dev/null +++ b/libFDK/src/fixpoint_math.cpp @@ -0,0 +1,895 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): M. Gayer + Description: Fixed point specific mathematical functions + +******************************************************************************/ + +#include "fixpoint_math.h" + + +#define MAX_LD_PRECISION 10 +#define LD_PRECISION 10 + +/* Taylor series coeffcients for ln(1-x), centered at 0 (MacLaurin polinomial). */ +#ifndef LDCOEFF_16BIT +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_DBL(-1.0), + FL2FXCONST_DBL(-1.0/2.0), + FL2FXCONST_DBL(-1.0/3.0), + FL2FXCONST_DBL(-1.0/4.0), + FL2FXCONST_DBL(-1.0/5.0), + FL2FXCONST_DBL(-1.0/6.0), + FL2FXCONST_DBL(-1.0/7.0), + FL2FXCONST_DBL(-1.0/8.0), + FL2FXCONST_DBL(-1.0/9.0), + FL2FXCONST_DBL(-1.0/10.0) +}; +#else +LNK_SECTION_CONSTDATA_L1 +static const FIXP_SGL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_SGL(-1.0), + FL2FXCONST_SGL(-1.0/2.0), + FL2FXCONST_SGL(-1.0/3.0), + FL2FXCONST_SGL(-1.0/4.0), + FL2FXCONST_SGL(-1.0/5.0), + FL2FXCONST_SGL(-1.0/6.0), + FL2FXCONST_SGL(-1.0/7.0), + FL2FXCONST_SGL(-1.0/8.0), + FL2FXCONST_SGL(-1.0/9.0), + FL2FXCONST_SGL(-1.0/10.0) +}; +#endif + +/***************************************************************************** + + functionname: CalcLdData + description: Delivers the Logarithm Dualis ld(op)/LD_DATA_SCALING with polynomial approximation. + input: Input op is assumed to be double precision fractional 0 < op < 1.0 + This function does not accept negative values. + output: For op == 0, the result is saturated to -1.0 + This function does not return positive values since input values are treated as fractional values. + It does not make sense to input an integer value into this function (and expect a positive output value) + since input values are treated as fractional values. + +*****************************************************************************/ + +LNK_SECTION_CODE_L1 +FIXP_DBL CalcLdData(FIXP_DBL op) +{ + return fLog2(op, 0); +} + + +/***************************************************************************** + functionname: LdDataVector +*****************************************************************************/ +LNK_SECTION_CODE_L1 +void LdDataVector( FIXP_DBL *srcVector, + FIXP_DBL *destVector, + INT n) +{ + INT i; + for ( i=0; i>1)) >> (FRACT_BITS-1); /* round */ + LONG high = u * ((v>>FRACT_BITS)<<1); + + prod = (LONG)(high+low); + + return((FIXP_DBL)prod); +} + + +/***************************************************************************** + + functionname: CalcInvLdData + description: Delivers the inverse of function CalcLdData(). + Delivers 2^(op*LD_DATA_SCALING) + input: Input op is assumed to be fractional -1.0 < op < 1.0 + output: For op == 0, the result is MAXVAL_DBL (almost 1.0). + For negative input values the output should be treated as a positive fractional value. + For positive input values the output should be treated as a positive integer value. + This function does not output negative values. + +*****************************************************************************/ +LNK_SECTION_CODE_L1 +/* This table is used for lookup 2^x with */ +/* x in range [0...1.0[ in steps of 1/32 */ +LNK_SECTION_DATA_L1 static const UINT exp2_tab_long[32]={ +0x40000000,0x4166C34C,0x42D561B4,0x444C0740, +0x45CAE0F2,0x47521CC6,0x48E1E9BA,0x4A7A77D4, +0x4C1BF829,0x4DC69CDD,0x4F7A9930,0x51382182, +0x52FF6B55,0x54D0AD5A,0x56AC1F75,0x5891FAC1, +0x5A82799A,0x5C7DD7A4,0x5E8451D0,0x60962665, +0x62B39509,0x64DCDEC3,0x6712460B,0x69540EC9, +0x6BA27E65,0x6DFDDBCC,0x70666F76,0x72DC8374, +0x75606374,0x77F25CCE,0x7A92BE8B,0x7D41D96E +// 0x80000000 +}; + +/* This table is used for lookup 2^x with */ +/* x in range [0...1/32[ in steps of 1/1024 */ +LNK_SECTION_DATA_L1 static const UINT exp2w_tab_long[32]={ +0x40000000,0x400B1818,0x4016321B,0x40214E0C, +0x402C6BE9,0x40378BB4,0x4042AD6D,0x404DD113, +0x4058F6A8,0x40641E2B,0x406F479E,0x407A7300, +0x4085A051,0x4090CF92,0x409C00C4,0x40A733E6, +0x40B268FA,0x40BD9FFF,0x40C8D8F5,0x40D413DD, +0x40DF50B8,0x40EA8F86,0x40F5D046,0x410112FA, +0x410C57A2,0x41179E3D,0x4122E6CD,0x412E3152, +0x41397DCC,0x4144CC3B,0x41501CA0,0x415B6EFB, +// 0x4166C34C, +}; +/* This table is used for lookup 2^x with */ +/* x in range [0...1/1024[ in steps of 1/32768 */ +LNK_SECTION_DATA_L1 static const UINT exp2x_tab_long[32]={ +0x40000000,0x400058B9,0x4000B173,0x40010A2D, +0x400162E8,0x4001BBA3,0x4002145F,0x40026D1B, +0x4002C5D8,0x40031E95,0x40037752,0x4003D011, +0x400428CF,0x4004818E,0x4004DA4E,0x4005330E, +0x40058BCE,0x4005E48F,0x40063D51,0x40069613, +0x4006EED5,0x40074798,0x4007A05B,0x4007F91F, +0x400851E4,0x4008AAA8,0x4009036E,0x40095C33, +0x4009B4FA,0x400A0DC0,0x400A6688,0x400ABF4F, +//0x400B1818 +}; + +LNK_SECTION_CODE_L1 FIXP_DBL CalcInvLdData(FIXP_DBL x) +{ + int set_zero = (x < FL2FXCONST_DBL(-31.0/64.0))? 0 : 1; + int set_max = (x >= FL2FXCONST_DBL( 31.0/64.0)) | (x == FL2FXCONST_DBL(0.0)); + + FIXP_SGL frac = (FIXP_SGL)(LONG)(x & 0x3FF); + UINT index3 = (UINT)(LONG)(x >> 10) & 0x1F; + UINT index2 = (UINT)(LONG)(x >> 15) & 0x1F; + UINT index1 = (UINT)(LONG)(x >> 20) & 0x1F; + int exp = (x > FL2FXCONST_DBL(0.0f)) ? (31 - (int)(x>>25)) : (int)(-(x>>25)); + + UINT lookup1 = exp2_tab_long[index1]*set_zero; + UINT lookup2 = exp2w_tab_long[index2]; + UINT lookup3 = exp2x_tab_long[index3]; + UINT lookup3f = lookup3 + (UINT)(LONG)fMultDiv2((FIXP_DBL)(0x0016302F),(FIXP_SGL)frac); + + UINT lookup12 = (UINT)(LONG)fMult((FIXP_DBL)lookup1, (FIXP_DBL) lookup2); + UINT lookup = (UINT)(LONG)fMult((FIXP_DBL)lookup12, (FIXP_DBL) lookup3f); + + FIXP_DBL retVal = (lookup<<3) >> exp; + + if (set_max) + retVal=FL2FXCONST_DBL(1.0f); + + return retVal; +} + + + + + +/***************************************************************************** + functionname: InitLdInt and CalcLdInt + description: Create and access table with integer LdData (0 to 193) +*****************************************************************************/ + + + LNK_SECTION_CONSTDATA_L1 + static const FIXP_DBL ldIntCoeff[] = { + (FIXP_DBL)0x80000001, (FIXP_DBL)0x00000000, (FIXP_DBL)0x02000000, (FIXP_DBL)0x032b8034, (FIXP_DBL)0x04000000, (FIXP_DBL)0x04a4d3c2, (FIXP_DBL)0x052b8034, (FIXP_DBL)0x059d5da0, + (FIXP_DBL)0x06000000, (FIXP_DBL)0x06570069, (FIXP_DBL)0x06a4d3c2, (FIXP_DBL)0x06eb3a9f, (FIXP_DBL)0x072b8034, (FIXP_DBL)0x0766a009, (FIXP_DBL)0x079d5da0, (FIXP_DBL)0x07d053f7, + (FIXP_DBL)0x08000000, (FIXP_DBL)0x082cc7ee, (FIXP_DBL)0x08570069, (FIXP_DBL)0x087ef05b, (FIXP_DBL)0x08a4d3c2, (FIXP_DBL)0x08c8ddd4, (FIXP_DBL)0x08eb3a9f, (FIXP_DBL)0x090c1050, + (FIXP_DBL)0x092b8034, (FIXP_DBL)0x0949a785, (FIXP_DBL)0x0966a009, (FIXP_DBL)0x0982809d, (FIXP_DBL)0x099d5da0, (FIXP_DBL)0x09b74949, (FIXP_DBL)0x09d053f7, (FIXP_DBL)0x09e88c6b, + (FIXP_DBL)0x0a000000, (FIXP_DBL)0x0a16bad3, (FIXP_DBL)0x0a2cc7ee, (FIXP_DBL)0x0a423162, (FIXP_DBL)0x0a570069, (FIXP_DBL)0x0a6b3d79, (FIXP_DBL)0x0a7ef05b, (FIXP_DBL)0x0a92203d, + (FIXP_DBL)0x0aa4d3c2, (FIXP_DBL)0x0ab7110e, (FIXP_DBL)0x0ac8ddd4, (FIXP_DBL)0x0ada3f60, (FIXP_DBL)0x0aeb3a9f, (FIXP_DBL)0x0afbd42b, (FIXP_DBL)0x0b0c1050, (FIXP_DBL)0x0b1bf312, + (FIXP_DBL)0x0b2b8034, (FIXP_DBL)0x0b3abb40, (FIXP_DBL)0x0b49a785, (FIXP_DBL)0x0b584822, (FIXP_DBL)0x0b66a009, (FIXP_DBL)0x0b74b1fd, (FIXP_DBL)0x0b82809d, (FIXP_DBL)0x0b900e61, + (FIXP_DBL)0x0b9d5da0, (FIXP_DBL)0x0baa708f, (FIXP_DBL)0x0bb74949, (FIXP_DBL)0x0bc3e9ca, (FIXP_DBL)0x0bd053f7, (FIXP_DBL)0x0bdc899b, (FIXP_DBL)0x0be88c6b, (FIXP_DBL)0x0bf45e09, + (FIXP_DBL)0x0c000000, (FIXP_DBL)0x0c0b73cb, (FIXP_DBL)0x0c16bad3, (FIXP_DBL)0x0c21d671, (FIXP_DBL)0x0c2cc7ee, (FIXP_DBL)0x0c379085, (FIXP_DBL)0x0c423162, (FIXP_DBL)0x0c4caba8, + (FIXP_DBL)0x0c570069, (FIXP_DBL)0x0c6130af, (FIXP_DBL)0x0c6b3d79, (FIXP_DBL)0x0c7527b9, (FIXP_DBL)0x0c7ef05b, (FIXP_DBL)0x0c88983f, (FIXP_DBL)0x0c92203d, (FIXP_DBL)0x0c9b8926, + (FIXP_DBL)0x0ca4d3c2, (FIXP_DBL)0x0cae00d2, (FIXP_DBL)0x0cb7110e, (FIXP_DBL)0x0cc0052b, (FIXP_DBL)0x0cc8ddd4, (FIXP_DBL)0x0cd19bb0, (FIXP_DBL)0x0cda3f60, (FIXP_DBL)0x0ce2c97d, + (FIXP_DBL)0x0ceb3a9f, (FIXP_DBL)0x0cf39355, (FIXP_DBL)0x0cfbd42b, (FIXP_DBL)0x0d03fda9, (FIXP_DBL)0x0d0c1050, (FIXP_DBL)0x0d140ca0, (FIXP_DBL)0x0d1bf312, (FIXP_DBL)0x0d23c41d, + (FIXP_DBL)0x0d2b8034, (FIXP_DBL)0x0d3327c7, (FIXP_DBL)0x0d3abb40, (FIXP_DBL)0x0d423b08, (FIXP_DBL)0x0d49a785, (FIXP_DBL)0x0d510118, (FIXP_DBL)0x0d584822, (FIXP_DBL)0x0d5f7cff, + (FIXP_DBL)0x0d66a009, (FIXP_DBL)0x0d6db197, (FIXP_DBL)0x0d74b1fd, (FIXP_DBL)0x0d7ba190, (FIXP_DBL)0x0d82809d, (FIXP_DBL)0x0d894f75, (FIXP_DBL)0x0d900e61, (FIXP_DBL)0x0d96bdad, + (FIXP_DBL)0x0d9d5da0, (FIXP_DBL)0x0da3ee7f, (FIXP_DBL)0x0daa708f, (FIXP_DBL)0x0db0e412, (FIXP_DBL)0x0db74949, (FIXP_DBL)0x0dbda072, (FIXP_DBL)0x0dc3e9ca, (FIXP_DBL)0x0dca258e, + (FIXP_DBL)0x0dd053f7, (FIXP_DBL)0x0dd6753e, (FIXP_DBL)0x0ddc899b, (FIXP_DBL)0x0de29143, (FIXP_DBL)0x0de88c6b, (FIXP_DBL)0x0dee7b47, (FIXP_DBL)0x0df45e09, (FIXP_DBL)0x0dfa34e1, + (FIXP_DBL)0x0e000000, (FIXP_DBL)0x0e05bf94, (FIXP_DBL)0x0e0b73cb, (FIXP_DBL)0x0e111cd2, (FIXP_DBL)0x0e16bad3, (FIXP_DBL)0x0e1c4dfb, (FIXP_DBL)0x0e21d671, (FIXP_DBL)0x0e275460, + (FIXP_DBL)0x0e2cc7ee, (FIXP_DBL)0x0e323143, (FIXP_DBL)0x0e379085, (FIXP_DBL)0x0e3ce5d8, (FIXP_DBL)0x0e423162, (FIXP_DBL)0x0e477346, (FIXP_DBL)0x0e4caba8, (FIXP_DBL)0x0e51daa8, + (FIXP_DBL)0x0e570069, (FIXP_DBL)0x0e5c1d0b, (FIXP_DBL)0x0e6130af, (FIXP_DBL)0x0e663b74, (FIXP_DBL)0x0e6b3d79, (FIXP_DBL)0x0e7036db, (FIXP_DBL)0x0e7527b9, (FIXP_DBL)0x0e7a1030, + (FIXP_DBL)0x0e7ef05b, (FIXP_DBL)0x0e83c857, (FIXP_DBL)0x0e88983f, (FIXP_DBL)0x0e8d602e, (FIXP_DBL)0x0e92203d, (FIXP_DBL)0x0e96d888, (FIXP_DBL)0x0e9b8926, (FIXP_DBL)0x0ea03232, + (FIXP_DBL)0x0ea4d3c2, (FIXP_DBL)0x0ea96df0, (FIXP_DBL)0x0eae00d2, (FIXP_DBL)0x0eb28c7f, (FIXP_DBL)0x0eb7110e, (FIXP_DBL)0x0ebb8e96, (FIXP_DBL)0x0ec0052b, (FIXP_DBL)0x0ec474e4, + (FIXP_DBL)0x0ec8ddd4, (FIXP_DBL)0x0ecd4012, (FIXP_DBL)0x0ed19bb0, (FIXP_DBL)0x0ed5f0c4, (FIXP_DBL)0x0eda3f60, (FIXP_DBL)0x0ede8797, (FIXP_DBL)0x0ee2c97d, (FIXP_DBL)0x0ee70525, + (FIXP_DBL)0x0eeb3a9f, (FIXP_DBL)0x0eef69ff, (FIXP_DBL)0x0ef39355, (FIXP_DBL)0x0ef7b6b4, (FIXP_DBL)0x0efbd42b, (FIXP_DBL)0x0effebcd, (FIXP_DBL)0x0f03fda9, (FIXP_DBL)0x0f0809cf, + (FIXP_DBL)0x0f0c1050, (FIXP_DBL)0x0f10113b, (FIXP_DBL)0x0f140ca0, (FIXP_DBL)0x0f18028d, (FIXP_DBL)0x0f1bf312, (FIXP_DBL)0x0f1fde3d, (FIXP_DBL)0x0f23c41d, (FIXP_DBL)0x0f27a4c0, + (FIXP_DBL)0x0f2b8034 + }; + + + LNK_SECTION_INITCODE + void InitLdInt() + { + /* nothing to do! Use preinitialized logarithm table */ + } + + + +LNK_SECTION_CODE_L1 +FIXP_DBL CalcLdInt(INT i) +{ + /* calculates ld(op)/LD_DATA_SCALING */ + /* op is assumed to be an integer value between 1 and 193 */ + + FDK_ASSERT((193>0) && ((FIXP_DBL)ldIntCoeff[0]==(FIXP_DBL)0x80000001)); /* tab has to be initialized */ + + if ((i>0)&&(i<193)) + return ldIntCoeff[i]; + else + { + return (0); + } +} + + +/***************************************************************************** + + functionname: invSqrtNorm2 + description: delivers 1/sqrt(op) normalized to .5...1 and the shift value of the OUTPUT + +*****************************************************************************/ +#define SQRT_BITS 7 +#define SQRT_VALUES 128 +#define SQRT_BITS_MASK 0x7f + +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL invSqrtTab[SQRT_VALUES] = { + 0x5a827999, 0x5a287e03, 0x59cf8cbb, 0x5977a0ab, 0x5920b4de, 0x58cac480, 0x5875cade, 0x5821c364, + 0x57cea99c, 0x577c792f, 0x572b2ddf, 0x56dac38d, 0x568b3631, 0x563c81df, 0x55eea2c3, 0x55a19521, + 0x55555555, 0x5509dfd0, 0x54bf311a, 0x547545d0, 0x542c1aa3, 0x53e3ac5a, 0x539bf7cc, 0x5354f9e6, + 0x530eafa4, 0x52c91617, 0x52842a5e, 0x523fe9ab, 0x51fc513f, 0x51b95e6b, 0x51770e8e, 0x51355f19, + 0x50f44d88, 0x50b3d768, 0x5073fa4f, 0x5034b3e6, 0x4ff601df, 0x4fb7e1f9, 0x4f7a5201, 0x4f3d4fce, + 0x4f00d943, 0x4ec4ec4e, 0x4e8986e9, 0x4e4ea718, 0x4e144ae8, 0x4dda7072, 0x4da115d9, 0x4d683948, + 0x4d2fd8f4, 0x4cf7f31b, 0x4cc08604, 0x4c898fff, 0x4c530f64, 0x4c1d0293, 0x4be767f5, 0x4bb23df9, + 0x4b7d8317, 0x4b4935ce, 0x4b1554a6, 0x4ae1de2a, 0x4aaed0f0, 0x4a7c2b92, 0x4a49ecb3, 0x4a1812fa, + 0x49e69d16, 0x49b589bb, 0x4984d7a4, 0x49548591, 0x49249249, 0x48f4fc96, 0x48c5c34a, 0x4896e53c, + 0x48686147, 0x483a364c, 0x480c6331, 0x47dee6e0, 0x47b1c049, 0x4784ee5f, 0x4758701c, 0x472c447c, + 0x47006a80, 0x46d4e130, 0x46a9a793, 0x467ebcb9, 0x46541fb3, 0x4629cf98, 0x45ffcb80, 0x45d61289, + 0x45aca3d5, 0x45837e88, 0x455aa1ca, 0x45320cc8, 0x4509beb0, 0x44e1b6b4, 0x44b9f40b, 0x449275ec, + 0x446b3b95, 0x44444444, 0x441d8f3b, 0x43f71bbe, 0x43d0e917, 0x43aaf68e, 0x43854373, 0x435fcf14, + 0x433a98c5, 0x43159fdb, 0x42f0e3ae, 0x42cc6397, 0x42a81ef5, 0x42841527, 0x4260458d, 0x423caf8c, + 0x4219528b, 0x41f62df1, 0x41d3412a, 0x41b08ba1, 0x418e0cc7, 0x416bc40d, 0x4149b0e4, 0x4127d2c3, + 0x41062920, 0x40e4b374, 0x40c3713a, 0x40a261ef, 0x40818511, 0x4060da21, 0x404060a1, 0x40201814 +}; + +LNK_SECTION_INITCODE +void InitInvSqrtTab() +{ + /* nothing to do ! + use preinitialized square root table + */ +} + + + +#if !defined(FUNCTION_invSqrtNorm2) +/***************************************************************************** + delivers 1/sqrt(op) normalized to .5...1 and the shift value of the OUTPUT, + i.e. the denormalized result is 1/sqrt(op) = invSqrtNorm(op) * 2^(shift) + uses Newton-iteration for approximation + Q(n+1) = Q(n) + Q(n) * (0.5 - 2 * V * Q(n)^2) + with Q = 0.5* V ^-0.5; 0.5 <= V < 1.0 +*****************************************************************************/ +FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift) +{ + + FIXP_DBL val = op ; + FIXP_DBL reg1, reg2, regtmp ; + + if (val == FL2FXCONST_DBL(0.0)) { + *shift = 1 ; + return((LONG)1); /* minimum positive value */ + } + + + /* normalize input, calculate shift value */ + FDK_ASSERT(val > FL2FXCONST_DBL(0.0)); + *shift = fNormz(val) - 1; /* CountLeadingBits() is not necessary here since test value is always > 0 */ + val <<=*shift ; /* normalized input V */ + *shift+=2 ; /* bias for exponent */ + + /* Newton iteration of 1/sqrt(V) */ + reg1 = invSqrtTab[ (INT)(val>>(DFRACT_BITS-1-(SQRT_BITS+1))) & SQRT_BITS_MASK ]; + reg2 = FL2FXCONST_DBL(0.0625f); /* 0.5 >> 3 */ + + regtmp= fPow2Div2(reg1); /* a = Q^2 */ + regtmp= reg2 - fMultDiv2(regtmp, val); /* b = 0.5 - 2 * V * Q^2 */ + reg1 += (fMultDiv2(regtmp, reg1)<<4); /* Q = Q + Q*b */ + + /* calculate the output exponent = input exp/2 */ + if (*shift & 0x00000001) { /* odd shift values ? */ + reg2 = FL2FXCONST_DBL(0.707106781186547524400844362104849f); /* 1/sqrt(2); */ + reg1 = fMultDiv2(reg1, reg2) << 2; + } + + *shift = *shift>>1; + + return(reg1); +} +#endif /* !defined(FUNCTION_invSqrtNorm2) */ + +/***************************************************************************** + + functionname: sqrtFixp + description: delivers sqrt(op) + +*****************************************************************************/ +FIXP_DBL sqrtFixp(FIXP_DBL op) +{ + INT tmp_exp = 0; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp); + + FDK_ASSERT(tmp_exp > 0) ; + return( (FIXP_DBL) ( fMultDiv2( (op<<(tmp_exp-1)), tmp_inv ) << 2 )); +} + + +#if !defined(FUNCTION_schur_div) +/***************************************************************************** + + functionname: schur_div + description: delivers op1/op2 with op3-bit accuracy + +*****************************************************************************/ + + +FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) +{ + INT L_num = (LONG)num>>1; + INT L_denum = (LONG)denum>>1; + INT div = 0; + INT k = count; + + FDK_ASSERT (num>=(FIXP_DBL)0); + FDK_ASSERT (denum>(FIXP_DBL)0); + FDK_ASSERT (num <= denum); + + if (L_num != 0) + while (--k) + { + div <<= 1; + L_num <<= 1; + if (L_num >= L_denum) + { + L_num -= L_denum; + div++; + } + } + return (FIXP_DBL)(div << (DFRACT_BITS - count)); +} + + +#endif /* !defined(FUNCTION_schur_div) */ + + +#ifndef FUNCTION_fMultNorm +FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e) +{ + INT product = 0; + INT norm_f1, norm_f2; + + if ( (f1 == (FIXP_DBL)0) || (f2 == (FIXP_DBL)0) ) { + *result_e = 0; + return (FIXP_DBL)0; + } + norm_f1 = CountLeadingBits(f1); + f1 = f1 << norm_f1; + norm_f2 = CountLeadingBits(f2); + f2 = f2 << norm_f2; + + product = fMult(f1, f2); + *result_e = - (norm_f1 + norm_f2); + + return (FIXP_DBL)product; +} +#endif + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e) +{ + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT (L_num >= (FIXP_DBL)0); + FDK_ASSERT (L_denum > (FIXP_DBL)0); + + if(L_num == (FIXP_DBL)0) + { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(L_num); + L_num = L_num << norm_num; + L_num = L_num >> 1; + *result_e = - norm_num + 1; + + norm_den = CountLeadingBits(L_denum); + L_denum = L_denum << norm_den; + *result_e -= - norm_den; + + div = schur_div(L_num, L_denum, FRACT_BITS); + + return div; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom) +{ + INT e; + FIXP_DBL res; + + FDK_ASSERT (denom >= num); + + res = fDivNorm(num, denom, &e); + + /* Avoid overflow since we must output a value with exponent 0 + there is no other choice than saturating to almost 1.0f */ + if(res == (FIXP_DBL)(1<<(DFRACT_BITS-2)) && e == 1) + { + res = (FIXP_DBL)MAXVAL_DBL; + } + else + { + res = scaleValue(res, e); + } + + return res; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNormHighPrec +FIXP_DBL fDivNormHighPrec(FIXP_DBL num, FIXP_DBL denom, INT *result_e) +{ + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT (num >= (FIXP_DBL)0); + FDK_ASSERT (denom > (FIXP_DBL)0); + + if(num == (FIXP_DBL)0) + { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(num); + num = num << norm_num; + num = num >> 1; + *result_e = - norm_num + 1; + + norm_den = CountLeadingBits(denom); + denom = denom << norm_den; + *result_e -= - norm_den; + + div = schur_div(num, denom, 31); + return div; +} +#endif /* !FUNCTION_fDivNormHighPrec */ + + + +FIXP_DBL CalcLog2(FIXP_DBL base_m, INT base_e, INT *result_e) +{ + return fLog2(base_m, base_e, result_e); +} + +FIXP_DBL f2Pow( + const FIXP_DBL exp_m, const INT exp_e, + INT *result_e + ) +{ + FIXP_DBL frac_part, result_m; + INT int_part; + + if (exp_e > 0) + { + INT exp_bits = DFRACT_BITS-1 - exp_e; + int_part = exp_m >> exp_bits; + frac_part = exp_m - (FIXP_DBL)(int_part << exp_bits); + frac_part = frac_part << exp_e; + } + else + { + int_part = 0; + frac_part = exp_m >> -exp_e; + } + + /* Best accuracy is around 0, so try to get there with the fractional part. */ + if( frac_part > FL2FXCONST_DBL(0.5f) ) + { + int_part = int_part + 1; + frac_part = frac_part + FL2FXCONST_DBL(-1.0f); + } + if( frac_part < FL2FXCONST_DBL(-0.5f) ) + { + int_part = int_part - 1; + frac_part = -(FL2FXCONST_DBL(-1.0f) - frac_part); + } + + /* Evaluate taylor polynomial which approximates 2^x */ + { + FIXP_DBL p; + + /* result_m ~= 2^frac_part */ + p = frac_part; + /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to fMultDiv2(). */ + result_m = FL2FXCONST_DBL(1.0f/2.0f); + for (INT i = 0; i < POW2_PRECISION; i++) { + /* next taylor series term: a_i * x^i, x=0 */ + result_m = fMultAddDiv2(result_m, pow2Coeff[i], p); + p = fMult(p, frac_part); + } + } + + /* "+ 1" compensates fMultAddDiv2() of the polynomial evaluation above. */ + *result_e = int_part + 1; + + return result_m; +} + +FIXP_DBL f2Pow( + const FIXP_DBL exp_m, const INT exp_e + ) +{ + FIXP_DBL result_m; + INT result_e; + + result_m = f2Pow(exp_m, exp_e, &result_e); + result_e = fixMin(DFRACT_BITS-1,fixMax(-(DFRACT_BITS-1),result_e)); + + return scaleValue(result_m, result_e); +} + +FIXP_DBL fPow( + FIXP_DBL base_m, INT base_e, + FIXP_DBL exp_m, INT exp_e, + INT *result_e + ) +{ + INT ans_lg2_e, baselg2_e; + FIXP_DBL base_lg2, ans_lg2, result; + + /* Calc log2 of base */ + base_lg2 = fLog2(base_m, base_e, &baselg2_e); + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(base_lg2, exp_m); + ans_lg2_e = exp_e + baselg2_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow( + FIXP_DBL baseLd_m, + INT baseLd_e, + FIXP_DBL exp_m, INT exp_e, + INT *result_e + ) +{ + INT ans_lg2_e; + FIXP_DBL ans_lg2, result; + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(baseLd_m, exp_m); + ans_lg2_e = exp_e + baseLd_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow( + FIXP_DBL baseLd_m, INT baseLd_e, + FIXP_DBL exp_m, INT exp_e + ) +{ + FIXP_DBL result_m; + int result_e; + + result_m = fLdPow(baseLd_m, baseLd_e, exp_m, exp_e, &result_e); + + return SATURATE_SHIFT(result_m, -result_e, DFRACT_BITS); +} + +FIXP_DBL fPowInt( + FIXP_DBL base_m, INT base_e, + INT exp, + INT *pResult_e + ) +{ + FIXP_DBL result; + + if (exp != 0) { + INT result_e = 0; + + if (base_m != (FIXP_DBL)0) { + { + INT leadingBits; + leadingBits = CountLeadingBits( base_m ); + base_m <<= leadingBits; + base_e -= leadingBits; + } + + result = base_m; + + { + int i; + for (i = 1; i < fAbs(exp); i++) { + result = fMult(result, base_m); + } + } + + if (exp < 0) { + /* 1.0 / ans */ + result = fDivNorm( FL2FXCONST_DBL(0.5f), result, &result_e ); + result_e++; + } else { + int ansScale = CountLeadingBits( result ); + result <<= ansScale; + result_e -= ansScale; + } + + result_e += exp * base_e; + + } else { + result = (FIXP_DBL)0; + } + *pResult_e = result_e; + } + else { + result = FL2FXCONST_DBL(0.5f); + *pResult_e = 1; + } + + return result; +} + +FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e) +{ + FIXP_DBL result_m; + + /* Short cut for zero and negative numbers. */ + if ( x_m <= FL2FXCONST_DBL(0.0f) ) { + *result_e = DFRACT_BITS-1; + return FL2FXCONST_DBL(-1.0f); + } + + /* Calculate log2() */ + { + FIXP_DBL px2_m, x2_m; + + /* Move input value x_m * 2^x_e toward 1.0, where the taylor approximation + of the function log(1-x) centered at 0 is most accurate. */ + { + INT b_norm; + + b_norm = fNormz(x_m)-1; + x2_m = x_m << b_norm; + x_e = x_e - b_norm; + } + + /* map x from log(x) domain to log(1-x) domain. */ + x2_m = - (x2_m + FL2FXCONST_DBL(-1.0) ); + + /* Taylor polinomial approximation of ln(1-x) */ + result_m = FL2FXCONST_DBL(0.0); + px2_m = x2_m; + for (int i=0; i> (enorm-1)) + ((FIXP_DBL)x_e << (DFRACT_BITS-1-enorm)); + + *result_e = enorm; + } else { + /* 1 compensates the fMultDiv2() above in the taylor polinomial evaluation loop.*/ + *result_e = 1; + } + } + + return result_m; +} + +FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e) +{ + if ( x_m <= FL2FXCONST_DBL(0.0f) ) { + x_m = FL2FXCONST_DBL(-1.0f); + } + else { + INT result_e; + x_m = fLog2(x_m, x_e, &result_e); + x_m = scaleValue(x_m, result_e-LD_DATA_SHIFT); + } + return x_m; +} + + + + diff --git a/libFDK/src/mdct.cpp b/libFDK/src/mdct.cpp new file mode 100644 index 00000000..9347a160 --- /dev/null +++ b/libFDK/src/mdct.cpp @@ -0,0 +1,388 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): Josef Hoepfl, Manuel Jander + Description: MDCT routines + +******************************************************************************/ + +#include "mdct.h" + + +#include "FDK_tools_rom.h" +#include "dct.h" +#include "fixpoint_math.h" + + +void mdct_init( H_MDCT hMdct, + FIXP_DBL *overlap, + INT overlapBufferSize ) +{ + hMdct->overlap.freq = overlap; + //FDKmemclear(overlap, overlapBufferSize*sizeof(FIXP_DBL)); + hMdct->prev_fr = 0; + hMdct->prev_nr = 0; + hMdct->prev_tl = 0; + hMdct->ov_size = overlapBufferSize; +} + + +void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) +{ + FIXP_DBL gain_m = *pGain_m; + int gain_e = *pGain_e; + int log2_tl; + + log2_tl = DFRACT_BITS-1-fNormz((FIXP_DBL)tl); + + gain_e += -MDCT_OUTPUT_GAIN - log2_tl - MDCT_OUT_HEADROOM + 1; + + FDK_ASSERT(log2_tl - 2 >= 0); + FDK_ASSERT(log2_tl - 2 < 8*sizeof(int)); + + /* Detect non-radix 2 transform length and add amplitude compensation factor + which cannot be included into the exponent above */ + switch ( (tl) >> (log2_tl - 2) ) { + case 0x7: /* 10 ms, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 0.53333333333333333333) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(0.53333333333333333333f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); + } + break; + case 0x6: /* 3/4 of radix 2, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 2.0/3.0) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(2.0/3.0f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(2.0/3.0f)); + } + break; + case 0x4: + /* radix 2, nothing to do. */ + break; + default: + /* unsupported */ + FDK_ASSERT(0); + break; + } + + *pGain_m = gain_m; + *pGain_e = gain_e; +} + +INT imdct_drain( + H_MDCT hMdct, + FIXP_DBL *output, + INT nrSamplesRoom + ) +{ + int buffered_samples = 0; + + if (nrSamplesRoom > 0) { + buffered_samples = hMdct->ov_offset; + + FDK_ASSERT(buffered_samples <= nrSamplesRoom); + + if (buffered_samples > 0) { + FDKmemcpy(output, hMdct->overlap.time, buffered_samples*sizeof(FIXP_DBL)); + hMdct->ov_offset = 0; + } + } + return buffered_samples; +} + +INT imdct_copy_ov_and_nr( + H_MDCT hMdct, + FIXP_DBL * pTimeData, + INT nrSamples + ) +{ + FIXP_DBL *pOvl; + int nt, nf, i; + + nt = fMin(hMdct->ov_offset, nrSamples); + nrSamples -= nt; + nf = fMin(hMdct->prev_nr, nrSamples); + nrSamples -= nf; + FDKmemcpy(pTimeData, hMdct->overlap.time, nt*sizeof(FIXP_DBL)); + pTimeData += nt; + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + for (i=0; iprev_tl == 0) { + hMdct->prev_wrs = wls; + hMdct->prev_fr = fl; + hMdct->prev_nr = (noOutSamples-fl)>>1; + hMdct->prev_tl = noOutSamples; + hMdct->ov_offset = 0; + use_current = 1; + } + + window_diff = (hMdct->prev_fr - fl)>>1; + + /* check if the previous window slope can be adjusted to match the current window slope */ + if (hMdct->prev_nr + window_diff > 0) { + use_current = 1; + } + /* check if the current window slope can be adjusted to match the previous window slope */ + if (nl - window_diff > 0 ) { + use_previous = 1; + } + + /* if both is possible choose the larger of both window slope lengths */ + if (use_current && use_previous) { + if (fl < hMdct->prev_fr) { + use_current = 0; + } else { + use_previous = 0; + } + } + /* + * If the previous transform block is big enough, enlarge previous window overlap, + * if not, then shrink current window overlap. + */ + if (use_current) { + hMdct->prev_nr += window_diff; + hMdct->prev_fr = fl; + hMdct->prev_wrs = wls; + } else { + nl -= window_diff; + fl = hMdct->prev_fr; + } + + *pfl = fl; + *pnl = nl; +} + +INT imdct_block( + H_MDCT hMdct, + FIXP_DBL *output, + FIXP_DBL *spectrum, + const SHORT scalefactor[], + const INT nSpec, + const INT noOutSamples, + const INT tl, + const FIXP_WTP *wls, + INT fl, + const FIXP_WTP *wrs, + const INT fr, + FIXP_DBL gain + ) +{ + FIXP_DBL *pOvl; + FIXP_DBL *pOut0 = output, *pOut1; + INT nl, nr; + int w, i, nrSamples = 0, specShiftScale, transform_gain_e = 0; + + /* Derive NR and NL */ + nr = (tl - fr)>>1; + nl = (tl - fl)>>1; + + /* Include 2/N IMDCT gain into gain factor and exponent. */ + imdct_gain(&gain, &transform_gain_e, tl); + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr != fl) { + imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples); + } + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + + if ( noOutSamples > nrSamples ) { + /* Purge buffered output. */ + for (i=0; iov_offset; i++) { + *pOut0 = hMdct->overlap.time[i]; + pOut0 ++; + } + nrSamples = hMdct->ov_offset; + hMdct->ov_offset = 0; + } + + for (w=0; wprev_wrs; + + /* Current spectrum */ + pSpec = spectrum+w*tl; + + /* DCT IV of current spectrum. */ + dct_IV(pSpec, tl, &specShiftScale); + + /* Optional scaling of time domain - no yet windowed - of current spectrum */ + /* and de-scale current spectrum signal (time domain, no yet windowed) */ + if (gain != (FIXP_DBL)0) { + scaleValuesWithFactor(pSpec, gain, tl, scalefactor[w] + specShiftScale); + } else { + scaleValues(pSpec, tl, scalefactor[w] + specShiftScale); + } + + if ( noOutSamples <= nrSamples ) { + /* Divert output first half to overlap buffer if we already got enough output samples. */ + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl/2; + } else { + /* Account output samples */ + nrSamples += hMdct->prev_nr + fl/2; + } + + /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ + for (i=0; iprev_nr; i++) { + FIXP_DBL x = - (*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0 ++; + } + + if ( noOutSamples <= nrSamples ) { + /* Divert output second half to overlap buffer if we already got enough output samples. */ + pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl/2 - 1; + hMdct->ov_offset += fl/2 + nl; + } else { + pOut1 = pOut0 + (fl - 1); + nrSamples += fl/2 + nl; + } + + /* output samples before window crossing point NR .. TL/2. -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ + /* output samples after window crossing point TL/2 .. TL/2+FL/2. -overlap[0..FL/2] - current[TL/2..FL/2] */ + pCurr = pSpec + tl - fl/2; + for (i=0; iprev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + hMdct->prev_wrs = wrs; + } + + /* Save overlap */ + + pOvl = hMdct->overlap.freq + hMdct->ov_size - tl/2; + FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset); + FDK_ASSERT(tl/2 <= hMdct->ov_size); + for (i=0; iAbout polyphase filtering + The polyphase implementation of a filterbank requires filtering at the input and output. + This is implemented as part of cplxAnalysisQmfFiltering() and cplxSynthesisQmfFiltering(). + The implementation requires the filter coefficients in a specific structure as described in + #sbr_qmf_64_640_qmf (in sbr_rom.cpp). + + This module comprises the computationally most expensive functions of the SBR decoder. The accuracy of + computations is also important and has a direct impact on the overall sound quality. Therefore a special + test program is available which can be used to only test the filterbank: main_audio.cpp + + This modules also uses scaling of data to provide better SNR on fixed-point processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. + An interesting note: The function getScalefactor() can constitute a significant amount of computational complexity - very much depending on the + bitrate. Since it is a rather small function, effective assembler optimization might be possible. + +*/ + +#include "qmf.h" + + +#include "fixpoint_math.h" +#include "dct.h" + +#ifdef QMFSYN_STATES_16BIT +#define QSSCALE (7) +#define FX_DBL2FX_QSS(x) ((FIXP_QSS) ((x)>>(DFRACT_BITS-QSS_BITS-QSSCALE) )) +#define FX_QSS2FX_DBL(x) ((FIXP_DBL)((LONG)x)<<(DFRACT_BITS-QSS_BITS-QSSCALE)) +#else +#define QSSCALE (0) +#define FX_DBL2FX_QSS(x) (x) +#define FX_QSS2FX_DBL(x) (x) +#endif + + +#if defined(__arm__) +#include "arm/qmf_arm.cpp" + +#endif + +/*! + * \brief Algorithmic scaling in sbrForwardModulation() + * + * The scaling in sbrForwardModulation() is caused by: + * + * \li 1 R_SHIFT in sbrForwardModulation() + * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands + * \li 1 ommited gain of 2.0 in qmfForwardModulation() + */ +#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7 + +/*! + * \brief Algorithmic scaling in cplxSynthesisQmfFiltering() + * + * The scaling in cplxSynthesisQmfFiltering() is caused by: + * + * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands + * \li 1 ommited gain of 2.0 in qmfInverseModulation() + * \li -6 division by 64 in synthesis filterbank + * \li x bits external influence + */ +#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1 + + +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +static +#ifndef FUNCTION_qmfSynPrototypeFirSlot +void qmfSynPrototypeFirSlot( +#else +void qmfSynPrototypeFirSlot_fallback( +#endif + HANDLE_QMF_FILTER_BANK qmf, + FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *RESTRICT timeOut, /*!< Time domain data */ + int stride + ) +{ + FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); + + p_flt = p_Filter+p_stride*QMF_NO_POLY; /* 5-ter von 330 */ + p_fltm = p_Filter+(qmf->FilterSize/2)-p_stride*QMF_NO_POLY; /* 5 + (320 - 2*5) = 315-ter von 330 */ + + FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); + + for (j = no_channels-1; j >= 0; j--) { /* ---- läuft ueber alle Linien eines Slots ---- */ + FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0 + FIXP_QMF real = realSlot[j]; // ~~"~~ + { + INT_PCM tmp; + FIXP_DBL Are = FX_QSS2FX_DBL(sta[0]) + fMultDiv2( p_fltm[0] , real); + + if (qmf->outGain!=(FIXP_DBL)0x80000000) { + Are = fMult(Are,qmf->outGain); + } + + #if SAMPLE_BITS > 16 + tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); + #else + tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); + #endif + if (Are < (FIXP_QMF)0) { + tmp = -tmp; + } + timeOut[ (j)*stride ] = tmp; + } + + sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag )); + sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real )); + sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag )); + sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real )); + sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag )); + sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real )); + sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag )); + sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real )); + sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag )); + + p_flt += (p_stride*QMF_NO_POLY); + p_fltm -= (p_stride*QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } +} + +#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +static +void qmfSynPrototypeFirSlot_NonSymmetric( + HANDLE_QMF_FILTER_BANK qmf, + FIXP_QMF *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_QMF *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *RESTRICT timeOut, /*!< Time domain data */ + int stride + ) +{ + FIXP_QSS* FilterStates = (FIXP_QSS*)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = ((DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor); + + p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */ + p_fltm = &p_flt[qmf->FilterSize/2]; /* at index 320, overall 640 coefficients */ + + FDK_ASSERT(SAMPLE_BITS-1-qmf->outScalefactor >= 0); // (DFRACT_BITS-SAMPLE_BITS)-1-qmf->outScalefactor >= 0); + + for (j = no_channels-1; j >= 0; j--) { /* ---- läuft ueber alle Linien eines Slots ---- */ + + FIXP_QMF imag = imagSlot[j]; // no_channels-1 .. 0 + FIXP_QMF real = realSlot[j]; // ~~"~~ + { + INT_PCM tmp; + FIXP_QMF Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[4] , real )); + + #if SAMPLE_BITS > 16 + tmp = (INT_PCM)(SATURATE_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); + #else + tmp = (INT_PCM)(SATURATE_RIGHT_SHIFT(fAbs(Are), scale, SAMPLE_BITS)); + #endif + if (Are < (FIXP_QMF)0) { + tmp = -tmp; + } + timeOut[j*stride] = tmp; + } + + sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2( p_flt [4] , imag )); + sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[3] , real )); + sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2( p_flt [3] , imag )); + + sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[2] , real )); + sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2( p_flt [2] , imag )); + sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[1] , real )); + sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2( p_flt [1] , imag )); + + sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2( p_fltm[0] , real )); + sta[8] = FX_DBL2FX_QSS(fMultDiv2( p_flt [0] , imag )); + + p_flt += (p_stride*QMF_NO_POLY); + p_fltm += (p_stride*QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } + +} +#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */ + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static +void qmfAnaPrototypeFirSlot( FIXP_QMF *analysisBuffer, + int no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, + int p_stride, /*!< Stide of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates + ) +{ + int k; + + FIXP_DBL accu; + const FIXP_PFT *RESTRICT p_flt = p_filter; + FIXP_QMF *RESTRICT pData_0 = analysisBuffer + 2*no_channels - 1; + FIXP_QMF *RESTRICT pData_1 = analysisBuffer; + + FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; + FIXP_QAS *RESTRICT sta_1 = (FIXP_QAS *)pFilterStates + (2*QMF_NO_POLY*no_channels) - 1; + int pfltStep = QMF_NO_POLY * (p_stride); + int staStep1 = no_channels<<1; + int staStep2 = (no_channels<<3) - 1; /* Rewind one less */ + + /* FIR filter 0 */ + accu = fMultDiv2( p_flt[0], *sta_1); sta_1 -= staStep1; + accu += fMultDiv2( p_flt[1], *sta_1); sta_1 -= staStep1; + accu += fMultDiv2( p_flt[2], *sta_1); sta_1 -= staStep1; + accu += fMultDiv2( p_flt[3], *sta_1); sta_1 -= staStep1; + accu += fMultDiv2( p_flt[4], *sta_1); + *pData_1++ = FX_DBL2FX_QMF(accu<<1); + sta_1 += staStep2; + + p_flt += pfltStep; + + /* FIR filters 1..63 127..65 */ + for (k=0; kno_channels; + int M = L>>1; + int scale; + FIXP_QMF accu; + + const FIXP_QMF *timeInTmp1 = (FIXP_QMF *) &timeIn[3 * M]; + const FIXP_QMF *timeInTmp2 = timeInTmp1; + FIXP_QMF *rSubbandTmp = rSubband; + + rSubband[0] = timeIn[3 * M] >> 1; + + for (i = M-1; i != 0; i--) { + accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); + *++rSubbandTmp = accu; + } + + timeInTmp1 = &timeIn[2 * M]; + timeInTmp2 = &timeIn[0]; + rSubbandTmp = &rSubband[M]; + + for (i = L-M; i != 0; i--) { + accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); + *rSubbandTmp++ = accu; + } + + dct_III(rSubband, timeIn, L, &scale); +} + +#if !defined(FUNCTION_qmfForwardModulationLP_odd) +static void +qmfForwardModulationLP_odd( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_QMF *timeIn, /*!< Time Signal */ + FIXP_QMF *rSubband ) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L>>1; + int shift = (anaQmf->no_channels>>6) + 1; + + for (i = 0; i < M; i++) { + rSubband[M + i] = (timeIn[L - 1 - i]>>1) - (timeIn[i]>>shift); + rSubband[M - 1 - i] = (timeIn[L + i]>>1) + (timeIn[2 * L - 1 - i]>>shift); + } + + dct_IV(rSubband, L, &shift); +} +#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ + + + +/*! + * + * \brief Perform complex-valued forward modulation of the time domain + * data of timeIn and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * Only the lower bands are obtained (upto anaQmf->lsb). For + * a full bandwidth analysis it is required to set both anaQmf->lsb + * and anaQmf->usb to the amount of QMF bands. + * + */ +static void +qmfForwardModulationHQ( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_QMF *RESTRICT timeIn, /*!< Time Signal */ + FIXP_QMF *RESTRICT rSubband, /*!< Real Output */ + FIXP_QMF *RESTRICT iSubband /*!< Imaginary Output */ + ) +{ + int i; + int L = anaQmf->no_channels; + int L2 = L<<1; + int shift = 0; + + for (i = 0; i < L; i+=2) { + FIXP_QMF x0, x1, y0, y1; + + x0 = timeIn[i] >> 1; + x1 = timeIn[i+1] >> 1; + y0 = timeIn[L2 - 1 - i] >> 1; + y1 = timeIn[L2 - 2 - i] >> 1; + + rSubband[i] = x0 - y0; + rSubband[i+1] = x1 - y1; + iSubband[i] = x0 + y0; + iSubband[i+1] = x1 + y1; + } + + dct_IV(rSubband, L, &shift); + dst_IV(iSubband, L, &shift); + + { + { + const FIXP_QTW *RESTRICT sbr_t_cos; + const FIXP_QTW *RESTRICT sbr_t_sin; + sbr_t_cos = anaQmf->t_cos; + sbr_t_sin = anaQmf->t_sin; + + for (i = 0; i < anaQmf->lsb; i++) { + cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], sbr_t_cos[i], sbr_t_sin[i]); + } + } + } +} + +/* + * \brief Perform one QMF slot analysis of the time domain data of timeIn + * with specified stride and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * Only the lower bands are obtained (upto anaQmf->lsb). For + * a full bandwidth analysis it is required to set both anaQmf->lsb + * and anaQmf->usb to the amount of QMF bands. + */ +void +qmfAnalysisFilteringSlot( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_QMF *qmfReal, /*!< Low and High band, real */ + FIXP_QMF *qmfImag, /*!< Low and High band, imag */ + const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ) +{ + int i; + int offset = anaQmf->no_channels*(QMF_NO_POLY*2-1); + /* + Feed time signal into oldest anaQmf->no_channels states + */ + { + FIXP_QAS *RESTRICT FilterStatesAnaTmp = ((FIXP_QAS*)anaQmf->FilterStates)+offset; + + /* Feed and scale actual time in slot */ + for(i=anaQmf->no_channels>>1; i!=0; i--) { + /* Place INT_PCM value left aligned in scaledTimeIn */ +#if (QAS_BITS==SAMPLE_BITS) + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; timeIn += stride; +#elif (QAS_BITS>SAMPLE_BITS) + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)<<(QAS_BITS-SAMPLE_BITS)); timeIn += stride; +#else + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn)>>(SAMPLE_BITS-QAS_BITS)); timeIn += stride; +#endif + } + } + + if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfAnaPrototypeFirSlot_NonSymmetric( + pWorkBuffer, + anaQmf->no_channels, + anaQmf->p_filter, + anaQmf->p_stride, + (FIXP_QAS*)anaQmf->FilterStates + ); + } else { + qmfAnaPrototypeFirSlot( pWorkBuffer, + anaQmf->no_channels, + anaQmf->p_filter, + anaQmf->p_stride, + (FIXP_QAS*)anaQmf->FilterStates + ); + } + + if (anaQmf->flags & QMF_FLAG_LP) { + if (anaQmf->flags & QMF_FLAG_CLDFB) + qmfForwardModulationLP_odd( anaQmf, + pWorkBuffer, + qmfReal ); + else + qmfForwardModulationLP_even( anaQmf, + pWorkBuffer, + qmfReal ); + + } else { + qmfForwardModulationHQ( anaQmf, + pWorkBuffer, + qmfReal, + qmfImag + ); + } + /* + Shift filter states + + Should be realized with modulo adressing on a DSP instead of a true buffer shift + */ + FDKmemmove ((FIXP_QAS*)anaQmf->FilterStates, (FIXP_QAS*)anaQmf->FilterStates+anaQmf->no_channels, offset*sizeof(FIXP_QAS)); +} + + +/*! + * + * \brief Perform complex-valued subband filtering of the time domain + * data of timeIn and stores the real part of the subband + * samples in rAnalysis, and the imaginary part in iAnalysis + * The qmf coefficient table is symmetric. The symmetry is expoited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. + * + * Only the lower bands are obtained (upto anaQmf->lsb). For + * a full bandwidth analysis it is required to set both anaQmf->lsb + * and anaQmf->usb to the amount of QMF bands. + * + * \sa PolyphaseFiltering + */ + +void +qmfAnalysisFiltering( HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_QMF **qmfReal, /*!< Pointer to real subband slots */ + FIXP_QMF **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, + const INT_PCM *timeIn, /*!< Time signal */ + const int stride, + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ) +{ + int i; + int no_channels = anaQmf->no_channels; + + scaleFactor->lb_scale = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK; + scaleFactor->lb_scale -= anaQmf->filterScale; + + for (i = 0; i < anaQmf->no_col; i++) + { + FIXP_QMF *qmfImagSlot = NULL; + + if (!(anaQmf->flags & QMF_FLAG_LP)) { + qmfImagSlot = qmfImag[i]; + } + + qmfAnalysisFilteringSlot( anaQmf, qmfReal[i], qmfImagSlot, timeIn , stride, pWorkBuffer ); + + timeIn += no_channels*stride; + + } /* no_col loop i */ +} + +/*! + * + * \brief Perform low power inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline +static void +qmfInverseModulationLP_even( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/ + ) +{ + int i; + int L = synQmf->no_channels; + int M = L>>1; + int scale; + FIXP_QMF tmp; + FIXP_QMF *RESTRICT tReal = pTimeOut; + FIXP_QMF *RESTRICT tImag = pTimeOut + L; + + /* Move input to output vector with offset */ + scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); + scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); + FDKmemclear(&tReal[0+synQmf->usb], (L-synQmf->usb)*sizeof(FIXP_QMF)); + + /* Dct type-2 transform */ + dct_II(tReal, tImag, L, &scale); + + /* Expand output and replace inplace the output buffers */ + tImag[0] = tReal[M]; + tImag[M] = (FIXP_QMF)0; + tmp = tReal [0]; + tReal [0] = tReal[M]; + tReal [M] = tmp; + + for (i = 1; i < M/2; i++) { + /* Imag */ + tmp = tReal[L - i]; + tImag[M - i] = tmp; + tImag[i + M] = -tmp; + + tmp = tReal[M + i]; + tImag[i] = tmp; + tImag[L - i] = -tmp; + + /* Real */ + tReal [M + i] = tReal[i]; + tReal [L - i] = tReal[M - i]; + tmp = tReal[i]; + tReal[i] = tReal [M - i]; + tReal [M - i] = tmp; + + } + /* Remaining odd terms */ + tmp = tReal[M + M/2]; + tImag[M/2] = tmp; + tImag[M/2 + M] = -tmp; + + tReal [M + M/2] = tReal[M/2]; +} + +inline +static void +qmfInverseModulationLP_odd( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_QMF *pTimeOut /*!< Pointer to qmf subband slot (output)*/ + ) +{ + int i; + int L = synQmf->no_channels; + int M = L>>1; + int shift = 0; + + /* Move input to output vector with offset */ + scaleValues(pTimeOut+M, qmfReal, synQmf->lsb, scaleFactorLowBand); + scaleValues(pTimeOut+M+synQmf->lsb, qmfReal+synQmf->lsb, synQmf->usb-synQmf->lsb, scaleFactorHighBand); + FDKmemclear(pTimeOut+M+synQmf->usb, (L-synQmf->usb)*sizeof(FIXP_QMF)); + + dct_IV(pTimeOut+M, L, &shift); + for (i = 0; i < M; i++) { + pTimeOut[i] = pTimeOut[L - 1 - i]; + pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; + } +} + + +/*! + * + * \brief Perform complex-valued inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline +static void +qmfInverseModulationHQ( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_QMF *qmfReal, /*!< Pointer to qmf real subband slot */ + const FIXP_QMF *qmfImag, /*!< Pointer to qmf imag subband slot */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand,/*!< Scalefactor for High band */ + FIXP_QMF *pWorkBuffer /*!< WorkBuffer (output) */ + ) +{ + int i; + int L = synQmf->no_channels; + int M = L>>1; + int shift = 0; + FIXP_QMF *RESTRICT tReal = pWorkBuffer; + FIXP_QMF *RESTRICT tImag = pWorkBuffer+L; + + if (synQmf->flags & QMF_FLAG_CLDFB){ + for (i = 0; i < synQmf->lsb; i++) { + cplxMult(&tImag[i], &tReal[i], + scaleValue(qmfImag[i],scaleFactorLowBand), scaleValue(qmfReal[i],scaleFactorLowBand), + synQmf->t_cos[i], synQmf->t_sin[i]); + } + for (; i < synQmf->usb; i++) { + cplxMult(&tImag[i], &tReal[i], + scaleValue(qmfImag[i],scaleFactorHighBand), scaleValue(qmfReal[i],scaleFactorHighBand), + synQmf->t_cos[i], synQmf->t_sin[i]); + } + } + + if ( (synQmf->flags & QMF_FLAG_CLDFB) == 0) { + scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, scaleFactorLowBand); + scaleValues(&tReal[0+synQmf->lsb], &qmfReal[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); + scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, scaleFactorLowBand); + scaleValues(&tImag[0+synQmf->lsb], &qmfImag[0+synQmf->lsb], synQmf->usb-synQmf->lsb, scaleFactorHighBand); + } + + if (synQmf->usb > synQmf->no_channels) { + return; + } + + FDKmemclear(&tReal[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF)); + FDKmemclear(&tImag[synQmf->usb], (synQmf->no_channels-synQmf->usb)*sizeof(FIXP_QMF)); + + dct_IV(tReal, L, &shift); + dst_IV(tImag, L, &shift); + + if (synQmf->flags & QMF_FLAG_CLDFB){ + for (i = 0; i < M; i++) { + FIXP_QMF r1, i1, r2, i2; + r1 = tReal[i]; + i2 = tImag[L - 1 - i]; + r2 = tReal[L - i - 1]; + i1 = tImag[i]; + + tReal[i] = (r1 - i1)>>1; + tImag[L - 1 - i] = -(r1 + i1)>>1; + tReal[L - i - 1] = (r2 - i2)>>1; + tImag[i] = -(r2 + i2)>>1; + } + } else + { + /* The array accesses are negative to compensate the missing minus sign in the low and hi band gain. */ + /* 26 cycles on ARM926 */ + for (i = 0; i < M; i++) { + FIXP_QMF r1, i1, r2, i2; + r1 = -tReal[i]; + i2 = -tImag[L - 1 - i]; + r2 = -tReal[L - i - 1]; + i1 = -tImag[i]; + + tReal[i] = (r1 - i1)>>1; + tImag[L - 1 - i] = -(r1 + i1)>>1; + tReal[L - i - 1] = (r2 - i2)>>1; + tImag[i] = -(r2 + i2)>>1; + } + } +} + +void qmfSynthesisFilteringSlot( HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_QMF *realSlot, + const FIXP_QMF *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, + INT_PCM *timeOut, + const int stride, + FIXP_QMF *pWorkBuffer) +{ + if (!(synQmf->flags & QMF_FLAG_LP)) + qmfInverseModulationHQ ( synQmf, + realSlot, + imagSlot, + scaleFactorLowBand, + scaleFactorHighBand, + pWorkBuffer + ); + else + { + if (synQmf->flags & QMF_FLAG_CLDFB) { + qmfInverseModulationLP_odd ( synQmf, + realSlot, + scaleFactorLowBand, + scaleFactorHighBand, + pWorkBuffer + ); + } else { + qmfInverseModulationLP_even ( synQmf, + realSlot, + scaleFactorLowBand, + scaleFactorHighBand, + pWorkBuffer + ); + } + } + + if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfSynPrototypeFirSlot_NonSymmetric ( + synQmf, + pWorkBuffer, + pWorkBuffer+synQmf->no_channels, + timeOut, + stride + ); + } else { + qmfSynPrototypeFirSlot ( synQmf, + pWorkBuffer, + pWorkBuffer+synQmf->no_channels, + timeOut, + stride + ); + } +} + + +/*! + * + * + * \brief Perform complex-valued subband synthesis of the + * low band and the high band and store the + * time domain data in timeOut + * + * First step: Calculate the proper scaling factor of current + * spectral data in qmfReal/qmfImag, old spectral data in the overlap + * range and filter states. + * + * Second step: Perform Frequency-to-Time mapping with inverse + * Modulation slot-wise. + * + * Third step: Perform FIR-filter slot-wise. To save space for filter + * states, the MAC operations are executed directly on the filter states + * instead of accumulating several products in the accumulator. The + * buffer shift at the end of the function should be replaced by a + * modulo operation, which is available on some DSPs. + * + * Last step: Copy the upper part of the spectral data to the overlap buffer. + * + * The qmf coefficient table is symmetric. The symmetry is exploited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. If the #define #QMFTABLE_FULL is set, + * coefficient addressing works on the full table size. The code will be + * slightly faster and slightly more compact. + * + * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels + */ +void +qmfSynthesisFiltering( HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_QMF **QmfBufferReal, /*!< Low and High band, real */ + FIXP_QMF **QmfBufferImag, /*!< Low and High band, imag */ + const QMF_SCALE_FACTOR *scaleFactor, + const INT ov_len, /*!< split Slot of overlap and actual slots */ + INT_PCM *timeOut, /*!< Pointer to output */ + const INT stride, /*!< stride factor of output */ + FIXP_QMF *pWorkBuffer /*!< pointer to temporal working buffer */ + ) +{ + int i; + int L = synQmf->no_channels; + SCHAR scaleFactorHighBand; + SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + + /* adapt scaling */ + scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->hb_scale; + scaleFactorLowBand_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->ov_lb_scale; + scaleFactorLowBand_no_ov = - ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - scaleFactor->lb_scale; + + for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */ + { + const FIXP_DBL *QmfBufferImagSlot = NULL; + + SCHAR scaleFactorLowBand = (iflags & QMF_FLAG_LP)) + QmfBufferImagSlot = QmfBufferImag[i]; + + qmfSynthesisFilteringSlot( synQmf, + QmfBufferReal[i], + QmfBufferImagSlot, + scaleFactorLowBand, + scaleFactorHighBand, + timeOut+(i*L*stride), + stride, + pWorkBuffer); + } /* no_col loop i */ + +} + + +/*! + * + * \brief Create QMF filter bank instance + * + * \return 0 if successful + * + */ +static int +qmfInitFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ + void *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< Lower end of QMF frequency range */ + int usb, /*!< Upper end of QMF frequency range */ + int no_channels, /*!< Number of channels (bands) */ + UINT flags) /*!< flags */ +{ + FDKmemclear(h_Qmf,sizeof(QMF_FILTER_BANK)); + + if (flags & QMF_FLAG_MPSLDFB) + { + return -1; + } + + if ( !(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB) ) + { + flags |= QMF_FLAG_NONSYMMETRIC; + h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; + + h_Qmf->p_stride = 1; + switch (no_channels) { + case 64: + h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; + h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; + h_Qmf->p_filter = qmf_cldfb_640; + h_Qmf->FilterSize = 640; + break; + case 32: + h_Qmf->t_cos = qmf_phaseshift_cos32_cldfb; + h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; + h_Qmf->p_filter = qmf_cldfb_320; + h_Qmf->FilterSize = 320; + break; + default: + return -1; + } + } + + if ( !(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0) ) + { + switch (no_channels) { + case 64: + h_Qmf->p_filter = qmf_64; + h_Qmf->t_cos = qmf_phaseshift_cos64; + h_Qmf->t_sin = qmf_phaseshift_sin64; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 32: + h_Qmf->p_filter = qmf_64; + if (flags & QMF_FLAG_DOWNSAMPLED) { + h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; + h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; + } + else { + h_Qmf->t_cos = qmf_phaseshift_cos32; + h_Qmf->t_sin = qmf_phaseshift_sin32; + } + h_Qmf->p_stride = 2; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + default: + return -1; + } + } + + h_Qmf->flags = flags; + + h_Qmf->no_channels = no_channels; + h_Qmf->no_col = noCols; + + h_Qmf->lsb = lsb; + h_Qmf->usb = fMin(usb, h_Qmf->no_channels); + + h_Qmf->FilterStates = (void*)pFilterStates; + + h_Qmf->outScalefactor = ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + h_Qmf->filterScale; + + if ( (h_Qmf->p_stride == 2) + || ((flags & QMF_FLAG_CLDFB) && (no_channels == 32)) ) { + h_Qmf->outScalefactor -= 1; + } + h_Qmf->outGain = (FIXP_DBL)0x80000000; /* default init value will be not applied */ + + return (0); +} + +/*! + * + * \brief Adjust synthesis qmf filter states + * + * \return void + * + */ +static inline void +qmfAdaptFilterStates (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ + int scaleFactorDiff) /*!< Scale factor difference to be applied */ +{ + if (synQmf == NULL || synQmf->FilterStates == NULL) { + return; + } + scaleValues((FIXP_QSS*)synQmf->FilterStates, synQmf->no_channels*(QMF_NO_POLY*2 - 1), scaleFactorDiff); +} + +/*! + * + * \brief Create QMF filter bank instance + * + * Only the lower bands are obtained (upto anaQmf->lsb). For + * a full bandwidth analysis it is required to set both anaQmf->lsb + * and anaQmf->usb to the amount of QMF bands. + * + * \return 0 if succesful + * + */ +int +qmfInitAnalysisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QAS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags); + if ( !(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL) ) { + FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QAS)); + } + + return err; +} + +/*! + * + * \brief Create QMF filter bank instance + * + * Only the lower bands are obtained (upto anaQmf->lsb). For + * a full bandwidth analysis it is required to set both anaQmf->lsb + * and anaQmf->usb to the amount of QMF bands. + * + * \return 0 if succesful + * + */ +int +qmfInitSynthesisFilterBank (HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QSS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int oldOutScale = h_Qmf->outScalefactor; + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, no_channels, flags); + if ( h_Qmf->FilterStates != NULL ) { + if ( !(flags & QMF_FLAG_KEEP_STATES) ) { + FDKmemclear(h_Qmf->FilterStates, (2*QMF_NO_POLY-1)*h_Qmf->no_channels*sizeof(FIXP_QSS)); + } else { + qmfAdaptFilterStates(h_Qmf, oldOutScale-h_Qmf->outScalefactor); + } + } + return err; +} + + + + +/*! + * + * \brief Change scale factor for output data and adjust qmf filter states + * + * \return void + * + */ +void +qmfChangeOutScalefactor (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ + ) +{ + if (synQmf == NULL || synQmf->FilterStates == NULL) { + return; + } + + /* Add internal filterbank scale */ + outScalefactor += ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + synQmf->filterScale; + + if ( (synQmf->p_stride == 2) + || ((synQmf->flags & QMF_FLAG_CLDFB) && (synQmf->no_channels == 32)) ) { + outScalefactor -= 1; + } + + /* adjust filter states when scale factor has been changed */ + if (synQmf->outScalefactor != outScalefactor) + { + int diff; + + if (outScalefactor > (SAMPLE_BITS - 1)) { + outScalefactor = SAMPLE_BITS - 1; + } else if (outScalefactor < (1 - SAMPLE_BITS)) { + outScalefactor = 1 - SAMPLE_BITS; + } + + diff = synQmf->outScalefactor - outScalefactor; + + qmfAdaptFilterStates(synQmf, diff); + + /* save new scale factor */ + synQmf->outScalefactor = outScalefactor; + } +} + +/*! + * + * \brief Change gain for output data + * + * \return void + * + */ +void +qmfChangeOutGain (HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain /*!< New gain for output data */ + ) +{ + synQmf->outGain = outputGain; +} + diff --git a/libFDK/src/scale.cpp b/libFDK/src/scale.cpp new file mode 100644 index 00000000..58294430 --- /dev/null +++ b/libFDK/src/scale.cpp @@ -0,0 +1,461 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: Scaling operations + +******************************************************************************/ + +#include "common_fix.h" + +#include "genericStds.h" + +/************************************************** + * Inline definitions + **************************************************/ + +#define SCALE_INLINE inline + + +#if defined(__mips__) /* cppp replaced: elif */ +#include "mips/scale.cpp" + +#elif defined(__arm__) +#include "arm/scale_arm.cpp" + +#endif + +#ifndef FUNCTION_scaleValues_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_SGL +SCALE_INLINE +void scaleValues(FIXP_SGL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ + ) +{ + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor==0) return; + + if(scalefactor > 0){ + scalefactor = fixmin_I(scalefactor,(INT)(DFRACT_BITS-1)); + for (i = len&3; i--; ) + { + *(vector++) <<= scalefactor; + } + for (i = len>>2; i--; ) + { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *(vector++) >>= negScalefactor; + } + for (i = len>>2; i--; ) + { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValues_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_DBL +SCALE_INLINE +void scaleValues(FIXP_DBL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ + ) +{ + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor==0) return; + + if(scalefactor > 0){ + scalefactor = fixmin_I(scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *(vector++) <<= scalefactor; + } + for (i = len>>2; i--; ) + { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *(vector++) >>= negScalefactor; + } + for (i = len>>2; i--; ) + { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValues_DBLDBL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_DBLDBL +SCALE_INLINE +void scaleValues(FIXP_DBL *dst, /*!< dst Vector */ + const FIXP_DBL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ + ) +{ + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor==0) { + if (dst != src) + FDKmemmove(dst, src, len*sizeof(FIXP_DBL)); + } + else { + + if(scalefactor > 0){ + scalefactor = fixmin_I(scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *(dst++) = *(src++) << scalefactor; + } + for (i = len>>2; i--; ) + { + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *(dst++) = *(src++) >> negScalefactor; + } + for (i = len>>2; i--; ) + { + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + } + } + } +} +#endif + +#ifndef FUNCTION_scaleValuesWithFactor_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValuesWithFactor_DBL +SCALE_INLINE +void scaleValuesWithFactor( + FIXP_DBL *vector, + FIXP_DBL factor, + INT len, + INT scalefactor + ) +{ + INT i; + + /* Compensate fMultDiv2 */ + scalefactor++; + + if(scalefactor > 0){ + scalefactor = fixmin_I(scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + } + for (i = len>>2; i--; ) + { + *vector = fMultDiv2(*vector, factor) << scalefactor; vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; vector++; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor,(INT)DFRACT_BITS-1); + for (i = len&3; i--; ) + { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + } + for (i = len>>2; i--; ) + { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; vector++; + } + } +} +#endif /* FUNCTION_scaleValuesWithFactor_DBL */ + + +/******************************************* + +IMPORTANT NOTE for usage of getScalefactor() + +If the input array contains negative values too, then these functions may sometimes return +the actual maximum value minus 1, due to the nature of the applied algorithm. +So be careful with possible fractional -1 values that may lead to overflows when being fPow2()'ed. + +********************************************/ + + + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor / possible left shift + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len /*!< Length of input vector */ + ) +{ + INT i; + SHORT temp, maxVal = 0; + + for(i=len;i!=0;i--){ + temp = (SHORT)(*vector++); + maxVal |= (temp^(temp>>(SHORT_BITS-1))); + } + + return fixmax_I((INT)0,(INT)(fixnormz_D((INT)maxVal) - (INT)1 - (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorPCM +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorPCM +SCALE_INLINE +INT getScalefactorPCM(const INT_PCM *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride + ) +{ + INT i; + INT_PCM temp, maxVal = 0; + + for(i=len;i!=0;i--){ + temp = (INT_PCM)(*vector); vector+=stride; + maxVal |= (temp^(temp>>((sizeof(INT_PCM)*8)-1))); + } + return fixmax_I((INT)0,(INT)(fixnormz_D((INT)maxVal) - (INT)1 - (INT)(DFRACT_BITS - SAMPLE_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * \param stride, item increment between vector members. + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride + ) +{ + INT i; + SHORT temp, maxVal = 0; + + for(i=len;i!=0;i--){ + temp = (SHORT)(*vector); vector+=stride; + maxVal |= (temp^(temp>>(SHORT_BITS-1))); + } + + return fixmax_I((INT)0,(INT)(fixnormz_D((INT)maxVal) - (INT)1 - (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactor_DBL +/*! + * + * \brief Calculate max possible scale factor for input vector + * + * \return Maximum scale factor + * + * This function can constitute a significant amount of computational complexity - very much depending on the + * bitrate. Since it is a rather small function, effective assembler optimization might be possible. + * + */ +#define FUNCTION_getScalefactor_DBL +SCALE_INLINE +INT getScalefactor(const FIXP_DBL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + FIXP_DBL temp, maxVal = (FIXP_DBL)0; + + for(i=len;i!=0;i--){ + temp = (LONG)(*vector++); + maxVal |= (FIXP_DBL)((LONG)temp^(LONG)(temp>>(DFRACT_BITS-1))); + } + + return fixmax_I((INT)0,(INT)(fixnormz_D(maxVal) - 1)); +} +#endif + +#ifndef FUNCTION_getScalefactor_SGL +#define FUNCTION_getScalefactor_SGL +SCALE_INLINE +INT getScalefactor(const FIXP_SGL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + SHORT temp, maxVal = (FIXP_SGL)0; + + for(i=len;i!=0;i--){ + temp = (SHORT)(*vector++); + maxVal |= (temp^(temp>>(FRACT_BITS-1))); + } + + return fixmax_I((INT)0,(INT)(fixnormz_D(FX_SGL2FX_DBL((FIXP_SGL)maxVal)) - 1)); +} +#endif + diff --git a/libMpegTPDec/include/mpegFileRead.h b/libMpegTPDec/include/mpegFileRead.h new file mode 100644 index 00000000..1fbfb58e --- /dev/null +++ b/libMpegTPDec/include/mpegFileRead.h @@ -0,0 +1,194 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Manuel Jander + Description: Bitstream data provider for MP4 decoders + +******************************************************************************/ + +#include "machine_type.h" +#include "FDK_audio.h" + +#define MPFREAD_MP4FF_DISABLE + +#ifndef MPFREAD_MP4FF_DISABLE + /*!< If MPFREAD_MP4FF_ENABLE is set, include support for MPEG ISO fileformat. + If not set, no .mp4, .m4a and .3gp files can be used for input. */ + #define MPFREAD_MP4FF_ENABLE +#endif + +/* maximum number of layers which can be read */ +/* shall equal max number of layers read by iisisoff */ +#define FILEREAD_MAX_LAYERS (2) + +typedef struct STRUCT_FILEREAD *HANDLE_FILEREAD; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Open an MPEG audio file and try to detect its format. + * \param filename String of the filename to be opened. + * \param fileFormat Skip file format detection and use given format if fileFormat != FF_UNKNOWN. + Else store detected format into *fileFmt. + * \param transportType Skip transport type detection and use given format if transportType != TT_UNKNOWN. + Else store detected format into *fileFmt. + * \param conf Pointer to unsigned char to hold the AudioSpecificConfig of the input file, if + any (MPEG 4 file format). In case of RAW LATM it holds the StreamMuxConfig. + * \param confSize Pointer to an integer, where the length of the ASC or SMC (in case of RAW LATM) + is stored to. + * \return MPEG file read handle. + */ +HANDLE_FILEREAD mpegFileRead_Open( const char *filename, + FILE_FORMAT fileFormat, + TRANSPORT_TYPE transportType, + UCHAR *conf[], + UINT confSize[], + INT *noOfLayers + ); + +/** + * \brief Get the file format of the input file. + * \param hDataSrc MPEG file read handle. + * \return File format of the input file. + */ +FILE_FORMAT mpegFileRead_GetFileFormat(HANDLE_FILEREAD hDataSrc); + +/** + * \brief Get the transport type of the input file. + * \param hDataSrc MPEG file read handle. + * \return Transport type of the input file. + */ +TRANSPORT_TYPE mpegFileRead_GetTransportType(HANDLE_FILEREAD hDataSrc); + +/** + * \brief Read data from MPEG file. In case of packet file, read one packet, in case + * of streaming file with embedded synchronisation layer (LOAS/ADTS...), just + * fill the buffer. + * + * \param hMpegFile MPEG file read handle. + * \param inBuffer Pointer to input buffer. + * \param bufferSize Size of input buffer. + * \param bytesValid Number of bytes that were read. + * \return 0 on success, -1 if unsupported file format or file read error. + */ +int mpegFileRead_Read( HANDLE_FILEREAD hMpegFile, + UCHAR *inBuffer[], + UINT bufferSize, + UINT *bytesValid + ); + +/** + * \brief Seek in file from origin by given offset in frames. + * \param hMpegFile MPEG file read handle. + * \param origin If 0, the origin is the file beginning (absolute seek). + * If 1, the origin is the current position (relative seek). + * \param offset The amount of frames to seek from the given origin. + * \return 0 on sucess, -1 if offset < 0 or file read error. + */ +int mpegFileRead_seek( HANDLE_FILEREAD hMpegFile, + INT origin, + INT offset + ); + +/** + * \brief Get file position in percent. + * \param hMpegFile MPEG file read handle. + * \return File position in percent. + */ +int mpegFileRead_getPercent(HANDLE_FILEREAD hMpegFile); + + +/** + * \brief Close MPEG audio file. + * \param hMpegFile Mpeg file read handle. + * \return 0 on sucess. + */ +int mpegFileRead_Close(HANDLE_FILEREAD *hMpegFile); + +#ifdef __cplusplus +} +#endif diff --git a/libMpegTPDec/include/tp_data.h b/libMpegTPDec/include/tp_data.h new file mode 100644 index 00000000..c6e89b51 --- /dev/null +++ b/libMpegTPDec/include/tp_data.h @@ -0,0 +1,350 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Manuel Jander + Description: MPEG Transport data tables + +******************************************************************************/ + +#ifndef __TP_DATA_H__ +#define __TP_DATA_H__ + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ +#define TP_GA_ENABLE +/* #define TP_CELP_ENABLE */ +/* #define TP_HVXC_ENABLE */ +/* #define TP_SLS_ENABLE */ +#define TP_ELD_ENABLE +/* #define TP_USAC_ENABLE */ +/* #define TP_RSVD50_ENABLE */ + +#if defined(TP_GA_ENABLE) || defined(TP_SLS_ENABLE) +#define TP_PCE_ENABLE /**< Enable full PCE support */ +#endif + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 + +typedef struct +{ +#ifdef TP_PCE_ENABLE + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; +#endif /* TP_PCE_ENABLE */ + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR NumChannels; /*!< Amount of audio channels summing all channel elements including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +#ifdef TP_GA_ENABLE +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag ; + UINT m_dependsOnCoreCoder ; + UINT m_coreCoderDelay ; + + UINT m_extensionFlag ; + UINT m_extensionFlag3 ; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; +#endif /* TP_GA_ENABLE */ + + + + +#ifdef TP_ELD_ENABLE + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2 /* LD MPEG Surround config */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + +} CSEldSpecificConfig; +#endif /* TP_ELD_ENABLE */ + + + + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + + /* XYZ Specific Data */ + union { +#ifdef TP_GA_ENABLE + CSGaSpecificConfig m_gaSpecificConfig; /**< General audio specific configuration. */ +#endif /* TP_GA_ENABLE */ +#ifdef TP_ELD_ENABLE + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ +#endif /* TP_ELD_ENABLE */ + } m_sc; + + /* Common ASC parameters */ +#ifdef TP_PCE_ENABLE + CProgramConfig m_progrConfigElement; /**< Program configuration. */ +#endif /* TP_PCE_ENABLE */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the bitstream */ + SCHAR m_psPresentFlag; /**< Flag indicating the presence of parametric stereo data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + +} CSAudioSpecificConfig; + +typedef INT (*cbUpdateConfig_t)(void*, const CSAudioSpecificConfig*); +typedef INT (*cbSsc_t)( + void*, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingFrequency, + const INT muxMode, + const INT configBytes + ); +typedef INT (*cbSbr_t)( + void * self, + HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, + const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex + ); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = +{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, + 0 +}; + +static inline +int getSamplingRateIndex( UINT samplingRate ) +{ + UINT sf_index, tableSize=sizeof(SamplingRateTable)/sizeof(UINT); + + for (sf_index=0; sf_indextableSize-1) { + return tableSize-1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) +{ + switch (channelConfig) { + case 1: case 2: case 3: + case 4: case 5: case 6: + return channelConfig; + case 7: case 12: case 14: + return 8; + case 11: + return 7; + default: + return 0; + } +} + +static inline +int getNumberOfEffectiveChannels(const int channelConfig) +{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0}; + return n[channelConfig]; +} + +#endif /* __TP_DATA_H__ */ diff --git a/libMpegTPDec/include/tpdec_lib.h b/libMpegTPDec/include/tpdec_lib.h new file mode 100644 index 00000000..2ad397df --- /dev/null +++ b/libMpegTPDec/include/tpdec_lib.h @@ -0,0 +1,521 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** MPEG-4 Transport Decoder *********************** + + Author(s): Manuel Jander + Description: MPEG Transport decoder + +******************************************************************************/ + +#ifndef __TPDEC_LIB_H__ +#define __TPDEC_LIB_H__ + +#include "tp_data.h" + +#include "FDK_bitstream.h" + +#define TRANSPORTDEC_INBUF_SIZE ( 8192 ) /*!< Size is in bytes. + Set the transport input buffer size carefully and + assure that it fulfills the requirements of the + supported transport format(s). */ + +typedef enum { + TRANSPORTDEC_OK = 0, /*!< All fine. */ + + /* Synchronization errors. Wait for new input data and try again. */ + tpdec_sync_error_start = 0x100, + TRANSPORTDEC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try again. */ + TRANSPORTDEC_SYNC_ERROR, /*!< No sync was found or sync got lost. Keep trying. */ + tpdec_sync_error_end, + + /* Decode errors. Mostly caused due to bit errors. */ + tpdec_decode_error_start = 0x400, + TRANSPORTDEC_PARSE_ERROR, /*!< Bitstream data showed inconsistencies (wrong syntax). */ + TRANSPORTDEC_UNSUPPORTED_FORMAT, /*!< Unsupported format or feature found in the bitstream data. */ + TRANSPORTDEC_CRC_ERROR, /*!< CRC error encountered in bitstream data. */ + tpdec_decode_error_end, + + /* Fatal errors. Stop immediately on one of these errors! */ + tpdec_fatal_error_start = 0x200, + TRANSPORTDEC_UNKOWN_ERROR, /*!< An unknown error occured. */ + TRANSPORTDEC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a function. */ + TRANSPORTDEC_NEED_TO_RESTART, /*!< The decoder needs to be restarted, since the requiered + configuration change cannot be performed. */ + tpdec_fatal_error_end + +} TRANSPORTDEC_ERROR; + + +/** Macro to identify decode errors. */ +#define TPDEC_IS_DECODE_ERROR(err) ( ((err>=tpdec_decode_error_start) && (err<=tpdec_decode_error_end)) ? 1 : 0) +/** Macro to identify fatal errors. */ +#define TPDEC_IS_FATAL_ERROR(err) ( ((err>=tpdec_fatal_error_start) && (err<=tpdec_fatal_error_end)) ? 1 : 0) + + +/** + * \brief Parameter identifiers for transportDec_SetParam() + */ +typedef enum { + TPDEC_PARAM_MINIMIZE_DELAY = 1, /** Delay minimization strategy. 0: none, 1: discard as many frames as possible. */ + TPDEC_PARAM_EARLY_CONFIG, /** Enable early config discovery. */ + TPDEC_PARAM_IGNORE_BUFFERFULLNESS, /** Ignore buffer fullness. */ + TPDEC_PARAM_SET_BITRATE, /** Set average bit rate for bit stream interruption frame misses estimation. */ + TPDEC_PARAM_RESET, /** Reset transport decoder instance status. */ + TPDEC_PARAM_BURST_PERIOD /** Set data reception burst period in mili seconds. */ +} TPDEC_PARAM; + +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 + + +/*! + \brief Reset Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Reset ( CProgramConfig *pPce ); + +/*! + \brief Initialize Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Init ( CProgramConfig *pPce ); + +/*! + \brief Inquire state of present Program Config Element structure. + \param pPce Program Config Element structure. + \return 1 if the PCE structure is filled correct, + 0 if no valid PCE present. +*/ +int CProgramConfig_IsValid ( const CProgramConfig *pPce ); + +#ifdef TP_PCE_ENABLE +/*! + \brief Read Program Config Element. + \param pPce Program Config Element structure. + \param bs Bitstream buffer to read from. + \param alignAnchor Align bitstream to alignAnchor bits after all read operations. + \return void +*/ +void CProgramConfig_Read ( CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + UINT alignAnchor ); + +/*! + \brief Compare two Program Config Elements. + \param pPce1 Pointer to first Program Config Element structure. + \param pPce2 Pointer to second Program Config Element structure. + \return -1 if PCEs are completely different, + 0 if PCEs are completely equal, + 1 if PCEs are different but have the same channel config, + 2 if PCEs have different channel config but same number of channels. +*/ +int CProgramConfig_Compare ( const CProgramConfig * const pPce1, + const CProgramConfig * const pPce2 ); + +/*! + \brief Get a Program Config Element that matches the predefined MPEG-4 channel configurations 1-14. + \param pPce Program Config Element structure. + \param channelConfig MPEG-4 channel configuration. + \return void +*/ +void CProgramConfig_GetDefault ( CProgramConfig *pPce, + const UINT channelConfig ); +#endif /* TP_PCE_ENABLE */ + +/** + * \brief Lookup and verify a given element. The decoder calls this + * method with every new element ID found in the bitstream. + * + * \param pPce A valid Program config structure. + * \param tag Tag of the current element to be looked up. + * \param channelIdx The current channel count of the decoder parser. + * \param chMapping Array to store the canonical channel mapping indexes. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \param elMapping Pointer where the canonical element index is stored. + * \param elType The element id of the current element to be looked up. + * + * \return Non-zero if the element belongs to the current program, zero + * if it does not. + */ +int CProgramConfig_LookupElement( + CProgramConfig *pPce, + UINT channelConfig, + const UINT tag, + const UINT channelIdx, + UCHAR chMapping[], + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], + UCHAR *elMapping, + MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType + ); + +/** + * \brief Get table of elements in canonical order from a + * give program config field. + * \param pPce A valid program config structure. + * \param table An array where the element IDs are stored. + * \param elListSize The length of the table array. + * \param pChMapIdx Pointer to a field receiving the corresponding + * implicit channel configuration index of the given + * PCE. If none can be found it receives the value 0. + * \return Total element count including all SCE, CPE and LFE. + */ +int CProgramConfig_GetElementTable( const CProgramConfig *pPce, + MP4_ELEMENT_ID table[], + const INT elListSize, + UCHAR *pChMapIdx ); + +/** + * \brief Initialize a given AudioSpecificConfig structure. + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \return void + */ +void AudioSpecificConfig_Init(CSAudioSpecificConfig *pAsc); + +/** + * \brief Parse a AudioSpecificConfig from a given bitstream handle. + * + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * \param fExplicitBackwardCompatible Do explicit backward compatibility parsing if set (flag). + * \param cb pointer to structure holding callback information + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + int fExplicitBackwardCompatible, + CSTpCallBacks *cb + ); + +/* CELP stuff */ +enum { + MPE = 0, + RPE = 1, + fs8KHz = 0, + fs16KHz = 1 +}; + +/* Defintion of flags that can be passed to transportDecOpen() */ +#define TP_FLAG_MPEG4 1 + +/* Capability flags */ +#define CAPF_TPDEC_ADIF 0x00001000 /**< Flag indicating support for ADIF transport format. */ +#define CAPF_TPDEC_ADTS 0x00002000 /**< Flag indicating support for ADTS transport format. */ +#define CAPF_TPDEC_LOAS 0x00004000 /**< Flag indicating support for LOAS transport format. */ +#define CAPF_TPDEC_LATM 0x00008000 /**< Flag indicating support for LATM transport format. */ +#define CAPF_TPDEC_RAWPACKETS 0x00010000 /**< Flag indicating support for raw packets transport format. */ + +typedef struct TRANSPORTDEC *HANDLE_TRANSPORTDEC; + + +/** + * \brief Configure Transport Decoder via a binary coded AudioSpecificConfig or StreamMuxConfig. + * The previously requested configuration callback will be called as well. The buffer conf + * must containt a SMC in case of LOAS/LATM transport format, and an ASC elseways. + * + * \param hTp Handle of a transport decoder. + * \param conf UCHAR buffer of the binary coded config (ASC or SMC). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig( const HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, + const UINT length, + const UINT layer ); + +/** + * \brief Open Transport medium for reading. + * + * \param transportDecFmt Format of the transport decoder medium to be accessed. + * \param flags Transport decoder flags. Currently only TP_FLAG_MPEG4, which signals a + * MPEG4 capable decoder (relevant for ADTS only). + * + * \return A pointer to a valid and allocated HANDLE_TRANSPORTDEC or a null pointer on failure. + */ +HANDLE_TRANSPORTDEC transportDec_Open( TRANSPORT_TYPE transportDecFmt, + const UINT flags ); + +/** + * \brief Register configuration change callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle audio config changes. + * \param user_data void pointer for user data passed to the callback as first parameter. + * \return 0 on success. + */ +int transportDec_RegisterAscCallback ( + HANDLE_TRANSPORTDEC hTp, + const cbUpdateConfig_t cbUpdateConfig, + void* user_data ); + +/** + * \brief Register SSC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC parsing. + * \param user_data void pointer for user data passed to the callback as first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSscCallback ( + HANDLE_TRANSPORTDEC hTp, + const cbSsc_t cbSscParse, + void* user_data ); + +/** + * \brief Register SBR header parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header parsing. + * \param user_data void pointer for user data passed to the callback as first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t cbSbr, void* user_data); + +/** + * \brief Fill internal input buffer with bitstream data from the external input buffer. + * The function only copies such data as long as the decoder-internal input buffer is not full. + * So it grabs whatever it can from pBuffer and returns information (bytesValid) so that at a + * subsequent call of %transportDec_FillData(), the right position in pBuffer can be determined to + * grab the next data. + * + * \param hTp Handle of transportDec. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required because decoder-internally + * we need the information to calculate the offset to pBuffer, where the next + * available data is, which is then fed into the decoder-internal buffer (as much + * as possible). Our example framework implementation fills the buffer at pBuffer + * again, once it contains no available valid bytes anymore (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer that have not yet been + * copied into the decoder's internal bitstream buffer by calling this function. + * The value is updated according to the amount of newly copied bytes. + * \param layer The layer the bitstream belongs to. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_FillData( + const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, + const UINT bufferSize, + UINT *pBytesValid, + const INT layer ); + +/** + * \brief Get transportDec bitstream handle. + * \param hTp Pointer to a transport decoder handle. + * \return HANDLE_FDK_BITSTREAM bitstream handle. + */ +HANDLE_FDK_BITSTREAM transportDec_GetBitstream ( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); + +/** + * \brief Get transport format. + * \param hTp Pointer to a transport decoder handle. + * \return The transport format. + */ +TRANSPORT_TYPE transportDec_GetFormat ( const HANDLE_TRANSPORTDEC hTp ); + +/** + * \brief Get the current buffer fullness value. + * + * \param hTp Handle of a transport decoder. + * + * \return Buffer fullness + */ +INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp ); + +/** + * \brief Close and deallocate transportDec. + * \param phTp Pointer to a previously allocated transport decoder handle. + * \return void + */ +void transportDec_Close ( HANDLE_TRANSPORTDEC *phTp ); + +/** + * \brief Read one access unit from the transportDec medium. + * \param hTp Handle of transportDec. + * \param length On return, this value is overwritten with the actual access unit length in bits. + * Set to -1 if length is unknown. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit ( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); + +/** + * \brief Get the remaining amount of bits of the current access unit. The result + * can be below zero, meaning that too many bits have been read. + * \param hTp Handle of transportDec. + * \return amount of remaining bits. + */ +INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); + +/** + * \brief Get the total amount of bits of the current access unit. + * \param hTp Handle of transportDec. + * \return amount of total bits. + */ +INT transportDec_GetAuBitsTotal( const HANDLE_TRANSPORTDEC hTp, const UINT layer ); + +/** + * \brief This function is required to be called when the decoder has finished parsing + * one Access Unit for bitstream housekeeping. + * \param hTp Transport Handle. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit ( const HANDLE_TRANSPORTDEC hTp ); + +/** + * \brief Obtain the amount of missing access units if applicable in case of + * a bit stream synchronization error. Each time transportDec_ReadAccessUnit() + * returns TRANSPORTDEC_SYNC_ERROR this function can be called to retrieve an estimate + * of the amount of missing access units. This works only in case of constant average + * bit rate (has to be known) and if the parameter TPDEC_PARAM_SET_BITRATE has been set + * accordingly. + * \param hTp Transport Handle. + * \param pNAccessUnits pointer to a memory location where the estimated lost frame count will be stored into. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp ); + + +/** + * \brief Set a given setting. + * \param hTp Transport Handle. + * \param param Identifier of the parameter to be changed. + * \param value Value for the parameter to be changed. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value ); + +/** + * \brief Get number of subframes (for LATM or ADTS) + * \param hTp Transport Handle. + * \return Number of ADTS/LATM subframes (return 1 for all other transport types). + */ +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp); + + +/** + * \brief Get info structure of transport decoder library. + * \param info A pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTp Transport handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be of a fixed size. + * \return Data region ID, which should be used when calling transportDec_CrcEndReg(). + */ +int transportDec_CrcStartReg ( const HANDLE_TRANSPORTDEC hTp, + const INT mBits ); + +/** + * \brief Set end of data region. + * \param hTp Transport handle. + * \param reg Data region ID, opbtained from transportDec_CrcStartReg(). + * \return void + */ +void transportDec_CrcEndReg ( const HANDLE_TRANSPORTDEC hTp, + const INT reg ); + +/** + * \brief Calculate ADTS crc and check if it is correct. The ADTS checksum is held internally. + * \param hTp Transport handle. + * \return Return TRANSPORTDEC_OK if the CRC is ok, or error if CRC is not correct. + */ +TRANSPORTDEC_ERROR transportDec_CrcCheck ( const HANDLE_TRANSPORTDEC hTp ); + + +#endif /* #ifndef __TPDEC_LIB_H__ */ diff --git a/libMpegTPDec/src/mpegFileFormat.h b/libMpegTPDec/src/mpegFileFormat.h new file mode 100644 index 00000000..b0cfe9e0 --- /dev/null +++ b/libMpegTPDec/src/mpegFileFormat.h @@ -0,0 +1,114 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Oliver Moser + Description: bitstream format detection routines + +******************************************************************************/ + +#if !defined(__BITSTREAM_FORMAT_H__) +#define __BITSTREAM_FORMAT_H__ + +#include "machine_type.h" +#include "FDK_audio.h" + +/** + * \brief Try to find out the format of a file, given the few first bytes. + * \param fileData pointer to a buffer holding the first bytes of a file. + * \param pAu pointer to UCHAR*, returns the address of the first AU found or NULL. + * \param length pointer to the length of the buffer fileData. Return length of first AU. + * \return the detected file format, or FF_UNKNOWN in case of failure. + */ +FILE_FORMAT GetFileFormat(UCHAR *fileData, UCHAR **pAu, UINT *length); + +/** + * \brief Try to find out the transport type contained in a given file. + * \param filename name of the file to be analysed. + * \param fileFormat pointer to a variable where the detected file format is stored into. + * \return the detected transport type or TT_UNKNOWN in case of failure. + */ +TRANSPORT_TYPE GetTransportType(const char* filename, FILE_FORMAT *fileFormat); + +#endif diff --git a/libMpegTPDec/src/tpdec_adif.cpp b/libMpegTPDec/src/tpdec_adif.cpp new file mode 100644 index 00000000..237e881f --- /dev/null +++ b/libMpegTPDec/src/tpdec_adif.cpp @@ -0,0 +1,155 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: ADIF reader + +******************************************************************************/ + +#include "tpdec_adif.h" + + +#include "FDK_bitstream.h" +#include "genericStds.h" + +TRANSPORTDEC_ERROR adifRead_DecodeHeader( + CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs + ) +{ + int i; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT startAnchor = FDKgetValidBits(bs); + + if ((INT)startAnchor < MIN_ADIF_HEADERLENGTH) { + return (TRANSPORTDEC_NOT_ENOUGH_BITS); + } + + if (FDKreadBits(bs,8) != 'A') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs,8) != 'D') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs,8) != 'I') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs,8) != 'F') { + return (TRANSPORTDEC_SYNC_ERROR); + } + + if ( (pAdifHeader->CopyrightIdPresent = FDKreadBits(bs,1)) != 0 ) + FDKpushBiDirectional(bs,72); /* CopyrightId */ + + + pAdifHeader->OriginalCopy = FDKreadBits(bs,1); + pAdifHeader->Home = FDKreadBits(bs,1); + pAdifHeader->BitstreamType = FDKreadBits(bs,1); + + /* pAdifHeader->BitRate = FDKreadBits(bs, 23); */ + pAdifHeader->BitRate = FDKreadBits(bs,16); + pAdifHeader->BitRate <<= 7; + pAdifHeader->BitRate |= FDKreadBits(bs,7); + + pAdifHeader->NumProgramConfigElements = FDKreadBits(bs,4) + 1; + + if (pAdifHeader->BitstreamType == 0) { + FDKpushBiDirectional(bs,20); /* adif_buffer_fullness */ + } + + /* Parse all PCEs but keep only one */ + for (i=0; i < pAdifHeader->NumProgramConfigElements; i++) + { + CProgramConfig_Read(pPce, bs, startAnchor); + } + + FDKbyteAlign(bs, startAnchor); + + return (ErrorStatus); +} + + + diff --git a/libMpegTPDec/src/tpdec_adif.h b/libMpegTPDec/src/tpdec_adif.h new file mode 100644 index 00000000..d6780a76 --- /dev/null +++ b/libMpegTPDec/src/tpdec_adif.h @@ -0,0 +1,123 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: ADIF reader + +******************************************************************************/ + +#ifndef TPDEC_ADIF_H +#define TPDEC_ADIF_H + +#include "tpdec_lib.h" + +#define MIN_ADIF_HEADERLENGTH 63 /* in bits */ + +typedef struct +{ + INT NumProgramConfigElements; + UINT BitRate; + UCHAR CopyrightIdPresent; + UCHAR OriginalCopy; + UCHAR Home; + UCHAR BitstreamType; +} CAdifHeader; + +/** + * \brief Parse a ADIF header at the given bitstream and store the parsed data into a given CAdifHeader + * and CProgramConfig struct + * + * \param pAdifHeader pointer to a CAdifHeader structure to hold the parsed ADIF header data. + * \param pPce pointer to a CProgramConfig structure where the last PCE will remain. + * + * \return TRANSPORTDEC_ERROR error code + */ +TRANSPORTDEC_ERROR adifRead_DecodeHeader( + CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs + ); + +#endif /* TPDEC_ADIF_H */ diff --git a/libMpegTPDec/src/tpdec_adts.cpp b/libMpegTPDec/src/tpdec_adts.cpp new file mode 100644 index 00000000..c4556816 --- /dev/null +++ b/libMpegTPDec/src/tpdec_adts.cpp @@ -0,0 +1,388 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: ADTS interface + +******************************************************************************/ + +#include "tpdec_adts.h" + + +#include "FDK_bitstream.h" + + + +void adtsRead_CrcInit(HANDLE_ADTS pAdts) /*!< pointer to adts crc info stucture */ +{ + FDKcrcInit(&pAdts->crcInfo, 0x8005, 0xFFFF, 16); +} + +int adtsRead_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + if (pAdts->bs.protection_absent) { + return 0; + } + + return ( FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits) ); + +} + +void adtsRead_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + if (pAdts->bs.protection_absent == 0) + { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +TRANSPORTDEC_ERROR adtsRead_CrcCheck( HANDLE_ADTS pAdts ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + if (pAdts->bs.protection_absent) + return TRANSPORTDEC_OK; + + crc = FDKcrcGetCRC(&pAdts->crcInfo); + if (crc != pAdts->crcReadValue) + { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} + + + +#define Adts_Length_SyncWord 12 +#define Adts_Length_Id 1 +#define Adts_Length_Layer 2 +#define Adts_Length_ProtectionAbsent 1 +#define Adts_Length_Profile 2 +#define Adts_Length_SamplingFrequencyIndex 4 +#define Adts_Length_PrivateBit 1 +#define Adts_Length_ChannelConfiguration 3 +#define Adts_Length_OriginalCopy 1 +#define Adts_Length_Home 1 +#define Adts_Length_CopyrightIdentificationBit 1 +#define Adts_Length_CopyrightIdentificationStart 1 +#define Adts_Length_FrameLength 13 +#define Adts_Length_BufferFullness 11 +#define Adts_Length_NumberOfRawDataBlocksInFrame 2 +#define Adts_Length_CrcCheck 16 + +TRANSPORTDEC_ERROR adtsRead_DecodeHeader( + HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + const INT ignoreBufferFullness + ) +{ + INT crcReg; + + INT valBits; + INT cmp_buffer_fullness; + int i, adtsHeaderLength; + + STRUCT_ADTS_BS bs; + +#ifdef TP_PCE_ENABLE + CProgramConfig oldPce; + /* Store the old PCE temporarily. Maybe we'll need it later if we + have channelConfig=0 and no PCE in this frame. */ + FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig)); +#endif + + valBits = FDKgetValidBits(hBs); + + /* adts_fixed_header */ + bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); + bs.layer = FDKreadBits(hBs, Adts_Length_Layer); + bs.protection_absent = FDKreadBits(hBs, Adts_Length_ProtectionAbsent); + bs.profile = FDKreadBits(hBs, Adts_Length_Profile); + bs.sample_freq_index = FDKreadBits(hBs, Adts_Length_SamplingFrequencyIndex); + bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); + bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); + bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); + bs.home = FDKreadBits(hBs, Adts_Length_Home); + + /* adts_variable_header */ + bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); + bs.copyright_start = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); + bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); + bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); + bs.num_raw_blocks = FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); + bs.num_pce_bits = 0; + + adtsHeaderLength = ADTS_HEADERLENGTH; + + if (!bs.protection_absent) { + FDKcrcReset(&pAdts->crcInfo); + FDKpushBack(hBs, 56); /* complete fixed and variable header! */ + crcReg = FDKcrcStartReg(&pAdts->crcInfo, hBs, 0); + FDKpushFor(hBs, 56); + } + + if (! bs.protection_absent && bs.num_raw_blocks>0) { + for (i=0; irawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16); + adtsHeaderLength += 16; + } + /* Change raw data blocks to delta values */ + pAdts->rawDataBlockDist[bs.num_raw_blocks] = bs.frame_length - 7 - bs.num_raw_blocks*2 - 2 ; + for (i=bs.num_raw_blocks; i>0; i--) { + pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i-1]; + } + } + + /* adts_error_check */ + if (!bs.protection_absent) + { + USHORT crc_check; + + FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg); + crc_check = FDKreadBits(hBs, Adts_Length_CrcCheck); + adtsHeaderLength += Adts_Length_CrcCheck; + + pAdts->crcReadValue = crc_check; + /* Check header CRC in case of multiple raw data blocks */ + if (bs.num_raw_blocks > 0) { + if (pAdts->crcReadValue != FDKcrcGetCRC(&pAdts->crcInfo)) { + return TRANSPORTDEC_CRC_ERROR; + } + /* Reset CRC for the upcoming raw_data_block() */ + FDKcrcReset(&pAdts->crcInfo); + } + } + + + /* check if valid header */ + if ( + (bs.layer != 0) || // we only support MPEG ADTS + (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz + ) { + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* special treatment of id-bit */ + if ( (bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0) ) + { + /* MPEG-2 decoder cannot play MPEG-4 bitstreams */ + + + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (!ignoreBufferFullness) + { + cmp_buffer_fullness = bs.frame_length*8 + bs.adts_fullness*32*getNumberOfEffectiveChannels(bs.channel_config); + + + /* Evaluate buffer fullness */ + if (bs.adts_fullness != 0x7FF) + { + if (pAdts->BufferFullnesStartFlag) + { + if ( valBits < cmp_buffer_fullness ) + { + /* Condition for start of decoding is not fulfilled */ + + /* The current frame will not be decoded */ + FDKpushBack(hBs, adtsHeaderLength); + + if ( (cmp_buffer_fullness+adtsHeaderLength) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + return TRANSPORTDEC_SYNC_ERROR; + } else { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + else + { + pAdts->BufferFullnesStartFlag = 0; + } + } + } + } + + + /* Get info from ADTS header */ + AudioSpecificConfig_Init(pAsc); + pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); + pAsc->m_samplingFrequencyIndex = bs.sample_freq_index; + pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; + pAsc->m_channelConfiguration = bs.channel_config; + pAsc->m_samplesPerFrame = 1024; + +#ifdef TP_PCE_ENABLE + if (bs.channel_config == 0) + { + int pceBits = 0; + UINT alignAnchor = FDKgetValidBits(hBs); + + if (FDKreadBits(hBs,3) == ID_PCE) { + /* Got luck! Parse the PCE */ + int crcReg; + crcReg = adtsRead_CrcStartReg(pAdts, hBs, 0); + + CProgramConfig_Read(&pAsc->m_progrConfigElement, hBs, alignAnchor); + + adtsRead_CrcEndReg(pAdts, hBs, crcReg); + pceBits = alignAnchor - FDKgetValidBits(hBs); + /* store the number of PCE bits */ + bs.num_pce_bits = pceBits; + } + else { + /* No PCE in this frame! Push back the ID tag bits. */ + FDKpushBack(hBs,3); + + /* Encoders do not have to write a PCE in each frame. + So if we already have a valid PCE we have to use it. */ + if ( oldPce.isValid + && (bs.sample_freq_index == pAdts->bs.sample_freq_index) /* we could compare the complete fixed header (bytes) here! */ + && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ + && (bs.mpeg_id == pAdts->bs.mpeg_id) ) + { /* Restore previous PCE which is still valid */ + FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, sizeof(CProgramConfig)); + } + else if (bs.mpeg_id == 0) { + /* If not it seems that we have a implicit channel configuration. + This mode is not allowed in the context of ISO/IEC 14496-3. + Skip this frame and try the next one. */ + FDKpushFor(hBs, (bs.frame_length<<3) - adtsHeaderLength - 3); + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + /* else { + ISO/IEC 13818-7 implicit channel mapping is allowed. + So just open the box of chocolates to see what we got. + } */ + } + } +#endif /* TP_PCE_ENABLE */ + + /* Copy bit stream data struct to persistent memory now, once we passed all sanity checks above. */ + FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS)); + + return TRANSPORTDEC_OK; +} + +int adtsRead_GetRawDataBlockLength( + HANDLE_ADTS pAdts, + INT blockNum + ) +{ + int length; + + if (pAdts->bs.num_raw_blocks == 0) { + length = (pAdts->bs.frame_length - 7) << 3; /* aac_frame_length subtracted by the header size (7 bytes). */ + if (pAdts->bs.protection_absent == 0) + length -= 16; /* substract 16 bit CRC */ + } else { + if (pAdts->bs.protection_absent) { + length = -1; /* raw data block length is unknown */ + } else { + if (blockNum < 0 || blockNum > 3) { + length = -1; + } + length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16; + } + } + if (blockNum == 0 && length > 0) { + length -= pAdts->bs.num_pce_bits; + } + return length; +} + + diff --git a/libMpegTPDec/src/tpdec_adts.h b/libMpegTPDec/src/tpdec_adts.h new file mode 100644 index 00000000..a3b83a5f --- /dev/null +++ b/libMpegTPDec/src/tpdec_adts.h @@ -0,0 +1,236 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: ADTS interface + +******************************************************************************/ + +#ifndef TPDEC_ADTS_H +#define TPDEC_ADTS_H + +#include "tpdec_lib.h" + + +#define ADTS_SYNCWORD ( 0xfff ) +#define ADTS_SYNCLENGTH ( 12 ) /* in bits */ +#define ADTS_HEADERLENGTH ( 56 ) /* minimum header size in bits */ +#define ADTS_FIXED_HEADERLENGTH ( 28 ) /* in bits */ +#define ADTS_VARIABLE_HEADERLENGTH ( ADTS_HEADERLENGTH - ADTS_FIXED_HEADERLENGTH ) + +#ifdef CHECK_TWO_SYNCS + #define ADTS_MIN_TP_BUF_SIZE ( 8191 + 2 ) +#else + #define ADTS_MIN_TP_BUF_SIZE ( 8191 ) +#endif + +#include "FDK_crc.h" + +typedef struct { + /* ADTS header fields */ + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR channel_config; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + USHORT adts_fullness; + UCHAR num_raw_blocks; + UCHAR num_pce_bits; +} STRUCT_ADTS_BS; + +struct STRUCT_ADTS { + + STRUCT_ADTS_BS bs; + + UCHAR decoderCanDoMpeg4; + UCHAR BufferFullnesStartFlag; + + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + USHORT rawDataBlockDist[4]; /* distance between each raw data block. Not the same as found in the bitstream */ +} ; + +typedef struct STRUCT_ADTS *HANDLE_ADTS; + +/*! + \brief Initialize ADTS CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void adtsRead_CrcInit( HANDLE_ADTS pAdts ); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int adtsRead_CrcStartReg( + HANDLE_ADTS pAdts, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by adtsRead_CrcStartReg() + * + * \return none + */ +void adtsRead_CrcEndReg( + HANDLE_ADTS pAdts, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the bitstream + * Deletes all CRC regions. + * + * \param pAdts ADTS data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR adtsRead_CrcCheck( HANDLE_ADTS pAdts ); + + +/** + * \brief Check if we have a valid ADTS frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is skipped. + * + * \param pAdts ADTS data handle which is filled with parsed ADTS header data + * \param bs handle of bitstream from whom the ADTS header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR adtsRead_DecodeHeader( + HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM bs, + const INT ignoreBufferFullness + ); + +/** + * \brief Get the raw data block length of the given block number. + * + * \param pAdts ADTS data handle + * \param blockNum current raw data block index + * \param pLength pointer to an INT where the length of the given raw data block is stored into + * the returned value might be -1, in which case the raw data block length is unknown. + * + * \return error status + */ +int adtsRead_GetRawDataBlockLength( + HANDLE_ADTS pAdts, + INT blockNum + ); + + +#endif /* TPDEC_ADTS_H */ diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp new file mode 100644 index 00000000..96a1b353 --- /dev/null +++ b/libMpegTPDec/src/tpdec_asc.cpp @@ -0,0 +1,1506 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Daniel Homm + Description: + +******************************************************************************/ + +#include "tpdec_lib.h" +#include "tp_data.h" +#ifdef TP_PCE_ENABLE +#include "FDK_crc.h" +#endif + + +void CProgramConfig_Reset(CProgramConfig *pPce) +{ + pPce->elCounter = 0; +} + +void CProgramConfig_Init(CProgramConfig *pPce) +{ + FDKmemclear(pPce, sizeof(CProgramConfig)); +#ifdef TP_PCE_ENABLE + pPce->SamplingFrequencyIndex = 0xf; +#endif +} + +int CProgramConfig_IsValid ( const CProgramConfig *pPce ) +{ + return ( (pPce->isValid) ? 1 : 0); +} + +#ifdef TP_PCE_ENABLE +#define PCE_HEIGHT_EXT_SYNC ( 0xAC ) + +/* + * Read the extension for height info. + * return 0 if successfull or -1 if the CRC failed. + */ +static +int CProgramConfig_ReadHeightExt( + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + int * const bytesAvailable, + const UINT alignmentAnchor + ) +{ + int err = 0; + FDK_CRCINFO crcInfo; /* CRC state info */ + INT crcReg; + FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); + crcReg = FDKcrcStartReg(&crcInfo, bs, 0); + UINT startAnchor = FDKgetValidBits(bs); + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(bs != NULL); + FDK_ASSERT(bytesAvailable != NULL); + + if ( (startAnchor >= 24) && (*bytesAvailable >= 3) + && (FDKreadBits(bs,8) == PCE_HEIGHT_EXT_SYNC) ) + { + int i; + + for (i=0; i < pPce->NumFrontChannelElements; i++) + { + pPce->FrontElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2); + } + for (i=0; i < pPce->NumSideChannelElements; i++) + { + pPce->SideElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2); + } + for (i=0; i < pPce->NumBackChannelElements; i++) + { + pPce->BackElementHeightInfo[i] = (UCHAR) FDKreadBits(bs,2); + } + FDKbyteAlign(bs, alignmentAnchor); + + FDKcrcEndReg(&crcInfo, bs, crcReg); + if ((USHORT)FDKreadBits(bs,8) != FDKcrcGetCRC(&crcInfo)) { + /* CRC failed */ + err = -1; + } + } + else { + /* No valid extension data found -> restore the initial bitbuffer state */ + FDKpushBack(bs, startAnchor - FDKgetValidBits(bs)); + } + + /* Always report the bytes read. */ + *bytesAvailable -= (startAnchor - FDKgetValidBits(bs)) >> 3; + + return (err); +} + +void CProgramConfig_Read( + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + UINT alignmentAnchor + ) +{ + int i, err = 0; + int commentBytes; + + pPce->NumEffectiveChannels = 0; + pPce->NumChannels = 0; + pPce->ElementInstanceTag = (UCHAR) FDKreadBits(bs,4); + pPce->Profile = (UCHAR) FDKreadBits(bs,2); + pPce->SamplingFrequencyIndex = (UCHAR) FDKreadBits(bs,4); + pPce->NumFrontChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumSideChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumBackChannelElements = (UCHAR) FDKreadBits(bs,4); + pPce->NumLfeChannelElements = (UCHAR) FDKreadBits(bs,2); + pPce->NumAssocDataElements = (UCHAR) FDKreadBits(bs,3); + pPce->NumValidCcElements = (UCHAR) FDKreadBits(bs,4); + + if ((pPce->MonoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->MonoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + } + + if ((pPce->StereoMixdownPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->StereoMixdownElementNumber = (UCHAR) FDKreadBits(bs,4); + } + + if ((pPce->MatrixMixdownIndexPresent = (UCHAR) FDKreadBits(bs,1)) != 0) + { + pPce->MatrixMixdownIndex = (UCHAR) FDKreadBits(bs,2); + pPce->PseudoSurroundEnable = (UCHAR) FDKreadBits(bs,1); + } + + for (i=0; i < pPce->NumFrontChannelElements; i++) + { + pPce->FrontElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->FrontElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; + } + + for (i=0; i < pPce->NumSideChannelElements; i++) + { + pPce->SideElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->SideElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; + } + + for (i=0; i < pPce->NumBackChannelElements; i++) + { + pPce->BackElementIsCpe[i] = (UCHAR) FDKreadBits(bs,1); + pPce->BackElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; + } + + pPce->NumEffectiveChannels = pPce->NumChannels; + + for (i=0; i < pPce->NumLfeChannelElements; i++) + { + pPce->LfeElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + pPce->NumChannels += 1; + } + + for (i=0; i < pPce->NumAssocDataElements; i++) + { + pPce->AssocDataElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + } + + for (i=0; i < pPce->NumValidCcElements; i++) + { + pPce->CcElementIsIndSw[i] = (UCHAR) FDKreadBits(bs,1); + pPce->ValidCcElementTagSelect[i] = (UCHAR) FDKreadBits(bs,4); + } + + FDKbyteAlign(bs, alignmentAnchor); + + pPce->CommentFieldBytes = (UCHAR) FDKreadBits(bs,8); + commentBytes = pPce->CommentFieldBytes; + + /* Search for height info extension and read it if available */ + err = CProgramConfig_ReadHeightExt( pPce, bs, &commentBytes, alignmentAnchor ); + + for (i=0; i < commentBytes; i++) + { + UCHAR text; + + text = (UCHAR)FDKreadBits(bs,8); + + if (i < PC_COMMENTLENGTH) + { + pPce->Comment[i] = text; + } + } + + pPce->isValid = (err) ? 0 : 1; +} + +/* + * Compare two program configurations. + * Returns the result of the comparison: + * -1 - completely different + * 0 - completely equal + * 1 - different but same channel configuration + * 2 - different channel configuration but same number of channels + */ +int CProgramConfig_Compare ( const CProgramConfig * const pPce1, + const CProgramConfig * const pPce2 ) +{ + int result = 0; /* Innocent until proven false. */ + + if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != 0) + { /* Configurations are not completely different. + So look into details and analyse the channel configurations: */ + result = -1; + + if (pPce1->NumChannels == pPce2->NumChannels) + { /* Now the logic changes. We first assume to have the same channel configuration + and then prove if this assumption is true. */ + result = 1; + + /* Front channels */ + if (pPce1->NumFrontChannelElements != pPce2->NumFrontChannelElements) { + result = 2; /* different number of front channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) { + if (pPce1->FrontElementHeightInfo[el] != pPce2->FrontElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of front channels */ + } + } + /* Side channels */ + if (pPce1->NumSideChannelElements != pPce2->NumSideChannelElements) { + result = 2; /* different number of side channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumSideChannelElements; el += 1) { + if (pPce1->SideElementHeightInfo[el] != pPce2->SideElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of side channels */ + } + } + /* Back channels */ + if (pPce1->NumBackChannelElements != pPce2->NumBackChannelElements) { + result = 2; /* different number of back channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumBackChannelElements; el += 1) { + if (pPce1->BackElementHeightInfo[el] != pPce2->BackElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of back channels */ + } + } + /* LFE channels */ + if (pPce1->NumLfeChannelElements != pPce2->NumLfeChannelElements) { + result = 2; /* different number of lfe channels */ + } + /* LFEs are always SCEs so we don't need to count the channels. */ + } + } + + return result; +} + +void CProgramConfig_GetDefault( CProgramConfig *pPce, + const UINT channelConfig ) +{ + FDK_ASSERT(pPce != NULL); + + /* Init PCE */ + CProgramConfig_Init(pPce); + pPce->Profile = 1; /* Set AAC LC because it is the only supported object type. */ + + switch (channelConfig) { + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */ + pPce->NumFrontChannelElements = 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumSideChannelElements = 1; + pPce->SideElementIsCpe[0] = 1; + pPce->NumBackChannelElements = 1; + pPce->BackElementIsCpe[0] = 1; + pPce->NumLfeChannelElements = 1; + pPce->NumChannels = 8; + pPce->NumEffectiveChannels = 7; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 12: /* 3/0/4.1ch surround back */ + pPce->BackElementIsCpe[1] = 1; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + case 11: /* 3/0/3.1ch */ + pPce->NumFrontChannelElements += 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumBackChannelElements += 2; + pPce->BackElementIsCpe[0] = 1; + pPce->BackElementIsCpe[1] += 0; + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 7; + pPce->NumEffectiveChannels += 6; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 14: /* 2/0/0-3/0/2-0.1ch front height */ + pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */ + case 7: /* 5/0/2.1ch front */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[2] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + case 6: /* 3/0/2.1ch */ + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 1; + case 5: /* 3/0/2.0ch */ + case 4: /* 3/0/1.0ch */ + pPce->NumBackChannelElements += 1; + pPce->BackElementIsCpe[0] = (channelConfig>4) ? 1 : 0; + pPce->NumChannels += (channelConfig>4) ? 2 : 1; + pPce->NumEffectiveChannels += (channelConfig>4) ? 2 : 1; + case 3: /* 3/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + case 1: /* 1/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[0] = 0; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 2: /* 2/0/0.ch */ + pPce->NumFrontChannelElements = 1; + pPce->FrontElementIsCpe[0] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + default: + pPce->isValid = 0; /* To be explicit! */ + break; + } + + if (pPce->isValid) { + /* Create valid element instance tags */ + int el, elTagSce = 0, elTagCpe = 0; + + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + pPce->FrontElementTagSelect[el] = (pPce->FrontElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + pPce->SideElementTagSelect[el] = (pPce->SideElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + pPce->BackElementTagSelect[el] = (pPce->BackElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + elTagSce = 0; + for (el = 0; el < pPce->NumLfeChannelElements; el += 1) { + pPce->LfeElementTagSelect[el] = elTagSce++; + } + } +} +#endif /* TP_PCE_ENABLE */ + +/** + * \brief get implicit audio channel type for given channelConfig and MPEG ordered channel index + * \param channelConfig MPEG channelConfiguration from 1 upto 14 + * \param index MPEG channel order index + * \return audio channel type. + */ +static +void getImplicitAudioChannelTypeAndIndex( + AUDIO_CHANNEL_TYPE *chType, + UCHAR *chIndex, + UINT channelConfig, + UINT index + ) +{ + if (index < 3) { + *chType = ACT_FRONT; + *chIndex = index; + } else { + switch (channelConfig) { + case 4: /* SCE, CPE, SCE */ + case 5: /* SCE, CPE, CPE */ + case 6: /* SCE, CPE, CPE, LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 7: /* SCE,CPE,CPE,CPE,LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_FRONT; + *chIndex = index; + break; + case 5: + case 6: + *chType = ACT_BACK; + *chIndex = index - 5; + break; + case 7: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 11: /* SCE,CPE,CPE,SCE,LFE */ + if (index < 6) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 12: /* SCE,CPE,CPE,CPE,LFE */ + if (index < 7) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 14: /* SCE,CPE,CPE,LFE,CPE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + case 6: + case 7: + *chType = ACT_FRONT_TOP; + *chIndex = index - 6; /* handle the top layer independently */ + break; + } + break; + default: + *chType = ACT_NONE; + break; + } + } +} + +int CProgramConfig_LookupElement( + CProgramConfig *pPce, + UINT channelConfig, + const UINT tag, + const UINT channelIdx, + UCHAR chMapping[], + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], + UCHAR *elMapping, + MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType + ) +{ + if (channelConfig > 0) + { + /* Constant channel mapping must have + been set during initialization. */ + if ( elType == ID_SCE + || elType == ID_CPE + || elType == ID_LFE ) + { + *elMapping = pPce->elCounter; + if (elList[pPce->elCounter] != elType) { + /* Not in the list */ + if ( (channelConfig == 2) && (elType == ID_SCE) ) + { /* This scenario occurs with HE-AAC v2 streams of buggy encoders. + Due to other decoder implementations decoding of these kind of streams is desired. */ + channelConfig = 1; + } else { + return 0; + } + } + /* Assume all front channels */ + getImplicitAudioChannelTypeAndIndex(&chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); + if (elType == ID_CPE) { + chType[channelIdx+1] = chType[channelIdx]; + chIndex[channelIdx+1] = chIndex[channelIdx]+1; + } + pPce->elCounter++; + } + /* Accept all non-channel elements, too. */ + return 1; + } + else + { +#ifdef TP_PCE_ENABLE + if (!pPce->isValid) +#endif /* TP_PCE_ENABLE */ + { + /* Implicit channel mapping. */ + if ( elType == ID_SCE + || elType == ID_CPE + || elType == ID_LFE ) + { + /* Store all channel element IDs */ + elList[pPce->elCounter] = elType; + *elMapping = pPce->elCounter++; + } + } +#ifdef TP_PCE_ENABLE + else { + /* Accept the additional channel(s), only if the tag is in the lists */ + int isCpe = 0, i; + /* Element counter */ + int ec[PC_NUM_HEIGHT_LAYER] = {0}; + /* Channel counters */ + int cc[PC_NUM_HEIGHT_LAYER] = {0}; + int fc[PC_NUM_HEIGHT_LAYER] = {0}; + int sc[PC_NUM_HEIGHT_LAYER] = {0}; + int bc[PC_NUM_HEIGHT_LAYER] = {0}; + int lc = 0;; + + /* General MPEG (PCE) composition rules: + - Over all: + + - Within each height layer: + + - Exception: + The LFE channels have no height info and thus they are arranged at the very + end of the normal height layer channels. + */ + + switch (elType) + { + case ID_CPE: + isCpe = 1; + case ID_SCE: + /* search in front channels */ + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + if (isCpe == pPce->FrontElementIsCpe[i] && pPce->FrontElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_FRONT); + for (h = heightLayer-1; h >= 0; h-=1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el+=1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el+=1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = fc[heightLayer]; + if (isCpe) { + chMapping[chIdx+1] = channelIdx+1; + chType[chIdx+1] = aChType; + chIndex[chIdx+1] = fc[heightLayer]+1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->FrontElementIsCpe[i]) { + cc[heightLayer] += 2; + fc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + fc[heightLayer] += 1; + } + } + /* search in side channels */ + for (i = 0; i < pPce->NumSideChannelElements; i++) { + int heightLayer = pPce->SideElementHeightInfo[i]; + if (isCpe == pPce->SideElementIsCpe[i] && pPce->SideElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_SIDE); + for (h = heightLayer-1; h >= 0; h-=1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el+=1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el+=1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* LFE channels belong to the normal height layer */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = sc[heightLayer]; + if (isCpe) { + chMapping[chIdx+1] = channelIdx+1; + chType[chIdx+1] = aChType; + chIndex[chIdx+1] = sc[heightLayer]+1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->SideElementIsCpe[i]) { + cc[heightLayer] += 2; + sc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + sc[heightLayer] += 1; + } + } + /* search in back channels */ + for (i = 0; i < pPce->NumBackChannelElements; i++) { + int heightLayer = pPce->BackElementHeightInfo[i]; + if (isCpe == pPce->BackElementIsCpe[i] && pPce->BackElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = (AUDIO_CHANNEL_TYPE)((heightLayer<<4) | ACT_BACK); + for (h = heightLayer-1; h >= 0; h-=1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el+=1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el+=1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el+=1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = bc[heightLayer]; + if (isCpe) { + chMapping[chIdx+1] = channelIdx+1; + chType[chIdx+1] = aChType; + chIndex[chIdx+1] = bc[heightLayer]+1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->BackElementIsCpe[i]) { + cc[heightLayer] += 2; + bc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + bc[heightLayer] += 1; + } + } + break; + + case ID_LFE: + { /* Unfortunately we have to go through all normal height + layer elements to get the position of the LFE channels. + Start with counting the front channels/elements at normal height */ + for (i = 0; i < pPce->NumFrontChannelElements; i+=1) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; + } + /* Count side channels/elements at normal height */ + for (i = 0; i < pPce->NumSideChannelElements; i+=1) { + int heightLayer = pPce->SideElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; + } + /* Count back channels/elements at normal height */ + for (i = 0; i < pPce->NumBackChannelElements; i+=1) { + int heightLayer = pPce->BackElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; + } + + /* search in lfe channels */ + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + int elIdx = ec[0]; /* LFE channels belong to the normal height layer */ + int chIdx = cc[0]; + if ( pPce->LfeElementTagSelect[i] == tag ) { + chMapping[chIdx] = channelIdx; + *elMapping = elIdx; + chType[chIdx] = ACT_LFE; + chIndex[chIdx] = lc; + return 1; + } + ec[0] += 1; + cc[0] += 1; + lc += 1; + } + } break; + + /* Non audio elements */ + case ID_CCE: + /* search in cce channels */ + for (i = 0; i < pPce->NumValidCcElements; i++) { + if (pPce->ValidCcElementTagSelect[i] == tag) { + return 1; + } + } + break; + case ID_DSE: + /* search associated data elements */ + for (i = 0; i < pPce->NumAssocDataElements; i++) { + if (pPce->AssocDataElementTagSelect[i] == tag) { + return 1; + } + } + break; + default: + return 0; + } + return 0; /* not found in any list */ + } +#endif /* TP_PCE_ENABLE */ + } + + return 1; +} + +#ifdef TP_PCE_ENABLE +int CProgramConfig_GetElementTable( + const CProgramConfig *pPce, + MP4_ELEMENT_ID elList[], + const INT elListSize, + UCHAR *pChMapIdx + ) +{ + int i, el = 0; + + FDK_ASSERT(elList != NULL); + FDK_ASSERT(pChMapIdx != NULL); + + *pChMapIdx = 0; + + if ( elListSize + < pPce->NumFrontChannelElements + pPce->NumSideChannelElements + pPce->NumBackChannelElements + pPce->NumLfeChannelElements + ) + { + return 0; + } + + for (i=0; i < pPce->NumFrontChannelElements; i++) + { + elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumSideChannelElements; i++) + { + elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumBackChannelElements; i++) + { + elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i=0; i < pPce->NumLfeChannelElements; i++) + { + elList[el++] = ID_LFE; + } + + + /* Find an corresponding channel configuration if possible */ + switch (pPce->NumChannels) { + case 1: case 2: case 3: case 4: case 5: case 6: + /* One and two channels have no alternatives. The other ones are mapped directly to the + corresponding channel config. Because of legacy reasons or for lack of alternative mappings. */ + *pChMapIdx = pPce->NumChannels; + break; + case 7: + { + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, 11); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) ? 11 : 0; + /* If compare result is 0 or 1 we can be sure that it is channel config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } + break; + case 8: + { /* Try the four possible 7.1ch configurations. One after the other. */ + UCHAR testCfg[4] = { 32, 14, 12, 7}; + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + for (i=0; i<4; i+=1) { + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, testCfg[i]); + /* ... and compare it with the given one. */ + if (!(CProgramConfig_Compare(pPce, tmpPce)&0xE)) { + /* If the compare result is 0 or 1 than the two channel configurations match. */ + /* Explicit mapping of 7.1 side channel configuration to 7.1 rear channel mapping. */ + *pChMapIdx = (testCfg[i]==32) ? 12 : testCfg[i]; + } + } + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } + break; + default: + /* The PCE does not match any predefined channel configuration. */ + *pChMapIdx = 0; + break; + } + + return el; +} +#endif + +static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) +{ + int tmp = 0; + + tmp = FDKreadBits(bs,5); + if (tmp == AOT_ESCAPE) { + int tmp2 = FDKreadBits(bs,6); + tmp = 32 + tmp2; + } + + return (AUDIO_OBJECT_TYPE)tmp; +} + +static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) +{ + INT sampleRate; + int idx; + + idx = FDKreadBits(bs, nBits); + if( idx == (1<m_frameLengthFlag = FDKreadBits(bs,1); + + self->m_dependsOnCoreCoder = FDKreadBits(bs,1); + + if( self->m_dependsOnCoreCoder ) + self->m_coreCoderDelay = FDKreadBits(bs,14); + + self->m_extensionFlag = FDKreadBits(bs,1); + + if( asc->m_channelConfiguration == 0 ) { + CProgramConfig_Read(&asc->m_progrConfigElement, bs, ascStartAnchor); + } + + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + self->m_layer = FDKreadBits(bs,3); + } + + if (self->m_extensionFlag) { + if (asc->m_aot == AOT_ER_BSAC) { + self->m_numOfSubFrame = FDKreadBits(bs,5); + self->m_layerLength = FDKreadBits(bs,11); + } + + if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || + (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) + { + asc->m_vcb11Flag = FDKreadBits(bs,1); /* aacSectionDataResilienceFlag */ + asc->m_rvlcFlag = FDKreadBits(bs,1); /* aacScalefactorDataResilienceFlag */ + asc->m_hcrFlag = FDKreadBits(bs,1); /* aacSpectralDataResilienceFlag */ + } + + self->m_extensionFlag3 = FDKreadBits(bs,1); + + } + return (ErrorStatus); +} +#endif /* TP_GA_ENABLE */ + + + + + +#ifdef TP_ELD_ENABLE + +static INT ld_sbr_header( const CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb ) +{ + const int channelConfiguration = asc->m_channelConfiguration; + int i = 0; + INT error = 0; + + if (channelConfiguration == 2) { + error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + } else { + error = cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); + } + + switch ( channelConfiguration ) { + case 14: + case 12: + case 7: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + case 6: + case 5: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + case 3: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + break; + + case 11: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + case 4: + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_CPE, i++); + error |= cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, asc->m_extensionSamplingFrequency, asc->m_samplesPerFrame, AOT_ER_AAC_ELD, ID_SCE, i++); + break; + } + + return error; +} + +static +TRANSPORTDEC_ERROR EldSpecificConfig_Parse( + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig; + ASC_ELD_EXT_TYPE eldExtType; + int eldExtLen, len, cnt; + + FDKmemclear(esc, sizeof(CSEldSpecificConfig)); + + esc->m_frameLengthFlag = FDKreadBits(hBs, 1 ); + if (esc->m_frameLengthFlag) { + asc->m_samplesPerFrame = 480; + } else { + asc->m_samplesPerFrame = 512; + } + + asc->m_vcb11Flag = FDKreadBits(hBs, 1 ); + asc->m_rvlcFlag = FDKreadBits(hBs, 1 ); + asc->m_hcrFlag = FDKreadBits(hBs, 1 ); + + esc->m_sbrPresentFlag = FDKreadBits(hBs, 1 ); + + if (esc->m_sbrPresentFlag == 1) { + esc->m_sbrSamplingRate = FDKreadBits(hBs, 1 ); /* 0: single rate, 1: dual rate */ + esc->m_sbrCrcFlag = FDKreadBits(hBs, 1 ); + + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency << esc->m_sbrSamplingRate; + + if (cb->cbSbr != NULL){ + if ( 0 != ld_sbr_header(asc, hBs, cb) ) { + return TRANSPORTDEC_PARSE_ERROR; + } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } + esc->m_useLdQmfTimeAlign = 0; + + /* new ELD syntax */ + /* parse ExtTypeConfigData */ + while ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4 )) != ELDEXT_TERM) { + eldExtLen = len = FDKreadBits(hBs, 4 ); + if ( len == 0xf ) { + len = FDKreadBits(hBs, 8 ); + eldExtLen += len; + + if ( len == 0xff ) { + len = FDKreadBits(hBs, 16 ); + eldExtLen += len; + } + } + + switch (eldExtType) { + default: + for(cnt=0; cnt= 11) + { + lastAscExt = ascExtId; + ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); + bitsAvailable -= 11; + + switch (ascExtId) { + case ASCEXT_SBR: /* 0x2b7 */ + if ( (self->m_extensionAudioObjectType != AOT_SBR) && (bitsAvailable >= 5) ) { + self->m_extensionAudioObjectType = getAOT(bs); + + if ( (self->m_extensionAudioObjectType == AOT_SBR) + || (self->m_extensionAudioObjectType == AOT_ER_BSAC) ) + { /* Get SBR extension configuration */ + self->m_sbrPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + + if ( self->m_sbrPresentFlag == 1 ) { + self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + + if ((INT)self->m_extensionSamplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + if ( self->m_extensionAudioObjectType == AOT_ER_BSAC ) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + bitsAvailable -= 4; + } + } + /* Update counter because of variable length fields (AOT and sampling rate) */ + bitsAvailable = (INT)FDKgetValidBits(bs); + } + break; + case ASCEXT_PS: /* 0x548 */ + if ( (lastAscExt == ASCEXT_SBR) + && (self->m_extensionAudioObjectType == AOT_SBR) + && (bitsAvailable > 0) ) + { /* Get PS extension configuration */ + self->m_psPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + } + break; + default: + /* Just ignore anything. */ + return TRANSPORTDEC_OK; + } + } + + return TRANSPORTDEC_OK; +} + +/* + * API Functions + */ + +void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) +{ + FDKmemclear(asc, sizeof(CSAudioSpecificConfig)); + + /* Init all values that should not be zero. */ + asc->m_aot = AOT_NONE; + asc->m_samplingFrequencyIndex = 0xf; + asc->m_epConfig = -1; + asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; +#ifdef TP_PCE_ENABLE + CProgramConfig_Init(&asc->m_progrConfigElement); +#endif +} + +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *self, + HANDLE_FDK_BITSTREAM bs, + int fExplicitBackwardCompatible, + CSTpCallBacks *cb + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT ascStartAnchor = FDKgetValidBits(bs); + int frameLengthFlag = -1; + + AudioSpecificConfig_Init(self); + + self->m_aot = getAOT(bs); + self->m_samplingFrequency = getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); + if (self->m_samplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + self->m_channelConfiguration = FDKreadBits(bs,4); + + /* SBR extension ( explicit non-backwards compatible mode ) */ + self->m_sbrPresentFlag = 0; + self->m_psPresentFlag = 0; + + if ( self->m_aot == AOT_SBR || self->m_aot == AOT_PS ) { + self->m_extensionAudioObjectType = AOT_SBR; + + self->m_sbrPresentFlag = 1; + if ( self->m_aot == AOT_PS ) { + self->m_psPresentFlag = 1; + } + + self->m_extensionSamplingFrequency = getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + self->m_aot = getAOT(bs); + + } else { + self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + } + + /* Parse whatever specific configs */ + switch (self->m_aot) + { +#ifdef TP_GA_ENABLE + case AOT_AAC_LC: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, self, bs, ascStartAnchor)) != TRANSPORTDEC_OK ) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; + break; +#endif /* TP_GA_ENABLE */ + case AOT_MPEGS: + if (cb->cbSsc != NULL) { + cb->cbSsc( + cb->cbSscData, + bs, + self->m_aot, + self->m_samplingFrequency, + 1, + 0 /* don't know the length */ + ); + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + break; +#ifdef TP_ELD_ENABLE + case AOT_ER_AAC_ELD: + if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK ) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; + self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; + self->m_extensionSamplingFrequency = (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate+1) * self->m_samplingFrequency; + break; +#endif /* TP_ELD_ENABLE */ + + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + break; + } + + /* Frame length */ + switch (self->m_aot) + { +#if defined(TP_GA_ENABLE) || defined(TP_USAC_ENABLE) + case AOT_AAC_LC: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + /*case AOT_USAC:*/ + if (!frameLengthFlag) + self->m_samplesPerFrame = 1024; + else + self->m_samplesPerFrame = 960; + break; +#endif /* TP_GA_ENABLE */ +#if defined(TP_GA_ENABLE) + case AOT_ER_AAC_LD: + if (!frameLengthFlag) + self->m_samplesPerFrame = 512; + else + self->m_samplesPerFrame = 480; + break; +#endif /* defined(TP_GA_ENABLE) */ + default: + break; + } + + switch (self->m_aot) + { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_SCAL: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_BSAC: + self->m_epConfig = FDKreadBits(bs,2); + + if (self->m_epConfig > 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; + } + break; + default: + break; + } + + if (fExplicitBackwardCompatible) { + ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( + CSAudioSpecificConfig *self, + HANDLE_FDK_BITSTREAM bs + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + AudioSpecificConfig_Init(self); + + if ((INT)FDKgetValidBits(bs) < 20) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + else { + /* DRM - Audio information data entity - type 9 + - Short Id 2 bits + - Stream Id 2 bits + - audio coding 2 bits + - SBR flag 1 bit + - audio mode 2 bits + - audio sampling rate 3 bits + - text flag 1 bit + - enhancement flag 1 bit + - coder field 5 bits + - rfa 1 bit */ + + int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; + + /* Read the SDC field */ + FDKreadBits(bs,4); /* Short and Stream Id */ + + audioCoding = FDKreadBits(bs, 2); + sbrFlag = FDKreadBits(bs, 1); + audioMode = FDKreadBits(bs, 2); + cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ + + FDKreadBits(bs, 2); /* Text and enhancement flag */ + coderField = FDKreadBits(bs, 5); + FDKreadBits(bs, 1); /* rfa */ + + /* Evaluate configuration and fill the ASC */ + switch (cSamplingFreq) { + case 0: /* 8 kHz */ + sfIdx = 11; + break; + case 1: /* 12 kHz */ + sfIdx = 9; + break; + case 2: /* 16 kHz */ + sfIdx = 8; + break; + case 3: /* 24 kHz */ + sfIdx = 6; + break; + case 5: /* 48 kHz */ + sfIdx = 3; + break; + case 4: /* reserved */ + case 6: /* reserved */ + case 7: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + + self->m_samplingFrequencyIndex = sfIdx; + self->m_samplingFrequency = SamplingRateTable[sfIdx]; + + if ( sbrFlag ) { + UINT i; + int tmp = -1; + self->m_sbrPresentFlag = 1; + self->m_extensionAudioObjectType = AOT_SBR; + self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; + for (i=0; i<(sizeof(SamplingRateTable)/sizeof(SamplingRateTable[0])); i++){ + if (SamplingRateTable[i] == self->m_extensionSamplingFrequency){ + tmp = i; + break; + } + } + self->m_extensionSamplingFrequencyIndex = tmp; + } + + switch (audioCoding) { + case 0: /* AAC */ + self->m_aot = AOT_DRM_AAC ; /* Set pseudo AOT for Drm AAC */ + + switch (audioMode) { + case 1: /* parametric stereo */ + self->m_psPresentFlag = 1; + case 0: /* mono */ + self->m_channelConfiguration = 1; + break; + case 2: /* stereo */ + self->m_channelConfiguration = 2; + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + self->m_vcb11Flag = 1; + self->m_hcrFlag = 1; + self->m_samplesPerFrame = 960; + self->m_epConfig = 1; + break; + case 1: /* CELP */ + self->m_aot = AOT_ER_CELP; + self->m_channelConfiguration = 1; + break; + case 2: /* HVXC */ + self->m_aot = AOT_ER_HVXC; + self->m_channelConfiguration = 1; + break; + case 3: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + self->m_aot = AOT_NONE; + break; + } + + if (self->m_psPresentFlag && !self->m_sbrPresentFlag) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + +bail: + return (ErrorStatus); +} + diff --git a/libMpegTPDec/src/tpdec_drm.cpp b/libMpegTPDec/src/tpdec_drm.cpp new file mode 100644 index 00000000..df319e51 --- /dev/null +++ b/libMpegTPDec/src/tpdec_drm.cpp @@ -0,0 +1,146 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: DRM transport stuff + +******************************************************************************/ + +#include "tpdec_drm.h" + + +#include "FDK_bitstream.h" + + + +void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcInit(&pDrm->crcInfo, 0x001d, 0xFFFF, 8); +} + +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, /*!< pointer to drm stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcReset(&pDrm->crcInfo); + + pDrm->crcReadValue = FDKreadBits(hBs, 8); + + return ( FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits) ); + +} + +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcEndReg(&pDrm->crcInfo, hBs, reg); +} + +TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF; + if (crc != pDrm->crcReadValue) + { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} + + diff --git a/libMpegTPDec/src/tpdec_drm.h b/libMpegTPDec/src/tpdec_drm.h new file mode 100644 index 00000000..2161b4ca --- /dev/null +++ b/libMpegTPDec/src/tpdec_drm.h @@ -0,0 +1,194 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Josef Hoepfl + Description: DRM interface + +******************************************************************************/ + +#ifndef TPDEC_DRM_H +#define TPDEC_DRM_H + +#include "tpdec_lib.h" + + +#include "FDK_crc.h" + +typedef struct { + + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + +} STRUCT_DRM; + +typedef STRUCT_DRM *HANDLE_DRM; + +/*! + \brief Initialize DRM CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void drmRead_CrcInit( HANDLE_DRM pDrm ); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by drmRead_CrcStartReg() + * + * \return none + */ +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the bitstream + * Deletes all CRC regions. + * + * \param pDrm DRM data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR drmRead_CrcCheck( HANDLE_DRM pDrm ); + +/** + * \brief Check if we have a valid DRM frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is skipped. + * + * \param pDrm DRM data handle which is filled with parsed DRM header data + * \param bs handle of bitstream from whom the DRM header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR drmRead_DecodeHeader( + HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM bs + ); + +/** + * \brief Parse a Drm specific SDC audio config from a given bitstream handle. + * + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs ); + + + +#endif /* TPDEC_DRM_H */ diff --git a/libMpegTPDec/src/tpdec_latm.cpp b/libMpegTPDec/src/tpdec_latm.cpp new file mode 100644 index 00000000..5710d776 --- /dev/null +++ b/libMpegTPDec/src/tpdec_latm.cpp @@ -0,0 +1,433 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Daniel Homm + Description: + +******************************************************************************/ + +#include "tpdec_latm.h" + + +#include "FDK_bitstream.h" + + +#define TPDEC_TRACKINDEX(p,l) (2*(p) + (l)) + +static +UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) +{ + UCHAR bytesForValue = 0, tmp = 0; + int value = 0; + + bytesForValue = (UCHAR) FDKreadBits(bs,2); + + for (UINT i=0; i<=bytesForValue; i++) { + value <<= 8; + tmp = (UCHAR) FDKreadBits(bs,8); + value += tmp; + } + + return value; +} + + +static +TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( + HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, + int m_muxConfigPresent, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound + ) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + if (m_muxConfigPresent) { + pLatmDemux->m_useSameStreamMux = FDKreadBits(bs,1); + + if (!pLatmDemux->m_useSameStreamMux) { + if ((ErrorStatus = CLatmDemux_ReadStreamMuxConfig(bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound))) { + return (ErrorStatus); + } + } + } + + /* If there was no configuration read, its not possible to parse PayloadLengthInfo below. */ + if (! *pfConfigFound) { + return TRANSPORTDEC_SYNC_ERROR; + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + /* Do only once per call, because parsing and decoding is done in-line. */ + if ((ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs,pLatmDemux))) { + return (ErrorStatus); + } + } else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_Read( + HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, + TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness + ) +{ + UINT cntBits; + UINT cmpBufferFullness; + UINT audioMuxLengthBytesLast = 0; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + cntBits = FDKgetValidBits(bs); + + if ((INT)cntBits < MIN_LATM_HEADERLENGTH) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + if ((ErrorStatus = CLatmDemux_ReadAudioMuxElement(bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), pTpDecCallbacks, pAsc, pfConfigFound))) + return (ErrorStatus); + + if (!ignoreBufferFullness) + { + cmpBufferFullness = 24+audioMuxLengthBytesLast*8 + + pLatmDemux->m_linfo[0][0].m_bufferFullness* pAsc[TPDEC_TRACKINDEX(0,0)].m_channelConfiguration*32; + + /* evaluate buffer fullness */ + + if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) + { + if (!pLatmDemux->BufferFullnessAchieved) + { + if (cntBits < cmpBufferFullness) + { + /* condition for start of decoding is not fulfilled */ + + /* the current frame will not be decoded */ + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + else + { + pLatmDemux->BufferFullnessAchieved = 1; + } + } + } + } + + return (ErrorStatus); +} + + +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int * pfConfigFound + ) +{ + LATM_LAYER_INFO *p_linfo = NULL; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs,1); + + if (pLatmDemux->m_AudioMuxVersion == 0) { + pLatmDemux->m_AudioMuxVersionA = 0; + } else { + pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs,1); + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs); + } + pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs,1); + pLatmDemux->m_noSubFrames = FDKreadBits(bs,6) + 1; + pLatmDemux->m_numProgram = FDKreadBits(bs,4) + 1; + + if (pLatmDemux->m_numProgram > 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + int idCnt = 0; + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + pLatmDemux->m_numLayer = FDKreadBits(bs,3) + 1; + if (pLatmDemux->m_numLayer > 2) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + for (UINT lay = 0; lay < pLatmDemux->m_numLayer; lay++) { + p_linfo = &pLatmDemux->m_linfo[prog][lay]; + + p_linfo->m_streamID = idCnt++; + p_linfo->m_frameLengthInBits = 0; + + if( (prog == 0) && (lay == 0) ) { + pLatmDemux->m_useSameConfig = 0; + } else { + pLatmDemux->m_useSameConfig = FDKreadBits(bs,1); + } + + if (pLatmDemux->m_useSameConfig) { + if (lay > 1) { + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog,lay)], &pAsc[TPDEC_TRACKINDEX(prog,lay-1)], sizeof(CSAudioSpecificConfig)); + } else { + return TRANSPORTDEC_PARSE_ERROR; + } + } else { + if (pLatmDemux->m_AudioMuxVersion == 1) + { + FDK_BITSTREAM tmpBs; + UINT ascStartPos, ascLen=0; + + ascLen = CLatmDemux_GetValue(bs); + ascStartPos = FDKgetValidBits(bs); + tmpBs = *bs; + FDKsyncCache(&tmpBs); + tmpBs.hBitBuf.ValidBits = ascLen; + + /* Read ASC */ + if ((ErrorStatus = AudioSpecificConfig_Parse(&pAsc[TPDEC_TRACKINDEX(prog,lay)], &tmpBs, 1, pTpDecCallbacks))) { + return (ErrorStatus); + } + *pfConfigFound = 1; + + /* The field p_linfo->m_ascLen could be wrong, so check if */ + if ( 0 > (INT)FDKgetValidBits(&tmpBs)) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(bs, ascLen); /* position bitstream after ASC */ + } + else { + /* Read ASC */ + if ((ErrorStatus = AudioSpecificConfig_Parse(&pAsc[TPDEC_TRACKINDEX(prog,lay)], bs, 0, pTpDecCallbacks))) { + return (ErrorStatus); + } + } + { + int cbError; + + cbError = pTpDecCallbacks->cbUpdateConfig(pTpDecCallbacks->cbUpdateConfigData, &pAsc[TPDEC_TRACKINDEX(prog,lay)]); + if (cbError != 0) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + *pfConfigFound = 1; + } + } + + p_linfo->m_frameLengthType = FDKreadBits(bs,3); + switch( p_linfo->m_frameLengthType ) { + case 0: + p_linfo->m_bufferFullness = FDKreadBits(bs,8); + + if (!pLatmDemux->m_allStreamsSameTimeFraming) { + if ((lay > 0) && (pAsc[TPDEC_TRACKINDEX(prog,lay)].m_aot == AOT_AAC_SCAL || pAsc[TPDEC_TRACKINDEX(prog,lay)].m_aot == AOT_ER_AAC_SCAL)) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } + break; + case 1: + /* frameLength = FDKreadBits(bs,9); */ + case 3: + case 4: + case 5: + /* CELP */ + case 6: + case 7: + /* HVXC */ + default: + return TRANSPORTDEC_PARSE_ERROR; //_LATM_INVALIDFRAMELENGTHTYPE; + + } /* switch framelengthtype*/ + + } /* layer loop */ + } /* prog loop */ + + pLatmDemux->m_otherDataPresent = FDKreadBits(bs,1); + pLatmDemux->m_otherDataLength = 0; + + if (pLatmDemux->m_otherDataPresent) { + int otherDataLenEsc = 0; + do { + pLatmDemux->m_otherDataLength <<= 8; // *= 256 + otherDataLenEsc = FDKreadBits(bs,1); + pLatmDemux->m_otherDataLength += FDKreadBits(bs,8); + } while (otherDataLenEsc); + } + + pLatmDemux->m_crcCheckPresent = FDKreadBits(bs,1); + pLatmDemux->m_crcCheckSum = 0; + + if (pLatmDemux->m_crcCheckPresent) { + pLatmDemux->m_crcCheckSum = FDKreadBits(bs,8); + } + + } + else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux) +{ + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + int totalPayloadBits = 0; + + if( pLatmDemux->m_allStreamsSameTimeFraming == 1 ) { + for (UINT prog=0; progm_numProgram; prog++ ) { + for (UINT lay=0; laym_numLayer; lay++ ) { + LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay]; + + switch (p_linfo->m_frameLengthType ) { + case 0: + p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs); + totalPayloadBits += p_linfo->m_frameLengthInBits; + break; + case 3: + case 5: + case 7: + default: + return TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; + } + } + } + } + else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; //AAC_DEC_LATM_TIMEFRAMING; + } + if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes*8) { + return TRANSPORTDEC_PARSE_ERROR; + } + return (ErrorStatus); +} + +int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) +{ + UCHAR endFlag; + int len = 0; + + do { + UCHAR tmp = (UCHAR) FDKreadBits(bs,8); + endFlag = (tmp < 255); + + len += tmp; + + } while( endFlag == 0 ); + + len <<= 3; /* convert from bytes to bits */ + + return len; +} + +int CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux) +{ + return pLatmDemux->m_linfo[0][0].m_frameLengthInBits; +} + +int CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) +{ + return pLatmDemux->m_otherDataPresent ? 1 : 0; +} + +int CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) +{ + return pLatmDemux->m_otherDataLength; +} + +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) +{ + return pLatmDemux->m_noSubFrames; +} + diff --git a/libMpegTPDec/src/tpdec_latm.h b/libMpegTPDec/src/tpdec_latm.h new file mode 100644 index 00000000..6dc13e86 --- /dev/null +++ b/libMpegTPDec/src/tpdec_latm.h @@ -0,0 +1,176 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Daniel Homm + Description: + +******************************************************************************/ + +#ifndef LATM_DEMUX_H +#define LATM_DEMUX_H + +#include "tpdec_lib.h" + + +#include "FDK_bitstream.h" + +#define MIN_LATM_HEADERLENGTH 9 +#define MIN_LOAS_HEADERLENGTH MIN_LATM_HEADERLENGTH + 24 /* both in bits */ + #define MIN_TP_BUF_SIZE_LOAS ( 8194 ) + +enum { + LATM_MAX_PROG = 1, + LATM_MAX_LAYER = 2, + LATM_MAX_VAR_CHUNKS=16, + LATM_MAX_ID=16 +}; + +typedef struct { + UINT m_frameLengthType; + UINT m_bufferFullness; + UINT m_streamID; + UINT m_frameLengthInBits; +} LATM_LAYER_INFO; + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROG][LATM_MAX_LAYER]; + UINT m_taraBufferFullness; + UINT m_otherDataLength; + UINT m_audioMuxLengthBytes; /* Length of LOAS payload */ + + UCHAR m_useSameStreamMux; + UCHAR m_AudioMuxVersion; + UCHAR m_AudioMuxVersionA; + UCHAR m_allStreamsSameTimeFraming; + UCHAR m_noSubFrames; + UCHAR m_numProgram; + UCHAR m_numLayer; + UCHAR m_useSameConfig; + + UCHAR m_otherDataPresent; + UCHAR m_crcCheckPresent; + UCHAR m_crcCheckSum; + + SCHAR BufferFullnessAchieved; +} CLatmDemux; + +int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs); + +TRANSPORTDEC_ERROR CLatmDemux_Read( + HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, + TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness + ); + +/** + * \brief Read StreamMuxConfig + * \param bs bit stream handle as data source + * \param pLatmDemux pointer to CLatmDemux struct of current LATM context + * \param pTpDecCallbacks Call back structure for configuration callbacks + * \param pAsc pointer to a ASC for configuration storage + * \param pfConfigFound pointer to a flag which is set to 1 if a configuration was found and processed successfully + * \return error code + */ +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int * pfConfigFound + ); + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux); + +int CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux); +int CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux); +int CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux); + + +#endif /* LATM_DEMUX_H */ diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp new file mode 100644 index 00000000..24f755b7 --- /dev/null +++ b/libMpegTPDec/src/tpdec_lib.cpp @@ -0,0 +1,1354 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** MPEG-4 Transport Decoder ************************ + + Author(s): Manuel Jander + Description: MPEG Transport decoder + +******************************************************************************/ + +#include "tpdec_lib.h" + +/* library version */ +#include "version" + + +#include "tp_data.h" + +#include "tpdec_adts.h" + +#include "tpdec_adif.h" + +#include "tpdec_latm.h" + +#include "tpdec_drm.h" + + +#define MODULE_NAME "transportDec" + +typedef union { + STRUCT_ADTS adts; + + CAdifHeader adif; + + CLatmDemux latm; + + STRUCT_DRM drm; + +} transportdec_parser_t; + +struct TRANSPORTDEC +{ + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */ + + CSTpCallBacks callbacks; /*!< Struct holding callback and its data */ + + FDK_BITSTREAM bitStream[2]; /* Bitstream reader */ + UCHAR *bsBuffer; /* Internal bitstreamd data buffer (unallocated in case of TT_MP4_RAWPACKETS) */ + + transportdec_parser_t parser; /* Format specific parser structs. */ + + CSAudioSpecificConfig asc[(1*2)]; /* Audio specific config from the last config found. */ + UINT globalFramePos; /* Global transport frame reference bit position. */ + UINT accessUnitAnchor[2]; /* Current access unit start bit position. */ + INT auLength[2]; /* Length of current access unit. */ + INT numberOfRawDataBlocks; /* Current number of raw data blocks contained remaining from the current transport frame. */ + UINT avgBitRate; /* Average bit rate used for frame loss estimation. */ + UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame loss estimation */ + INT remainder; /* Reminder in division during lost access unit estimation. */ + INT missingAccessUnits; /* Estimated missing access units. */ + UINT burstPeriod; /* Data burst period in mili seconds. */ + UINT holdOffFrames; /* Amount of frames that were already hold off due to buffer fullness condition not being met. */ + UINT flags; /* Flags. */ +}; + +/* Flag bitmasks for "flags" member of struct TRANSPORTDEC */ +#define TPDEC_SYNCOK 1 +#define TPDEC_MINIMIZE_DELAY 2 +#define TPDEC_IGNORE_BUFFERFULLNESS 4 +#define TPDEC_EARLY_CONFIG 8 +#define TPDEC_LOST_FRAMES_PENDING 16 +#define TPDEC_CONFIG_FOUND 32 + +C_ALLOC_MEM(Ram_TransportDecoder, TRANSPORTDEC, 1) +C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, TRANSPORTDEC_INBUF_SIZE) + + + + +HANDLE_TRANSPORTDEC transportDec_Open( const TRANSPORT_TYPE transportFmt, const UINT flags) +{ + HANDLE_TRANSPORTDEC hInput; + + hInput = GetRam_TransportDecoder(0); + if ( hInput == NULL ) { + return NULL; + } + + /* Init transportDec struct. */ + hInput->transportFmt = transportFmt; + + switch (transportFmt) { + + case TT_MP4_ADIF: + break; + + case TT_MP4_ADTS: + if (flags & TP_FLAG_MPEG4) + hInput->parser.adts.decoderCanDoMpeg4 = 1; + else + hInput->parser.adts.decoderCanDoMpeg4 = 0; + adtsRead_CrcInit(&hInput->parser.adts); + hInput->parser.adts.BufferFullnesStartFlag = 1; + hInput->numberOfRawDataBlocks = 0; + break; + + case TT_DRM: + drmRead_CrcInit(&hInput->parser.drm); + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + case TT_MP4_RAW: + break; + + default: + FreeRam_TransportDecoder(&hInput); + hInput = NULL; + break; + } + + if (hInput != NULL) { + /* Create bitstream */ + if ( TT_IS_PACKET(transportFmt) ) { + hInput->bsBuffer = NULL; + } else { + hInput->bsBuffer = GetRam_TransportDecoderBuffer(0); + if (hInput->bsBuffer == NULL) { + transportDec_Close( &hInput ); + return NULL; + } + FDKinitBitStream(&hInput->bitStream[0], hInput->bsBuffer, TRANSPORTDEC_INBUF_SIZE, 0, BS_READER); + } + + hInput->burstPeriod = 0; + } + + return hInput; +} + +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, UCHAR *conf, const UINT length, UINT layer ) +{ + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + FDKinitBitStream(hBs, conf, 0x10000000, length<<3, BS_READER); + + int fConfigFound = 0; + + /* config transport decoder */ + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + { + if (layer != 0) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + CLatmDemux *pLatmDemux = &hTp->parser.latm; + err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, hTp->asc, &fConfigFound); + if (err != TRANSPORTDEC_OK) { + return err; + } + } + break; + default: + fConfigFound = 1; + err = AudioSpecificConfig_Parse(&hTp->asc[layer], hBs, 1, &hTp->callbacks); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case TT_DRM: + fConfigFound = 1; + err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +int transportDec_RegisterAscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbUpdateConfig_t cbUpdateConfig, void* user_data) +{ + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUpdateConfig = cbUpdateConfig; + hTpDec->callbacks.cbUpdateConfigData = user_data; + return 0; +} + +int transportDec_RegisterSscCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSsc_t cbSsc, void* user_data) +{ + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSsc = cbSsc; + hTpDec->callbacks.cbSscData = user_data; + return 0; +} + +int transportDec_RegisterSbrCallback( HANDLE_TRANSPORTDEC hTpDec, const cbSbr_t cbSbr, void* user_data) +{ + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSbr = cbSbr; + hTpDec->callbacks.cbSbrData = user_data; + return 0; +} + +TRANSPORTDEC_ERROR transportDec_FillData( + const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, + const UINT bufferSize, + UINT *pBytesValid, + const INT layer ) +{ + HANDLE_FDK_BITSTREAM hBs; + + if ( (hTp == NULL) + || (layer >= 2) ) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + if (*pBytesValid == 0) { + /* nothing to do */ + return TRANSPORTDEC_OK; + } + + /* set bitbuffer shortcut */ + hBs = &hTp->bitStream[layer]; + + if ( TT_IS_PACKET(hTp->transportFmt) ) { + if (hTp->numberOfRawDataBlocks == 0) { + /* For packet based transport, pass input buffer to bitbuffer without copying the data. + Unfortunately we do not know the actual buffer size. And the FDK bit buffer implementation + needs a number 2^x. So we assume the maximum of 48 channels with 6144 bits per channel + and round it up to the next power of 2 => 65536 bytes */ + FDKinitBitStream(hBs, pBuffer, 0x10000, (*pBytesValid)<<3, BS_READER); + *pBytesValid = 0; + } + } else { + /* ... else feed bitbuffer with new stream data (append). */ + if (hTp->numberOfRawDataBlocks <= 0) { + FDKfeedBuffer (hBs, pBuffer, bufferSize, pBytesValid) ; + } + } + + return TRANSPORTDEC_OK; +} + +HANDLE_FDK_BITSTREAM transportDec_GetBitstream( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) +{ + return &hTp->bitStream[layer]; +} + +TRANSPORT_TYPE transportDec_GetFormat( const HANDLE_TRANSPORTDEC hTp ) +{ + return hTp->transportFmt; +} + +INT transportDec_GetBufferFullness( const HANDLE_TRANSPORTDEC hTp ) +{ + INT bufferFullness = -1; + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.adts_fullness != 0x7ff) { + bufferFullness = hTp->parser.adts.bs.frame_length*8 + hTp->parser.adts.bs.adts_fullness * 32 * getNumberOfEffectiveChannels(hTp->parser.adts.bs.channel_config); + } + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hTp->parser.latm.m_linfo[0][0].m_bufferFullness != 0xff) { + bufferFullness = hTp->parser.latm.m_linfo[0][0].m_bufferFullness; + } + break; + default: + break; + } + + return bufferFullness; +} + +/** + * \brief adjust bit stream position and the end of an access unit. + * \param hTp transport decoder handle. + * \return error code. + */ +static +TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit(HANDLE_TRANSPORTDEC hTp) +{ + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + switch (hTp->transportFmt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if ( hTp->numberOfRawDataBlocks == 0 ) + { + /* Do byte align at the end of AudioMuxElement. */ + FDKbyteAlign(hBs, hTp->globalFramePos); + + /* Check global frame length */ + if (hTp->transportFmt == TT_MP4_LOAS && hTp->parser.latm.m_audioMuxLengthBytes > 0) + { + int loasOffset; + + loasOffset = (hTp->parser.latm.m_audioMuxLengthBytes*8 + FDKgetValidBits(hBs)) - hTp->globalFramePos; + if (loasOffset != 0) { + FDKpushBiDirectional(hBs, loasOffset); + /* For ELD and other payloads there is an unknown amount of padding, so ignore unread bits, but + throw an error only if too many bits where read. */ + if (loasOffset < 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + break; + + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.protection_absent == 0) + { + int offset; + + /* Calculate offset to end of AU */ + offset = hTp->parser.adts.rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks]<<3; + /* CAUTION: The PCE (if available) is declared to be a part of the header! */ + offset -= hTp->accessUnitAnchor[0] - FDKgetValidBits(hBs) + 16 + hTp->parser.adts.bs.num_pce_bits; + FDKpushBiDirectional(hBs, offset); + } + if (hTp->parser.adts.bs.num_raw_blocks > 0 && hTp->parser.adts.bs.protection_absent == 0) { + /* Note this CRC read currently happens twice because of transportDec_CrcCheck() */ + hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16); + } + if ( hTp->numberOfRawDataBlocks == 0 ) + { + /* Check global frame length */ + if (hTp->parser.adts.bs.protection_absent == 0) + { + int offset; + + offset = (hTp->parser.adts.bs.frame_length*8 - ADTS_SYNCLENGTH + FDKgetValidBits(hBs)) - hTp->globalFramePos; + if (offset != 0) { + FDKpushBiDirectional(hBs, offset); + } + } + } + break; + + default: + break; + } + + return err; +} + + +/** + * \brief Determine additional buffer fullness contraint due to burst data reception. + * The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a precondition. + * \param hTp transport decoder handle. + * \param bufferFullness the buffer fullness value of the first frame to be decoded. + * \param bitsAvail the amount of available bits at the end of the first frame to be decoded. + * \return error code + */ +static +TRANSPORTDEC_ERROR additionalHoldOffNeeded( + HANDLE_TRANSPORTDEC hTp, + INT bufferFullness, + INT bitsAvail + ) +{ + INT checkLengthBits, avgBitsPerFrame; + INT maxAU; /* maximum number of frames per Master Frame */ + INT samplesPerFrame = hTp->asc->m_samplesPerFrame; + INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency; + + if ( (hTp->avgBitRate == 0) || (hTp->burstPeriod == 0) ) { + return TRANSPORTDEC_OK; + } + if ( (samplesPerFrame == 0 ) || (samplingFrequency == 0) ) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + /* One Master Frame is sent every hTp->burstPeriod ms */ + maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame*1000 - 1); + maxAU = maxAU / (samplesPerFrame*1000); + /* Subtract number of frames which were already held off. */ + maxAU -= hTp->holdOffFrames; + + avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency-1); + avgBitsPerFrame = avgBitsPerFrame / samplingFrequency; + + /* Consider worst case of bufferFullness quantization. */ + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness += 31; + break; + default: + break; + } + + checkLengthBits = bufferFullness + (maxAU-1)*avgBitsPerFrame; + + /* Check if buffer is big enough to fullfill buffer fullness condition */ + if ( (checkLengthBits /*+headerBits*/) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + return TRANSPORTDEC_SYNC_ERROR; + } + + if ( bitsAvail < checkLengthBits ) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + else { + return TRANSPORTDEC_OK; + } +} + +static TRANSPORTDEC_ERROR transportDec_readHeader( + HANDLE_TRANSPORTDEC hTp, + HANDLE_FDK_BITSTREAM hBs, + int syncLength, + int ignoreBufferFullness, + int *pRawDataBlockLength, + int *pfTraverseMoreFrames, + int *pSyncLayerFrameBits, + int *pfConfigFound, + int *pHeaderBits + ) +{ + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int rawDataBlockLength = *pRawDataBlockLength; + int fTraverseMoreFrames = (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; + int syncLayerFrameBits = (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; + int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0; + int startPos; + + startPos = FDKgetValidBits(hBs); + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->numberOfRawDataBlocks <= 0) + { + int errC; + + hTp->globalFramePos = FDKgetValidBits(hBs); + + /* Parse ADTS header */ + err = adtsRead_DecodeHeader( &hTp->parser.adts, &hTp->asc[0], hBs, ignoreBufferFullness ); + if (err != TRANSPORTDEC_OK) { + if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]); + if (errC != 0) { + if (errC == TRANSPORTDEC_NEED_TO_RESTART) { + err = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } else { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + fConfigFound = 1; + hTp->numberOfRawDataBlocks = hTp->parser.adts.bs.num_raw_blocks+1; + } + } + } + else { + /* Reset CRC because the next bits are the beginning of a raw_data_block() */ + FDKcrcReset(&hTp->parser.adts.crcInfo); + hTp->parser.adts.bs.num_pce_bits = 0; + } + if (err == TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks--; + rawDataBlockLength = adtsRead_GetRawDataBlockLength(&hTp->parser.adts, (hTp->parser.adts.bs.num_raw_blocks-hTp->numberOfRawDataBlocks)); + if (rawDataBlockLength <= 0) { + /* No further frame traversal possible. */ + fTraverseMoreFrames = 0; + } + syncLayerFrameBits = (hTp->parser.adts.bs.frame_length<<3) - (startPos - FDKgetValidBits(hBs)) - syncLength; + if (syncLayerFrameBits <= 0) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + case TT_MP4_LOAS: + if (hTp->numberOfRawDataBlocks <= 0) + { + syncLayerFrameBits = FDKreadBits(hBs, 13); + hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits; + syncLayerFrameBits <<= 3; + } + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + if (hTp->numberOfRawDataBlocks <= 0) + { + hTp->globalFramePos = FDKgetValidBits(hBs); + + err = CLatmDemux_Read( + hBs, + &hTp->parser.latm, + hTp->transportFmt, + &hTp->callbacks, + hTp->asc, + &fConfigFound, + ignoreBufferFullness); + + if (err != TRANSPORTDEC_OK) { + if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + if (hTp->transportFmt == TT_MP4_LOAS) { + syncLayerFrameBits -= startPos - FDKgetValidBits(hBs) - (13); + } + } + } else { + err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm); + if (err != TRANSPORTDEC_OK) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } + if (err == TRANSPORTDEC_OK) { + rawDataBlockLength = CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm); + hTp->numberOfRawDataBlocks--; + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + default: + { + syncLayerFrameBits = 0; + } + break; + } + +bail: + + *pRawDataBlockLength = rawDataBlockLength; + + if (pHeaderBits != NULL) { + *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs); + } + if (pfConfigFound != NULL) { + *pfConfigFound = fConfigFound; + } + + if (pfTraverseMoreFrames != NULL) { + *pfTraverseMoreFrames = fTraverseMoreFrames; + } + if (pSyncLayerFrameBits != NULL) { + *pSyncLayerFrameBits = syncLayerFrameBits; + } + if (pfConfigFound != NULL) { + *pfConfigFound = fConfigFound; + } + + return err; +} + +/* How many bits to advance for synchronization search. */ +#define TPDEC_SYNCSKIP 8 + +static +TRANSPORTDEC_ERROR synchronization( + HANDLE_TRANSPORTDEC hTp, + INT *pHeaderBits + ) +{ + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + + INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */ + INT rawDataBlockLength = 0, rawDataBlockLengthPrevious; + INT totalBits; + INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious; + INT numFramesTraversed = 0, fTraverseMoreFrames, fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1; + INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0; + INT ignoreBufferFullness = hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK); + + /* Synch parameters */ + INT syncLength; /* Length of sync word in bits */ + UINT syncWord; /* Sync word to be found */ + UINT syncMask; /* Mask for sync word (for adding one bit, so comprising one bit less) */ + C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1); + + totalBits = (INT)FDKgetValidBits(hBs); + + if (totalBits <= 0) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + goto bail; + } + + fTraverseMoreFrames = (hTp->flags & (TPDEC_MINIMIZE_DELAY|TPDEC_EARLY_CONFIG)) && ! (hTp->flags & TPDEC_SYNCOK); + + /* Set transport specific sync parameters */ + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + syncWord = ADTS_SYNCWORD; + syncLength = ADTS_SYNCLENGTH; + break; + case TT_MP4_LOAS: + syncWord = 0x2B7; + syncLength = 11; + break; + default: + syncWord = 0; + syncLength = 0; + break; + } + + syncMask = (1<numberOfRawDataBlocks == 0) { + /* search synchword */ + + FDK_ASSERT( (bitsAvail % TPDEC_SYNCSKIP) == 0); + + if ((bitsAvail-syncLength) < TPDEC_SYNCSKIP) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + headerBits = 0; + } else { + + synch = FDKreadBits(hBs, syncLength); + + if ( !(hTp->flags & TPDEC_SYNCOK) ) { + for (; (bitsAvail-syncLength) >= TPDEC_SYNCSKIP; bitsAvail-=TPDEC_SYNCSKIP) { + if (synch == syncWord) { + break; + } + synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | FDKreadBits(hBs, TPDEC_SYNCSKIP); + } + } + if (synch != syncWord) { + /* No correct syncword found. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + err = TRANSPORTDEC_OK; + } + headerBits = syncLength; + } + } else { + headerBits = 0; + } + + /* Save previous raw data block data */ + rawDataBlockLengthPrevious = rawDataBlockLength; + numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks; + + /* Parse transport header (raw data block granularity) */ + + if (err == TRANSPORTDEC_OK ) + { + err = transportDec_readHeader( + hTp, + hBs, + syncLength, + ignoreBufferFullness, + &rawDataBlockLength, + &fTraverseMoreFrames, + &syncLayerFrameBits, + &fConfigFound, + &headerBits + ); + } + + bitsAvail -= headerBits; + + checkLengthBits = syncLayerFrameBits; + + /* Check if the whole frame would fit the bitstream buffer */ + if (err == TRANSPORTDEC_OK) { + if ( (checkLengthBits+headerBits) > ((TRANSPORTDEC_INBUF_SIZE<<3)-7) ) { + /* We assume that the size of the transport bit buffer has been + chosen to meet all system requirements, thus this condition + is considered a synchronisation error. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + if ( bitsAvail < checkLengthBits ) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } + + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + break; + } + + + if (err == TRANSPORTDEC_SYNC_ERROR) { + int bits; + + /* Enforce re-sync of transport headers. */ + hTp->numberOfRawDataBlocks = 0; + + /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */ + bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP; + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead next time. */ + FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits); + bitsAvail += headerBits - TPDEC_SYNCSKIP - bits; + headerBits = 0; + } + + /* Frame traversal */ + if ( fTraverseMoreFrames ) + { + /* Save parser context for early config discovery "rewind all frames" */ + if ( (hTp->flags & TPDEC_EARLY_CONFIG) && !(hTp->flags & TPDEC_MINIMIZE_DELAY)) + { + /* ignore buffer fullness if just traversing additional frames for ECD */ + ignoreBufferFullness = 1; + + /* Save context in order to return later */ + if ( err == TRANSPORTDEC_OK && startPosFirstFrame == -1 ) { + startPosFirstFrame = FDKgetValidBits(hBs); + numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks; + globalFramePosFirstFrame = hTp->globalFramePos; + rawDataBlockLengthFirstFrame = rawDataBlockLength; + headerBitsFirstFrame = headerBits; + errFirstFrame = err; + FDKmemcpy(contextFirstFrame, &hTp->parser, sizeof(transportdec_parser_t)); + } + + /* Break when config was found or it is not possible anymore to find a config */ + if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) + { + /* In case of ECD and sync error, do not rewind anywhere. */ + if (err == TRANSPORTDEC_SYNC_ERROR) + { + startPosFirstFrame = -1; + fConfigFound = 0; + numFramesTraversed = 0; + } + break; + } + } + + if (err == TRANSPORTDEC_OK) { + FDKpushFor(hBs, rawDataBlockLength); + bitsAvail -= rawDataBlockLength; + numFramesTraversed++; + /* Ignore error here itentionally. */ + transportDec_AdjustEndOfAccessUnit(hTp); + } + } + } while ( fTraverseMoreFrames || (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK))); + + /* Restore context in case of ECD frame traversal */ + if ( startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK) ) { + FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame); + FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t)); + hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame; + hTp->globalFramePos = globalFramePosFirstFrame; + rawDataBlockLength = rawDataBlockLengthFirstFrame; + headerBits = headerBitsFirstFrame; + err = errFirstFrame; + numFramesTraversed = 0; + } + + /* Additional burst data mode buffer fullness check. */ + if ( !(hTp->flags & (TPDEC_LOST_FRAMES_PENDING|TPDEC_IGNORE_BUFFERFULLNESS|TPDEC_SYNCOK)) && err == TRANSPORTDEC_OK) { + err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), FDKgetValidBits(hBs) - syncLayerFrameBits); + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + hTp->holdOffFrames++; + } + } + + /* Rewind for retry because of not enough bits */ + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + FDKpushBack(hBs, headerBits); + headerBits = 0; + } + else { + /* reset hold off frame counter */ + hTp->holdOffFrames = 0; + } + + /* Return to last good frame in case of frame traversal but not ECD. */ + if (numFramesTraversed > 0) { + FDKpushBack(hBs, rawDataBlockLengthPrevious); + if (err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious; + headerBits = headerBitsPrevious; + } + err = TRANSPORTDEC_OK; + } + +bail: + hTp->auLength[0] = rawDataBlockLength; + + /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, were the bit buffer is already full, + or no new burst packet fits. Recover by advancing the bit buffer. */ + if ( (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && (FDKgetValidBits(hBs) >= ((TRANSPORTDEC_INBUF_SIZE*8 - ((hTp->avgBitRate*hTp->burstPeriod)/1000)) - 7)) ) + { + FDKpushFor(hBs, TPDEC_SYNCSKIP); + err = TRANSPORTDEC_SYNC_ERROR; + } + + if (err == TRANSPORTDEC_OK) { + hTp->flags |= TPDEC_SYNCOK; + } + + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + if (pHeaderBits != NULL) { + *pHeaderBits = headerBits; + } + + if (err == TRANSPORTDEC_SYNC_ERROR) { + hTp->flags &= ~TPDEC_SYNCOK; + } + + C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1); + + return err; +} + +/** + * \brief Synchronize to stream and estimate the amount of missing access units due + * to a current synchronization error in case of constant average bit rate. + */ +static +TRANSPORTDEC_ERROR transportDec_readStream ( HANDLE_TRANSPORTDEC hTp, const UINT layer ) +{ + + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer]; + INT nAU = -1; + INT headerBits; + INT bitDistance, bfDelta; + + /* Obtain distance to next synch word */ + bitDistance = FDKgetValidBits(hBs); + error = synchronization(hTp, &headerBits); + bitDistance -= FDKgetValidBits(hBs); + + + FDK_ASSERT(bitDistance >= 0); + + if (error == TRANSPORTDEC_SYNC_ERROR || (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) + { + /* Check if estimating lost access units is feasible. */ + if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && hTp->asc[0].m_samplingFrequency > 0) + { + if (error == TRANSPORTDEC_OK) + { + int aj; + + aj = transportDec_GetBufferFullness(hTp); + if (aj > 0) { + bfDelta = aj; + } else { + bfDelta = 0; + } + /* sync was ok: last of a series of bad access units. */ + hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING; + /* Add up bitDistance until end of the current frame. Later we substract + this frame from the grand total, since this current successfully synchronized + frame should not be skipped of course; but it must be accounted into the + bufferfulness math. */ + bitDistance += hTp->auLength[0]; + } else { + if ( !(hTp->flags & TPDEC_LOST_FRAMES_PENDING) ) { + /* sync not ok: one of many bad access units. */ + hTp->flags |= TPDEC_LOST_FRAMES_PENDING; + bfDelta = - (INT)hTp->lastValidBufferFullness; + } else { + bfDelta = 0; + } + } + + { + int num, denom; + + /* Obtain estimate of number of lost frames */ + num = hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + hTp->remainder; + denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame; + if (num > 0) { + nAU = num / denom; + hTp->remainder = num % denom; + } else { + hTp->remainder = num; + } + + if (error == TRANSPORTDEC_OK) + { + /* Final adjustment of remainder, taken -1 into account because current + frame should not be skipped, thus substract -1 or do nothing instead + of +1-1 accordingly. */ + if ( (denom - hTp->remainder) >= hTp->remainder ) { + nAU--; + } + + if (nAU < 0) { + /* There was one frame too much concealed, so unfortunately we will have to skip one good frame. */ + transportDec_EndAccessUnit(hTp); + error = synchronization(hTp, &headerBits); + nAU = -1; +#ifdef DEBUG + FDKprintf("ERROR: Bufferfullness accounting failed. remainder=%d, nAU=%d\n", hTp->remainder, nAU); +#endif + } + hTp->remainder = 0; + /* Enforce last missed frames to be concealed. */ + if (nAU > 0) { + FDKpushBack(hBs, headerBits); + } + } + } + } + } + + /* Be sure that lost frames are handled correctly. This is necessary due to some + sync error sequences where later it turns out that there is not enough data, but + the bits upto the sync word are discarded, thus causing a value of nAU > 0 */ + if (nAU > 0) { + error = TRANSPORTDEC_SYNC_ERROR; + } + + hTp->missingAccessUnits = nAU; + + return error; +} + +/* returns error code */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) +{ + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs; + + if (!hTp) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + hBs = &hTp->bitStream[layer]; + + if ((INT)FDKgetValidBits(hBs) <= 0) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + switch (hTp->transportFmt) { + + case TT_MP4_ADIF: + /* Read header if not already done */ + if (!(hTp->flags & TPDEC_CONFIG_FOUND)) + { + CProgramConfig *pce; + + AudioSpecificConfig_Init(&hTp->asc[0]); + pce = &hTp->asc[0].m_progrConfigElement; + err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); + if (err) + goto bail; + + /* Map adif header to ASC */ + hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); + hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; + hTp->asc[0].m_samplingFrequency = SamplingRateTable[pce->SamplingFrequencyIndex]; + hTp->asc[0].m_channelConfiguration = 0; + hTp->asc[0].m_samplesPerFrame = 1024; + hTp->avgBitRate = hTp->parser.adif.BitRate; + + /* Call callback to decoder. */ + { + int errC; + + errC = hTp->callbacks.cbUpdateConfig(hTp->callbacks.cbUpdateConfigData, &hTp->asc[0]); + if (errC == 0) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } else { + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + } + hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */ + break; + + case TT_MP4_RAW: + case TT_DRM: + /* One Access Unit was filled into buffer. + So get the length out of the buffer. */ + hTp->auLength[layer] = FDKgetValidBits(hBs); + hTp->flags |= TPDEC_SYNCOK; + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + { + int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND; + err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], NULL, NULL, &fConfigFound, NULL); + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + } + break; + + case TT_MP4_ADTS: + case TT_MP4_LOAS: + err = transportDec_readStream(hTp, layer); + break; + + default: + err = TRANSPORTDEC_UNSUPPORTED_FORMAT; + break; + } + + if (err == TRANSPORTDEC_OK) { + hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs); + } else { + hTp->accessUnitAnchor[layer] = 0; + } + +bail: + return err; +} + +INT transportDec_GetAuBitsRemaining( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) +{ + INT bits; + + if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) { + bits = hTp->auLength[layer] - (hTp->accessUnitAnchor[layer] - FDKgetValidBits(&hTp->bitStream[layer])); + } else { + bits = FDKgetValidBits(&hTp->bitStream[layer]); + } + + return bits; +} + +INT transportDec_GetAuBitsTotal( const HANDLE_TRANSPORTDEC hTp, const UINT layer ) +{ + return hTp->auLength[layer]; +} + +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount ( INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp ) +{ + *pNAccessUnits = hTp->missingAccessUnits; + + return TRANSPORTDEC_OK; +} + +/* Inform the transportDec layer that reading of access unit has finished. */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) +{ + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + + err = transportDec_AdjustEndOfAccessUnit(hTp); + + switch (hTp->transportFmt) { + default: + break; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_SetParam ( const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value) +{ + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + + switch (param) { + case TPDEC_PARAM_MINIMIZE_DELAY: + if (value) { + hTp->flags |= TPDEC_MINIMIZE_DELAY; + } else { + hTp->flags &= ~TPDEC_MINIMIZE_DELAY; + } + break; + case TPDEC_PARAM_EARLY_CONFIG: + if (value) { + hTp->flags |= TPDEC_EARLY_CONFIG; + } else { + hTp->flags &= ~TPDEC_EARLY_CONFIG; + } + break; + case TPDEC_PARAM_IGNORE_BUFFERFULLNESS: + if (value) { + hTp->flags |= TPDEC_IGNORE_BUFFERFULLNESS; + } else { + hTp->flags &= ~TPDEC_IGNORE_BUFFERFULLNESS; + } + break; + case TPDEC_PARAM_SET_BITRATE: + hTp->avgBitRate = value; + break; + case TPDEC_PARAM_BURST_PERIOD: + hTp->burstPeriod = value; + break; + case TPDEC_PARAM_RESET: + { + int i; + + for (i=0; i<(1*2); i++) { + FDKresetBitbuffer(&hTp->bitStream[i]); + hTp->auLength[i] = 0; + hTp->accessUnitAnchor[i] = 0; + } + hTp->flags &= ~(TPDEC_SYNCOK|TPDEC_LOST_FRAMES_PENDING); + if (hTp->transportFmt != TT_MP4_ADIF) { + hTp->flags &= ~TPDEC_CONFIG_FOUND; + } + hTp->remainder = 0; + hTp->avgBitRate = 0; + hTp->missingAccessUnits = 0; + hTp->numberOfRawDataBlocks = 0; + hTp->globalFramePos = 0; + hTp->holdOffFrames = 0; + } + break; + } + + return error; +} + +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) +{ + UINT nSubFrames = 0; + + if (hTp == NULL) + return 0; + + if (hTp->transportFmt==TT_MP4_LATM_MCP1 || hTp->transportFmt==TT_MP4_LATM_MCP0 || hTp->transportFmt==TT_MP4_LOAS) + nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + else if (hTp->transportFmt==TT_MP4_ADTS) + nSubFrames = hTp->parser.adts.bs.num_raw_blocks; + + return nSubFrames; +} + +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) +{ + if (phTp != NULL) + { + if (*phTp != NULL) { + if ( ! TT_IS_PACKET((*phTp)->transportFmt) ) { + FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer); + } + if (*phTp != NULL) { + FreeRam_TransportDecoder(phTp); + } + } + } +} + +TRANSPORTDEC_ERROR transportDec_GetLibInfo( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR; + info += i; + + info->module_id = FDK_TPDEC; +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); + info->flags = 0 + | CAPF_ADIF + | CAPF_ADTS + | CAPF_LATM + | CAPF_LOAS + | CAPF_RAWPACKETS + | CAPF_DRM + ; + + return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ +} + + +int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) +{ + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); + case TT_DRM: + return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); + default: + return 0; + } +} + +void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) +{ + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); + break; + case TT_DRM: + drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); + break; + default: + break; + } +} + +TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) +{ + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + if ( (pTp->parser.adts.bs.num_raw_blocks > 0) && (pTp->parser.adts.bs.protection_absent == 0) ) + { + HANDLE_FDK_BITSTREAM hBs = &pTp->bitStream[0]; + + transportDec_AdjustEndOfAccessUnit(pTp); + } + return adtsRead_CrcCheck(&pTp->parser.adts); + case TT_DRM: + return drmRead_CrcCheck(&pTp->parser.drm); + break; + default: + return TRANSPORTDEC_OK; + } +} diff --git a/libMpegTPDec/src/version b/libMpegTPDec/src/version new file mode 100644 index 00000000..75e22c9a --- /dev/null +++ b/libMpegTPDec/src/version @@ -0,0 +1,13 @@ + +/* library info */ +#define TP_LIB_VL0 2 +#define TP_LIB_VL1 3 +#define TP_LIB_VL2 7 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif diff --git a/libMpegTPEnc/include/mpegFileWrite.h b/libMpegTPEnc/include/mpegFileWrite.h new file mode 100644 index 00000000..f886a0bb --- /dev/null +++ b/libMpegTPEnc/include/mpegFileWrite.h @@ -0,0 +1,140 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Manuel Jander + Description: Bitstream data provider for MP4 decoders + +******************************************************************************/ + +#include "machine_type.h" +#include "FDK_audio.h" + +/*!< If MPFWRITE_MP4FF_ENABLE is set, include support for MPEG ISO fileformat. + If not set, no .mp4, .m4a and .3gp files can be used for input. */ +/* #define MPFWRITE_MP4FF_ENABLE */ + +typedef struct STRUCT_FILEWRITE *HANDLE_FILEWRITE; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Open an MPEG audio file. + * \param mpegFileWrite_Filename String of the filename to be opened. + * \param fileFmt Transport format to use. + * \param conf + * \param confSize + * \return MPEG file write handle. + */ +HANDLE_FILEWRITE mpegFileWrite_Open( char *mpegFileWrite_Filename, + FILE_FORMAT fileFmt, + TRANSPORT_TYPE transportType, + UCHAR *conf, + UINT confSize + ); + +/** + * \brief Write to an MPEG audio file. + * \param inBuffer Buffer to write. + * \param bufferSize Size of buffer to write in bytes. + * \return 0 on sucess, -1 on unsupported file format or write error. + */ +int mpegFileWrite_Write( HANDLE_FILEWRITE hFileWrite, + UCHAR *inBuffer, + int bufferSize + ); + +/** + * \brief Deallocate memory and close file. + * \param hFileWrite MPEG file write handle. + * \return 0 on sucess. + */ +int mpegFileWrite_Close( HANDLE_FILEWRITE *hFileWrite ); + + +#ifdef __cplusplus +} +#endif diff --git a/libMpegTPEnc/include/tp_data.h b/libMpegTPEnc/include/tp_data.h new file mode 100644 index 00000000..c6e89b51 --- /dev/null +++ b/libMpegTPEnc/include/tp_data.h @@ -0,0 +1,350 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Manuel Jander + Description: MPEG Transport data tables + +******************************************************************************/ + +#ifndef __TP_DATA_H__ +#define __TP_DATA_H__ + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ +#define TP_GA_ENABLE +/* #define TP_CELP_ENABLE */ +/* #define TP_HVXC_ENABLE */ +/* #define TP_SLS_ENABLE */ +#define TP_ELD_ENABLE +/* #define TP_USAC_ENABLE */ +/* #define TP_RSVD50_ENABLE */ + +#if defined(TP_GA_ENABLE) || defined(TP_SLS_ENABLE) +#define TP_PCE_ENABLE /**< Enable full PCE support */ +#endif + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 + +typedef struct +{ +#ifdef TP_PCE_ENABLE + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; +#endif /* TP_PCE_ENABLE */ + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR NumChannels; /*!< Amount of audio channels summing all channel elements including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +#ifdef TP_GA_ENABLE +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag ; + UINT m_dependsOnCoreCoder ; + UINT m_coreCoderDelay ; + + UINT m_extensionFlag ; + UINT m_extensionFlag3 ; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; +#endif /* TP_GA_ENABLE */ + + + + +#ifdef TP_ELD_ENABLE + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2 /* LD MPEG Surround config */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + +} CSEldSpecificConfig; +#endif /* TP_ELD_ENABLE */ + + + + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + + /* XYZ Specific Data */ + union { +#ifdef TP_GA_ENABLE + CSGaSpecificConfig m_gaSpecificConfig; /**< General audio specific configuration. */ +#endif /* TP_GA_ENABLE */ +#ifdef TP_ELD_ENABLE + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ +#endif /* TP_ELD_ENABLE */ + } m_sc; + + /* Common ASC parameters */ +#ifdef TP_PCE_ENABLE + CProgramConfig m_progrConfigElement; /**< Program configuration. */ +#endif /* TP_PCE_ENABLE */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the bitstream */ + SCHAR m_psPresentFlag; /**< Flag indicating the presence of parametric stereo data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + +} CSAudioSpecificConfig; + +typedef INT (*cbUpdateConfig_t)(void*, const CSAudioSpecificConfig*); +typedef INT (*cbSsc_t)( + void*, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingFrequency, + const INT muxMode, + const INT configBytes + ); +typedef INT (*cbSbr_t)( + void * self, + HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, + const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex + ); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = +{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, + 0 +}; + +static inline +int getSamplingRateIndex( UINT samplingRate ) +{ + UINT sf_index, tableSize=sizeof(SamplingRateTable)/sizeof(UINT); + + for (sf_index=0; sf_indextableSize-1) { + return tableSize-1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) +{ + switch (channelConfig) { + case 1: case 2: case 3: + case 4: case 5: case 6: + return channelConfig; + case 7: case 12: case 14: + return 8; + case 11: + return 7; + default: + return 0; + } +} + +static inline +int getNumberOfEffectiveChannels(const int channelConfig) +{ /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0,1,2,3,4,5,5,7,0,0, 0, 6, 7, 0, 7, 0}; + return n[channelConfig]; +} + +#endif /* __TP_DATA_H__ */ diff --git a/libMpegTPEnc/include/tpenc_lib.h b/libMpegTPEnc/include/tpenc_lib.h new file mode 100644 index 00000000..2833e825 --- /dev/null +++ b/libMpegTPEnc/include/tpenc_lib.h @@ -0,0 +1,296 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** MPEG-4 Transport Encoder ************************ + + Author(s): Manuel Jander + Description: MPEG Transport encode + +******************************************************************************/ + +#ifndef __TPENC_LIB_H__ +#define __TPENC_LIB_H__ + +#include "tp_data.h" +#include "FDK_bitstream.h" + +#define TRANSPORTENC_INBUF_SIZE 8192 + +typedef enum { + TRANSPORTENC_OK = 0, /*!< All fine. */ + TRANSPORTENC_NO_MEM, /*!< Out of memory. */ + TRANSPORTENC_UNKOWN_ERROR = 1, /*!< Unknown error (embarrasing). */ + TRANSPORTENC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a function . */ + TRANSPORTENC_PARSE_ERROR, /*!< Bitstream data contained inconsistencies (wrong syntax). */ + TRANSPORTENC_UNSUPPORTED_FORMAT, /*!< Unsupported transport format. */ + TRANSPORTENC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try again. */ + + TRANSPORTENC_INVALID_CONFIG, /*!< Error in configuration. */ + TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES, /*!< LATM: number of subframes out of range. */ + TRANSPORTENC_LOAS_NOT_AVAILABLE, /*!< LOAS format not supported. */ + TRANSPORTENC_INVALID_LATM_ALIGNMENT, /*!< AudioMuxElement length not aligned to 1 byte. */ + + TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH, /*!< Invalid transmission frame length (< 0). */ + TRANSPORTENC_INVALID_CELP_FRAME_LENGTH, /*!< Invalid CELP frame length found (>= 62). */ + TRANSPORTENC_INVALID_FRAME_BITS, /*!< Frame bits is not 40 and not 80. */ + TRANSPORTENC_INVALID_AOT, /*!< Unknown AOT found. */ + TRANSPORTENC_INVALID_AU_LENGTH /*!< Invalid Access Unit length (not byte-aligned). */ + +} TRANSPORTENC_ERROR; + +typedef struct TRANSPORTENC *HANDLE_TRANSPORTENC; + +/** + * \brief Determine a reasonable channel configuration on the basis of channel_mode. + * \param noChannels Number of audio channels. + * \return CHANNEL_MODE value that matches the given amount of audio channels. + */ +CHANNEL_MODE transportEnc_GetChannelMode( int noChannels ); + +/** + * \brief Register SBR heaqder writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header writing. + * \param user_data void pointer for user data passed to the callback as first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSbrCallback ( + HANDLE_TRANSPORTENC hTpEnc, + const cbSbr_t cbSbr, + void* user_data + ); + +/** + * \brief Register SSC writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC writing. + * \param user_data void pointer for user data passed to the callback as first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSscCallback ( + HANDLE_TRANSPORTENC hTpEnc, + const cbSsc_t cbSsc, + void* user_data + ); + +/** + * \brief Write ASC from given parameters. + * \param asc A HANDLE_FDK_BITSTREAM where the ASC is written to. + * \param config Structure containing the codec configuration settings. + * \param cb callback information structure. + * \return 0 on success. + */ +int transportEnc_writeASC ( + HANDLE_FDK_BITSTREAM asc, + CODER_CONFIG *config, + CSTpCallBacks *cb + ); + + +/* Defintion of flags that can be passed to transportEnc_Open() */ +#define TP_FLAG_MPEG4 1 /** MPEG4 (instead of MPEG2) */ +#define TP_FLAG_LATM_AMV 2 /** LATM AudioMuxVersion */ +#define TP_FLAG_LATM_AMVA 4 /** LATM AudioMuxVersionA */ + +/** + * \brief Allocate transport encoder. + * \param phTpEnc Pointer to transport encoder handle. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Open( HANDLE_TRANSPORTENC *phTpEnc ); + +/** + * \brief Init transport encoder. + * \param bsBuffer Pointer to transport encoder. + * \param bsBuffer Pointer to bitstream buffer. + * \param bsBufferSize Size in bytes of bsBuffer. + * \param transportFmt Format of the transport to be written. + * \param config Pointer to a valid CODER_CONFIG struct. + * \param flags Transport encoder flags. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Init( + HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, + INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *config, + UINT flags + ); + +/** + * \brief Get transport encoder bitstream. + * \param hTp Pointer to a transport encoder handle. + * \return The handle to the requested FDK bitstream. + */ +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream( HANDLE_TRANSPORTENC hTp ); + +/** + * \brief Get amount of bits required by the transport headers. + * \param hTp Handle of transport encoder. + * \param auBits Amount of payload bits required for the current subframe. + * \return Error code. + */ +INT transportEnc_GetStaticBits( HANDLE_TRANSPORTENC hTp, int auBits ); + +/** + * \brief Close transport encoder. This function assures that all allocated memory is freed. + * \param phTp Pointer to a previously allocated transport encoder handle. + */ +void transportEnc_Close( HANDLE_TRANSPORTENC *phTp ); + +/** + * \brief Write one access unit. + * \param hTp Handle of transport encoder. + * \param total_bits Amount of total access unit bits. + * \param bufferFullness Value of current buffer fullness in bits. + * \param noConsideredChannels Number of bitrate wise considered channels (all minus LFE channels). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit( HANDLE_TRANSPORTENC hTp, + INT total_bits, + int bufferFullness, + int noConsideredChannels ); + +/** + * \brief Inform the transportEnc layer that writing of access unit has finished. This function + * is required to be called when the encoder has finished writing one Access + * one Access Unit for bitstream housekeeping. + * \param hTp Transport handle. + * \param pBits Pointer to an int, where the current amount of frame bits is passed + * and where the current amount of subframe bits is returned. + * + * OR: This integer is modified by the amount of extra bit alignment that may occurr. + * + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_EndAccessUnit( HANDLE_TRANSPORTENC hTp, int *pBits); + +/* + * \brief Get a payload frame. + * \param hTpEnc Transport encoder handle. + * \param nBytes Pointer to an int to hold the frame size in bytes. Returns zero + * if currently there is no complete frame for output (number of sub frames > 1). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, int *nbytes); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTpEnc Transport encoder handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be of a fixed size. + * \return Data region ID, which should be used when calling transportEnc_CrcEndReg(). + */ +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits); + +/** + * \brief Set end of data region. + * \param hTpEnc Transport encoder handle. + * \param reg Data region ID, opbtained from transportEnc_CrcStartReg(). + * \return void + */ +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg); + +/** + * \brief Get AudioSpecificConfig or StreamMuxConfig from transport encoder handle and write it to dataBuffer. + * \param hTpEnc Transport encoder handle. + * \param cc Pointer to the current and valid configuration contained in a CODER_CONFIG struct. + * \param dataBuffer Bitbuffer holding binary configuration. + * \param confType Pointer to an UINT where the configuration type is returned (0:ASC, 1:SMC). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetConf( HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType ); + +/** + * \brief Get information (version among other things) of the transport encoder library. + * \param info Pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetLibInfo( LIB_INFO *info ); + +#endif /* #ifndef __TPENC_LIB_H__ */ diff --git a/libMpegTPEnc/src/tpenc_adif.cpp b/libMpegTPEnc/src/tpenc_adif.cpp new file mode 100644 index 00000000..b48a32ee --- /dev/null +++ b/libMpegTPEnc/src/tpenc_adif.cpp @@ -0,0 +1,182 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + contents/description: ADIF Transport Headers writing + +******************************************************************************/ + +#include "tpenc_adif.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + + + +int adifWrite_EncodeHeader(ADIF_INFO *adif, + HANDLE_FDK_BITSTREAM hBs, + INT adif_buffer_fullness) +{ + /* ADIF/PCE/ADTS definitions */ + const char adifId[5]="ADIF"; + const int copyRightIdPresent=0; + const int originalCopy=0; + const int home=0; + + int i; + + INT sampleRate = adif->samplingRate; + INT totalBitRate = adif->bitRate; + + if (adif->headerWritten) + return 0; + + /* Align inside PCE with respect to the first bit of the header */ + UINT alignAnchor = FDKgetValidBits(hBs); + + /* Signal variable bitrate if buffer fullnes exceeds 20 bit */ + adif->bVariableRate = ( adif_buffer_fullness >= (INT)(0x1<<20) ) ? 1 : 0; + + FDKwriteBits(hBs, adifId[0],8); + FDKwriteBits(hBs, adifId[1],8); + FDKwriteBits(hBs, adifId[2],8); + FDKwriteBits(hBs, adifId[3],8); + + + FDKwriteBits(hBs, copyRightIdPresent ? 1:0,1); + + if(copyRightIdPresent) { + for(i=0;i<72;i++) { + FDKwriteBits(hBs,0,1); + } + } + FDKwriteBits(hBs, originalCopy ? 1:0,1); + FDKwriteBits(hBs, home ? 1:0,1); + FDKwriteBits(hBs, adif->bVariableRate?1:0, 1); + FDKwriteBits(hBs, totalBitRate,23); + + /* we write only one PCE at the moment */ + FDKwriteBits(hBs, 0, 4); + + if(!adif->bVariableRate) { + FDKwriteBits(hBs, adif_buffer_fullness, 20); + } + + /* Write PCE */ + transportEnc_writePCE(hBs, adif->cm, sampleRate, adif->instanceTag, adif->profile, 0, 0, alignAnchor); + + return 0; +} + +int adifWrite_GetHeaderBits(ADIF_INFO *adif) +{ + /* ADIF definitions */ + const int copyRightIdPresent=0; + + if (adif->headerWritten) + return 0; + + int bits = 0; + + bits += 8*4; /* ADIF ID */ + + bits += 1; /* Copyright present */ + + if (copyRightIdPresent) + bits += 72; /* Copyright ID */ + + bits += 26; + + bits += 4; /* Number of PCE's */ + + if(!adif->bVariableRate) { + bits += 20; + } + + /* write PCE */ + bits = transportEnc_GetPCEBits(adif->cm, 0, bits); + + return bits; +} + diff --git a/libMpegTPEnc/src/tpenc_adif.h b/libMpegTPEnc/src/tpenc_adif.h new file mode 100644 index 00000000..d5903548 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_adif.h @@ -0,0 +1,135 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: Alex Goeschel + contents/description: Transport Headers support + +******************************************************************************/ + +#ifndef TPENC_ADIF_H +#define TPENC_ADIF_H + +#include "machine_type.h" +#include "FDK_bitstream.h" + +#include "tp_data.h" + +typedef struct { + CHANNEL_MODE cm; + INT samplingRate; + INT bitRate; + int profile; + int bVariableRate; + int instanceTag; + int headerWritten; +} ADIF_INFO; + +/** + * \brief encodes ADIF Header + * + * \param adif pointer to ADIF_INFO structure + * \param hBitStream handle of bitstream, where the ADIF header is written into + * \param adif_buffer_fullness buffer fullness value for the ADIF header + * + * \return 0 on success + */ +int adifWrite_EncodeHeader( + ADIF_INFO *adif, + HANDLE_FDK_BITSTREAM hBitStream, + INT adif_buffer_fullness + ); + +/** + * \brief Get bit demand of a ADIF header + * + * \param adif pointer to ADIF_INFO structure + * + * \return amount of bits required to write the ADIF header according to the data + * contained in the adif parameter + */ +int adifWrite_GetHeaderBits( ADIF_INFO *adif ); + +#endif /* TPENC_ADIF_H */ + diff --git a/libMpegTPEnc/src/tpenc_adts.cpp b/libMpegTPEnc/src/tpenc_adts.cpp new file mode 100644 index 00000000..f4f3178b --- /dev/null +++ b/libMpegTPEnc/src/tpenc_adts.cpp @@ -0,0 +1,315 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: Alex Groeschel + contents/description: ADTS Transport Headers support + +******************************************************************************/ + +#include "tpenc_adts.h" + + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + + +int adtsWrite_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + if (pAdts->protection_absent) { + return 0; + } + return ( FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits) ); +} + +void adtsWrite_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + if (pAdts->protection_absent == 0) + { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +int adtsWrite_GetHeaderBits( HANDLE_ADTS hAdts ) +{ + int bits = 0; + + if (hAdts->currentBlock == 0) { + /* Static and variable header bits */ + bits = 56; + if (!hAdts->protection_absent) { + /* Add header/ single raw data block CRC bits */ + bits += 16; + if (hAdts->num_raw_blocks>0) { + /* Add bits of raw data block position markers */ + bits += (hAdts->num_raw_blocks)*16; + } + } + } + if (!hAdts->protection_absent && hAdts->num_raw_blocks>0) { + /* Add raw data block CRC bits. Not really part of the header, put they cause bit overhead to be accounted. */ + bits += 16; + } + + hAdts->headerBits = bits; + + return bits; +} + +INT adtsWrite_Init(HANDLE_ADTS hAdts, CODER_CONFIG *config) +{ + /* Sanity checks */ + if ( config->nSubFrames < 1 + || config->nSubFrames > 4 + || (int)config->aot > 4 + || (int)config->aot < 1 ) { + return -1; + } + + /* fixed header */ + if (config->flags & CC_MPEG_ID) { + hAdts->mpeg_id = 0; /* MPEG 4 */ + } else { + hAdts->mpeg_id = 1; /* MPEG 2 */ + } + hAdts->layer=0; + hAdts->protection_absent = ! (config->flags & CC_PROTECTION); + hAdts->profile = ((int)config->aot) - 1; + hAdts->sample_freq_index = getSamplingRateIndex(config->samplingRate); + hAdts->sample_freq = config->samplingRate; + hAdts->private_bit=0; + hAdts->channel_mode = config->channelMode; + hAdts->original=0; + hAdts->home=0; + /* variable header */ + hAdts->copyright_id=0; + hAdts->copyright_start=0; + + hAdts->num_raw_blocks=config->nSubFrames-1; /* 0 means 1 raw data block */ + + FDKcrcInit(&hAdts->crcInfo, 0x8005, 0xFFFF, 16); + + hAdts->currentBlock = 0; + + + return 0; +} + +int adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, + HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, + int frame_length) +{ + INT crcIndex = 0; + + + hAdts->headerBits = adtsWrite_GetHeaderBits(hAdts); + + FDK_ASSERT(((frame_length+hAdts->headerBits)/8)<0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + } + + if (hAdts->currentBlock == 0) { + FDKresetBitbuffer(hBitStream, BS_WRITER); + } + + hAdts->subFrameStartBit = FDKgetValidBits(hBitStream); + + /* Skip new header if this is raw data block 1..n */ + if (hAdts->currentBlock == 0) + { + FDKresetBitbuffer(hBitStream, BS_WRITER); + + if (hAdts->num_raw_blocks == 0) { + crcIndex = adtsWrite_CrcStartReg(hAdts, hBitStream, 0); + } + + /* fixed header */ + FDKwriteBits(hBitStream, 0xFFF, 12); + FDKwriteBits(hBitStream, hAdts->mpeg_id, 1); + FDKwriteBits(hBitStream, hAdts->layer, 2); + FDKwriteBits(hBitStream, hAdts->protection_absent, 1); + FDKwriteBits(hBitStream, hAdts->profile, 2); + FDKwriteBits(hBitStream, hAdts->sample_freq_index, 4); + FDKwriteBits(hBitStream, hAdts->private_bit, 1); + FDKwriteBits(hBitStream, getChannelConfig(hAdts->channel_mode), 3); + FDKwriteBits(hBitStream, hAdts->original, 1); + FDKwriteBits(hBitStream, hAdts->home, 1); + /* variable header */ + FDKwriteBits(hBitStream, hAdts->copyright_id, 1); + FDKwriteBits(hBitStream, hAdts->copyright_start, 1); + FDKwriteBits(hBitStream, (frame_length + hAdts->headerBits)>>3, 13); + FDKwriteBits(hBitStream, buffer_fullness, 11); + FDKwriteBits(hBitStream, hAdts->num_raw_blocks, 2); + + if (!hAdts->protection_absent) { + int i; + + /* End header CRC portion for single raw data block and write dummy zero values for unknown fields. */ + if (hAdts->num_raw_blocks == 0) { + adtsWrite_CrcEndReg(hAdts, hBitStream, crcIndex); + } else { + for (i=0; inum_raw_blocks; i++) { + FDKwriteBits(hBitStream, 0, 16); + } + } + FDKwriteBits(hBitStream, 0, 16); + } + } /* End of ADTS header */ + + return 0; +} + +void adtsWrite_EndRawDataBlock(HANDLE_ADTS hAdts, + HANDLE_FDK_BITSTREAM hBs, + int *pBits) +{ + if (!hAdts->protection_absent) { + FDK_BITSTREAM bsWriter; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 56); + + if (hAdts->num_raw_blocks == 0) { + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } else { + int distance; + + /* Write CRC of current raw data block */ + FDKwriteBits(hBs, FDKcrcGetCRC(&hAdts->crcInfo), 16); + + /* Write distance to current data block */ + if (hAdts->currentBlock < hAdts->num_raw_blocks) { + FDKpushFor(&bsWriter, hAdts->currentBlock*16); + distance = FDKgetValidBits(hBs) - (56 + (hAdts->num_raw_blocks)*16 + 16); + FDKwriteBits(&bsWriter, distance>>3, 16); + } + } + FDKsyncCache(&bsWriter); + } + + /* Write total frame lenth for multiple raw data blocks and header CRC */ + if (hAdts->num_raw_blocks > 0 && hAdts->currentBlock == hAdts->num_raw_blocks) { + FDK_BITSTREAM bsWriter; + int crcIndex = 0; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + crcIndex = FDKcrcStartReg(&hAdts->crcInfo, &bsWriter, 0); + } + /* Write total frame length */ + FDKpushFor(&bsWriter, 56-28+2); + FDKwriteBits(&bsWriter, FDKgetValidBits(hBs)>>3, 13); + + /* Write header CRC */ + if (!hAdts->protection_absent) { + FDKpushFor(&bsWriter, 11+2 + (hAdts->num_raw_blocks)*16); + FDKcrcEndReg(&hAdts->crcInfo, &bsWriter, crcIndex); + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } + FDKsyncCache(&bsWriter); + } + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hAdts->subFrameStartBit; + if (!hAdts->protection_absent && hAdts->num_raw_blocks > 0) { + /* Fixup CRC bits, since they come after each raw data block */ + *pBits += 16; + } + hAdts->currentBlock++; +} + diff --git a/libMpegTPEnc/src/tpenc_adts.h b/libMpegTPEnc/src/tpenc_adts.h new file mode 100644 index 00000000..c12c7c71 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_adts.h @@ -0,0 +1,218 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: Alex Groeschel + contents/description: ADTS Transport writer + +******************************************************************************/ + +#ifndef TPENC_ADTS_H +#define TPENC_ADTS_H + + + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + INT sample_freq; + CHANNEL_MODE channel_mode; + UCHAR decoderCanDoMpeg4; + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block begins */ + FDK_CRCINFO crcInfo; +} STRUCT_ADTS; + +typedef STRUCT_ADTS *HANDLE_ADTS; + +/** + * \brief Initialize ADTS data structure + * + * \param hAdts ADTS data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the ADTS header is extrated from + * + * \return 0 in case of success. + */ +INT adtsWrite_Init( + HANDLE_ADTS hAdts, + CODER_CONFIG *config + ); + +/** + * \brief Get the total bit overhead caused by ADTS + * + * \hAdts handle to ADTS data + * + * \return Amount of additional bits required for the current raw data block + */ +int adtsWrite_GetHeaderBits( HANDLE_ADTS hAdts ); + +/** + * \brief Write an ADTS header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hAdts ADTS data handle + * \param hBitStream bitstream handle into which the ADTS may be written into + * \param buffer_fullness the buffer fullness value for the ADTS header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT adtsWrite_EncodeHeader( + HANDLE_ADTS hAdts, + HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, + int frame_length + ); +/** + * \brief Finish a ADTS raw data block + * + * \param hAdts ADTS data handle + * \param hBs bitstream handle into which the ADTS may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit count, + * which is corrected to the current raw data block boundary. + * + */ +void adtsWrite_EndRawDataBlock( + HANDLE_ADTS hAdts, + HANDLE_FDK_BITSTREAM hBs, + int *bits + ); + + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC region + * + * \return ID for the created region, -1 in case of an error + */ +int adtsWrite_CrcStartReg( + HANDLE_ADTS pAdts, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by adtsWrite_CrcStartReg() + */ +void adtsWrite_CrcEndReg( + HANDLE_ADTS pAdts, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + + + + +#endif /* TPENC_ADTS_H */ + diff --git a/libMpegTPEnc/src/tpenc_asc.cpp b/libMpegTPEnc/src/tpenc_asc.cpp new file mode 100644 index 00000000..bc4302ef --- /dev/null +++ b/libMpegTPEnc/src/tpenc_asc.cpp @@ -0,0 +1,576 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): + Description: + +******************************************************************************/ + +#include "tp_data.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" +#include "FDK_bitstream.h" +#include "genericStds.h" + +#define PCE_MAX_ELEMENTS 8 + +/** + * Describe a PCE based on placed channel elements and element type sequence. + */ +typedef struct { + + UCHAR num_front_channel_elements; /*!< Number of front channel elements. */ + UCHAR num_side_channel_elements; /*!< Number of side channel elements. */ + UCHAR num_back_channel_elements; /*!< Number of back channel elements. */ + UCHAR num_lfe_channel_elements; /*!< Number of lfe channel elements. */ + MP4_ELEMENT_ID el_list[PCE_MAX_ELEMENTS];/*!< List contains sequence describing the elements + in present channel mode. (MPEG order) */ +} PCE_CONFIGURATION; + + +/** + * Map an incoming channel mode to a existing PCE configuration entry. + */ +typedef struct { + + CHANNEL_MODE channel_mode; /*!< Present channel mode. */ + PCE_CONFIGURATION pce_configuration; /*!< Program config element description. */ + +} CHANNEL_CONFIGURATION; + + +/** + * \brief Table contains all supported channel modes and according PCE configuration description. + * + * The number of channel element parameter describes the kind of consecutively elements. + * E.g. MODE_1_2_2_2_1 means: + * - First 3 elements (SCE,CPE,CPE) are front channel elements. + * - Next element (CPE) is a back channel element. + * - Last element (LFE) is a lfe channel element. + */ +static const CHANNEL_CONFIGURATION pceConfigTab[] = +{ + { MODE_1, { 1, 0, 0, 0, { ID_SCE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_2, { 1, 0, 0, 0, { ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_2, { 2, 0, 0, 0, { ID_SCE, ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_2_1, { 2, 0, 1, 0, { ID_SCE, ID_CPE, ID_SCE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_2_2, { 2, 0, 1, 0, { ID_SCE, ID_CPE, ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_2_2_1, { 2, 0, 1, 1, { ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_2_2_2_1, { 3, 0, 1, 1, { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE, ID_NONE, ID_NONE } } }, + + + { MODE_1_1, { 2, 0, 0, 0, { ID_SCE, ID_SCE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_1_1_1, { 2, 2, 0, 0, { ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_1_1_1_1_1_1, { 2, 2, 2, 0, { ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_NONE, ID_NONE } } }, + { MODE_1_1_1_1_1_1_1_1, { 3, 2, 3, 0, { ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE, ID_SCE } } }, + + { MODE_2_2, { 1, 0, 1, 0, { ID_CPE, ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_2_2_2, { 1, 1, 1, 0, { ID_CPE, ID_CPE, ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_2_2_2_2, { 4, 0, 0, 0, { ID_CPE, ID_CPE, ID_CPE, ID_CPE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + + { MODE_2_1, { 1, 0, 1, 0, { ID_CPE, ID_SCE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE } } }, + + { MODE_7_1_REAR_SURROUND, { 2, 0, 2, 1, { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE, ID_NONE, ID_NONE } } }, + { MODE_7_1_FRONT_CENTER, { 3, 0, 1, 1, { ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE, ID_NONE, ID_NONE } } }, + +}; + + +/** + * \brief Get program config element description for existing channel mode. + * + * \param channel_mode Current channel mode. + * + * \return + * - Pointer to PCE_CONFIGURATION entry, on success. + * - NULL, on failure. + */ +static const PCE_CONFIGURATION* getPceEntry( + const CHANNEL_MODE channel_mode + ) +{ + UINT i; + const PCE_CONFIGURATION *pce_config = NULL; + + for (i=0; i < (sizeof(pceConfigTab)/sizeof(CHANNEL_CONFIGURATION)); i++) { + if (pceConfigTab[i].channel_mode == channel_mode) { + pce_config = &pceConfigTab[i].pce_configuration; + } + } + + return pce_config; +} + +int getChannelConfig( CHANNEL_MODE channel_mode ) +{ + INT chan_config = 0; + + switch(channel_mode) { + case MODE_1: chan_config = 1; break; + case MODE_2: chan_config = 2; break; + case MODE_1_2: chan_config = 3; break; + case MODE_1_2_1: chan_config = 4; break; + case MODE_1_2_2: chan_config = 5; break; + case MODE_1_2_2_1: chan_config = 6; break; + case MODE_1_2_2_2_1: chan_config = 7; break; + + default: chan_config = 0; + } + + return chan_config; +} + +CHANNEL_MODE transportEnc_GetChannelMode( int noChannels ) +{ + CHANNEL_MODE chMode; + + if (noChannels <= 8 && noChannels > 0) + chMode = (CHANNEL_MODE)((noChannels == 8) ? 7 : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/ + else + chMode = MODE_UNKNOWN; + + return chMode; +} + +#ifdef TP_PCE_ENABLE +int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, + CHANNEL_MODE channelMode, + INT sampleRate, + int instanceTagPCE, + int profile, + int matrixMixdownA, + int pseudoSurroundEnable, + UINT alignAnchor) +{ + int sampleRateIndex, i; + const PCE_CONFIGURATION* config = NULL; + const MP4_ELEMENT_ID* pEl_list = NULL; + UCHAR cpeCnt=0, sceCnt=0, lfeCnt=0; + + sampleRateIndex = getSamplingRateIndex(sampleRate); + if (sampleRateIndex == 15) { + return -1; + } + + if ((config=getPceEntry(channelMode))==NULL) { + return -1; + } + + /* Pointer to first element in element list. */ + pEl_list = &config->el_list[0]; + + FDKwriteBits(hBs, instanceTagPCE, 4); /* Element instance tag */ + FDKwriteBits(hBs, profile, 2); /* Object type */ + FDKwriteBits(hBs, sampleRateIndex, 4); /* Sample rate index*/ + + FDKwriteBits(hBs, config->num_front_channel_elements, 4); /* Front channel Elements */ + FDKwriteBits(hBs, config->num_side_channel_elements , 4); /* No Side Channel Elements */ + FDKwriteBits(hBs, config->num_back_channel_elements , 4); /* No Back channel Elements */ + FDKwriteBits(hBs, config->num_lfe_channel_elements , 2); /* No Lfe channel elements */ + + FDKwriteBits(hBs, 0, 3); /* No assoc data elements */ + FDKwriteBits(hBs, 0, 4); /* No valid cc elements */ + FDKwriteBits(hBs, 0, 1); /* Mono mixdown present */ + FDKwriteBits(hBs, 0, 1); /* Stereo mixdown present */ + + if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) { + FDKwriteBits(hBs, 1, 1); /* Matrix mixdown present */ + FDKwriteBits(hBs, (matrixMixdownA-1)&0x3, 2); /* matrix_mixdown_idx */ + FDKwriteBits(hBs, (pseudoSurroundEnable)?1:0, 1); /* pseudo_surround_enable */ + } + else { + FDKwriteBits(hBs, 0, 1); /* Matrix mixdown not present */ + } + + for(i=0; inum_front_channel_elements; i++) { + UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0; + UCHAR tag = (isCpe) ? cpeCnt++ : sceCnt++; + FDKwriteBits(hBs, isCpe, 1); /* Front channel Elements is CPE? */ + FDKwriteBits(hBs, tag, 4); /* Front channel Instance Tag.*/ + } + for(i=0; inum_side_channel_elements; i++) { + UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0; + UCHAR tag = (isCpe) ? cpeCnt++ : sceCnt++; + FDKwriteBits(hBs, isCpe, 1); /* Front channel Elements is CPE? */ + FDKwriteBits(hBs, tag, 4); /* Front channel Instance Tag.*/ + } + for(i=0; inum_back_channel_elements; i++) { + UCHAR isCpe = (*pEl_list++==ID_CPE) ? 1 : 0; + UCHAR tag = (isCpe) ? cpeCnt++ : sceCnt++; + FDKwriteBits(hBs, isCpe, 1); /* Front channel Elements is CPE? */ + FDKwriteBits(hBs, tag, 4); /* Front channel Instance Tag.*/ + } + for(i=0; inum_lfe_channel_elements; i++) { + FDKwriteBits(hBs, lfeCnt++, 4); /* LFE channel Instance Tag. */ + } + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + /* Byte alignment: relative to alignAnchor + ADTS: align with respect to the first bit of the raw_data_block() + ADIF: align with respect to the first bit of the header + LATM: align with respect to the first bit of the ASC */ + FDKbyteAlign(hBs, alignAnchor); /* Alignment */ + + FDKwriteBits(hBs, 0 ,8); /* Do no write any comment. */ + + /* - comment_field_bytes always 0. */ + + return 0; +} + +int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, + int matrixMixdownA, + int bits) +{ + const PCE_CONFIGURATION* config = NULL; + + if ((config=getPceEntry(channelMode))==NULL) { + return -1; /* unsupported channelmapping */ + } + + bits += 4 + 2 + 4; /* Element instance tag + Object type + Sample rate index */ + bits += 4 + 4 + 4 + 2; /* No (front + side + back + lfe channel) elements */ + bits += 3 + 4; /* No (assoc data + valid cc) elements */ + bits += 1 + 1 + 1 ; /* Mono + Stereo + Matrix mixdown present */ + + if ( matrixMixdownA!=0 && ((channelMode==MODE_1_2_2)||(channelMode==MODE_1_2_2_1)) ) { + bits +=3; /* matrix_mixdown_idx + pseudo_surround_enable */ + } + + bits += (1+4) * (INT)config->num_front_channel_elements; + bits += (1+4) * (INT)config->num_side_channel_elements; + bits += (1+4) * (INT)config->num_back_channel_elements; + bits += (4) * (INT)config->num_lfe_channel_elements; + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + if ((bits%8) != 0) { + bits += (8 - (bits%8)); /* Alignment */ + } + + bits += 8; /* Comment field bytes */ + + /* - comment_field_bytes alwys 0. */ + + return bits; +} +#endif /* TP_PCE_ENABLE */ + +static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, AUDIO_OBJECT_TYPE aot) +{ + int tmp = (int) aot; + + if (tmp > 31) { + FDKwriteBits( hBitstreamBuffer, AOT_ESCAPE, 5 ); + FDKwriteBits( hBitstreamBuffer, tmp-32, 6 ); /* AudioObjectType */ + } else { + FDKwriteBits( hBitstreamBuffer, tmp, 5 ); + } +} + +static void writeSampleRate(HANDLE_FDK_BITSTREAM hBitstreamBuffer, int sampleRate) +{ + int sampleRateIndex = getSamplingRateIndex(sampleRate); + + FDKwriteBits( hBitstreamBuffer, sampleRateIndex, 4 ); + if( sampleRateIndex == 15 ) { + FDKwriteBits( hBitstreamBuffer, sampleRate, 24 ); + } +} + +#ifdef TP_GA_ENABLE +static +int transportEnc_writeGASpecificConfig( + HANDLE_FDK_BITSTREAM asc, + CODER_CONFIG *config, + int extFlg, + UINT alignAnchor + ) +{ + int aot = config->aot; + int samplesPerFrame = config->samplesPerFrame; + + /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits( asc, ((samplesPerFrame==960 || samplesPerFrame==480)?1:0), 1); /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 (I)MDCT*/ + FDKwriteBits( asc, 0, 1); /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits( asc, extFlg, 1 ); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */ + + /* Write PCE if channel config is not 1-7 */ + if (getChannelConfig(config->channelMode) == 0) { + transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, config->matrixMixdownA, (config->flags&CC_PSEUDO_SURROUND)?1:0, alignAnchor); + } + if (extFlg) { + if (aot == AOT_ER_BSAC) { + FDKwriteBits( asc, config->BSACnumOfSubFrame, 5 ); /* numOfSubFrame */ + FDKwriteBits( asc, config->BSAClayerLength, 11 ); /* layer_length */ + } + if ((aot == AOT_ER_AAC_LC) || (aot == AOT_ER_AAC_LTP) || + (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD)) + { + FDKwriteBits( asc, (config->flags & CC_VCB11) ? 1 : 0, 1 ); /* aacSectionDataResillienceFlag */ + FDKwriteBits( asc, (config->flags & CC_RVLC) ? 1 : 0, 1 ); /* aacScaleFactorDataResillienceFlag */ + FDKwriteBits( asc, (config->flags & CC_HCR) ? 1 : 0, 1 ); /* aacSpectralDataResillienceFlag */ + } + FDKwriteBits( asc, 0, 1 ); /* extensionFlag3: reserved. Shall be '0' */ + } + return 0; +} +#endif /* TP_GA_ENABLE */ + +#ifdef TP_ELD_ENABLE + +static +int transportEnc_writeELDSpecificConfig( + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *config, + int epConfig, + CSTpCallBacks *cb + ) +{ + /* ELD specific config */ + if (config->channelMode == MODE_1_1) { + return -1; + } + FDKwriteBits(hBs, (config->samplesPerFrame == 480) ? 1 : 0, 1); + + FDKwriteBits(hBs, (config->flags & CC_VCB11 ) ? 1:0, 1); + FDKwriteBits(hBs, (config->flags & CC_RVLC ) ? 1:0, 1); + FDKwriteBits(hBs, (config->flags & CC_HCR ) ? 1:0, 1); + + FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1:0, 1); /* SBR header flag */ + if ( (config->flags & CC_SBR) ) { + FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0:1, 1); /* Samplerate Flag */ + FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1:0, 1); /* SBR CRC flag*/ + + if (cb->cbSbr != NULL) { + const PCE_CONFIGURATION *pPce; + int e; + + pPce = getPceEntry(config->channelMode); + + for (e=0; eel_list[e] != ID_NONE; e++ ) { + if ( (pPce->el_list[e] == ID_SCE) || (pPce->el_list[e] == ID_CPE) ) { + cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->el_list[e], e); + } + } + } + } + + FDKwriteBits(hBs, 0, 4); /* ELDEXT_TERM */ + + return 0; +} +#endif /* TP_ELD_ENABLE */ + + +int transportEnc_writeASC ( + HANDLE_FDK_BITSTREAM asc, + CODER_CONFIG *config, + CSTpCallBacks *cb + ) +{ + UINT extFlag = 0; + int err; + int epConfig = 0; + + /* Required for the PCE. */ + UINT alignAnchor = FDKgetValidBits(asc); + + /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */ + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_USAC: + extFlag = 1; + break; + default: + break; + } + + if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) + writeAot(asc, config->extAOT); + else + writeAot(asc, config->aot); + + { + writeSampleRate(asc, config->samplingRate); + } + + /* Try to guess a reasonable channel mode if not given */ + if (config->channelMode == MODE_INVALID) { + config->channelMode = transportEnc_GetChannelMode(config->noChannels); + if (config->channelMode == MODE_INVALID) + return -1; + } + + FDKwriteBits( asc, getChannelConfig(config->channelMode), 4 ); + + if (config->sbrSignaling==SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) { + writeSampleRate(asc, config->extSamplingRate); + writeAot(asc, config->aot); + } + + switch (config->aot) { +#ifdef TP_GA_ENABLE + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_SSR: + case AOT_AAC_LTP: + case AOT_AAC_SCAL: + case AOT_TWIN_VQ: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + err = transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor); + if (err) + return err; + break; +#endif /* TP_GA_ENABLE */ +#ifdef TP_ELD_ENABLE + case AOT_ER_AAC_ELD: + err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb); + if (err) + return err; + break; +#endif /* TP_ELD_ENABLE */ + default: + return -1; + } + + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_HILN: + case AOT_ER_PARA: + case AOT_ER_AAC_ELD: + FDKwriteBits( asc, 0, 2 ); /* epconfig 0 */ + break; + default: + break; + } + + /* backward compatible explicit signaling of extension AOT */ + if (config->sbrSignaling==SIG_EXPLICIT_BW_COMPATIBLE) + { + TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN; + + if (config->sbrPresent) { + ascExtId=ASCEXT_SBR; + FDKwriteBits( asc, ascExtId, 11 ); + writeAot(asc, config->extAOT); + FDKwriteBits( asc, 1, 1 ); /* sbrPresentFlag=1 */ + writeSampleRate(asc, config->extSamplingRate); + if (config->psPresent) { + ascExtId=ASCEXT_PS; + FDKwriteBits( asc, ascExtId, 11 ); + FDKwriteBits( asc, 1, 1 ); /* psPresentFlag=1 */ + } + } + + } + + /* Make sure all bits are sync'ed */ + FDKsyncCache( asc ); + + return 0; +} diff --git a/libMpegTPEnc/src/tpenc_asc.h b/libMpegTPEnc/src/tpenc_asc.h new file mode 100644 index 00000000..47fe7a16 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_asc.h @@ -0,0 +1,142 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): Manuel Jander + Description: Audio Specific Config writer + +******************************************************************************/ + +#ifndef TPENC_ASC_H +#define TPENC_ASC_H + +/** + * \brief Get channel config from channel mode. + * + * \param channel_mode channel mode + * + * \return chanel config + */ +int getChannelConfig( CHANNEL_MODE channel_mode ); + +/** + * \brief Write a Program Config Element. + * + * \param hBs bitstream handle into which the PCE is appended + * \param channelMode the channel mode to be used + * \param sampleRate the sample rate + * \param instanceTagPCE the instance tag of the Program Config Element + * \param profile the MPEG Audio profile to be used + * \param matrix mixdown gain + * \param pseudo surround indication + * \param reference bitstream position for alignment + * \return zero on success, non-zero on failure. + */ +int transportEnc_writePCE( + HANDLE_FDK_BITSTREAM hBs, + CHANNEL_MODE channelMode, + INT sampleRate, + int instanceTagPCE, + int profile, + int matrixMixdownA, + int pseudoSurroundEnable, + UINT alignAnchor + ); + +/** + * \brief Get the bit count required by a Program Config Element + * + * \param channelMode the channel mode to be used + * \param matrix mixdown gain + * \param bit offset at which the PCE would start + * \return the amount of bits required for the PCE including the given bit offset. + */ +int transportEnc_GetPCEBits( + CHANNEL_MODE channelMode, + int matrixMixdownA, + int bits + ); + +#endif /* TPENC_ASC_H */ + diff --git a/libMpegTPEnc/src/tpenc_dab.cpp b/libMpegTPEnc/src/tpenc_dab.cpp new file mode 100644 index 00000000..202fecf9 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_dab.cpp @@ -0,0 +1,467 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport Headers support + +******************************************************************************/ +#include +#include "FDK_audio.h" +#include "tpenc_dab.h" + + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +#include "common_fix.h" + +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, /*!< pointer to dab stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcStartReg(%p): bits in crc region=%d\n", hBs, mBits); + return ( FDKcrcStartReg(&pDab->crcInfo2, hBs, mBits) ); +} + +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, /*!< pointer to dab crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcEndReg(%p): crc region=%d\n", hBs, reg); + FDKcrcEndReg(&pDab->crcInfo2, hBs, reg); +} + +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ) +{ + int bits = 0; + + if (hDab->currentBlock == 0) { + /* Static and variable header bits */ + bits += 16; //header_firecode 16 + bits += 8; //rfa=1, dac_rate=1, sbr_flag=1, aac_channel_mode=1, ps_flag=1, mpeg_surround_config=3 + bits += 12 * hDab->num_raw_blocks; //au_start[1...num_aus] 12 bit AU start position markers + + //4 byte alignment + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) + bits+=4; + //16sbr => 16 + 5 + 3 + 12*(2-1) => 36 => 40 bits 5 + //24sbr => 16 + 5 + 3 + 12*(3-1) => 48 ok 6 + //32sbr => 16 + 5 + 3 + 12*(4-1) => 60 => 64 bits 8 + //48sbr => 16 + 5 + 3 + 12*(6-1) => 84 => 88 bits 11 + } + + /* Add raw data block CRC bits. Not really part of the header, put they cause bit overhead to be accounted. */ + bits += 16; + + + return bits; +} + + +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ) +{ + //fprintf(stderr, "streamDataLength=%d (%d bytes)\n", streamDataLength, streamDataLength >> 3); + return dabWrite_GetHeaderBits(hDab); +} + + +INT dabWrite_Init(HANDLE_DAB hDab, CODER_CONFIG *config) +{ + /* Sanity checks */ + if((int)config->aot > 4 + || (int)config->aot < 1 ) { + return -1; + } + + /* Sanity checks DAB-specific */ + if ( !(config->nSubFrames == 2 && config->samplingRate == 16000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 3 && config->samplingRate == 24000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 4 && config->samplingRate == 32000) && + !(config->nSubFrames == 6 && config->samplingRate == 48000)) { + return -1; + } + + hDab->dac_rate = 0; + hDab->aac_channel_mode=0; + hDab->sbr_flag = 0; + hDab->ps_flag = 0; + hDab->mpeg_surround_config=0; + hDab->subchannels_num=config->bitRate/8000; + + + if(config->samplingRate == 24000 || config->samplingRate == 48000) + hDab->dac_rate = 1; + + if (config->extAOT==AOT_SBR || config->extAOT == AOT_PS) + hDab->sbr_flag = 1; + + if(config->extAOT == AOT_PS) + hDab->ps_flag = 1; + + + if(config->channelMode == MODE_2) + hDab->aac_channel_mode = 1; + + //fprintf(stderr, "hDab->dac_rate=%d\n", hDab->dac_rate); + //fprintf(stderr, "hDab->sbr_flag=%d\n", hDab->sbr_flag); + //fprintf(stderr, "hDab->ps_flag=%d\n", hDab->ps_flag); + //fprintf(stderr, "hDab->aac_channel_mode=%d\n", hDab->aac_channel_mode); + //fprintf(stderr, "hDab->subchannels_num=%d\n", hDab->subchannels_num); + //fprintf(stderr, "cc->nSubFrames=%d\n", config->nSubFrames); + + hDab->num_raw_blocks=config->nSubFrames-1; /* 0 means 1 raw data block */ + + FDKcrcInit(&hDab->crcInfo, 0x1021, 0xFFFF, 16); + FDKcrcInit(&hDab->crcFire, 0x782d, 0, 16); + FDKcrcInit(&hDab->crcInfo2, 0x8005, 0xFFFF, 16); + + hDab->currentBlock = 0; + hDab->headerBits = dabWrite_GetHeaderBits(hDab); + + return 0; +} + +int dabWrite_EncodeHeader(HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, + int frame_length) +{ + INT crcIndex = 0; + + + FDK_ASSERT(((frame_length+hDab->headerBits)/8)<0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ + + FDKcrcReset(&hDab->crcInfo); + + +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->currentBlock=%d, frame_length=%d, buffer_fullness=%d\n", +// hDab->currentBlock, frame_length, buffer_fullness); + +// if (hDab->currentBlock == 0) { +// //hDab->subFrameStartPrev=dabWrite_GetHeaderBits(hDab); +// fprintf(stderr, "header bits[%d] [%d]\n", hDab->subFrameStartPrev, hDab->subFrameStartPrev >> 3); +// FDKresetBitbuffer(hBitStream, BS_WRITER); +// } + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->subFrameStartBit=%d [%d]\n", hDab->subFrameStartBit, hDab->subFrameStartBit >> 3); + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + /* Skip new header if this is raw data block 1..n */ + if (hDab->currentBlock == 0) + { + FDKresetBitbuffer(hBitStream, BS_WRITER); +// fprintf(stderr, "dabWrite_EncodeHeader() after FDKresetBitbuffer=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + + /* fixed header */ + FDKwriteBits(hBitStream, 0, 16); //header_firecode + FDKwriteBits(hBitStream, 0, 1); //rfa + FDKwriteBits(hBitStream, hDab->dac_rate, 1); + FDKwriteBits(hBitStream, hDab->sbr_flag, 1); + FDKwriteBits(hBitStream, hDab->aac_channel_mode, 1); + FDKwriteBits(hBitStream, hDab->ps_flag, 1); + FDKwriteBits(hBitStream, hDab->mpeg_surround_config, 3); + /* variable header */ + int i; + for(i=0; inum_raw_blocks; i++) + FDKwriteBits(hBitStream, 0, 12); + /* padding */ + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) { + FDKwriteBits(hBitStream, 0, 4); + } + } /* End of DAB header */ + + hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + FDK_ASSERT(FDKgetValidBits(hBitStream) % 8 == 0); //only aligned header + +// fprintf(stderr, "dabWrite_EncodeHeader() FDKgetValidBits(hBitStream)=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + return 0; +} + +int dabWrite_writeExtensionFillPayload(HANDLE_FDK_BITSTREAM hBitStream, int extPayloadBits) +{ +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + + INT extBitsUsed = 0; + INT extPayloadType = EXT_FIL; + //fprintf(stderr, "FDKaacEnc_writeExtensionPayload() extPayloadType=%d\n", extPayloadType); + if (extPayloadBits >= EXT_TYPE_BITS) + { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + case EXT_FILL_DATA: + fillByte = 0xA5; + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = extPayloadBits; + FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS); + writeBits -= 8; /* acount for the extension type and the fill nibble */ + while (writeBits >= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + +void dabWrite_FillRawDataBlock(HANDLE_FDK_BITSTREAM hBitStream, int payloadBits) +{ + INT extBitsUsed = 0; +#define EL_ID_BITS ( 3 ) +#define FILL_EL_COUNT_BITS ( 4 ) +#define FILL_EL_ESC_COUNT_BITS ( 8 ) +#define MAX_FILL_DATA_BYTES ( 269 ) + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count=-1, alignBits=7; + + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15*8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits+alignBits)>>3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + ((esc_count>=0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt*8, payloadBits); /* convert back to bits */ +#if 0 + extBitsUsed += FDKaacEnc_writeExtensionPayload( hBitStream, + pExtension->type, + pExtension->pPayload, + cnt ); +#else + extBitsUsed += dabWrite_writeExtensionFillPayload(hBitStream, cnt); +#endif + payloadBits -= cnt; + } +} + +void dabWrite_EndRawDataBlock(HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBs, + int *pBits) +{ + FDK_BITSTREAM bsWriter; + INT crcIndex = 0; + USHORT crcData; + INT writeBits=0; + INT writeBitsNonLastBlock=0; + INT writeBitsLastBlock=0; +#if 1 + if (hDab->currentBlock == hDab->num_raw_blocks) { + //calculate byte-alignment before writing ID_FIL + if((FDKgetValidBits(hBs)+3) % 8){ + writeBits = 8 - ((FDKgetValidBits(hBs)+3) % 8); + } + + INT offset_end = hDab->subchannels_num*110*8 - 2*8 - 3; + writeBitsLastBlock = offset_end - FDKgetValidBits(hBs); + dabWrite_FillRawDataBlock(hBs, writeBitsLastBlock); + FDKsyncCache(hBs); + //fprintf(stderr, "FIL-element written=%d\n", writeBitsLastBlock); + writeBitsLastBlock=writeBits; + } +#endif + FDKwriteBits(hBs, 7, 3); //finalize AU: ID_END + FDKsyncCache(hBs); + //byte-align (if ID_FIL doesn't align it). + if(FDKgetValidBits(hBs) % 8){ + writeBits = 8 - (FDKgetValidBits(hBs) % 8); + FDKwriteBits(hBs, 0x00, writeBits); + FDKsyncCache(hBs); + } + + //fake-written bits alignment for last AU + if (hDab->currentBlock == hDab->num_raw_blocks) + writeBits=writeBitsLastBlock; + + INT frameLen = (FDKgetValidBits(hBs) - hDab->subFrameStartBit) >> 3; + //fprintf(stderr, "frame=%d, offset writeBits=%d\n", frameLen, writeBits); + + FDK_ASSERT(FDKgetValidBits(hBs) % 8 == 0); //only aligned au's + FDK_ASSERT(hDab->subchannels_num*110*8 >= FDKgetValidBits(hBs)+2*8); //don't overlap superframe + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, hDab->subFrameStartBit); + FDKcrcReset(&hDab->crcInfo); + hDab->crcIndex = FDKcrcStartReg(&hDab->crcInfo, &bsWriter, 0); +#if 0 + if (hDab->currentBlock == hDab->num_raw_blocks) { + INT offset_size = hDab->subchannels_num*110*8 - 2*8 - FDKgetValidBits(hBs); + //fprintf(stderr, "offset_size=%d\n", offset_size >> 3); + FDKpushFor(hBs, offset_size); + } +#endif + + FDKpushFor(&bsWriter, FDKgetValidBits(hBs) - hDab->subFrameStartBit); + FDKcrcEndReg(&hDab->crcInfo, &bsWriter, hDab->crcIndex); + crcData = FDKcrcGetCRC(&hDab->crcInfo); + //fprintf(stderr, "crcData = %04x\n", crcData); + /* Write inverted CRC of current raw data block */ + FDKwriteBits(hBs, crcData ^ 0xffff, 16); + FDKsyncCache(hBs); + + + /* Write distance to current data block */ + if(hDab->currentBlock) { + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 24 + (hDab->currentBlock-1)*12); + //fprintf(stderr, "FDKwriteBits() = %d\n", hDab->subFrameStartBit>>3); + FDKwriteBits(&bsWriter, (hDab->subFrameStartBit>>3), 12); + FDKsyncCache(&bsWriter); + } + + /* Write FireCode */ + if (hDab->currentBlock == hDab->num_raw_blocks) { + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 16); + + FDKcrcReset(&hDab->crcFire); + crcIndex = FDKcrcStartReg(&hDab->crcFire, &bsWriter, 72); + FDKpushFor(&bsWriter, 9*8); //9bytes + FDKcrcEndReg(&hDab->crcFire, &bsWriter, crcIndex); + + crcData = FDKcrcGetCRC(&hDab->crcFire); + //fprintf(stderr, "Firecode: %04x\n", crcData); + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKwriteBits(&bsWriter, crcData, 16); + FDKsyncCache(&bsWriter); + } + + if (hDab->currentBlock == 0) + *pBits += hDab->headerBits; + else + *pBits += 16; + + *pBits += writeBits + 3; //size: ID_END + alignment + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hDab->subFrameStartBit; + /* Fixup CRC bits, since they come after each raw data block */ + + hDab->currentBlock++; + //fprintf(stderr, "dabWrite_EndRawDataBlock() *pBits=%d (%d)\n", *pBits, *pBits >> 3); +} + diff --git a/libMpegTPEnc/src/tpenc_dab.h b/libMpegTPEnc/src/tpenc_dab.h new file mode 100644 index 00000000..17b83c69 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_dab.h @@ -0,0 +1,217 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport writer + +******************************************************************************/ + +#ifndef TPENC_DAB_H +#define TPENC_DAB_H + + + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + USHORT frame_length; + UCHAR dac_rate; + UCHAR aac_channel_mode; + UCHAR sbr_flag; + UCHAR ps_flag; + UCHAR mpeg_surround_config; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + int subchannels_num; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block begins */ + //int subFrameStartPrev; /*!< Bit position where the previous raw data block begins */ + int crcIndex; + FDK_CRCINFO crcInfo; + FDK_CRCINFO crcFire; + FDK_CRCINFO crcInfo2; + USHORT tab[256]; +} STRUCT_DAB; + +typedef STRUCT_DAB *HANDLE_DAB; + +/** + * \brief Initialize DAB data structure + * + * \param hDab DAB data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the DAB header is extrated from + * + * \return 0 in case of success. + */ +INT dabWrite_Init( + HANDLE_DAB hDab, + CODER_CONFIG *config + ); + +/** + * \brief Get the total bit overhead caused by DAB + * + * \hDab handle to DAB data + * + * \return Amount of additional bits required for the current raw data block + */ +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ); +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ); + +/** + * \brief Write an DAB header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hDab DAB data handle + * \param hBitStream bitstream handle into which the DAB may be written into + * \param buffer_fullness the buffer fullness value for the DAB header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT dabWrite_EncodeHeader( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, + int frame_length + ); +/** + * \brief Finish a DAB raw data block + * + * \param hDab DAB data handle + * \param hBs bitstream handle into which the DAB may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit count, + * which is corrected to the current raw data block boundary. + * + */ +void dabWrite_EndRawDataBlock( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBs, + int *bits + ); + + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC region + * + * \return ID for the created region, -1 in case of an error + */ +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by dabWrite_CrcStartReg() + */ +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + + + + +#endif /* TPENC_DAB_H */ + diff --git a/libMpegTPEnc/src/tpenc_latm.cpp b/libMpegTPEnc/src/tpenc_latm.cpp new file mode 100644 index 00000000..f292019d --- /dev/null +++ b/libMpegTPEnc/src/tpenc_latm.cpp @@ -0,0 +1,881 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): + Description: + +******************************************************************************/ + +#include "tpenc_latm.h" + + +#include "genericStds.h" + +static const short celpFrameLengthTable[64] = { + 154, 170, 186, 147, 156, 165, 114, 120, + 186, 126, 132, 138, 142, 146, 154, 166, + 174, 182, 190, 198, 206, 210, 214, 110, + 114, 118, 120, 122, 218, 230, 242, 254, + 266, 278, 286, 294, 318, 342, 358, 374, + 390, 406, 422, 136, 142, 148, 154, 160, + 166, 170, 174, 186, 198, 206, 214, 222, + 230, 238, 216, 160, 280, 338, 0, 0 +}; + +/******* + write value to transport stream + first two bits define the size of the value itself + then the value itself, with a size of 0-3 bytes +*******/ +static +UINT transportEnc_LatmWriteValue(HANDLE_FDK_BITSTREAM hBs, int value) +{ + UCHAR valueBytes = 4; + unsigned int bitsWritten = 0; + int i; + + if ( value < (1<<8) ) { + valueBytes = 1; + } else if ( value < (1<<16) ) { + valueBytes = 2; + } else if ( value < (1<<24) ) { + valueBytes = 3; + } else { + valueBytes = 4; + } + + FDKwriteBits(hBs, valueBytes-1, 2 ); /* size of value in Bytes */ + for (i=0; i>((valueBytes-1-i)<<3)), 8); + } + + bitsWritten = (valueBytes<<3)+2; + + return bitsWritten; +} + +static +UINT transportEnc_LatmCountFixBitDemandHeader ( HANDLE_LATM_STREAM hAss ) +{ + int bitDemand = 0; + int insertSetupData = 0 ; + + /* only if start of new latm frame */ + if (hAss->subFrameCnt==0) + { + /* AudioSyncStream */ + + if (hAss->tt == TT_MP4_LOAS) { + bitDemand += 11 ; /* syncword */ + bitDemand += 13 ; /* audioMuxLengthBytes */ + } + + /* AudioMuxElement*/ + + /* AudioMuxElement::Stream Mux Config */ + if (hAss->muxConfigPeriod > 0) { + insertSetupData = (hAss->latmFrameCounter == 0); + } else { + insertSetupData = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + /* AudioMuxElement::useSameStreamMux Flag */ + bitDemand+=1; + + if( insertSetupData ) { + bitDemand += hAss->streamMuxConfigBits; + } + } + + /* AudioMuxElement::otherDataBits */ + bitDemand += 8*hAss->otherDataLenBytes; + + /* AudioMuxElement::ByteAlign */ + if ( bitDemand % 8 ) { + hAss->fillBits = 8 - (bitDemand % 8); + bitDemand += hAss->fillBits ; + } else { + hAss->fillBits = 0; + } + } + + return bitDemand ; +} + +static +UINT transportEnc_LatmCountVarBitDemandHeader ( HANDLE_LATM_STREAM hAss , unsigned int streamDataLength ) +{ + int bitDemand = 0; + int prog, layer; + + /* Payload Length Info*/ + if( hAss->allStreamsSameTimeFraming ) { + for( prog=0; prognoProgram; prog++ ) { + for( layer=0; layerm_linfo[prog][layer]); + + if( p_linfo->streamID >= 0 ) { + switch( p_linfo->frameLengthType ) { + case 0: + if ( streamDataLength > 0 ) { + streamDataLength -= bitDemand ; + while( streamDataLength >= (255<<3) ) { + bitDemand+=8; + streamDataLength -= (255<<3); + } + bitDemand += 8; + } + break; + + case 1: + case 4: + case 6: + bitDemand += 2; + break; + + default: + return 0; + } + } + } + } + } else { + /* there are many possibilities to use this mechanism. */ + switch( hAss->varMode ) { + case LATMVAR_SIMPLE_SEQUENCE: { + /* Use the sequence generated by the encoder */ + //int streamCntPosition = transportEnc_SetWritePointer( hAss->hAssemble, 0 ); + //int streamCntPosition = FDKgetValidBits( hAss->hAssemble ); + bitDemand+=4; + + hAss->varStreamCnt = 0; + for( prog=0; prognoProgram; prog++ ) { + for( layer=0; layerm_linfo[prog][layer]); + + if( p_linfo->streamID >= 0 ) { + + bitDemand+=4; /* streamID */ + switch( p_linfo->frameLengthType ) { + case 0: + streamDataLength -= bitDemand ; + while( streamDataLength >= (255<<3) ) { + bitDemand+=8; + streamDataLength -= (255<<3); + } + + bitDemand += 8; + break; + /*bitDemand += 1; endFlag + break;*/ + + case 1: + case 4: + case 6: + + break; + + default: + return 0; + } + hAss->varStreamCnt++; + } + } + } + bitDemand+=4; + //transportEnc_UpdateBitstreamField( hAss->hAssemble, streamCntPosition, hAss->varStreamCnt-1, 4 ); + //UINT pos = streamCntPosition-FDKgetValidBits(hAss->hAssemble); + //FDKpushBack( hAss->hAssemble, pos); + //FDKwriteBits( hAss->hAssemble, hAss->varStreamCnt-1, 4); + //FDKpushFor( hAss->hAssemble, pos-4); + } + break; + + default: + return 0; + } + } + + return bitDemand ; +} + +TRANSPORTENC_ERROR +CreateStreamMuxConfig( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, + CSTpCallBacks *cb + ) +{ + INT streamIDcnt, tmp; + int layer, prog; + + USHORT coreFrameOffset=0; + + hAss->taraBufferFullness = 0xFF; + hAss->audioMuxVersionA = 0; /* for future extensions */ + hAss->streamMuxConfigBits = 0; + + FDKwriteBits( hBs, hAss->audioMuxVersion, 1 ); /* audioMuxVersion */ + hAss->streamMuxConfigBits += 1; + + if ( hAss->audioMuxVersion == 1 ) { + FDKwriteBits( hBs, hAss->audioMuxVersionA, 1 ); /* audioMuxVersionA */ + hAss->streamMuxConfigBits+=1; + } + + if ( hAss->audioMuxVersionA == 0 ) + { + if ( hAss->audioMuxVersion == 1 ) { + hAss->streamMuxConfigBits+= transportEnc_LatmWriteValue( hBs, hAss->taraBufferFullness );/* taraBufferFullness */ + } + FDKwriteBits( hBs, hAss->allStreamsSameTimeFraming ? 1:0, 1 ); /* allStreamsSameTimeFraming */ + FDKwriteBits( hBs, hAss->noSubframes-1, 6 ); /* Number of Subframes */ + FDKwriteBits( hBs, hAss->noProgram-1, 4 ); /* Number of Programs */ + + hAss->streamMuxConfigBits+=11; + + streamIDcnt = 0; + for( prog=0; prognoProgram; prog++ ) { + int transLayer = 0; + + FDKwriteBits( hBs, hAss->noLayer[prog]-1, 3 ); + hAss->streamMuxConfigBits+=3; + + for( layer=0; layerm_linfo[prog][layer]); + CODER_CONFIG *p_lci = hAss->config[prog][layer]; + + p_linfo->streamID = -1; + + if( hAss->config[prog][layer] != NULL ) { + int useSameConfig = 0; + + if( transLayer > 0 ) { + FDKwriteBits( hBs, useSameConfig ? 1 : 0, 1 ); + hAss->streamMuxConfigBits+=1; + } + if( (useSameConfig == 0) || (transLayer==0) ) { + const UINT alignAnchor = FDKgetValidBits(hBs); + + transportEnc_writeASC( + hBs, + hAss->config[prog][layer], + cb + ); + + if ( hAss->audioMuxVersion == 1 ) { + UINT ascLen = transportEnc_LatmWriteValue(hBs, 0); + FDKbyteAlign(hBs, alignAnchor); + ascLen = FDKgetValidBits(hBs) - alignAnchor - ascLen; + FDKpushBack(hBs, FDKgetValidBits(hBs) - alignAnchor); + + transportEnc_LatmWriteValue(hBs, ascLen); + + transportEnc_writeASC( + hBs, + hAss->config[prog][layer], + cb + ); + + FDKbyteAlign(hBs, alignAnchor); /* asc length fillbits */ + } + + hAss->streamMuxConfigBits += FDKgetValidBits(hBs) - alignAnchor; /* add asc length to smc summary */ + } + transLayer++; + + if( !hAss->allStreamsSameTimeFraming ) { + if( streamIDcnt >= LATM_MAX_STREAM_ID ) + return TRANSPORTENC_INVALID_CONFIG; + } + p_linfo->streamID = streamIDcnt++; + + switch( p_lci->aot ) { + case AOT_AAC_MAIN : + case AOT_AAC_LC : + case AOT_AAC_SSR : + case AOT_AAC_LTP : + case AOT_AAC_SCAL : + case AOT_ER_AAC_LD : + case AOT_ER_AAC_ELD : + case AOT_USAC: + p_linfo->frameLengthType = 0; + + FDKwriteBits( hBs, p_linfo->frameLengthType, 3 ); /* frameLengthType */ + FDKwriteBits( hBs, bufferFullness, 8 ); /* bufferFullness */ + hAss->streamMuxConfigBits+=11; + + if ( !hAss->allStreamsSameTimeFraming ) { + CODER_CONFIG *p_lci_prev = hAss->config[prog][layer-1]; + if ( ((p_lci->aot == AOT_AAC_SCAL) || (p_lci->aot == AOT_ER_AAC_SCAL)) && + ((p_lci_prev->aot == AOT_CELP) || (p_lci_prev->aot == AOT_ER_CELP)) ) { + FDKwriteBits( hBs, coreFrameOffset, 6 ); /* coreFrameOffset */ + hAss->streamMuxConfigBits+=6; + } + } + break; + + case AOT_TWIN_VQ: + p_linfo->frameLengthType = 1; + tmp = ( (p_lci->bitsFrame+7) >> 3 ) - 20; /* transmission frame length in bytes */ + if( (tmp < 0) ) { + return TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH; + } + FDKwriteBits( hBs, p_linfo->frameLengthType, 3 ); /* frameLengthType */ + FDKwriteBits( hBs, tmp, 9 ); + hAss->streamMuxConfigBits+=12; + + p_linfo->frameLengthBits = (tmp+20) << 3; + break; + + case AOT_CELP: + p_linfo->frameLengthType = 4; + FDKwriteBits( hBs, p_linfo->frameLengthType, 3 ); /* frameLengthType */ + hAss->streamMuxConfigBits+=3; + { + int i; + for( i=0; i<62; i++ ) { + if( celpFrameLengthTable[i] == p_lci->bitsFrame ) + break; + } + if( i>=62 ) { + return TRANSPORTENC_INVALID_CELP_FRAME_LENGTH; + } + + FDKwriteBits( hBs, i, 6 ); /* CELPframeLengthTabelIndex */ + hAss->streamMuxConfigBits+=6; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_HVXC: + p_linfo->frameLengthType = 6; + FDKwriteBits( hBs, p_linfo->frameLengthType, 3 ); /* frameLengthType */ + hAss->streamMuxConfigBits+=3; + { + int i; + + if( p_lci->bitsFrame == 40 ) { + i = 0; + } else if( p_lci->bitsFrame == 80 ) { + i = 1; + } else { + return TRANSPORTENC_INVALID_FRAME_BITS; + } + FDKwriteBits( hBs, i, 1 ); /* HVXCframeLengthTableIndex */ + hAss->streamMuxConfigBits+=1; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_NULL_OBJECT: + default: + return TRANSPORTENC_INVALID_AOT; + } + } + } + } + + FDKwriteBits( hBs, (hAss->otherDataLenBytes>0) ? 1:0, 1 ); /* otherDataPresent */ + hAss->streamMuxConfigBits+=1; + + if( hAss->otherDataLenBytes > 0 ) { + + INT otherDataLenTmp = hAss->otherDataLenBytes; + INT escCnt = 0; + INT otherDataLenEsc = 1; + + while(otherDataLenTmp) { + otherDataLenTmp >>= 8; + escCnt ++; + } + + do { + otherDataLenTmp = (hAss->otherDataLenBytes>>(escCnt*8)) & 0xFF; + escCnt--; + otherDataLenEsc = escCnt>0; + + FDKwriteBits( hBs, otherDataLenEsc, 1 ); + FDKwriteBits( hBs, otherDataLenTmp, 8 ); + hAss->streamMuxConfigBits+=9; + } while(otherDataLenEsc); + } + + { + USHORT crcCheckPresent=0; + USHORT crcCheckSum=0; + + FDKwriteBits( hBs, crcCheckPresent, 1 ); /* crcCheckPresent */ + hAss->streamMuxConfigBits+=1; + if ( crcCheckPresent ){ + FDKwriteBits( hBs, crcCheckSum, 8 ); /* crcCheckSum */ + hAss->streamMuxConfigBits+=8; + } + } + + } else { /* if ( audioMuxVersionA == 0 ) */ + + /* for future extensions */ + + } + + return TRANSPORTENC_OK; +} + + +static TRANSPORTENC_ERROR +WriteAuPayloadLengthInfo( HANDLE_FDK_BITSTREAM hBitStream, int AuLengthBits ) +{ + int restBytes; + + if( AuLengthBits % 8 ) + return TRANSPORTENC_INVALID_AU_LENGTH; + + while( AuLengthBits >= 255*8 ) { + FDKwriteBits( hBitStream, 255, 8 ); /* 255 shows incomplete AU */ + AuLengthBits -= (255*8); + } + + restBytes = (AuLengthBits) >> 3; + FDKwriteBits( hBitStream, restBytes, 8 ); + + return TRANSPORTENC_OK; +} + +static +TRANSPORTENC_ERROR transportEnc_LatmSetNrOfSubframes( HANDLE_LATM_STREAM hAss, + INT noSubframes_next) /* nr of access units / payloads within a latm frame */ +{ + /* sanity chk */ + if (noSubframes_next < 1 || noSubframes_next > MAX_NR_OF_SUBFRAMES) { + return TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES; + } + + hAss->noSubframes_next = noSubframes_next; + + /* if at start then we can take over the value immediately, otherwise we have to wait for the next SMC */ + if ( (hAss->subFrameCnt == 0) && (hAss->latmFrameCounter == 0) ) { + hAss->noSubframes = noSubframes_next; + } + + return TRANSPORTENC_OK; +} + +static +int allStreamsSameTimeFraming( HANDLE_LATM_STREAM hAss, UCHAR noProgram, UCHAR noLayer[] /* return */ ) +{ + int prog, layer; + + signed int lastNoSamples = -1; + signed int minFrameSamples = FDK_INT_MAX; + signed int maxFrameSamples = 0; + + signed int highestSamplingRate = -1; + + for( prog=0; progconfig[prog][layer] != NULL ) + { + INT hsfSamplesFrame; + + noLayer[prog]++; + + if( highestSamplingRate < 0 ) + highestSamplingRate = hAss->config[prog][layer]->samplingRate; + + hsfSamplesFrame = hAss->config[prog][layer]->samplesPerFrame * highestSamplingRate / hAss->config[prog][layer]->samplingRate; + + if( hsfSamplesFrame <= minFrameSamples ) minFrameSamples = hsfSamplesFrame; + if( hsfSamplesFrame >= maxFrameSamples ) maxFrameSamples = hsfSamplesFrame; + + if( lastNoSamples == -1 ) { + lastNoSamples = hsfSamplesFrame; + } else { + if( hsfSamplesFrame != lastNoSamples ) { + return 0; + } + } + } + } + } + + return 1; +} + +/** + * Initialize LATM/LOAS Stream and add layer 0 at program 0. + */ +static +TRANSPORTENC_ERROR transportEnc_InitLatmStream( HANDLE_LATM_STREAM hAss, + int fractDelayPresent, + signed int muxConfigPeriod, /* insert setup data every muxConfigPeriod frames */ + UINT audioMuxVersion, + TRANSPORT_TYPE tt + ) +{ + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + if (hAss == NULL) + return TRANSPORTENC_INVALID_PARAMETER; + + hAss->tt = tt; + + hAss->noProgram = 1; + + hAss->audioMuxVersion = audioMuxVersion; + + /* Fill noLayer array using hAss->config */ + hAss->allStreamsSameTimeFraming = allStreamsSameTimeFraming( hAss, hAss->noProgram, hAss->noLayer ); + /* Only allStreamsSameTimeFraming==1 is supported */ + FDK_ASSERT(hAss->allStreamsSameTimeFraming); + + hAss->fractDelayPresent = fractDelayPresent; + hAss->otherDataLenBytes = 0; + + hAss->varMode = LATMVAR_SIMPLE_SEQUENCE; + + /* initialize counters */ + hAss->subFrameCnt = 0; + hAss->noSubframes = DEFAULT_LATM_NR_OF_SUBFRAMES; + hAss->noSubframes_next = DEFAULT_LATM_NR_OF_SUBFRAMES; + + /* sync layer related */ + hAss->audioMuxLengthBytes = 0; + + hAss->latmFrameCounter = 0; + hAss->muxConfigPeriod = muxConfigPeriod; + + return ErrorStatus; +} + + +/** + * + */ +UINT transportEnc_LatmCountTotalBitDemandHeader ( HANDLE_LATM_STREAM hAss , unsigned int streamDataLength ) +{ + UINT bitDemand = 0; + + switch (hAss->tt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hAss->subFrameCnt == 0) { + bitDemand = transportEnc_LatmCountFixBitDemandHeader ( hAss ); + } + bitDemand += transportEnc_LatmCountVarBitDemandHeader ( hAss , streamDataLength /*- bitDemand*/); + break; + default: + break; + } + + return bitDemand; +} + +static TRANSPORTENC_ERROR +AdvanceAudioMuxElement ( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int auBits, + int bufferFullness, + CSTpCallBacks *cb + ) +{ + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + int insertMuxSetup; + + /* Insert setup data to assemble Buffer */ + if (hAss->subFrameCnt == 0) + { + if (hAss->muxConfigPeriod > 0) { + insertMuxSetup = (hAss->latmFrameCounter == 0); + } else { + insertMuxSetup = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + if( insertMuxSetup ) { + FDKwriteBits( hBs, 0, 1 ); /* useSameStreamMux useNewStreamMux */ + CreateStreamMuxConfig(hAss, hBs, bufferFullness, cb); + if (ErrorStatus != TRANSPORTENC_OK) + return ErrorStatus; + } else { + FDKwriteBits( hBs, 1, 1 ); /* useSameStreamMux */ + } + } + } + + /* PayloadLengthInfo */ + { + int prog, layer; + + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < hAss->noLayer[prog]; layer++) { + ErrorStatus = WriteAuPayloadLengthInfo( hBs, auBits ); + if (ErrorStatus != TRANSPORTENC_OK) + return ErrorStatus; + } + } + } + /* At this point comes the access unit. */ + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR +transportEnc_LatmWrite ( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int auBits, + int bufferFullness, + CSTpCallBacks *cb + ) +{ + TRANSPORTENC_ERROR ErrorStatus; + + if (hAss->subFrameCnt == 0) { + /* Start new frame */ + FDKresetBitbuffer(hBs, BS_WRITER); + } + + hAss->latmSubframeStart = FDKgetValidBits(hBs); + + /* Insert syncword and syncword distance + - only if loas + - we must update the syncword distance (=audiomuxlengthbytes) later + */ + if( hAss->tt == TT_MP4_LOAS && hAss->subFrameCnt == 0) + { + /* Start new LOAS frame */ + FDKwriteBits( hBs, 0x2B7, 11 ); + hAss->audioMuxLengthBytes = 0; + hAss->audioMuxLengthBytesPos = FDKgetValidBits( hBs ); /* store read pointer position */ + FDKwriteBits( hBs, hAss->audioMuxLengthBytes, 13 ); + } + + ErrorStatus = AdvanceAudioMuxElement( + hAss, + hBs, + auBits, + bufferFullness, + cb + ); + + if (ErrorStatus != TRANSPORTENC_OK) + return ErrorStatus; + + return ErrorStatus; +} + +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, + int *bits) +{ + /* Substract bits from possible previous subframe */ + *bits -= hAss->latmSubframeStart; + /* Add fill bits */ + if (hAss->subFrameCnt == 0) + *bits += hAss->fillBits; +} + + +void transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *bytes) +{ + + hAss->subFrameCnt++; + if (hAss->subFrameCnt >= hAss->noSubframes) + { + + /* Add LOAS frame length if required. */ + if (hAss->tt == TT_MP4_LOAS) + { + int latmBytes; + + latmBytes = (FDKgetValidBits(hBs)+7) >> 3; + + /* write length info into assembler buffer */ + hAss->audioMuxLengthBytes = latmBytes - 3; /* 3=Syncword + length */ + { + FDK_BITSTREAM tmpBuf; + + FDKinitBitStream( &tmpBuf, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER ) ; + FDKpushFor( &tmpBuf, hAss->audioMuxLengthBytesPos ); + FDKwriteBits( &tmpBuf, hAss->audioMuxLengthBytes, 13 ); + FDKsyncCache( &tmpBuf ); + } + } + + /* Write AudioMuxElement byte alignment fill bits */ + FDKwriteBits(hBs, 0, hAss->fillBits); + + FDK_ASSERT( (FDKgetValidBits(hBs) % 8) == 0); + + hAss->subFrameCnt = 0; + + FDKsyncCache(hBs); + *bytes = (FDKgetValidBits(hBs) + 7)>>3; + //FDKfetchBuffer(hBs, buffer, (UINT*)bytes); + + if (hAss->muxConfigPeriod > 0) + { + hAss->latmFrameCounter++; + + if (hAss->latmFrameCounter >= hAss->muxConfigPeriod) { + hAss->latmFrameCounter = 0; + hAss->noSubframes = hAss->noSubframes_next; + } + } + } else { + /* No data this time */ + *bytes = 0; + } +} + +/** + * Init LATM/LOAS + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, + CSTpCallBacks *cb + ) +{ + TRANSPORTENC_ERROR ErrorStatus; + int fractDelayPresent = 0; + int prog, layer; + + int setupDataDistanceFrames = layerConfig->headerPeriod; + + FDK_ASSERT(setupDataDistanceFrames>=0); + + for (prog=0; progconfig[prog][layer] = NULL; + hAss->m_linfo[prog][layer].streamID = -1; + } + } + + hAss->config[0][0] = layerConfig; + hAss->m_linfo[0][0].streamID = 0; + + ErrorStatus = transportEnc_InitLatmStream( hAss, + fractDelayPresent, + setupDataDistanceFrames, + (audioMuxVersion)?1:0, + tt + ); + if (ErrorStatus != TRANSPORTENC_OK) + goto bail; + + ErrorStatus = transportEnc_LatmSetNrOfSubframes( + hAss, + layerConfig->nSubFrames + ); + if (ErrorStatus != TRANSPORTENC_OK) + goto bail; + + /* Get the size of the StreamMuxConfig somehow */ + AdvanceAudioMuxElement(hAss, hBs, 0, 0, cb); + //CreateStreamMuxConfig(hAss, hBs, 0); + +bail: + return ErrorStatus; +} + + + + + + diff --git a/libMpegTPEnc/src/tpenc_latm.h b/libMpegTPEnc/src/tpenc_latm.h new file mode 100644 index 00000000..34eea587 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_latm.h @@ -0,0 +1,264 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Encoder ************************** + + Author(s): + Description: + +******************************************************************************/ + +#ifndef TPENC_LATM_H +#define TPENC_LATM_H + + + +#include "tpenc_lib.h" +#include "FDK_bitstream.h" + + +#define DEFAULT_LATM_NR_OF_SUBFRAMES 1 +#define DEFAULT_LATM_SMC_REPEAT 8 + +#define MAX_AAC_LAYERS 9 + +#define LATM_MAX_PROGRAMS 1 +#define LATM_MAX_STREAM_ID 16 + +#define LATM_MAX_LAYERS 1 /*MAX_AAC_LAYERS*/ + +#define MAX_NR_OF_SUBFRAMES 2 /* set this carefully to avoid buffer overflows */ + +typedef enum { LATMVAR_SIMPLE_SEQUENCE } LATM_VAR_MODE; + +typedef struct { + signed int frameLengthType; + signed int frameLengthBits; + signed int varFrameLengthTable[4]; + signed int streamID; +} LATM_LAYER_INFO; + + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + CODER_CONFIG *config[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + + LATM_VAR_MODE varMode; + TRANSPORT_TYPE tt; + + int audioMuxLengthBytes; + + int audioMuxLengthBytesPos; + int taraBufferFullness; /* state of the bit reservoir */ + int varStreamCnt; + unsigned int otherDataLenBytes; + + UCHAR latmFrameCounter; /* Current frame number. Counts modulo muxConfigPeriod */ + UCHAR muxConfigPeriod; /* Distance in frames between MuxConfig */ + + UCHAR audioMuxVersion; /* AMV1 supports transmission of taraBufferFullness and ASC lengths */ + UCHAR audioMuxVersionA; /* for future extensions */ + + UCHAR noProgram; + UCHAR noLayer[LATM_MAX_PROGRAMS]; + UCHAR fractDelayPresent; + + UCHAR allStreamsSameTimeFraming; + UCHAR subFrameCnt; /* Current Subframe frame */ + UCHAR noSubframes; /* Number of subframes */ + UINT latmSubframeStart; /* Position of current subframe start */ + UCHAR noSubframes_next; + + UCHAR fillBits; /* AudioMuxElement fill bits */ + UCHAR streamMuxConfigBits; + +} LATM_STREAM; + +typedef LATM_STREAM *HANDLE_LATM_STREAM; + +/** + * \brief Initialize LATM_STREAM Handle. Creates automatically one program with one layer with + * the given layerConfig. The layerConfig must be persisten because references to this pointer + * are made at any time again. + * Use transportEnc_Latm_AddLayer() to add more programs/layers. + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param layerConfig a valid CODER_CONFIG struct containing the current audio configuration parameters + * \param audioMuxVersion the LATM audioMuxVersion to be used + * \param tt the specific TRANSPORT_TYPE to be used, either TT_MP4_LOAS, TT_MP4_LATM_MCP1 or TT_MP4_LATM_MCP0 LOAS + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init( + HANDLE_LATM_STREAM hLatmStreamInfo, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, + CSTpCallBacks *cb + ); + +/** + * \brief Get bit demand of next LATM/LOAS header + * + * \param hAss HANDLE_LATM_STREAM handle + * \param streamDataLength the length of the payload + * + * \return the number of bits required by the LATM/LOAS headers + */ +unsigned int transportEnc_LatmCountTotalBitDemandHeader ( + HANDLE_LATM_STREAM hAss, + unsigned int streamDataLength + ); + +/** + * \brief Write LATM/LOAS header into given bitstream handle + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBitstream Bitstream handle + * \param auBits amount of current payload bits + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR +transportEnc_LatmWrite ( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBitstream, + int auBits, + int bufferFullness, + CSTpCallBacks *cb + ); + +/** + * \brief Adjust bit count relative to current subframe + * + * \param hAss HANDLE_LATM_STREAM handle + * \param pBits pointer to an int, where the current frame bit count is contained, + * and where the subframe relative bit count will be returned into + * + * \return void + */ +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, + int *pBits); + +/** + * \brief Request an LATM frame, which may, or may not be available + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param pBytes pointer to an int, where the current frame byte count stored into. + * A return value of zero means that currently no LATM/LOAS frame can be returned. + * The latter is expected in case of multiple subframes being used. + * + * \return void + */ +void transportEnc_LatmGetFrame( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *pBytes + ); + +/** + * \brief Write a StreamMuxConfig into the given bitstream handle + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return void + */ +TRANSPORTENC_ERROR +CreateStreamMuxConfig( + HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, + CSTpCallBacks *cb + ); + + +#endif /* TPENC_LATM_H */ diff --git a/libMpegTPEnc/src/tpenc_lib.cpp b/libMpegTPEnc/src/tpenc_lib.cpp new file mode 100644 index 00000000..2c6f0c10 --- /dev/null +++ b/libMpegTPEnc/src/tpenc_lib.cpp @@ -0,0 +1,690 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** MPEG-4 Transport Encoder ************************ + + Author(s): Manuel Jander + Description: MPEG Transport encode + +******************************************************************************/ + +#include "tpenc_lib.h" + +/* library info */ +#include "version" + +#define MODULE_NAME "transportEnc" + +#include "tpenc_asc.h" +#include "conv_string.h" + +#include "tpenc_adts.h" + +#include "tpenc_adif.h" + +#include "tpenc_dab.h" + +#include "tpenc_latm.h" + +typedef struct { + int curSubFrame; + int nSubFrames; + int prevBits; +} RAWPACKETS_INFO; + +struct TRANSPORTENC +{ + CODER_CONFIG config; + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transport type. */ + + FDK_BITSTREAM bitStream; + UCHAR *bsBuffer; + INT bsBufferSize; + + INT pceFrameCounter; /*!< Indicates frame period when PCE must be written in raw_data_block. + -1 means not to write a PCE in raw_dat_block. */ + union { + STRUCT_ADTS adts; + + ADIF_INFO adif; + + STRUCT_DAB dab; + + LATM_STREAM latm; + + RAWPACKETS_INFO raw; + + + + } writer; + + CSTpCallBacks callbacks; +}; + +typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT; + + +/* + * MEMORY Declaration + */ + +C_ALLOC_MEM(Ram_TransportEncoder, TRANSPORTENC, 1) + +TRANSPORTENC_ERROR transportEnc_Open( HANDLE_TRANSPORTENC *phTpEnc ) +{ + HANDLE_TRANSPORTENC hTpEnc; + + if ( phTpEnc == NULL ){ + return TRANSPORTENC_INVALID_PARAMETER; + } + + hTpEnc = GetRam_TransportEncoder(0); + + if ( hTpEnc == NULL ) { + return TRANSPORTENC_NO_MEM; + } + + *phTpEnc = hTpEnc; + return TRANSPORTENC_OK; +} + +/** + * \brief Get frame period of PCE in raw_data_block. + * + * - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0 whererfore + * no additonal PCE will be written in raw_data_block. + * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1. + * - The PCE repetition rate in raw_data_block can be controlled via headerPeriod parameter. + * + * \param channelConfig Channel Configuration derived from Channel Mode + * \param transportFmt Format of the transport to be written. + * \param headerPeriod Chosen PCE frame repetition rate. + * \param matrixMixdownA Indicates if a valid Matrix Mixdown coefficient is available. + * + * \return PCE frame repetition rate. -1 means no PCE present in raw_data_block. + */ +static INT getPceRepetitionRate( + const int channelConfig, + const TRANSPORT_TYPE transportFmt, + const int headerPeriod, + const int matrixMixdownA + ) +{ + INT pceFrameCounter = -1; /* variable to be returned */ + + if (headerPeriod>0) { + switch ( channelConfig ) { + case 0: + switch (transportFmt) { + case TT_MP4_ADTS: + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + case TT_MP4_LOAS: /* PCE in ASC if chChonfig==0 */ + case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */ + case TT_DRM: /* PCE not allowed in DRM */ + case TT_DABPLUS: + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + break; + case 5: /* MODE_1_2_2 */ + case 6: /* MODE_1_2_2_1 */ + /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config present. */ + if (matrixMixdownA!=0) { + switch (transportFmt) { + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + case TT_MP4_ADTS: + case TT_MP4_LOAS: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP1: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + case TT_DRM: /* PCE not allowed in DRM */ + case TT_DABPLUS: + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch transportFmt */ + } /* if matrixMixdownA!=0 */ + break; + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch getChannelConfig() */ + } /* if headerPeriod>0 */ + else { + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + + return pceFrameCounter; +} + +TRANSPORTENC_ERROR transportEnc_Init( + HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, + INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *cconfig, + UINT flags + ) +{ + /* Copy configuration structure */ + FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG)); + + /* Init transportEnc struct. */ + hTpEnc->transportFmt = transportFmt; + + hTpEnc->bsBuffer = bsBuffer; + hTpEnc->bsBufferSize = bsBufferSize; + + FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize, 0, BS_WRITER); + + switch (transportFmt) { + + case TT_MP4_ADIF: + /* Sanity checks */ + if ( (hTpEnc->config.aot != AOT_AAC_LC) + ||(hTpEnc->config.samplesPerFrame != 1024)) + { + return TRANSPORTENC_INVALID_PARAMETER; + } + hTpEnc->writer.adif.headerWritten = 0; + hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate; + hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate; + hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1; + hTpEnc->writer.adif.cm = hTpEnc->config.channelMode; + hTpEnc->writer.adif.bVariableRate = 0; + hTpEnc->writer.adif.instanceTag = 0; + break; + + case TT_MP4_ADTS: + /* Sanity checks */ + if ( ( hTpEnc->config.aot != AOT_AAC_LC) + ||(hTpEnc->config.samplesPerFrame != 1024) ) + { + return TRANSPORTENC_INVALID_PARAMETER; + } + if ( adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) { + return TRANSPORTENC_INVALID_PARAMETER; + } + break; + + case TT_DABPLUS: + /* Sanity checks */ + if ( ( hTpEnc->config.aot != AOT_AAC_LC) + ||(hTpEnc->config.samplesPerFrame != 960) ) + { + return TRANSPORTENC_INVALID_PARAMETER; + } + if ( dabWrite_Init(&hTpEnc->writer.dab, &hTpEnc->config) != 0) { + return TRANSPORTENC_INVALID_PARAMETER; + } + break; + + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + { + TRANSPORTENC_ERROR error; + + error = transportEnc_Latm_Init( + &hTpEnc->writer.latm, + &hTpEnc->bitStream, + &hTpEnc->config, + flags & TP_FLAG_LATM_AMV, + transportFmt, + &hTpEnc->callbacks + ); + if (error != TRANSPORTENC_OK) { + return error; + } + } + break; + + case TT_MP4_RAW: + hTpEnc->writer.raw.curSubFrame = 0; + hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames; + break; + + + + default: + return TRANSPORTENC_INVALID_PARAMETER; + } + + /* pceFrameCounter indicates if PCE must be written in raw_data_block. */ + hTpEnc->pceFrameCounter = getPceRepetitionRate( + getChannelConfig(hTpEnc->config.channelMode), + transportFmt, + hTpEnc->config.headerPeriod, + hTpEnc->config.matrixMixdownA); + + return TRANSPORTENC_OK; +} + +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream( HANDLE_TRANSPORTENC hTp ) +{ + return &hTp->bitStream; +} + +int transportEnc_RegisterSbrCallback( HANDLE_TRANSPORTENC hTpEnc, const cbSbr_t cbSbr, void* user_data) +{ + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbSbr = cbSbr; + hTpEnc->callbacks.cbSbrData = user_data; + return 0; +} + + +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit( + HANDLE_TRANSPORTENC hTp, + INT frameUsedBits, + int bufferFullness, + int ncc + ) +{ + TRANSPORTENC_ERROR err = TRANSPORTENC_OK; + + if (!hTp) { + return TRANSPORTENC_INVALID_PARAMETER; + } + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream; + + /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */ + if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { + frameUsedBits += transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); + adifWrite_EncodeHeader( + &hTp->writer.adif, + hBs, + bufferFullness + ); + break; + case TT_MP4_ADTS: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ + adtsWrite_EncodeHeader( + &hTp->writer.adts, + &hTp->bitStream, + bufferFullness, + frameUsedBits + ); + break; + case TT_DABPLUS: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ + dabWrite_EncodeHeader( + &hTp->writer.dab, + &hTp->bitStream, + bufferFullness, + frameUsedBits + ); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */ + transportEnc_LatmWrite( + &hTp->writer.latm, + hBs, + frameUsedBits, + bufferFullness, + &hTp->callbacks + ); + break; + case TT_MP4_RAW: + if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) { + hTp->writer.raw.curSubFrame = 0; + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, BS_WRITER); + } + hTp->writer.raw.prevBits = FDKgetValidBits(hBs); + break; + default: + err = TRANSPORTENC_UNSUPPORTED_FORMAT; + break; + } + + /* Write PCE in raw_data_block if required */ + if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { + INT crcIndex = 0; + /* Align inside PCE with repsect to the first bit of the raw_data_block() */ + UINT alignAnchor = FDKgetValidBits(&hTp->bitStream); + + /* Write PCE element ID bits */ + FDKwriteBits(&hTp->bitStream, ID_PCE, 3); + + if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { + crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0); + } + + /* Write PCE as first raw_data_block element */ + transportEnc_writePCE(&hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, 1, hTp->config.matrixMixdownA, (hTp->config.flags&CC_PSEUDO_SURROUND)?1:0, alignAnchor); + + if ( (hTp->transportFmt==TT_MP4_ADTS) && !hTp->writer.adts.protection_absent) { + adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex); + } + hTp->pceFrameCounter = 0; /* reset pce frame counter */ + } + + if (hTp->pceFrameCounter!=-1) { + hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is active. */ + } + + return err; +} + + +TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, int *bits) +{ + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + transportEnc_LatmAdjustSubframeBits(&hTp->writer.latm, bits); + break; + case TT_MP4_ADTS: + adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits); + break; + case TT_DABPLUS: + dabWrite_EndRawDataBlock(&hTp->writer.dab, &hTp->bitStream, bits); + break; + case TT_MP4_ADIF: + /* Substract ADIF header from AU bits, not to be considered. */ + *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif); + hTp->writer.adif.headerWritten = 1; + break; + case TT_MP4_RAW: + *bits -= hTp->writer.raw.prevBits; + break; + default: + break; + } + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, int *nbytes) +{ + HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream; + + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + *nbytes = hTpEnc->bsBufferSize; + transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes); + break; + case TT_MP4_ADTS: + if (hTpEnc->writer.adts.currentBlock >= hTpEnc->writer.adts.num_raw_blocks+1) { + *nbytes = (FDKgetValidBits(hBs) + 7)>>3; + hTpEnc->writer.adts.currentBlock = 0; + } else { + *nbytes = 0; + } + break; + case TT_DABPLUS: + if (hTpEnc->writer.dab.currentBlock >= hTpEnc->writer.dab.num_raw_blocks+1) { + *nbytes = (FDKgetValidBits(hBs) + 7)>>3; + hTpEnc->writer.dab.currentBlock = 0; + } else { + *nbytes = 0; + } + break; + case TT_MP4_ADIF: + FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0); + *nbytes = (FDKgetValidBits(hBs) + 7)>>3; + break; + case TT_MP4_RAW: + FDKsyncCache(hBs); + hTpEnc->writer.raw.curSubFrame++; + *nbytes = ((FDKgetValidBits(hBs)-hTpEnc->writer.raw.prevBits) + 7)>>3; + break; + default: + break; + } + + return TRANSPORTENC_OK; +} + +INT transportEnc_GetStaticBits( HANDLE_TRANSPORTENC hTp, int auBits ) +{ + INT nbits = 0, nPceBits = 0; + + /* Write PCE within raw_data_block in transport lib. */ + if (hTp->pceFrameCounter>=hTp->config.headerPeriod) { + nPceBits = transportEnc_GetPCEBits(hTp->config.channelMode, hTp->config.matrixMixdownA, 3); /* Consider 3 bits ID signalling in alignment */ + auBits += nPceBits; /* Adapt required raw_data_block bit consumtpion for AU length information e.g. in LATM/LOAS configuration. */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_RAW: + nbits = 0; /* Do not consider the ADIF header into the total bitrate */ + break; + case TT_MP4_ADTS: + nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts); + break; + case TT_DABPLUS: + nbits = dabWrite_CountTotalBitDemandHeader(&hTp->writer.dab, auBits); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + nbits = transportEnc_LatmCountTotalBitDemandHeader( &hTp->writer.latm, auBits ); + break; + default: + nbits = 0; + break; + } + + /* PCE is written in the transport library therefore the bit consumption is part of the transport static bits. */ + nbits += nPceBits; + + return nbits; +} + +void transportEnc_Close(HANDLE_TRANSPORTENC *phTp) +{ + if (phTp != NULL) + { + if (*phTp != NULL) { + FreeRam_TransportEncoder(phTp); + } + } +} + +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits) +{ + int crcReg = 0; + + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, mBits); + break; + case TT_DABPLUS: + crcReg = dabWrite_CrcStartReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, mBits); + break; + default: + break; + } + + return crcReg; +} + +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg) +{ + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg); + break; + case TT_DABPLUS: + dabWrite_CrcEndReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, reg); + break; + default: + break; + } +} + + +TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType) +{ + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + HANDLE_LATM_STREAM hLatmConfig = &hTpEnc->writer.latm; + + *confType = 0; /* set confType variable to default */ + + /* write StreamMuxConfig or AudioSpecificConfig depending on format used */ + switch (hTpEnc->transportFmt) + { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + tpErr = CreateStreamMuxConfig(hLatmConfig, dataBuffer, 0, &hTpEnc->callbacks); + *confType = 1; /* config is SMC */ + break; + default: + if (transportEnc_writeASC(dataBuffer, cc, &hTpEnc->callbacks) != 0) { + tpErr = TRANSPORTENC_UNKOWN_ERROR; + } + } + + return tpErr; + +} + +TRANSPORTENC_ERROR transportEnc_GetLibInfo( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return TRANSPORTENC_INVALID_PARAMETER; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return TRANSPORTENC_UNKOWN_ERROR; + } + info += i; + + info->module_id = FDK_TPENC; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + + /* Set flags */ + info->flags = 0 + | CAPF_ADIF + | CAPF_ADTS + | CAPF_LATM + | CAPF_LOAS + | CAPF_RAWPACKETS + | CAPF_DAB_AAC + ; + + return TRANSPORTENC_OK; +} + diff --git a/libMpegTPEnc/src/version b/libMpegTPEnc/src/version new file mode 100644 index 00000000..8742568b --- /dev/null +++ b/libMpegTPEnc/src/version @@ -0,0 +1,13 @@ + +/* library info */ +#define TP_LIB_VL0 2 +#define TP_LIB_VL1 3 +#define TP_LIB_VL2 6 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif diff --git a/libPCMutils/include/limiter.h b/libPCMutils/include/limiter.h new file mode 100644 index 00000000..0d3d701b --- /dev/null +++ b/libPCMutils/include/limiter.h @@ -0,0 +1,233 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************ FDK PCM postprocessor module ********************* + + Author(s): Matthias Neusinger + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#ifndef _LIMITER_H_ +#define _LIMITER_H_ + + +#include "common_fix.h" + +#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */ +#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */ + +#define TDL_GAIN_SCALING (15) /* scaling of gain value. */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + TDLIMIT_OK = 0, + + __error_codes_start = -100, + + TDLIMIT_INVALID_HANDLE, + TDLIMIT_INVALID_PARAMETER, + + __error_codes_end +} TDLIMITER_ERROR; + +struct TDLimiter; +typedef struct TDLimiter* TDLimiterPtr; + +/****************************************************************************** +* createLimiter * +* maxAttackMs: maximum and initial attack/lookahead time in milliseconds * +* releaseMs: release time in milliseconds (90% time constant) * +* threshold: limiting threshold * +* maxChannels: maximum and initial number of channels * +* maxSampleRate: maximum and initial sampling rate in Hz * +* returns: limiter handle * +******************************************************************************/ +TDLimiterPtr createLimiter(unsigned int maxAttackMs, + unsigned int releaseMs, + INT_PCM threshold, + unsigned int maxChannels, + unsigned int maxSampleRate); + + +/****************************************************************************** +* resetLimiter * +* limiter: limiter handle * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR resetLimiter(TDLimiterPtr limiter); + + +/****************************************************************************** +* destroyLimiter * +* limiter: limiter handle * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR destroyLimiter(TDLimiterPtr limiter); + +/****************************************************************************** +* applyLimiter * +* limiter: limiter handle * +* pGain : pointer to gains to be applied to the signal before limiting, * +* which are downscaled by TDL_GAIN_SCALING bit. * +* These gains are delayed by gain_delay, and smoothed. * +* Smoothing is done by a butterworth lowpass filter with a cutoff * +* frequency which is fixed with respect to the sampling rate. * +* It is a substitute for the smoothing due to windowing and * +* overlap/add, if a gain is applied in frequency domain. * +* gain_scale: pointer to scaling exponents to be applied to the signal before * +* limiting, without delay and without smoothing * +* gain_size: number of elements in pGain, currently restricted to 1 * +* gain_delay: delay [samples] with which the gains in pGain shall be applied * +* gain_delay <= nSamples * +* samples: input/output buffer containing interleaved samples * +* precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits * +* nSamples: number of samples per channel * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR applyLimiter(TDLimiterPtr limiter, + INT_PCM* samples, + FIXP_DBL* pGain, + const INT* gain_scale, + const UINT gain_size, + const UINT gain_delay, + const UINT nSamples); + +/****************************************************************************** +* getLimiterDelay * +* limiter: limiter handle * +* returns: exact delay caused by the limiter in samples * +******************************************************************************/ +unsigned int getLimiterDelay(TDLimiterPtr limiter); + +/****************************************************************************** +* setLimiterNChannels * +* limiter: limiter handle * +* nChannels: number of channels ( <= maxChannels specified on create) * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR setLimiterNChannels(TDLimiterPtr limiter, unsigned int nChannels); + +/****************************************************************************** +* setLimiterSampleRate * +* limiter: limiter handle * +* sampleRate: sampling rate in Hz ( <= maxSampleRate specified on create) * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR setLimiterSampleRate(TDLimiterPtr limiter, unsigned int sampleRate); + +/****************************************************************************** +* setLimiterAttack * +* limiter: limiter handle * +* attackMs: attack time in ms ( <= maxAttackMs specified on create) * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR setLimiterAttack(TDLimiterPtr limiter, unsigned int attackMs); + +/****************************************************************************** +* setLimiterRelease * +* limiter: limiter handle * +* releaseMs: release time in ms * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR setLimiterRelease(TDLimiterPtr limiter, unsigned int releaseMs); + +/****************************************************************************** +* setLimiterThreshold * +* limiter: limiter handle * +* threshold: limiter threshold * +* returns: error code * +******************************************************************************/ +TDLIMITER_ERROR setLimiterThreshold(TDLimiterPtr limiter, INT_PCM threshold); + +#ifdef __cplusplus +} +#endif + + +#endif //#ifndef _LIMITER_H_ diff --git a/libPCMutils/include/pcmutils_lib.h b/libPCMutils/include/pcmutils_lib.h new file mode 100644 index 00000000..e7e6a41c --- /dev/null +++ b/libPCMutils/include/pcmutils_lib.h @@ -0,0 +1,334 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************ FDK PCM up/downmixing module ********************* + + Author(s): Christian Griebel + Description: Declares functions to interface with the PCM downmix processing + module. + +*******************************************************************************/ + +#ifndef _PCMUTILS_LIB_H_ +#define _PCMUTILS_LIB_H_ + +#include "machine_type.h" +#include "common_fix.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + + +/* ------------------------ * + * ERROR CODES: * + * ------------------------ */ +typedef enum +{ + PCMDMX_OK = 0x0, /*!< No error happened. */ + + pcm_dmx_fatal_error_start, + PCMDMX_OUT_OF_MEMORY = 0x2, /*!< Not enough memory to set up an instance of the module. */ + PCMDMX_UNKNOWN = 0x5, /*!< Error condition is of unknown reason, or from a third + party module. */ + pcm_dmx_fatal_error_end, + + PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */ + PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */ + PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not supported and thus + no processing was performed. */ + PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */ + PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */ + PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most probably the + value ist out of range. */ + PCMDMX_CORRUPT_ANC_DATA /*!< The read ancillary data was corrupt. */ + +} PCMDMX_ERROR; + +/** Macro to identify fatal errors. */ +#define PCMDMX_IS_FATAL_ERROR(err) ( (((err)>=pcm_dmx_fatal_error_start) && ((err)<=pcm_dmx_fatal_error_end)) ? 1 : 0) + +/* ------------------------ * + * RUNTIME PARAMS: * + * ------------------------ */ +typedef enum +{ + DMX_BS_DATA_EXPIRY_FRAME, /*!< The number of frames without new metadata that have to go + by before the bitstream data expires. The value 0 disables + expiry. */ + DMX_BS_DATA_DELAY, /*!< The number of delay frames of the output samples compared + to the bitstream data. */ + MIN_NUMBER_OF_OUTPUT_CHANNELS, /*!< The minimum number of output channels. For all input + configurations that have less than the given channels the + module will modify the output automatically to obtain the + given number of output channels. Mono signals will be + duplicated. If more than two output channels are desired + the module just adds empty channels. The parameter value + must be either -1, 0, 1, 2, 6 or 8. If the value is + greater than zero and exceeds the value of parameter + MAX_NUMBER_OF_OUTPUT_CHANNELS the latter will be set to + the same value. Both values -1 and 0 disable the feature. */ + MAX_NUMBER_OF_OUTPUT_CHANNELS, /*!< The maximum number of output channels. For all input + configurations that have more than the given channels the + module will apply a mixdown automatically to obtain the + given number of output channels. The value must be either + -1, 0, 1, 2, 6 or 8. If it is greater than zero and lower + or equal than the value of MIN_NUMBER_OF_OUTPUT_CHANNELS + parameter the latter will be set to the same value. + The values -1 and 0 disable the feature. */ + DMX_DUAL_CHANNEL_MODE, /*!< Downmix mode for two channel audio data. */ + DMX_PSEUDO_SURROUND_MODE /*!< Defines how module handles pseudo surround compatible + signals. See PSEUDO_SURROUND_MODE type for details. */ +} PCMDMX_PARAM; + +/* Parameter value types */ +typedef enum +{ + NEVER_DO_PS_DMX = -1, /*!< Never create a pseudo surround compatible downmix. */ + AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if + signalled in bitstreams meta data. (Default) */ + FORCE_PS_DMX = 1 /*!< Always create a pseudo surround compatible downmix. + CAUTION: This can lead to excessive signal cancellations + and signal level differences for non-compatible signals. */ +} PSEUDO_SURROUND_MODE; + +typedef enum +{ + STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */ + CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */ + CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */ + MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two + channels. */ +} DUAL_CHANNEL_MODE; + + +/* ------------------------ * + * MODULES INTERFACE: * + * ------------------------ */ +typedef struct PCM_DMX_INSTANCE *HANDLE_PCM_DOWNMIX; + +/* Modules reset flags */ +#define PCMDMX_RESET_PARAMS ( 1 ) +#define PCMDMX_RESET_BS_DATA ( 2 ) +#define PCMDMX_RESET_FULL ( PCMDMX_RESET_PARAMS | PCMDMX_RESET_BS_DATA ) + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** Open and initialize an instance of the PCM downmix module + * @param [out] Pointer to a buffer receiving the handle of the new instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Open ( + HANDLE_PCM_DOWNMIX *pSelf + ); + +/** Set one parameter for one instance of the PCM downmix module. + * @param [in] Handle of PCM downmix instance. + * @param [in] Parameter to be set. + * @param [in] Parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetParam ( + HANDLE_PCM_DOWNMIX self, + const PCMDMX_PARAM param, + const INT value + ); + +/** Get one parameter value of one PCM downmix module instance. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [out] Pointer to buffer receiving the parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_GetParam ( + HANDLE_PCM_DOWNMIX self, + const PCMDMX_PARAM param, + INT * const pValue + ); + +/** Read downmix meta-data directly from a given bitstream. + * @param [in] Handle of PCM downmix instance. + * @param [in] Handle of FDK bitstream buffer. + * @param [in] Length of ancillary data in bits. + * @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Parse ( + HANDLE_PCM_DOWNMIX self, + HANDLE_FDK_BITSTREAM hBitStream, + UINT ancDataBits, + int isMpeg2 + ); + +/** Read downmix meta-data from a given data buffer. + * @param [in] Handle of PCM downmix instance. + * @param [in] Pointer to ancillary data buffer. + * @param [in] Size of ancillary data in bytes. + * @param [in] Flag indicating wheter the ancillary data is from a MPEG-1/2 or an MPEG-4 stream. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_ReadDvbAncData ( + HANDLE_PCM_DOWNMIX self, + UCHAR *pAncDataBuf, + UINT ancDataBytes, + int isMpeg2 + ); + +/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream. + * @param [in] Handle of PCM downmix instance. + * @param [in] Matrix mixdown index present flag extracted from PCE. + * @param [in] The 2 bit matrix mixdown index extracted from PCE. + * @param [in] The pseudo surround enable flag extracted from PCE. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce ( + HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable + ); + +/** Reset the module. + * @param [in] Handle of PCM downmix instance. + * @param [in] Flags telling which parts of the module shall be reset. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Reset ( + HANDLE_PCM_DOWNMIX self, + UINT flags + ); + +/** Create a mixdown, bypass or extend the output signal depending on the modules settings and the + * respective given input configuration. + * + * \param [in] Handle of PCM downmix module instance. + * \param [inout] Pointer to time buffer with decoded PCM samples. + * \param [in] The I/O block size which is the number of samples per channel. + * \param [inout] Pointer to buffer that holds the number of input channels and where the + * amount of output channels is written to. + * \param [in] Flag which indicates if output time data is writtern interleaved or as + * subsequent blocks. + * \param [inout] Array were the corresponding channel type for each output audio channel is + * stored into. + * \param [inout] Array were the corresponding channel type index for each output audio channel + * is stored into. + * \param [in] Array containing the output channel mapping to be used (from MPEG PCE ordering + * to whatever is required). + * \param [out] Pointer on a field receiving the scale factor that has to be applied on all + * samples afterwards. If the handed pointer is NULL the final scaling is done + * internally. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame ( + HANDLE_PCM_DOWNMIX self, + INT_PCM *pPcmBuf, + UINT frameSize, + INT *nChannels, + int fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const UCHAR channelMapping[][8], + INT *pDmxOutScale + ); + +/** Close an instance of the PCM downmix module. + * @param [inout] Pointer to a buffer containing the handle of the instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Close ( + HANDLE_PCM_DOWNMIX *pSelf + ); + +/** Get library info for this module. + * @param [out] Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info ); + + +#ifdef __cplusplus +} +#endif + +#endif /* _PCMUTILS_LIB_H_ */ diff --git a/libPCMutils/src/limiter.cpp b/libPCMutils/src/limiter.cpp new file mode 100644 index 00000000..af724f02 --- /dev/null +++ b/libPCMutils/src/limiter.cpp @@ -0,0 +1,498 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************ FDK PCM postprocessor module ********************* + + Author(s): Matthias Neusinger + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#include "limiter.h" + + +struct TDLimiter { + unsigned int attack; + FIXP_DBL attackConst, releaseConst; + unsigned int attackMs, releaseMs, maxAttackMs; + FIXP_PCM threshold; + unsigned int channels, maxChannels; + unsigned int sampleRate, maxSampleRate; + FIXP_DBL cor, max; + FIXP_DBL* maxBuf; + FIXP_DBL* delayBuf; + unsigned int maxBufIdx, delayBufIdx; + FIXP_DBL smoothState0; + FIXP_DBL minGain; + + FIXP_DBL additionalGainPrev; + FIXP_DBL additionalGainFilterState; + FIXP_DBL additionalGainFilterState1; +}; + +/* create limiter */ +TDLimiterPtr createLimiter( + unsigned int maxAttackMs, + unsigned int releaseMs, + INT_PCM threshold, + unsigned int maxChannels, + unsigned int maxSampleRate + ) +{ + TDLimiterPtr limiter = NULL; + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + /* calc attack and release time in samples */ + attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000); + release = (unsigned int)(releaseMs * maxSampleRate / 1000); + + /* alloc limiter struct */ + limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter)); + if (!limiter) return NULL; + + /* alloc max and delay buffers */ + limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL)); + limiter->delayBuf = (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL)); + + if (!limiter->maxBuf || !limiter->delayBuf) { + destroyLimiter(limiter); + return NULL; + } + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack+1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + /* init parameters */ + limiter->attackMs = maxAttackMs; + limiter->maxAttackMs = maxAttackMs; + limiter->releaseMs = releaseMs; + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->threshold = (FIXP_PCM)threshold; + limiter->channels = maxChannels; + limiter->maxChannels = maxChannels; + limiter->sampleRate = maxSampleRate; + limiter->maxSampleRate = maxSampleRate; + + resetLimiter(limiter); + + return limiter; +} + + +/* reset limiter */ +TDLIMITER_ERROR resetLimiter(TDLimiterPtr limiter) +{ + if (limiter != NULL) { + + limiter->maxBufIdx = 0; + limiter->delayBufIdx = 0; + limiter->max = (FIXP_DBL)0; + limiter->cor = FL2FXCONST_DBL(1.0f/(1<<1)); + limiter->smoothState0 = FL2FXCONST_DBL(1.0f/(1<<1)); + limiter->minGain = FL2FXCONST_DBL(1.0f/(1<<1)); + + limiter->additionalGainPrev = FL2FXCONST_DBL(1.0f/(1<additionalGainFilterState = FL2FXCONST_DBL(1.0f/(1<additionalGainFilterState1 = FL2FXCONST_DBL(1.0f/(1<maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL) ); + FDKmemset(limiter->delayBuf, 0, limiter->attack * limiter->channels * sizeof(FIXP_DBL) ); + } + else { + return TDLIMIT_INVALID_HANDLE; + } + + return TDLIMIT_OK; +} + + +/* destroy limiter */ +TDLIMITER_ERROR destroyLimiter(TDLimiterPtr limiter) +{ + if (limiter != NULL) { + FDKfree(limiter->maxBuf); + FDKfree(limiter->delayBuf); + + FDKfree(limiter); + } + else { + return TDLIMIT_INVALID_HANDLE; + } + return TDLIMIT_OK; +} + +/* apply limiter */ +TDLIMITER_ERROR applyLimiter(TDLimiterPtr limiter, + INT_PCM* samples, + FIXP_DBL* pGain, + const INT* gain_scale, + const UINT gain_size, + const UINT gain_delay, + const UINT nSamples) +{ + unsigned int i, j; + FIXP_PCM tmp1, tmp2; + FIXP_DBL tmp, old, gain, additionalGain, additionalGainUnfiltered; + FIXP_DBL minGain = FL2FXCONST_DBL(1.0f/(1<<1)); + + FDK_ASSERT(gain_size == 1); + FDK_ASSERT(gain_delay <= nSamples); + + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + { + unsigned int channels = limiter->channels; + unsigned int attack = limiter->attack; + FIXP_DBL attackConst = limiter->attackConst; + FIXP_DBL releaseConst = limiter->releaseConst; + FIXP_DBL threshold = FX_PCM2FX_DBL(limiter->threshold)>>TDL_GAIN_SCALING; + + FIXP_DBL max = limiter->max; + FIXP_DBL* maxBuf = limiter->maxBuf; + unsigned int maxBufIdx = limiter->maxBufIdx; + FIXP_DBL cor = limiter->cor; + FIXP_DBL* delayBuf = limiter->delayBuf; + unsigned int delayBufIdx = limiter->delayBufIdx; + + FIXP_DBL smoothState0 = limiter->smoothState0; + FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState; + FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1; + + for (i = 0; i < nSamples; i++) { + + if (i < gain_delay) { + additionalGainUnfiltered = limiter->additionalGainPrev; + } else { + additionalGainUnfiltered = pGain[0]; + } + + /* Smooth additionalGain */ + /* [b,a] = butter(1, 0.01) */ + static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.015466*2.0), FL2FXCONST_SGL( 0.015466*2.0) }; + static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.000000), FL2FXCONST_SGL(-0.96907) }; + /* [b,a] = butter(1, 0.001) */ + //static const FIXP_SGL b[] = { FL2FXCONST_SGL(0.0015683*2.0), FL2FXCONST_SGL( 0.0015683*2.0) }; + //static const FIXP_SGL a[] = { FL2FXCONST_SGL(1.0000000), FL2FXCONST_SGL(-0.99686) }; + additionalGain = - fMult(additionalGainSmoothState, a[1]) + fMultDiv2( additionalGainUnfiltered, b[0]) + fMultDiv2(additionalGainSmoothState1, b[1]); + additionalGainSmoothState1 = additionalGainUnfiltered; + additionalGainSmoothState = additionalGain; + + /* Apply the additional scaling that has no delay and no smoothing */ + if (gain_scale[0] > 0) { + additionalGain <<= gain_scale[0]; + } else { + additionalGain >>= gain_scale[0]; + } + + /* get maximum absolute sample value of all channels, including the additional gain. */ + tmp1 = (FIXP_PCM)0; + for (j = 0; j < channels; j++) { + tmp2 = (FIXP_PCM)samples[i * channels + j]; + if (tmp2 == (FIXP_PCM)SAMPLE_MIN) /* protect fAbs from -1.0 value */ + tmp2 = (FIXP_PCM)(SAMPLE_MIN+1); + tmp1 = fMax(tmp1, fAbs(tmp2)); + } + tmp = SATURATE_LEFT_SHIFT(fMultDiv2(tmp1, additionalGain), 1, DFRACT_BITS); + + /* set threshold as lower border to save calculations in running maximum algorithm */ + tmp = fMax(tmp, threshold); + + /* running maximum */ + old = maxBuf[maxBufIdx]; + maxBuf[maxBufIdx] = tmp; + + if (tmp >= max) { + /* new sample is greater than old maximum, so it is the new maximum */ + max = tmp; + } + else if (old < max) { + /* maximum does not change, as the sample, which has left the window was + not the maximum */ + } + else { + /* the old maximum has left the window, we have to search the complete + buffer for the new max */ + max = maxBuf[0]; + for (j = 1; j <= attack; j++) { + if (maxBuf[j] > max) max = maxBuf[j]; + } + } + maxBufIdx++; + if (maxBufIdx >= attack+1) maxBufIdx = 0; + + /* calc gain */ + /* gain is downscaled by one, so that gain = 1.0 can be represented */ + if (max > threshold) { + gain = fDivNorm(threshold, max)>>1; + } + else { + gain = FL2FXCONST_DBL(1.0f/(1<<1)); + } + + /* gain smoothing, method: TDL_EXPONENTIAL */ + /* first order IIR filter with attack correction to avoid overshoots */ + + /* correct the 'aiming' value of the exponential attack to avoid the remaining overshoot */ + if (gain < smoothState0) { + cor = fMin(cor, fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f*(1<<1)),smoothState0)), FL2FXCONST_SGL(1.11111111f/(1<<1)))<<2); + } + else { + cor = gain; + } + + /* smoothing filter */ + if (cor < smoothState0) { + smoothState0 = fMult(attackConst,(smoothState0 - cor)) + cor; /* attack */ + smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */ + } + else { + /* sign inversion twice to round towards +infinity, + so that gain can converge to 1.0 again, + for bit-identical output when limiter is not active */ + smoothState0 = -fMult(releaseConst,-(smoothState0 - cor)) + cor; /* release */ + } + + gain = smoothState0; + + /* lookahead delay, apply gain */ + for (j = 0; j < channels; j++) { + + tmp = delayBuf[delayBufIdx * channels + j]; + delayBuf[delayBufIdx * channels + j] = fMult((FIXP_PCM)samples[i * channels + j], additionalGain); + + /* Apply gain to delayed signal */ + if (gain < FL2FXCONST_DBL(1.0f/(1<<1))) + tmp = fMult(tmp,gain<<1); + + samples[i * channels + j] = FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(tmp,TDL_GAIN_SCALING,DFRACT_BITS)); + } + delayBufIdx++; + if (delayBufIdx >= attack) delayBufIdx = 0; + + /* save minimum gain factor */ + if (gain < minGain) minGain = gain; + } + + + limiter->max = max; + limiter->maxBufIdx = maxBufIdx; + limiter->cor = cor; + limiter->delayBufIdx = delayBufIdx; + + limiter->smoothState0 = smoothState0; + limiter->additionalGainFilterState = additionalGainSmoothState; + limiter->additionalGainFilterState1 = additionalGainSmoothState1; + + limiter->minGain = minGain; + + limiter->additionalGainPrev = pGain[0]; + + return TDLIMIT_OK; + } +} + +/* get delay in samples */ +unsigned int getLimiterDelay(TDLimiterPtr limiter) +{ + FDK_ASSERT(limiter != NULL); + return limiter->attack; +} + +/* set number of channels */ +TDLIMITER_ERROR setLimiterNChannels(TDLimiterPtr limiter, unsigned int nChannels) +{ + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER; + + limiter->channels = nChannels; + //resetLimiter(limiter); + + return TDLIMIT_OK; +} + +/* set sampling rate */ +TDLIMITER_ERROR setLimiterSampleRate(TDLimiterPtr limiter, unsigned int sampleRate) +{ + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER; + + /* update attack and release time in samples */ + attack = (unsigned int)(limiter->attackMs * sampleRate / 1000); + release = (unsigned int)(limiter->releaseMs * sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack+1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->sampleRate = sampleRate; + + /* reset */ + //resetLimiter(limiter); + + return TDLIMIT_OK; +} + +/* set attack time */ +TDLIMITER_ERROR setLimiterAttack(TDLimiterPtr limiter, unsigned int attackMs) +{ + unsigned int attack; + FIXP_DBL attackConst, exponent; + INT e_ans; + + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER; + + /* calculate attack time in samples */ + attack = (unsigned int)(attackMs * limiter->sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack+1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->attackMs = attackMs; + + return TDLIMIT_OK; +} + +/* set release time */ +TDLIMITER_ERROR setLimiterRelease(TDLimiterPtr limiter, unsigned int releaseMs) +{ + unsigned int release; + FIXP_DBL releaseConst, exponent; + INT e_ans; + + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + /* calculate release time in samples */ + release = (unsigned int)(releaseMs * limiter->sampleRate / 1000); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->releaseConst = releaseConst; + limiter->releaseMs = releaseMs; + + return TDLIMIT_OK; +} + +/* set limiter threshold */ +TDLIMITER_ERROR setLimiterThreshold(TDLimiterPtr limiter, INT_PCM threshold) +{ + if ( limiter == NULL ) return TDLIMIT_INVALID_HANDLE; + + limiter->threshold = (FIXP_PCM)threshold; + + return TDLIMIT_OK; +} diff --git a/libPCMutils/src/pcmutils_lib.cpp b/libPCMutils/src/pcmutils_lib.cpp new file mode 100644 index 00000000..e47a7dd5 --- /dev/null +++ b/libPCMutils/src/pcmutils_lib.cpp @@ -0,0 +1,2505 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/**************************** FDK PCM utils module ************************** + + Author(s): Christian Griebel + Description: Defines functions that perform downmixing or a simple channel + expansion in the PCM time domain. + +*******************************************************************************/ + +#include "pcmutils_lib.h" + +#include "genericStds.h" +#include "fixpoint_math.h" +#include "FDK_core.h" + + +/* ------------------------ * + * GLOBAL SETTINGS (GFR): * + * ------------------------ */ +#define DSE_METADATA_ENABLE /*!< Enable this to support MPEG/ETSI DVB ancillary data for + encoder assisted downmixing of MPEG-4 AAC and + MPEG-1/2 layer 2 streams. */ +#define PCE_METADATA_ENABLE /*!< Enable this to support MPEG matrix mixdown with a + coefficient carried in the PCE. */ + +#define PCM_DMX_MAX_IN_CHANNELS ( 8 ) /* Neither the maximum number of input nor the maximum number of output channels ... */ +#define PCM_DMX_MAX_OUT_CHANNELS ( 8 ) /* ... must exceed the maximum number of channels that the framework can handle. */ + +/* ------------------------ * + * SPECIFIC SETTINGS: * + * ------------------------ */ +#define PCM_CHANNEL_EXTENSION_ENABLE /*!< Allow module to duplicate mono signals or add zero channels to achieve the + desired number of output channels. */ + +#define PCM_DMX_DFLT_MAX_OUT_CHANNELS ( 6 ) /*!< The maximum number of output channels. If the value is greater than 0 the module + will automatically create a mixdown for all input signals with more channels + than specified. */ +#define PCM_DMX_DFLT_MIN_OUT_CHANNELS ( 0 ) /*!< The minimum number of output channels. If the value is greater than 0 the module + will do channel extension automatically for all input signals with less channels + than specified. */ +#define PCM_DMX_MAX_DELAY_FRAMES ( 1 ) /*!< The maximum delay frames to align the bitstreams payload with the PCM output. */ +#define PCM_DMX_DFLT_EXPIRY_FRAME ( 50 ) /*!< If value is greater than 0 the mixdown coefficients will expire by default after the + given number of frames. The value 50 corresponds to at least 500ms (FL 960 @ 96kHz) */ +/* #define PCMDMX_DEBUG */ + +/* Derived setting: + * No need to edit beyond this line. */ +#if defined(DSE_METADATA_ENABLE) || defined(PCE_METADATA_ENABLE) || defined(ARIB_MIXDOWN_ENABLE) + #define PCM_DOWNMIX_ENABLE /*!< Generally enable down mixing. */ +#endif +#if (PCM_DMX_MAX_IN_CHANNELS > 2) || (PCM_DMX_MAX_OUT_CHANNELS > 2) + #define PCM_DMX_MAX_CHANNELS ( 8 ) + #define PCM_DMX_MAX_CHANNEL_GROUPS ( 4 ) + #define PCM_DMX_MAX_CHANNELS_PER_GROUP PCM_DMX_MAX_CHANNELS /* All channels can be in one group */ +#else + #define PCM_DMX_MAX_CHANNELS ( 3 ) /* Need to add 1 because there are three channel positions in first channel group. */ + #define PCM_DMX_MAX_CHANNEL_GROUPS ( 1 ) /* Only front channels supported. */ + #define PCM_DMX_MAX_CHANNELS_PER_GROUP ( 2 ) /* The maximum over all channel groups */ +#endif +#if (PCM_DMX_MAX_IN_CHANNELS > PCM_DMX_MAX_OUT_CHANNELS) + #define PCM_DMX_MAX_IO_CHANNELS PCM_DMX_MAX_IN_CHANNELS +#else + #define PCM_DMX_MAX_IO_CHANNELS PCM_DMX_MAX_OUT_CHANNELS +#endif + +/* Decoder library info */ +#define PCMDMX_LIB_VL0 2 +#define PCMDMX_LIB_VL1 4 +#define PCMDMX_LIB_VL2 2 +#define PCMDMX_LIB_TITLE "PCM Downmix Lib" +#ifdef __ANDROID__ +#define PCMDMX_LIB_BUILD_DATE "" +#define PCMDMX_LIB_BUILD_TIME "" +#else +#define PCMDMX_LIB_BUILD_DATE __DATE__ +#define PCMDMX_LIB_BUILD_TIME __TIME__ +#endif + + +/* Fixed and unique channel group indices. + * The last group index has to be smaller than PCM_DMX_MAX_CHANNEL_GROUPS. */ +#define CH_GROUP_FRONT ( 0 ) +#define CH_GROUP_SIDE ( 1 ) +#define CH_GROUP_REAR ( 2 ) +#define CH_GROUP_LFE ( 3 ) + +/* The ordering of the following fixed channel labels has to be in MPEG-4 style. + * From the center to the back with left and right channel interleaved (starting with left). + * The last channel label index has to be smaller than PCM_DMX_MAX_CHANNELS. */ +#define CENTER_FRONT_CHANNEL ( 0 ) /* C */ +#define LEFT_FRONT_CHANNEL ( 1 ) /* L */ +#define RIGHT_FRONT_CHANNEL ( 2 ) /* R */ +#define LEFT_REAR_CHANNEL ( 3 ) /* Lr (aka left back channel) or center back channel */ +#define RIGHT_REAR_CHANNEL ( 4 ) /* Rr (aka right back channel) */ +#define LOW_FREQUENCY_CHANNEL ( 5 ) /* Lf */ +#define LEFT_MULTIPRPS_CHANNEL ( 6 ) /* Left multipurpose channel */ +#define RIGHT_MULTIPRPS_CHANNEL ( 7 ) /* Right multipurpose channel */ + +/* More constants */ +#define ONE_CHANNEL ( 1 ) +#define TWO_CHANNEL ( 2 ) +#define SIX_CHANNEL ( 6 ) +#define EIGHT_CHANNEL ( 8 ) + +#define PCMDMX_A_IDX_DEFAULT ( 2 ) +#define PCMDMX_B_IDX_DEFAULT ( 2 ) +#define PCMDMX_LFE_IDX_DEFAULT ( 15 ) +#define PCMDMX_GAIN_5_DEFAULT ( 0 ) +#define PCMDMX_GAIN_2_DEFAULT ( 0 ) + +#define PCMDMX_MAX_HEADROOM ( 3 ) /* Defines the maximum PCM scaling headroom that can be done by a + postprocessing step. This value must be greater or equal to 0. */ + +#define FALSE 0 +#define TRUE 1 +#define IN 0 +#define OUT 1 + +/* Type definitions: */ +#ifndef DMX_HIGH_PRECISION_ENABLE + #define FIXP_DMX FIXP_SGL + #define FX_DMX2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) + #define FX_DBL2FX_DMX(x) FX_DBL2FX_SGL(x) + #define FL2FXCONST_DMX(x) FL2FXCONST_SGL(x) + #define MAXVAL_DMX MAXVAL_SGL + #define FX_DMX2SHRT(x) ((SHORT)(x)) + #define FX_DMX2FL(x) FX_DBL2FL(FX_DMX2FX_DBL(x)) +#else + #define FIXP_DMX FIXP_DBL + #define FX_DMX2FX_DBL(x) ((FIXP_DBL)(x)) + #define FX_DBL2FX_DMX(x) ((FIXP_DBL)(x) + #define FL2FXCONST_DMX(x) FL2FXCONST_DBL(x) + #define MAXVAL_DMX MAXVAL_DBL + #define FX_DMX2SHRT(x) ((SHORT)((x)>>FRACT_BITS)) + #define FX_DMX2FL(x) FX_DBL2FL(x) +#endif + +/* The number of channels positions for each group in the internal representation. + * See the channel labels above. */ +static const UCHAR maxChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS] = { +#if (PCM_DMX_MAX_CHANNELS > 3) + 3, 0, 2, 1 +#else + PCM_DMX_MAX_CHANNELS_PER_GROUP +#endif +}; + +/* List of packed channel modes */ +typedef enum +{ /* CH_MODE____ */ + CH_MODE_UNDEFINED = 0x0000, + /* 1 channel */ + CH_MODE_1_0_0_0 = 0x0001, /* chCfg 1 */ + /* 2 channels */ + CH_MODE_2_0_0_0 = 0x0002, /* chCfg 2 */ + /* 3 channels */ + CH_MODE_3_0_0_0 = 0x0003, /* chCfg 3 */ + CH_MODE_2_0_1_0 = 0x0102, + CH_MODE_2_0_0_1 = 0x1002, + /* 4 channels */ + CH_MODE_3_0_1_0 = 0x0103, /* chCfg 4 */ + CH_MODE_2_0_2_0 = 0x0202, + CH_MODE_2_0_1_1 = 0x1102, + CH_MODE_4_0_0_0 = 0x0004, + /* 5 channels */ + CH_MODE_3_0_2_0 = 0x0203, /* chCfg 5 */ + CH_MODE_2_0_2_1 = 0x1202, + CH_MODE_3_0_1_1 = 0x1103, + CH_MODE_3_2_0_0 = 0x0023, + CH_MODE_5_0_0_0 = 0x0005, + /* 6 channels */ + CH_MODE_3_0_2_1 = 0x1203, /* chCfg 6 */ + CH_MODE_3_2_0_1 = 0x1023, + CH_MODE_3_2_1_0 = 0x0123, + CH_MODE_5_0_1_0 = 0x0105, + CH_MODE_6_0_0_0 = 0x0006, + /* 7 channels */ + CH_MODE_2_2_2_1 = 0x1222, + CH_MODE_3_0_3_1 = 0x1303, /* chCfg 11 */ + CH_MODE_3_2_1_1 = 0x1123, + CH_MODE_3_2_2_0 = 0x0223, + CH_MODE_3_0_2_2 = 0x2203, + CH_MODE_5_0_2_0 = 0x0205, + CH_MODE_5_0_1_1 = 0x1105, + CH_MODE_7_0_0_0 = 0x0007, + /* 8 channels */ + CH_MODE_3_2_2_1 = 0x1223, + CH_MODE_3_0_4_1 = 0x1403, /* chCfg 12 */ + CH_MODE_5_0_2_1 = 0x1205, /* chCfg 7 + 14 */ + CH_MODE_5_2_1_0 = 0x0125, + CH_MODE_3_2_1_2 = 0x2123, + CH_MODE_2_2_2_2 = 0x2222, + CH_MODE_3_0_3_2 = 0x2303, + CH_MODE_8_0_0_0 = 0x0008 + +} PCM_DMX_CHANNEL_MODE; + + +/* These are the channel configurations linked to + the number of output channels give by the user: */ +static const PCM_DMX_CHANNEL_MODE outChModeTable[PCM_DMX_MAX_CHANNELS+1] = +{ + CH_MODE_UNDEFINED, + CH_MODE_1_0_0_0, /* 1 channel */ + CH_MODE_2_0_0_0, /* 2 channels */ + CH_MODE_3_0_0_0 /* 3 channels */ +#if (PCM_DMX_MAX_CHANNELS > 3) + ,CH_MODE_3_0_1_0, /* 4 channels */ + CH_MODE_3_0_2_0, /* 5 channels */ + CH_MODE_3_0_2_1, /* 6 channels */ + CH_MODE_3_0_3_1, /* 7 channels */ + CH_MODE_3_0_4_1 /* 8 channels */ +#endif +}; + +static const FIXP_DMX abMixLvlValueTab[8] = +{ + FL2FXCONST_DMX(0.500f), /* scaled by 1 */ + FL2FXCONST_DMX(0.841f), + FL2FXCONST_DMX(0.707f), + FL2FXCONST_DMX(0.596f), + FL2FXCONST_DMX(0.500f), + FL2FXCONST_DMX(0.422f), + FL2FXCONST_DMX(0.355f), + FL2FXCONST_DMX(0.0f) +}; + +static const FIXP_DMX lfeMixLvlValueTab[16] = +{ /* value, scale */ + FL2FXCONST_DMX(0.7905f), /* 2 */ + FL2FXCONST_DMX(0.5000f), /* 2 */ + FL2FXCONST_DMX(0.8395f), /* 1 */ + FL2FXCONST_DMX(0.7065f), /* 1 */ + FL2FXCONST_DMX(0.5945f), /* 1 */ + FL2FXCONST_DMX(0.500f), /* 1 */ + FL2FXCONST_DMX(0.841f), /* 0 */ + FL2FXCONST_DMX(0.707f), /* 0 */ + FL2FXCONST_DMX(0.596f), /* 0 */ + FL2FXCONST_DMX(0.500f), /* 0 */ + FL2FXCONST_DMX(0.316f), /* 0 */ + FL2FXCONST_DMX(0.178f), /* 0 */ + FL2FXCONST_DMX(0.100f), /* 0 */ + FL2FXCONST_DMX(0.032f), /* 0 */ + FL2FXCONST_DMX(0.010f), /* 0 */ + FL2FXCONST_DMX(0.000f) /* 0 */ +}; + + + +#ifdef PCE_METADATA_ENABLE + /* MPEG matrix mixdown: + Set 1: L' = (1 + 2^-0.5 + A )^-1 * [L + C * 2^-0.5 + A * Ls]; + R' = (1 + 2^-0.5 + A )^-1 * [R + C * 2^-0.5 + A * Rs]; + + Set 2: L' = (1 + 2^-0.5 + 2A )^-1 * [L + C * 2^-0.5 - A * (Ls + Rs)]; + R' = (1 + 2^-0.5 + 2A )^-1 * [R + C * 2^-0.5 + A * (Ls + Rs)]; + + M = (3 + 2A)^-1 * [L + C + R + A*(Ls + Rs)]; + */ + static const FIXP_DMX mpegMixDownIdx2Coef[4] = + { + FL2FXCONST_DMX(0.70710678f), + FL2FXCONST_DMX(0.5f), + FL2FXCONST_DMX(0.35355339f), + FL2FXCONST_DMX(0.0f) + }; + + static const FIXP_SGL mpegMixDownIdx2PreFact[3][4] = + { { /* Set 1: */ + FL2FXCONST_DMX(0.4142135623730950f), + FL2FXCONST_DMX(0.4530818393219728f), + FL2FXCONST_DMX(0.4852813742385703f), + FL2FXCONST_DMX(0.5857864376269050f) + },{ /* Set 2: */ + FL2FXCONST_DMX(0.3203772410170407f), + FL2FXCONST_DMX(0.3693980625181293f), + FL2FXCONST_DMX(0.4142135623730950f), + FL2FXCONST_DMX(0.5857864376269050f) + },{ /* Mono DMX set: */ + FL2FXCONST_DMX(0.2265409196609864f), + FL2FXCONST_DMX(0.25f), + FL2FXCONST_DMX(0.2697521433898179f), + FL2FXCONST_DMX(0.3333333333333333f) } + }; +#endif /* PCE_METADATA_ENABLE */ + + +#define TYPE_NONE ( 0x0 ) +#define TYPE_DSE_DATA ( 0x1 ) +#define TYPE_PCE_DATA ( 0x2 ) + +typedef struct +{ + UINT typeFlags; + /* From DSE */ + UCHAR cLevIdx; + UCHAR sLevIdx; + UCHAR dmixIdxA; + UCHAR dmixIdxB; + UCHAR dmixIdxLfe; + UCHAR dmxGainIdx2; + UCHAR dmxGainIdx5; +#ifdef PCE_METADATA_ENABLE + /* From PCE */ + UCHAR matrixMixdownIdx; +#endif + /* Attributes: */ + SCHAR pseudoSurround; /*!< If set to 1 the signal is pseudo surround compatible. The value 0 tells + that it is not. If the value is -1 the information is not available. */ + UINT expiryCount; /*!< Counter to monitor the life time of a meta data set. */ + +} DMX_BS_META_DATA; + +/* Default metadata */ +static const DMX_BS_META_DATA dfltMetaData = { + 0, 2, 2, 2, 2, 15, 0, 0, +#ifdef PCE_METADATA_ENABLE + 0, +#endif + -1, 0 +}; + +/* Dynamic (user) params: + See the definition of PCMDMX_PARAM for details on the specific fields. */ +typedef struct +{ + UINT expiryFrame; /*!< Linked to DMX_BS_DATA_EXPIRY_FRAME */ + DUAL_CHANNEL_MODE dualChannelMode; /*!< Linked to DMX_DUAL_CHANNEL_MODE */ + PSEUDO_SURROUND_MODE pseudoSurrMode; /*!< Linked to DMX_PSEUDO_SURROUND_MODE */ + SHORT numOutChannelsMin; /*!< Linked to MIN_NUMBER_OF_OUTPUT_CHANNELS */ + SHORT numOutChannelsMax; /*!< Linked to MAX_NUMBER_OF_OUTPUT_CHANNELS */ + UCHAR frameDelay; /*!< Linked to DMX_BS_DATA_DELAY */ + +} PCM_DMX_USER_PARAMS; + +/* Modules main data structure: */ +struct PCM_DMX_INSTANCE +{ + /* Metadata */ + DMX_BS_META_DATA bsMetaData[PCM_DMX_MAX_DELAY_FRAMES+1]; + PCM_DMX_USER_PARAMS userParams; + + UCHAR applyProcessing; /*!< Flag to en-/disable modules processing. + The max channel limiting is done independently. */ +}; + +/* Memory allocation macro */ +C_ALLOC_MEM_STATIC(PcmDmxInstance, struct PCM_DMX_INSTANCE, 1) + + +/** Evaluate a given channel configuration and extract a packed channel mode. In addition the + * function generates a channel offset table for the mapping to the internal representation. + * This function is the inverse to the getChannelDescription() routine. + * @param [in] The total number of channels of the given configuration. + * @param [in] Array holding the corresponding channel types for each channel. + * @param [in] Array holding the corresponding channel type indices for each channel. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @param [out] The generated packed channel mode that represents the given input configuration. + * @returns Returns an error code. + **/ +static +PCMDMX_ERROR getChannelMode ( + const INT numChannels, /* in */ + const AUDIO_CHANNEL_TYPE channelType[], /* in */ + const UCHAR channelIndices[], /* in */ + UCHAR offsetTable[PCM_DMX_MAX_CHANNELS], /* out */ + PCM_DMX_CHANNEL_MODE *chMode /* out */ + ) +{ + UCHAR chIdx[PCM_DMX_MAX_CHANNEL_GROUPS][PCM_DMX_MAX_CHANNELS_PER_GROUP]; + UCHAR numChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS]; /* Total num of channels per group of the input config */ + UCHAR numChFree[PCM_DMX_MAX_CHANNEL_GROUPS]; /* Number of free slots per group in the internal repr. */ + UCHAR hardToPlace[PCM_DMX_MAX_CHANNELS]; /* List of channels not matching the internal repr. */ + UCHAR h2pSortIdx[PCM_DMX_MAX_CHANNELS]; + PCMDMX_ERROR err = PCMDMX_OK; + int ch, grpIdx; + int numChToPlace = 0; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(offsetTable != NULL); + FDK_ASSERT(chMode != NULL); + + /* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */ + FDKmemclear(numChInGrp, PCM_DMX_MAX_CHANNEL_GROUPS*sizeof(UCHAR)); + FDKmemset(offsetTable, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + FDKmemset(chIdx, 255, PCM_DMX_MAX_CHANNEL_GROUPS*PCM_DMX_MAX_CHANNELS_PER_GROUP*sizeof(UCHAR)); + FDKmemset(hardToPlace, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + FDKmemset(h2pSortIdx, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + /* Get the restrictions of the internal representation */ + FDKmemcpy(numChFree, maxChInGrp, PCM_DMX_MAX_CHANNEL_GROUPS*sizeof(UCHAR)); + + *chMode = CH_MODE_UNDEFINED; + + /* Categorize channels */ + for (ch = 0; ch < numChannels; ch += 1) { + UCHAR chGrpIdx = channelIndices[ch]; + int i = 0, j; + + switch (channelType[ch]) { + case ACT_FRONT_TOP: + chGrpIdx += numChInGrp[CH_GROUP_FRONT]; /* Append after normal plain */ + case ACT_FRONT: + grpIdx = CH_GROUP_FRONT; + break; +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + case ACT_SIDE_TOP: + chGrpIdx += numChInGrp[CH_GROUP_SIDE]; /* Append after normal plain */ + case ACT_SIDE: + grpIdx = CH_GROUP_SIDE; + break; + case ACT_BACK_TOP: + chGrpIdx += numChInGrp[CH_GROUP_REAR]; /* Append after normal plain */ + case ACT_BACK: + grpIdx = CH_GROUP_REAR; + break; + case ACT_LFE: + grpIdx = CH_GROUP_LFE; + break; +#endif + default: + /* Found a channel that can not be categorized! Most likely due to corrupt input signalling. + The rescue strategy is to append it to the front channels (=> ignore index). + This could cause strange behaviour so return an error to signal it. */ + err = PCMDMX_INVALID_MODE; + grpIdx = CH_GROUP_FRONT; + chGrpIdx = numChannels + numChToPlace; + numChToPlace += 1; + break; + } + + if (numChInGrp[grpIdx] < PCM_DMX_MAX_CHANNELS_PER_GROUP) { + /* Sort channels by index */ + while ( (i < numChInGrp[grpIdx]) && (chGrpIdx > channelIndices[chIdx[grpIdx][i]]) ) { + i += 1; + } + for (j = numChInGrp[grpIdx]; j > i; j -= 1) { + chIdx[grpIdx][j] = chIdx[grpIdx][j-1]; + } + chIdx[grpIdx][i] = ch; + numChInGrp[grpIdx] += 1; + } + } + +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + FDK_ASSERT( (numChInGrp[CH_GROUP_FRONT]+numChInGrp[CH_GROUP_SIDE] + +numChInGrp[CH_GROUP_REAR]+numChInGrp[CH_GROUP_LFE]) == numChannels); +#else + FDK_ASSERT( numChInGrp[CH_GROUP_FRONT] == numChannels ); +#endif + + /* Compose channel offset table: + * Map all channels to the internal representation. */ + numChToPlace = 0; + + /* Non-symmetric channels */ + if (numChInGrp[CH_GROUP_FRONT] & 0x1) { + /* Odd number of front channels -> we have a center channel. + In MPEG-4 the center has the index 0. */ + offsetTable[CENTER_FRONT_CHANNEL] = chIdx[CH_GROUP_FRONT][0]; + numChFree[CH_GROUP_FRONT] -= 1; + } + + for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) { + int chMapPos = 0; + ch = 0; /* Index of channel within the specific group */ + + switch (grpIdx) { + case CH_GROUP_FRONT: + chMapPos = LEFT_FRONT_CHANNEL; + ch = numChInGrp[grpIdx] & 0x1; + break; +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + case CH_GROUP_SIDE: + break; + case CH_GROUP_REAR: + chMapPos = LEFT_REAR_CHANNEL; + break; + case CH_GROUP_LFE: + chMapPos = LOW_FREQUENCY_CHANNEL; + break; +#endif + default: + FDK_ASSERT(0); + continue; + } + + /* Map all channels of the group */ + for ( ; ch < numChInGrp[grpIdx]; ch += 1) { + if (numChFree[grpIdx] > 0) { + offsetTable[chMapPos] = chIdx[grpIdx][ch]; + chMapPos += 1; + numChFree[grpIdx] -= 1; + } else { + /* Add to the list of hardship cases considering a MPEG-like sorting order: */ + int pos, sortIdx = grpIdx*PCM_DMX_MAX_CHANNELS_PER_GROUP + channelIndices[chIdx[grpIdx][ch]]; + for (pos = numChToPlace; pos > 0; pos -= 1) { + if (h2pSortIdx[pos-1] > sortIdx) { + hardToPlace[pos] = hardToPlace[pos-1]; + h2pSortIdx[pos] = h2pSortIdx[pos-1]; + } else { + /* Insert channel at the current index/position */ + break; + } + } + hardToPlace[pos] = chIdx[grpIdx][ch]; + h2pSortIdx[pos] = sortIdx; + numChToPlace += 1; + } + } + } + + { /* Assign the hardship cases */ + int chMapPos = 0; + int mappingHeat = 0; + for (ch = 0; ch < numChToPlace; ch+=1) { + int chAssigned = 0; + + /* Just assigning the channels to the next best slot can lead to undesired results (especially for x/x/1.x + configurations). Thus use the MPEG-like sorting index to find the best fitting slot for each channel. + If this is not possible the sorting index will be ignored (mappingHeat >= 2). */ + for ( ; chMapPos < PCM_DMX_MAX_CHANNELS; chMapPos+=1) { + if (offsetTable[chMapPos] == 255) { + int prvSortIdx = 0; + int nxtSortIdx = (CH_GROUP_LFE+1)*PCM_DMX_MAX_CHANNELS_PER_GROUP; + + if (mappingHeat < 2) { + if (chMapPos < LEFT_REAR_CHANNEL) { + /* Got front channel slot */ + prvSortIdx = CH_GROUP_FRONT*PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - CENTER_FRONT_CHANNEL; + nxtSortIdx = CH_GROUP_SIDE *PCM_DMX_MAX_CHANNELS_PER_GROUP; + } + else if (chMapPos < LOW_FREQUENCY_CHANNEL) { + /* Got back channel slot */ + prvSortIdx = CH_GROUP_REAR*PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - LEFT_REAR_CHANNEL; + nxtSortIdx = CH_GROUP_LFE *PCM_DMX_MAX_CHANNELS_PER_GROUP; + } + else if (chMapPos < LEFT_MULTIPRPS_CHANNEL) { + /* Got lfe channel slot */ + prvSortIdx = CH_GROUP_LFE *PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - LOW_FREQUENCY_CHANNEL; + nxtSortIdx = (CH_GROUP_LFE+1)*PCM_DMX_MAX_CHANNELS_PER_GROUP; + } + } + + /* Assign the channel only if its sort index is within the range */ + if ( (h2pSortIdx[ch] >= prvSortIdx) + && (h2pSortIdx[ch] < nxtSortIdx) ) { + offsetTable[chMapPos++] = hardToPlace[ch]; + chAssigned = 1; + break; + } + } + } + if (chAssigned == 0) { + chMapPos = 0; + ch -= 1; + mappingHeat += 1; + continue; + } + } + } + + /* Compose the channel mode */ + *chMode = (PCM_DMX_CHANNEL_MODE)( (numChInGrp[CH_GROUP_FRONT] & 0xF) +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + | (numChInGrp[CH_GROUP_SIDE] & 0xF) << 4 + | (numChInGrp[CH_GROUP_REAR] & 0xF) << 8 + | (numChInGrp[CH_GROUP_LFE] & 0xF) << 12 +#endif + ); + + return err; +} + + +/** Generate a channel offset table and complete channel description for a given (packed) channel mode. + * This function is the inverse to the getChannelMode() routine but does not support weird channel + * configurations. All channels have to be in the normal height layer and there must not be more + * channels in each group than given by maxChInGrp. + * @param [in] The packed channel mode of the configuration to be processed. + * @param [in] Array containing the channel mapping to be used (From MPEG PCE ordering to whatever is required). + * @param [out] Array where corresponding channel types for each channels are stored into. + * @param [out] Array where corresponding channel type indices for each output channel are stored into. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @returns None. + **/ +static +void getChannelDescription ( + const PCM_DMX_CHANNEL_MODE chMode, /* in */ + const UCHAR channelMapping[][8], /* in */ + AUDIO_CHANNEL_TYPE channelType[], /* out */ + UCHAR channelIndices[], /* out */ + UCHAR offsetTable[PCM_DMX_MAX_CHANNELS] /* out */ + ) +{ + const UCHAR *pChannelMap; + int grpIdx, ch = 0, numChannels = 0; + UCHAR numChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS]; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(channelMapping != NULL); + FDK_ASSERT(offsetTable != NULL); + + /* Init output arrays */ + FDKmemclear(channelType, PCM_DMX_MAX_IO_CHANNELS*sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemclear(channelIndices, PCM_DMX_MAX_IO_CHANNELS*sizeof(UCHAR)); + FDKmemset(offsetTable, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + + /* Extract the number of channels per group */ + numChInGrp[CH_GROUP_FRONT] = chMode & 0xF; +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + numChInGrp[CH_GROUP_SIDE] = (chMode >> 4) & 0xF; + numChInGrp[CH_GROUP_REAR] = (chMode >> 8) & 0xF; + numChInGrp[CH_GROUP_LFE] = (chMode >> 12) & 0xF; +#endif + + /* Summerize to get the total number of channels */ + for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) { + numChannels += numChInGrp[grpIdx]; + } + + /* Get the appropriate channel map */ + switch (chMode) { + case CH_MODE_1_0_0_0: + case CH_MODE_2_0_0_0: + case CH_MODE_3_0_0_0: + case CH_MODE_3_0_1_0: + case CH_MODE_3_0_2_0: + case CH_MODE_3_0_2_1: + pChannelMap = channelMapping[numChannels]; + break; + case CH_MODE_3_0_3_1: + pChannelMap = channelMapping[11]; + break; + case CH_MODE_3_0_4_1: + pChannelMap = channelMapping[12]; + break; + case CH_MODE_5_0_2_1: + pChannelMap = channelMapping[7]; + break; + default: + /* fallback */ + pChannelMap = channelMapping[0]; + break; + } + + /* Compose channel offset table */ + + /* Non-symmetric channels */ + if (numChInGrp[CH_GROUP_FRONT] & 0x1) { + /* Odd number of front channels -> we have a center channel. + In MPEG-4 the center has the index 0. */ + int mappedIdx = pChannelMap[ch]; + offsetTable[CENTER_FRONT_CHANNEL] = mappedIdx; + channelType[mappedIdx] = ACT_FRONT; + channelIndices[mappedIdx] = 0; + ch += 1; + } + + for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) { + AUDIO_CHANNEL_TYPE type = ACT_NONE; + int chMapPos = 0, maxChannels = 0; + int chIdx = 0; /* Index of channel within the specific group */ + + switch (grpIdx) { + case CH_GROUP_FRONT: + type = ACT_FRONT; + chMapPos = LEFT_FRONT_CHANNEL; + maxChannels = 3; + chIdx = numChInGrp[grpIdx] & 0x1; + break; +#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1) + case CH_GROUP_SIDE: + /* Always map side channels to the multipurpose group. */ + type = ACT_SIDE; + chMapPos = LEFT_MULTIPRPS_CHANNEL; + break; + case CH_GROUP_REAR: + type = ACT_BACK; + chMapPos = LEFT_REAR_CHANNEL; + maxChannels = 2; + break; + case CH_GROUP_LFE: + type = ACT_LFE; + chMapPos = LOW_FREQUENCY_CHANNEL; + maxChannels = 1; + break; +#endif + default: + break; + } + + /* Map all channels in this group */ + for ( ; chIdx < numChInGrp[grpIdx]; chIdx += 1) { + int mappedIdx = pChannelMap[ch]; + if (chIdx == maxChannels) { + /* No space left in this channel group! + Use the multipurpose group instead: */ + chMapPos = LEFT_MULTIPRPS_CHANNEL; + } + offsetTable[chMapPos] = mappedIdx; + channelType[mappedIdx] = type; + channelIndices[mappedIdx] = chIdx; + chMapPos += 1; + ch += 1; + } + } +} + +/** Private helper function for downmix matrix manipulation that initializes + * one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix factors. + * @param [in] Index of channel (row) to be initialized. + * @returns Nothing to return. + **/ +static +void dmxInitChannel( + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + INT mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + const unsigned int outCh + ) +{ + unsigned int inCh; + for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) { + if (inCh == outCh) { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.5f); + mixScales[outCh][inCh] = 1; + } else { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.0f); + mixScales[outCh][inCh] = 0; + } + } +} + +/** Private helper function for downmix matrix manipulation that does a reset + * of one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix factors. + * @param [in] Index of channel (row) to be cleared/reset. + * @returns Nothing to return. + **/ +static +void dmxClearChannel( + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + INT mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + const unsigned int outCh + ) +{ + FDKmemclear(&mixFactors[outCh], PCM_DMX_MAX_CHANNELS*sizeof(FIXP_DMX)); + FDKmemclear(&mixScales[outCh], PCM_DMX_MAX_CHANNELS*sizeof(INT)); +} + +/** Private helper function for downmix matrix manipulation that applies a source channel (row) + * scaled by a given mix factor to a destination channel (row) in a given downmix matrix. + * Existing mix factors of the destination channel (row) will get overwritten. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static +void dmxSetChannel( + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + INT mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + const unsigned int dstCh, + const unsigned int srcCh, + const FIXP_DMX factor, + const INT scale + ) +{ + int ch; + for (ch=0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) { + if (mixFactors[srcCh][ch] != (FIXP_DMX)0) { + mixFactors[dstCh][ch] = FX_DBL2FX_DMX(fMult(mixFactors[srcCh][ch], factor)); + mixScales[dstCh][ch] = mixScales[srcCh][ch] + scale; + } + } +} + +/** Private helper function for downmix matrix manipulation that adds a source channel (row) + * scaled by a given mix factor to a destination channel (row) in a given downmix matrix. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static +void dmxAddChannel( + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + INT mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + const unsigned int dstCh, + const unsigned int srcCh, + const FIXP_DMX factor, + const INT scale + ) +{ + int ch; + for (ch=0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) { + FIXP_DBL addFact = fMult(mixFactors[srcCh][ch], factor); + if (addFact != (FIXP_DMX)0) { + INT newScale = mixScales[srcCh][ch] + scale; + if (mixFactors[dstCh][ch] != (FIXP_DMX)0) { + if (newScale > mixScales[dstCh][ch]) { + mixFactors[dstCh][ch] >>= newScale - mixScales[dstCh][ch]; + } else { + addFact >>= mixScales[dstCh][ch] - newScale; + newScale = mixScales[dstCh][ch]; + } + } + mixFactors[dstCh][ch] += FX_DBL2FX_DMX(addFact); + mixScales[dstCh][ch] = newScale; + } + } +} + + +/** Private function that creates a downmix factor matrix depending on the input and output + * configuration, the user parameters as well as the given metadata. This function is the modules + * brain and hold all downmix algorithms. + * @param [in] Flag that indicates if inChMode holds a real (packed) channel mode or has been + converted to a MPEG-4 channel configuration index. + * @param [in] Dependent on the inModeIsCfg flag this field hands in a (packed) channel mode or + the corresponding MPEG-4 channel configuration index.of the input configuration. + * @param [in] The (packed) channel mode of the output configuration. + * @param [in] Pointer to structure holding all current user parameter. + * @param [in] Pointer to field holding all current meta data. + * @param [out] Pointer to fixed-point parts of the downmix matrix. Normalized to one scale factor. + * @param [out] The common scale factor of the downmix matrix. + * @returns An error code. + **/ +static +PCMDMX_ERROR getMixFactors ( + const UCHAR inModeIsCfg, + PCM_DMX_CHANNEL_MODE inChMode, + const PCM_DMX_CHANNEL_MODE outChMode, + const PCM_DMX_USER_PARAMS *pParams, + const DMX_BS_META_DATA *pMetaData, + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS], + INT *pOutScale + ) +{ + PCMDMX_ERROR err = PCMDMX_OK; + INT mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS]; + INT maxScale = 0; + int numInChannel, numOutChannel; + unsigned int outCh, inCh, inChCfg = 0; + unsigned int valid[PCM_DMX_MAX_CHANNELS] = { 0 }; + + FDK_ASSERT(pMetaData != NULL); + FDK_ASSERT(mixFactors != NULL); + /* Check on a supported output configuration */ + FDK_ASSERT( (outChMode == CH_MODE_1_0_0_0) + || (outChMode == CH_MODE_2_0_0_0) + || (outChMode == CH_MODE_3_0_2_1) ); + + if (inModeIsCfg) { + /* Workaround for the ambiguity of the internal channel modes. + Convert channel config to channel mode: */ + inChCfg = (unsigned int)inChMode; + switch (inChCfg) { + case 1: case 2: case 3: +#if (PCM_DMX_MAX_CHANNELS > 3) + case 4: case 5: case 6: +#endif + inChMode = outChModeTable[inChCfg]; + break; + case 11: + inChMode = CH_MODE_3_0_3_1; + break; + case 12: + inChMode = CH_MODE_3_0_4_1; + break; + case 7: case 14: + inChMode = CH_MODE_5_0_2_1; + break; + default: + FDK_ASSERT(0); + } + } + + /* Extract the total number of input channels */ + numInChannel = (inChMode&0xF) + + ((inChMode>> 4)&0xF) + + ((inChMode>> 8)&0xF) + + ((inChMode>>12)&0xF); + /* Extract the total number of output channels */ + numOutChannel = (outChMode&0xF) + + ((outChMode>> 4)&0xF) + + ((outChMode>> 8)&0xF) + + ((outChMode>>12)&0xF); + + /* MPEG ammendment 4 aka ETSI metadata and fallback mode: */ + + + /* Create identity DMX matrix: */ + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + dmxInitChannel( mixFactors, mixScales, outCh ); + } + if (((inChMode>>12)&0xF) == 0) { + /* Clear empty or wrongly mapped input channel */ + dmxClearChannel( mixFactors, mixScales, LOW_FREQUENCY_CHANNEL ); + } + + /* FIRST STAGE: */ + if (numInChannel > SIX_CHANNEL) + { /* Always use MPEG equations either with meta data or with default values. */ + FIXP_DMX dMixFactA, dMixFactB; + INT dMixScaleA, dMixScaleB; + int isValidCfg = TRUE; + + /* Get factors from meta data */ + dMixFactA = abMixLvlValueTab[pMetaData->dmixIdxA]; + dMixScaleA = (pMetaData->dmixIdxA==0) ? 1 : 0; + dMixFactB = abMixLvlValueTab[pMetaData->dmixIdxB]; + dMixScaleB = (pMetaData->dmixIdxB==0) ? 1 : 0; + + /* Check if input is in the list of supported configurations */ + switch (inChMode) { + case CH_MODE_3_0_3_1: /* chCfg 11 */ + /* 6.1ch: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */ + dmxClearChannel( mixFactors, mixScales, RIGHT_MULTIPRPS_CHANNEL ); /* clear empty input channel */ + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + break; + case CH_MODE_3_2_1_0: + case CH_MODE_3_2_1_1: /* chCfg 11 but with side channels */ + /* 6.1ch: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */ + dmxClearChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL ); /* clear empty input channel */ + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA ); + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + break; + case CH_MODE_5_2_1_0: + case CH_MODE_5_0_1_0: + case CH_MODE_5_0_1_1: + /* Ls' = Cs*dmix_a_idx; + Rs' = Cs*dmix_a_idx; */ + dmxClearChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL ); /* clear empty input channel */ + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + /* 7.1ch Surround Back: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Lsr*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Rsr*dmix_b_idx; */ + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + break; + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + if (inChCfg == 14) { + /* 7.1ch Front Height: C' = C; Ls' = Ls; Rs' = Rs; LFE' = LFE; + L' = L*dmix_a_idx + Lv*dmix_b_idx; + R' = R*dmix_a_idx + Rv*dmix_b_idx; */ + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB ); + } else { + /* 7.1ch Front: Ls' = Ls; Rs' = Rs; LFE' = LFE; + C' = C + (Lc+Rc)*dmix_a_idx; + L' = L + Lc*dmix_b_idx; + R' = R + Rc*dmix_b_idx; + CAUTION: L+R are not at (MPEG) index 1+2. */ + dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dMixFactA, dMixScaleA ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_MULTIPRPS_CHANNEL, FL2FXCONST_DMX(0.5f), 1 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dMixFactB, dMixScaleB ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, FL2FXCONST_DMX(0.5f), 1 ); + } + break; + default: + /* Nothing to do. Just use the identity matrix. */ + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + break; + } + + /* Add additional DMX gain */ + if ( (isValidCfg == TRUE) + && (pMetaData->dmxGainIdx5 != 0)) + { /* Apply DMX gain 5 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx5 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx5 & 0x3F; + + /* 10^(dmx_gain_5/80) */ + dmxGain = FX_DBL2FX_DMX( fLdPow( + FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign*val*(LONG)FL2FXCONST_DBL(0.0125f)), 0, + &dmxScale ) + ); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_REAR_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, LOW_FREQUENCY_CHANNEL, LOW_FREQUENCY_CHANNEL, dmxGain, dmxScale ); + } + + /* Mark the output channels */ + valid[CENTER_FRONT_CHANNEL] = 1; + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + valid[LEFT_REAR_CHANNEL] = 1; + valid[RIGHT_REAR_CHANNEL] = 1; + valid[LOW_FREQUENCY_CHANNEL] = 1; + + /* Update channel mode for the next stage */ + inChMode = CH_MODE_3_0_2_1; + } + + /* SECOND STAGE: */ + if (numOutChannel <= TWO_CHANNEL) { + /* Create DMX matrix according to input configuration */ + switch (inChMode) { + case CH_MODE_2_0_0_0: /* chCfg 2 */ + /* Apply the dual channel mode. */ + switch (pParams->dualChannelMode) { + case CH1_MODE: /* L' = 0.707 * Ch1; + R' = 0.707 * Ch1; */ + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + break; + case CH2_MODE: /* L' = 0.707 * Ch2; + R' = 0.707 * Ch2; */ + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; + R' = 0.5*Ch1 + 0.5*Ch2; */ + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 ); + break; + default: + case STEREO_MODE: + /* Nothing to do */ + break; + } + break; + case CH_MODE_2_0_1_0: + /* L' = L + 0.707*S; + R' = R + 0.707*S; */ + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + break; + case CH_MODE_3_0_0_0: /* chCfg 3 */ + /* L' = L + 0.707*C; + R' = R + 0.707*C; */ + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + break; + case CH_MODE_3_0_1_0: /* chCfg 4 */ + /* L' = L + 0.707*C + 0.707*S; + R' = R + 0.707*C + 0.707*S; */ + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.707f), 0 ); + break; + case CH_MODE_3_0_2_0: /* chCfg 5 */ + case CH_MODE_3_0_2_1: /* chCfg 6 */ + /* MPEG + ITU + DLB + But because the default downmix equations and coefficients are equal we stick to MPEG. */ + if ( (pMetaData->typeFlags & TYPE_DSE_DATA) + || !(pMetaData->typeFlags & TYPE_PCE_DATA) ) + { + FIXP_DMX cMixLvl, sMixLvl, lMixLvl; + INT cMixScale, sMixScale, lMixScale; + + /* Get factors from meta data */ + cMixLvl = abMixLvlValueTab[pMetaData->cLevIdx]; + cMixScale = (pMetaData->cLevIdx==0) ? 1 : 0; + sMixLvl = abMixLvlValueTab[pMetaData->sLevIdx]; + sMixScale = (pMetaData->sLevIdx==0) ? 1 : 0; + lMixLvl = lfeMixLvlValueTab[pMetaData->dmixIdxLfe]; + if (pMetaData->dmixIdxLfe <= 1) { + lMixScale = 2; + } else if (pMetaData->dmixIdxLfe <= 5) { + lMixScale = 1; + } else { + lMixScale = 0; + } + /* Setup the DMX matrix */ + if ( (pParams->pseudoSurrMode == FORCE_PS_DMX) + || ((pParams->pseudoSurrMode == AUTO_PS_DMX) && (pMetaData->pseudoSurround==1))) + { /* L' = L + C*clev - (Ls+Rs)*slev + LFE*lflev; + R' = R + C*clev + (Ls+Rs)*slev + LFE*lflev; */ + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, cMixLvl, cMixScale ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, -sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL, -sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, cMixLvl, cMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL, sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale ); + } + else + { /* L' = L + C*clev + Ls*slev + LFE*llev; + R' = R + C*clev + Rs*slev + LFE*llev; */ + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, cMixLvl, cMixScale ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, cMixLvl, cMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL, sMixLvl, sMixScale ); + dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale ); + } + + /* Add additional DMX gain */ + if ( pMetaData->dmxGainIdx2 != 0 ) + { /* Apply DMX gain 2 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx2 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx2 & 0x3F; + + /* 10^(dmx_gain_2/80) */ + dmxGain = FX_DBL2FX_DMX( fLdPow( + FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign*val*(LONG)FL2FXCONST_DBL(0.0125f)), 0, + &dmxScale ) + ); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, dmxGain, dmxScale ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dmxGain, dmxScale ); + } + } +#ifdef PCE_METADATA_ENABLE + else { + FIXP_DMX flev, clev, slevLL, slevLR, slevRL, slevRR; + FIXP_DMX mtrxMixDwnCoef = mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx]; + + if ( (pParams->pseudoSurrMode == FORCE_PS_DMX) + || ((pParams->pseudoSurrMode == AUTO_PS_DMX) && (pMetaData->pseudoSurround==1))) + { /* 3/2 input: L' = (1.707+2*A)^-1 * [L+0.707*C-A*Ls-A*Rs]; + R' = (1.707+2*A)^-1 * [R+0.707*C+A*Ls+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[1][pMetaData->matrixMixdownIdx]; + slevRR = slevRL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLL = slevLR = -slevRL; + } + else { + /* 3/2 input: L' = (1.707+A)^-1 * [L+0.707*C+A*Ls]; + R' = (1.707+A)^-1 * [R+0.707*C+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[0][pMetaData->matrixMixdownIdx]; + slevRR = slevLL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLR = slevRL = (FIXP_SGL)0; + } + /* common factor */ + clev = FX_DBL2FX_DMX(fMult(flev, mpegMixDownIdx2Coef[0] /* 0.707 */)); + + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, flev, 0 ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, clev, 0 ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, slevLL, 0 ); + dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL, slevLR, 0 ); + + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, flev, 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, clev, 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL, slevRL, 0 ); + dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL, slevRR, 0 ); + } +#endif /* PCE_METADATA_ENABLE */ + break; + default: + /* This configuration does not fit to any known downmix equation! */ + err = PCMDMX_INVALID_MODE; + break; + } + /* Mark the output channels */ + FDKmemclear(valid, PCM_DMX_MAX_CHANNELS*sizeof(unsigned int)); + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + /* Update channel mode for the next stage */ + inChMode = CH_MODE_2_0_0_0; + } + + if (numOutChannel == ONE_CHANNEL) { + FIXP_DMX monoMixLevel; + INT monoMixScale; + +#ifdef PCE_METADATA_ENABLE + if ( (pMetaData->typeFlags & TYPE_PCE_DATA) + && !(pMetaData->typeFlags & TYPE_DSE_DATA) ) + { /* C' = (3+2*A)^-1 * [C+L+R+A*Ls+A+Rs]; */ + monoMixLevel = mpegMixDownIdx2PreFact[2][pMetaData->matrixMixdownIdx]; + monoMixScale = 0; + + dmxClearChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL ); + mixFactors[CENTER_FRONT_CHANNEL][CENTER_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][LEFT_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_FRONT_CHANNEL] = monoMixLevel; + monoMixLevel = FX_DBL2FX_DMX(fMult(monoMixLevel, mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx])); + mixFactors[CENTER_FRONT_CHANNEL][LEFT_REAR_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_REAR_CHANNEL] = monoMixLevel; + } + else +#endif + { /* C' = L + R; [default] */ + monoMixLevel = FL2FXCONST_DMX(0.5f); + monoMixScale = 1; + dmxClearChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL ); /* C is not in the mix */ + dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, LEFT_FRONT_CHANNEL, monoMixLevel, monoMixScale ); + dmxAddChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, monoMixLevel, monoMixScale ); + } + + /* Mark the output channel */ + FDKmemclear(valid, PCM_DMX_MAX_CHANNELS*sizeof(unsigned int)); + valid[CENTER_FRONT_CHANNEL] = 1; + } + +#define MAX_SEARCH_START_VAL ( -7 ) + + { + LONG chSum[PCM_DMX_MAX_CHANNELS]; + INT chSumMax = MAX_SEARCH_START_VAL; + + /* Determine the current maximum scale factor */ + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + if (valid[outCh]!=0) { + for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) { + if (mixScales[outCh][inCh] > maxScale) + { /* Store the new maximum */ + maxScale = mixScales[outCh][inCh]; + } + } + } + } + + /* Individualy analyse output chanal levels */ + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + chSum[outCh] = MAX_SEARCH_START_VAL; + if (valid[outCh]!=0) { + int ovrflwProtScale = 0; + + /* Accumulate all factors for each output channel */ + chSum[outCh] = 0; + for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) { + SHORT addFact = FX_DMX2SHRT(mixFactors[outCh][inCh]); + if ( mixScales[outCh][inCh] <= maxScale ) { + addFact >>= maxScale - mixScales[outCh][inCh]; + } else { + addFact <<= mixScales[outCh][inCh] - maxScale; + } + chSum[outCh] += addFact; + } + if (chSum[outCh] > (LONG)MAXVAL_SGL) { + while (chSum[outCh] > (LONG)MAXVAL_SGL) { + ovrflwProtScale += 1; + chSum[outCh] >>= 1; + } + } else if (chSum[outCh] > 0) { + while ((chSum[outCh]<<1) <= (LONG)MAXVAL_SGL) { + ovrflwProtScale -= 1; + chSum[outCh] <<= 1; + } + } + /* Store the differential scaling in the same array */ + chSum[outCh] = ovrflwProtScale; + } + } + + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + if ( (valid[outCh] != 0) + && (chSum[outCh] > chSumMax) ) + { /* Store the new maximum */ + chSumMax = chSum[outCh]; + } + } + maxScale = FDKmax(maxScale+chSumMax, 0); + + /* Normalize all factors */ + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + if (valid[outCh]!=0) { + for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) { + if (mixFactors[outCh][inCh] != (FIXP_DMX)0) { + if ( mixScales[outCh][inCh] <= maxScale ) { + mixFactors[outCh][inCh] >>= maxScale - mixScales[outCh][inCh]; + } else { + mixFactors[outCh][inCh] <<= mixScales[outCh][inCh] - maxScale; + } + mixScales[outCh][inCh] = maxScale; + } + } + } + } + } + + + /* return the scale factor */ + *pOutScale = maxScale; + + return (err); +} + + +/** Open and initialize an instance of the PCM downmix module + * @param [out] Pointer to a buffer receiving the handle of the new instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Open ( + HANDLE_PCM_DOWNMIX *pSelf + ) +{ + HANDLE_PCM_DOWNMIX self; + + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + *pSelf = NULL; + + self = (HANDLE_PCM_DOWNMIX) GetPcmDmxInstance( 0 ); + if (self == NULL) { + return (PCMDMX_OUT_OF_MEMORY); + } + + /* Reset the full instance */ + pcmDmx_Reset( self, PCMDMX_RESET_FULL ); + + *pSelf = self; + + return (PCMDMX_OK); +} + + +/** Reset all static values like e.g. mixdown coefficients. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Flags telling which parts of the module shall be reset. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Reset ( + HANDLE_PCM_DOWNMIX self, + UINT flags + ) +{ + if (self == NULL) { return (PCMDMX_INVALID_HANDLE); } + + if (flags & PCMDMX_RESET_PARAMS) { + PCM_DMX_USER_PARAMS *pParams = &self->userParams; + + pParams->dualChannelMode = STEREO_MODE; + pParams->pseudoSurrMode = NEVER_DO_PS_DMX; + pParams->numOutChannelsMax = PCM_DMX_DFLT_MAX_OUT_CHANNELS; + pParams->numOutChannelsMin = PCM_DMX_DFLT_MIN_OUT_CHANNELS; + pParams->frameDelay = 0; + pParams->expiryFrame = PCM_DMX_DFLT_EXPIRY_FRAME; + + self->applyProcessing = 0; + } + + if (flags & PCMDMX_RESET_BS_DATA) { + int slot; + /* Init all slots with a default set */ + for (slot = 0; slot <= PCM_DMX_MAX_DELAY_FRAMES; slot += 1) { + FDKmemcpy(&self->bsMetaData[slot], &dfltMetaData, sizeof(DMX_BS_META_DATA)); + } + } + + return (PCMDMX_OK); +} + + +/** Set one parameter for one instance of the PCM downmix module. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [in] Parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetParam ( + HANDLE_PCM_DOWNMIX self, + const PCMDMX_PARAM param, + const INT value + ) +{ + switch (param) + { + case DMX_BS_DATA_EXPIRY_FRAME: + if (self == NULL) + return (PCMDMX_INVALID_HANDLE); + self->userParams.expiryFrame = (value > 0) ? (UINT)value : 0; + break; + + case DMX_BS_DATA_DELAY: + if ( (value > PCM_DMX_MAX_DELAY_FRAMES) + || (value < 0) ) { + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + self->userParams.frameDelay = (UCHAR)value; + break; + + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: case 0: case ONE_CHANNEL: case TWO_CHANNEL: +#if (PCM_DMX_MAX_OUT_CHANNELS >= 6) + case SIX_CHANNEL: +#endif +#if (PCM_DMX_MAX_OUT_CHANNELS >= 8) + case EIGHT_CHANNEL: +#endif + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) + return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMin = (value > 0) ? value : -1; + if ( (value > 0) + && (self->userParams.numOutChannelsMax > 0) + && (value > self->userParams.numOutChannelsMax) ) + { /* MIN > MAX would be an invalid state. Thus set MAX = MIN in this case. */ + self->userParams.numOutChannelsMax = self->userParams.numOutChannelsMin; + } + break; + + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: case 0: case ONE_CHANNEL: case TWO_CHANNEL: +#if (PCM_DMX_MAX_OUT_CHANNELS >= 6) + case SIX_CHANNEL: +#endif +#if (PCM_DMX_MAX_OUT_CHANNELS >= 8) + case EIGHT_CHANNEL: +#endif + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) + return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMax = (value > 0) ? value : -1; + if ( (value > 0) + && (value < self->userParams.numOutChannelsMin) ) + { /* MAX < MIN would be an invalid state. Thus set MIN = MAX in this case. */ + self->userParams.numOutChannelsMin = self->userParams.numOutChannelsMax; + } + break; + + case DMX_DUAL_CHANNEL_MODE: + switch ((DUAL_CHANNEL_MODE)value) { + case STEREO_MODE: + case CH1_MODE: + case CH2_MODE: + case MIXED_MODE: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) + return (PCMDMX_INVALID_HANDLE); + self->userParams.dualChannelMode = (DUAL_CHANNEL_MODE)value; + self->applyProcessing = 1; /* Force processing */ + break; + + case DMX_PSEUDO_SURROUND_MODE: + switch ((PSEUDO_SURROUND_MODE)value) { + case NEVER_DO_PS_DMX: + case AUTO_PS_DMX: + case FORCE_PS_DMX: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) + return (PCMDMX_INVALID_HANDLE); + self->userParams.pseudoSurrMode = (PSEUDO_SURROUND_MODE)value; + break; + + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + +/** Get one parameter value of one PCM downmix module instance. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [out] Pointer to buffer receiving the parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_GetParam ( + HANDLE_PCM_DOWNMIX self, + const PCMDMX_PARAM param, + INT * const pValue + ) +{ + PCM_DMX_USER_PARAMS *pUsrParams; + + if ( (self == NULL) + || (pValue == NULL) ) { + return (PCMDMX_INVALID_HANDLE); + } + pUsrParams = &self->userParams; + + switch (param) + { + case DMX_BS_DATA_EXPIRY_FRAME: + *pValue = (INT)pUsrParams->expiryFrame; + break; + case DMX_BS_DATA_DELAY: + *pValue = (INT)pUsrParams->frameDelay; + break; + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMin; + break; + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMax; + break; + case DMX_DUAL_CHANNEL_MODE: + *pValue = (INT)pUsrParams->dualChannelMode; + break; + case DMX_PSEUDO_SURROUND_MODE: + *pValue = (INT)pUsrParams->pseudoSurrMode; + break; + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + + +#ifdef DSE_METADATA_ENABLE + +#define MAX_DSE_ANC_BYTES ( 16 ) /* 15 bytes */ +#define ANC_DATA_SYNC_BYTE ( 0xBC ) /* ancillary data sync byte. */ + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_Parse ( + HANDLE_PCM_DOWNMIX self, + HANDLE_FDK_BITSTREAM hBs, + UINT ancDataBits, + int isMpeg2 + ) +{ + PCMDMX_ERROR errorStatus = PCMDMX_OK; + DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0]; + + int skip4Dmx = 0, skip4Ext = 0; + int dmxLvlAvail = 0, extDataAvail = 0; + int foundNewData = 0; + UINT minAncBits = ((isMpeg2) ? 5 : 3)*8; + + if ( (self == NULL) + || (hBs == NULL) ) { return (PCMDMX_INVALID_HANDLE); } + + ancDataBits = FDKgetValidBits(hBs); + + /* sanity checks */ + if ( (ancDataBits < minAncBits) + || (ancDataBits > FDKgetValidBits(hBs)) ) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + pBsMetaData = &self->bsMetaData[0]; + + if (isMpeg2) { + /* skip DVD ancillary data */ + FDKpushFor(hBs, 16); + } + + /* check sync word */ + if (FDKreadBits(hBs,8) != ANC_DATA_SYNC_BYTE) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + /* skip MPEG audio type and Dolby surround mode */ + FDKpushFor(hBs, 4); + + if (isMpeg2) { + /* int numAncBytes = */ FDKreadBits(hBs, 4); + /* advanced dynamic range control */ + if (FDKreadBit(hBs)) skip4Dmx += 24; + /* dialog normalization */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + /* reproduction_level */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + } else { + FDKpushFor(hBs, 2); /* drc presentation mode */ + pBsMetaData->pseudoSurround = FDKreadBit(hBs); + FDKpushFor(hBs, 4); /* reserved bits */ + } + + /* downmixing levels MPEGx status */ + dmxLvlAvail = FDKreadBit(hBs); + + if (isMpeg2) { + /* scale factor CRC status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + } else { + /* ancillary data extension status */ + extDataAvail = FDKreadBit(hBs); + } + + /* audio coding and compression status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* coarse grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* fine grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + + /* skip the useless data to get to the DMX levels */ + FDKpushFor(hBs, skip4Dmx); + + /* downmix_levels_MPEGX */ + if (dmxLvlAvail) + { + if (FDKreadBit(hBs)) { /* center_mix_level_on */ + pBsMetaData->cLevIdx = FDKreadBits(hBs, 3); + foundNewData = 1; + } else { + FDKreadBits(hBs, 3); + } + if (FDKreadBit(hBs)) { /* surround_mix_level_on */ + pBsMetaData->sLevIdx = FDKreadBits(hBs, 3); + foundNewData = 1; + } else { + FDKreadBits(hBs, 3); + } + } + + /* skip the useless data to get to the ancillary data extension */ + FDKpushFor(hBs, skip4Ext); + + /* anc data extension (MPEG-4 only) */ + if (extDataAvail) { + int extDmxLvlSt, extDmxGainSt, extDmxLfeSt; + + FDKreadBit(hBs); /* reserved bit */ + extDmxLvlSt = FDKreadBit(hBs); + extDmxGainSt = FDKreadBit(hBs); + extDmxLfeSt = FDKreadBit(hBs); + FDKreadBits(hBs, 4); /* reserved bits */ + + if (extDmxLvlSt) { + pBsMetaData->dmixIdxA = FDKreadBits(hBs, 3); + pBsMetaData->dmixIdxB = FDKreadBits(hBs, 3); + FDKreadBits(hBs, 2); /* reserved bits */ + foundNewData = 1; + } + if (extDmxGainSt) { + pBsMetaData->dmxGainIdx5 = FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + pBsMetaData->dmxGainIdx2 = FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + foundNewData = 1; + } + if (extDmxLfeSt) { + pBsMetaData->dmixIdxLfe = FDKreadBits(hBs, 4); + FDKreadBits(hBs, 4); /* reserved bits */ + foundNewData = 1; + } + } + + /* final sanity check on the amount of read data */ + if ((INT)FDKgetValidBits(hBs) < 0) { + errorStatus = PCMDMX_CORRUPT_ANC_DATA; + } + + if ( (errorStatus == PCMDMX_OK) + && (foundNewData == 1) ) { + /* announce new data */ + pBsMetaData->typeFlags |= TYPE_DSE_DATA; + /* reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + + return (errorStatus); +} + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_ReadDvbAncData ( + HANDLE_PCM_DOWNMIX self, + UCHAR *pAncDataBuf, + UINT ancDataBytes, + int isMpeg2 + ) +{ + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + PCMDMX_ERROR errorStatus = PCMDMX_OK; + + if (self == NULL) { return (PCMDMX_INVALID_HANDLE); } + + /* sanity checks */ + if ( (pAncDataBuf == NULL) + || (ancDataBytes == 0) ) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + FDKinitBitStream (hBs, pAncDataBuf, MAX_DSE_ANC_BYTES, ancDataBytes*8, BS_READER); + + errorStatus = pcmDmx_Parse ( + self, + hBs, + ancDataBytes*8, + isMpeg2 ); + + return (errorStatus); +} +#endif /* DSE_METADATA_ENABLE */ + +#ifdef PCE_METADATA_ENABLE +/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream. + * Note: Call only if matrix_mixdown_idx_present is true. + * @param [in] Handle of PCM downmix module instance. + * @param [in] The 2 bit matrix mixdown index extracted from PCE. + * @param [in] The pseudo surround enable flag extracted from PCE. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce ( + HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable + ) +{ + DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0]; + + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + if (matrixMixdownPresent) { + pBsMetaData->pseudoSurround = pseudoSurroundEnable; + pBsMetaData->matrixMixdownIdx = matrixMixdownIdx & 0x03; + pBsMetaData->typeFlags |= TYPE_PCE_DATA; + /* Reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + + return (PCMDMX_OK); +} +#endif /* PCE_METADATA_ENABLE */ + + +/** Apply down or up mixing. + * @param [in] Handle of PCM downmix module instance. + * @param [inout] Pointer to buffer that hold the time domain signal. + * @param [in] Pointer where the amount of output samples is returned into. + * @param [inout] Pointer where the amount of output channels is returned into. + * @param [in] Flag which indicates if output time data are writtern interleaved or as subsequent blocks. + * @param [inout] Array where the corresponding channel type for each output audio channel is stored into. + * @param [inout] Array where the corresponding channel type index for each output audio channel is stored into. + * @param [in] Array containing the out channel mapping to be used (From MPEG PCE ordering to whatever is required). + * @param [out] Pointer on a field receiving the scale factor that has to be applied on all samples afterwards. + * If the handed pointer is NULL scaling is done internally. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame ( + HANDLE_PCM_DOWNMIX self, + INT_PCM *pPcmBuf, + UINT frameSize, + INT *nChannels, + int fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const UCHAR channelMapping[][8], + INT *pDmxOutScale + ) +{ + PCM_DMX_USER_PARAMS *pParam = NULL; + PCMDMX_ERROR errorStatus = PCMDMX_OK; + DUAL_CHANNEL_MODE dualChannelMode; + PCM_DMX_CHANNEL_MODE inChMode; + PCM_DMX_CHANNEL_MODE outChMode; + INT devNull; /* Just a dummy to avoid a lot of branches in the code */ + int numOutChannels, numInChannels; + int inStride, outStride, offset; + int dmxMaxScale, dmxScale; + int ch, slot; + UCHAR inOffsetTable[PCM_DMX_MAX_CHANNELS]; + + DMX_BS_META_DATA bsMetaData; + + if ( (self == NULL) + || (nChannels == NULL) + || (channelType == NULL) + || (channelIndices == NULL) + || (channelMapping == NULL) ) { + return (PCMDMX_INVALID_HANDLE); + } + + /* Init the output scaling */ + dmxScale = 0; + if (pDmxOutScale != NULL) { + /* Avoid final scaling internally and hand it to the outside world. */ + *pDmxOutScale = 0; + dmxMaxScale = PCMDMX_MAX_HEADROOM; + } else { + /* Apply the scaling internally. */ + pDmxOutScale = &devNull; /* redirect to temporal stack memory */ + dmxMaxScale = 0; + } + + pParam = &self->userParams; + numInChannels = *nChannels; + + /* Perform some input sanity checks */ + if (pPcmBuf == NULL) { return (PCMDMX_INVALID_ARGUMENT); } + if (frameSize == 0) { return (PCMDMX_INVALID_ARGUMENT); } + if ( (numInChannels == 0) + || (numInChannels > PCM_DMX_MAX_IN_CHANNELS) ) + { return (PCMDMX_INVALID_ARGUMENT); } + + /* Check on misconfiguration */ + FDK_ASSERT( (pParam->numOutChannelsMax <= 0) \ + || (pParam->numOutChannelsMax >= pParam->numOutChannelsMin)); + + /* Determine if the module has to do processing */ + if ( (self->applyProcessing == 0) + && ((pParam->numOutChannelsMax <= 0) + || (pParam->numOutChannelsMax >= numInChannels)) + && (pParam->numOutChannelsMin <= numInChannels) ) { + /* Nothing to do */ + return (errorStatus); + } + + /* Determine the number of output channels */ + if ( (pParam->numOutChannelsMax > 0) + && (numInChannels > pParam->numOutChannelsMax) ) { + numOutChannels = pParam->numOutChannelsMax; + } + else if (numInChannels < pParam->numOutChannelsMin) { + numOutChannels = pParam->numOutChannelsMin; + } + else { + numOutChannels = numInChannels; + } + + dualChannelMode = pParam->dualChannelMode; + + /* Analyse input channel configuration and get channel offset + * table that can be accessed with the fixed channel labels. */ + errorStatus = getChannelMode( + numInChannels, + channelType, + channelIndices, + inOffsetTable, + &inChMode + ); + if ( PCMDMX_IS_FATAL_ERROR(errorStatus) + || (inChMode == CH_MODE_UNDEFINED) ) { + /* We don't need to restore because the channel + configuration has not been changed. Just exit. */ + return (PCMDMX_INVALID_CH_CONFIG); + } + + /* Set input stride and offset */ + if (fInterleaved) { + inStride = numInChannels; + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Reset downmix meta data if necessary */ + if ( (pParam->expiryFrame > 0) + && (++self->bsMetaData[0].expiryCount > pParam->expiryFrame) ) + { /* The metadata read from bitstream is too old. */ + PCMDMX_ERROR err = pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA); + FDK_ASSERT(err == PCMDMX_OK); + } + FDKmemcpy(&bsMetaData, &self->bsMetaData[pParam->frameDelay], sizeof(DMX_BS_META_DATA)); + /* Maintain delay line */ + for (slot = pParam->frameDelay; slot > 0; slot -= 1) { + FDKmemcpy(&self->bsMetaData[slot], &self->bsMetaData[slot-1], sizeof(DMX_BS_META_DATA)); + } + + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#ifdef PCM_DOWNMIX_ENABLE + if ( numInChannels > numOutChannels ) + { /* Apply downmix */ + INT_PCM *pInPcm[PCM_DMX_MAX_IN_CHANNELS] = { NULL }; + INT_PCM *pOutPcm[PCM_DMX_MAX_OUT_CHANNELS] = { NULL }; + FIXP_DMX mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS]; + UCHAR outOffsetTable[PCM_DMX_MAX_CHANNELS]; + UINT sample; + int chCfg = 0; + int bypScale = 0; + +#if (PCM_DMX_MAX_IN_CHANNELS >= 7) + if (numInChannels > SIX_CHANNEL) { + AUDIO_CHANNEL_TYPE multiPurposeChType[2]; + + /* Get the type of the multipurpose channels */ + multiPurposeChType[0] = channelType[inOffsetTable[LEFT_MULTIPRPS_CHANNEL]]; + multiPurposeChType[1] = channelType[inOffsetTable[RIGHT_MULTIPRPS_CHANNEL]]; + + /* Check if the input configuration is one defined in the standard. */ + switch (inChMode) { + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + /* Further analyse the input config to distinguish the two CH_MODE_5_0_2_1 configs. */ + if ( (multiPurposeChType[0] == ACT_FRONT_TOP) + && (multiPurposeChType[1] == ACT_FRONT_TOP) ) { + chCfg = 14; + } else { + chCfg = 7; + } + break; + case CH_MODE_3_0_3_1: /* chCfg 11 */ + chCfg = 11; + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + chCfg = 12; + break; + default: + chCfg = 0; /* Not a known config */ + break; + } + } +#endif + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + + /* Get channel description and channel mapping for the desired output configuration. */ + getChannelDescription( + outChMode, + channelMapping, + channelType, + channelIndices, + outOffsetTable + ); + /* Now there is no way back because we modified the channel configuration! */ + + /* Create the DMX matrix */ + errorStatus = getMixFactors ( + (chCfg>0) ? 1 : 0, + (chCfg>0) ? (PCM_DMX_CHANNEL_MODE)chCfg : inChMode, + outChMode, + pParam, + &bsMetaData, + mixFactors, + &dmxScale + ); + /* No fatal errors can occur here. The function is designed to always return a valid matrix. + The error code is used to signal configurations and matrices that are not conform to any standard. */ + + /* Determine the final scaling */ + bypScale = FDKmin(dmxMaxScale, dmxScale); + *pDmxOutScale += bypScale; + dmxScale -= bypScale; + + { /* Set channel pointer for input. Remove empty cols. */ + int inCh, outCh, map[PCM_DMX_MAX_CHANNELS]; + ch = 0; + for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) { + if (inOffsetTable[inCh] != 255) { + pInPcm[ch] = &pPcmBuf[inOffsetTable[inCh]*offset]; + map[ch++] = inCh; + } + } + if (ch != numInChannels) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Remove unused cols from factor matrix */ + for (inCh=0; inCh < numInChannels; inCh+=1) { + if (inCh != map[inCh]) { + int outCh; + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + mixFactors[outCh][inCh] = mixFactors[outCh][map[inCh]]; + } + } + } + + /* Set channel pointer for output. Remove empty cols. */ + ch = 0; + for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) { + if (outOffsetTable[outCh] != 255) { + pOutPcm[ch] = &pPcmBuf[outOffsetTable[outCh]*offset]; + map[ch++] = outCh; + } + } + FDK_ASSERT(ch == numOutChannels); + + /* Remove unused rows from factor matrix */ + for (outCh=0; outCh < numOutChannels; outCh+=1) { + if (outCh != map[outCh]) { + FDKmemcpy(&mixFactors[outCh], &mixFactors[map[outCh]], PCM_DMX_MAX_CHANNELS*sizeof(FIXP_DMX)); + } + } + } + + /* Sample processing loop */ + for (sample = 0; sample < frameSize; sample++) + { + FIXP_PCM tIn[PCM_DMX_MAX_IN_CHANNELS]; + FIXP_DBL tOut[PCM_DMX_MAX_OUT_CHANNELS] = { (FIXP_DBL)0 }; + int inCh, outCh; + + /* Preload all input samples */ + for (inCh=0; inCh < numInChannels; inCh+=1) { + tIn[inCh] = (FIXP_PCM)*pInPcm[inCh]; + pInPcm[inCh] += inStride; + } + /* Apply downmix coefficients to input samples and accumulate for output */ + for (outCh=0; outCh < numOutChannels; outCh+=1) { + for (inCh=0; inCh < numInChannels; inCh+=1) { + tOut[outCh] += fMult(tIn[inCh], mixFactors[outCh][inCh]); + } + /* Write sample */ +#if (SAMPLE_BITS == DFRACT_BITS) + *pOutPcm[outCh] = (INT_PCM)SATURATE_LEFT_SHIFT(tOut[outCh], dmxScale, SAMPLE_BITS); +#else + *pOutPcm[outCh] = (INT_PCM)SATURATE_RIGHT_SHIFT(tOut[outCh], DFRACT_BITS-SAMPLE_BITS-dmxScale, SAMPLE_BITS); +#endif + pOutPcm[outCh] += outStride; + } + } + + /* Update the number of output channels */ + *nChannels = numOutChannels; + + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + else +#endif /* PCM_DOWNMIX_ENABLE */ +#ifdef PCM_CHANNEL_EXTENSION_ENABLE + if ( numInChannels < numOutChannels ) + { /* Apply rudimentary upmix */ + /* Set up channel pointer */ + UINT sample; + UCHAR outOffsetTable[PCM_DMX_MAX_CHANNELS]; + + /* FIRST STAGE + Create a stereo/dual channel signal */ + if (numInChannels == ONE_CHANNEL) + { + INT_PCM *pInPcm[PCM_DMX_MAX_CHANNELS]; + INT_PCM *pOutLF, *pOutRF; + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? TWO_CHANNEL : 1; + outChMode = outChModeTable[TWO_CHANNEL]; + + /* Get channel description and channel mapping for this + * stages number of output channels (always STEREO). */ + getChannelDescription( + outChMode, + channelMapping, + channelType, + channelIndices, + outOffsetTable + ); + /* Now there is no way back because we modified the channel configuration! */ + + /* Set input channel pointer. The first channel is always at index 0. */ + pInPcm[CENTER_FRONT_CHANNEL] = &pPcmBuf[(frameSize-1)*inStride]; /* Considering input mapping could lead to a invalid pointer + here if the channel is not declared to be a front channel. */ + + /* Set output channel pointer (for this stage). */ + pOutLF = &pPcmBuf[outOffsetTable[LEFT_FRONT_CHANNEL]*offset+(frameSize-1)*outStride]; + pOutRF = &pPcmBuf[outOffsetTable[RIGHT_FRONT_CHANNEL]*offset+(frameSize-1)*outStride]; + + /* 1/0 input: */ + for (sample = 0; sample < frameSize; sample++) { + /* L' = C; R' = C; */ + *pOutLF = *pOutRF = *pInPcm[CENTER_FRONT_CHANNEL]; + + pInPcm[CENTER_FRONT_CHANNEL] -= inStride; + pOutLF -= outStride; pOutRF -= outStride; + } + + /* Prepare for next stage: */ + inStride = outStride; + inChMode = outChMode; + FDKmemcpy(inOffsetTable, outOffsetTable, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + } + +#if (PCM_DMX_MAX_OUT_CHANNELS > 2) + /* SECOND STAGE + Extend with zero channels to achieved the desired number of output channels. */ + if (numOutChannels > TWO_CHANNEL) + { + INT_PCM *pIn[PCM_DMX_MAX_CHANNELS] = { NULL }; + INT_PCM *pOut[PCM_DMX_MAX_CHANNELS] = { NULL }; + AUDIO_CHANNEL_TYPE inChTypes[PCM_DMX_MAX_CHANNELS]; + UCHAR inChIndices[PCM_DMX_MAX_CHANNELS]; + UCHAR numChPerGrp[2][PCM_DMX_MAX_CHANNEL_GROUPS]; + int nContentCh = 0; /* Number of channels with content */ + int nEmptyCh = 0; /* Number of channels with content */ + int ch, chGrp, isCompatible = 1; + + /* Do not change the signalling which is the channel types and indices. + Just reorder and add channels. So first save the input signalling. */ + FDKmemcpy(inChTypes, channelType, PCM_DMX_MAX_CHANNELS*sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemcpy(inChIndices, channelIndices, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + + /* Check if input channel config can be easily mapped to the desired output config. */ + for (chGrp = 0; chGrp < PCM_DMX_MAX_CHANNEL_GROUPS; chGrp += 1) { + numChPerGrp[IN][chGrp] = (inChMode >> (chGrp*4)) & 0xF; + numChPerGrp[OUT][chGrp] = (outChMode >> (chGrp*4)) & 0xF; + + if (numChPerGrp[IN][chGrp] > numChPerGrp[OUT][chGrp]) { + isCompatible = 0; + break; + } + } + + if ( isCompatible ) { + /* Get new channel description and channel + * mapping for the desired output channel mode. */ + getChannelDescription( + outChMode, + channelMapping, + channelType, + channelIndices, + outOffsetTable + ); + /* If the input config has a back center channel but the output + config has not, copy it to left and right (if available). */ + if ( (numChPerGrp[IN][CH_GROUP_REAR]%2) + && !(numChPerGrp[OUT][CH_GROUP_REAR]%2) ) { + if (numChPerGrp[IN][CH_GROUP_REAR] == 1) { + inOffsetTable[RIGHT_REAR_CHANNEL] = inOffsetTable[LEFT_REAR_CHANNEL]; + } else if (numChPerGrp[IN][CH_GROUP_REAR] == 3) { + inOffsetTable[RIGHT_MULTIPRPS_CHANNEL] = inOffsetTable[LEFT_MULTIPRPS_CHANNEL]; + } + } + } + else { + /* Just copy and extend the original config */ + FDKmemcpy(outOffsetTable, inOffsetTable, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR)); + } + + /* Set I/O channel pointer. + Note: The following assignment algorithm clears the channel offset tables. + Thus they can not be used afterwards. */ + for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) { + if ( (outOffsetTable[ch] < 255) + && (inOffsetTable[ch] < 255) ) + { /* Set I/O pointer: */ + pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch]*offset+(frameSize-1)*inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[ch]*offset+(frameSize-1)*outStride]; + /* Update signalling */ + channelType[outOffsetTable[ch]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[ch]] = inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[ch] = 255; + nContentCh += 1; + } + } + if ( isCompatible ) { + /* Assign the remaining input channels. + This is just a safety appliance. We should never need it. */ + for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) { + if (inOffsetTable[ch] < 255) { + int outCh; + for (outCh = 0 ; outCh < PCM_DMX_MAX_CHANNELS; outCh += 1) { + if (outOffsetTable[outCh] < 255) { + break; + } + } + /* Set I/O pointer: */ + pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch]*offset+(frameSize-1)*inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[outCh]*offset+(frameSize-1)*outStride]; + /* Update signalling */ + channelType[outOffsetTable[outCh]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[outCh]] = inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[outCh] = 255; + nContentCh += 1; + } + } + /* Set the remaining output channel pointer */ + for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) { + if (outOffsetTable[ch] < 255) { + pOut[nContentCh+nEmptyCh] = &pPcmBuf[outOffsetTable[ch]*offset+(frameSize-1)*outStride]; + /* Expand output signalling */ + channelType[outOffsetTable[ch]] = ACT_NONE; + channelIndices[outOffsetTable[ch]] = nEmptyCh; + outOffsetTable[ch] = 255; + nEmptyCh += 1; + } + } + } + else { + /* Set the remaining output channel pointer */ + for (ch = nContentCh; ch < numOutChannels; ch+=1) { + pOut[ch] = &pPcmBuf[ch*offset+(frameSize-1)*outStride]; + /* Expand output signalling */ + channelType[ch] = ACT_NONE; + channelIndices[ch] = nEmptyCh; + nEmptyCh += 1; + } + } + + /* First copy the channels that have signal */ + for (sample = 0; sample < frameSize; sample+=1) { + INT_PCM tIn[PCM_DMX_MAX_CHANNELS]; + /* Read all channel samples */ + for (ch = 0; ch < nContentCh; ch+=1) { + tIn[ch] = *pIn[ch]; + pIn[ch] -= inStride; + } + /* Write all channel samples */ + for (ch = 0; ch < nContentCh; ch+=1) { + *pOut[ch] = tIn[ch]; + pOut[ch] -= outStride; + } + } + + /* Clear all the other channels */ + for (sample = 0; sample < frameSize; sample++) { + for (ch = nContentCh; ch < numOutChannels; ch+=1) { + *pOut[ch] = (INT_PCM)0; + pOut[ch] -= outStride; + } + } + } +#endif /* if (PCM_DMX_MAX_OUT_CHANNELS > 2) */ + + /* update the number of output channels */ + *nChannels = numOutChannels; + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + else +#endif /* PCM_CHANNEL_EXTENSION_ENABLE */ + if ( numInChannels == numOutChannels ) + { + /* Don't need to change the channel description here */ + + switch (numInChannels) + { + case 2: + { /* Set up channel pointer */ + INT_PCM *pInPcm[PCM_DMX_MAX_CHANNELS]; + INT_PCM *pOutL, *pOutR; + FIXP_DMX flev; + + UINT sample; + int inStride, outStride, offset; + + if (fInterleaved) { + inStride = numInChannels; + outStride = 2; /* fixed !!! (below stereo is donwmixed to mono if required */ + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + outStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Set input channel pointer */ + pInPcm[LEFT_FRONT_CHANNEL] = &pPcmBuf[inOffsetTable[LEFT_FRONT_CHANNEL]*offset]; + pInPcm[RIGHT_FRONT_CHANNEL] = &pPcmBuf[inOffsetTable[RIGHT_FRONT_CHANNEL]*offset]; + + /* Set output channel pointer (same as input) */ + pOutL = pInPcm[LEFT_FRONT_CHANNEL]; + pOutR = pInPcm[RIGHT_FRONT_CHANNEL]; + + /* Set downmix levels: */ + flev = FL2FXCONST_DMX(0.70710678f); + /* 2/0 input: */ + switch (dualChannelMode) + { + case CH1_MODE: /* L' = 0.707 * Ch1; R' = 0.707 * Ch1 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = + (INT_PCM)SATURATE_RIGHT_SHIFT(fMult((FIXP_PCM)*pInPcm[LEFT_FRONT_CHANNEL], flev), DFRACT_BITS-SAMPLE_BITS, SAMPLE_BITS); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; + pOutL += outStride; pOutR += outStride; + } + break; + case CH2_MODE: /* L' = 0.707 * Ch2; R' = 0.707 * Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = + (INT_PCM)SATURATE_RIGHT_SHIFT(fMult((FIXP_PCM)*pInPcm[RIGHT_FRONT_CHANNEL], flev), DFRACT_BITS-SAMPLE_BITS, SAMPLE_BITS); + + pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; pOutR += outStride; + } + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; R' = 0.5*Ch1 + 0.5*Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (*pInPcm[LEFT_FRONT_CHANNEL] >> 1) + (*pInPcm[RIGHT_FRONT_CHANNEL] >> 1); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; pOutR += outStride; + } + break; + default: + case STEREO_MODE: + /* nothing to do */ + break; + } + } + break; + + default: + /* nothing to do */ + break; + } + } + + return (errorStatus); +} + + +/** Close an instance of the PCM downmix module. + * @param [inout] Pointer to a buffer containing the handle of the instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Close ( + HANDLE_PCM_DOWNMIX *pSelf + ) +{ + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + FreePcmDmxInstance( pSelf ); + *pSelf = NULL; + + return (PCMDMX_OK); +} + + +/** Get library info for this module. + * @param [out] Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return PCMDMX_UNKNOWN; + } + + /* Add the library info */ + info[i].module_id = FDK_PCMDMX; + info[i].version = LIB_VERSION(PCMDMX_LIB_VL0, PCMDMX_LIB_VL1, PCMDMX_LIB_VL2); + LIB_VERSION_STRING(info+i); + info[i].build_date = PCMDMX_LIB_BUILD_DATE; + info[i].build_time = PCMDMX_LIB_BUILD_TIME; + info[i].title = PCMDMX_LIB_TITLE; + + /* Set flags */ + info[i].flags = 0 +#ifdef PCM_DOWNMIX_ENABLE + | CAPF_DMX_BLIND /* At least blind downmixing is possible */ + #ifdef PCE_METADATA_ENABLE + | CAPF_DMX_PCE /* Guided downmix with data from MPEG-2/4 Program Config Elements (PCE). */ + #ifdef ARIB_MIXDOWN_ENABLE + | CAPF_DMX_ARIB /* PCE guided downmix with slightly different equations and levels. */ + #endif + #endif /* PCE_METADATA_ENABLE */ + #ifdef DSE_METADATA_ENABLE + | CAPF_DMX_DVB /* Guided downmix with data from DVB ancillary data fields. */ + #endif +#endif /* PCM_DOWNMIX_ENABLE */ +#ifdef PCM_CHANNEL_EXTENSION_ENABLE + | CAPF_DMX_CH_EXP /* Simple upmixing by dublicating channels or adding zero channels. */ +#endif + ; + + /* Add lib info for FDK tools (if not yet done). */ + FDK_toolsGetLibInfo(info); + + return PCMDMX_OK; +} + + + diff --git a/libSBRdec/include/sbrdecoder.h b/libSBRdec/include/sbrdecoder.h new file mode 100644 index 00000000..3bb9ba32 --- /dev/null +++ b/libSBRdec/include/sbrdecoder.h @@ -0,0 +1,347 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************ Fraunhofer IIS SBR decoder library ****************** + + Author(s): + Description: SBR decoder front-end prototypes and definitions. + +******************************************************************************/ + +#ifndef __SBRDECODER_H +#define __SBRDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" +#include "FDK_audio.h" + + +#define SBR_DEBUG_EXTHLP "\ +--- SBR ---\n\ + 0x00000010 Ancillary data and SBR-Header\n\ + 0x00000020 SBR-Side info\n\ + 0x00000040 Decoded SBR-bitstream data, e.g. envelope data\n\ + 0x00000080 SBR-Bitstream statistics\n\ + 0x00000100 Miscellaneous SBR-messages\n\ + 0x00000200 SBR-Energies and gains in the adjustor\n\ + 0x00000400 Fatal SBR errors\n\ + 0x00000800 Transposer coefficients for inverse filtering\n\ +" + +/* Capability flags */ +#define CAPF_SBR_LP 0x00000001 /*!< Flag indicating library's capability of Low Power mode. */ +#define CAPF_SBR_HQ 0x00000002 /*!< Flag indicating library's capability of High Quality mode. */ +#define CAPF_SBR_DRM_BS 0x00000004 /*!< Flag indicating library's capability to decode DRM SBR data. */ +#define CAPF_SBR_CONCEALMENT 0x00000008 /*!< Flag indicating library's capability to conceal erroneous frames. */ +#define CAPF_SBR_DRC 0x00000010 /*!< Flag indicating library's capability for Dynamic Range Control. */ +#define CAPF_SBR_PS_MPEG 0x00000020 /*!< Flag indicating library's capability to do MPEG Parametric Stereo. */ +#define CAPF_SBR_PS_DRM 0x00000040 /*!< Flag indicating library's capability to do DRM Parametric Stereo. */ + +typedef enum +{ + SBRDEC_OK = 0, /*!< All fine. */ + /* SBRDEC_CONCEAL, */ + /* SBRDEC_NOSYNCH, */ + /* SBRDEC_ILLEGAL_PROGRAM, */ + /* SBRDEC_ILLEGAL_TAG, */ + /* SBRDEC_ILLEGAL_CHN_CONFIG, */ + /* SBRDEC_ILLEGAL_SECTION, */ + /* SBRDEC_ILLEGAL_SCFACTORS, */ + /* SBRDEC_ILLEGAL_PULSE_DATA, */ + /* SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED, */ + /* SBRDEC_GC_NOT_IMPLEMENTED, */ + /* SBRDEC_ILLEGAL_PLUS_ELE_ID, */ + SBRDEC_CREATE_ERROR, /*!< */ + SBRDEC_NOT_INITIALIZED, /*!< */ + SBRDEC_MEM_ALLOC_FAILED, /*!< Memory allocation failed. Probably not enough memory available. */ + SBRDEC_PARSE_ERROR, /*!< */ + SBRDEC_UNSUPPORTED_CONFIG, /*!< */ + SBRDEC_SET_PARAM_FAIL /*!< */ +} SBR_ERROR; + +typedef enum +{ + SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR bitstream delay of one frame. */ + SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ + SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for ELD streams only. */ + SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next process call. */ + SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, ...). */ + SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ +} SBRDEC_PARAM; + +typedef struct SBR_DECODER_INSTANCE *HANDLE_SBRDECODER; + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** + * \brief Allocates and initializes one SBR decoder instance. + * \param pSelf Pointer to where a SBR decoder handle is copied into. + * \return Error code. + */ +SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER *pSelf ); + +/** + * \brief Initialize a SBR decoder runtime instance. Must be called before decoding starts. + * + * \param self Handle to a SBR decoder instance. + * \param sampleRateIn Input samplerate of the SBR decoder instance. + * \param sampleRateOut Output samplerate of the SBR decoder instance. + * \param samplesPerFrame Number of samples per frames. + * \param coreCodec Audio Object Type (AOT) of the core codec. + * \param elementID Table with MPEG-4 element Ids in canonical order. + * \param forceReset Flag that enforces a complete decoder reset. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_InitElement ( + HANDLE_SBRDECODER self, + const int sampleRateIn, + const int sampleRateOut, + const int samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const int elementIndex + ); + +/** + * \brief pass out of band SBR header to SBR decoder + * + * \param self Handle to a SBR decoder instance. + * \param hBs bit stream handle data source. + * \param elementID SBR element ID. + * \param elementIndex SBR element index. + * + * \return Error code. + */ +INT sbrDecoder_Header ( + HANDLE_SBRDECODER self, + HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, + const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex + ); + +/** + * \brief Set a parameter of the SBR decoder runtime instance. + * \param self SBR decoder handle. + * \param param Parameter which will be set if successfull. + * \param value New parameter value. + * \return Error code. + */ +SBR_ERROR sbrDecoder_SetParam ( HANDLE_SBRDECODER self, + const SBRDEC_PARAM param, + const INT value ); + +/** + * \brief Feed DRC channel data into a SBR decoder runtime instance. + * + * \param self SBR decoder handle. + * \param ch Channel number to which the DRC data is associated to. + * \param numBands Number of DRC bands. + * \param pNextFact_mag Pointer to a table with the DRC factor magnitudes. + * \param nextFact_exp Exponent for all DRC factors. + * \param drcInterpolationScheme DRC interpolation scheme. + * \param winSequence Window sequence from core coder (eight short or one long window). + * \param pBandTop Pointer to a table with the top borders for all DRC bands. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, + INT ch, + UINT numBands, + FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, + USHORT *pBandTop ); + +/** + * \brief Disable SBR DRC for a certain channel. + * + * \param hSbrDecoder SBR decoder handle. + * \param ch Number of the channel that has to be disabled. + * + * \return None. + */ +void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self, + INT ch ); + + +/** + * \brief Parse one SBR element data extension data block. The bit stream position will + * be placed at the end of the SBR payload block. The remaining bits will be returned + * into *count if a payload length is given (byPayLen > 0). If no SBR payload length is + * given (bsPayLen < 0) then the bit stream position on return will be random after this + * function call in case of errors, and any further decoding will be completely pointless. + * This function accepts either normal ordered SBR data or reverse ordered DRM SBR data. + * + * \param self SBR decoder handle. + * \param hBs Bit stream handle as data source. + * \param count Pointer to an integer where the amount of parsed SBR payload bits is stored into. + * \param bsPayLen If > 0 this value is the SBR payload length. If < 0, the SBR payload length is unknown. + * \param flags CRC flag (0: EXT_SBR_DATA; 1: EXT_SBR_DATA_CRC) + * \param prev_element Previous MPEG-4 element ID. + * \param element_index Index of the current element. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Parse ( + HANDLE_SBRDECODER self, + HANDLE_FDK_BITSTREAM hBs, + int *count, + int bsPayLen, + int crcFlag, + MP4_ELEMENT_ID prev_element, + int element_index, + int fGlobalIndependencyFlag + ); + +/** + * \brief This function decodes the given SBR bitstreams and applies SBR to the given time data. + * + * SBR-processing works InPlace. I.e. the calling function has to provide + * a time domain buffer timeData which can hold the completely decoded + * result. + * + * Left and right channel are read and stored according to the + * interleaving flag, frame length and number of channels. + * + * \param self Handle of an open SBR decoder instance. + * \param hSbrBs SBR Bitstream handle. + * \param timeData Pointer to input and finally upsampled output data. + * \param numChannels Pointer to a buffer holding the number of channels in time data buffer. + * \param sampleRate Output samplerate. + * \param channelMapping Channel mapping indices. + * \param interleaved Flag indicating if time data is stored interleaved (1: Interleaved time data, 0: non-interleaved timedata). + * \param coreDecodedOk Flag indicating if the core decoder did not find any error (0: core decoder found errors, 1: no errors). + * \param psDecoded Pointer to a buffer holding a flag. Input: PS is possible, Output: PS has been rendered. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, + INT_PCM *timeData, + int *numChannels, + int *sampleRate, + const UCHAR channelMapping[(8)], + const int interleaved, + const int coreDecodedOk, + UCHAR *psDecoded ); + + +/** + * \brief Close SBR decoder instance and free memory. + * \param self SBR decoder handle. + * \return Error Code. + */ +SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *self ); + + +/** + * \brief Get SBR decoder library information. + * \param info Pointer to a LIB_INFO struct, where library information is written to. + * \return 0 on success, -1 if invalid handle or if no free element is available to write information to. + */ +INT sbrDecoder_GetLibInfo( LIB_INFO *info ); + +/** + * \brief Determine the modules output signal delay in samples. + * \param self SBR decoder handle. + * \return The number of samples signal delay added by the module. + */ +UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libSBRdec/src/arm/env_calc_arm.cpp b/libSBRdec/src/arm/env_calc_arm.cpp new file mode 100644 index 00000000..12b17d87 --- /dev/null +++ b/libSBRdec/src/arm/env_calc_arm.cpp @@ -0,0 +1,148 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** Fraunhofer IIS *************************** + + Author(s): Arthur Tritthart + Description: (ARM optimised) SBR domain coding + +******************************************************************************/ +#ifndef INCLUSION_GUARD_CALC_ENV_ARM +#define INCLUSION_GUARD_CALC_ENV_ARM + + +/*! + \brief Compute maximal value of a complex array (re/im) of a given width + Negative values are temporarily logically or'ed with 0xFFFFFFFF + instead of negating the value, if the sign bit is set. + \param maxVal Preset maximal value + \param reTmp real input signal + \param imTmp imaginary input signal + \return new maximal value +*/ + +#ifdef FUNCTION_FDK_get_maxval +__asm FIXP_DBL FDK_get_maxval (FIXP_DBL maxVal, FIXP_DBL *reTmp, FIXP_DBL *imTmp, int width ) +{ + + /* Register map: + r0 maxVal + r1 reTmp + r2 imTmp + r3 width + r4 real + r5 imag + */ + PUSH {r4-r5} + + MOVS r3, r3, ASR #1 + ADC r3, r3, #0 + BCS FDK_get_maxval_loop_2nd_part + BEQ FDK_get_maxval_loop_end + +FDK_get_maxval_loop + LDR r4, [r1], #4 + LDR r5, [r2], #4 + EOR r4, r4, r4, ASR #31 + EOR r5, r5, r5, ASR #31 + ORR r0, r0, r4 + ORR r0, r0, r5 + +FDK_get_maxval_loop_2nd_part + LDR r4, [r1], #4 + LDR r5, [r2], #4 + EOR r4, r4, r4, ASR #31 + EOR r5, r5, r5, ASR #31 + ORR r0, r0, r4 + ORR r0, r0, r5 + + SUBS r3, r3, #1 + BNE FDK_get_maxval_loop + +FDK_get_maxval_loop_end + POP {r4-r5} + BX lr +} +#endif /* FUNCTION_FDK_get_maxval */ + +#endif /* INCLUSION_GUARD_CALC_ENV_ARM */ diff --git a/libSBRdec/src/arm/lpp_tran_arm.cpp b/libSBRdec/src/arm/lpp_tran_arm.cpp new file mode 100644 index 00000000..028a26f7 --- /dev/null +++ b/libSBRdec/src/arm/lpp_tran_arm.cpp @@ -0,0 +1,154 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** Fraunhofer IIS *************************** + + Author(s): Arthur Tritthart + Description: (ARM optimised) LPP transposer subroutines + +******************************************************************************/ + + +#if defined(__arm__) + + +#define FUNCTION_LPPTRANSPOSER_func1 + +#ifdef FUNCTION_LPPTRANSPOSER_func1 + +/* Note: This code requires only 43 cycles per iteration instead of 61 on ARM926EJ-S */ +#ifdef __GNUC__ +__attribute__ ((noinline)) +#endif +static void lppTransposer_func1( + FIXP_DBL *lowBandReal, + FIXP_DBL *lowBandImag, + FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, + int loops, + int hiBand, + int dynamicScale, + int descale, + FIXP_SGL a0r, + FIXP_SGL a0i, + FIXP_SGL a1r, + FIXP_SGL a1i) +{ + + FIXP_DBL real1, real2, imag1, imag2, accu1, accu2; + + real2 = lowBandReal[-2]; + real1 = lowBandReal[-1]; + imag2 = lowBandImag[-2]; + imag1 = lowBandImag[-1]; + for(int i=0; i < loops; i++) + { + accu1 = fMultDiv2( a0r,real1); + accu2 = fMultDiv2( a0i,imag1); + accu1 = fMultAddDiv2(accu1,a1r,real2); + accu2 = fMultAddDiv2(accu2,a1i,imag2); + real2 = fMultDiv2( a1i,real2); + accu1 = accu1 - accu2; + accu1 = accu1 >> dynamicScale; + + accu2 = fMultAddDiv2(real2,a1r,imag2); + real2 = real1; + imag2 = imag1; + accu2 = fMultAddDiv2(accu2,a0i,real1); + real1 = lowBandReal[i]; + accu2 = fMultAddDiv2(accu2,a0r,imag1); + imag1 = lowBandImag[i]; + accu2 = accu2 >> dynamicScale; + + accu1 <<= 1; + accu2 <<= 1; + + qmfBufferReal[i][hiBand] = accu1 + (real1>>descale); + qmfBufferImag[i][hiBand] = accu2 + (imag1>>descale); + } +} +#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */ +#endif /* __arm__ */ + + + diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp new file mode 100644 index 00000000..73bd7baf --- /dev/null +++ b/libSBRdec/src/env_calc.cpp @@ -0,0 +1,2317 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope calculation + + The envelope adjustor compares the energies present in the transposed + highband to the reference energies conveyed with the bitstream. + The highband is amplified (sometimes) or attenuated (mostly) to the + desired level. + + The spectral shape of the reference energies can be changed several times per + frame if necessary. Each set of energy values corresponding to a certain range + in time will be called an envelope here. + The bitstream supports several frequency scales and two resolutions. Normally, + one or more QMF-subbands are grouped to one SBR-band. An envelope contains + reference energies for each SBR-band. + In addition to the energy envelopes, noise envelopes are transmitted that + define the ratio of energy which is generated by adding noise instead of + transposing the lowband. The noise envelopes are given in a coarser time + and frequency resolution. + If a signal contains strong tonal components, synthetic sines can be + generated in individual SBR bands. + + An overlap buffer of 6 QMF-timeslots is used to allow a more + flexible alignment of the envelopes in time that is not restricted to the + core codec's frame borders. + Therefore the envelope adjustor has access to the spectral data of the + current frame as well as the last 6 QMF-timeslots of the previous frame. + However, in average only the data of 1 frame is being processed as + the adjustor is called once per frame. + + Depending on the frequency range set in the bitstream, only QMF-subbands between + lowSubband and highSubband are adjusted. + + Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a special Mantissa-Exponent format + ( see calculateSbrEnvelope() ) are being used. The main entry point for this modules is calculateSbrEnvelope(). + + \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref documentationOverview +*/ + + +#include "env_calc.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "transcendent.h" +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" /* need FDKpow() for debug outputs */ + +#if defined(__arm__) +#include "arm/env_calc_arm.cpp" +#endif + +typedef struct +{ + FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; + FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; + FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; + FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; + FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; + + SCHAR nrgRef_e[MAX_FREQ_COEFFS]; + SCHAR nrgEst_e[MAX_FREQ_COEFFS]; + SCHAR nrgGain_e[MAX_FREQ_COEFFS]; + SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; + SCHAR nrgSine_e[MAX_FREQ_COEFFS]; +} +ENV_CALC_NRGS; + +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, + SCHAR *filtBuffer_e, + FIXP_DBL *NrgGain, + SCHAR *NrgGain_e, + int subbands); + +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, + int lowSubband, int highSubband, + int start_pos, int next_pos, + SCHAR frameExp, + FIXP_DBL *nrgEst, + SCHAR *nrgEst_e ); + +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, + int nSfb, + UCHAR *freqBandTable, + int start_pos, int next_pos, + SCHAR input_e, + FIXP_DBL *nrg_est, + SCHAR *nrg_est_e ); + +static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, ENV_CALC_NRGS* nrgs, int c, + FIXP_DBL tmpNoise, SCHAR tmpNoise_e, + UCHAR sinePresentFlag, + UCHAR sineMapped, + int noNoiseFlag); + +static void calcAvgGain(ENV_CALC_NRGS* nrgs, + int lowSubband, + int highSubband, + FIXP_DBL *sumRef_m, + SCHAR *sumRef_e, + FIXP_DBL *ptrAvgGain_m, + SCHAR *ptrAvgGain_e); + +static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, + ENV_CALC_NRGS* nrgs, + UCHAR *ptrHarmIndex, + int lowSubbands, + int noSubbands, + int scale_change, + int noNoiseFlag, + int *ptrPhaseIndex, + int scale_diff_low); + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, + ENV_CALC_NRGS* nrgs, + UCHAR *ptrHarmIndex, + int lowSubbands, + int noSubbands, + int scale_change, + int noNoiseFlag, + int *ptrPhaseIndex); +static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, + FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + ENV_CALC_NRGS* nrgs, + int lowSubbands, + int noSubbands, + int scale_change, + FIXP_SGL smooth_ratio, + int noNoiseFlag, + int filtBufferNoiseShift); + + +/*! + \brief Map sine flags from bitstream to QMF bands + + The bitstream carries only 1 sine flag per band and frame. + This function maps every sine flag from the bitstream to a specific QMF subband + and to a specific envelope where the sine shall start. + The result is stored in the vector sineMapped which contains one entry per + QMF subband. The value of an entry specifies the envelope where a sine + shall start. A value of #MAX_ENVELOPES indicates that no sine is present + in the subband. + The missing harmonics flags from the previous frame (harmFlagsPrev) determine + if a sine starts at the beginning of the frame or at the transient position. + Additionally, the flags in harmFlagsPrev are being updated by this function + for the next frame. +*/ +static void mapSineFlags(UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ + int nSfb, /*!< Number of bands in the table */ + UCHAR *addHarmonics, /*!< vector with 1 flag per sfb */ + int *harmFlagsPrev, /*!< Packed 'addHarmonics' */ + int tranEnv, /*!< Transient position */ + SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each QMF band */ + +{ + int i; + int lowSubband2 = freqBandTable[0]<<1; + int bitcount = 0; + int oldflags = *harmFlagsPrev; + int newflags = 0; + + /* + Format of harmFlagsPrev: + + first word = flags for highest 16 sfb bands in use + second word = flags for next lower 16 sfb bands (if present) + third word = flags for lowest 16 sfb bands (if present) + + Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. + The lowest bit of the first word corresponds to the _highest_ sfb band in use. + This is ensures that each flag is mapped to the same QMF band even after a + change of the crossover-frequency. + */ + + + /* Reset the output vector first */ + FDKmemset(sineMapped, MAX_ENVELOPES,MAX_FREQ_COEFFS); /* MAX_ENVELOPES means 'no sine' */ + + freqBandTable += nSfb; + addHarmonics += nSfb-1; + + for (i=nSfb; i!=0; i--) { + int ui = *freqBandTable--; /* Upper limit of the current scale factor band. */ + int li = *freqBandTable; /* Lower limit of the current scale factor band. */ + + if ( *addHarmonics-- ) { /* There is a sine in this band */ + + unsigned int mask = 1 << bitcount; + newflags |= mask; /* Set flag */ + + /* + If there was a sine in the last frame, let it continue from the first envelope on + else start at the transient position. + */ + sineMapped[(ui+li-lowSubband2) >> 1] = ( oldflags & mask ) ? 0 : tranEnv; + } + + if ((++bitcount == 16) || i==1) { + bitcount = 0; + *harmFlagsPrev++ = newflags; + oldflags = *harmFlagsPrev; /* Fetch 16 of the old flags */ + newflags = 0; + } + } +} + + +/*! + \brief Reduce gain-adjustment induced aliasing for real valued filterbank. +*/ +/*static*/ void +aliasingReduction(FIXP_DBL* degreeAlias, /*!< estimated aliasing for each QMF channel */ + ENV_CALC_NRGS* nrgs, + int* useAliasReduction, /*!< synthetic sine engergy for each subband, used as flag */ + int noSubbands) /*!< number of QMF channels to process */ +{ + FIXP_DBL* nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ + SCHAR* nrgGain_e = nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ + FIXP_DBL* nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ + SCHAR* nrgEst_e = nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ + int grouping = 0, index = 0, noGroups, k; + int groupVector[MAX_FREQ_COEFFS]; + + /* Calculate grouping*/ + for (k = 0; k < noSubbands-1; k++ ){ + if ( (degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k] ) { + if(grouping==0){ + groupVector[index++] = k; + grouping = 1; + } + else{ + if(groupVector[index-1] + 3 == k){ + groupVector[index++] = k + 1; + grouping = 0; + } + } + } + else{ + if(grouping){ + if(useAliasReduction[k]) + groupVector[index++] = k + 1; + else + groupVector[index++] = k; + grouping = 0; + } + } + } + + if(grouping){ + groupVector[index++] = noSubbands; + } + noGroups = index >> 1; + + + /*Calculate new gain*/ + for (int group = 0; group < noGroups; group ++) { + FIXP_DBL nrgOrig = FL2FXCONST_DBL(0.0f); /* Original signal energy in current group of bands */ + SCHAR nrgOrig_e = 0; + FIXP_DBL nrgAmp = FL2FXCONST_DBL(0.0f); /* Amplified signal energy in group (using current gains) */ + SCHAR nrgAmp_e = 0; + FIXP_DBL nrgMod = FL2FXCONST_DBL(0.0f); /* Signal energy in group when applying modified gains */ + SCHAR nrgMod_e = 0; + FIXP_DBL groupGain; /* Total energy gain in group */ + SCHAR groupGain_e; + FIXP_DBL compensation; /* Compensation factor for the energy change when applying modified gains */ + SCHAR compensation_e; + + int startGroup = groupVector[2*group]; + int stopGroup = groupVector[2*group+1]; + + /* Calculate total energy in group before and after amplification with current gains: */ + for(k = startGroup; k < stopGroup; k++){ + /* Get original band energy */ + FIXP_DBL tmp = nrgEst[k]; + SCHAR tmp_e = nrgEst_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e); + + /* Multiply band energy with current gain */ + tmp = fMult(tmp,nrgGain[k]); + tmp_e = tmp_e + nrgGain_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e); + } + + /* Calculate total energy gain in group */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, + nrgOrig, nrgOrig_e, + &groupGain, &groupGain_e); + + for(k = startGroup; k < stopGroup; k++){ + FIXP_DBL tmp; + SCHAR tmp_e; + + FIXP_DBL alpha = degreeAlias[k]; + if (k < noSubbands - 1) { + if (degreeAlias[k + 1] > alpha) + alpha = degreeAlias[k + 1]; + } + + /* Modify gain depending on the degree of aliasing */ + FDK_add_MantExp( fMult(alpha,groupGain), groupGain_e, + fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha,nrgGain[k]), nrgGain_e[k], + &nrgGain[k], &nrgGain_e[k] ); + + /* Apply modified gain to original energy */ + tmp = fMult(nrgGain[k],nrgEst[k]); + tmp_e = nrgGain_e[k] + nrgEst_e[k]; + + /* Accumulate energy with modified gains applied */ + FDK_add_MantExp( tmp, tmp_e, + nrgMod, nrgMod_e, + &nrgMod, &nrgMod_e ); + } + + /* Calculate compensation factor to retain the energy of the amplified signal */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, + nrgMod, nrgMod_e, + &compensation, &compensation_e); + + /* Apply compensation factor to all gains of the group */ + for(k = startGroup; k < stopGroup; k++){ + nrgGain[k] = fMult(nrgGain[k],compensation); + nrgGain_e[k] = nrgGain_e[k] + compensation_e; + } + } +} + + + /* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15-(s)) +#define EXP2SCALE(e) (15-(e)) + +/*! + \brief Apply spectral envelope to subband samples + + This function is called from sbr_dec.cpp in each frame. + + To enhance accuracy and due to the usage of tables for squareroots and + inverse, some calculations are performed with the operands being split + into mantissa and exponent. The variable names in the source code carry + the suffixes _m and _e respectively. The control data + in #hFrameData containts envelope data which is represented by this format but + stored in single words. (See requantizeEnvelopeData() for details). This data + is unpacked within calculateSbrEnvelope() to follow the described suffix convention. + + The actual value (comparable to the corresponding float-variable in the + research-implementation) of a mantissa/exponent-pair can be calculated as + + \f$ value = value\_m * 2^{value\_e} \f$ + + All energies and noise levels decoded from the bitstream suit for an + original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. Therefore, + the scale factor hb_scale passed into this function will be converted + to an 'input exponent' (#input_e), which fits the internal representation. + + Before the actual processing, an exponent #adj_e for resulting adjusted + samples is derived from the maximum reference energy. + + Then, for each envelope, the following steps are performed: + + \li Calculate energy in the signal to be adjusted. Depending on the the value of + #interpolFreq (interpolation mode), this is either done seperately + for each QMF-subband or for each SBR-band. + The resulting energies are stored in #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) + and #nrgEst_e[#MAX_FREQ_COEFFS] (exponents). + \li Calculate gain and noise level for each subband:
+ \f$ gain = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } + \hspace{2cm} + noise = \sqrt{ nrgRef \cdot noiseRatio } + \f$
+ where noiseRatio and nrgRef are extracted from the + bitstream and nrgEst is the subband energy before adjustment. + The resulting gains are stored in #nrgGain_m[#MAX_FREQ_COEFFS] + (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] (exponents), the noise levels + are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] and #noiseLevel_e[#MAX_FREQ_COEFFS] + (exponents). + The sine levels are stored in #nrgSine_m[#MAX_FREQ_COEFFS] + and #nrgSine_e[#MAX_FREQ_COEFFS]. + \li Noise limiting: The gain for each subband is limited both absolutely + and relatively compared to the total gain over all subbands. + \li Boost gain: Calculate and apply boost factor for each limiter band + in order to compensate for the energy loss imposed by the limiting. + \li Apply gains and add noise: The gains and noise levels are applied + to all timeslots of the current envelope. A short FIR-filter (length 4 + QMF-timeslots) can be used to smooth the sudden change at the envelope borders. + Each complex subband sample of the current timeslot is multiplied by the + smoothed gain, then random noise with the calculated level is added. + + \note + To reduce the stack size, some of the local arrays could be located within + the time output buffer. Of the 512 samples temporarily available there, + about half the size is already used by #SBR_FRAME_DATA. A pointer to the + remaining free memory could be supplied by an additional argument to calculateSbrEnvelope() + in sbr_dec: + + \par + \code + calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, + &hSbrDec->SbrCalculateEnvelope, + hHeaderData, + hFrameData, + QmfBufferReal, + QmfBufferImag, + timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + 1); + \endcode + + \par + Within calculateSbrEnvelope(), some pointers could be defined instead of the arrays + #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: + + \par + \code + fract* nrgRef_m = timeOutPtr; + SCHAR* nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS; + fract* nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS; + SCHAR* nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS; + fract* noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS; + \endcode + +
+*/ +void +calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples to be processed */ + FIXP_DBL **analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, + const int frameErrorFlag + ) +{ + int c, i, j, envNoise = 0; + UCHAR* borders = hFrameData->frameInfo.borders; + + FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + + int lowSubband = hFreq->lowSubband; + int highSubband = hFreq->highSubband; + int noSubbands = highSubband - lowSubband; + + int noNoiseBands = hFreq->nNfb; + int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + UCHAR first_start = borders[0] * hHeaderData->timeStep; + + SCHAR sineMapped[MAX_FREQ_COEFFS]; + SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); + SCHAR adj_e = 0; + SCHAR output_e; + SCHAR final_e = 0; + + SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; + + int useAliasReduction[64]; + UCHAR smooth_length = 0; + + FIXP_SGL * pIenv = hFrameData->iEnvelope; + + /* + Extract sine flags for all QMF bands + */ + mapSineFlags(hFreq->freqBandTable[1], + hFreq->nSfb[1], + hFrameData->addHarmonics, + h_sbr_cal_env->harmFlagsPrev, + hFrameData->frameInfo.tranEnv, + sineMapped); + + + /* + Scan for maximum in bufferd noise levels. + This is needed in case that we had strong noise in the previous frame + which is smoothed into the current frame. + The resulting exponent is used as start value for the maximum search + in reference energies + */ + if (!useLP) + adj_e = h_sbr_cal_env->filtBufferNoise_e - getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); + + /* + Scan for maximum reference energy to be able + to select appropriate values for adj_e and final_e. + */ + + for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { + INT maxSfbNrg_e = -FRACT_BITS+NRG_EXP_OFFSET; /* start value for maximum search */ + + /* Fetch frequency resolution for current envelope: */ + for (j=hFreq->nSfb[hFrameData->frameInfo.freqRes[i]]; j!=0; j--) { + maxSfbNrg_e = fixMax(maxSfbNrg_e,(INT)((LONG)(*pIenv++) & MASK_E)); + } + maxSfbNrg_e -= NRG_EXP_OFFSET; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = (maxSfbNrg_e+1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the current + */ + maxSfbNrg_e += 6; + + if (borders[i] < hHeaderData->numberTimeSlots) + /* This envelope affects timeslots that belong to the output frame */ + adj_e = (maxSfbNrg_e > adj_e) ? maxSfbNrg_e : adj_e; + + if (borders[i+1] > hHeaderData->numberTimeSlots) + /* This envelope affects timeslots after the output frame */ + final_e = (maxSfbNrg_e > final_e) ? maxSfbNrg_e : final_e; + + } + + /* + Calculate adjustment factors and apply them for every envelope. + */ + pIenv = hFrameData->iEnvelope; + + for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { + + int k, noNoiseFlag; + SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); + C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1); + + /* + Helper variables. + */ + UCHAR start_pos = hHeaderData->timeStep * borders[i]; /* Start-position in time (subband sample) for current envelope. */ + UCHAR stop_pos = hHeaderData->timeStep * borders[i+1]; /* Stop-position in time (subband sample) for current envelope. */ + UCHAR freq_res = hFrameData->frameInfo.freqRes[i]; /* Frequency resolution for current envelope. */ + + + /* Always do fully initialize the temporary energy table. This prevents negative energies and extreme gain factors in + cases where the number of limiter bands exceeds the number of subbands. The latter can be caused by undetected bit + errors and is tested by some streams from the certification set. */ + FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS)); + + /* If the start-pos of the current envelope equals the stop pos of the current + noise envelope, increase the pointer (i.e. choose the next noise-floor).*/ + if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise+1]){ + noiseLevels += noNoiseBands; /* The noise floor data is stored in a row [noiseFloor1 noiseFloor2...].*/ + envNoise++; + } + + if(i==hFrameData->frameInfo.tranEnv || i==h_sbr_cal_env->prevTranEnv) /* attack */ + { + noNoiseFlag = 1; + if (!useLP) + smooth_length = 0; /* No smoothing on attacks! */ + } + else { + noNoiseFlag = 0; + if (!useLP) + smooth_length = (1 - hHeaderData->bs_data.smoothingLength) << 2; /* can become either 0 or 4 */ + } + + + /* + Energy estimation in transposed highband. + */ + if (hHeaderData->bs_data.interpolFreq) + calcNrgPerSubband(analysBufferReal, + (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, + start_pos, stop_pos, + input_e, + pNrgs->nrgEst, + pNrgs->nrgEst_e); + else + calcNrgPerSfb(analysBufferReal, + (useLP) ? NULL : analysBufferImag, + hFreq->nSfb[freq_res], + hFreq->freqBandTable[freq_res], + start_pos, stop_pos, + input_e, + pNrgs->nrgEst, + pNrgs->nrgEst_e); + + /* + Calculate subband gains + */ + { + UCHAR * table = hFreq->freqBandTable[freq_res]; + UCHAR * pUiNoise = &hFreq->freqBandTableNoise[1]; /*! Upper limit of the current noise floor band. */ + + FIXP_SGL * pNoiseLevels = noiseLevels; + + FIXP_DBL tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + SCHAR tmpNoise_e = (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + int cc = 0; + c = 0; + for (j = 0; j < hFreq->nSfb[freq_res]; j++) { + + FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); + SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; + + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j+1]; + + for (k=li; k= sineMapped[cc]); + cc++; + } + + for (k=li; k= *pUiNoise) { + tmpNoise = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); + + if (useLP) + useAliasReduction[k-lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, + tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], + noNoiseFlag); + + pNrgs->nrgRef[c] = refNrg; + pNrgs->nrgRef_e[c] = refNrg_e; + + c++; + } + pIenv++; + } + } + + /* + Noise limiting + */ + + for (c = 0; c < hFreq->noLimiterBands; c++) { + + FIXP_DBL sumRef, boostGain, maxGain; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; + + calcAvgGain(pNrgs, + hFreq->limiterBandTable[c], hFreq->limiterBandTable[c+1], + &sumRef, &sumRef_e, + &maxGain, &maxGain_e); + + /* Multiply maxGain with limiterGain: */ + maxGain = fMult(maxGain, FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); + maxGain_e += FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; + + /* Scale mantissa of MaxGain into range between 0.5 and 1: */ + if (maxGain == FL2FXCONST_DBL(0.0f)) + maxGain_e = -FRACT_BITS; + else { + SCHAR charTemp = CountLeadingBits(maxGain); + maxGain_e -= charTemp; + maxGain <<= (int)charTemp; + } + + if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */ + maxGain = FL2FXCONST_DBL(0.5f); + maxGain_e = maxGainLimit_e; + } + + + /* Every subband gain is compared to the scaled "average gain" + and limited if necessary: */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c+1]; k++) { + if ( (pNrgs->nrgGain_e[k] > maxGain_e) || (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k]>maxGain) ) { + + FIXP_DBL noiseAmp; + SCHAR noiseAmp_e; + + FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); + pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k],noiseAmp); + pNrgs->noiseLevel_e[k] += noiseAmp_e; + pNrgs->nrgGain[k] = maxGain; + pNrgs->nrgGain_e[k] = maxGain_e; + } + } + + /* -- Boost gain + Calculate and apply boost factor for each limiter band: + 1. Check how much energy would be present when using the limited gain + 2. Calculate boost factor by comparison with reference energy + 3. Apply boost factor to compensate for the energy loss due to limiting + */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { + + /* 1.a Add energy of adjusted signal (using preliminary gain) */ + FIXP_DBL tmp = fMult(pNrgs->nrgGain[k],pNrgs->nrgEst[k]); + SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; + FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e); + + /* 1.b Add sine energy (if present) */ + if(pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { + FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, &accu, &accu_e); + } + else { + /* 1.c Add noise energy (if present) */ + if(noNoiseFlag == 0) { + FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, accu_e, &accu, &accu_e); + } + } + } + + /* 2.a Calculate ratio of wanted energy and accumulated energy */ + if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */ + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } else { + INT div_e; + boostGain = fDivNorm(sumRef, accu, &div_e); + boostGain_e = sumRef_e - accu_e + div_e; + } + + + /* 2.b Result too high? --> Limit the boost factor to +4 dB */ + if((boostGain_e > 3) || + (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || + (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f)) ) + { + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } + /* 3. Multiply all signal components with the boost factor */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; k++) { + pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k],boostGain); + pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1; + + pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k],boostGain); + pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1; + + pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k],boostGain); + pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1; + } + } + /* End of noise limiting */ + + if (useLP) + aliasingReduction(degreeAlias+lowSubband, + pNrgs, + useAliasReduction, + noSubbands); + + /* For the timeslots within the range for the output frame, + use the same scale for the noise levels. + Drawback: If the envelope exceeds the frame border, the noise levels + will have to be rescaled later to fit final_e of + the gain-values. + */ + noise_e = (start_pos < no_cols) ? adj_e : final_e; + + /* + Convert energies to amplitude levels + */ + for (k=0; knrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); + FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], &pNrgs->nrgGain_e[k]); + FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], &noise_e); + } + + + + /* + Apply calculated gains and adaptive noise + */ + + /* assembleHfSignals() */ + { + int scale_change, sc_change; + FIXP_SGL smooth_ratio; + int filtBufferNoiseShift=0; + + /* Initialize smoothing buffers with the first valid values */ + if (h_sbr_cal_env->startUp) + { + if (!useLP) { + h_sbr_cal_env->filtBufferNoise_e = noise_e; + + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); + + } + h_sbr_cal_env->startUp = 0; + } + + if (!useLP) { + + equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ + h_sbr_cal_env->filtBuffer_e, /* buffered */ + pNrgs->nrgGain, /* current */ + pNrgs->nrgGain_e, /* current */ + noSubbands); + + /* Adapt exponent of buffered noise levels to the current exponent + so they can easily be smoothed */ + if((h_sbr_cal_env->filtBufferNoise_e - noise_e)>=0) { + int shift = fixMin(DFRACT_BITS-1,(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k=0; kfiltBufferNoise[k] <<= shift; + } + else { + int shift = fixMin(DFRACT_BITS-1,-(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k=0; kfiltBufferNoise[k] >>= shift; + } + + h_sbr_cal_env->filtBufferNoise_e = noise_e; + } + + /* find best scaling! */ + scale_change = -(DFRACT_BITS-1); + for(k=0;knrgGain_e[k]); + } + sc_change = (start_posnrgGain_e[k] + (sc_change-1); + pNrgs->nrgGain[k] >>= sc; + pNrgs->nrgGain_e[k] += sc; + } + + if (!useLP) { + for(k=0;kfiltBuffer_e[k] + (sc_change-1); + h_sbr_cal_env->filtBuffer[k] >>= sc; + } + } + + for (j = start_pos; j < stop_pos; j++) + { + /* This timeslot is located within the first part of the processing buffer + and will be fed into the QMF-synthesis for the current frame. + adj_e - input_e + This timeslot will not yet be fed into the QMF so we do not care + about the adj_e. + sc_change = final_e - input_e + */ + if ( (j==no_cols) && (start_posfiltBufferNoise[k] will be applied in function adjustTimeSlotHQ() */ + if (shift>=0) { + shift = fixMin(DFRACT_BITS-1,shift); + for (k=0; knrgSine[k] <<= shift; + pNrgs->noiseLevel[k] <<= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] <<= shift; + */ + } + } + else { + shift = fixMin(DFRACT_BITS-1,-shift); + for (k=0; knrgSine[k] >>= shift; + pNrgs->noiseLevel[k] >>= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] >>= shift; + */ + } + } + + /* update noise scaling */ + noise_e = final_e; + if (!useLP) + h_sbr_cal_env->filtBufferNoise_e = noise_e; /* scaling value unused! */ + + /* update gain buffer*/ + sc_change -= (final_e - input_e); + + if (sc_change<0) { + for(k=0;knrgGain[k] >>= -sc_change; + pNrgs->nrgGain_e[k] += -sc_change; + } + if (!useLP) { + for(k=0;kfiltBuffer[k] >>= -sc_change; + } + } + } else { + scale_change+=sc_change; + } + + } // if + + if (!useLP) { + + /* Prevent the smoothing filter from running on constant levels */ + if (j-start_pos < smooth_length) + smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j-start_pos]; + else + smooth_ratio = FL2FXCONST_SGL(0.0f); + + adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], + h_sbr_cal_env, + pNrgs, + lowSubband, + noSubbands, + scale_change, + smooth_ratio, + noNoiseFlag, + filtBufferNoiseShift); + } + else + { + if (flags & SBRDEC_ELD_GRID) { + adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], + pNrgs, + &h_sbr_cal_env->harmIndex, + lowSubband, + noSubbands, + scale_change, + noNoiseFlag, + &h_sbr_cal_env->phaseIndex, + EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale); + } else + { + adjustTimeSlotLC(&analysBufferReal[j][lowSubband], + pNrgs, + &h_sbr_cal_env->harmIndex, + lowSubband, + noSubbands, + scale_change, + noNoiseFlag, + &h_sbr_cal_env->phaseIndex); + } + } + } // for + + if (!useLP) { + /* Update time-smoothing-buffers for gains and noise levels + The gains and the noise values of the current envelope are copied into the buffer. + This has to be done at the end of each envelope as the values are required for + a smooth transition to the next envelope. */ + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, noSubbands*sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, noSubbands*sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, noSubbands*sizeof(FIXP_DBL)); + } + + } + C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1); + } + + /* Rescale output samples */ + { + FIXP_DBL maxVal; + int ov_reserve, reserve; + + /* Determine headroom in old adjusted samples */ + maxVal = maxSubbandSample( analysBufferReal, + (useLP) ? NULL : analysBufferImag, + lowSubband, + highSubband, + 0, + first_start); + + ov_reserve = fNorm(maxVal); + + /* Determine headroom in new adjusted samples */ + maxVal = maxSubbandSample( analysBufferReal, + (useLP) ? NULL : analysBufferImag, + lowSubband, + highSubband, + first_start, + no_cols); + + reserve = fNorm(maxVal); + + /* Determine common output exponent */ + if (ov_adj_e - ov_reserve > adj_e - reserve ) /* set output_e to the maximum */ + output_e = ov_adj_e - ov_reserve; + else + output_e = adj_e - reserve; + + /* Rescale old samples */ + rescaleSubbandSamples( analysBufferReal, + (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, + 0, first_start, + ov_adj_e - output_e); + + /* Rescale new samples */ + rescaleSubbandSamples( analysBufferReal, + (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, + first_start, no_cols, + adj_e - output_e); + } + + /* Update hb_scale */ + sbrScaleFactor->hb_scale = EXP2SCALE(output_e); + + /* Save the current final exponent for the next frame: */ + sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e); + + + /* We need to remeber to the next frame that the transient + will occur in the first envelope (if tranEnv == nEnvelopes). */ + if(hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) + h_sbr_cal_env->prevTranEnv = 0; + else + h_sbr_cal_env->prevTranEnv = -1; + +} + + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be used. + + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< static SBR control data, initialized with defaults */ + const int chan, /*!< Channel for which to assign buffers */ + const UINT flags) +{ + SBR_ERROR err = SBRDEC_OK; + int i; + + /* Clear previous missing harmonics flags */ + for (i=0; i<(MAX_FREQ_COEFFS+15)>>4; i++) { + hs->harmFlagsPrev[i] = 0; + } + hs->harmIndex = 0; + + /* + Setup pointers for time smoothing. + The buffer itself will be initialized later triggered by the startUp-flag. + */ + hs->prevTranEnv = -1; + + + /* initialization */ + resetSbrEnvelopeCalc(hs); + + if (chan==0) { /* do this only once */ + err = resetFreqBandTables(hHeaderData, flags); + } + + return err; +} + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be used. + + \return errorCode, 0 if successful +*/ +int +deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hs) +{ + return 0; +} + + +/*! + \brief Reset envelope instance + + This function must be called for each channel on a change of configuration. + Note that resetFreqBandTables should also be called in this case. + + \return errorCode, 0 if successful +*/ +void +resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ +{ + hCalEnv->phaseIndex = 0; + + /* Noise exponent needs to be reset because the output exponent for the next frame depends on it */ + hCalEnv->filtBufferNoise_e = 0; + + hCalEnv->startUp = 1; +} + + +/*! + \brief Equalize exponents of the buffered gain values and the new ones + + After equalization of exponents, the FIR-filter addition for smoothing + can be performed. + This function is called once for each envelope before adjusting. +*/ +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, /*!< bufferd gains */ + SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ + FIXP_DBL *nrgGain, /*!< gains for current envelope */ + SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ + int subbands) /*!< Number of QMF subbands */ +{ + int band; + int diff; + + for (band=0; band0) { + filtBuffer[band] >>= diff; /* Compensate for the scale change by shifting the mantissa. */ + filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ + } + else if (diff<0) { + /* The buffered gains seem to be larger, but maybe there + are some unused bits left in the mantissa */ + + int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band]))-1; + + if ((-diff) <= reserve) { + /* There is enough space in the buffered mantissa so + that we can take the new exponent as common. + */ + filtBuffer[band] <<= (-diff); + filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ + } + else { + filtBuffer[band] <<= reserve; /* Shift the mantissa as far as possible: */ + filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ + + /* For the remaining difference, change the new gain value */ + diff = fixMin(-(reserve + diff),DFRACT_BITS-1); + nrgGain[band] >>= diff; + nrgGain_e[band] += diff; + } + } + } +} + +/*! + \brief Shift left the mantissas of all subband samples + in the giventime and frequency range by the specified number of bits. + + This function is used to rescale the audio data in the overlap buffer + which has already been envelope adjusted with the last frame. +*/ +void rescaleSubbandSamples(FIXP_DBL ** re, /*!< Real part of input and output subband samples */ + FIXP_DBL ** im, /*!< Imaginary part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< End of frequency range to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos, /*!< End of time rage (QMF-timeslot) */ + int shift) /*!< number of bits to shift */ +{ + int width = highSubband-lowSubband; + + if ( (width > 0) && (shift!=0) ) { + if (im!=NULL) { + for (int l=start_pos; l 0 ) { + if (im!=NULL) + { + for (int l=start_pos; l>(DFRACT_BITS-1))); + maxVal |= (FIXP_DBL)((LONG)(tmp2)^((LONG)tmp2>>(DFRACT_BITS-1))); + } while(--k!=0); +#endif + } + } else + { + for (int l=start_pos; l>(DFRACT_BITS-1))); + }while(--k!=0); + } + } + } + + return(maxVal); +} + +#define SHIFT_BEFORE_SQUARE (3) /* (7/2) */ +/*!< + If the accumulator does not provide enough overflow bits or + does not provide a high dynamic range, the below energy calculation + requires an additional shift operation for each sample. + On the other hand, doing the shift allows using a single-precision + multiplication for the square (at least 16bit x 16bit). + For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic + is required for the energy accumulation. + Theoretically, the sample-squares can sum up to a value of 76, + requiring 7 overflow bits. However since such situations are *very* + rare, accu can be limited to 64. + In case native saturated arithmetic is not available, overflows + can be prevented by replacing the above #define by + #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2) + which will result in slightly reduced accuracy. +*/ + +/*! + \brief Estimates the mean energy of each filter-bank channel for the + duration of the current envelope + + This function is used when interpolFreq is true. +*/ +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int lowSubband, /*!< Begin of the SBR frequency range */ + int highSubband, /*!< High end of the SBR frequency range */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR frameExp, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + SCHAR preShift; + SCHAR shift; + FIXP_DBL sum; + int k,l; + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: */ + frameExp = frameExp << 1; + + for (k=lowSubband; k>(DFRACT_BITS-1))); + bufferReal[l] = analysBufferReal[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l])^((LONG)bufferReal[l]>>(DFRACT_BITS-1))); + } + } + else + { + for (l=start_pos;l>(DFRACT_BITS-1))); + } + } + + if (maxVal!=FL2FXCONST_DBL(0.f)) { + + + /* If the accu does not provide enough overflow bits, we cannot + shift the samples up to the limit. + Instead, keep up to 3 free bits in each sample, i.e. up to + 6 bits after calculation of square. + Please note the comment on saturated arithmetic above! + */ + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + preShift = CntLeadingZeros(maxVal)-1; + preShift -= SHIFT_BEFORE_SQUARE; + + if (preShift>=0) { + if (analysBufferImag!=NULL) { + for (l=start_pos; l> (int)negpreShift; + FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp1); + accu = fPow2AddDiv2(accu, temp2); + } + } else + { + for (l=start_pos; l> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp); + } + } + } + accu <<= 1; + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(accu); + sum = accu << (int)shift; + + /* Divide by width of envelope and apply frame scale: */ + *nrgEst++ = fMult(sum, invWidth); + shift += 2 * preShift; + if (analysBufferImag!=NULL) + *nrgEst_e++ = frameExp - shift; + else + *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ + } /* maxVal!=0 */ + else { + + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + *nrgEst++ = FL2FXCONST_DBL(0.0f); + *nrgEst_e++ = 0; + } + } +} + +/*! + \brief Estimates the mean energy of each Scale factor band for the + duration of the current envelope. + + This function is used when interpolFreq is false. +*/ +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int nSfb, /*!< Number of scale factor bands */ + UCHAR *freqBandTable, /*!< First Subband for each Sfb */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR input_e, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e ) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + FIXP_DBL temp; + SCHAR preShift; + SCHAR shift, sum_e; + FIXP_DBL sum; + + int j,k,l,li,ui; + FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient, + but overflow bits are required for accumulation */ + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: */ + input_e = input_e << 1; + + for(j=0; j=0) { + for (l=start_pos; l> -(int)preShift; + sumLine += fPow2Div2(temp); + temp = analysBufferImag[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } else + { + if (preShift>=0) { + for (l=start_pos; l> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } + + /* The number of QMF-channels per SBR bands may be up to 15. + Shift right to avoid overflows in sum over all channels. */ + sumLine = sumLine >> (4-1); + sumAll += sumLine; + } + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(sumAll); + sum = sumAll << (int)shift; + + /* Divide by width of envelope: */ + sum = fMult(sum,invWidth); + + /* Divide by width of Sfb: */ + sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui-li))); + + /* Set all Subband energies in the Sfb to the average energy: */ + if (analysBufferImag!=NULL) + sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ + else + sum_e = input_e + 4 + 1 - shift; /* -4 to compensate right-shift; +1 due to missing imag. part */ + + sum_e -= 2 * preShift; + } /* maxVal!=0 */ + else { + + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + sum = FL2FXCONST_DBL(0.0f); + sum_e = 0; + } + + for (k=li; knrgEst[i]; /*!< Energy in transposed signal */ + SCHAR nrgEst_e = nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ + FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ + SCHAR *ptrNrgGain_e = &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ + FIXP_DBL *ptrNoiseLevel = &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ + SCHAR *ptrNoiseLevel_e = &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ + FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ + SCHAR *ptrNrgSine_e = &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ + + FIXP_DBL a, b, c; + SCHAR a_e, b_e, c_e; + + /* + This addition of 1 prevents divisions by zero in the reference code. + For very small energies in nrgEst, it prevents the gains from becoming + very high which could cause some trouble due to the smoothing. + */ + b_e = (int)(nrgEst_e - 1); + if (b_e>=0) { + nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (nrgEst >> 1); + nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ + + } else { + nrgEst = (nrgEst >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); + nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* A = NrgRef * TmpNoise */ + a = fMult(nrgRef,tmpNoise); + a_e = nrgRef_e + tmpNoise_e; + + /* B = 1 + TmpNoise */ + b_e = (int)(tmpNoise_e - 1); + if (b_e>=0) { + b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e+1,DFRACT_BITS-1)) + (tmpNoise >> 1); + b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ + } else { + b = (tmpNoise >> (INT)(fixMin(-b_e+1,DFRACT_BITS-1))) + (FL2FXCONST_DBL(0.5f) >> 1); + b_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */ + FDK_divide_MantExp( a, a_e, + b, b_e, + ptrNoiseLevel, ptrNoiseLevel_e); + + if (sinePresentFlag) { + + /* C = (1 + TmpNoise) * NrgEst */ + c = fMult(b,nrgEst); + c_e = b_e + nrgEst_e; + + /* gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */ + FDK_divide_MantExp( a, a_e, + c, c_e, + ptrNrgGain, ptrNrgGain_e); + + if (sineMapped) { + + /* sineLevel = nrgRef/ (1 + TmpNoise) */ + FDK_divide_MantExp( nrgRef, nrgRef_e, + b, b_e, + ptrNrgSine, ptrNrgSine_e); + } + } + else { + if (noNoiseFlag) { + /* B = NrgEst */ + b = nrgEst; + b_e = nrgEst_e; + } + else { + /* B = NrgEst * (1 + TmpNoise) */ + b = fMult(b,nrgEst); + b_e = b_e + nrgEst_e; + } + + + /* gain = nrgRef / B */ + FDK_divide_MantExp( nrgRef, nrgRef_e, + b, b_e, + ptrNrgGain, ptrNrgGain_e); + } +} + + +/*! + \brief Calculate "average gain" for the specified subband range. + + This is rather a gain of the average magnitude than the average + of gains! + The result is used as a relative limit for all gains within the + current "limiter band" (a certain frequency range). +*/ +static void calcAvgGain(ENV_CALC_NRGS* nrgs, + int lowSubband, /*!< Begin of the limiter band */ + int highSubband, /*!< High end of the limiter band */ + FIXP_DBL *ptrSumRef, + SCHAR *ptrSumRef_e, + FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ + SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ +{ + FIXP_DBL *nrgRef = nrgs->nrgRef; /*!< Reference Energy according to envelope data */ + SCHAR *nrgRef_e = nrgs->nrgRef_e; /*!< Reference Energy according to envelope data (exponent) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ + SCHAR *nrgEst_e = nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ + + FIXP_DBL sumRef = 1; + FIXP_DBL sumEst = 1; + SCHAR sumRef_e = -FRACT_BITS; + SCHAR sumEst_e = -FRACT_BITS; + int k; + + for (k=lowSubband; knrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int phaseIndex = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + + static const INT harmonicPhase [2][4] = { + { 1, 0, -1, 0}, + { 0, 1, 0, -1} + }; + + static const FIXP_DBL harmonicPhaseX [2][4] = { + { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001) }, + { FL2FXCONST_DBL(2.0*1.245183154539139e-001), FL2FXCONST_DBL(2.0* 1.123767859325028e-001), FL2FXCONST_DBL(2.0*-1.245183154539139e-001), FL2FXCONST_DBL(2.0*-1.123767859325028e-001) } + }; + + for (k=0; k < noSubbands; k++) { + + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + if( (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) || (noNoiseFlag == 1) ){ + sbNoise = FL2FXCONST_DBL(0.0f); + } else { + sbNoise = pNoiseLevel[0]; + } + + signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); + + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise)<<4); + + signalReal += pSineLevel[0] * harmonicPhase[0][harmIndex]; + + *ptrReal = signalReal; + + if (k == 0) { + *(ptrReal-1) += scaleValue(fMultDiv2(harmonicPhaseX[lowSubband&1][harmIndex], pSineLevel[0]), -scale_diff_low) ; + if (k < noSubbands - 1) { + *(ptrReal) += fMultDiv2(pSineLevel[1], harmonicPhaseX[(lowSubband+1)&1][harmIndex]); + } + } + if (k > 0 && k < noSubbands - 1 && tone_count < 16) { + *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1] [harmIndex]); + *(ptrReal) += fMultDiv2(pSineLevel[+ 1], harmonicPhaseX [(lowSubband+k+1)&1][harmIndex]); + } + if (k == noSubbands - 1 && tone_count < 16) { + if (k > 0) { + *(ptrReal) += fMultDiv2(pSineLevel[- 1], harmonicPhaseX [(lowSubband+k)&1][harmIndex]); + } + if (k + lowSubband + 1< 63) { + *(ptrReal+1) += fMultDiv2(pSineLevel[0], harmonicPhaseX[(lowSubband+k+1)&1][harmIndex]); + } + } + + if(pSineLevel[0] != FL2FXCONST_DBL(0.0f)){ + tone_count++; + } + ptrReal++; + pNoiseLevel++; + pGain++; + pSineLevel++; + } + + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1); +} + +/*! + \brief Amplify one timeslot of the signal with the calculated gains + and add the noisefloor. +*/ + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS* nrgs, + UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex) /*!< Start index to random number array */ +{ + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int k; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + UCHAR freqInvFlag = (lowSubband & 1); + FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; + int tone_count = 0; + int sineSign = 1; + + #define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.00815f)) + #define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f*0.16773f)) + + /* + First pass for k=0 pulled out of the loop: + */ + + index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + /* + The next multiplication constitutes the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #FRACT_BITS valid bits). + */ + signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); + sineLevel = *pSineLevel++; + sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); + + if (sineLevel!=FL2FXCONST_DBL(0.0f)) tone_count++; + else if (!noNoiseFlag) + /* Add noisefloor to the amplified signal */ + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + + { + if (!(harmIndex&0x1)) { + /* harmIndex 0,2 */ + signalReal += (harmIndex&0x2) ? -sineLevel : sineLevel; + *ptrReal++ = signalReal; + } + else { + /* harmIndex 1,3 in combination with freqInvFlag */ + int shift = (int) (scale_change+1); + shift = (shift>=0) ? fixMin(DFRACT_BITS-1,shift) : fixMax(-(DFRACT_BITS-1),shift); + + FIXP_DBL tmp1 = (shift>=0) ? ( fMultDiv2(C1, sineLevel) >> shift ) + : ( fMultDiv2(C1, sineLevel) << (-shift) ); + FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext); + + + /* save switch and compare operations and reduce to XOR statement */ + if ( ((harmIndex>>1)&0x1)^freqInvFlag) { + *(ptrReal-1) += tmp1; + signalReal -= tmp2; + } else { + *(ptrReal-1) -= tmp1; + signalReal += tmp2; + } + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } + } + + pNoiseLevel++; + + if ( noSubbands > 2 ) { + if (!(harmIndex&0x1)) { + /* harmIndex 0,2 */ + if(!harmIndex) + { + sineSign = 0; + } + + for (k=noSubbands-2; k!=0; k--) { + FIXP_DBL sinelevel = *pSineLevel++; + index++; + if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == FL2FXCONST_DBL(0.0f)) && !noNoiseFlag) + { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + } + + /* The next multiplication constitutes the actual envelope adjustment of the signal. */ + signalReal += fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); + + pNoiseLevel++; + *ptrReal++ = signalReal; + } /* for ... */ + } + else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if (harmIndex==1) freqInvFlag = !freqInvFlag; + + for (k=noSubbands-2; k!=0; k--) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of the signal. */ + signalReal = fMultDiv2(*ptrReal,*pGain++) << ((int)scale_change); + + if (*pSineLevel++!=FL2FXCONST_DBL(0.0f)) tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + } + + pNoiseLevel++; + + if (tone_count <= 16) { + FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1); + signalReal += (freqInvFlag) ? (-addSine) : (addSine); + } + + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } /* for ... */ + } + } + + if (noSubbands > -1) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of the signal. */ + signalReal = fMultDiv2(*ptrReal,*pGain) << ((int)scale_change); + sineLevelPrev = fMultDiv2(pSineLevel[-1],FL2FX_SGL(0.0163f)); + sineLevel = pSineLevel[0]; + + if (pSineLevel[0]!=FL2FXCONST_DBL(0.0f)) tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal = signalReal + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0])<<4); + } + + if (!(harmIndex&0x1)) { + /* harmIndex 0,2 */ + *ptrReal = signalReal + ( (sineSign) ? -sineLevel : sineLevel); + } + else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if(tone_count <= 16){ + if (freqInvFlag) { + *ptrReal++ = signalReal - sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel); + } + else { + *ptrReal++ = signalReal + sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel); + } + } + else *ptrReal = signalReal; + } + } + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); +} +static void adjustTimeSlotHQ( + FIXP_DBL *RESTRICT ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + ENV_CALC_NRGS* nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + UCHAR *RESTRICT ptrHarmIndex =&h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + int *RESTRICT ptrPhaseIndex =&h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + int shift; + + *ptrPhaseIndex = (index+noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + *ptrHarmIndex = (harmIndex + 1) & 3; + + /* + Possible optimization: + smooth_ratio and harmIndex stay constant during the loop. + It might be faster to include a separate loop in each path. + + the check for smooth_ratio is now outside the loop and the workload + of the whole function decreased by about 20 % + */ + + filtBufferNoiseShift += 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift<0) + shift = fixMin(DFRACT_BITS-1,-filtBufferNoiseShift); + else + shift = fixMin(DFRACT_BITS-1, filtBufferNoiseShift); + + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + + for (k=0; k>shift) + + fMult(direct_ratio,noiseLevel[k]); + } + else { + smoothedNoise = (fMultDiv2(smooth_ratio,filtBufferNoise[k])< scale factor of 2 */ + temp = fMultNorm(oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], &temp_e); + + /* overall scale factor of temp ist addition of scalefactors from log2 calculation, + limiter bands scalefactor (2) and limiter bands multiplication */ + temp_e += oct_e + 2; + + /* div can be a maximum of 64 (k2 = 64 and kx = 1) + -> oct can be a maximum of 6 + -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum factor of 3) + -> we need a scale factor of 5 for comparisson + */ + if (temp >> (5 - temp_e) < FL2FXCONST_DBL (0.49f) >> 5) { + + if (workLimiterBandTable[hiLimIndex] == workLimiterBandTable[loLimIndex]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + isPatchBorder[0] = isPatchBorder[1] = 0; + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) { + isPatchBorder[1] = 1; + break; + } + } + if (!isPatchBorder[1]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[loLimIndex] == patchBorders[k]) { + isPatchBorder[0] = 1; + break; + } + } + if (!isPatchBorder[0]) { + workLimiterBandTable[loLimIndex] = highSubband; + nBands--; + } + } + loLimIndex = hiLimIndex; + hiLimIndex++; + + } + shellsort(workLimiterBandTable, tempNoLim + 1); + + /* Test if algorithm exceeded maximum allowed limiterbands */ + if( nBands > MAX_NUM_LIMITERS || nBands <= 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Copy limiterbands from working buffer into final destination */ + for (k = 0; k <= nBands; k++) { + limiterBandTable[k] = workLimiterBandTable[k]; + } + } + *noLimiterBands = nBands; + + return SBRDEC_OK; +} + diff --git a/libSBRdec/src/env_calc.h b/libSBRdec/src/env_calc.h new file mode 100644 index 00000000..8154166c --- /dev/null +++ b/libSBRdec/src/env_calc.h @@ -0,0 +1,165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope calculation prototypes +*/ +#ifndef __ENV_CALC_H +#define __ENV_CALC_H + +#include "sbrdecoder.h" +#include "env_extr.h" /* for HANDLE_SBR_HEADER_DATA */ +#include "sbr_scale.h" + + +typedef struct +{ + FIXP_DBL filtBuffer[MAX_FREQ_COEFFS]; /*!< previous gains (required for smoothing) */ + FIXP_DBL filtBufferNoise[MAX_FREQ_COEFFS]; /*!< previous noise levels (required for smoothing) */ + SCHAR filtBuffer_e[MAX_FREQ_COEFFS]; /*!< Exponents of previous gains */ + SCHAR filtBufferNoise_e; /*!< Common exponent of previous noise levels */ + + int startUp; /*!< flag to signal initial conditions in buffers */ + int phaseIndex; /*!< Index for randomPase array */ + int prevTranEnv; /*!< The transient envelope of the previous frame. */ + + int harmFlagsPrev[(MAX_FREQ_COEFFS+15)/16]; + /*!< Words with 16 flags each indicating where a sine was added in the previous frame.*/ + UCHAR harmIndex; /*!< Current phase of synthetic sine */ + +} +SBR_CALCULATE_ENVELOPE; + +typedef SBR_CALCULATE_ENVELOPE *HANDLE_SBR_CALCULATE_ENVELOPE; + + + +void +calculateSbrEnvelope (QMF_SCALE_FACTOR *sbrScaleFactor, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, + const int frameErrorFlag + ); + +SBR_ERROR +createSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope, + HANDLE_SBR_HEADER_DATA hHeaderData, + const int chan, + const UINT flags); + +int +deleteSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope); + +void +resetSbrEnvelopeCalc (HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv); + +SBR_ERROR +ResetLimiterBands ( UCHAR *limiterBandTable, + UCHAR *noLimiterBands, + UCHAR *freqBandTable, + int noFreqBands, + const PATCH_PARAM *patchParam, + int noPatches, + int limiterBands); + +void rescaleSubbandSamples( FIXP_DBL ** re, + FIXP_DBL ** im, + int lowSubband, int noSubbands, + int start_pos, int next_pos, + int shift); + +FIXP_DBL maxSubbandSample( FIXP_DBL ** analysBufferReal_m, + FIXP_DBL ** analysBufferImag_m, + int lowSubband, + int highSubband, + int start_pos, + int stop_pos); + +#endif // __ENV_CALC_H diff --git a/libSBRdec/src/env_dec.cpp b/libSBRdec/src/env_dec.cpp new file mode 100644 index 00000000..c65c1691 --- /dev/null +++ b/libSBRdec/src/env_dec.cpp @@ -0,0 +1,852 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief envelope decoding + This module provides envelope decoding and error concealment algorithms. The main + entry point is decodeSbrData(). + + \sa decodeSbrData(),\ref documentationOverview +*/ + +#include "env_dec.h" + +#include "env_extr.h" +#include "transcendent.h" + +#include "genericStds.h" + + +static void decodeEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_otherChannel); +static void sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_FRAME_DATA h_data_right); +static void requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution); +static void deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static int checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); + + + +#define SBR_ENERGY_PAN_OFFSET (12 << ENV_EXP_FRACT) +#define SBR_MAX_ENERGY (35 << ENV_EXP_FRACT) + +#define DECAY ( 1 << ENV_EXP_FRACT) + +#if ENV_EXP_FRACT +#define DECAY_COUPLING ( 1 << (ENV_EXP_FRACT-1) ) /*!< corresponds to a value of 0.5 */ +#else +#define DECAY_COUPLING 1 /*!< If the energy data is not shifted, use 1 instead of 0.5 */ +#endif + + +/*! + \brief Convert table index +*/ +static int indexLow2High(int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequency resolution */ +{ + if(res == 0) + { + if (offset >= 0) + { + if (index < offset) + return(index); + else + return(2*index - offset); + } + else + { + offset = -offset; + if (index < offset) + return(2*index+index); + else + return(2*index + offset); + } + } + else + return(index); +} + + +/*! + \brief Update previous envelope value for delta-coding + + The current envelope values needs to be stored for delta-coding + in the next frame. The stored envelope is always represented with + the high frequency resolution. If the current envelope uses the + low frequency resolution, the energy value will be mapped to the + corresponding high-res bands. +*/ +static void mapLowResEnergyVal(FIXP_SGL currVal, /*!< current energy value */ + FIXP_SGL* prevData,/*!< pointer to previous data vector */ + int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequeny resolution */ +{ + if(res == 0) + { + if (offset >= 0) + { + if(index < offset) + prevData[index] = currVal; + else + { + prevData[2*index - offset] = currVal; + prevData[2*index+1 - offset] = currVal; + } + } + else + { + offset = -offset; + if (index < offset) + { + prevData[3*index] = currVal; + prevData[3*index+1] = currVal; + prevData[3*index+2] = currVal; + } + else + { + prevData[2*index + offset] = currVal; + prevData[2*index + 1 + offset] = currVal; + } + } + } + else + prevData[index] = currVal; +} + + + +/*! + \brief Convert raw envelope and noisefloor data to energy levels + + This function is being called by sbrDecoder_ParseElement() and provides two important algorithms: + + First the function decodes envelopes and noise floor levels as described in requantizeEnvelopeData() + and sbr_envelope_unmapping(). The function also implements concealment algorithms in case there are errors + within the sbr data. For both operations fractional arithmetic is used. + Therefore you might encounter different output values on your target + system compared to the reference implementation. +*/ +void +decodeSbrData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, /*!< pointer to left channel previous frame data */ + HANDLE_SBR_FRAME_DATA h_data_right, /*!< pointer to right channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right)/*!< pointer to right channel previous frame data */ +{ + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + int errLeft; + + /* Save previous energy values to be able to reuse them later for concealment. */ + FDKmemcpy (tempSfbNrgPrev, h_prev_data_left->sfb_nrg_prev, MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + + decodeEnvelope (hHeaderData, h_data_left, h_prev_data_left, h_prev_data_right); + decodeNoiseFloorlevels (hHeaderData, h_data_left, h_prev_data_left); + + if(h_data_right != NULL) { + errLeft = hHeaderData->frameErrorFlag; + decodeEnvelope (hHeaderData, h_data_right, h_prev_data_right, h_prev_data_left); + decodeNoiseFloorlevels (hHeaderData, h_data_right, h_prev_data_right); + + if (!errLeft && hHeaderData->frameErrorFlag) { + /* If an error occurs in the right channel where the left channel seemed ok, + we apply concealment also on the left channel. This ensures that the coupling + modes of both channels match and that we have the same number of envelopes in + coupling mode. + However, as the left channel has already been processed before, the resulting + energy levels are not the same as if the left channel had been concealed + during the first call of decodeEnvelope(). + */ + /* Restore previous energy values for concealment, because the values have been + overwritten by the first call of decodeEnvelope(). */ + FDKmemcpy (h_prev_data_left->sfb_nrg_prev, tempSfbNrgPrev, MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + /* Do concealment */ + decodeEnvelope (hHeaderData, h_data_left, h_prev_data_left, h_prev_data_right); + } + + if (h_data_left->coupling) { + sbr_envelope_unmapping (hHeaderData, h_data_left, h_data_right); + } + } + + /* Display the data for debugging: */ +} + + +/*! + \brief Convert from coupled channels to independent L/R data +*/ +static void +sbr_envelope_unmapping (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel */ + HANDLE_SBR_FRAME_DATA h_data_right) /*!< pointer to right channel */ +{ + int i; + FIXP_SGL tempL_m, tempR_m, tempRplus1_m, newL_m, newR_m; + SCHAR tempL_e, tempR_e, tempRplus1_e, newL_e, newR_e; + + + /* 1. Unmap (already dequantized) coupled envelope energies */ + + for (i = 0; i < h_data_left->nScaleFactors; i++) { + tempR_m = (FIXP_SGL)((LONG)h_data_right->iEnvelope[i] & MASK_M); + tempR_e = (SCHAR)((LONG)h_data_right->iEnvelope[i] & MASK_E); + + tempR_e -= (18 + NRG_EXP_OFFSET); /* -18 = ld(UNMAPPING_SCALE / h_data_right->nChannels) */ + tempL_m = (FIXP_SGL)((LONG)h_data_left->iEnvelope[i] & MASK_M); + tempL_e = (SCHAR)((LONG)h_data_left->iEnvelope[i] & MASK_E); + + tempL_e -= NRG_EXP_OFFSET; + + /* Calculate tempRight+1 */ + FDK_add_MantExp( tempR_m, tempR_e, + FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + FDK_divide_MantExp( tempL_m, tempL_e+1, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, + &newR_m, &newR_e ); + + if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } + + newL_m = FX_DBL2FX_SGL(fMult(tempR_m,newR_m)); + newL_e = tempR_e + newR_e; + + h_data_right->iEnvelope[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NRG_EXP_OFFSET) & MASK_E); + h_data_left->iEnvelope[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NRG_EXP_OFFSET) & MASK_E); + } + + /* 2. Dequantize and unmap coupled noise floor levels */ + + for (i = 0; i < hHeaderData->freqBandData.nNfb * h_data_left->frameInfo.nNoiseEnvelopes; i++) { + + tempL_e = (SCHAR)(6 - (LONG)h_data_left->sbrNoiseFloorLevel[i]); + tempR_e = (SCHAR)((LONG)h_data_right->sbrNoiseFloorLevel[i] - 12) /*SBR_ENERGY_PAN_OFFSET*/; + + /* Calculate tempR+1 */ + FDK_add_MantExp( FL2FXCONST_SGL(0.5f), 1+tempR_e, /* tempR */ + FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + /* Calculate 2*tempLeft/(tempR+1) */ + FDK_divide_MantExp( FL2FXCONST_SGL(0.5f), tempL_e+2, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, + &newR_m, &newR_e ); + + /* if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } */ + + /* L = tempR * R */ + newL_m = newR_m; + newL_e = newR_e + tempR_e; + h_data_right->sbrNoiseFloorLevel[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NOISE_EXP_OFFSET) & MASK_E); + h_data_left->sbrNoiseFloorLevel[i] = ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NOISE_EXP_OFFSET) & MASK_E); + } +} + + +/*! + \brief Simple alternative to the real SBR concealment + + If the real frameInfo is not available due to a frame loss, a replacement will + be constructed with 1 envelope spanning the whole frame (FIX-FIX). + The delta-coded energies are set to negative values, resulting in a fade-down. + In case of coupling, the balance-channel will move towards the center. +*/ +static void +leanSbrConcealment(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ + ) +{ + FIXP_SGL target; /* targeted level for sfb_nrg_prev during fade-down */ + FIXP_SGL step; /* speed of fade */ + int i; + + int currentStartPos = FDKmax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int currentStopPos = hHeaderData->numberTimeSlots; + + + /* Use some settings of the previous frame */ + h_sbr_data->ampResolutionCurrentFrame = h_prev_data->ampRes; + h_sbr_data->coupling = h_prev_data->coupling; + for(i=0;isbr_invf_mode[i] = h_prev_data->sbr_invf_mode[i]; + + /* Generate concealing control data */ + + h_sbr_data->frameInfo.nEnvelopes = 1; + h_sbr_data->frameInfo.borders[0] = currentStartPos; + h_sbr_data->frameInfo.borders[1] = currentStopPos; + h_sbr_data->frameInfo.freqRes[0] = 1; + h_sbr_data->frameInfo.tranEnv = -1; /* no transient */ + h_sbr_data->frameInfo.nNoiseEnvelopes = 1; + h_sbr_data->frameInfo.bordersNoise[0] = currentStartPos; + h_sbr_data->frameInfo.bordersNoise[1] = currentStopPos; + + h_sbr_data->nScaleFactors = hHeaderData->freqBandData.nSfb[1]; + + /* Generate fake envelope data */ + + h_sbr_data->domain_vec[0] = 1; + + if (h_sbr_data->coupling == COUPLING_BAL) { + target = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + step = (FIXP_SGL)DECAY_COUPLING; + } + else { + target = FL2FXCONST_SGL(0.0f); + step = (FIXP_SGL)DECAY; + } + if (hHeaderData->bs_info.ampResolution == 0) { + target <<= 1; + step <<= 1; + } + + for (i=0; i < h_sbr_data->nScaleFactors; i++) { + if (h_prev_data->sfb_nrg_prev[i] > target) + h_sbr_data->iEnvelope[i] = -step; + else + h_sbr_data->iEnvelope[i] = step; + } + + /* Noisefloor levels are always cleared ... */ + + h_sbr_data->domain_vec_noise[0] = 1; + for (i=0; i < hHeaderData->freqBandData.nNfb; i++) + h_sbr_data->sbrNoiseFloorLevel[i] = FL2FXCONST_SGL(0.0f); + + /* ... and so are the sines */ + FDKmemclear(h_sbr_data->addHarmonics, MAX_FREQ_COEFFS); +} + + +/*! + \brief Build reference energies and noise levels from bitstream elements +*/ +static void +decodeEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data, /*!< pointer to data of last frame */ + HANDLE_SBR_PREV_FRAME_DATA otherChannel /*!< other channel's last frame data */ + ) +{ + int i; + int fFrameError = hHeaderData->frameErrorFlag; + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + + if (!fFrameError) { + /* + To avoid distortions after bad frames, set the error flag if delta coding in time occurs. + However, SBR can take a little longer to come up again. + */ + if ( h_prev_data->frameErrorFlag ) { + if (h_sbr_data->domain_vec[0] != 0) { + fFrameError = 1; + } + } else { + /* Check that the previous stop position and the current start position match. + (Could be done in checkFrameInfo(), but the previous frame data is not available there) */ + if ( h_sbr_data->frameInfo.borders[0] != h_prev_data->stopPos - hHeaderData->numberTimeSlots ) { + /* Both the previous as well as the current frame are flagged to be ok, but they do not match! */ + if (h_sbr_data->domain_vec[0] == 1) { + /* Prefer concealment over delta-time coding between the mismatching frames */ + fFrameError = 1; + } + else { + /* Close the gap in time by triggering timeCompensateFirstEnvelope() */ + fFrameError = 1; + } + } + } + } + + + if (fFrameError) /* Error is detected */ + { + leanSbrConcealment(hHeaderData, + h_sbr_data, + h_prev_data); + + /* decode the envelope data to linear PCM */ + deltaToLinearPcmEnvelopeDecoding (hHeaderData, h_sbr_data, h_prev_data); + } + else /*Do a temporary dummy decoding and check that the envelope values are within limits */ + { + if (h_prev_data->frameErrorFlag) { + timeCompensateFirstEnvelope (hHeaderData, h_sbr_data, h_prev_data); + if (h_sbr_data->coupling != h_prev_data->coupling) { + /* + Coupling mode has changed during concealment. + The stored energy levels need to be converted. + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + /* Former Level-Channel will be used for both channels */ + if (h_prev_data->coupling == COUPLING_BAL) + h_prev_data->sfb_nrg_prev[i] = otherChannel->sfb_nrg_prev[i]; + /* Former L/R will be combined as the new Level-Channel */ + else if (h_sbr_data->coupling == COUPLING_LEVEL) + h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] + otherChannel->sfb_nrg_prev[i]) >> 1; + else if (h_sbr_data->coupling == COUPLING_BAL) + h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + } + } + } + FDKmemcpy (tempSfbNrgPrev, h_prev_data->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof (FIXP_SGL)); + + deltaToLinearPcmEnvelopeDecoding (hHeaderData, h_sbr_data, h_prev_data); + + fFrameError = checkEnvelopeData (hHeaderData, h_sbr_data, h_prev_data); + + if (fFrameError) + { + hHeaderData->frameErrorFlag = 1; + FDKmemcpy (h_prev_data->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof (FIXP_SGL)); + decodeEnvelope (hHeaderData, h_sbr_data, h_prev_data, otherChannel); + return; + } + } + + requantizeEnvelopeData (h_sbr_data, h_sbr_data->ampResolutionCurrentFrame); + + hHeaderData->frameErrorFlag = fFrameError; +} + + +/*! + \brief Verify that envelope energies are within the allowed range + \return 0 if all is fine, 1 if an envelope value was too high +*/ +static int +checkEnvelopeData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ + ) +{ + FIXP_SGL *iEnvelope = h_sbr_data->iEnvelope; + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + int i = 0, errorFlag = 0; + FIXP_SGL sbr_max_energy = + (h_sbr_data->ampResolutionCurrentFrame == 1) ? SBR_MAX_ENERGY : (SBR_MAX_ENERGY << 1); + + /* + Range check for current energies + */ + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + if (iEnvelope[i] > sbr_max_energy) { + errorFlag = 1; + } + if (iEnvelope[i] < FL2FXCONST_SGL(0.0f)) { + errorFlag = 1; + /* iEnvelope[i] = FL2FXCONST_SGL(0.0f); */ + } + } + + /* + Range check for previous energies + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + sfb_nrg_prev[i] = fixMax(sfb_nrg_prev[i], FL2FXCONST_SGL(0.0f)); + sfb_nrg_prev[i] = fixMin(sfb_nrg_prev[i], sbr_max_energy); + } + + return (errorFlag); +} + + +/*! + \brief Verify that the noise levels are within the allowed range + + The function is equivalent to checkEnvelopeData(). + When the noise-levels are being decoded, it is already too late for + concealment. Therefore the noise levels are simply limited here. +*/ +static void +limitNoiseLevels(HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data) /*!< pointer to current data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + + /* + Set range limits. The exact values depend on the coupling mode. + However this limitation is primarily intended to avoid unlimited + accumulation of the delta-coded noise levels. + */ + #define lowerLimit ((FIXP_SGL)0) /* lowerLimit actually refers to the _highest_ noise energy */ + #define upperLimit ((FIXP_SGL)35) /* upperLimit actually refers to the _lowest_ noise energy */ + + /* + Range check for current noise levels + */ + for (i = 0; i < h_sbr_data->frameInfo.nNoiseEnvelopes * nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] = fixMin(h_sbr_data->sbrNoiseFloorLevel[i], upperLimit); + h_sbr_data->sbrNoiseFloorLevel[i] = fixMax(h_sbr_data->sbrNoiseFloorLevel[i], lowerLimit); + } +} + + +/*! + \brief Compensate for the wrong timing that might occur after a frame error. +*/ +static void +timeCompensateFirstEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to actual data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to data of last frame */ +{ + int i, nScalefactors; + FRAME_INFO *pFrameInfo = &h_sbr_data->frameInfo; + UCHAR *nSfb = hHeaderData->freqBandData.nSfb; + int estimatedStartPos = h_prev_data->stopPos - hHeaderData->numberTimeSlots; + int refLen, newLen, shift; + FIXP_SGL deltaExp; + + /* Original length of first envelope according to bitstream */ + refLen = pFrameInfo->borders[1] - pFrameInfo->borders[0]; + /* Corrected length of first envelope (concealing can make the first envelope longer) */ + newLen = pFrameInfo->borders[1] - estimatedStartPos; + + if (newLen <= 0) { + /* An envelope length of <= 0 would not work, so we don't use it. + May occur if the previous frame was flagged bad due to a mismatch + of the old and new frame infos. */ + newLen = refLen; + estimatedStartPos = pFrameInfo->borders[0]; + } + + deltaExp = FDK_getNumOctavesDiv8(newLen, refLen); + + /* Shift by -3 to rescale ld-table, ampRes-1 to enable coarser steps */ + shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + h_sbr_data->ampResolutionCurrentFrame - 3); + deltaExp = deltaExp >> shift; + pFrameInfo->borders[0] = estimatedStartPos; + pFrameInfo->bordersNoise[0] = estimatedStartPos; + + if (h_sbr_data->coupling != COUPLING_BAL) { + nScalefactors = (pFrameInfo->freqRes[0]) ? nSfb[1] : nSfb[0]; + + for (i = 0; i < nScalefactors; i++) + h_sbr_data->iEnvelope[i] = h_sbr_data->iEnvelope[i] + deltaExp; + } +} + + + +/*! + \brief Convert each envelope value from logarithmic to linear domain + + Energy levels are transmitted in powers of 2, i.e. only the exponent + is extracted from the bitstream. + Therefore, normally only integer exponents can occur. However during + fading (in case of a corrupt bitstream), a fractional part can also + occur. The data in the array iEnvelope is shifted left by ENV_EXP_FRACT + compared to an integer representation so that numbers smaller than 1 + can be represented. + + This function calculates a mantissa corresponding to the fractional + part of the exponent for each reference energy. The array iEnvelope + is converted in place to save memory. Input and output data must + be interpreted differently, as shown in the below figure: + + \image html EnvelopeData.png + + The data is then used in calculateSbrEnvelope(). +*/ +static void +requantizeEnvelopeData (HANDLE_SBR_FRAME_DATA h_sbr_data, int ampResolution) +{ + int i; + FIXP_SGL mantissa; + int ampShift = 1 - ampResolution; + int exponent; + + /* In case that ENV_EXP_FRACT is changed to something else but 0 or 8, + the initialization of this array has to be adapted! + */ +#if ENV_EXP_FRACT + static const FIXP_SGL pow2[ENV_EXP_FRACT] = + { + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 1))), /* 0.7071 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 2))), /* 0.5946 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 3))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 4))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 5))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 6))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 7))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 8))) /* 0.5013 */ + }; + + int bit, mask; +#endif + + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + exponent = (LONG)h_sbr_data->iEnvelope[i]; + +#if ENV_EXP_FRACT + + exponent = exponent >> ampShift; + mantissa = 0.5f; + + /* Amplify mantissa according to the fractional part of the + exponent (result will be between 0.500000 and 0.999999) + */ + mask = 1; /* begin with lowest bit of exponent */ + + for ( bit=ENV_EXP_FRACT-1; bit>=0; bit-- ) { + if (exponent & mask) { + /* The current bit of the exponent is set, + multiply mantissa with the corresponding factor: */ + mantissa = (FIXP_SGL)( (mantissa * pow2[bit]) << 1); + } + /* Advance to next bit */ + mask = mask << 1; + } + + /* Make integer part of exponent right aligned */ + exponent = exponent >> ENV_EXP_FRACT; + +#else + /* In case of the high amplitude resolution, 1 bit of the exponent gets lost by the shift. + This will be compensated by a mantissa of 0.5*sqrt(2) instead of 0.5 if that bit is 1. */ + mantissa = (exponent & ampShift) ? FL2FXCONST_SGL(0.707106781186548f) : FL2FXCONST_SGL(0.5f); + exponent = exponent >> ampShift; +#endif + + /* + Mantissa was set to 0.5 (instead of 1.0, therefore increase exponent by 1). + Multiply by L=nChannels=64 by increasing exponent by another 6. + => Increase exponent by 7 + */ + exponent += 7 + NRG_EXP_OFFSET; + + /* Combine mantissa and exponent and write back the result */ + h_sbr_data->iEnvelope[i] = (FIXP_SGL)(((LONG)mantissa & MASK_M) | (exponent & MASK_E)); + + } +} + + +/*! + \brief Build new reference energies from old ones and delta coded data +*/ +static void +deltaToLinearPcmEnvelopeDecoding (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i, domain, no_of_bands, band, freqRes; + + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + FIXP_SGL *ptr_nrg = h_sbr_data->iEnvelope; + + int offset = 2 * hHeaderData->freqBandData.nSfb[0] - hHeaderData->freqBandData.nSfb[1]; + + for (i = 0; i < h_sbr_data->frameInfo.nEnvelopes; i++) { + domain = h_sbr_data->domain_vec[i]; + freqRes = h_sbr_data->frameInfo.freqRes[i]; + + FDK_ASSERT(freqRes >= 0 && freqRes <= 1); + + no_of_bands = hHeaderData->freqBandData.nSfb[freqRes]; + + FDK_ASSERT(no_of_bands < (64)); + + if (domain == 0) + { + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, 0, freqRes); + ptr_nrg++; + for (band = 1; band < no_of_bands; band++) + { + *ptr_nrg = *ptr_nrg + *(ptr_nrg-1); + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } + else + { + for (band = 0; band < no_of_bands; band++) + { + *ptr_nrg = *ptr_nrg + sfb_nrg_prev[indexLow2High(offset, band, freqRes)]; + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } + } +} + + +/*! + \brief Build new noise levels from old ones and delta coded data +*/ +static void +decodeNoiseFloorlevels (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + int nNoiseFloorEnvelopes = h_sbr_data->frameInfo.nNoiseEnvelopes; + + /* Decode first noise envelope */ + + if (h_sbr_data->domain_vec_noise[0] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[0]; + for (i = 1; i < nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } + else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] += h_prev_data->prevNoiseLevel[i]; + } + } + + /* If present, decode the second noise envelope + Note: nNoiseFloorEnvelopes can only be 1 or 2 */ + + if (nNoiseFloorEnvelopes > 1) { + if (h_sbr_data->domain_vec_noise[1] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[nNfb]; + for (i = nNfb + 1; i < 2*nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } + else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i + nNfb] += h_sbr_data->sbrNoiseFloorLevel[i]; + } + } + } + + limitNoiseLevels(hHeaderData, h_sbr_data); + + /* Update prevNoiseLevel with the last noise envelope */ + for (i = 0; i < nNfb; i++) + h_prev_data->prevNoiseLevel[i] = h_sbr_data->sbrNoiseFloorLevel[i + nNfb*(nNoiseFloorEnvelopes-1)]; + + + /* Requantize the noise floor levels in COUPLING_OFF-mode */ + if (!h_sbr_data->coupling) { + int nf_e; + + for (i = 0; i < nNoiseFloorEnvelopes*nNfb; i++) { + nf_e = 6 - (LONG)h_sbr_data->sbrNoiseFloorLevel[i] + 1 + NOISE_EXP_OFFSET; + /* +1 to compensate for a mantissa of 0.5 instead of 1.0 */ + + h_sbr_data->sbrNoiseFloorLevel[i] = + (FIXP_SGL)( ((LONG)FL2FXCONST_SGL(0.5f)) + /* mantissa */ + (nf_e & MASK_E) ); /* exponent */ + + } + } +} diff --git a/libSBRdec/src/env_dec.h b/libSBRdec/src/env_dec.h new file mode 100644 index 00000000..6f6dae37 --- /dev/null +++ b/libSBRdec/src/env_dec.h @@ -0,0 +1,101 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope decoding +*/ +#ifndef __ENV_DEC_H +#define __ENV_DEC_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +void decodeSbrData (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, + HANDLE_SBR_FRAME_DATA h_data_right, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right); + + +#endif diff --git a/libSBRdec/src/env_extr.cpp b/libSBRdec/src/env_extr.cpp new file mode 100644 index 00000000..4d53a135 --- /dev/null +++ b/libSBRdec/src/env_extr.cpp @@ -0,0 +1,1398 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope extraction + The functions provided by this module are mostly called by applySBR(). After it is + determined that there is valid SBR data, sbrGetHeaderData() might be called if the current + SBR data contains an \ref SBR_HEADER_ELEMENT as opposed to a \ref SBR_STANDARD_ELEMENT. This function + may return various error codes as defined in #SBR_HEADER_STATUS . Most importantly it returns HEADER_RESET when decoder + settings need to be recalculated according to the SBR specifications. In that case applySBR() + will initiatite the required re-configuration. + + The header data is stored in a #SBR_HEADER_DATA structure. + + The actual SBR data for the current frame is decoded into SBR_FRAME_DATA stuctures by sbrGetChannelPairElement() + [for stereo streams] and sbrGetSingleChannelElement() [for mono streams]. There is no fractional arithmetic involved. + + Once the information is extracted, the data needs to be further prepared before the actual decoding process. + This is done in decodeSbrData(). + + \sa Description of buffer management in applySBR(). \ref documentationOverview + +

About the SBR data format:

+ + Each frame includes SBR data (side chain information), and can be either the \ref SBR_HEADER_ELEMENT or the \ref SBR_STANDARD_ELEMENT. + Parts of the data can be protected by a CRC checksum. + + \anchor SBR_HEADER_ELEMENT

The SBR_HEADER_ELEMENT

+ + The SBR_HEADER_ELEMENT can be transmitted with every frame, however, it typically is send every second or so. It contains fundamental + information such as SBR sampling frequency and frequency range as well as control signals that do not require frequent changes. It also + includes the \ref SBR_STANDARD_ELEMENT. + + Depending on the changes between the information in a current SBR_HEADER_ELEMENT and the previous SBR_HEADER_ELEMENT, the SBR decoder might need + to be reset and reconfigured (e.g. new tables need to be calculated). + + \anchor SBR_STANDARD_ELEMENT

The SBR_STANDARD_ELEMENT

+ + This data can be subdivided into "side info" and "raw data", where side info is defined as signals needed to decode the raw data + and some decoder tuning signals. Raw data is referred to as PCM and Huffman coded envelope and noise floor estimates. The side info also + includes information about the time-frequency grid for the current frame. + + \sa \ref documentationOverview +*/ + +#include "env_extr.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "huff_dec.h" + + +#include "psbitdec.h" + +#define DRM_PARAMETRIC_STEREO 0 +#define EXTENSION_ID_PS_CODING 2 + + +static int extractFrameInfo (HANDLE_FDK_BITSTREAM hBs, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + const UINT nrOfChannels, + const UINT flags + ); + + +static int sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs, + const UINT flags); + +static void sbrGetDirectionControlData (HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs); + +static void sbrGetNoiseFloorData (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs); + +static int checkFrameInfo (FRAME_INFO *pFrameInfo, int numberOfTimeSlots, int overlap, int timeStep); + +SBR_ERROR +initHeaderData ( + HANDLE_SBR_HEADER_DATA hHeaderData, + const int sampleRateIn, + const int sampleRateOut, + const int samplesPerFrame, + const UINT flags + ) +{ + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + SBR_ERROR sbrError = SBRDEC_OK; + int numAnalysisBands; + + if ( sampleRateIn == sampleRateOut ) { + hHeaderData->sbrProcSmplRate = sampleRateOut<<1; + numAnalysisBands = 32; + } else { + hHeaderData->sbrProcSmplRate = sampleRateOut; + if ( (sampleRateOut>>1) == sampleRateIn) { + /* 1:2 */ + numAnalysisBands = 32; + } else if ( (sampleRateOut>>2) == sampleRateIn ) { + /* 1:4 */ + numAnalysisBands = 32; + } else if ( (sampleRateOut*3)>>3 == (sampleRateIn*8)>>3 ) { + /* 3:8, 3/4 core frame length */ + numAnalysisBands = 24; + } else { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + } + + /* Fill in default values first */ + hHeaderData->syncState = SBR_NOT_INITIALIZED; + hHeaderData->status = 0; + hHeaderData->frameErrorFlag = 0; + + hHeaderData->bs_info.ampResolution = 1; + hHeaderData->bs_info.xover_band = 0; + hHeaderData->bs_info.sbr_preprocessing = 0; + + hHeaderData->bs_data.startFreq = 5; + hHeaderData->bs_data.stopFreq = 0; + hHeaderData->bs_data.freqScale = 2; + hHeaderData->bs_data.alterScale = 1; + hHeaderData->bs_data.noise_bands = 2; + hHeaderData->bs_data.limiterBands = 2; + hHeaderData->bs_data.limiterGains = 2; + hHeaderData->bs_data.interpolFreq = 1; + hHeaderData->bs_data.smoothingLength = 1; + + hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2; + + /* Setup pointers to frequency band tables */ + hFreq->freqBandTable[0] = hFreq->freqBandTableLo; + hFreq->freqBandTable[1] = hFreq->freqBandTableHi; + + /* Patch some entries */ + if (sampleRateOut > 24000) { /* Trigger an error if SBR is going to be processed without */ + hHeaderData->bs_data.startFreq = 7; /* having read these frequency values from bit stream before. */ + hHeaderData->bs_data.stopFreq = 3; + } + + /* One SBR timeslot corresponds to the amount of samples equal to the amount of analysis bands, divided by the timestep. */ + hHeaderData->numberTimeSlots = (samplesPerFrame/numAnalysisBands) >> (hHeaderData->timeStep - 1); + if (hHeaderData->numberTimeSlots > (16)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + } + + hHeaderData->numberOfAnalysisBands = numAnalysisBands; + +bail: + return sbrError; +} + + +/*! + \brief Initialize the SBR_PREV_FRAME_DATA struct +*/ +void +initSbrPrevFrameData (HANDLE_SBR_PREV_FRAME_DATA h_prev_data, /*!< handle to struct SBR_PREV_FRAME_DATA */ + int timeSlots) /*!< Framelength in SBR-timeslots */ +{ + int i; + + /* Set previous energy and noise levels to 0 for the case + that decoding starts in the middle of a bitstream */ + for (i=0; i < MAX_FREQ_COEFFS; i++) + h_prev_data->sfb_nrg_prev[i] = (FIXP_DBL)0; + for (i=0; i < MAX_NOISE_COEFFS; i++) + h_prev_data->prevNoiseLevel[i] = (FIXP_DBL)0; + for (i=0; i < MAX_INVF_BANDS; i++) + h_prev_data->sbr_invf_mode[i] = INVF_OFF; + + h_prev_data->stopPos = timeSlots; + h_prev_data->coupling = COUPLING_OFF; + h_prev_data->ampRes = 0; +} + + +/*! + \brief Read header data from bitstream + + \return error status - 0 if ok +*/ +SBR_HEADER_STATUS +sbrGetHeaderData (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_FDK_BITSTREAM hBs, + const UINT flags, + const int fIsSbrData) +{ + SBR_HEADER_DATA_BS *pBsData; + SBR_HEADER_DATA_BS lastHeader; + SBR_HEADER_DATA_BS_INFO lastInfo; + int headerExtra1=0, headerExtra2=0; + + /* Copy SBR bit stream header to temporary header */ + lastHeader = hHeaderData->bs_data; + lastInfo = hHeaderData->bs_info; + + /* Read new header from bitstream */ + { + pBsData = &hHeaderData->bs_data; + } + + { + hHeaderData->bs_info.ampResolution = FDKreadBits (hBs, 1); + } + + pBsData->startFreq = FDKreadBits (hBs, 4); + pBsData->stopFreq = FDKreadBits (hBs, 4); + + { + hHeaderData->bs_info.xover_band = FDKreadBits (hBs, 3); + FDKreadBits (hBs, 2); + } + + headerExtra1 = FDKreadBits (hBs, 1); + headerExtra2 = FDKreadBits (hBs, 1); + + /* Handle extra header information */ + if( headerExtra1) + { + pBsData->freqScale = FDKreadBits (hBs, 2); + pBsData->alterScale = FDKreadBits (hBs, 1); + pBsData->noise_bands = FDKreadBits (hBs, 2); + } + else { + pBsData->freqScale = 2; + pBsData->alterScale = 1; + pBsData->noise_bands = 2; + } + + if (headerExtra2) { + pBsData->limiterBands = FDKreadBits (hBs, 2); + pBsData->limiterGains = FDKreadBits (hBs, 2); + pBsData->interpolFreq = FDKreadBits (hBs, 1); + pBsData->smoothingLength = FDKreadBits (hBs, 1); + } + else { + pBsData->limiterBands = 2; + pBsData->limiterGains = 2; + pBsData->interpolFreq = 1; + pBsData->smoothingLength = 1; + } + + /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */ + if(hHeaderData->syncState < SBR_HEADER || + lastHeader.startFreq != pBsData->startFreq || + lastHeader.stopFreq != pBsData->stopFreq || + lastHeader.freqScale != pBsData->freqScale || + lastHeader.alterScale != pBsData->alterScale || + lastHeader.noise_bands != pBsData->noise_bands || + lastInfo.xover_band != hHeaderData->bs_info.xover_band) { + return HEADER_RESET; /* New settings */ + } + + return HEADER_OK; +} + +/*! + \brief Get missing harmonics parameters (only used for AAC+SBR) + + \return error status - 0 if ok +*/ +int +sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs) +{ + int i, bitsRead = 0; + + int flag = FDKreadBits(hBs,1); + bitsRead++; + + if(flag){ + for(i=0;ifreqBandData.nSfb[1];i++){ + hFrameData->addHarmonics[i] = FDKreadBits (hBs, 1 ); + bitsRead++; + } + } + else { + for(i=0; iaddHarmonics[i] = 0; + } + return(bitsRead); +} + +/*! + \brief Reads extension data from the bitstream + + The bitstream format allows up to 4 kinds of extended data element. + Extended data may contain several elements, each identified by a 2-bit-ID. + So far, no extended data elements are defined hence the first 2 parameters + are unused. The data should be skipped in order to update the number + of read bits for the consistency check in applySBR(). +*/ +static int extractExtendedData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< handle to SBR header */ + HANDLE_FDK_BITSTREAM hBs /*!< Handle to the bit buffer */ + ,HANDLE_PS_DEC hParametricStereoDec /*!< Parametric Stereo Decoder */ + ) { + INT nBitsLeft; + int extended_data; + int i, frameOk = 1; + + + extended_data = FDKreadBits(hBs, 1); + + if (extended_data) { + int cnt; + int bPsRead = 0; + + cnt = FDKreadBits(hBs, 4); + if (cnt == (1<<4)-1) + cnt += FDKreadBits(hBs, 8); + + + nBitsLeft = 8 * cnt; + + /* sanity check for cnt */ + if (nBitsLeft > (INT)FDKgetValidBits(hBs)) { + /* limit nBitsLeft */ + nBitsLeft = (INT)FDKgetValidBits(hBs); + /* set frame error */ + frameOk = 0; + } + + while (nBitsLeft > 7) { + int extension_id = FDKreadBits(hBs, 2); + nBitsLeft -= 2; + + switch(extension_id) { + + + + case EXTENSION_ID_PS_CODING: + + /* Read PS data from bitstream */ + + if (hParametricStereoDec != NULL) { + if(bPsRead && !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot].mpeg.bPsHeaderValid) { + cnt = nBitsLeft >> 3; /* number of remaining bytes */ + for (i=0; i> 3; /* number of remaining bytes */ + for (i=0; icoupling = COUPLING_OFF; + + { + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits(hBs, 4); + } + } + } + + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits (hBs, 1); /* bs_coupling */ + } + + /* + Grid control + */ + if ( !extractFrameInfo ( hBs, hHeaderData, hFrameData, 1, flags) ) + return 0; + + if ( !checkFrameInfo (&hFrameData->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + return 0; + + + /* + Fetch domain vectors (time or frequency direction for delta-coding) + */ + sbrGetDirectionControlData (hFrameData, hBs); + + for (i=0; ifreqBandData.nInvfBands; i++) { + hFrameData->sbr_invf_mode[i] = + (INVF_MODE) FDKreadBits (hBs, 2); + } + + + + /* raw data */ + if ( !sbrGetEnvelope (hHeaderData, hFrameData, hBs, flags) ) + return 0; + + + sbrGetNoiseFloorData (hHeaderData, hFrameData, hBs); + + sbrGetSyntheticCodedData(hHeaderData, hFrameData, hBs); + + { + /* sbr extended data */ + if (! extractExtendedData( + hHeaderData, + hBs + ,hParametricStereoDec + )) { + return 0; + } + } + + return 1; +} + + + +/*! + \brief Read bitstream elements of a channel pair + \return SbrFrameOK +*/ +int +sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameDataLeft, /*!< Dynamic control data for first channel */ + HANDLE_SBR_FRAME_DATA hFrameDataRight,/*!< Dynamic control data for second channel */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, + const int overlap ) +{ + int i, bit; + + + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + FDKreadBits(hBs, 4); + } + + /* Read coupling flag */ + bit = FDKreadBits (hBs, 1); + + if (bit) { + hFrameDataLeft->coupling = COUPLING_LEVEL; + hFrameDataRight->coupling = COUPLING_BAL; + } + else { + hFrameDataLeft->coupling = COUPLING_OFF; + hFrameDataRight->coupling = COUPLING_OFF; + } + + + /* + Grid control + */ + if ( !extractFrameInfo (hBs, hHeaderData, hFrameDataLeft, 2, flags) ) + return 0; + + if ( !checkFrameInfo (&hFrameDataLeft->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + return 0; + + if (hFrameDataLeft->coupling) { + FDKmemcpy (&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo, sizeof(FRAME_INFO)); + hFrameDataRight->ampResolutionCurrentFrame = hFrameDataLeft->ampResolutionCurrentFrame; + } + else { + if ( !extractFrameInfo (hBs, hHeaderData, hFrameDataRight, 2, flags) ) + return 0; + + if ( !checkFrameInfo (&hFrameDataRight->frameInfo, hHeaderData->numberTimeSlots, overlap, hHeaderData->timeStep) ) + return 0; + } + + /* + Fetch domain vectors (time or frequency direction for delta-coding) + */ + sbrGetDirectionControlData (hFrameDataLeft, hBs); + sbrGetDirectionControlData (hFrameDataRight, hBs); + + for (i=0; ifreqBandData.nInvfBands; i++) { + hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); + } + + if (hFrameDataLeft->coupling) { + for (i=0; ifreqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i]; + } + + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataLeft, hBs, flags) ) { + return 0; + } + + sbrGetNoiseFloorData (hHeaderData, hFrameDataLeft, hBs); + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataRight, hBs, flags) ) { + return 0; + } + } + else { + + for (i=0; ifreqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE) FDKreadBits (hBs, 2); + } + + + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataLeft, hBs, flags) ) + return 0; + + if ( !sbrGetEnvelope (hHeaderData, hFrameDataRight, hBs, flags) ) + return 0; + + sbrGetNoiseFloorData (hHeaderData, hFrameDataLeft, hBs); + + } + sbrGetNoiseFloorData (hHeaderData, hFrameDataRight, hBs); + + sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs); + sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs); + + { + if (! extractExtendedData( + hHeaderData, + hBs + ,NULL + ) ) { + return 0; + } + } + + return 1; +} + + + + +/*! + \brief Read direction control data from bitstream +*/ +void +sbrGetDirectionControlData (HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs) /*!< handle to struct BIT_BUF */ +{ + int i; + + for (i = 0; i < h_frame_data->frameInfo.nEnvelopes; i++) { + h_frame_data->domain_vec[i] = FDKreadBits (hBs, 1); + } + + for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { + h_frame_data->domain_vec_noise[i] = FDKreadBits (hBs, 1); + } +} + + + +/*! + \brief Read noise-floor-level data from bitstream +*/ +void +sbrGetNoiseFloorData (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs) /*!< handle to struct BIT_BUF */ +{ + int i,j; + int delta; + COUPLING_MODE coupling; + int noNoiseBands = hHeaderData->freqBandData.nNfb; + + Huffman hcb_noiseF; + Huffman hcb_noise; + int envDataTableCompFactor; + + coupling = h_frame_data->coupling; + + + /* + Select huffman codebook depending on coupling mode + */ + if (coupling == COUPLING_BAL) { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T; + hcb_noiseF = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F" */ + envDataTableCompFactor = 1; + } + else { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T; + hcb_noiseF = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F" */ + envDataTableCompFactor = 0; + } + + /* + Read raw noise-envelope data + */ + for (i=0; iframeInfo.nNoiseEnvelopes; i++) { + + + if (h_frame_data->domain_vec_noise[i] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->sbrNoiseFloorLevel[i*noNoiseBands] = + (FIXP_SGL) (((int)FDKreadBits (hBs, 5)) << envDataTableCompFactor); + } + else { + h_frame_data->sbrNoiseFloorLevel[i*noNoiseBands] = + (FIXP_SGL) (int)FDKreadBits (hBs, 5); + } + + for (j = 1; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noiseF, hBs); + h_frame_data->sbrNoiseFloorLevel[i*noNoiseBands+j] = (FIXP_SGL) (delta << envDataTableCompFactor); + } + } + else { + for (j = 0; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noise, hBs); + h_frame_data->sbrNoiseFloorLevel[i*noNoiseBands+j] = (FIXP_SGL) (delta << envDataTableCompFactor); + } + } + } +} + + +/*! + \brief Read envelope data from bitstream +*/ +static int +sbrGetEnvelope (HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags) +{ + int i, j; + UCHAR no_band[MAX_ENVELOPES]; + int delta = 0; + int offset = 0; + COUPLING_MODE coupling = h_frame_data->coupling; + int ampRes = hHeaderData->bs_info.ampResolution; + int nEnvelopes = h_frame_data->frameInfo.nEnvelopes; + int envDataTableCompFactor; + int start_bits, start_bits_balance; + Huffman hcb_t, hcb_f; + + h_frame_data->nScaleFactors = 0; + + if ( (h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1) ) { + if (flags & SBRDEC_ELD_GRID) + ampRes = h_frame_data->ampResolutionCurrentFrame; + else + ampRes = 0; + } + h_frame_data->ampResolutionCurrentFrame = ampRes; + + /* + Set number of bits for first value depending on amplitude resolution + */ + if(ampRes == 1) + { + start_bits = 6; + start_bits_balance = 5; + } + else + { + start_bits = 7; + start_bits_balance = 6; + } + + /* + Calculate number of values for each envelope and alltogether + */ + for (i = 0; i < nEnvelopes; i++) { + no_band[i] = hHeaderData->freqBandData.nSfb[h_frame_data->frameInfo.freqRes[i]]; + h_frame_data->nScaleFactors += no_band[i]; + } + if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) + return 0; + + /* + Select Huffman codebook depending on coupling mode and amplitude resolution + */ + if (coupling == COUPLING_BAL) { + envDataTableCompFactor = 1; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F; + } + else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; + } + } + else { + envDataTableCompFactor = 0; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F; + } + else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; + } + } + + /* + Now read raw envelope data + */ + for (j = 0, offset = 0; j < nEnvelopes; j++) { + + + if (h_frame_data->domain_vec[j] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL) (( (int)FDKreadBits(hBs, start_bits_balance)) << envDataTableCompFactor); + } + else { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL) (int)FDKreadBits (hBs, start_bits); + } + } + + for (i = (1 - h_frame_data->domain_vec[j]); i < no_band[j]; i++) { + + if (h_frame_data->domain_vec[j] == 0) { + delta = DecodeHuffmanCW(hcb_f, hBs); + } + else { + delta = DecodeHuffmanCW(hcb_t, hBs); + } + + h_frame_data->iEnvelope[offset + i] = (FIXP_SGL) (delta << envDataTableCompFactor); + } + offset += no_band[j]; + } + +#if ENV_EXP_FRACT + /* Convert from int to scaled fract (ENV_EXP_FRACT bits for the fractional part) */ + for (i = 0; i < h_frame_data->nScaleFactors; i++) { + h_frame_data->iEnvelope[i] <<= ENV_EXP_FRACT; + } +#endif + + return 1; +} + + +//static const FRAME_INFO v_frame_info1_8 = { 0, 1, {0, 8}, {1}, -1, 1, {0, 8} }; +static const FRAME_INFO v_frame_info2_8 = { 0, 2, {0, 4, 8}, {1, 1}, -1, 2, {0, 4, 8} }; +static const FRAME_INFO v_frame_info4_8 = { 0, 4, {0, 2, 4, 6, 8}, {1, 1, 1, 1}, -1, 2, {0, 4, 8} }; + +/***************************************************************************/ +/*! + \brief Generates frame info for FIXFIXonly frame class used for low delay version + + \return nothing + ****************************************************************************/ + static void generateFixFixOnly ( FRAME_INFO *hSbrFrameInfo, + int tranPosInternal, + int numberTimeSlots + ) +{ + int nEnv, i, tranIdx; + const int *pTable; + + switch (numberTimeSlots) { + case 8: + pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal]; + break; + case 15: + pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal]; + break; + case 16: + pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal]; + break; + default: + FDK_ASSERT(0); + /* in case assertion checks are disabled, force a definite memory fault at first access */ + pTable = NULL; + break; + } + + /* look number of envelopes in table */ + nEnv = pTable[0]; + /* look up envelope distribution in table */ + for (i=1; iborders[i] = pTable[i+2]; + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + hSbrFrameInfo->nEnvelopes = nEnv; + + /* transient idx */ + tranIdx = hSbrFrameInfo->tranEnv = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[tranIdx?tranIdx:1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2) */ + hSbrFrameInfo->nNoiseEnvelopes = 2; +} + +/*! + \brief Extracts LowDelaySBR control data from the bitstream. + + \return zero for bitstream error, one for correct. +*/ +static int +extractLowDelayGrid (HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< contains the FRAME_INFO struct to be filled */ + int timeSlots + ) +{ + FRAME_INFO * pFrameInfo = &h_frame_data->frameInfo; + INT numberTimeSlots = hHeaderData->numberTimeSlots; + INT temp = 0, k; + + /* FIXFIXonly framing case */ + h_frame_data->frameInfo.frameClass = 0; + + /* get the transient position from the bitstream */ + switch (timeSlots){ + case 8: + /* 3bit transient position (temp={0;..;7}) */ + temp = FDKreadBits( hBitBuf, 3); + break; + + case 16: + case 15: + /* 4bit transient position (temp={0;..;15}) */ + temp = FDKreadBits( hBitBuf, 4); + break; + + default: + return 0; + } + + /* calculate borders according to the transient position */ + generateFixFixOnly ( pFrameInfo, + temp, + numberTimeSlots + ); + + /* decode freq res: */ + for (k = 0; k < pFrameInfo->nEnvelopes; k++) { + pFrameInfo->freqRes[k] = (UCHAR) FDKreadBits (hBitBuf, 1); /* f = F [1 bits] */ + } + + + return 1; +} + +/*! + \brief Extract the frame information (structure FRAME_INFO) from the bitstream + \return Zero for bitstream error, one for correct. +*/ +int +extractFrameInfo ( HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the frame-info will be stored */ + const UINT nrOfChannels, + const UINT flags + ) +{ + FRAME_INFO * pFrameInfo = &h_frame_data->frameInfo; + int numberTimeSlots = hHeaderData->numberTimeSlots; + int pointer_bits = 0, nEnv = 0, b = 0, border, i, n = 0, + k, p, aL, aR, nL, nR, + temp = 0, staticFreqRes; + UCHAR frameClass; + + if (flags & SBRDEC_ELD_GRID) { + /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames and the LowDelayGrid for transient Frames */ + frameClass = FDKreadBits (hBs, 1); /* frameClass = [1 bit] */ + if ( frameClass == 1 ) { + /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal SBR-Grid for FIXIFX */ + /* extract the AACLD-Sbr-Grid */ + pFrameInfo->frameClass = frameClass; + extractLowDelayGrid (hBs, hHeaderData, h_frame_data, numberTimeSlots); + return 1; + } + } else + { + frameClass = FDKreadBits (hBs, 2); /* frameClass = C [2 bits] */ + } + + + switch (frameClass) { + case 0: + temp = FDKreadBits (hBs, 2); /* E [2 bits ] */ + nEnv = (int) (1 << temp); /* E -> e */ + + if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1)) + h_frame_data->ampResolutionCurrentFrame = FDKreadBits( hBs, 1); /* new ELD Syntax 07-11-09 */ + + staticFreqRes = FDKreadBits (hBs, 1); + + { + if (nEnv > MAX_ENVELOPES_HEAAC) + return 0; + } + + b = nEnv + 1; + switch (nEnv) { + case 1: + switch (numberTimeSlots) { + case 15: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_15, sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_16, sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (numberTimeSlots) { + case 15: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_15, sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_16, sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (numberTimeSlots) { + case 15: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_15, sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_16, sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 8: +#if (MAX_ENVELOPES >= 8) + switch (numberTimeSlots) { + case 15: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_15, sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy (pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_16, sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; +#else + return 0; +#endif + } + /* Apply correct freqRes (High is default) */ + if (!staticFreqRes) { + for (i = 0; i < nEnv ; i++) + pFrameInfo->freqRes[i] = 0; + } + + break; + case 1: + case 2: + temp = FDKreadBits (hBs, 2); /* A [2 bits] */ + + n = FDKreadBits (hBs, 2); /* n = N [2 bits] */ + + nEnv = n + 1; /* # envelopes */ + b = nEnv + 1; /* # borders */ + + break; + } + + switch (frameClass) { + case 1: + /* Decode borders: */ + pFrameInfo->borders[0] = 0; /* first border */ + border = temp + numberTimeSlots; /* A -> aR */ + i = b-1; /* frame info index for last border */ + pFrameInfo->borders[i] = border; /* last border */ + + for (k = 0; k < n; k++) { + temp = FDKreadBits (hBs, 2);/* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n+1)); + p = FDKreadBits (hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > n+1) + return 0; + + pFrameInfo->tranEnv = p ? n + 2 - p : -1; + + + /* Decode freq res: */ + for (k = n; k >= 0; k--) { + pFrameInfo->freqRes[k] = FDKreadBits (hBs, 1); /* f = F [1 bits] */ + } + + + /* Calculate noise floor middle border: */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + else + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv]; + + break; + + case 2: + /* Decode borders: */ + border = temp; /* A -> aL */ + pFrameInfo->borders[0] = border; /* first border */ + + for (k = 1; k <= n; k++) { + temp = FDKreadBits (hBs, 2);/* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + pFrameInfo->borders[k] = numberTimeSlots; /* last border */ + + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n+1)); + p = FDKreadBits (hBs, pointer_bits); /* p = P [pointer_bits bits] */ + if (p > n+1) + return 0; + + if (p == 0 || p == 1) + pFrameInfo->tranEnv = -1; + else + pFrameInfo->tranEnv = p - 1; + + + + /* Decode freq res: */ + for (k = 0; k <= n; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + + + /* Calculate noise floor middle border: */ + switch (p) { + case 0: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[1]; + break; + case 1: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + break; + default: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv]; + break; + } + + break; + + case 3: + /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */ + + aL = FDKreadBits (hBs, 2); /* AL [2 bits], AL -> aL */ + + aR = FDKreadBits (hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */ + + nL = FDKreadBits (hBs, 2); /* nL = NL [2 bits] */ + + nR = FDKreadBits (hBs, 2); /* nR = NR [2 bits] */ + + + + /*------------------------------------------------------------------------- + Calculate help variables + --------------------------------------------------------------------------*/ + + /* general: */ + nEnv = nL + nR + 1; /* # envelopes */ + if (nEnv > MAX_ENVELOPES) + return 0; + b = nEnv + 1; /* # borders */ + + + + /*------------------------------------------------------------------------- + Decode envelopes + --------------------------------------------------------------------------*/ + + + /* L-borders: */ + border = aL; /* first border */ + pFrameInfo->borders[0] = border; + + for (k = 1; k <= nL; k++) { + temp = FDKreadBits (hBs, 2);/* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + + + /* R-borders: */ + border = aR; /* last border */ + i = nEnv; + + pFrameInfo->borders[i] = border; + + for (k = 0; k < nR; k++) { + temp = FDKreadBits (hBs, 2);/* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + + /* decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL+nR+1)); + p = FDKreadBits (hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > nL+nR+1) + return 0; + + pFrameInfo->tranEnv = p ? b - p : -1; + + + + /* decode freq res: */ + for (k = 0; k < nEnv; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + + + /*------------------------------------------------------------------------- + Decode noise floors + --------------------------------------------------------------------------*/ + pFrameInfo->bordersNoise[0] = aL; + + if (nEnv == 1) { + /* 1 noise floor envelope: */ + pFrameInfo->bordersNoise[1] = aR; + } + else { + /* 2 noise floor envelopes */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[nEnv - 1]; + else + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv]; + pFrameInfo->bordersNoise[2] = aR; + } + break; + } + + + /* + Store number of envelopes, noise floor envelopes and frame class + */ + pFrameInfo->nEnvelopes = nEnv; + + if (nEnv == 1) + pFrameInfo->nNoiseEnvelopes = 1; + else + pFrameInfo->nNoiseEnvelopes = 2; + + pFrameInfo->frameClass = frameClass; + + if (pFrameInfo->frameClass == 2 || pFrameInfo->frameClass == 1) { + /* calculate noise floor first and last borders: */ + pFrameInfo->bordersNoise[0] = pFrameInfo->borders[0]; + pFrameInfo->bordersNoise[pFrameInfo->nNoiseEnvelopes] = pFrameInfo->borders[nEnv]; + } + + + return 1; +} + + +/*! + \brief Check if the frameInfo vector has reasonable values. + \return Zero for error, one for correct +*/ +static int +checkFrameInfo (FRAME_INFO * pFrameInfo, /*!< pointer to frameInfo */ + int numberOfTimeSlots, /*!< QMF time slots per frame */ + int overlap, /*!< Amount of overlap QMF time slots */ + int timeStep) /*!< QMF slots to SBR slots step factor */ +{ + int maxPos,i,j; + int startPos; + int stopPos; + int tranEnv; + int startPosNoise; + int stopPosNoise; + int nEnvelopes = pFrameInfo->nEnvelopes; + int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes; + + if(nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) + return 0; + + if(nNoiseEnvelopes > MAX_NOISE_ENVELOPES) + return 0; + + startPos = pFrameInfo->borders[0]; + stopPos = pFrameInfo->borders[nEnvelopes]; + tranEnv = pFrameInfo->tranEnv; + startPosNoise = pFrameInfo->bordersNoise[0]; + stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes]; + + if (overlap < 0 || overlap > (6)) { + return 0; + } + if (timeStep < 1 || timeStep > 2) { + return 0; + } + maxPos = numberOfTimeSlots + (overlap/timeStep); + + /* Check that the start and stop positions of the frame are reasonable values. */ + if( (startPos < 0) || (startPos >= stopPos) ) + return 0; + if( startPos > maxPos-numberOfTimeSlots ) /* First env. must start in or directly after the overlap buffer */ + return 0; + if( stopPos < numberOfTimeSlots ) /* One complete frame must be ready for output after processing */ + return 0; + if(stopPos > maxPos) + return 0; + + /* Check that the start border for every envelope is strictly later in time */ + for(i=0;iborders[i] >= pFrameInfo->borders[i+1]) + return 0; + } + + /* Check that the envelope to be shortened is actually among the envelopes */ + if(tranEnv>nEnvelopes) + return 0; + + + /* Check the noise borders */ + if(nEnvelopes==1 && nNoiseEnvelopes>1) + return 0; + + if(startPos != startPosNoise || stopPos != stopPosNoise) + return 0; + + + /* Check that the start border for every noise-envelope is strictly later in time*/ + for(i=0; ibordersNoise[i] >= pFrameInfo->bordersNoise[i+1]) + return 0; + } + + /* Check that every noise border is the same as an envelope border*/ + for(i=0; ibordersNoise[i]; + + for(j=0; jborders[j] == startPosNoise) + break; + } + if(j==nEnvelopes) + return 0; + } + + return 1; +} diff --git a/libSBRdec/src/env_extr.h b/libSBRdec/src/env_extr.h new file mode 100644 index 00000000..0518ea91 --- /dev/null +++ b/libSBRdec/src/env_extr.h @@ -0,0 +1,324 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope extraction prototypes +*/ + +#ifndef __ENVELOPE_EXTRACTION_H +#define __ENVELOPE_EXTRACTION_H + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" +#include "lpp_tran.h" + +#include "psdec.h" + +#define ENV_EXP_FRACT 0 +/*!< Shift raw envelope data to support fractional numbers. + Can be set to 8 instead of 0 to enhance accuracy during concealment. + This is not required for conformance and #requantizeEnvelopeData() will + become more expensive. +*/ + +#define EXP_BITS 6 +/*!< Size of exponent-part of a pseudo float envelope value (should be at least 6). + The remaining bits in each word are used for the mantissa (should be at least 10). + This format is used in the arrays iEnvelope[] and sbrNoiseFloorLevel[] + in the FRAME_DATA struct which must fit in a certain part of the output buffer + (See buffer management in sbr_dec.cpp). + Exponents and mantissas could also be stored in separate arrays. + Accessing the exponent or the mantissa would be simplified and the masks #MASK_E + resp. #MASK_M would no longer be required. +*/ + +#define MASK_M (((1 << (FRACT_BITS - EXP_BITS)) - 1) << EXP_BITS) /*!< Mask for extracting the mantissa of a pseudo float envelope value */ +#define MASK_E ((1 << EXP_BITS) - 1) /*!< Mask for extracting the exponent of a pseudo float envelope value */ + +#define SIGN_EXT ( ((SCHAR)-1) ^ MASK_E) /*!< a CHAR-constant with all bits above our sign-bit set */ +#define ROUNDING ( (FIXP_SGL)(1<<(EXP_BITS-1)) ) /*!< 0.5-offset for rounding the mantissa of a pseudo-float envelope value */ +#define NRG_EXP_OFFSET 16 /*!< Will be added to the reference energy's exponent to prevent negative numbers */ +#define NOISE_EXP_OFFSET 38 /*!< Will be added to the noise level exponent to prevent negative numbers */ + +typedef enum +{ + HEADER_NOT_PRESENT, + HEADER_ERROR, + HEADER_OK, + HEADER_RESET +} +SBR_HEADER_STATUS; + +typedef enum +{ + SBR_NOT_INITIALIZED = 0, + UPSAMPLING = 1, + SBR_HEADER = 2, + SBR_ACTIVE = 3 +} +SBR_SYNC_STATE; + + +typedef enum +{ + COUPLING_OFF = 0, + COUPLING_LEVEL, + COUPLING_BAL +} +COUPLING_MODE; + +typedef struct +{ + UCHAR nSfb[2]; /*!< Number of SBR-bands for low and high freq-resolution */ + UCHAR nNfb; /*!< Actual number of noise bands to read from the bitstream*/ + UCHAR numMaster; /*!< Number of SBR-bands in v_k_master */ + UCHAR lowSubband; /*!< QMF-band where SBR frequency range starts */ + UCHAR highSubband; /*!< QMF-band where SBR frequency range ends */ + UCHAR limiterBandTable[MAX_NUM_LIMITERS+1]; /*!< Limiter band table. */ + UCHAR noLimiterBands; /*!< Number of limiter bands. */ + UCHAR nInvfBands; /*!< Number of bands for inverse filtering */ + UCHAR *freqBandTable[2]; /*!< Pointers to freqBandTableLo and freqBandTableHi */ + UCHAR freqBandTableLo[MAX_FREQ_COEFFS/2+1]; + /*!< Mapping of SBR bands to QMF bands for low frequency resolution */ + UCHAR freqBandTableHi[MAX_FREQ_COEFFS+1]; + /*!< Mapping of SBR bands to QMF bands for high frequency resolution */ + UCHAR freqBandTableNoise[MAX_NOISE_COEFFS+1]; + /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR v_k_master[MAX_FREQ_COEFFS+1]; + /*!< Master BandTable which freqBandTable is derived from */ +} +FREQ_BAND_DATA; + +typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; + +#define SBRDEC_ELD_GRID 1 +#define SBRDEC_SYNTAX_SCAL 2 +#define SBRDEC_SYNTAX_USAC 4 +#define SBRDEC_SYNTAX_RSVD50 8 +#define SBRDEC_LOW_POWER 16 /* Flag indicating that Low Power QMF mode shall be used. */ +#define SBRDEC_PS_DECODED 32 /* Flag indicating that PS was decoded and rendered. */ +#define SBRDEC_LD_MPS_QMF 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_SYNTAX_DRM 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ +#define SBRDEC_DOWNSAMPLE 8192 /* Flag indicating that the downsampling mode is used. */ +#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ +#define SBRDEC_FORCE_RESET 32768 /* Flag is used to force a reset of all elements in use. */ + +#define SBRDEC_HDR_STAT_RESET 1 +#define SBRDEC_HDR_STAT_UPDATE 2 + +typedef struct { + UCHAR ampResolution; /*!< Amplitude resolution of envelope values (0: 1.5dB, 1: 3dB) */ + UCHAR xover_band; /*!< Start index in #v_k_master[] used for dynamic crossover frequency */ + UCHAR sbr_preprocessing; /*!< SBR prewhitening flag. */ +} SBR_HEADER_DATA_BS_INFO; + +typedef struct { + /* Changes in these variables causes a reset of the decoder */ + UCHAR startFreq; /*!< Index for SBR start frequency */ + UCHAR stopFreq; /*!< Index for SBR highest frequency */ + UCHAR freqScale; /*!< 0: linear scale, 1-3 logarithmic scales */ + UCHAR alterScale; /*!< Flag for coarser frequency resolution */ + UCHAR noise_bands; /*!< Noise bands per octave, read from bitstream*/ + + /* don't require reset */ + UCHAR limiterBands; /*!< Index for number of limiter bands per octave */ + UCHAR limiterGains; /*!< Index to select gain limit */ + UCHAR interpolFreq; /*!< Select gain calculation method (1: per QMF channel, 0: per SBR band) */ + UCHAR smoothingLength; /*!< Smoothing of gains over time (0: on 1: off) */ + +} SBR_HEADER_DATA_BS; + +typedef struct +{ + SBR_SYNC_STATE syncState; /*!< The current initialization status of the header */ + + UCHAR status; /*!< Flags field used for signaling a reset right before the processing starts and an update from config (e.g. ASC). */ + UCHAR frameErrorFlag; /*!< Frame data valid flag. CAUTION: This variable will be overwritten by the flag stored in the element structure. + This is necessary because of the frame delay. There it might happen that different slots use the same header. */ + UCHAR numberTimeSlots; /*!< AAC: 16,15 */ + UCHAR numberOfAnalysisBands; /*!< Number of QMF analysis bands */ + UCHAR timeStep; /*!< Time resolution of SBR in QMF-slots */ + UINT sbrProcSmplRate; /*!< SBR processing sampling frequency (!= OutputSamplingRate) + (always: CoreSamplingRate * UpSamplingFactor; even in single rate mode) */ + + SBR_HEADER_DATA_BS bs_data; /*!< current SBR header. */ + SBR_HEADER_DATA_BS_INFO bs_info; /*!< SBR info. */ + + FREQ_BAND_DATA freqBandData; /*!< Pointer to struct #FREQ_BAND_DATA */ +} +SBR_HEADER_DATA; + +typedef SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + + +typedef struct +{ + UCHAR frameClass; /*!< Select grid type */ + UCHAR nEnvelopes; /*!< Number of envelopes */ + UCHAR borders[MAX_ENVELOPES+1]; /*!< Envelope borders (in SBR-timeslots, e.g. mp3PRO: 0..11) */ + UCHAR freqRes[MAX_ENVELOPES]; /*!< Frequency resolution for each envelope (0=low, 1=high) */ + SCHAR tranEnv; /*!< Transient envelope, -1 if none */ + UCHAR nNoiseEnvelopes; /*!< Number of noise envelopes */ + UCHAR bordersNoise[MAX_NOISE_ENVELOPES+1];/*!< borders of noise envelopes */ +} +FRAME_INFO; + + +typedef struct +{ + FIXP_SGL sfb_nrg_prev[MAX_FREQ_COEFFS]; /*!< Previous envelope (required for differential-coded values) */ + FIXP_SGL prevNoiseLevel[MAX_NOISE_COEFFS]; /*!< Previous noise envelope (required for differential-coded values) */ + COUPLING_MODE coupling; /*!< Stereo-mode of previous frame */ + INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Previous strength of filtering in transposer */ + UCHAR ampRes; /*!< Previous amplitude resolution (0: 1.5dB, 1: 3dB) */ + UCHAR stopPos; /*!< Position in time where last envelope ended */ + UCHAR frameErrorFlag; /*!< Previous frame status */ +} +SBR_PREV_FRAME_DATA; + +typedef SBR_PREV_FRAME_DATA *HANDLE_SBR_PREV_FRAME_DATA; + + +typedef struct +{ + int nScaleFactors; /*!< total number of scalefactors in frame */ + + FRAME_INFO frameInfo; /*!< time grid for current frame */ + UCHAR domain_vec[MAX_ENVELOPES]; /*!< Bitfield containing direction of delta-coding for each envelope (0:frequency, 1:time) */ + UCHAR domain_vec_noise[MAX_NOISE_ENVELOPES]; /*!< Same as above, but for noise envelopes */ + + INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Strength of filtering in transposer */ + COUPLING_MODE coupling; /*!< Stereo-mode */ + int ampResolutionCurrentFrame; /*!< Amplitude resolution of envelope values (0: 1.5dB, 1: 3dB) */ + + UCHAR addHarmonics[MAX_FREQ_COEFFS]; /*!< Flags for synthetic sine addition */ + + FIXP_SGL iEnvelope[MAX_NUM_ENVELOPE_VALUES]; /*!< Envelope data */ + FIXP_SGL sbrNoiseFloorLevel[MAX_NUM_NOISE_VALUES]; /*!< Noise envelope data */ +} +SBR_FRAME_DATA; + +typedef SBR_FRAME_DATA *HANDLE_SBR_FRAME_DATA; + +void initSbrPrevFrameData (HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + int timeSlots); + + +int sbrGetSingleChannelElement (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBitBuf, + HANDLE_PS_DEC hParametricStereoDec, + const UINT flags, + const int overlap + ); + +int sbrGetChannelPairElement (HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameDataLeft, + HANDLE_SBR_FRAME_DATA hFrameDataRight, + HANDLE_FDK_BITSTREAM hBitBuf, + const UINT flags, + const int overlap); + +SBR_HEADER_STATUS +sbrGetHeaderData (HANDLE_SBR_HEADER_DATA headerData, + HANDLE_FDK_BITSTREAM hBitBuf, + const UINT flags, + const int fIsSbrData); + +/*! + \brief Initialize SBR header data + + Copy default values to the header data struct and patch some entries + depending on the core codec. +*/ +SBR_ERROR +initHeaderData ( + HANDLE_SBR_HEADER_DATA hHeaderData, + const int sampleRateIn, + const int sampleRateOut, + const int samplesPerFrame, + const UINT flags + ); +#endif diff --git a/libSBRdec/src/huff_dec.cpp b/libSBRdec/src/huff_dec.cpp new file mode 100644 index 00000000..31d686d2 --- /dev/null +++ b/libSBRdec/src/huff_dec.cpp @@ -0,0 +1,120 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Huffman Decoder +*/ + +#include "huff_dec.h" + +/***************************************************************************/ +/*! + \brief Decodes one huffman code word + + Reads bits from the bitstream until a valid codeword is found. + The table entries are interpreted either as index to the next entry + or - if negative - as the codeword. + + \return decoded value + + \author + +****************************************************************************/ +int +DecodeHuffmanCW (Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to Bitbuffer */ +{ + SCHAR index = 0; + int value, bit; + + while (index >= 0) { + bit = FDKreadBits (hBs, 1); + index = h[index][bit]; + } + + value = index+64; /* Add offset */ + + + return value; +} diff --git a/libSBRdec/src/huff_dec.h b/libSBRdec/src/huff_dec.h new file mode 100644 index 00000000..54436587 --- /dev/null +++ b/libSBRdec/src/huff_dec.h @@ -0,0 +1,100 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Huffman Decoder +*/ +#ifndef __HUFF_DEC_H +#define __HUFF_DEC_H + +#include "sbrdecoder.h" +#include "FDK_bitstream.h" + +typedef const SCHAR (*Huffman)[2]; + +int +DecodeHuffmanCW (Huffman h, + HANDLE_FDK_BITSTREAM hBitBuf); + +#endif diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp new file mode 100644 index 00000000..117e7390 --- /dev/null +++ b/libSBRdec/src/lpp_tran.cpp @@ -0,0 +1,986 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Low Power Profile Transposer, + This module provides the transposer. The main entry point is lppTransposer(). The function generates + high frequency content by copying data from the low band (provided by core codec) into the high band. + This process is also referred to as "patching". The function also implements spectral whitening by means of + inverse filtering based on LPC coefficients. + + Together with the QMF filterbank the transposer can be tested using a supplied test program. See main_audio.cpp for details. + This module does use fractional arithmetic and the accuracy of the computations has an impact on the overall sound quality. + The module also needs to take into account the different scaling of spectral data. + + \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview +*/ + +#include "lpp_tran.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" +#include "autocorr2nd.h" + + + +#if defined(__arm__) +#include "arm/lpp_tran_arm.cpp" +#endif + + + +#define LPC_SCALE_FACTOR 2 + + +/*! + * + * \brief Get bandwidth expansion factor from filtering level + * + * Returns a filter parameter (bandwidth expansion factor) depending on + * the desired filtering level signalled in the bitstream. + * When switching the filtering level from LOW to OFF, an additional + * level is being inserted to achieve a smooth transition. + */ + +#ifndef FUNCTION_mapInvfMode +static FIXP_DBL +mapInvfMode (INVF_MODE mode, + INVF_MODE prevMode, + WHITENING_FACTORS whFactors) +{ + switch (mode) { + case INVF_LOW_LEVEL: + if(prevMode == INVF_OFF) + return whFactors.transitionLevel; + else + return whFactors.lowLevel; + + case INVF_MID_LEVEL: + return whFactors.midLevel; + + case INVF_HIGH_LEVEL: + return whFactors.highLevel; + + default: + if(prevMode == INVF_LOW_LEVEL) + return whFactors.transitionLevel; + else + return whFactors.off; + } +} +#endif /* #ifndef FUNCTION_mapInvfMode */ + +/*! + * + * \brief Perform inverse filtering level emphasis + * + * Retrieve bandwidth expansion factor and apply smoothing for each filter band + * + */ + +#ifndef FUNCTION_inverseFilteringLevelEmphasis +static void +inverseFilteringLevelEmphasis(HANDLE_SBR_LPP_TRANS hLppTrans,/*!< Handle of lpp transposer */ + UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ + FIXP_DBL * bwVector /*!< Resulting filtering levels */ + ) +{ + for(int i = 0; i < nInvfBands; i++) { + FIXP_DBL accu; + FIXP_DBL bwTmp = mapInvfMode (sbr_invf_mode[i], + sbr_invf_mode_prev[i], + hLppTrans->pSettings->whFactors); + + if(bwTmp < hLppTrans->bwVectorOld[i]) { + accu = fMultDiv2(FL2FXCONST_DBL(0.75f),bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.25f),hLppTrans->bwVectorOld[i]); + } + else { + accu = fMultDiv2(FL2FXCONST_DBL(0.90625f),bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.09375f),hLppTrans->bwVectorOld[i]); + } + + if (accu < FL2FXCONST_DBL(0.015625f)>>1) + bwVector[i] = FL2FXCONST_DBL(0.0f); + else + bwVector[i] = fixMin(accu<<1,FL2FXCONST_DBL(0.99609375f)); + } +} +#endif /* #ifndef FUNCTION_inverseFilteringLevelEmphasis */ + +/* Resulting autocorrelation determinant exponent */ +#define ACDET_EXP (2*(DFRACT_BITS+sbrScaleFactor->lb_scale+10-ac.det_scale)) +#define AC_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR) +#define ALPHA_EXP (-sbrScaleFactor->lb_scale+LPC_SCALE_FACTOR+1) +/* Resulting transposed QMF values exponent 16 bit normalized samplebits assumed. */ +#define QMFOUT_EXP ((SAMPLE_BITS-15)-sbrScaleFactor->lb_scale) + +/*! + * + * \brief Perform transposition by patching of subband samples. + * This function serves as the main entry point into the module. The function determines the areas for the + * patching process (these are the source range as well as the target range) and implements spectral whitening + * by means of inverse filtering. The function autoCorrelation2nd() is an auxiliary function for calculating the + * LPC coefficients for the filtering. The actual calculation of the LPC coefficients and the implementation + * of the filtering are done as part of lppTransposer(). + * + * Note that the filtering is done on all available QMF subsamples, whereas the patching is only done on those QMF + * subsamples that will be used in the next QMF synthesis. The filtering is also implemented before the patching + * includes further dependencies on parameters from the SBR data. + * + */ + +void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband samples (source) */ + + FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of subband samples (source) */ + const int useLP, + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ + ) +{ + INT bwIndex[MAX_NUM_PATCHES]; + FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + int patch; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i=0, a1i=0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + FIXP_DBL k1, k1_below=0, k1_below2=0; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comLowBandScale; + int ovLowBandShift; + int lowBandShift; +/* int ovHighBandShift;*/ + int targetStopBand; + + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete highband + (because the last patch would be too short). + Possible optimization: Clearing bands up to usb would be sufficient here. */ + targetStopBand = patchParam[pSettings->noOfPatches-1].targetStartBand + + patchParam[pSettings->noOfPatches-1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + if (!useLP) { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + } else + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + } + + /* init bwIndex for each patch */ + FDKmemclear(bwIndex, pSettings->noOfPatches*sizeof(INT)); + + /* + Calc common low band scale factor + */ + comLowBandScale = fixMin(sbrScaleFactor->ov_lb_scale,sbrScaleFactor->lb_scale); + + ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; + lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + /* outer loop over bands to do analysis only once for each band */ + + if (!useLP) { + start = pSettings->lbStartPatching; + stop = pSettings->lbStopPatching; + } else + { + start = fixMax(1, pSettings->lbStartPatching - 2); + stop = patchParam[0].targetStartBand; + } + + + for ( loBand = start; loBand < stop; loBand++ ) { + + FIXP_DBL lowBandReal[(((1024)/(32))+(6))+LPC_ORDER]; + FIXP_DBL *plowBandReal = lowBandReal; + FIXP_DBL **pqmfBufferReal = qmfBufferReal; + FIXP_DBL lowBandImag[(((1024)/(32))+(6))+LPC_ORDER]; + FIXP_DBL *plowBandImag = lowBandImag; + FIXP_DBL **pqmfBufferImag = qmfBufferImag; + int resetLPCCoeffs=0; + int dynamicScale = DFRACT_BITS-1-LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for(i=0;ilpcFilterStatesReal[i][loBand]; + if (!useLP) + *plowBandImag++ = hLppTrans->lpcFilterStatesImag[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + if (!useLP) { + for(i=0;inCols+pSettings->overlap;i++){ + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandImag++ = (*pqmfBufferImag++)[loBand]; + } + } else + { + /* pSettings->overlap is always even */ + FDK_ASSERT((pSettings->overlap & 1) == 0); + + for(i=0;i<((pSettings->overlap+pSettings->nCols)>>1);i++) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + if (pSettings->nCols & 1) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandReal, LPC_ORDER+pSettings->overlap) + ovLowBandShift); + dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift); + if (!useLP) { + dynamicScale = fixMin(dynamicScale, getScalefactor(lowBandImag, LPC_ORDER+pSettings->overlap) + ovLowBandShift); + dynamicScale = fixMin(dynamicScale, getScalefactor(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols) + lowBandShift); + } + dynamicScale = fixMax(0, dynamicScale-1); /* one additional bit headroom to prevent -1.0 */ + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift); + + if (!useLP) { + scaleValues(&lowBandImag[0], LPC_ORDER+pSettings->overlap, dynamicScale-ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER+pSettings->overlap], pSettings->nCols, dynamicScale-lowBandShift); + } + + + if (!useLP) { + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal+LPC_ORDER, lowBandImag+LPC_ORDER, autoCorrLength); + } + else + { + acDetScale += autoCorr2nd_real(&ac, lowBandReal+LPC_ORDER, autoCorrLength); + } + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2*(comLowBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale>126 ) { + resetLPCCoeffs = 1; + } + + + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) + alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp,absTmp,absDet; + + absDet = fixp_abs(ac.det); + + if (!useLP) { + tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) - + ( (fMultDiv2(ac.r01i,ac.r12i) + fMultDiv2(ac.r02r,ac.r11r)) >> (LPC_SCALE_FACTOR-1) ); + } else + { + tmp = ( fMultDiv2(ac.r01r,ac.r12r) >> (LPC_SCALE_FACTOR-1) ) - + ( fMultDiv2(ac.r02r,ac.r11r) >> (LPC_SCALE_FACTOR-1) ); + } + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale+ac.det_scale; + + if ( (scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL>>scale) ) { + resetLPCCoeffs = 1; + } + else { + alphar[1] = FX_DBL2FX_SGL(scaleValue(result,scale)); + if((tmp> (LPC_SCALE_FACTOR-1) ) + + ( (fMultDiv2(ac.r01r,ac.r12i) - (FIXP_DBL)fMultDiv2(ac.r02i,ac.r11r)) >> (LPC_SCALE_FACTOR-1) ) ; + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale+ac.det_scale; + + if ( (scale > 0) && (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL>>scale) ) { + resetLPCCoeffs = 1; + } + else { + alphai[1] = FX_DBL2FX_SGL(scaleValue(result,scale)); + if((tmp=0 */ + FIXP_DBL tmp,absTmp; + + if (!useLP) { + tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) + + (fMultDiv2(alphar[1],ac.r12r) + fMultDiv2(alphai[1],ac.r12i)); + } else + { + if(ac.r01r>=FL2FXCONST_DBL(0.0f)) + tmp = (ac.r01r>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r); + else + tmp = -((-ac.r01r)>>(LPC_SCALE_FACTOR+1)) + fMultDiv2(alphar[1],ac.r12r); + } + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r>>1)) { + resetLPCCoeffs=1; + } + else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1)); + + if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r>(LPC_SCALE_FACTOR+1)) + + (fMultDiv2(alphai[1],ac.r12r) - fMultDiv2(alphar[1],ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r>>1)) { + resetLPCCoeffs=1; + } + else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValue(result,scale+1)); + if((tmp>FL2FX_DBL(0.0f)) ^ (ac.r11r= FL2FXCONST_DBL(0.5f) ) + resetLPCCoeffs=1; + if( (fMultDiv2(alphar[1],alphar[1]) + fMultDiv2(alphai[1],alphai[1])) >= FL2FXCONST_DBL(0.5f) ) + resetLPCCoeffs=1; + } + + if(resetLPCCoeffs){ + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) + { + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + } + + if (useLP) + { + + /* Aliasing detection */ + if(ac.r11r==FL2FXCONST_DBL(0.0f)) { + k1 = FL2FXCONST_DBL(0.0f); + } + else { + if ( fixp_abs(ac.r01r) >= fixp_abs(ac.r11r) ) { + if ( fMultDiv2(ac.r01r,ac.r11r) < FL2FX_DBL(0.0f)) { + k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/; + }else { + /* Since this value is squared later, it must not ever become -1.0f. */ + k1 = (FIXP_DBL)(MINVAL_DBL+1) /*FL2FXCONST_SGL(-1.0f)*/; + } + } + else { + INT scale; + FIXP_DBL result = fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); + k1 = scaleValue(result,scale); + + if(!((ac.r01r 1){ + /* Check if the gain should be locked */ + FIXP_DBL deg = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); + degreeAlias[loBand] = FL2FXCONST_DBL(0.0f); + if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))){ + if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand-1] = deg; + } + } + else if ( k1_below2 > FL2FXCONST_DBL(0.0f) ) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))){ + if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand-1] = deg; + } + } + else if ( k1_below2 < FL2FXCONST_DBL(0.0f) ) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + } + /* remember k1 values of the 2 QMF channels below the current channel */ + k1_below2 = k1_below; + k1_below = k1; + } + + patch = 0; + + while ( patch < pSettings->noOfPatches ) { /* inner loop over every patch */ + + int hiBand = loBand + patchParam[patch].targetBandOffs; + + if ( loBand < patchParam[patch].sourceStartBand + || loBand >= patchParam[patch].sourceStopBand + //|| hiBand >= hLppTrans->pSettings->noChannels + ) { + /* Lowband not in current patch - proceed */ + patch++; + continue; + } + + FDK_ASSERT( hiBand < (64) ); + + /* bwIndex[patch] is already initialized with value from previous band inside this patch */ + while (hiBand >= pSettings->bwBorders[bwIndex[patch]]) + bwIndex[patch]++; + + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]); + + a0r = FX_DBL2FX_SGL(fMult(bw,alphar[0])); /* Apply current bandwidth expansion factor */ + + + if (!useLP) + a0i = FX_DBL2FX_SGL(fMult(bw,alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw,alphar[1])); + if (!useLP) + a1i = FX_DBL2FX_SGL(fMult(bw,alphai[1])); + + + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + + if ( bw <= FL2FXCONST_SGL(0.0f) ) { + if (!useLP) { + int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); + for(i = startSample; i < stopSample; i++ ) { + qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale; + qmfBufferImag[i][hiBand] = lowBandImag[LPC_ORDER+i]>>descale; + } + } else + { + int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); + for(i = startSample; i < stopSample; i++ ) { + qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER+i]>>descale; + } + } + } + else { /* bw <= 0 */ + + if (!useLP) { + int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); +#ifdef FUNCTION_LPPTRANSPOSER_func1 + lppTransposer_func1(lowBandReal+LPC_ORDER+startSample,lowBandImag+LPC_ORDER+startSample, + qmfBufferReal+startSample,qmfBufferImag+startSample, + stopSample-startSample, (int) hiBand, + dynamicScale,descale, + a0r, a0i, a1r, a1i); +#else + for(i = startSample; i < stopSample; i++ ) { + FIXP_DBL accu1, accu2; + + accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) - fMultDiv2(a0i,lowBandImag[LPC_ORDER+i-1]) + + fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]) - fMultDiv2(a1i,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale; + accu2 = (fMultDiv2(a0i,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a0r,lowBandImag[LPC_ORDER+i-1]) + + fMultDiv2(a1i,lowBandReal[LPC_ORDER+i-2]) + fMultDiv2(a1r,lowBandImag[LPC_ORDER+i-2]))>>dynamicScale; + + qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1); + qmfBufferImag[i][hiBand] = (lowBandImag[LPC_ORDER+i]>>descale) + (accu2<<1); + } +#endif + } else + { + int descale = fixMin(DFRACT_BITS-1, (LPC_SCALE_FACTOR+dynamicScale)); + + FDK_ASSERT(dynamicScale >= 0); + for(i = startSample; i < stopSample; i++ ) { + FIXP_DBL accu1; + + accu1 = (fMultDiv2(a0r,lowBandReal[LPC_ORDER+i-1]) + fMultDiv2(a1r,lowBandReal[LPC_ORDER+i-2]))>>dynamicScale; + + qmfBufferReal[i][hiBand] = (lowBandReal[LPC_ORDER+i]>>descale) + (accu1<<1); + } + } + } /* bw <= 0 */ + + patch++; + + } /* inner loop over patches */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + + } /* outer loop over bands (loBand) */ + + if (useLP) + { + for ( loBand = pSettings->lbStartPatching; loBand < pSettings->lbStopPatching; loBand++ ) { + patch = 0; + while ( patch < pSettings->noOfPatches ) { + + UCHAR hiBand = loBand + patchParam[patch].targetBandOffs; + + if ( loBand < patchParam[patch].sourceStartBand + || loBand >= patchParam[patch].sourceStopBand + || hiBand >= (64) /* Highband out of range (biterror) */ + ) { + /* Lowband not in current patch or highband out of range (might be caused by biterrors)- proceed */ + patch++; + continue; + } + + if(hiBand != patchParam[patch].targetStartBand) + degreeAlias[hiBand] = degreeAlias[loBand]; + + patch++; + } + }/* end for loop */ + } + + for (i = 0; i < nInvfBands; i++ ) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comLowBandScale-(LPC_SCALE_FACTOR); + +} + +/*! + * + * \brief Initialize one low power transposer instance + * + * + */ +SBR_ERROR +createLppTransposer (HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ + TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ + const int highBandStartSb, /*!< ? */ + UCHAR *v_k_master, /*!< Master table */ + const int numMaster, /*!< Valid entries in master table */ + const int usb, /*!< Highband area stop subband */ + const int timeSlots, /*!< Number of time slots */ + const int nCols, /*!< Number of colums (codec qmf bank) */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + const int noNoiseBands, /*!< Number of noise bands */ + UINT fs, /*!< Sample Frequency */ + const int chan, /*!< Channel number */ + const int overlap + ) +{ + /* FB inverse filtering settings */ + hs->pSettings = pSettings; + + pSettings->nCols = nCols; + pSettings->overlap = overlap; + + switch (timeSlots) { + + case 15: + case 16: + break; + + default: + return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ + } + + if (chan==0) { + /* Init common data only once */ + hs->pSettings->nCols = nCols; + + return resetLppTransposer (hs, + highBandStartSb, + v_k_master, + numMaster, + noiseBandTable, + noNoiseBands, + usb, + fs); + } + return SBRDEC_OK; +} + + +static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, UCHAR direction) +{ + int index; + + if( goalSb <= v_k_master[0] ) + return v_k_master[0]; + + if( goalSb >= v_k_master[numMaster] ) + return v_k_master[numMaster]; + + if(direction) { + index = 0; + while( v_k_master[index] < goalSb ) { + index++; + } + } else { + index = numMaster; + while( v_k_master[index] > goalSb ) { + index--; + } + } + + return v_k_master[index]; +} + + +/*! + * + * \brief Reset memory for one lpp transposer instance + * + * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error + */ +SBR_ERROR +resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR highBandStartSb, /*!< High band area: start subband */ + UCHAR *v_k_master, /*!< Master table */ + UCHAR numMaster, /*!< Valid entries in master table */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR noNoiseBands, /*!< Number of noise bands */ + UCHAR usb, /*!< High band area: stop subband */ + UINT fs /*!< SBR output sampling frequency */ + ) +{ + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + int i, patch; + int targetStopBand; + int sourceStartBand; + int patchDistance; + int numBandsInPatch; + + int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling terms*/ + int xoverOffset = highBandStartSb - lsb; /* Calculate distance in QMF bands between k0 and kx */ + int startFreqHz; + + int desiredBorder; + + usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with float code). */ + + /* + * Plausibility check + */ + + if ( lsb - SHIFT_START_SB < 4 ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + + /* + * Initialize the patching parameter + */ + /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */ + desiredBorder = (((2048000*2) / fs) + 1) >> 1; + + desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = SHIFT_START_SB + xoverOffset; + targetStopBand = lsb + xoverOffset; /* upperBand */ + + /* Even (odd) numbered channel must be patched to even (odd) numbered channel */ + patch = 0; + while(targetStopBand < usb) { + + /* Too many patches? + Allow MAX_NUM_PATCHES+1 patches here. + we need to check later again, since patch might be the highest patch + AND contain less than 3 bands => actual number of patches will be reduced by 1. + */ + if (patch > MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + patchParam[patch].guardStartBand = targetStopBand; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = desiredBorder - targetStopBand; /* Get the desired range of the patch */ + + if ( numBandsInPatch >= lsb - sourceStartBand ) { + /* Desired number bands are not available -> patch whole source range */ + patchDistance = targetStopBand - sourceStartBand; /* Get the targetOffset */ + patchDistance = patchDistance & ~1; /* Rounding off odd numbers and make all even */ + numBandsInPatch = lsb - (targetStopBand - patchDistance); /* Update number of bands to be patched */ + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + /* Desired number bands are available -> get the minimal even patching distance */ + patchDistance = numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ + patchDistance = (patchDistance + 1) & ~1; /* Rounding up odd numbers and make all even */ + + if (numBandsInPatch > 0) { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + patch++; + } + + /* All patches but first */ + sourceStartBand = SHIFT_START_SB; + + /* Check if we are close to desiredBorder */ + if( desiredBorder - targetStopBand < 3) /* MPEG doc */ + { + desiredBorder = usb; + } + + } + + patch--; + + /* If highest patch contains less than three subband: skip it */ + if ( (patch>0) && (patchParam[patch].numBandsInPatch < 3) ) { + patch--; + targetStopBand = patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; + } + + /* now check if we don't have one too many */ + if (patch >= MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + pSettings->noOfPatches = patch + 1; + + /* Check lowest and highest source subband */ + pSettings->lbStartPatching = targetStopBand; + pSettings->lbStopPatching = 0; + for ( patch = 0; patch < pSettings->noOfPatches; patch++ ) { + pSettings->lbStartPatching = fixMin( pSettings->lbStartPatching, patchParam[patch].sourceStartBand ); + pSettings->lbStopPatching = fixMax( pSettings->lbStopPatching, patchParam[patch].sourceStopBand ); + } + + for(i = 0 ; i < noNoiseBands; i++){ + pSettings->bwBorders[i] = noiseBandTable[i+1]; + } + + /* + * Choose whitening factors + */ + + startFreqHz = ( (lsb + xoverOffset)*fs ) >> 7; /* Shift does a division by 2*(64) */ + + for( i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++ ) + { + if( startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) + break; + } + i--; + + pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0]; + pSettings->whFactors.transitionLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][1]; + pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2]; + pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3]; + pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4]; + + return SBRDEC_OK; +} diff --git a/libSBRdec/src/lpp_tran.h b/libSBRdec/src/lpp_tran.h new file mode 100644 index 00000000..003a5474 --- /dev/null +++ b/libSBRdec/src/lpp_tran.h @@ -0,0 +1,242 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Low Power Profile Transposer, +*/ + +#ifndef _LPP_TRANS_H +#define _LPP_TRANS_H + +#include "sbrdecoder.h" +#include "qmf.h" + +/* + Common +*/ +#define QMF_OUT_SCALE 8 + +/* + Env-Adjust +*/ +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS) +#define MAX_NUM_LIMITERS 12 + +/* Set MAX_ENVELOPES to the largest value of all supported BSFORMATs + by overriding MAX_ENVELOPES in the correct order: */ +#define MAX_ENVELOPES_HEAAC 5 +#define MAX_ENVELOPES MAX_ENVELOPES_HEAAC + +#define MAX_FREQ_COEFFS 48 +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) + +#define MAX_GAIN_EXP 34 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_EXP) + example: 34=99dB */ +#define MAX_GAIN_CONCEAL_EXP 1 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_CONCEAL_EXP) in concealment case (0dB) */ + +/* + LPP Transposer +*/ +#define LPC_ORDER 2 + +#define MAX_INVF_BANDS MAX_NOISE_COEFFS + +#define MAX_NUM_PATCHES 6 +#define SHIFT_START_SB 1 /*!< lowest subband of source range */ + +typedef enum +{ + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} +INVF_MODE; + + +/** parameter set for one single patch */ +typedef struct { + UCHAR sourceStartBand; /*!< first band in lowbands where to take the samples from */ + UCHAR sourceStopBand; /*!< first band in lowbands which is not included in the patch anymore */ + UCHAR guardStartBand; /*!< first band in highbands to be filled with zeros in order to + reduce interferences between patches */ + UCHAR targetStartBand; /*!< first band in highbands to be filled with whitened lowband signal */ + UCHAR targetBandOffs; /*!< difference between 'startTargetBand' and 'startSourceBand' */ + UCHAR numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + + +/** whitening factors for different levels of whitening + need to be initialized corresponding to crossover frequency */ +typedef struct { + FIXP_DBL off; /*!< bw factor for signal OFF */ + FIXP_DBL transitionLevel; + FIXP_DBL lowLevel; /*!< bw factor for signal LOW_LEVEL */ + FIXP_DBL midLevel; /*!< bw factor for signal MID_LEVEL */ + FIXP_DBL highLevel; /*!< bw factor for signal HIGH_LEVEL */ +} WHITENING_FACTORS; + + +/*! The transposer settings are calculated on a header reset and are shared by both channels. */ +typedef struct { + UCHAR nCols; /*!< number subsamples of a codec frame */ + UCHAR noOfPatches; /*!< number of patches */ + UCHAR lbStartPatching; /*!< first band of lowbands that will be patched */ + UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ + UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different inverse filtering levels */ + + PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + WHITENING_FACTORS whFactors; /*!< the pole moving factors for certain whitening levels as indicated + in the bitstream depending on the crossover frequency */ + UCHAR overlap; /*!< Overlap size */ +} TRANSPOSER_SETTINGS; + + +typedef struct +{ + TRANSPOSER_SETTINGS *pSettings; /*!< Common settings for both channels */ + FIXP_DBL bwVectorOld[MAX_NUM_PATCHES]; /*!< pole moving factors of past frame */ + FIXP_DBL lpcFilterStatesReal[LPC_ORDER][(32)]; /*!< pointer array to save filter states */ + FIXP_DBL lpcFilterStatesImag[LPC_ORDER][(32)]; /*!< pointer array to save filter states */ +} +SBR_LPP_TRANS; + +typedef SBR_LPP_TRANS *HANDLE_SBR_LPP_TRANS; + + +void lppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, + QMF_SCALE_FACTOR *sbrScaleFactor, + FIXP_DBL **qmfBufferReal, + + FIXP_DBL *degreeAlias, + FIXP_DBL **qmfBufferImag, + const int useLP, + const int timeStep, + const int firstSlotOffset, + const int lastSlotOffset, + const int nInvfBands, + INVF_MODE *sbr_invf_mode, + INVF_MODE *sbr_invf_mode_prev + ); + + +SBR_ERROR +createLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, + TRANSPOSER_SETTINGS *pSettings, + const int highBandStartSb, + UCHAR *v_k_master, + const int numMaster, + const int usb, + const int timeSlots, + const int nCols, + UCHAR *noiseBandTable, + const int noNoiseBands, + UINT fs, + const int chan, + const int overlap); + + +SBR_ERROR +resetLppTransposer (HANDLE_SBR_LPP_TRANS hLppTrans, + UCHAR highBandStartSb, + UCHAR *v_k_master, + UCHAR numMaster, + UCHAR *noiseBandTable, + UCHAR noNoiseBands, + UCHAR usb, + UINT fs); + + + +#endif /* _LPP_TRANS_H */ + diff --git a/libSBRdec/src/psbitdec.cpp b/libSBRdec/src/psbitdec.cpp new file mode 100644 index 00000000..ec6e4843 --- /dev/null +++ b/libSBRdec/src/psbitdec.cpp @@ -0,0 +1,593 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "psbitdec.h" + + +#include "sbr_rom.h" +#include "huff_dec.h" + +/* PS dec privat functions */ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); +void ResetPsDeCor (HANDLE_PS_DEC h_ps_d); + +/***************************************************************************/ +/*! + \brief huffman decoding by codebook table + + \return index of huffman codebook table + +****************************************************************************/ +static SCHAR +decode_huff_cw (Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< Handle to Bitbuffer */ + int *length) /*!< length of huffman codeword (or NULL) */ +{ + UCHAR bit = 0; + SCHAR index = 0; + UCHAR bitCount = 0; + + while (index >= 0) { + bit = FDKreadBits (hBitBuf, 1); + bitCount++; + index = h[index][bit]; + } + if (length) { + *length = bitCount; + } + return( index+64 ); /* Add offset */ +} + +/***************************************************************************/ +/*! + \brief helper function - limiting of value to min/max values + + \return limited value + +****************************************************************************/ + +static SCHAR +limitMinMax(SCHAR i, + SCHAR min, + SCHAR max) +{ + if (imax) + return max; + else + return i; +} + +/***************************************************************************/ +/*! + \brief Decodes delta values in-place and updates + data buffers according to quantization classes. + + When delta coded in frequency the first element is deltacode from zero. + aIndex buffer is decoded from delta values to actual values. + + \return none + +****************************************************************************/ +static void +deltaDecodeArray(SCHAR enable, + SCHAR *aIndex, /*!< ICC/IID parameters */ + SCHAR *aPrevFrameIndex, /*!< ICC/IID parameters of previous frame */ + SCHAR DtDf, + UCHAR nrElements, /*!< as conveyed in bitstream */ + /*!< output array size: nrElements*stride */ + UCHAR stride, /*!< 1=dflt, 2=half freq. resolution */ + SCHAR minIdx, + SCHAR maxIdx) +{ + int i; + + /* Delta decode */ + if ( enable==1 ) { + if (DtDf == 0) { /* Delta coded in freq */ + aIndex[0] = 0 + aIndex[0]; + aIndex[0] = limitMinMax(aIndex[0],minIdx,maxIdx); + for (i = 1; i < nrElements; i++) { + aIndex[i] = aIndex[i-1] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i],minIdx,maxIdx); + } + } + else { /* Delta time */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = aPrevFrameIndex[i*stride] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i],minIdx,maxIdx); + } + } + } + else { /* No data is sent, set index to zero */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = 0; + } + } + if (stride==2) { + for (i=nrElements*stride-1; i>0; i--) { + aIndex[i] = aIndex[i>>1]; + } + } +} + +/***************************************************************************/ +/*! + \brief Mapping of ICC/IID parameters to 20 stereo bands + + \return none + +****************************************************************************/ +static void map34IndexTo20 (SCHAR *aIndex, /*!< decoded ICC/IID parameters */ + UCHAR noBins) /*!< number of stereo bands */ +{ + aIndex[0] = (2*aIndex[0]+aIndex[1])/3; + aIndex[1] = (aIndex[1]+2*aIndex[2])/3; + aIndex[2] = (2*aIndex[3]+aIndex[4])/3; + aIndex[3] = (aIndex[4]+2*aIndex[5])/3; + aIndex[4] = (aIndex[6]+aIndex[7])/2; + aIndex[5] = (aIndex[8]+aIndex[9])/2; + aIndex[6] = aIndex[10]; + aIndex[7] = aIndex[11]; + aIndex[8] = (aIndex[12]+aIndex[13])/2; + aIndex[9] = (aIndex[14]+aIndex[15])/2; + aIndex[10] = aIndex[16]; + /* For IPD/OPD it stops here */ + + if (noBins == NO_HI_RES_BINS) + { + aIndex[11] = aIndex[17]; + aIndex[12] = aIndex[18]; + aIndex[13] = aIndex[19]; + aIndex[14] = (aIndex[20]+aIndex[21])/2; + aIndex[15] = (aIndex[22]+aIndex[23])/2; + aIndex[16] = (aIndex[24]+aIndex[25])/2; + aIndex[17] = (aIndex[26]+aIndex[27])/2; + aIndex[18] = (aIndex[28]+aIndex[29]+aIndex[30]+aIndex[31])/4; + aIndex[19] = (aIndex[32]+aIndex[33])/2; + } +} + +/***************************************************************************/ +/*! + \brief Decodes delta coded IID, ICC, IPD and OPD indices + + \return PS processing flag. If set to 1 + +****************************************************************************/ +int +DecodePs( struct PS_DEC *h_ps_d, /*!< PS handle */ + const UCHAR frameError ) /*!< Flag telling that frame had errors */ +{ + MPEG_PS_BS_DATA *pBsData; + UCHAR gr, env; + int bPsHeaderValid, bPsDataAvail; + + /* Shortcuts to avoid deferencing and keep the code readable */ + pBsData = &h_ps_d->bsData[h_ps_d->processSlot].mpeg; + bPsHeaderValid = pBsData->bPsHeaderValid; + bPsDataAvail = (h_ps_d->bPsDataAvail[h_ps_d->processSlot] == ppt_mpeg) ? 1 : 0; + + /*************************************************************************************** + * Decide whether to process or to conceal PS data or not. */ + + if ( ( h_ps_d->psDecodedPrv && !frameError && !bPsDataAvail) + || (!h_ps_d->psDecodedPrv && (frameError || !bPsDataAvail || !bPsHeaderValid)) ) { + /* Don't apply PS processing. + * Declare current PS header and bitstream data invalid. */ + pBsData->bPsHeaderValid = 0; + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + return (0); + } + + if (frameError || !bPsHeaderValid) + { /* no new PS data available (e.g. frame loss) */ + /* => keep latest data constant (i.e. FIX with noEnv=0) */ + pBsData->noEnv = 0; + } + + /*************************************************************************************** + * Decode bitstream payload or prepare parameter for concealment: + */ + for (env=0; envnoEnv; env++) { + SCHAR *aPrevIidIndex; + SCHAR *aPrevIccIndex; + + UCHAR noIidSteps = pBsData->bFineIidQ?NO_IID_STEPS_FINE:NO_IID_STEPS; + + if (env==0) { + aPrevIidIndex = h_ps_d->specificTo.mpeg.aIidPrevFrameIndex; + aPrevIccIndex = h_ps_d->specificTo.mpeg.aIccPrevFrameIndex; + } + else { + aPrevIidIndex = pBsData->aaIidIndex[env-1]; + aPrevIccIndex = pBsData->aaIccIndex[env-1]; + } + + deltaDecodeArray(pBsData->bEnableIid, + pBsData->aaIidIndex[env], + aPrevIidIndex, + pBsData->abIidDtFlag[env], + FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid], + (pBsData->freqResIid)?1:2, + -noIidSteps, + noIidSteps); + + deltaDecodeArray(pBsData->bEnableIcc, + pBsData->aaIccIndex[env], + aPrevIccIndex, + pBsData->abIccDtFlag[env], + FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc], + (pBsData->freqResIcc)?1:2, + 0, + NO_ICC_STEPS-1); + } /* for (env=0; envnoEnv; env++) */ + + /* handling of FIX noEnv=0 */ + if (pBsData->noEnv==0) { + /* set noEnv=1, keep last parameters or force 0 if not enabled */ + pBsData->noEnv = 1; + + if (pBsData->bEnableIid) { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv-1][gr] = + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr]; + } + } + else { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv-1][gr] = 0; + } + } + + if (pBsData->bEnableIcc) { + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv-1][gr] = + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr]; + } + } + else { + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv-1][gr] = 0; + } + } + } + + /* Update previous frame index buffers */ + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr] = + pBsData->aaIidIndex[pBsData->noEnv-1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr] = + pBsData->aaIccIndex[pBsData->noEnv-1][gr]; + } + + /* PS data from bitstream (if avail) was decoded now */ + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + + /* handling of env borders for FIX & VAR */ + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->aEnvStartStop[0] = 0; + for (env=1; envnoEnv; env++) { + pBsData->aEnvStartStop[env] = + (env * h_ps_d->noSubSamples) / pBsData->noEnv; + } + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + /* 1024 (32 slots) env borders: 0, 8, 16, 24, 32 */ + /* 960 (30 slots) env borders: 0, 7, 15, 22, 30 */ + } + else { /* if (h_ps_d->bFrameClass == 0) */ + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->aEnvStartStop[0] = 0; + + /* handle case aEnvStartStop[noEnv]aEnvStartStop[pBsData->noEnv] < h_ps_d->noSubSamples) { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv][gr] = + pBsData->aaIidIndex[pBsData->noEnv-1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv][gr] = + pBsData->aaIccIndex[pBsData->noEnv-1][gr]; + } + pBsData->noEnv++; + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + } + + /* enforce strictly monotonic increasing borders */ + for (env=1; envnoEnv; env++) { + UCHAR thr; + thr = (UCHAR)h_ps_d->noSubSamples - (pBsData->noEnv - env); + if (pBsData->aEnvStartStop[env] > thr) { + pBsData->aEnvStartStop[env] = thr; + } + else { + thr = pBsData->aEnvStartStop[env-1]+1; + if (pBsData->aEnvStartStop[env] < thr) { + pBsData->aEnvStartStop[env] = thr; + } + } + } + } /* if (h_ps_d->bFrameClass == 0) ... else */ + + /* copy data prior to possible 20<->34 in-place mapping */ + for (env=0; envnoEnv; env++) { + UCHAR i; + for (i=0; ispecificTo.mpeg.coef.aaIidIndexMapped[env][i] = pBsData->aaIidIndex[env][i]; + } + for (i=0; ispecificTo.mpeg.coef.aaIccIndexMapped[env][i] = pBsData->aaIccIndex[env][i]; + } + } + + + /* MPEG baseline PS */ + /* Baseline version of PS always uses the hybrid filter structure with 20 stereo bands. */ + /* If ICC/IID parameters for 34 stereo bands are decoded they have to be mapped to 20 */ + /* stereo bands. */ + /* Additionaly the IPD/OPD parameters won't be used. */ + + for (env=0; envnoEnv; env++) { + if (pBsData->freqResIid == 2) + map34IndexTo20 (h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env], NO_HI_RES_IID_BINS); + if (pBsData->freqResIcc == 2) + map34IndexTo20 (h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env], NO_HI_RES_ICC_BINS); + + /* IPD/OPD is disabled in baseline version and thus was removed here */ + } + + return (1); +} + + +/***************************************************************************/ +/*! + + \brief Reads parametric stereo data from bitstream + + \return + +****************************************************************************/ +unsigned int +ReadPsData (HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ + int nBitsLeft /*!< max number of bits available */ + ) +{ + MPEG_PS_BS_DATA *pBsData; + + UCHAR gr, env; + SCHAR dtFlag; + INT startbits; + Huffman CurrentTable; + SCHAR bEnableHeader; + + if (!h_ps_d) + return 0; + + pBsData = &h_ps_d->bsData[h_ps_d->bsReadSlot].mpeg; + + if (h_ps_d->bsReadSlot != h_ps_d->bsLastSlot) { + /* Copy last header data */ + FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, sizeof(MPEG_PS_BS_DATA)); + } + + + startbits = (INT) FDKgetValidBits(hBitBuf); + + bEnableHeader = (SCHAR) FDKreadBits (hBitBuf, 1); + + /* Read header */ + if (bEnableHeader) { + pBsData->bPsHeaderValid = 1; + pBsData->bEnableIid = (UCHAR) FDKreadBits (hBitBuf, 1); + if (pBsData->bEnableIid) { + pBsData->modeIid = (UCHAR) FDKreadBits (hBitBuf, 3); + } + + pBsData->bEnableIcc = (UCHAR) FDKreadBits (hBitBuf, 1); + if (pBsData->bEnableIcc) { + pBsData->modeIcc = (UCHAR) FDKreadBits (hBitBuf, 3); + } + + pBsData->bEnableExt = (UCHAR) FDKreadBits (hBitBuf, 1); + } + + pBsData->bFrameClass = (UCHAR) FDKreadBits (hBitBuf, 1); + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->noEnv = FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR) FDKreadBits (hBitBuf, 2)]; + /* all additional handling of env borders is now in DecodePs() */ + } + else { + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->noEnv = 1+(UCHAR) FDKreadBits (hBitBuf, 2); + for (env=1; envnoEnv+1; env++) + pBsData->aEnvStartStop[env] = ((UCHAR) FDKreadBits (hBitBuf, 5)) + 1; + /* all additional handling of env borders is now in DecodePs() */ + } + + /* verify that IID & ICC modes (quant grid, freq res) are supported */ + if ((pBsData->modeIid > 5) || (pBsData->modeIcc > 5)) { + /* no useful PS data could be read from bitstream */ + h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_none; + /* discard all remaining bits */ + nBitsLeft -= startbits - FDKgetValidBits(hBitBuf); + while (nBitsLeft > 0) { + int i = nBitsLeft; + if (i>8) { + i = 8; + } + FDKreadBits (hBitBuf, i); + nBitsLeft -= i; + } + return (startbits - FDKgetValidBits(hBitBuf)); + } + + if (pBsData->modeIid > 2){ + pBsData->freqResIid = pBsData->modeIid-3; + pBsData->bFineIidQ = 1; + } + else{ + pBsData->freqResIid = pBsData->modeIid; + pBsData->bFineIidQ = 0; + } + + if (pBsData->modeIcc > 2){ + pBsData->freqResIcc = pBsData->modeIcc-3; + } + else{ + pBsData->freqResIcc = pBsData->modeIcc; + } + + + /* Extract IID data */ + if (pBsData->bEnableIid) { + for (env=0; envnoEnv; env++) { + dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); + if (!dtFlag) + { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIidFreqDecode; + } + else + { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; + else + CurrentTable = (Huffman)&aBookPsIidTimeDecode; + } + + for (gr = 0; gr < FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid]; gr++) + pBsData->aaIidIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); + pBsData->abIidDtFlag[env] = dtFlag; + } + } + + /* Extract ICC data */ + if (pBsData->bEnableIcc) { + for (env=0; envnoEnv; env++) { + dtFlag = (SCHAR)FDKreadBits (hBitBuf, 1); + if (!dtFlag) + CurrentTable = (Huffman)&aBookPsIccFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIccTimeDecode; + + for (gr = 0; gr < FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc]; gr++) + pBsData->aaIccIndex[env][gr] = decode_huff_cw(CurrentTable,hBitBuf,NULL); + pBsData->abIccDtFlag[env] = dtFlag; + } + } + + if (pBsData->bEnableExt) { + + /*! + Decoders that support only the baseline version of the PS tool are allowed + to ignore the IPD/OPD data, but according header data has to be parsed. + ISO/IEC 14496-3 Subpart 8 Annex 4 + */ + + int cnt = FDKreadBits(hBitBuf, PS_EXTENSION_SIZE_BITS); + if (cnt == (1<bPsDataAvail[h_ps_d->bsReadSlot] = ppt_mpeg; + + + + return (startbits - FDKgetValidBits(hBitBuf)); +} + diff --git a/libSBRdec/src/psbitdec.h b/libSBRdec/src/psbitdec.h new file mode 100644 index 00000000..a2d4d6c2 --- /dev/null +++ b/libSBRdec/src/psbitdec.h @@ -0,0 +1,103 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#ifndef __PSBITDEC_H +#define __PSBITDEC_H + +#include "sbrdecoder.h" + + +#include "psdec.h" + + +unsigned int +ReadPsData (struct PS_DEC *h_ps_d, + HANDLE_FDK_BITSTREAM hBs, + int nBitsLeft); + +int +DecodePs(struct PS_DEC *h_ps_d, + const UCHAR frameError); + + +#endif /* __PSBITDEC_H */ diff --git a/libSBRdec/src/psdec.cpp b/libSBRdec/src/psdec.cpp new file mode 100644 index 00000000..965917af --- /dev/null +++ b/libSBRdec/src/psdec.cpp @@ -0,0 +1,1414 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief parametric stereo decoder +*/ + +#include "psdec.h" + + + +#include "FDK_bitbuffer.h" +#include "psdec_hybrid.h" + +#include "sbr_rom.h" +#include "sbr_ram.h" + +#include "FDK_tools_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + + +/********************************************************************/ +/* MLQUAL DEFINES */ +/********************************************************************/ + + #define FRACT_ZERO FRACT_BITS-1 +/********************************************************************/ + +SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ); + +void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ); + + +/***** HELPERS *****/ + +static void assignTimeSlotsPS (FIXP_DBL *bufAdr, FIXP_DBL **bufPtr, const int numSlots, const int numChan); + + + +/*******************/ + +#define DIV3 FL2FXCONST_DBL(1.f/3.f) /* division 3.0 */ +#define DIV1_5 FL2FXCONST_DBL(2.f/3.f) /* division 1.5 */ + +/***************************************************************************/ +/*! + \brief Creates one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int +CreatePsDec( HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ + int aacSamplesPerFrame + ) +{ + SBR_ERROR errorInfo = SBRDEC_OK; + HANDLE_PS_DEC h_ps_d; + int i; + + if (*h_PS_DEC == NULL) { + /* Get ps dec ram */ + h_ps_d = GetRam_ps_dec(); + if (h_ps_d == NULL) { + errorInfo = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + } else { + /* Reset an open instance */ + h_ps_d = *h_PS_DEC; + } + + /* initialisation */ + switch (aacSamplesPerFrame) { + case 960: + h_ps_d->noSubSamples = 30; /* col */ + break; + case 1024: + h_ps_d->noSubSamples = 32; /* col */ + break; + default: + h_ps_d->noSubSamples = -1; + break; + } + + if (h_ps_d->noSubSamples > MAX_NUM_COL + || h_ps_d->noSubSamples <= 0) + { + goto bail; + } + h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ + + h_ps_d->psDecodedPrv = 0; + h_ps_d->procFrameBased = -1; + for (i = 0; i < (1)+1; i++) { + h_ps_d->bPsDataAvail[i] = ppt_none; + } + + + for (i = 0; i < (1)+1; i++) { + FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA)); + } + + errorInfo = ResetPsDec( h_ps_d ); + + if ( errorInfo != SBRDEC_OK ) + goto bail; + + ResetPsDeCor( h_ps_d ); + + *h_PS_DEC = h_ps_d; + + + + return 0; + +bail: + DeletePsDec(&h_ps_d); + + return -1; +} /*END CreatePsDec */ + +/***************************************************************************/ +/*! + \brief Delete one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int +DeletePsDec( HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ +{ + if (*h_PS_DEC == NULL) { + return -1; + } + + + FreeRam_ps_dec(h_PS_DEC); + + + return 0; +} /*END DeletePsDec */ + +/***************************************************************************/ +/*! + \brief resets some values of the PS handle to default states + + \return + +****************************************************************************/ +SBR_ERROR ResetPsDec( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */ +{ + SBR_ERROR errorInfo = SBRDEC_OK; + INT i; + + const UCHAR noQmfBandsInHybrid20 = 3; + /* const UCHAR noQmfBandsInHybrid34 = 5; */ + + const UCHAR aHybridResolution20[] = { HYBRID_8_CPLX, + HYBRID_2_REAL, + HYBRID_2_REAL }; + + h_ps_d->specificTo.mpeg.delayBufIndex = 0; + + /* explicitly init state variables to safe values (until first ps header arrives) */ + + h_ps_d->specificTo.mpeg.lastUsb = 0; + + h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = -(DFRACT_BITS-1); + + FDKmemclear(h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf, (NO_QMF_CHANNELS-FIRST_DELAY_SB)*sizeof(UCHAR)); + h_ps_d->specificTo.mpeg.noSampleDelay = delayIndexQmf[0]; + + for (i=0 ; i < NO_SERIAL_ALLPASS_LINKS; i++) { + h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[i] = 0; + } + + h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufReal; + + assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB), + &h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[1], + h_ps_d->specificTo.mpeg.noSampleDelay-1, + (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)); + + h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] = h_ps_d->specificTo.mpeg.aaQmfDelayBufImag; + + assignTimeSlotsPS ( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0] + (NO_QMF_CHANNELS-FIRST_DELAY_SB), + &h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[1], + h_ps_d->specificTo.mpeg.noSampleDelay-1, + (NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)); + + /* Hybrid Filter Bank 1 creation. */ + errorInfo = InitHybridFilterBank ( &h_ps_d->specificTo.mpeg.hybrid, + h_ps_d->noSubSamples, + noQmfBandsInHybrid20, + aHybridResolution20 ); + + for ( i = 0; i < NO_IID_GROUPS; i++ ) + { + h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f); + h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f); + } + + FDKmemclear( h_ps_d->specificTo.mpeg.h21rPrev, sizeof( h_ps_d->specificTo.mpeg.h21rPrev ) ); + FDKmemclear( h_ps_d->specificTo.mpeg.h22rPrev, sizeof( h_ps_d->specificTo.mpeg.h22rPrev ) ); + + return errorInfo; +} + +/***************************************************************************/ +/*! + \brief clear some buffers used in decorrelation process + + \return + +****************************************************************************/ +void ResetPsDeCor( HANDLE_PS_DEC h_ps_d ) /*!< pointer to the module state */ +{ + INT i; + + FDKmemclear(h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aPowerPrevScal, NO_MID_RES_BINS*sizeof(SCHAR)); + + for (i=0 ; i < FIRST_DELAY_SB ; i++) { + FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + } + for (i=0 ; i < NO_SUB_QMF_CHANNELS ; i++) { + FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + } + +} + +/*******************************************************************************/ + +/* slot based funcion prototypes */ + +static void deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, + + FIXP_DBL *mHybridRealLeft, + FIXP_DBL *mHybridImagLeft, + SCHAR sf_mHybridLeft, + + FIXP_DBL *rIntBufferLeft, + FIXP_DBL *iIntBufferLeft, + SCHAR sf_IntBuffer, + + FIXP_DBL *mHybridRealRight, + FIXP_DBL *mHybridImagRight, + + FIXP_DBL *rIntBufferRight, + FIXP_DBL *iIntBufferRight ); + +static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, + + FIXP_DBL *mHybridRealLeft, + FIXP_DBL *mHybridImagLeft, + + FIXP_DBL *QmfLeftReal, + FIXP_DBL *QmfLeftImag, + + FIXP_DBL *mHybridRealRight, + FIXP_DBL *mHybridImagRight, + + FIXP_DBL *QmfRightReal, + FIXP_DBL *QmfRightImag + ); + + +/***************************************************************************/ +/*! + \brief Get scale factor for all ps delay buffer. + + \return + +****************************************************************************/ +static +int getScaleFactorPsStatesBuffer(HANDLE_PS_DEC h_ps_d) +{ + INT i; + int scale = DFRACT_BITS-1; + + for (i=0; ispecificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS)); + } + + for (i=0; ispecificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB)); + } + + for (i=0; ispecificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS)); + } + + for (i=0; ispecificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS)); + } + + for (i=0; ispecificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS)); + } + + for (i=0; ispecificTo.mpeg.pAaRealDelayBufferQmf[i], len)); + scale = fMin(scale, getScalefactor(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len)); + } + + return (scale); +} + +/***************************************************************************/ +/*! + \brief Rescale all ps delay buffer. + + \return + +****************************************************************************/ +static +void scalePsStatesBuffer(HANDLE_PS_DEC h_ps_d, + int scale) +{ + INT i; + + if (scale < 0) + scale = fixMax((INT)scale,(INT)-(DFRACT_BITS-1)); + else + scale = fixMin((INT)scale,(INT)DFRACT_BITS-1); + + for (i=0; ispecificTo.mpeg.hybrid.mQmfBufferRealSlot[i], NO_SUB_QMF_CHANNELS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.hybrid.mQmfBufferImagSlot[i], NO_SUB_QMF_CHANNELS, scale ); + } + + for (i=0; ispecificTo.mpeg.aaRealDelayBufferQmf[i], FIRST_DELAY_SB, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[i], FIRST_DELAY_SB, scale ); + } + + for (i=0; ispecificTo.mpeg.aaRealDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[i], NO_SUB_QMF_CHANNELS, scale ); + } + + for (i=0; ispecificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); + } + + for (i=0; ispecificTo.mpeg.aaaRealDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[i], NO_DELAY_LENGTH_VECTORS, scale ); + } + + for (i=0; ispecificTo.mpeg.pAaRealDelayBufferQmf[i], len, scale ); + scaleValues( h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[i], len, scale ); + } + + scale <<= 1; + + scaleValues( h_ps_d->specificTo.mpeg.aPeakDecayFastBin, NO_MID_RES_BINS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aPrevPeakDiffBin, NO_MID_RES_BINS, scale ); + scaleValues( h_ps_d->specificTo.mpeg.aPrevNrgBin, NO_MID_RES_BINS, scale ); +} + +/***************************************************************************/ +/*! + \brief Scale input channel to the same scalefactor and rescale hybrid + filterbank values + + \return + +****************************************************************************/ + +void scalFilterBankValues( HANDLE_PS_DEC h_ps_d, + FIXP_DBL **fixpQmfReal, + FIXP_DBL **fixpQmfImag, + int lsb, + int scaleFactorLowBandSplitLow, + int scaleFactorLowBandSplitHigh, + SCHAR *scaleFactorLowBand_lb, + SCHAR *scaleFactorLowBand_hb, + int scaleFactorHighBands, + INT *scaleFactorHighBand, + INT noCols + ) +{ + INT maxScal; + + INT i; + + scaleFactorHighBands = -scaleFactorHighBands; + scaleFactorLowBandSplitLow = -scaleFactorLowBandSplitLow; + scaleFactorLowBandSplitHigh = -scaleFactorLowBandSplitHigh; + + /* get max scale factor */ + maxScal = fixMax(scaleFactorHighBands,fixMax(scaleFactorLowBandSplitLow, scaleFactorLowBandSplitHigh )); + + { + int headroom = getScaleFactorPsStatesBuffer(h_ps_d); + maxScal = fixMax(maxScal,(INT)(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-headroom)); + maxScal += 1; + } + + /* scale whole left channel to the same scale factor */ + + /* low band ( overlap buffer ) */ + if ( maxScal != scaleFactorLowBandSplitLow ) { + INT scale = scaleFactorLowBandSplitLow - maxScal; + for ( i=0; i<(6); i++ ) { + scaleValues( fixpQmfReal[i], lsb, scale ); + scaleValues( fixpQmfImag[i], lsb, scale ); + } + } + /* low band ( current frame ) */ + if ( maxScal != scaleFactorLowBandSplitHigh ) { + INT scale = scaleFactorLowBandSplitHigh - maxScal; + /* for ( i=(6); i<(6)+MAX_NUM_COL; i++ ) { */ + for ( i=(6); i<(6)+noCols; i++ ) { + scaleValues( fixpQmfReal[i], lsb, scale ); + scaleValues( fixpQmfImag[i], lsb, scale ); + } + } + /* high band */ + if ( maxScal != scaleFactorHighBands ) { + INT scale = scaleFactorHighBands - maxScal; + /* for ( i=0; ispecificTo.mpeg.scaleFactorPsDelayBuffer ) + scalePsStatesBuffer(h_ps_d,(h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer-maxScal)); + + h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer = maxScal; + h_ps_d->specificTo.mpeg.scaleFactorPsDelayBuffer = maxScal; + + *scaleFactorHighBand += maxScal - scaleFactorHighBands; + + h_ps_d->rescal = maxScal - scaleFactorLowBandSplitHigh; + h_ps_d->sf_IntBuffer = maxScal; + + *scaleFactorLowBand_lb += maxScal - scaleFactorLowBandSplitLow; + *scaleFactorLowBand_hb += maxScal - scaleFactorLowBandSplitHigh; +} + +void rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **QmfBufferReal, /* qmf filterbank values */ + FIXP_DBL **QmfBufferImag, /* qmf filterbank values */ + int lsb, /* sbr start subband */ + INT noCols) +{ + int i; + /* scale back 6 timeslots look ahead for hybrid filterbank to original value */ + for ( i=noCols; irescal ); + scaleValues( QmfBufferImag[i], lsb, h_ps_d->rescal ); + } +} + +/***************************************************************************/ +/*! + \brief Generate decorrelated side channel using allpass/delay + + \return + +****************************************************************************/ +static void +deCorrelateSlotBased( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + + FIXP_DBL *mHybridRealLeft, /*!< left (mono) hybrid values real */ + FIXP_DBL *mHybridImagLeft, /*!< left (mono) hybrid values imag */ + SCHAR sf_mHybridLeft, /*!< scalefactor for left (mono) hybrid bands */ + + FIXP_DBL *rIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */ + FIXP_DBL *iIntBufferLeft, /*!< real qmf bands left (mono) (38x64) */ + SCHAR sf_IntBuffer, /*!< scalefactor for all left and right qmf bands */ + + FIXP_DBL *mHybridRealRight, /*!< right (decorrelated) hybrid values real */ + FIXP_DBL *mHybridImagRight, /*!< right (decorrelated) hybrid values imag */ + + FIXP_DBL *rIntBufferRight, /*!< real qmf bands right (decorrelated) (38x64) */ + FIXP_DBL *iIntBufferRight ) /*!< real qmf bands right (decorrelated) (38x64) */ +{ + + INT i, m, sb, gr, bin; + + FIXP_DBL peakDiff, nrg, transRatio; + + FIXP_DBL *RESTRICT aaLeftReal; + FIXP_DBL *RESTRICT aaLeftImag; + + FIXP_DBL *RESTRICT aaRightReal; + FIXP_DBL *RESTRICT aaRightImag; + + FIXP_DBL *RESTRICT pRealDelayBuffer; + FIXP_DBL *RESTRICT pImagDelayBuffer; + + C_ALLOC_SCRATCH_START(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS); + C_ALLOC_SCRATCH_START(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS); + +/*! +
+   parameter index       qmf bands             hybrid bands
+  ----------------------------------------------------------------------------
+         0                   0                      0,7
+         1                   0                      1,6
+         2                   0                      2
+         3                   0                      3           HYBRID BANDS
+         4                   1                      9
+         5                   1                      8
+         6                   2                     10
+         7                   2                     11
+  ----------------------------------------------------------------------------
+         8                   3
+         9                   4
+        10                   5
+        11                   6
+        12                   7
+        13                   8
+        14                   9,10      (2 )                      QMF BANDS
+        15                   11 - 13   (3 )
+        16                   14 - 17   (4 )
+        17                   18 - 22   (5 )
+        18                   23 - 34   (12)
+        19                   35 - 63   (29)
+  ----------------------------------------------------------------------------
+
+*/ + + #define FLTR_SCALE 3 + + /* hybrid bands (parameter index 0 - 7) */ + aaLeftReal = mHybridRealLeft; + aaLeftImag = mHybridImagLeft; + + aaPowerSlot[0] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[0], aaLeftReal[0]), aaLeftImag[0], aaLeftImag[0] ) >> FLTR_SCALE ) + + ( fMultAddDiv2( fMultDiv2(aaLeftReal[7], aaLeftReal[7]), aaLeftImag[7], aaLeftImag[7] ) >> FLTR_SCALE ); + + aaPowerSlot[1] = ( fMultAddDiv2( fMultDiv2(aaLeftReal[1], aaLeftReal[1]), aaLeftImag[1], aaLeftImag[1] ) >> FLTR_SCALE ) + + ( fMultAddDiv2( fMultDiv2(aaLeftReal[6], aaLeftReal[6]), aaLeftImag[6], aaLeftImag[6] ) >> FLTR_SCALE ); + + aaPowerSlot[2] = fMultAddDiv2( fMultDiv2(aaLeftReal[2], aaLeftReal[2]), aaLeftImag[2], aaLeftImag[2] ) >> FLTR_SCALE; + aaPowerSlot[3] = fMultAddDiv2( fMultDiv2(aaLeftReal[3], aaLeftReal[3]), aaLeftImag[3], aaLeftImag[3] ) >> FLTR_SCALE; + + aaPowerSlot[4] = fMultAddDiv2( fMultDiv2(aaLeftReal[9], aaLeftReal[9]), aaLeftImag[9], aaLeftImag[9] ) >> FLTR_SCALE; + aaPowerSlot[5] = fMultAddDiv2( fMultDiv2(aaLeftReal[8], aaLeftReal[8]), aaLeftImag[8], aaLeftImag[8] ) >> FLTR_SCALE; + + aaPowerSlot[6] = fMultAddDiv2( fMultDiv2(aaLeftReal[10], aaLeftReal[10]), aaLeftImag[10], aaLeftImag[10] ) >> FLTR_SCALE; + aaPowerSlot[7] = fMultAddDiv2( fMultDiv2(aaLeftReal[11], aaLeftReal[11]), aaLeftImag[11], aaLeftImag[11] ) >> FLTR_SCALE; + + /* qmf bands (parameter index 8 - 19) */ + for ( bin = 8; bin < NO_MID_RES_BINS; bin++ ) { + FIXP_DBL slotNrg = FL2FXCONST_DBL(0.f); + + for ( i = groupBorders20[bin+2]; i < groupBorders20[bin+3]; i++ ) { /* max loops: 29 */ + slotNrg += fMultAddDiv2 ( fMultDiv2(rIntBufferLeft[i], rIntBufferLeft[i]), iIntBufferLeft[i], iIntBufferLeft[i]) >> FLTR_SCALE; + } + aaPowerSlot[bin] = slotNrg; + + } + + + /* calculation of transient ratio */ + for (bin=0; bin < NO_MID_RES_BINS; bin++) { /* noBins = 20 ( BASELINE_PS ) */ + + h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = fMult( h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin], PEAK_DECAY_FACTOR ); + + if (h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] < aaPowerSlot[bin]) { + h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] = aaPowerSlot[bin]; + } + + /* calculate PSmoothPeakDecayDiffNrg */ + peakDiff = fMultAdd ( (h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]>>1), + INT_FILTER_COEFF, h_ps_d->specificTo.mpeg.aPeakDecayFastBin[bin] - aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin]); + + /* save peakDiff for the next frame */ + h_ps_d->specificTo.mpeg.aPrevPeakDiffBin[bin] = peakDiff; + + nrg = h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] + fMult( INT_FILTER_COEFF, aaPowerSlot[bin] - h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] ); + + /* Negative energies don't exist. But sometimes they appear due to rounding. */ + + nrg = fixMax(nrg,FL2FXCONST_DBL(0.f)); + + /* save nrg for the next frame */ + h_ps_d->specificTo.mpeg.aPrevNrgBin[bin] = nrg; + + nrg = fMult( nrg, TRANSIENT_IMPACT_FACTOR ); + + /* save transient impact factor */ + if ( peakDiff <= nrg || peakDiff == FL2FXCONST_DBL(0.0) ) { + aaTransRatioSlot[bin] = (FIXP_DBL)MAXVAL_DBL /* FL2FXCONST_DBL(1.0f)*/; + } + else if ( nrg <= FL2FXCONST_DBL(0.0f) ) { + aaTransRatioSlot[bin] = FL2FXCONST_DBL(0.f); + } + else { + /* scale to denominator */ + INT scale_left = fixMax(0, CntLeadingZeros(peakDiff) - 1); + aaTransRatioSlot[bin] = schur_div( nrg<specificTo.mpeg.delayBufIndex; /* set delay indices */ + + pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferSubQmf[TempDelay]; + pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferSubQmf[TempDelay]; + + aaLeftReal = mHybridRealLeft; + aaLeftImag = mHybridImagLeft; + aaRightReal = mHybridRealRight; + aaRightImag = mHybridImagRight; + + /************************/ + /* ICC groups : 0 - 9 */ + /************************/ + + /* gr = ICC groups */ + for (gr=0; gr < SUBQMF_GROUPS; gr++) { + + transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; + + /* sb = subQMF/QMF subband */ + sb = groupBorders20[gr]; + + /* Update delay buffers, sample delay allpass = 2 */ + rTmp0 = pRealDelayBuffer[sb]; + iTmp0 = pImagDelayBuffer[sb]; + + pRealDelayBuffer[sb] = aaLeftReal[sb]; + pImagDelayBuffer[sb] = aaLeftImag[sb]; + + /* delay by fraction */ + cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReSubQmf20[sb], aaFractDelayPhaseFactorImSubQmf20[sb]); + rR0<<=1; + iR0<<=1; + + FIXP_DBL *pAaaRealDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerSubQmf[sb]; + FIXP_DBL *pAaaImagDelayRBufferSerSubQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerSubQmf[sb]; + + for (m=0; mspecificTo.mpeg.aDelayRBufIndexSer[m]; + + /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */ + rTmp0 = pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer]; + iTmp0 = pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer]; + + /* delay by fraction */ + cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReSubQmf20[sb][m], aaFractDelayPhaseFactorSerImSubQmf20[sb][m]); + + rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], rR0)) << 1; + iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], iR0)) << 1; + + pAaaRealDelayRBufferSerSubQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], rTmp); + pAaaImagDelayRBufferSerSubQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], iTmp); + + rR0 = rTmp; + iR0 = iTmp; + + pAaaRealDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m]; + pAaaImagDelayRBufferSerSubQmf += aAllpassLinkDelaySer[m]; + + } /* m */ + + /* duck if a past transient is found */ + aaRightReal[sb] = fMult(transRatio, rR0); + aaRightImag[sb] = fMult(transRatio, iR0); + + } /* gr */ + + + scaleValues( mHybridRealLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); + scaleValues( mHybridImagLeft, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); + scaleValues( mHybridRealRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); + scaleValues( mHybridImagRight, NO_SUB_QMF_CHANNELS, -SCAL_HEADROOM ); + + + /************************/ + + aaLeftReal = rIntBufferLeft; + aaLeftImag = iIntBufferLeft; + aaRightReal = rIntBufferRight; + aaRightImag = iIntBufferRight; + + pRealDelayBuffer = h_ps_d->specificTo.mpeg.aaRealDelayBufferQmf[TempDelay]; + pImagDelayBuffer = h_ps_d->specificTo.mpeg.aaImagDelayBufferQmf[TempDelay]; + + /************************/ + /* ICC groups : 10 - 19 */ + /************************/ + + + /* gr = ICC groups */ + for (gr=SUBQMF_GROUPS; gr < NO_IID_GROUPS - NR_OF_DELAY_GROUPS; gr++) { + + transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; + + /* sb = subQMF/QMF subband */ + for (sb = groupBorders20[gr]; sb < groupBorders20[gr+1]; sb++) { + FIXP_DBL resR, resI; + + /* decayScaleFactor = 1.0f + decay_cutoff * DECAY_SLOPE - DECAY_SLOPE * sb; DECAY_SLOPE = 0.05 */ + FIXP_DBL decayScaleFactor = decayScaleFactTable[sb]; + + /* Update delay buffers, sample delay allpass = 2 */ + rTmp0 = pRealDelayBuffer[sb]; + iTmp0 = pImagDelayBuffer[sb]; + + pRealDelayBuffer[sb] = aaLeftReal[sb]; + pImagDelayBuffer[sb] = aaLeftImag[sb]; + + /* delay by fraction */ + cplxMultDiv2(&rR0, &iR0, rTmp0, iTmp0, aaFractDelayPhaseFactorReQmf[sb], aaFractDelayPhaseFactorImQmf[sb]); + rR0<<=1; + iR0<<=1; + + resR = fMult(decayScaleFactor, rR0); + resI = fMult(decayScaleFactor, iR0); + + FIXP_DBL *pAaaRealDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[sb]; + FIXP_DBL *pAaaImagDelayRBufferSerQmf = h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[sb]; + + for (m=0; mspecificTo.mpeg.aDelayRBufIndexSer[m]; + + /* get delayed values from according buffer : m(0)=3; m(1)=4; m(2)=5; */ + rTmp0 = pAaaRealDelayRBufferSerQmf[tmpDelayRSer]; + iTmp0 = pAaaImagDelayRBufferSerQmf[tmpDelayRSer]; + + /* delay by fraction */ + cplxMultDiv2(&rTmp, &iTmp, rTmp0, iTmp0, aaFractDelayPhaseFactorSerReQmf[sb][m], aaFractDelayPhaseFactorSerImQmf[sb][m]); + + rTmp = (rTmp - fMultDiv2(aAllpassLinkDecaySer[m], resR))<<1; + iTmp = (iTmp - fMultDiv2(aAllpassLinkDecaySer[m], resI))<<1; + + resR = fMult(decayScaleFactor, rTmp); + resI = fMult(decayScaleFactor, iTmp); + + pAaaRealDelayRBufferSerQmf[tmpDelayRSer] = rR0 + fMult(aAllpassLinkDecaySer[m], resR); + pAaaImagDelayRBufferSerQmf[tmpDelayRSer] = iR0 + fMult(aAllpassLinkDecaySer[m], resI); + + rR0 = rTmp; + iR0 = iTmp; + + pAaaRealDelayRBufferSerQmf += aAllpassLinkDelaySer[m]; + pAaaImagDelayRBufferSerQmf += aAllpassLinkDelaySer[m]; + + } /* m */ + + /* duck if a past transient is found */ + aaRightReal[sb] = fMult(transRatio, rR0); + aaRightImag[sb] = fMult(transRatio, iR0); + + } /* sb */ + } /* gr */ + + /************************/ + /* ICC groups : 20, 21 */ + /************************/ + + + /* gr = ICC groups */ + for (gr=DELAY_GROUP_OFFSET; gr < NO_IID_GROUPS; gr++) { + + INT sbStart = groupBorders20[gr]; + INT sbStop = groupBorders20[gr+1]; + + UCHAR *pDelayBufIdx = &h_ps_d->specificTo.mpeg.aDelayBufIndexDelayQmf[sbStart-FIRST_DELAY_SB]; + + transRatio = aaTransRatioSlot[bins2groupMap20[gr]]; + + /* sb = subQMF/QMF subband */ + for (sb = sbStart; sb < sbStop; sb++) { + + /* Update delay buffers */ + rR0 = h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB]; + iR0 = h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB]; + + h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftReal[sb]; + h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[*pDelayBufIdx][sb-FIRST_DELAY_SB] = aaLeftImag[sb]; + + /* duck if a past transient is found */ + aaRightReal[sb] = fMult(transRatio, rR0); + aaRightImag[sb] = fMult(transRatio, iR0); + + if (++(*pDelayBufIdx) >= delayIndexQmf[sb]) { + *pDelayBufIdx = 0; + } + pDelayBufIdx++; + + } /* sb */ + } /* gr */ + + + /* Update delay buffer index */ + if (++h_ps_d->specificTo.mpeg.delayBufIndex >= NO_SAMPLE_DELAY_ALLPASS) + h_ps_d->specificTo.mpeg.delayBufIndex = 0; + + for (m=0; mspecificTo.mpeg.aDelayRBufIndexSer[m] >= aAllpassLinkDelaySer[m]) + h_ps_d->specificTo.mpeg.aDelayRBufIndexSer[m] = 0; + } + + + scaleValues( &rIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); + scaleValues( &iIntBufferLeft[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); + scaleValues( &rIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); + scaleValues( &iIntBufferRight[NO_QMF_BANDS_HYBRID20], NO_QMF_CHANNELS-NO_QMF_BANDS_HYBRID20, -SCAL_HEADROOM ); + + /* free memory on scratch */ + C_ALLOC_SCRATCH_END(aaTransRatioSlot, FIXP_DBL, NO_MID_RES_BINS); + C_ALLOC_SCRATCH_END(aaPowerSlot, FIXP_DBL, NO_MID_RES_BINS); +} + + +void initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + int env, + int usb + ) { + + INT group = 0; + INT bin = 0; + INT noIidSteps; + +/* const UCHAR *pQuantizedIIDs;*/ + + FIXP_SGL invL; + FIXP_DBL ScaleL, ScaleR; + FIXP_DBL Alpha, Beta; + FIXP_DBL h11r, h12r, h21r, h22r; + + const FIXP_DBL *PScaleFactors; + + /* Overwrite old values in delay buffers when upper subband is higher than in last frame */ + if (env == 0) { + + if ((usb > h_ps_d->specificTo.mpeg.lastUsb) && h_ps_d->specificTo.mpeg.lastUsb) { + + INT i,k,length; + + for (i=h_ps_d->specificTo.mpeg.lastUsb ; i < FIRST_DELAY_SB; i++) { + FDKmemclear(h_ps_d->specificTo.mpeg.aaaRealDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + FDKmemclear(h_ps_d->specificTo.mpeg.aaaImagDelayRBufferSerQmf[i], NO_DELAY_LENGTH_VECTORS*sizeof(FIXP_DBL)); + } + + for (k=0 ; kspecificTo.mpeg.pAaRealDelayBufferQmf[k], FIRST_DELAY_SB*sizeof(FIXP_DBL)); + } + length = (usb-FIRST_DELAY_SB)*sizeof(FIXP_DBL); + if(length>0) { + FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[0], length); + FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[0], length); + } + length = (fixMin(NO_DELAY_BUFFER_BANDS,(INT)usb)-FIRST_DELAY_SB)*sizeof(FIXP_DBL); + if(length>0) { + for (k=1 ; k < h_ps_d->specificTo.mpeg.noSampleDelay; k++) { + FDKmemclear(h_ps_d->specificTo.mpeg.pAaRealDelayBufferQmf[k], length); + FDKmemclear(h_ps_d->specificTo.mpeg.pAaImagDelayBufferQmf[k], length); + } + } + } + h_ps_d->specificTo.mpeg.lastUsb = usb; + } /* env == 0 */ + + if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) + { + PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS_FINE; + /*pQuantizedIIDs = quantizedIIDsFine;*/ + } + + else + { + PScaleFactors = ScaleFactors; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS; + /*pQuantizedIIDs = quantizedIIDs;*/ + } + + + /* dequantize and decode */ + for ( group = 0; group < NO_IID_GROUPS; group++ ) { + + bin = bins2groupMap20[group]; + + /*! +

type 'A' rotation

+ mixing procedure R_a, used in baseline version
+ + Scale-factor vectors c1 and c2 are precalculated in initPsTables () and stored in + scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. + From the linearized IID parameters (intensity differences), two scale factors are + calculated. They are used to obtain the coefficients h11... h22. + */ + + /* ScaleR and ScaleL are scaled by 1 shift right */ + + ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]]; + ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.coef.aaIidIndexMapped[env][bin]]; + + Beta = fMult (fMult( Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]], ( ScaleR - ScaleL )), FIXP_SQRT05); + Alpha = Alphas[h_ps_d->specificTo.mpeg.coef.aaIccIndexMapped[env][bin]]>>1; + + /* Alpha and Beta are now both scaled by 2 shifts right */ + + /* calculate the coefficients h11... h22 from scale-factors and ICC parameters */ + + /* h values are scaled by 1 shift right */ + { + FIXP_DBL trigData[4]; + + inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData); + h11r = fMult( ScaleL, trigData[0]); + h12r = fMult( ScaleR, trigData[2]); + h21r = fMult( ScaleL, trigData[1]); + h22r = fMult( ScaleR, trigData[3]); + } + /*****************************************************************************************/ + /* Interpolation of the matrices H11... H22: */ + /* */ + /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / (n[e+1] - n[e]) */ + /* ... */ + /*****************************************************************************************/ + + /* invL = 1/(length of envelope) */ + invL = FX_DBL2FX_SGL(GetInvInt(h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); + + h_ps_d->specificTo.mpeg.coef.H11r[group] = h_ps_d->specificTo.mpeg.h11rPrev[group]; + h_ps_d->specificTo.mpeg.coef.H12r[group] = h_ps_d->specificTo.mpeg.h12rPrev[group]; + h_ps_d->specificTo.mpeg.coef.H21r[group] = h_ps_d->specificTo.mpeg.h21rPrev[group]; + h_ps_d->specificTo.mpeg.coef.H22r[group] = h_ps_d->specificTo.mpeg.h22rPrev[group]; + + h_ps_d->specificTo.mpeg.coef.DeltaH11r[group] = fMult ( h11r - h_ps_d->specificTo.mpeg.coef.H11r[group], invL ); + h_ps_d->specificTo.mpeg.coef.DeltaH12r[group] = fMult ( h12r - h_ps_d->specificTo.mpeg.coef.H12r[group], invL ); + h_ps_d->specificTo.mpeg.coef.DeltaH21r[group] = fMult ( h21r - h_ps_d->specificTo.mpeg.coef.H21r[group], invL ); + h_ps_d->specificTo.mpeg.coef.DeltaH22r[group] = fMult ( h22r - h_ps_d->specificTo.mpeg.coef.H22r[group], invL ); + + /* update prev coefficients for interpolation in next envelope */ + + h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r; + h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r; + h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r; + h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r; + + } /* group loop */ +} + + +static void applySlotBasedRotation( HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + + FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ + FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ + + FIXP_DBL *QmfLeftReal, /*!< real bands left qmf channel */ + FIXP_DBL *QmfLeftImag, /*!< imag bands left qmf channel */ + + FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ + FIXP_DBL *mHybridImagRight, /*!< hybrid values imag right */ + + FIXP_DBL *QmfRightReal, /*!< real bands right qmf channel */ + FIXP_DBL *QmfRightImag /*!< imag bands right qmf channel */ + ) +{ + INT group; + INT subband; + + FIXP_DBL *RESTRICT HybrLeftReal; + FIXP_DBL *RESTRICT HybrLeftImag; + FIXP_DBL *RESTRICT HybrRightReal; + FIXP_DBL *RESTRICT HybrRightImag; + + FIXP_DBL tmpLeft, tmpRight; + + + /**********************************************************************************************/ + /*! +

Mapping

+ + The number of stereo bands that is actually used depends on the number of availble + parameters for IID and ICC: +
+   nr. of IID para.| nr. of ICC para. | nr. of Stereo bands
+   ----------------|------------------|-------------------
+     10,20         |     10,20        |        20
+     10,20         |     34           |        34
+     34            |     10,20        |        34
+     34            |     34           |        34
+  
+ In the case the number of parameters for IIS and ICC differs from the number of stereo + bands, a mapping from the lower number to the higher number of parameters is applied. + Index mapping of IID and ICC parameters is already done in psbitdec.cpp. Further mapping is + not needed here in baseline version. + **********************************************************************************************/ + + /************************************************************************************************/ + /*! +

Mixing

+ + To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, n_[e+1] the + parameters at position n[e] and n[e+1] are required as well as the subband domain signals + s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] represents the start position for + envelope e. The border positions n[e] are handled in DecodePS(). + + The stereo sub subband signals are constructed as: +
+  l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
+  r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
+  
+ In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... h22(b) need to + be calculated first (b: parameter index). Depending on ICC mode either mixing procedure R_a + or R_b is used for that. For both procedures, the parameters for parameter position n[e+1] + is used. + ************************************************************************************************/ + + + /************************************************************************************************/ + /*! +

Phase parameters

+ With disabled phase parameters (which is the case in baseline version), the H-matrices are + just calculated by: + +
+  H11(k,n[e+1] = h11(b(k))
+  (...)
+  b(k): parameter index according to mapping table
+  
+ +

Processing of the samples in the sub subbands

+ this loop includes the interpolation of the coefficients Hxx + ************************************************************************************************/ + + + /* loop thru all groups ... */ + HybrLeftReal = mHybridRealLeft; + HybrLeftImag = mHybridImagLeft; + HybrRightReal = mHybridRealRight; + HybrRightImag = mHybridImagRight; + + /******************************************************/ + /* construct stereo sub subband signals according to: */ + /* */ + /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */ + /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */ + /******************************************************/ + for ( group = 0; group < SUBQMF_GROUPS; group++ ) { + + h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group]; + h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group]; + h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group]; + h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group]; + + subband = groupBorders20[group]; + + tmpLeft = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]); + tmpRight = fMultAddDiv2( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]); + HybrLeftReal [subband] = tmpLeft<<1; + HybrRightReal[subband] = tmpRight<<1; + + tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]); + tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]); + HybrLeftImag [subband] = tmpLeft; + HybrRightImag[subband] = tmpRight; + } + + /* continue in the qmf buffers */ + HybrLeftReal = QmfLeftReal; + HybrLeftImag = QmfLeftImag; + HybrRightReal = QmfRightReal; + HybrRightImag = QmfRightImag; + + for (; group < NO_IID_GROUPS; group++ ) { + + h_ps_d->specificTo.mpeg.coef.H11r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH11r[group]; + h_ps_d->specificTo.mpeg.coef.H12r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH12r[group]; + h_ps_d->specificTo.mpeg.coef.H21r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH21r[group]; + h_ps_d->specificTo.mpeg.coef.H22r[group] += h_ps_d->specificTo.mpeg.coef.DeltaH22r[group]; + + for ( subband = groupBorders20[group]; subband < groupBorders20[group + 1]; subband++ ) + { + tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightReal[subband]); + tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftReal[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightReal[subband]); + HybrLeftReal [subband] = tmpLeft; + HybrRightReal[subband] = tmpRight; + + tmpLeft = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H11r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H21r[group], HybrRightImag[subband]); + tmpRight = fMultAdd( fMultDiv2(h_ps_d->specificTo.mpeg.coef.H12r[group], HybrLeftImag[subband]), h_ps_d->specificTo.mpeg.coef.H22r[group], HybrRightImag[subband]); + HybrLeftImag [subband] = tmpLeft; + HybrRightImag[subband] = tmpRight; + + } /* subband */ + } +} + + +/***************************************************************************/ +/*! + \brief Applies IID, ICC, IPD and OPD parameters to the current frame. + + \return none + +****************************************************************************/ +void +ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ + FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ + FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ + FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ + FIXP_DBL *iIntBufferRight /*!< imag bands right qmf channel (38x64) */ + ) +{ + + /*! + The 64-band QMF representation of the monaural signal generated by the SBR tool + is used as input of the PS tool. After the PS processing, the outputs of the left + and right hybrid synthesis filterbanks are used to generate the stereo output + signal. + +
+
+             -------------            ----------            -------------
+            | Hybrid      | M_n[k,m] |          | L_n[k,m] | Hybrid      | l[n]
+   m[n] --->| analysis    |--------->|          |--------->| synthesis   |----->
+            | filter bank |          |          |          | filter bank |
+             -------------           | Stereo   |           -------------
+                   |                 | recon-   |
+                   |                 | stuction |
+                  \|/                |          |
+             -------------           |          |
+            | De-         | D_n[k,m] |          |
+            | correlation |--------->|          |
+             -------------           |          |           -------------
+                                     |          | R_n[k,m] | Hybrid      | r[n]
+                                     |          |--------->| synthesis   |----->
+   IID, ICC ------------------------>|          |          | filter bank |
+  (IPD, OPD)                          ----------            -------------
+
+  m[n]:      QMF represantation of the mono input
+  M_n[k,m]:  (sub-)sub-band domain signals of the mono input
+  D_n[k,m]:  decorrelated (sub-)sub-band domain signals
+  L_n[k,m]:  (sub-)sub-band domain signals of the left output
+  R_n[k,m]:  (sub-)sub-band domain signals of the right output
+  l[n],r[n]: left/right output signals
+
+  
+ */ + + /* get temporary hybrid qmf values of one timeslot */ + C_ALLOC_SCRATCH_START(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_START(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_START(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_START(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); + + SCHAR sf_IntBuffer = h_ps_d->sf_IntBuffer; + + /* clear workbuffer */ + FDKmemclear(hybridRealLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); + FDKmemclear(hybridImagLeft, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); + FDKmemclear(hybridRealRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); + FDKmemclear(hybridImagRight, NO_SUB_QMF_CHANNELS*sizeof(FIXP_DBL)); + + + /*! + Hybrid analysis filterbank: + The lower 3 (5) of the 64 QMF subbands are further split to provide better frequency resolution. + for PS processing. + For the 10 and 20 stereo bands configuration, the QMF band H_0(w) is split + up into 8 (sub-) sub-bands and the QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) + 4th. (See figures 8.20 and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) + */ + + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing */ + { /* fill hybrid delay buffer. */ + h_ps_d->procFrameBased = 0; + + fillHybridDelayLine( rIntBufferLeft, + iIntBufferLeft, + hybridRealLeft, + hybridImagLeft, + hybridRealRight, + hybridImagRight, + &h_ps_d->specificTo.mpeg.hybrid ); + } + + slotBasedHybridAnalysis ( rIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */ + iIntBufferLeft[HYBRID_FILTER_DELAY], /* qmf filterbank values */ + hybridRealLeft, /* hybrid filterbank values */ + hybridImagLeft, /* hybrid filterbank values */ + &h_ps_d->specificTo.mpeg.hybrid); /* hybrid filterbank handle */ + + + SCHAR hybridScal = h_ps_d->specificTo.mpeg.hybrid.sf_mQmfBuffer; + + + /*! + Decorrelation: + By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) are + converted into de-correlated (sub-)sub-band samples d_k(n). + - k: frequency in hybrid spectrum + - n: time index + */ + + deCorrelateSlotBased( h_ps_d, /* parametric stereo decoder handle */ + hybridRealLeft, /* left hybrid time slot */ + hybridImagLeft, + hybridScal, /* scale factor of left hybrid time slot */ + rIntBufferLeft[0], /* left qmf time slot */ + iIntBufferLeft[0], + sf_IntBuffer, /* scale factor of left and right qmf time slot */ + hybridRealRight, /* right hybrid time slot */ + hybridImagRight, + rIntBufferRight, /* right qmf time slot */ + iIntBufferRight ); + + + + /*! + Stereo Processing: + The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according to + the stereo cues which are defined per stereo band. + */ + + + applySlotBasedRotation( h_ps_d, /* parametric stereo decoder handle */ + hybridRealLeft, /* left hybrid time slot */ + hybridImagLeft, + rIntBufferLeft[0], /* left qmf time slot */ + iIntBufferLeft[0], + hybridRealRight, /* right hybrid time slot */ + hybridImagRight, + rIntBufferRight, /* right qmf time slot */ + iIntBufferRight ); + + + + + /*! + Hybrid synthesis filterbank: + The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the hybrid synthesis + filterbanks which are identical to the 64 complex synthesis filterbank of the SBR tool. The + input to the filterbank are slots of 64 QMF samples. For each slot the filterbank outputs one + block of 64 samples of one reconstructed stereo channel. The hybrid synthesis filterbank is + computed seperatly for the left and right channel. + */ + + + /* left channel */ + slotBasedHybridSynthesis ( hybridRealLeft, /* one timeslot of hybrid filterbank values */ + hybridImagLeft, + rIntBufferLeft[0], /* one timeslot of qmf filterbank values */ + iIntBufferLeft[0], + &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */ + + /* right channel */ + slotBasedHybridSynthesis ( hybridRealRight, /* one timeslot of hybrid filterbank values */ + hybridImagRight, + rIntBufferRight, /* one timeslot of qmf filterbank values */ + iIntBufferRight, + &h_ps_d->specificTo.mpeg.hybrid ); /* hybrid filterbank handle */ + + + + + + + + /* free temporary hybrid qmf values of one timeslot */ + C_ALLOC_SCRATCH_END(hybridImagRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_END(hybridRealRight, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_END(hybridImagLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); + C_ALLOC_SCRATCH_END(hybridRealLeft, FIXP_DBL, NO_SUB_QMF_CHANNELS); + +}/* END ApplyPsSlot */ + + +/***************************************************************************/ +/*! + + \brief assigns timeslots to an array + + \return + +****************************************************************************/ + +static void assignTimeSlotsPS (FIXP_DBL *bufAdr, + FIXP_DBL **bufPtr, + const int numSlots, + const int numChan) +{ + FIXP_DBL *ptr; + int slot; + ptr = bufAdr; + for(slot=0; slot < numSlots; slot++) { + bufPtr [slot] = ptr; + ptr += numChan; + } +} + diff --git a/libSBRdec/src/psdec.h b/libSBRdec/src/psdec.h new file mode 100644 index 00000000..3dbc76d4 --- /dev/null +++ b/libSBRdec/src/psdec.h @@ -0,0 +1,352 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef __PSDEC_H +#define __PSDEC_H + +#include "sbrdecoder.h" + + + +/* This PS decoder implements the baseline version. So it always uses the */ +/* hybrid filter structure for 20 stereo bands and does not implemet IPD/OPD */ +/* synthesis. The baseline version has to support the complete PS bitstream */ +/* syntax. But IPD/OPD data is ignored and set to 0. If 34 stereo band config */ +/* is used in the bitstream for IIS/ICC the decoded parameters are mapped to */ +/* 20 stereo bands. */ + + +#include "FDK_bitstream.h" + +#include "psdec_hybrid.h" + +#define SCAL_HEADROOM ( 2 ) + +#define PS_EXTENSION_SIZE_BITS ( 4 ) +#define PS_EXTENSION_ESC_COUNT_BITS ( 8 ) + +#define NO_QMF_CHANNELS ( 64 ) +#define MAX_NUM_COL ( 32 ) + + + #define NO_QMF_BANDS_HYBRID20 ( 3 ) + #define NO_SUB_QMF_CHANNELS ( 12 ) + + #define NRG_INT_COEFF ( 0.75f ) + #define INT_FILTER_COEFF (FL2FXCONST_DBL( 1.0f - NRG_INT_COEFF )) + #define PEAK_DECAY_FACTOR (FL2FXCONST_DBL( 0.765928338364649f )) + #define TRANSIENT_IMPACT_FACTOR (FL2FXCONST_DBL( 2.0 / 3.0 )) + + #define NO_SERIAL_ALLPASS_LINKS ( 3 ) + #define MAX_NO_PS_ENV ( 4 + 1 ) /* +1 needed for VAR_BORDER */ + + #define MAX_DELAY_BUFFER_SIZE ( 14 ) + #define NO_DELAY_BUFFER_BANDS ( 35 ) + + #define NO_HI_RES_BINS ( 34 ) + #define NO_MID_RES_BINS ( 20 ) + #define NO_LOW_RES_BINS ( 10 ) + + #define FIRST_DELAY_SB ( 23 ) + #define NO_SAMPLE_DELAY_ALLPASS ( 2 ) + #define NO_DELAY_LENGTH_VECTORS ( 12 ) /* d(m): d(0)=3 + d(1)=4 + d(2)=5 */ + + #define NO_HI_RES_IID_BINS ( NO_HI_RES_BINS ) + #define NO_HI_RES_ICC_BINS ( NO_HI_RES_BINS ) + + #define NO_MID_RES_IID_BINS ( NO_MID_RES_BINS ) + #define NO_MID_RES_ICC_BINS ( NO_MID_RES_BINS ) + + #define NO_LOW_RES_IID_BINS ( NO_LOW_RES_BINS ) + #define NO_LOW_RES_ICC_BINS ( NO_LOW_RES_BINS ) + + #define SUBQMF_GROUPS ( 10 ) + #define QMF_GROUPS ( 12 ) + + #define SUBQMF_GROUPS_HI_RES ( 32 ) + #define QMF_GROUPS_HI_RES ( 18 ) + + #define NO_IID_GROUPS ( SUBQMF_GROUPS + QMF_GROUPS ) + #define NO_IID_GROUPS_HI_RES ( SUBQMF_GROUPS_HI_RES + QMF_GROUPS_HI_RES ) + + #define NO_IID_STEPS ( 7 ) /* 1 .. + 7 */ + #define NO_IID_STEPS_FINE ( 15 ) /* 1 .. +15 */ + #define NO_ICC_STEPS ( 8 ) /* 0 .. + 7 */ + + #define NO_IID_LEVELS ( 2 * NO_IID_STEPS + 1 ) /* - 7 .. + 7 */ + #define NO_IID_LEVELS_FINE ( 2 * NO_IID_STEPS_FINE + 1 ) /* -15 .. +15 */ + #define NO_ICC_LEVELS ( NO_ICC_STEPS ) /* 0 .. + 7 */ + + #define FIXP_SQRT05 ((FIXP_DBL)0x5a827980) /* 1/SQRT2 */ + + struct PS_DEC_COEFFICIENTS { + + FIXP_DBL H11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + FIXP_DBL DeltaH11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL DeltaH12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL DeltaH21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL DeltaH22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + SCHAR aaIidIndexMapped[MAX_NO_PS_ENV][NO_HI_RES_IID_BINS]; /*!< The mapped IID index for all envelopes and all IID bins */ + SCHAR aaIccIndexMapped[MAX_NO_PS_ENV][NO_HI_RES_ICC_BINS]; /*!< The mapped ICC index for all envelopes and all ICC bins */ + + }; + + + + +typedef enum { + ppt_none = 0, + ppt_mpeg = 1, + ppt_drm = 2 +} PS_PAYLOAD_TYPE; + + +typedef struct { + UCHAR bPsHeaderValid; /*!< set if new header is available from bitstream */ + + UCHAR bEnableIid; /*!< One bit denoting the presence of IID parameters */ + UCHAR bEnableIcc; /*!< One bit denoting the presence of ICC parameters */ + UCHAR bEnableExt; /*!< The PS extension layer is enabled using the enable_ext bit. + If it is set to %1 the IPD and OPD parameters are sent. + If it is disabled, i.e. %0, the extension layer is skipped. */ + + UCHAR modeIid; /*!< The configuration of IID parameters (number of bands and + quantisation grid, iid_quant) is determined by iid_mode. */ + UCHAR modeIcc; /*!< The configuration of Inter-channel Coherence parameters + (number of bands and quantisation grid) is determined by + icc_mode. */ + + UCHAR freqResIid; /*!< 0=low, 1=mid or 2=high frequency resolution for iid */ + UCHAR freqResIcc; /*!< 0=low, 1=mid or 2=high frequency resolution for icc */ + + UCHAR bFineIidQ; /*!< Use fine Iid quantisation. */ + + UCHAR bFrameClass; /*!< The frame_class bit determines whether the parameter + positions of the current frame are uniformly spaced + accross the frame or they are defined using the positions + described by border_position. */ + + UCHAR noEnv; /*!< The number of envelopes per frame */ + UCHAR aEnvStartStop[MAX_NO_PS_ENV+1]; /*!< In case of variable parameter spacing the parameter + positions are determined by border_position */ + + SCHAR abIidDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for IID, 0 => freq */ + SCHAR abIccDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for ICC, 0 => freq */ + + SCHAR aaIidIndex[MAX_NO_PS_ENV][NO_HI_RES_IID_BINS]; /*!< The IID index for all envelopes and all IID bins */ + SCHAR aaIccIndex[MAX_NO_PS_ENV][NO_HI_RES_ICC_BINS]; /*!< The ICC index for all envelopes and all ICC bins */ + +} MPEG_PS_BS_DATA; + + + +struct PS_DEC { + + SCHAR noSubSamples; + SCHAR noChannels; + + SCHAR procFrameBased; /*!< Helper to detected switching from frame based to slot based + processing */ + + PS_PAYLOAD_TYPE bPsDataAvail[(1)+1]; /*!< set if new data available from bitstream */ + UCHAR psDecodedPrv; /*!< set if PS has been processed in the last frame */ + + /* helpers for frame delay line */ + UCHAR bsLastSlot; /*!< Index of last read slot. */ + UCHAR bsReadSlot; /*!< Index of current read slot for additional delay. */ + UCHAR processSlot; /*!< Index of current slot for processing (need for add. delay). */ + + + INT rescal; + INT sf_IntBuffer; + + union { /* Bitstream data */ + MPEG_PS_BS_DATA mpeg; /*!< Struct containing all MPEG specific PS data from bitstream. */ + } bsData[(1)+1]; + + shouldBeUnion { /* Static data */ + struct { + SCHAR aIidPrevFrameIndex[NO_HI_RES_IID_BINS]; /*!< The IID index for previous frame */ + SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for previous frame */ + + UCHAR delayBufIndex; /*!< Pointer to where the latest sample is in buffer */ + UCHAR noSampleDelay; /*!< How many QMF samples delay is used. */ + UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */ + + UCHAR aDelayRBufIndexSer[NO_SERIAL_ALLPASS_LINKS]; /*!< Delay buffer for reverb filter */ + UCHAR aDelayBufIndexDelayQmf[NO_QMF_CHANNELS-FIRST_DELAY_SB]; /*!< Delay buffer for ICC group 20 & 21 */ + + SCHAR scaleFactorPsDelayBuffer; /*!< Scale factor for ps delay buffer */ + + /* hybrid filter bank delay lines */ + FIXP_DBL aaQmfDelayBufReal[(NO_QMF_CHANNELS-FIRST_DELAY_SB) + (MAX_DELAY_BUFFER_SIZE-1)*(NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)]; + FIXP_DBL aaQmfDelayBufImag[(NO_QMF_CHANNELS-FIRST_DELAY_SB) + (MAX_DELAY_BUFFER_SIZE-1)*(NO_DELAY_BUFFER_BANDS-FIRST_DELAY_SB)]; + + FIXP_DBL *pAaRealDelayBufferQmf[MAX_DELAY_BUFFER_SIZE]; /*!< Real part delay buffer */ + FIXP_DBL *pAaImagDelayBufferQmf[MAX_DELAY_BUFFER_SIZE]; /*!< Imaginary part delay buffer */ + + FIXP_DBL aaRealDelayBufferQmf[NO_SAMPLE_DELAY_ALLPASS][FIRST_DELAY_SB]; /*!< Real part delay buffer */ + FIXP_DBL aaImagDelayBufferQmf[NO_SAMPLE_DELAY_ALLPASS][FIRST_DELAY_SB]; /*!< Imaginary part delay buffer*/ + + FIXP_DBL aaRealDelayBufferSubQmf[NO_SAMPLE_DELAY_ALLPASS][NO_SUB_QMF_CHANNELS]; /*!< Real part delay buffer */ + FIXP_DBL aaImagDelayBufferSubQmf[NO_SAMPLE_DELAY_ALLPASS][NO_SUB_QMF_CHANNELS]; /*!< Imaginary part delay buffer */ + + FIXP_DBL aaaRealDelayRBufferSerQmf[FIRST_DELAY_SB][NO_DELAY_LENGTH_VECTORS]; /*!< Real part delay buffer */ + FIXP_DBL aaaImagDelayRBufferSerQmf[FIRST_DELAY_SB][NO_DELAY_LENGTH_VECTORS]; /*!< Imaginary part delay buffer */ + + FIXP_DBL aaaRealDelayRBufferSerSubQmf[NO_SUB_QMF_CHANNELS][NO_DELAY_LENGTH_VECTORS]; /*!< Real part delay buffer */ + FIXP_DBL aaaImagDelayRBufferSerSubQmf[NO_SUB_QMF_CHANNELS][NO_DELAY_LENGTH_VECTORS]; /*!< Imaginary part delay buffer */ + + HYBRID hybrid; /*!< hybrid filter bank struct 1 or 2. */ + + FIXP_DBL aPrevNrgBin[NO_MID_RES_BINS]; /*!< energy of previous frame */ + FIXP_DBL aPrevPeakDiffBin[NO_MID_RES_BINS]; /*!< peak difference of previous frame */ + FIXP_DBL aPeakDecayFastBin[NO_MID_RES_BINS]; /*!< Saved max. peak decay value per bin */ + SCHAR aPowerPrevScal[NO_MID_RES_BINS]; /*!< Last power value (each bin) of previous frame */ + + FIXP_DBL h11rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ + FIXP_DBL h12rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ + FIXP_DBL h21rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ + FIXP_DBL h22rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) coefficients */ + + PS_DEC_COEFFICIENTS coef; /*!< temporal coefficients (reusable scratch memory) */ + + } mpeg; + + } specificTo; + + +}; + +typedef struct PS_DEC *HANDLE_PS_DEC; + + +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, int aacSamplesPerFrame); + +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC); + +void +scalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **fixpQmfReal, /* qmf filterbank values */ + FIXP_DBL **fixpQmfImag, /* qmf filterbank values */ + int lsb, /* sbr start subband */ + int scaleFactorLowBandSplitLow, + int scaleFactorLowBandSplitHigh, + SCHAR *scaleFactorLowBand_lb, + SCHAR *scaleFactorLowBand_hb, + int scaleFactorHighBands, + INT *scaleFactorHighBand, + INT noCols); + +void +rescalFilterBankValues( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **QmfBufferReal, /* qmf filterbank values */ + FIXP_DBL **QmfBufferImag, /* qmf filterbank values */ + int lsb, /* sbr start subband */ + INT noCols); + + +void +initSlotBasedRotation( HANDLE_PS_DEC h_ps_d, + int env, + int usb); + +void +ApplyPsSlot( HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **rIntBufferLeft, /* real values of left qmf timeslot */ + FIXP_DBL **iIntBufferLeft, /* imag values of left qmf timeslot */ + FIXP_DBL *rIntBufferRight, /* real values of right qmf timeslot */ + FIXP_DBL *iIntBufferRight); /* imag values of right qmf timeslot */ + + + +#endif /* __PSDEC_H */ diff --git a/libSBRdec/src/psdec_hybrid.cpp b/libSBRdec/src/psdec_hybrid.cpp new file mode 100644 index 00000000..cbd0e925 --- /dev/null +++ b/libSBRdec/src/psdec_hybrid.cpp @@ -0,0 +1,652 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "psdec_hybrid.h" + + +#include "fft.h" +#include "sbr_ram.h" + +#include "FDK_tools_rom.h" +#include "sbr_rom.h" + +/******************************************************************************* + Functionname: InitHybridFilterBank + ******************************************************************************* + + Description: Init one instance of HANDLE_HYBRID stuct + + Arguments: + + Return: none + +*******************************************************************************/ + + +SBR_ERROR +InitHybridFilterBank ( HANDLE_HYBRID hs, /*!< Handle to HYBRID struct. */ + SCHAR frameSize, /*!< Framesize (in Qmf súbband samples). */ + SCHAR noBands, /*!< Number of Qmf bands for hybrid filtering. */ + const UCHAR *pResolution ) /*!< Resolution in Qmf bands (length noBands). */ +{ + SCHAR i; + UCHAR maxNoChannels = 0; + + for (i = 0; i < noBands; i++) { + hs->pResolution[i] = pResolution[i]; + if(pResolution[i] > maxNoChannels) + maxNoChannels = pResolution[i]; + } + + hs->nQmfBands = noBands; + hs->frameSize = frameSize; + hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1; + + hs->sf_mQmfBuffer = 0; + + return SBRDEC_OK; +} + +/******************************************************************************* + Functionname: dualChannelFiltering + ******************************************************************************* + + Description: fast 2-channel real-valued filtering with 6-tap delay. + + Arguments: + + Return: none + +*******************************************************************************/ + +/*! +2 channel filter +
+   Filter Coefs:
+   0.0,
+   0.01899487526049,
+   0.0,
+   -0.07293139167538,
+   0.0,
+   0.30596630545168,
+   0.5,
+   0.30596630545168,
+   0.0,
+   -0.07293139167538,
+   0.0,
+   0.01899487526049,
+   0.0
+
+
+   Filter design:
+   h[q,n] = g[n] * cos(2pi/2 * q * (n-6) );  n = 0..12,  q = 0,1;
+
+   ->  h[0,n] = g[n] * 1;
+   ->  h[1,n] = g[n] * pow(-1,n);
+
+*/ + +static void slotBasedDualChannelFiltering( const FIXP_DBL *pQmfReal, + const FIXP_DBL *pQmfImag, + + FIXP_DBL *mHybridReal, + FIXP_DBL *mHybridImag) +{ + + FIXP_DBL t1, t3, t5, t6; + + /* symmetric filter coefficients */ + + /* you don't have to shift the result after fMult because of p2_13_20 <= 0.5 */ + t1 = fMultDiv2(p2_13_20[1] , ( (pQmfReal[1] >> 1) + (pQmfReal[11] >> 1))); + t3 = fMultDiv2(p2_13_20[3] , ( (pQmfReal[3] >> 1) + (pQmfReal[ 9] >> 1))); + t5 = fMultDiv2(p2_13_20[5] , ( (pQmfReal[5] >> 1) + (pQmfReal[ 7] >> 1))); + t6 = fMultDiv2(p2_13_20[6] , (pQmfReal[6] >> 1) ); + + mHybridReal[0] = (t1 + t3 + t5 + t6) << 2; + mHybridReal[1] = (- t1 - t3 - t5 + t6) << 2; + + t1 = fMultDiv2(p2_13_20[1] , ( (pQmfImag[1] >> 1) + (pQmfImag[11] >> 1))); + t3 = fMultDiv2(p2_13_20[3] , ( (pQmfImag[3] >> 1) + (pQmfImag[ 9] >> 1))); + t5 = fMultDiv2(p2_13_20[5] , ( (pQmfImag[5] >> 1) + (pQmfImag[ 7] >> 1))); + t6 = fMultDiv2(p2_13_20[6] , pQmfImag[6] >> 1 ); + + mHybridImag[0] = (t1 + t3 + t5 + t6) << 2; + mHybridImag[1] = (- t1 - t3 - t5 + t6) << 2; +} + + +/******************************************************************************* + Functionname: eightChannelFiltering + ******************************************************************************* + + Description: fast 8-channel complex-valued filtering with 6-tap delay. + + Arguments: + + Return: none + +*******************************************************************************/ +/*! + 8 channel filter + + Implementation using a FFT of length 8 +
+   prototype filter coefficients:
+   0.00746082949812   0.02270420949825   0.04546865930473   0.07266113929591   0.09885108575264   0.11793710567217
+   0.125
+   0.11793710567217   0.09885108575264   0.07266113929591   0.04546865930473   0.02270420949825   0.00746082949812
+
+   Filter design:
+   N = 13; Q = 8;
+   h[q,n]       = g[n] * exp(j * 2 * pi / Q * (q + .5) * (n - 6));  n = 0..(N-1),  q = 0..(Q-1);
+
+   Time Signal:   x[t];
+   Filter Bank Output
+   y[q,t] = conv(x[t],h[q,t]) = conv(h[q,t],x[t]) = sum(x[k] * h[q, t - k] ) = sum(h[q, k] * x[t - k] ); k = 0..(N-1);
+
+   y[q,t] =   x[t - 12]*h[q, 12]  +  x[t - 11]*h[q, 11]  +  x[t - 10]*h[q, 10]  +  x[t -  9]*h[q,  9]
+           +  x[t -  8]*h[q,  8]  +  x[t -  7]*h[q,  7]
+           +  x[t -  6]*h[q,  6]
+           +  x[t -  5]*h[q,  5]  +  x[t -  4]*h[q,  4]
+           +  x[t -  3]*h[q,  3]  +  x[t -  2]*h[q,  2]  +  x[t -  1]*h[q,  1]  +  x[t -  0]*h[q,  0];
+
+   h'[q, n] = h[q,(N-1)-n] = g[n] * exp(j * 2 * pi / Q * (q + .5) * (6 - n));  n = 0..(N-1),  q = 0..(Q-1);
+
+   y[q,t] =   x[t - 12]*h'[q,  0]  +  x[t - 11]*h'[q,  1]  +  x[t - 10]*h'[q,  2]  +  x[t -  9]*h'[q,  3]
+           +  x[t -  8]*h'[q,  4]  +  x[t -  7]*h'[q,  5]
+           +  x[t -  6]*h'[q,  6]
+           +  x[t -  5]*h'[q,  7]  +  x[t -  4]*h'[q,  8]
+           +  x[t -  3]*h'[q,  9]  +  x[t -  2]*h'[q, 10]  +  x[t -  1]*h'[q, 11]  +  x[t -  0]*h'[q, 12];
+
+   Try to split off FFT Modulation Term:
+   FFT(x[t], q) = sum(x[t+k]*exp(-j*2*pi/N *q * k))
+                                           c                                           m
+   Step 1:  h'[q,n] = g[n] * ( exp(j * 2 * pi / 8 * .5 * (6 - n)) ) * ( exp (j * 2 * pi / 8 * q * (6 - n)) );
+
+    h'[q,n] = g[n] *c[n] * m[q,n]; (see above)
+    c[n]    = exp( j * 2 * pi / 8 * .5 * (6 - n) );
+    m[q,n]  = exp( j * 2 * pi / 8 *  q * (6 - n) );
+
+    y[q,t] = x[t -  0]*g[0]*c[0]*m[q,0]  +  x[t -  1]*g[1]*c[ 1]*m[q, 1]  + ...
+             ...                         +  x[t - 12]*g[2]*c[12]*m[q,12];
+
+                                                                              |
+    n                   m                            *exp(-j*2*pi)            |   n'                   fft
+-------------------------------------------------------------------------------------------------------------------------
+    0       exp( j * 2 * pi / 8 * q * 6) ->  exp(-j * 2 * pi / 8 * q * 2)     |   2         exp(-j * 2 * pi / 8 * q * 0)
+    1       exp( j * 2 * pi / 8 * q * 5) ->  exp(-j * 2 * pi / 8 * q * 3)     |   3         exp(-j * 2 * pi / 8 * q * 1)
+    2       exp( j * 2 * pi / 8 * q * 4) ->  exp(-j * 2 * pi / 8 * q * 4)     |   4         exp(-j * 2 * pi / 8 * q * 2)
+    3       exp( j * 2 * pi / 8 * q * 3) ->  exp(-j * 2 * pi / 8 * q * 5)     |   5         exp(-j * 2 * pi / 8 * q * 3)
+    4       exp( j * 2 * pi / 8 * q * 2) ->  exp(-j * 2 * pi / 8 * q * 6)     |   6         exp(-j * 2 * pi / 8 * q * 4)
+    5       exp( j * 2 * pi / 8 * q * 1) ->  exp(-j * 2 * pi / 8 * q * 7)     |   7         exp(-j * 2 * pi / 8 * q * 5)
+    6       exp( j * 2 * pi / 8 * q * 0)                                      |   0         exp(-j * 2 * pi / 8 * q * 6)
+    7       exp(-j * 2 * pi / 8 * q * 1)                                      |   1         exp(-j * 2 * pi / 8 * q * 7)
+    8       exp(-j * 2 * pi / 8 * q * 2)                                      |   2
+    9       exp(-j * 2 * pi / 8 * q * 3)                                      |   3
+    10      exp(-j * 2 * pi / 8 * q * 4)                                      |   4
+    11      exp(-j * 2 * pi / 8 * q * 5)                                      |   5
+    12      exp(-j * 2 * pi / 8 * q * 6)                                      |   6
+
+
+    now use fft modulation coefficients
+    m[6]  =       = fft[0]
+    m[7]  =       = fft[1]
+    m[8]  = m[ 0] = fft[2]
+    m[9]  = m[ 1] = fft[3]
+    m[10] = m[ 2] = fft[4]
+    m[11] = m[ 3] = fft[5]
+    m[12] = m[ 4] = fft[6]
+            m[ 5] = fft[7]
+
+    y[q,t] = (                       x[t- 6]*g[ 6]*c[ 6] ) * fft[q,0]  +
+             (                       x[t- 7]*g[ 7]*c[ 7] ) * fft[q,1]  +
+             ( x[t- 0]*g[ 0]*c[ 0] + x[t- 8]*g[ 8]*c[ 8] ) * fft[q,2]  +
+             ( x[t- 1]*g[ 1]*c[ 1] + x[t- 9]*g[ 9]*c[ 9] ) * fft[q,3]  +
+             ( x[t- 2]*g[ 2]*c[ 2] + x[t-10]*g[10]*c[10] ) * fft[q,4]  +
+             ( x[t- 3]*g[ 3]*c[ 3] + x[t-11]*g[11]*c[11] ) * fft[q,5]  +
+             ( x[t- 4]*g[ 4]*c[ 4] + x[t-12]*g[12]*c[12] ) * fft[q,6]  +
+             ( x[t- 5]*g[ 5]*c[ 5]                       ) * fft[q,7];
+
+    pre twiddle factors c[n] = exp(j * 2 * pi / 8 * .5 * (6 - n));
+    n                c]           |  n                c[n]         |  n                c[n]
+---------------------------------------------------------------------------------------------------
+    0       exp( j * 6 * pi / 8)  |  1       exp( j * 5 * pi / 8)  |  2       exp( j * 4 * pi / 8)
+    3       exp( j * 3 * pi / 8)  |  4       exp( j * 2 * pi / 8)  |  5       exp( j * 1 * pi / 8)
+    6       exp( j * 0 * pi / 8)  |  7       exp(-j * 1 * pi / 8)  |  8       exp(-j * 2 * pi / 8)
+    9       exp(-j * 3 * pi / 8)  | 10       exp(-j * 4 * pi / 8)  | 11       exp(-j * 5 * pi / 8)
+   12       exp(-j * 6 * pi / 8)  |                                |
+
+*/ + +/* defining rotation factors for *ChannelFiltering */ + +#define cos0Pi FL2FXCONST_DBL( 1.f) +#define sin0Pi FL2FXCONST_DBL( 0.f) + +#define cos1Pi FL2FXCONST_DBL(-1.f) +#define sin1Pi FL2FXCONST_DBL( 0.f) + +#define cos1Pi_2 FL2FXCONST_DBL( 0.f) +#define sin1Pi_2 FL2FXCONST_DBL( 1.f) + +#define cos1Pi_3 FL2FXCONST_DBL( 0.5f) +#define sin1Pi_3 FL2FXCONST_DBL( 0.86602540378444f) + +#define cos0Pi_4 cos0Pi +#define cos1Pi_4 FL2FXCONST_DBL(0.70710678118655f) +#define cos2Pi_4 cos1Pi_2 +#define cos3Pi_4 (-cos1Pi_4) +#define cos4Pi_4 (-cos0Pi_4) +#define cos5Pi_4 cos3Pi_4 +#define cos6Pi_4 cos2Pi_4 + +#define sin0Pi_4 sin0Pi +#define sin1Pi_4 FL2FXCONST_DBL(0.70710678118655f) +#define sin2Pi_4 sin1Pi_2 +#define sin3Pi_4 sin1Pi_4 +#define sin4Pi_4 sin0Pi_4 +#define sin5Pi_4 (-sin3Pi_4) +#define sin6Pi_4 (-sin2Pi_4) + +#define cos0Pi_8 cos0Pi +#define cos1Pi_8 FL2FXCONST_DBL(0.92387953251129f) +#define cos2Pi_8 cos1Pi_4 +#define cos3Pi_8 FL2FXCONST_DBL(0.38268343236509f) +#define cos4Pi_8 cos2Pi_4 +#define cos5Pi_8 (-cos3Pi_8) +#define cos6Pi_8 (-cos2Pi_8) + +#define sin0Pi_8 sin0Pi +#define sin1Pi_8 cos3Pi_8 +#define sin2Pi_8 sin1Pi_4 +#define sin3Pi_8 cos1Pi_8 +#define sin4Pi_8 sin2Pi_4 +#define sin5Pi_8 sin3Pi_8 +#define sin6Pi_8 sin1Pi_4 + +#if defined(ARCH_PREFER_MULT_32x16) + #define FIXP_HYB FIXP_SGL + #define FIXP_CAST FX_DBL2FX_SGL +#else + #define FIXP_HYB FIXP_DBL + #define FIXP_CAST +#endif + +static const FIXP_HYB cr[13] = +{ + FIXP_CAST(cos6Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos4Pi_8), + FIXP_CAST(cos3Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos1Pi_8), + FIXP_CAST(cos0Pi_8), + FIXP_CAST(cos1Pi_8), FIXP_CAST(cos2Pi_8), FIXP_CAST(cos3Pi_8), + FIXP_CAST(cos4Pi_8), FIXP_CAST(cos5Pi_8), FIXP_CAST(cos6Pi_8) +}; + +static const FIXP_HYB ci[13] = +{ + FIXP_CAST( sin6Pi_8), FIXP_CAST( sin5Pi_8), FIXP_CAST( sin4Pi_8), + FIXP_CAST( sin3Pi_8), FIXP_CAST( sin2Pi_8), FIXP_CAST( sin1Pi_8), + FIXP_CAST( sin0Pi_8) , + FIXP_CAST(-sin1Pi_8), FIXP_CAST(-sin2Pi_8), FIXP_CAST(-sin3Pi_8), + FIXP_CAST(-sin4Pi_8), FIXP_CAST(-sin5Pi_8), FIXP_CAST(-sin6Pi_8) +}; + +static void slotBasedEightChannelFiltering( const FIXP_DBL *pQmfReal, + const FIXP_DBL *pQmfImag, + + FIXP_DBL *mHybridReal, + FIXP_DBL *mHybridImag) +{ + + int bin; + FIXP_DBL _fft[128 + ALIGNMENT_DEFAULT - 1]; + FIXP_DBL *fft = (FIXP_DBL *)ALIGN_PTR(_fft); + +#if defined(ARCH_PREFER_MULT_32x16) + const FIXP_SGL *p = p8_13_20; /* BASELINE_PS */ +#else + const FIXP_DBL *p = p8_13_20; /* BASELINE_PS */ +#endif + + /* pre twiddeling */ + + /* x*(a*b + c*d) = fMultDiv2(x, fMultAddDiv2(fMultDiv2(a, b), c, d)) */ + /* x*(a*b - c*d) = fMultDiv2(x, fMultSubDiv2(fMultDiv2(a, b), c, d)) */ + FIXP_DBL accu1, accu2, accu3, accu4; + + #define TWIDDLE_1(n_0,n_1,n_2) \ + cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]); \ + accu1 = fMultDiv2(p[n_0], accu1); \ + accu2 = fMultDiv2(p[n_0], accu2); \ + cplxMultDiv2(&accu3, &accu4, pQmfReal[n_1], pQmfImag[n_1], cr[n_1], ci[n_1]); \ + accu3 = fMultDiv2(p[n_1], accu3); \ + accu4 = fMultDiv2(p[n_1], accu4); \ + fft[FIXP_FFT_IDX_R(n_2)] = accu1 + accu3; \ + fft[FIXP_FFT_IDX_I(n_2)] = accu2 + accu4; + + #define TWIDDLE_0(n_0,n_1) \ + cplxMultDiv2(&accu1, &accu2, pQmfReal[n_0], pQmfImag[n_0], cr[n_0], ci[n_0]); \ + fft[FIXP_FFT_IDX_R(n_1)] = fMultDiv2(p[n_0], accu1); \ + fft[FIXP_FFT_IDX_I(n_1)] = fMultDiv2(p[n_0], accu2); + + TWIDDLE_0( 6, 0) + TWIDDLE_0( 7, 1) + + TWIDDLE_1( 0, 8, 2) + TWIDDLE_1( 1, 9, 3) + TWIDDLE_1( 2,10, 4) + TWIDDLE_1( 3,11, 5) + TWIDDLE_1( 4,12, 6) + + TWIDDLE_0( 5, 7) + + fft_8 (fft); + + /* resort fft data into output array*/ + for(bin=0; bin<8;bin++ ) { + mHybridReal[bin] = fft[FIXP_FFT_IDX_R(bin)] << 4; + mHybridImag[bin] = fft[FIXP_FFT_IDX_I(bin)] << 4; + } +} + + +/******************************************************************************* + Functionname: fillHybridDelayLine + ******************************************************************************* + + Description: The delay line of the hybrid filter is filled and copied from + left to right. + + Return: none + +*******************************************************************************/ + +void +fillHybridDelayLine( FIXP_DBL **fixpQmfReal, /*!< Qmf real Values */ + FIXP_DBL **fixpQmfImag, /*!< Qmf imag Values */ + FIXP_DBL fixpHybridLeftR[12], /*!< Hybrid real Values left channel */ + FIXP_DBL fixpHybridLeftI[12], /*!< Hybrid imag Values left channel */ + FIXP_DBL fixpHybridRightR[12], /*!< Hybrid real Values right channel */ + FIXP_DBL fixpHybridRightI[12], /*!< Hybrid imag Values right channel */ + HANDLE_HYBRID hHybrid ) +{ + int i; + + for (i = 0; i < HYBRID_FILTER_DELAY; i++) { + slotBasedHybridAnalysis ( fixpQmfReal[i], + fixpQmfReal[i], + fixpHybridLeftR, + fixpHybridLeftI, + hHybrid ); + } + + FDKmemcpy(fixpHybridRightR, fixpHybridLeftR, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS); + FDKmemcpy(fixpHybridRightI, fixpHybridLeftI, sizeof(FIXP_DBL)*NO_SUB_QMF_CHANNELS); +} + + +/******************************************************************************* + Functionname: slotBasedHybridAnalysis + ******************************************************************************* + + Description: The lower QMF subbands are further split to provide better + frequency resolution for PS processing. + + Return: none + +*******************************************************************************/ + + +void +slotBasedHybridAnalysis ( FIXP_DBL *fixpQmfReal, /*!< Qmf real Values */ + FIXP_DBL *fixpQmfImag, /*!< Qmf imag Values */ + + FIXP_DBL fixpHybridReal[12], /*!< Hybrid real Values */ + FIXP_DBL fixpHybridImag[12], /*!< Hybrid imag Values */ + + HANDLE_HYBRID hHybrid) +{ + int k, band; + HYBRID_RES hybridRes; + int chOffset = 0; + + C_ALLOC_SCRATCH_START(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH); + + FIXP_DBL *pTempImagSlot = pTempRealSlot + HYBRID_FILTER_LENGTH; + FIXP_DBL *pWorkRealSlot = pTempImagSlot + HYBRID_FILTER_LENGTH; + FIXP_DBL *pWorkImagSlot = pWorkRealSlot + HYBRID_FILTER_LENGTH; + + /*! + Hybrid filtering is applied to the first hHybrid->nQmfBands QMF bands (3 when 10 or 20 stereo bands + are used, 5 when 34 stereo bands are used). For the remaining QMF bands a delay would be necessary. + But there is no need to implement a delay because there is a look-ahead of HYBRID_FILTER_DELAY = 6 + QMF samples in the low-band buffer. + */ + + for(band = 0; band < hHybrid->nQmfBands; band++) { + + /* get hybrid resolution per qmf band */ + /* in case of baseline ps 10/20 band stereo mode : */ + /* */ + /* qmfBand[0] : 8 ( HYBRID_8_CPLX ) */ + /* qmfBand[1] : 2 ( HYBRID_2_REAL ) */ + /* qmfBand[2] : 2 ( HYBRID_2_REAL ) */ + /* */ + /* (split the 3 lower qmf band to 12 hybrid bands) */ + + hybridRes = (HYBRID_RES)hHybrid->pResolution[band]; + + FDKmemcpy(pWorkRealSlot, hHybrid->mQmfBufferRealSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); + FDKmemcpy(pWorkImagSlot, hHybrid->mQmfBufferImagSlot[band], hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); + + pWorkRealSlot[hHybrid->qmfBufferMove] = fixpQmfReal[band]; + pWorkImagSlot[hHybrid->qmfBufferMove] = fixpQmfImag[band]; + + FDKmemcpy(hHybrid->mQmfBufferRealSlot[band], pWorkRealSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); + FDKmemcpy(hHybrid->mQmfBufferImagSlot[band], pWorkImagSlot + 1, hHybrid->qmfBufferMove * sizeof(FIXP_DBL)); + + if (fixpQmfReal) { + + /* actual filtering only if output signal requested */ + switch( hybridRes ) { + + /* HYBRID_2_REAL & HYBRID_8_CPLX are only needful for baseline ps */ + case HYBRID_2_REAL: + + slotBasedDualChannelFiltering( pWorkRealSlot, + pWorkImagSlot, + pTempRealSlot, + pTempImagSlot); + break; + + case HYBRID_8_CPLX: + + slotBasedEightChannelFiltering( pWorkRealSlot, + pWorkImagSlot, + pTempRealSlot, + pTempImagSlot); + break; + + default: + FDK_ASSERT(0); + } + + for(k = 0; k < (SCHAR)hybridRes; k++) { + fixpHybridReal [chOffset + k] = pTempRealSlot[k]; + fixpHybridImag [chOffset + k] = pTempImagSlot[k]; + } + chOffset += hybridRes; + } /* if (mHybridReal) */ + } + + /* group hybrid channels 3+4 -> 3 and 2+5 -> 2 */ + fixpHybridReal[3] += fixpHybridReal[4]; + fixpHybridImag[3] += fixpHybridImag[4]; + fixpHybridReal[4] = (FIXP_DBL)0; + fixpHybridImag[4] = (FIXP_DBL)0; + + fixpHybridReal[2] += fixpHybridReal[5]; + fixpHybridImag[2] += fixpHybridImag[5]; + fixpHybridReal[5] = (FIXP_DBL)0; + fixpHybridImag[5] = (FIXP_DBL)0; + + /* free memory on scratch */ + C_ALLOC_SCRATCH_END(pTempRealSlot, FIXP_DBL, 4*HYBRID_FILTER_LENGTH); + +} + + +/******************************************************************************* + Functionname: slotBasedHybridSynthesis + ******************************************************************************* + + Description: The coefficients offering higher resolution for the lower QMF + channel are simply added prior to the synthesis with the 54 + subbands QMF. + + Arguments: + + Return: none + +*******************************************************************************/ + +/*!
+      l,r0(n) ---\
+      l,r1(n) ---- + --\
+      l,r2(n) ---/      \
+                         + --> F0(w)
+      l,r3(n) ---\      /
+      l,r4(n) ---- + --/
+      l,r5(n) ---/
+
+
+      l,r6(n) ---\
+                  + ---------> F1(w)
+      l,r7(n) ---/
+
+
+      l,r8(n) ---\
+                  + ---------> F2(w)
+      l,r9(n) ---/
+
+    
+ Hybrid QMF synthesis filterbank for the 10 and 20 stereo-bands configurations. The + coefficients offering higher resolution for the lower QMF channel are simply added + prior to the synthesis with the 54 subbands QMF. + + [see ISO/IEC 14496-3:2001/FDAM 2:2004(E) - Page 52] +*/ + + +void +slotBasedHybridSynthesis ( FIXP_DBL *fixpHybridReal, /*!< Hybrid real Values */ + FIXP_DBL *fixpHybridImag, /*!< Hybrid imag Values */ + FIXP_DBL *fixpQmfReal, /*!< Qmf real Values */ + FIXP_DBL *fixpQmfImag, /*!< Qmf imag Values */ + HANDLE_HYBRID hHybrid ) /*!< Handle to HYBRID struct. */ +{ + int k, band; + + HYBRID_RES hybridRes; + int chOffset = 0; + + for(band = 0; band < hHybrid->nQmfBands; band++) { + + FIXP_DBL qmfReal = FL2FXCONST_DBL(0.f); + FIXP_DBL qmfImag = FL2FXCONST_DBL(0.f); + hybridRes = (HYBRID_RES)hHybrid->pResolution[band]; + + for(k = 0; k < (SCHAR)hybridRes; k++) { + qmfReal += fixpHybridReal[chOffset + k]; + qmfImag += fixpHybridImag[chOffset + k]; + } + + fixpQmfReal[band] = qmfReal; + fixpQmfImag[band] = qmfImag; + + chOffset += hybridRes; + } +} + + + diff --git a/libSBRdec/src/psdec_hybrid.h b/libSBRdec/src/psdec_hybrid.h new file mode 100644 index 00000000..fcf9e3ee --- /dev/null +++ b/libSBRdec/src/psdec_hybrid.h @@ -0,0 +1,165 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#ifndef __HYBRID_H +#define __HYBRID_H + +#include "sbrdecoder.h" + + +#define HYBRID_FILTER_LENGTH 13 +#define HYBRID_FILTER_DELAY 6 + + +#define FAST_FILTER2 +#define FAST_FILTER4 +#define FAST_FILTER8 +#define FAST_FILTER12 + +#define FFT_IDX_R(a) (2*a) +#define FFT_IDX_I(a) (2*a+1) + +#define FIXP_FFT_IDX_R(a) (a<<1) +#define FIXP_FFT_IDX_I(a) ((a<<1) + 1) + + +typedef enum { + + HYBRID_2_REAL = 2, + HYBRID_4_CPLX = 4, + HYBRID_8_CPLX = 8, + HYBRID_12_CPLX = 12 + +} HYBRID_RES; + +typedef struct +{ + SCHAR nQmfBands; + SCHAR frameSize; + SCHAR qmfBufferMove; + + UCHAR pResolution[3]; + + FIXP_DBL mQmfBufferRealSlot[3][HYBRID_FILTER_LENGTH]; /**< Stores old Qmf samples. */ + FIXP_DBL mQmfBufferImagSlot[3][HYBRID_FILTER_LENGTH]; + SCHAR sf_mQmfBuffer; + +} HYBRID; + +typedef HYBRID *HANDLE_HYBRID; + +void +fillHybridDelayLine( FIXP_DBL **fixpQmfReal, + FIXP_DBL **fixpQmfImag, + FIXP_DBL fixpHybridLeftR[12], + FIXP_DBL fixpHybridLeftI[12], + FIXP_DBL fixpHybridRightR[12], + FIXP_DBL fixpHybridRightI[12], + HANDLE_HYBRID hHybrid ); + +void +slotBasedHybridAnalysis ( FIXP_DBL *fixpQmfReal, + FIXP_DBL *fixpQmfImag, + + FIXP_DBL *fixpHybridReal, + FIXP_DBL *fixpHybridImag, + + HANDLE_HYBRID hHybrid); + + +void +slotBasedHybridSynthesis ( FIXP_DBL *fixpHybridReal, + FIXP_DBL *fixpHybridImag, + + FIXP_DBL *fixpQmfReal, + FIXP_DBL *fixpQmfImag, + + HANDLE_HYBRID hHybrid ); + +SBR_ERROR InitHybridFilterBank ( HANDLE_HYBRID hHybrid, + SCHAR frameSize, + SCHAR noBands, + const UCHAR *pResolution ); + + +#endif /* __HYBRID_H */ diff --git a/libSBRdec/src/sbr_crc.cpp b/libSBRdec/src/sbr_crc.cpp new file mode 100644 index 00000000..a495f10e --- /dev/null +++ b/libSBRdec/src/sbr_crc.cpp @@ -0,0 +1,183 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief CRC check coutines +*/ + +#include "sbr_crc.h" + +#include "FDK_bitstream.h" +#include "transcendent.h" + +#define MAXCRCSTEP 16 +#define MAXCRCSTEP_LD 4 + +/*! + \brief crc calculation +*/ +static ULONG +calcCRC (HANDLE_CRC hCrcBuf, ULONG bValue, int nBits) +{ + int i; + ULONG bMask = (1UL << (nBits - 1)); + + for (i = 0; i < nBits; i++, bMask >>= 1) { + USHORT flag = (hCrcBuf->crcState & hCrcBuf->crcMask) ? 1 : 0; + USHORT flag1 = (bMask & bValue) ? 1 : 0; + + flag ^= flag1; + hCrcBuf->crcState <<= 1; + if (flag) + hCrcBuf->crcState ^= hCrcBuf->crcPoly; + } + + return (hCrcBuf->crcState); +} + + +/*! + \brief crc +*/ +static int +getCrc (HANDLE_FDK_BITSTREAM hBs, ULONG NrBits) +{ + int i; + CRC_BUFFER CrcBuf; + + CrcBuf.crcState = SBR_CRC_START; + CrcBuf.crcPoly = SBR_CRC_POLY; + CrcBuf.crcMask = SBR_CRC_MASK; + + int CrcStep = NrBits>>MAXCRCSTEP_LD; + + int CrcNrBitsRest = (NrBits - CrcStep * MAXCRCSTEP); + ULONG bValue; + + for (i = 0; i < CrcStep; i++) { + bValue = FDKreadBits (hBs, MAXCRCSTEP); + calcCRC (&CrcBuf, bValue, MAXCRCSTEP); + } + + bValue = FDKreadBits (hBs, CrcNrBitsRest); + calcCRC (&CrcBuf, bValue, CrcNrBitsRest); + + return (CrcBuf.crcState & SBR_CRC_RANGE); + +} + + +/*! + \brief crc interface + \return 1: CRC OK, 0: CRC check failure +*/ +int +SbrCrcCheck (HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ + LONG NrBits) /*!< max. CRC length */ +{ + int crcResult = 1; + ULONG NrCrcBits; + ULONG crcCheckResult; + LONG NrBitsAvailable; + ULONG crcCheckSum; + + crcCheckSum = FDKreadBits (hBs, 10); + + NrBitsAvailable = FDKgetValidBits(hBs); + if (NrBitsAvailable <= 0){ + return 0; + } + + NrCrcBits = fixMin ((INT)NrBits, (INT)NrBitsAvailable); + + crcCheckResult = getCrc (hBs, NrCrcBits); + FDKpushBack(hBs, (NrBitsAvailable - FDKgetValidBits(hBs)) ); + + + if (crcCheckResult != crcCheckSum) { + crcResult = 0; + } + + return (crcResult); +} diff --git a/libSBRdec/src/sbr_crc.h b/libSBRdec/src/sbr_crc.h new file mode 100644 index 00000000..30b83295 --- /dev/null +++ b/libSBRdec/src/sbr_crc.h @@ -0,0 +1,123 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief CRC checking routines +*/ +#ifndef __SBR_CRC_H +#define __SBR_CRC_H + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" + +/* some useful crc polynoms: + +crc5: x^5+x^4+x^2+x^1+1 +crc6: x^6+x^5+x^3+x^2+x+1 +crc7: x^7+x^6+x^2+1 +crc8: x^8+x^2+x+x+1 +*/ + +/* default SBR CRC */ /* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY 0x0233 +#define SBR_CRC_MASK 0x0200 +#define SBR_CRC_START 0x0000 +#define SBR_CRC_RANGE 0x03FF + +typedef struct +{ + USHORT crcState; + USHORT crcMask; + USHORT crcPoly; +} +CRC_BUFFER; + +typedef CRC_BUFFER *HANDLE_CRC; + +int SbrCrcCheck (HANDLE_FDK_BITSTREAM hBitBuf, + LONG NrCrcBits); + + +#endif diff --git a/libSBRdec/src/sbr_deb.cpp b/libSBRdec/src/sbr_deb.cpp new file mode 100644 index 00000000..9baff2e8 --- /dev/null +++ b/libSBRdec/src/sbr_deb.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Print selected debug messages +*/ + +#include "sbr_deb.h" + diff --git a/libSBRdec/src/sbr_deb.h b/libSBRdec/src/sbr_deb.h new file mode 100644 index 00000000..cb954ba1 --- /dev/null +++ b/libSBRdec/src/sbr_deb.h @@ -0,0 +1,94 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Debugging aids +*/ + +#ifndef __SBR_DEB_H +#define __SBR_DEB_H + +#include "sbrdecoder.h" + +#endif diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp new file mode 100644 index 00000000..76009ba2 --- /dev/null +++ b/libSBRdec/src/sbr_dec.cpp @@ -0,0 +1,1102 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Sbr decoder + This module provides the actual decoder implementation. The SBR data (side information) is already + decoded. Only three functions are provided: + + \li 1.) createSbrDec(): One time initialization + \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in an SBR_HEADER_ELEMENT requires a reset + and recalculation of important SBR structures. + \li 3.) sbr_dec(): The actual decoder. Calls the different tools such as filterbanks, lppTransposer(), and calculateSbrEnvelope() + [the envelope adjuster]. + + \sa sbr_dec(), \ref documentationOverview +*/ + +#include "sbr_dec.h" + +#include "sbr_ram.h" +#include "env_extr.h" +#include "env_calc.h" +#include "scale.h" + +#include "genericStds.h" + +#include "sbrdec_drc.h" + + + +static void assignLcTimeSlots( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + FIXP_DBL **QmfBufferReal, + int noCols ) +{ + int slot, i; + FIXP_DBL *ptr; + + /* Number of QMF timeslots in the overlap buffer: */ + ptr = hSbrDec->pSbrOverlapBuffer; + for(slot=0; slotLppTrans.pSettings->overlap; slot++) { + QmfBufferReal[slot] = ptr; ptr += (64); + } + + /* Assign timeslots to Workbuffer1 */ + ptr = hSbrDec->WorkBuffer1; + for(i=0; i> 1) + hSbrDec->LppTrans.pSettings->overlap; + int totCols = noCols + hSbrDec->LppTrans.pSettings->overlap; + + /* Number of QMF timeslots in the overlap buffer: */ + ptr = hSbrDec->pSbrOverlapBuffer; + for(slot=0; slotLppTrans.pSettings->overlap; slot++) { + QmfBufferReal[slot] = ptr; ptr += (64); + QmfBufferImag[slot] = ptr; ptr += (64); + } + + /* Assign first half of timeslots to Workbuffer1 */ + ptr = hSbrDec->WorkBuffer1; + for(; slotWorkBuffer2; + for(; slotuseLP = useLP; + if (useLP) { + hSbrDec->SynthesisQMF.flags |= QMF_FLAG_LP; + hSbrDec->AnalysiscQMF.flags |= QMF_FLAG_LP; + } else { + hSbrDec->SynthesisQMF.flags &= ~QMF_FLAG_LP; + hSbrDec->AnalysiscQMF.flags &= ~QMF_FLAG_LP; + } + if (!useLP) + assignHqTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, hSbrDec->QmfBufferImag, noCols ); + else + { + assignLcTimeSlots( hSbrDec, hSbrDec->QmfBufferReal, noCols ); + } +} + +static void changeQmfType( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + int useLdTimeAlign ) +{ + UINT synQmfFlags = hSbrDec->SynthesisQMF.flags; + UINT anaQmfFlags = hSbrDec->AnalysiscQMF.flags; + int resetSynQmf = 0; + int resetAnaQmf = 0; + + /* assign qmf type */ + if (useLdTimeAlign) { + if (synQmfFlags & QMF_FLAG_CLDFB) { + /* change the type to MPSLD */ + synQmfFlags &= ~QMF_FLAG_CLDFB; + synQmfFlags |= QMF_FLAG_MPSLDFB; + resetSynQmf = 1; + } + if (anaQmfFlags & QMF_FLAG_CLDFB) { + /* change the type to MPSLD */ + anaQmfFlags &= ~QMF_FLAG_CLDFB; + anaQmfFlags |= QMF_FLAG_MPSLDFB; + resetAnaQmf = 1; + } + } else { + if (synQmfFlags & QMF_FLAG_MPSLDFB) { + /* change the type to CLDFB */ + synQmfFlags &= ~QMF_FLAG_MPSLDFB; + synQmfFlags |= QMF_FLAG_CLDFB; + resetSynQmf = 1; + } + if (anaQmfFlags & QMF_FLAG_MPSLDFB) { + /* change the type to CLDFB */ + anaQmfFlags &= ~QMF_FLAG_MPSLDFB; + anaQmfFlags |= QMF_FLAG_CLDFB; + resetAnaQmf = 1; + } + } + + if (resetAnaQmf) { + QMF_FILTER_BANK prvAnaQmf; + int qmfErr; + + /* Store current configuration */ + FDKmemcpy(&prvAnaQmf, &hSbrDec->AnalysiscQMF, sizeof(QMF_FILTER_BANK)); + + /* Reset analysis QMF */ + qmfErr = qmfInitAnalysisFilterBank ( + &hSbrDec->AnalysiscQMF, + hSbrDec->anaQmfStates, + hSbrDec->AnalysiscQMF.no_col, + hSbrDec->AnalysiscQMF.lsb, + hSbrDec->AnalysiscQMF.usb, + hSbrDec->AnalysiscQMF.no_channels, + anaQmfFlags | QMF_FLAG_KEEP_STATES + ); + + if (qmfErr != 0) { + /* Restore old configuration of analysis QMF */ + FDKmemcpy(&hSbrDec->AnalysiscQMF, &prvAnaQmf, sizeof(QMF_FILTER_BANK)); + } + } + + if (resetSynQmf) { + QMF_FILTER_BANK prvSynQmf; + int qmfErr; + + /* Store current configuration */ + FDKmemcpy(&prvSynQmf, &hSbrDec->SynthesisQMF, sizeof(QMF_FILTER_BANK)); + + /* Reset synthesis QMF */ + qmfErr = qmfInitSynthesisFilterBank ( + &hSbrDec->SynthesisQMF, + hSbrDec->pSynQmfStates, + hSbrDec->SynthesisQMF.no_col, + hSbrDec->SynthesisQMF.lsb, + hSbrDec->SynthesisQMF.usb, + hSbrDec->SynthesisQMF.no_channels, + synQmfFlags | QMF_FLAG_KEEP_STATES + ); + + if (qmfErr != 0) { + /* Restore old configuration of synthesis QMF */ + FDKmemcpy(&hSbrDec->SynthesisQMF, &prvSynQmf, sizeof(QMF_FILTER_BANK)); + } + } +} + + +/*! + \brief SBR decoder core function for one channel + + \image html BufferMgmtDetailed-1632.png + + Besides the filter states of the QMF filter bank and the LPC-states of + the LPP-Transposer, processing is mainly based on four buffers: + #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2 + is reused for all channels and might be used by the core decoder, a + static overlap buffer is required for each channel. Du to in-place + processing, #timeIn and #timeOut point to identical locations. + + The spectral data is organized in so-called slots, each slot + containing 64 bands of complex data. The number of slots per frame is + dependend on the frame size. For mp3PRO, there are 18 slots per frame + and 6 slots per #OverlapBuffer. It is not necessary to have the slots + in located consecutive address ranges. + + To optimize memory usage and to minimize the number of memory + accesses, the memory management is organized as follows (Slot numbers + based on mp3PRO): + + 1.) Input time domain signal is located in #timeIn, the last slots + (0..5) of the spectral data of the previous frame are located in the + #OverlapBuffer. In addition, #frameData of the current frame resides + in the upper part of #timeIn. + + 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are transformed + into a slot of up to 32 complex spectral low band values at a + time. The first spectral slot -- nr. 6 -- is written at slot number + zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with + spectral data. + + 3.) LPP-Transposition in lppTransposer() is processed on 24 slots. During the + transposition, the high band part of the spectral data is replicated + based on the low band data. + + Envelope Adjustment is processed on the high band part of the spectral + data only by calculateSbrEnvelope(). + + 4.) The cplxSynthesisQmfFiltering() creates 64 time domain samples out + of a slot of 64 complex spectral values at a time. The first 6 slots + in #timeOut are filled from the results of spectral slots 0..5 in the + #OverlapBuffer. The consecutive slots in timeOut are now filled with + the results of spectral slots 6..17. + + 5.) The preprocessed slots 18..23 have to be stored in the + #OverlapBuffer. + +*/ + +void +sbr_dec ( HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + const int strideIn, /*!< Time data traversal strideIn */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, + const UINT flags, + const int codecFrameSize + ) +{ + int i, slot, reserve; + int saveLbScale; + int ov_len; + int lastSlotOffs; + FIXP_DBL maxVal; + + /* 1+1/3 frames of spectral data: */ + FIXP_DBL **QmfBufferReal = hSbrDec->QmfBufferReal; + FIXP_DBL **QmfBufferImag = hSbrDec->QmfBufferImag; + + /* Number of QMF timeslots in the overlap buffer: */ + ov_len = hSbrDec->LppTrans.pSettings->overlap; + + /* Number of QMF slots per frame */ + int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + /* assign qmf time slots */ + if ( ((flags & SBRDEC_LOW_POWER ) ? 1 : 0) != ((hSbrDec->SynthesisQMF.flags & QMF_FLAG_LP) ? 1 : 0) ) { + assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, flags & SBRDEC_LOW_POWER); + } + + if (flags & SBRDEC_ELD_GRID) { + /* Choose the right low delay filter bank */ + changeQmfType( hSbrDec, (flags & SBRDEC_LD_MPS_QMF) ? 1 : 0 ); + + /* If the LD-MPS QMF is not available delay the signal by (96-48*ldSbrSamplingRate) + * samples according to ISO/IEC 14496-3:2009/FDAM 2:2010(E) chapter 4.5.2.13. */ + if ( (flags & SBRDEC_LD_MPS_QMF) + && (hSbrDec->AnalysiscQMF.flags & QMF_FLAG_CLDFB) ) + { + INT_PCM *pDlyBuf = hSbrDec->coreDelayBuf; /* DLYBUF */ + int smpl, delay = 96 >> (!(flags & SBRDEC_DOWNSAMPLE) ? 1 : 0); + /* Create TMPBUF */ + C_AALLOC_SCRATCH_START(pcmTemp, INT_PCM, (96)); + /* Copy delay samples from INBUF to TMPBUF */ + for (smpl = 0; smpl < delay; smpl += 1) { + pcmTemp[smpl] = timeIn[(codecFrameSize-delay+smpl)*strideIn]; + } + /* Move input signal remainder to the very end of INBUF */ + for (smpl = (codecFrameSize-delay-1)*strideIn; smpl >= 0; smpl -= strideIn) { + timeIn[smpl+delay] = timeIn[smpl]; + } + /* Copy delayed samples from last frame from DLYBUF to the very beginning of INBUF */ + for (smpl = 0; smpl < delay; smpl += 1) { + timeIn[smpl*strideIn] = pDlyBuf[smpl]; + } + /* Copy TMPBUF to DLYBUF */ + FDKmemcpy(pDlyBuf, pcmTemp, delay*sizeof(INT_PCM)); + /* Destory TMPBUF */ + C_AALLOC_SCRATCH_END(pcmTemp, INT_PCM, (96)); + } + } + + /* + low band codec signal subband filtering + */ + + { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); + + qmfAnalysisFiltering( &hSbrDec->AnalysiscQMF, + QmfBufferReal + ov_len, + QmfBufferImag + ov_len, + &hSbrDec->sbrScaleFactor, + timeIn, + strideIn, + qmfTemp + ); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + } + + /* + Clear upper half of spectrum + */ + { + int nAnalysisBands = hHeaderData->numberOfAnalysisBands; + + if (! (flags & SBRDEC_LOW_POWER)) { + for (slot = ov_len; slot < noCols+ov_len; slot++) { + FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); + FDKmemclear(&QmfBufferImag[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); + } + } else + for (slot = ov_len; slot < noCols+ov_len; slot++) { + FDKmemclear(&QmfBufferReal[slot][nAnalysisBands],((64)-nAnalysisBands)*sizeof(FIXP_DBL)); + } + } + + + + /* + Shift spectral data left to gain accuracy in transposer and adjustor + */ + maxVal = maxSubbandSample( QmfBufferReal, + (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, + 0, + hSbrDec->AnalysiscQMF.lsb, + ov_len, + noCols+ov_len ); + + reserve = fixMax(0,CntLeadingZeros(maxVal)-1) ; + reserve = fixMin(reserve,DFRACT_BITS-1-hSbrDec->sbrScaleFactor.lb_scale); + + /* If all data is zero, lb_scale could become too large */ + rescaleSubbandSamples( QmfBufferReal, + (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, + 0, + hSbrDec->AnalysiscQMF.lsb, + ov_len, + noCols+ov_len, + reserve); + + hSbrDec->sbrScaleFactor.lb_scale += reserve; + + /* + save low band scale, wavecoding or parametric stereo may modify it + */ + saveLbScale = hSbrDec->sbrScaleFactor.lb_scale; + + + if (applyProcessing) + { + UCHAR * borders = hFrameData->frameInfo.borders; + lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - hHeaderData->numberTimeSlots; + + FIXP_DBL degreeAlias[(64)]; + + /* The transposer will override most values in degreeAlias[]. + The array needs to be cleared at least from lowSubband to highSubband before. */ + if (flags & SBRDEC_LOW_POWER) + FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], (hHeaderData->freqBandData.highSubband-hHeaderData->freqBandData.lowSubband)*sizeof(FIXP_DBL)); + + /* + Inverse filtering of lowband and transposition into the SBR-frequency range + */ + + lppTransposer ( &hSbrDec->LppTrans, + &hSbrDec->sbrScaleFactor, + QmfBufferReal, + degreeAlias, // only used if useLP = 1 + QmfBufferImag, + flags & SBRDEC_LOW_POWER, + hHeaderData->timeStep, + borders[0], + lastSlotOffs, + hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, + hPrevFrameData->sbr_invf_mode ); + + + + + + /* + Adjust envelope of current frame. + */ + + calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, + &hSbrDec->SbrCalculateEnvelope, + hHeaderData, + hFrameData, + QmfBufferReal, + QmfBufferImag, + flags & SBRDEC_LOW_POWER, + + degreeAlias, + flags, + (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); + + + /* + Update hPrevFrameData (to be used in the next frame) + */ + for (i=0; ifreqBandData.nInvfBands; i++) { + hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; + } + hPrevFrameData->coupling = hFrameData->coupling; + hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; + hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; + } + else { + /* Reset hb_scale if no highband is present, because hb_scale is considered in the QMF-synthesis */ + hSbrDec->sbrScaleFactor.hb_scale = saveLbScale; + } + + + for (i=0; iLppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImag[i], QmfBufferImag[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); + } else + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesReal[i], QmfBufferReal[noCols-LPC_ORDER+i], hSbrDec->AnalysiscQMF.lsb*sizeof(FIXP_DBL)); + } + + /* + Synthesis subband filtering. + */ + + if ( ! (flags & SBRDEC_PS_DECODED) ) { + + { + int outScalefactor = 0; + + if (h_ps_d != NULL) { + h_ps_d->procFrameBased = 1; /* we here do frame based processing */ + } + + + sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, + QmfBufferReal, + (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, + hSbrDec->SynthesisQMF.no_col, + &outScalefactor + ); + + + + qmfChangeOutScalefactor(&hSbrDec->SynthesisQMF, outScalefactor ); + + { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2*(64)); + + qmfSynthesisFiltering( &hSbrDec->SynthesisQMF, + QmfBufferReal, + (flags & SBRDEC_LOW_POWER) ? NULL : QmfBufferImag, + &hSbrDec->sbrScaleFactor, + hSbrDec->LppTrans.pSettings->overlap, + timeOut, + strideOut, + qmfTemp); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2*(64)); + } + + } + + } else { /* (flags & SBRDEC_PS_DECODED) */ + INT i, sdiff, outScalefactor, scaleFactorLowBand, scaleFactorHighBand; + SCHAR scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + + HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->SynthesisQMF; + HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->SynthesisQMF; + + /* adapt scaling */ + sdiff = hSbrDec->sbrScaleFactor.lb_scale - reserve; /* Scaling difference */ + scaleFactorHighBand = sdiff - hSbrDec->sbrScaleFactor.hb_scale; /* Scale of current high band */ + scaleFactorLowBand_ov = sdiff - hSbrDec->sbrScaleFactor.ov_lb_scale; /* Scale of low band overlapping QMF data */ + scaleFactorLowBand_no_ov = sdiff - hSbrDec->sbrScaleFactor.lb_scale; /* Scale of low band current QMF data */ + outScalefactor = 0; /* Initial output scale */ + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot based processing copy filter states */ + { /* procFrameBased will be unset later */ + /* copy filter states from left to right */ + FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, ((640)-(64))*sizeof(FIXP_QSS)); + } + + /* scale ALL qmf vales ( real and imag ) of mono / left channel to the + same scale factor ( ov_lb_sf, lb_sf and hq_sf ) */ + scalFilterBankValues( h_ps_d, /* parametric stereo decoder handle */ + QmfBufferReal, /* qmf filterbank values */ + QmfBufferImag, /* qmf filterbank values */ + synQmf->lsb, /* sbr start subband */ + hSbrDec->sbrScaleFactor.ov_lb_scale, + hSbrDec->sbrScaleFactor.lb_scale, + &scaleFactorLowBand_ov, /* adapt scaling values */ + &scaleFactorLowBand_no_ov, /* adapt scaling values */ + hSbrDec->sbrScaleFactor.hb_scale, /* current frame ( highband ) */ + &scaleFactorHighBand, + synQmf->no_col); + + /* use the same synthese qmf values for left and right channel */ + synQmfRight->no_col = synQmf->no_col; + synQmfRight->lsb = synQmf->lsb; + synQmfRight->usb = synQmf->usb; + + int env=0; + + outScalefactor += (SCAL_HEADROOM+1); /* psDiffScale! */ + + { + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2*(64)); + + int maxShift = 0; + + if (hSbrDec->sbrDrcChannel.enable != 0) { + if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.prevFact_exp; + } + if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.currFact_exp; + } + if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.nextFact_exp; + } + } + + /* copy DRC data to right channel (with PS both channels use the same DRC gains) */ + FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, sizeof(SBRDEC_DRC_CHANNEL)); + + for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ + + INT outScalefactorR, outScalefactorL; + outScalefactorR = outScalefactorL = outScalefactor; + + /* qmf timeslot of right channel */ + FIXP_DBL* rQmfReal = pWorkBuffer; + FIXP_DBL* rQmfImag = pWorkBuffer + 64; + + + { + if ( i == h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env] ) { + initSlotBasedRotation( h_ps_d, env, hHeaderData->freqBandData.highSubband ); + env++; + } + + ApplyPsSlot( h_ps_d, /* parametric stereo decoder handle */ + (QmfBufferReal + i), /* one timeslot of left/mono channel */ + (QmfBufferImag + i), /* one timeslot of left/mono channel */ + rQmfReal, /* one timeslot or right channel */ + rQmfImag); /* one timeslot or right channel */ + } + + + scaleFactorLowBand = (i<(6)) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; + + + sbrDecoder_drcApplySlot ( /* right channel */ + &hSbrDecRight->sbrDrcChannel, + rQmfReal, + rQmfImag, + i, + synQmfRight->no_col, + maxShift + ); + + outScalefactorR += maxShift; + + sbrDecoder_drcApplySlot ( /* left channel */ + &hSbrDec->sbrDrcChannel, + *(QmfBufferReal + i), + *(QmfBufferImag + i), + i, + synQmf->no_col, + maxShift + ); + + outScalefactorL += maxShift; + + + /* scale filter states for left and right channel */ + qmfChangeOutScalefactor( synQmf, outScalefactorL ); + qmfChangeOutScalefactor( synQmfRight, outScalefactorR ); + + { + + qmfSynthesisFilteringSlot( synQmfRight, + rQmfReal, /* QMF real buffer */ + rQmfImag, /* QMF imag buffer */ + scaleFactorLowBand, + scaleFactorHighBand, + timeOutRight+(i*synQmf->no_channels*strideOut), + strideOut, + pWorkBuffer); + + qmfSynthesisFilteringSlot( synQmf, + *(QmfBufferReal + i), /* QMF real buffer */ + *(QmfBufferImag + i), /* QMF imag buffer */ + scaleFactorLowBand, + scaleFactorHighBand, + timeOut+(i*synQmf->no_channels*strideOut), + strideOut, + pWorkBuffer); + + } + } /* no_col loop i */ + + /* scale back (6) timeslots look ahead for hybrid filterbank to original value */ + rescalFilterBankValues( h_ps_d, + QmfBufferReal, + QmfBufferImag, + synQmf->lsb, + synQmf->no_col ); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2*(64)); + } + } + + sbrDecoder_drcUpdateChannel( &hSbrDec->sbrDrcChannel ); + + + /* + Update overlap buffer + Even bands above usb are copied to avoid outdated spectral data in case + the stop frequency raises. + */ + + if (hSbrDec->LppTrans.pSettings->overlap > 0) + { + if (! (flags & SBRDEC_LOW_POWER)) { + for ( i=0; iLppTrans.pSettings->overlap; i++ ) { + FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); + FDKmemcpy(QmfBufferImag[i], QmfBufferImag[i+noCols], (64)*sizeof(FIXP_DBL)); + } + } else + for ( i=0; iLppTrans.pSettings->overlap; i++ ) { + FDKmemcpy(QmfBufferReal[i], QmfBufferReal[i+noCols], (64)*sizeof(FIXP_DBL)); + } + } + + hSbrDec->sbrScaleFactor.ov_lb_scale = saveLbScale; + + /* Save current frame status */ + hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; + +} // sbr_dec() + + +/*! + \brief Creates sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrDec (SBR_CHANNEL * hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, /*!< Downsampling factor */ + const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ + const UINT flags, + const int overlap, + int chan) /*!< Channel for which to assign buffers etc. */ + +{ + SBR_ERROR err = SBRDEC_OK; + int timeSlots = hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ + int noCols = timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ + HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); + + /* Initialize scale factors */ + hs->sbrScaleFactor.ov_lb_scale = 0; + hs->sbrScaleFactor.ov_hb_scale = 0; + hs->sbrScaleFactor.hb_scale = 0; + + + /* + create envelope calculator + */ + err = createSbrEnvelopeCalc (&hs->SbrCalculateEnvelope, + hHeaderData, + chan, + flags); + if (err != SBRDEC_OK) { + return err; + } + + /* + create QMF filter banks + */ + { + int qmfErr; + /* Adapted QMF analysis post-twiddles for down-sampled HQ SBR */ + const UINT downSampledFlag = (flags & SBRDEC_DOWNSAMPLE) ? QMF_FLAG_DOWNSAMPLED : 0; + + qmfErr = qmfInitAnalysisFilterBank ( + &hs->AnalysiscQMF, + hs->anaQmfStates, + noCols, + hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.highSubband, + hHeaderData->numberOfAnalysisBands, + (qmfFlags & (~QMF_FLAG_KEEP_STATES)) | downSampledFlag + ); + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + if (hs->pSynQmfStates == NULL) { + hs->pSynQmfStates = GetRam_sbr_QmfStatesSynthesis(chan); + if (hs->pSynQmfStates == NULL) + return SBRDEC_MEM_ALLOC_FAILED; + } + + { + int qmfErr; + + qmfErr = qmfInitSynthesisFilterBank ( + &hs->SynthesisQMF, + hs->pSynQmfStates, + noCols, + hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.highSubband, + (64) / downsampleFac, + qmfFlags & (~QMF_FLAG_KEEP_STATES) + ); + + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + initSbrPrevFrameData (&hSbrChannel->prevFrameData, timeSlots); + + /* + create transposer + */ + err = createLppTransposer (&hs->LppTrans, + pSettings, + hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, + hHeaderData->freqBandData.numMaster, + hs->SynthesisQMF.usb, + timeSlots, + hs->AnalysiscQMF.no_col, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, + hHeaderData->sbrProcSmplRate, + chan, + overlap ); + if (err != SBRDEC_OK) { + return err; + } + + /* The CLDFB does not have overlap */ + if ((qmfFlags & QMF_FLAG_CLDFB) == 0) { + if (hs->pSbrOverlapBuffer == NULL) { + hs->pSbrOverlapBuffer = GetRam_sbr_OverlapBuffer(chan); + if (hs->pSbrOverlapBuffer == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + } else { + /* Clear overlap buffer */ + FDKmemclear( hs->pSbrOverlapBuffer, + sizeof(FIXP_DBL) * 2 * (6) * (64) + ); + } + } + + /* Clear input delay line */ + FDKmemclear(hs->coreDelayBuf, (96)*sizeof(INT_PCM)); + + /* assign qmf time slots */ + assignTimeSlots( &hSbrChannel->SbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, qmfFlags & QMF_FLAG_LP); + + return err; +} + +/*! + \brief Delete sbr decoder structure + \return errorCode, 0 if successful +*/ +int +deleteSbrDec (SBR_CHANNEL * hSbrChannel) +{ + HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec; + + deleteSbrEnvelopeCalc (&hs->SbrCalculateEnvelope); + + /* delete QMF filter states */ + if (hs->pSynQmfStates != NULL) { + FreeRam_sbr_QmfStatesSynthesis(&hs->pSynQmfStates); + } + + + if (hs->pSbrOverlapBuffer != NULL) { + FreeRam_sbr_OverlapBuffer(&hs->pSbrOverlapBuffer); + } + + return 0; +} + + +/*! + \brief resets sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetSbrDec (HANDLE_SBR_DEC hSbrDec, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, + const int useLP, + const int downsampleFac + ) +{ + SBR_ERROR sbrError = SBRDEC_OK; + + int old_lsb = hSbrDec->SynthesisQMF.lsb; + int new_lsb = hHeaderData->freqBandData.lowSubband; + int l, startBand, stopBand, startSlot, size; + + int source_scale, target_scale, delta_scale, target_lsb, target_usb, reserve; + FIXP_DBL maxVal; + + /* overlapBuffer point to first (6) slots */ + FIXP_DBL **OverlapBufferReal = hSbrDec->QmfBufferReal; + FIXP_DBL **OverlapBufferImag = hSbrDec->QmfBufferImag; + + if (!hSbrDec->LppTrans.pSettings) { + return SBRDEC_NOT_INITIALIZED; + } + + /* assign qmf time slots */ + assignTimeSlots( hSbrDec, hHeaderData->numberTimeSlots * hHeaderData->timeStep, useLP); + + + + resetSbrEnvelopeCalc (&hSbrDec->SbrCalculateEnvelope); + + hSbrDec->SynthesisQMF.lsb = hHeaderData->freqBandData.lowSubband; + hSbrDec->SynthesisQMF.usb = fixMin((INT)hSbrDec->SynthesisQMF.no_channels, (INT)hHeaderData->freqBandData.highSubband); + + hSbrDec->AnalysiscQMF.lsb = hSbrDec->SynthesisQMF.lsb; + hSbrDec->AnalysiscQMF.usb = hSbrDec->SynthesisQMF.usb; + + + /* + The following initialization of spectral data in the overlap buffer + is required for dynamic x-over or a change of the start-freq for 2 reasons: + + 1. If the lowband gets _wider_, unadjusted data would remain + + 2. If the lowband becomes _smaller_, the highest bands of the old lowband + must be cleared because the whitening would be affected + */ + startBand = old_lsb; + stopBand = new_lsb; + startSlot = hHeaderData->timeStep * (hPrevFrameData->stopPos - hHeaderData->numberTimeSlots); + size = fixMax(0,stopBand-startBand); + + /* keep already adjusted data in the x-over-area */ + if (!useLP) { + for (l=startSlot; lLppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); + FDKmemclear(&OverlapBufferImag[l][startBand], size*sizeof(FIXP_DBL)); + } + } else + for (l=startSlot; lLppTrans.pSettings->overlap ; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size*sizeof(FIXP_DBL)); + } + + + /* + reset LPC filter states + */ + startBand = fixMin(old_lsb,new_lsb); + stopBand = fixMax(old_lsb,new_lsb); + size = fixMax(0,stopBand-startBand); + + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[0][startBand], size*sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesReal[1][startBand], size*sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[0][startBand], size*sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImag[1][startBand], size*sizeof(FIXP_DBL)); + } + + + /* + Rescale already processed spectral data between old and new x-over frequency. + This must be done because of the separate scalefactors for lowband and highband. + */ + startBand = fixMin(old_lsb,new_lsb); + stopBand = fixMax(old_lsb,new_lsb); + + if (new_lsb > old_lsb) { + /* The x-over-area was part of the highband before and will now belong to the lowband */ + source_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; + target_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; + target_lsb = 0; + target_usb = old_lsb; + } + else { + /* The x-over-area was part of the lowband before and will now belong to the highband */ + source_scale = hSbrDec->sbrScaleFactor.ov_lb_scale; + target_scale = hSbrDec->sbrScaleFactor.ov_hb_scale; + /* jdr: The values old_lsb and old_usb might be wrong because the previous frame might have been "upsamling". */ + target_lsb = hSbrDec->SynthesisQMF.lsb; + target_usb = hSbrDec->SynthesisQMF.usb; + } + + /* Shift left all samples of the x-over-area as much as possible + An unnecessary coarse scale could cause ov_lb_scale or ov_hb_scale to be + adapted and the accuracy in the next frame would seriously suffer! */ + + maxVal = maxSubbandSample( OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, + startBand, + stopBand, + 0, + startSlot); + + reserve = CntLeadingZeros(maxVal)-1; + reserve = fixMin(reserve,DFRACT_BITS-1-source_scale); + + rescaleSubbandSamples( OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, + startBand, + stopBand, + 0, + startSlot, + reserve); + source_scale += reserve; + + delta_scale = target_scale - source_scale; + + if (delta_scale > 0) { /* x-over-area is dominant */ + delta_scale = -delta_scale; + startBand = target_lsb; + stopBand = target_usb; + + if (new_lsb > old_lsb) { + /* The lowband has to be rescaled */ + hSbrDec->sbrScaleFactor.ov_lb_scale = source_scale; + } + else { + /* The highband has be be rescaled */ + hSbrDec->sbrScaleFactor.ov_hb_scale = source_scale; + } + } + + FDK_ASSERT(startBand <= stopBand); + + if (!useLP) { + for (l=0; lLppTrans, + hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, + hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, + hHeaderData->freqBandData.highSubband, + hHeaderData->sbrProcSmplRate); + if (sbrError != SBRDEC_OK) + return sbrError; + + sbrError = ResetLimiterBands ( hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands); + + + return sbrError; +} diff --git a/libSBRdec/src/sbr_dec.h b/libSBRdec/src/sbr_dec.h new file mode 100644 index 00000000..edde6371 --- /dev/null +++ b/libSBRdec/src/sbr_dec.h @@ -0,0 +1,214 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef __SBR_DEC_H +#define __SBR_DEC_H + +#include "sbrdecoder.h" + +#include "lpp_tran.h" +#include "qmf.h" +#include "env_calc.h" +#include "FDK_audio.h" + + +#include "sbrdec_drc.h" + +#define SACDEC_ALIGNMENT_FIX + +typedef struct +{ + QMF_FILTER_BANK AnalysiscQMF; + QMF_FILTER_BANK SynthesisQMF; + + SBR_CALCULATE_ENVELOPE SbrCalculateEnvelope; + SBR_LPP_TRANS LppTrans; + + QMF_SCALE_FACTOR sbrScaleFactor; + QMF_SCALE_FACTOR sbrScaleFactorRight; + + /*! Delayed spectral data needed for the dynamic framing of SBR. Not required in case of CLDFB */ + FIXP_DBL * pSbrOverlapBuffer; + + /* References to workbuffers */ + FIXP_DBL * WorkBuffer1; + FIXP_DBL * WorkBuffer2; + + /* Delayed time input signal needed to align CLDFD with LD-MPS QMF. */ + INT_PCM coreDelayBuf[(96)]; + + /* QMF filter states */ + FIXP_QAS anaQmfStates[(320)]; + FIXP_QSS * pSynQmfStates; + + /* Reference pointer arrays for QMF time slots, + mixed among overlap and current slots. */ + FIXP_DBL * QmfBufferReal[(((1024)/(32))+(6))]; + FIXP_DBL * QmfBufferImag[(((1024)/(32))+(6))]; + int useLP; + + /* QMF domain extension time slot reference pointer array */ + + SBRDEC_DRC_CHANNEL sbrDrcChannel; + +} SBR_DEC; + +typedef SBR_DEC *HANDLE_SBR_DEC; + + +typedef struct +{ + SBR_FRAME_DATA frameData[(1)+1]; + SBR_PREV_FRAME_DATA prevFrameData; + SBR_DEC SbrDec; +} +SBR_CHANNEL; + +typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL; + +void +SbrDecodeAndProcess (HANDLE_SBR_DEC hSbrDec, + INT_PCM *timeIn, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, + int applyProcessing, + int channelNr + , UCHAR useLP + ); + + +void +SbrConstructTimeOutput (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ + int channelNr + ,UCHAR useLP + ); + + +void +sbr_dec (HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + const int strideIn, /*!< Time data traversal strideIn */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData,/*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, + const UINT flags, + const int codecFrameSize + ); + + + +SBR_ERROR +createSbrDec (SBR_CHANNEL * hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, + const UINT qmfFlags, + const UINT flags, + const int overlap, + int chan); + +int +deleteSbrDec (SBR_CHANNEL * hSbrChannel); + +SBR_ERROR +resetSbrDec (HANDLE_SBR_DEC hSbrDec, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, + const int useLP, + const int downsampleFac); + +#endif diff --git a/libSBRdec/src/sbr_ram.cpp b/libSBRdec/src/sbr_ram.cpp new file mode 100644 index 00000000..c1c24998 --- /dev/null +++ b/libSBRdec/src/sbr_ram.cpp @@ -0,0 +1,194 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Memory layout + + + This module declares all static and dynamic memory spaces +*/ + +#include "sbr_ram.h" + + + + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER2_TAG 1 + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! SBR Decoder main structure */ +C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1) +/*! SBR Decoder element data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8)) +/*! SBR Decoder individual channel data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8)+1) + +/*! Filter states for QMF-synthesis.
+ Dimension: #(8) * (#QMF_FILTER_STATE_SYN_SIZE-#(64)) */ +C_AALLOC_MEM2_L(Ram_sbr_QmfStatesSynthesis, FIXP_QSS, (640)-(64), (8)+1, SECT_DATA_L1) + +/*! Delayed spectral data needed for the dynamic framing of SBR. + For mp3PRO, 1/3 of a frame is buffered (#(6) 6) */ +C_AALLOC_MEM2(Ram_sbr_OverlapBuffer, FIXP_DBL, 2 * (6) * (64), (8)+1) + +/*! Static Data of PS */ + +C_ALLOC_MEM(Ram_ps_dec, PS_DEC, 1) + + +/* @} */ + + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core decoder +
+ Depending on the mode set by DONT_USE_CORE_WORKBUFFER, workbuffers are + defined additionally to the CoreWorkbuffer. +
+ The size of WorkBuffers is ((1024)/(32))*(64) = 2048. +
+ WorkBuffer2 is a pointer to the CoreWorkBuffer wich is reused here in the SBR part. In case of + DONT_USE_CORE_WORKBUFFER, the CoreWorkbuffer is not used and the according + Workbuffer2 is defined locally in this file. +
+ WorkBuffer1 is reused in the AAC core (-> aacdecoder.cpp, aac_ram.cpp) +
+ + Use of WorkBuffers: +
+
+    -------------------------------------------------------------
+    AAC core:
+
+      CoreWorkbuffer: spectral coefficients
+      WorkBuffer1:    CAacDecoderChannelInfo, CAacDecoderDynamicData
+
+    -------------------------------------------------------------
+    SBR part:
+      ----------------------------------------------
+      Low Power Mode (useLP=1 or LOW_POWER_SBR_ONLY), see assignLcTimeSlots()
+
+        SLOT_BASED_PROTOTYPE_SYN_FILTER
+
+        WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | RealLeft       |                         | RealRight      |
+        |________________|                         |________________|
+
+      ----------------------------------------------
+      High Quality Mode (!LOW_POWER_SBR_ONLY and useLP=0), see assignHqTimeSlots()
+
+         SLOTBASED_PS
+
+         WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | Real/Imag      |  interleaved            | Real/Imag      |  interleaved
+        |________________|  first half actual ch   |________________|  second half actual ch
+
+    -------------------------------------------------------------
+
+  
+ +*/ +/* @{ */ +C_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer1, FIXP_DBL, ((1024)/(32))*(64), SECT_DATA_L1, WORKBUFFER1_TAG) +C_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer2, FIXP_DBL, ((1024)/(32))*(64), SECT_DATA_L2, WORKBUFFER2_TAG) + +/* @} */ + + + + diff --git a/libSBRdec/src/sbr_ram.h b/libSBRdec/src/sbr_ram.h new file mode 100644 index 00000000..7ab5044d --- /dev/null +++ b/libSBRdec/src/sbr_ram.h @@ -0,0 +1,159 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! +\file +\brief Memory layout + +*/ +#ifndef _SBR_RAM_H_ +#define _SBR_RAM_H_ + +#include "sbrdecoder.h" + +#include "env_extr.h" +#include "sbr_dec.h" + + + +#define SBRDEC_MAX_CH_PER_ELEMENT (2) + +typedef struct +{ + SBR_CHANNEL *pSbrChannel[SBRDEC_MAX_CH_PER_ELEMENT]; + TRANSPOSER_SETTINGS transposerSettings; /* Common transport settings for each individual channel of an element */ + HANDLE_FDK_BITSTREAM hBs; + + MP4_ELEMENT_ID elementID; /* Element ID set during initialization. Can be used for concealment */ + int nChannels; /* Number of elements output channels (=2 in case of PS) */ + + UCHAR frameErrorFlag[(1)+1]; /* Frame error status (for every slot in the delay line). + Will be copied into header at the very beginning of decodeElement() routine. */ + + UCHAR useFrameSlot; /* Index which defines which slot will be decoded/filled next (used with additional delay) */ + UCHAR useHeaderSlot[(1)+1]; /* Index array that provides the link between header and frame data + (important when processing with additional delay). */ +} SBR_DECODER_ELEMENT; + + +struct SBR_DECODER_INSTANCE +{ + SBR_DECODER_ELEMENT *pSbrElement[(8)]; + SBR_HEADER_DATA sbrHeader[(8)][(1)+1]; /* Sbr header for each individual channel of an element */ + + FIXP_DBL *workBuffer1; + FIXP_DBL *workBuffer2; + + HANDLE_PS_DEC hParametricStereoDec; + + /* Global parameters */ + AUDIO_OBJECT_TYPE coreCodec; /* AOT of core codec */ + int numSbrElements; + int numSbrChannels; + INT sampleRateIn; /* SBR decoder input sampling rate; might be different than the transposer input sampling rate. */ + INT sampleRateOut; /* Sampling rate of the SBR decoder output audio samples. */ + USHORT codecFrameSize; + UCHAR synDownsampleFac; + UCHAR numDelayFrames; /* The current number of additional delay frames used for processing. */ + UCHAR numFlushedFrames; /* The variable counts the number of frames which are flushed consecutively. */ + + UINT flags; + +}; + +H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) +H_ALLOC_MEM(Ram_SbrDecChannel, SBR_CHANNEL) +H_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE) + +H_ALLOC_MEM(Ram_sbr_QmfStatesSynthesis, FIXP_QSS) +H_ALLOC_MEM(Ram_sbr_OverlapBuffer, FIXP_DBL) + + +H_ALLOC_MEM(Ram_ps_dec, PS_DEC) + + +H_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer1, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(Ram_SbrDecWorkBuffer2, FIXP_DBL) + + +#endif /* _SBR_RAM_H_ */ diff --git a/libSBRdec/src/sbr_rom.cpp b/libSBRdec/src/sbr_rom.cpp new file mode 100644 index 00000000..4f2cc482 --- /dev/null +++ b/libSBRdec/src/sbr_rom.cpp @@ -0,0 +1,1423 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Definition of constant tables + + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbr_rom.h" + + + + +/*! + \name StartStopBands + \brief Start and stop subbands of the highband. + + k_o = startMin + offset[bs_start_freq]; + startMin = {3000,4000,5000} * (128/FS_sbr) / FS_sbr < 32Khz, 32Khz <= FS_sbr < 64KHz, 64KHz <= FS_sbr + The stop subband can also be calculated to save memory by defining #CALC_STOP_BAND. +*/ +//@{ +const UCHAR FDK_sbrDecoder_sbr_start_freq_16[16] = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_22[16] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_24[16] = {11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_32[16] = {10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_40[16] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_44[16] = { 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_48[16] = { 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_64[16] = { 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_88[16] = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31}; +//@} + + +/*! + \name Whitening + \brief Coefficients for spectral whitening in the transposer +*/ +//@{ +/*! Assignment of whitening tuning depending on the crossover frequency */ +const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES] = { + 0, + 5000, + 6000, + 6500, + 7000, + 7500, + 8000, + 9000, + 10000 +}; + +/*! + \brief Whithening levels tuning table + + With the current tuning, there are some redundant entries: + + \li NUM_WHFACTOR_TABLE_ENTRIES can be reduced by 3, + \li the first coloumn can be eliminated. + +*/ +const FIXP_DBL FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] = { + /* OFF_LEVEL, TRANSITION_LEVEL, LOW_LEVEL, MID_LEVEL, HIGH_LEVEL */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* < 5000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 5000 < 6000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6000 < 6500 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6500 < 7000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7000 < 7500 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7500 < 8000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 8000 < 9000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 9000 < 10000 */ + { FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* > 10000 */ +}; + + +//@} + + +/*! + \name EnvAdj + \brief Constants and tables used for envelope adjustment +*/ +//@{ + +/*! Mantissas of gain limits */ +const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4] = +{ + FL2FXCONST_SGL(0.5011932025f), /*!< -3 dB. Gain limit when limiterGains in frameData is 0 */ + FL2FXCONST_SGL(0.5f), /*!< 0 dB. Gain limit when limiterGains in frameData is 1 */ + FL2FXCONST_SGL(0.9976346258f), /*!< +3 dB. Gain limit when limiterGains in frameData is 2 */ + FL2FXCONST_SGL(0.6776263578f) /*!< Inf. Gain limit when limiterGains in frameData is 3 */ +}; + +/*! Exponents of gain limits */ +const UCHAR FDK_sbrDecoder_sbr_limGains_e[4] = +{ + 0, 1, 1, 67 +}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = +{ + FL2FXCONST_SGL(1.0f / 4.0f), + FL2FXCONST_SGL(1.2f / 4.0f), + FL2FXCONST_SGL(2.0f / 4.0f), + FL2FXCONST_SGL(3.0f / 4.0f) +}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = +{ + FL2FXCONST_DBL(1.0f / 4.0f), + FL2FXCONST_DBL(1.2f / 4.0f), + FL2FXCONST_DBL(2.0f / 4.0f), + FL2FXCONST_DBL(3.0f / 4.0f) +}; + +/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope */ +const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { + FL2FXCONST_SGL(0.66666666666666f), + FL2FXCONST_SGL(0.36516383427084f), + FL2FXCONST_SGL(0.14699433520835f), + FL2FXCONST_SGL(0.03183050093751f) +}; + + +/*! Real and imaginary part of random noise which will be modulated + to the desired level. An accuracy of 13 bits is sufficient for these + random numbers. +*/ +const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2] = { + { FL2FXCONST_SGL(-0.99948153278296f / 8.0), FL2FXCONST_SGL(-0.59483417516607f / 8.0) }, + { FL2FXCONST_SGL( 0.97113454393991f / 8.0), FL2FXCONST_SGL(-0.67528515225647f / 8.0) }, + { FL2FXCONST_SGL( 0.14130051758487f / 8.0), FL2FXCONST_SGL(-0.95090983575689f / 8.0) }, + { FL2FXCONST_SGL(-0.47005496701697f / 8.0), FL2FXCONST_SGL(-0.37340549728647f / 8.0) }, + { FL2FXCONST_SGL( 0.80705063769351f / 8.0), FL2FXCONST_SGL( 0.29653668284408f / 8.0) }, + { FL2FXCONST_SGL(-0.38981478896926f / 8.0), FL2FXCONST_SGL( 0.89572605717087f / 8.0) }, + { FL2FXCONST_SGL(-0.01053049862020f / 8.0), FL2FXCONST_SGL(-0.66959058036166f / 8.0) }, + { FL2FXCONST_SGL(-0.91266367957293f / 8.0), FL2FXCONST_SGL(-0.11522938140034f / 8.0) }, + { FL2FXCONST_SGL( 0.54840422910309f / 8.0), FL2FXCONST_SGL( 0.75221367176302f / 8.0) }, + { FL2FXCONST_SGL( 0.40009252867955f / 8.0), FL2FXCONST_SGL(-0.98929400334421f / 8.0) }, + { FL2FXCONST_SGL(-0.99867974711855f / 8.0), FL2FXCONST_SGL(-0.88147068645358f / 8.0) }, + { FL2FXCONST_SGL(-0.95531076805040f / 8.0), FL2FXCONST_SGL( 0.90908757154593f / 8.0) }, + { FL2FXCONST_SGL(-0.45725933317144f / 8.0), FL2FXCONST_SGL(-0.56716323646760f / 8.0) }, + { FL2FXCONST_SGL(-0.72929675029275f / 8.0), FL2FXCONST_SGL(-0.98008272727324f / 8.0) }, + { FL2FXCONST_SGL( 0.75622801399036f / 8.0), FL2FXCONST_SGL( 0.20950329995549f / 8.0) }, + { FL2FXCONST_SGL( 0.07069442601050f / 8.0), FL2FXCONST_SGL(-0.78247898470706f / 8.0) }, + { FL2FXCONST_SGL( 0.74496252926055f / 8.0), FL2FXCONST_SGL(-0.91169004445807f / 8.0) }, + { FL2FXCONST_SGL(-0.96440182703856f / 8.0), FL2FXCONST_SGL(-0.94739918296622f / 8.0) }, + { FL2FXCONST_SGL( 0.30424629369539f / 8.0), FL2FXCONST_SGL(-0.49438267012479f / 8.0) }, + { FL2FXCONST_SGL( 0.66565033746925f / 8.0), FL2FXCONST_SGL( 0.64652935542491f / 8.0) }, + { FL2FXCONST_SGL( 0.91697008020594f / 8.0), FL2FXCONST_SGL( 0.17514097332009f / 8.0) }, + { FL2FXCONST_SGL(-0.70774918760427f / 8.0), FL2FXCONST_SGL( 0.52548653416543f / 8.0) }, + { FL2FXCONST_SGL(-0.70051415345560f / 8.0), FL2FXCONST_SGL(-0.45340028808763f / 8.0) }, + { FL2FXCONST_SGL(-0.99496513054797f / 8.0), FL2FXCONST_SGL(-0.90071908066973f / 8.0) }, + { FL2FXCONST_SGL( 0.98164490790123f / 8.0), FL2FXCONST_SGL(-0.77463155528697f / 8.0) }, + { FL2FXCONST_SGL(-0.54671580548181f / 8.0), FL2FXCONST_SGL(-0.02570928536004f / 8.0) }, + { FL2FXCONST_SGL(-0.01689629065389f / 8.0), FL2FXCONST_SGL( 0.00287506445732f / 8.0) }, + { FL2FXCONST_SGL(-0.86110349531986f / 8.0), FL2FXCONST_SGL( 0.42548583726477f / 8.0) }, + { FL2FXCONST_SGL(-0.98892980586032f / 8.0), FL2FXCONST_SGL(-0.87881132267556f / 8.0) }, + { FL2FXCONST_SGL( 0.51756627678691f / 8.0), FL2FXCONST_SGL( 0.66926784710139f / 8.0) }, + { FL2FXCONST_SGL(-0.99635026409640f / 8.0), FL2FXCONST_SGL(-0.58107730574765f / 8.0) }, + { FL2FXCONST_SGL(-0.99969370862163f / 8.0), FL2FXCONST_SGL( 0.98369989360250f / 8.0) }, + { FL2FXCONST_SGL( 0.55266258627194f / 8.0), FL2FXCONST_SGL( 0.59449057465591f / 8.0) }, + { FL2FXCONST_SGL( 0.34581177741673f / 8.0), FL2FXCONST_SGL( 0.94879421061866f / 8.0) }, + { FL2FXCONST_SGL( 0.62664209577999f / 8.0), FL2FXCONST_SGL(-0.74402970906471f / 8.0) }, + { FL2FXCONST_SGL(-0.77149701404973f / 8.0), FL2FXCONST_SGL(-0.33883658042801f / 8.0) }, + { FL2FXCONST_SGL(-0.91592244254432f / 8.0), FL2FXCONST_SGL( 0.03687901376713f / 8.0) }, + { FL2FXCONST_SGL(-0.76285492357887f / 8.0), FL2FXCONST_SGL(-0.91371867919124f / 8.0) }, + { FL2FXCONST_SGL( 0.79788337195331f / 8.0), FL2FXCONST_SGL(-0.93180971199849f / 8.0) }, + { FL2FXCONST_SGL( 0.54473080610200f / 8.0), FL2FXCONST_SGL(-0.11919206037186f / 8.0) }, + { FL2FXCONST_SGL(-0.85639281671058f / 8.0), FL2FXCONST_SGL( 0.42429854760451f / 8.0) }, + { FL2FXCONST_SGL(-0.92882402971423f / 8.0), FL2FXCONST_SGL( 0.27871809078609f / 8.0) }, + { FL2FXCONST_SGL(-0.11708371046774f / 8.0), FL2FXCONST_SGL(-0.99800843444966f / 8.0) }, + { FL2FXCONST_SGL( 0.21356749817493f / 8.0), FL2FXCONST_SGL(-0.90716295627033f / 8.0) }, + { FL2FXCONST_SGL(-0.76191692573909f / 8.0), FL2FXCONST_SGL( 0.99768118356265f / 8.0) }, + { FL2FXCONST_SGL( 0.98111043100884f / 8.0), FL2FXCONST_SGL(-0.95854459734407f / 8.0) }, + { FL2FXCONST_SGL(-0.85913269895572f / 8.0), FL2FXCONST_SGL( 0.95766566168880f / 8.0) }, + { FL2FXCONST_SGL(-0.93307242253692f / 8.0), FL2FXCONST_SGL( 0.49431757696466f / 8.0) }, + { FL2FXCONST_SGL( 0.30485754879632f / 8.0), FL2FXCONST_SGL(-0.70540034357529f / 8.0) }, + { FL2FXCONST_SGL( 0.85289650925190f / 8.0), FL2FXCONST_SGL( 0.46766131791044f / 8.0) }, + { FL2FXCONST_SGL( 0.91328082618125f / 8.0), FL2FXCONST_SGL(-0.99839597361769f / 8.0) }, + { FL2FXCONST_SGL(-0.05890199924154f / 8.0), FL2FXCONST_SGL( 0.70741827819497f / 8.0) }, + { FL2FXCONST_SGL( 0.28398686150148f / 8.0), FL2FXCONST_SGL( 0.34633555702188f / 8.0) }, + { FL2FXCONST_SGL( 0.95258164539612f / 8.0), FL2FXCONST_SGL(-0.54893416026939f / 8.0) }, + { FL2FXCONST_SGL(-0.78566324168507f / 8.0), FL2FXCONST_SGL(-0.75568541079691f / 8.0) }, + { FL2FXCONST_SGL(-0.95789495447877f / 8.0), FL2FXCONST_SGL(-0.20423194696966f / 8.0) }, + { FL2FXCONST_SGL( 0.82411158711197f / 8.0), FL2FXCONST_SGL( 0.96654618432562f / 8.0) }, + { FL2FXCONST_SGL(-0.65185446735885f / 8.0), FL2FXCONST_SGL(-0.88734990773289f / 8.0) }, + { FL2FXCONST_SGL(-0.93643603134666f / 8.0), FL2FXCONST_SGL( 0.99870790442385f / 8.0) }, + { FL2FXCONST_SGL( 0.91427159529618f / 8.0), FL2FXCONST_SGL(-0.98290505544444f / 8.0) }, + { FL2FXCONST_SGL(-0.70395684036886f / 8.0), FL2FXCONST_SGL( 0.58796798221039f / 8.0) }, + { FL2FXCONST_SGL( 0.00563771969365f / 8.0), FL2FXCONST_SGL( 0.61768196727244f / 8.0) }, + { FL2FXCONST_SGL( 0.89065051931895f / 8.0), FL2FXCONST_SGL( 0.52783352697585f / 8.0) }, + { FL2FXCONST_SGL(-0.68683707712762f / 8.0), FL2FXCONST_SGL( 0.80806944710339f / 8.0) }, + { FL2FXCONST_SGL( 0.72165342518718f / 8.0), FL2FXCONST_SGL(-0.69259857349564f / 8.0) }, + { FL2FXCONST_SGL(-0.62928247730667f / 8.0), FL2FXCONST_SGL( 0.13627037407335f / 8.0) }, + { FL2FXCONST_SGL( 0.29938434065514f / 8.0), FL2FXCONST_SGL(-0.46051329682246f / 8.0) }, + { FL2FXCONST_SGL(-0.91781958879280f / 8.0), FL2FXCONST_SGL(-0.74012716684186f / 8.0) }, + { FL2FXCONST_SGL( 0.99298717043688f / 8.0), FL2FXCONST_SGL( 0.40816610075661f / 8.0) }, + { FL2FXCONST_SGL( 0.82368298622748f / 8.0), FL2FXCONST_SGL(-0.74036047190173f / 8.0) }, + { FL2FXCONST_SGL(-0.98512833386833f / 8.0), FL2FXCONST_SGL(-0.99972330709594f / 8.0) }, + { FL2FXCONST_SGL(-0.95915368242257f / 8.0), FL2FXCONST_SGL(-0.99237800466040f / 8.0) }, + { FL2FXCONST_SGL(-0.21411126572790f / 8.0), FL2FXCONST_SGL(-0.93424819052545f / 8.0) }, + { FL2FXCONST_SGL(-0.68821476106884f / 8.0), FL2FXCONST_SGL(-0.26892306315457f / 8.0) }, + { FL2FXCONST_SGL( 0.91851997982317f / 8.0), FL2FXCONST_SGL( 0.09358228901785f / 8.0) }, + { FL2FXCONST_SGL(-0.96062769559127f / 8.0), FL2FXCONST_SGL( 0.36099095133739f / 8.0) }, + { FL2FXCONST_SGL( 0.51646184922287f / 8.0), FL2FXCONST_SGL(-0.71373332873917f / 8.0) }, + { FL2FXCONST_SGL( 0.61130721139669f / 8.0), FL2FXCONST_SGL( 0.46950141175917f / 8.0) }, + { FL2FXCONST_SGL( 0.47336129371299f / 8.0), FL2FXCONST_SGL(-0.27333178296162f / 8.0) }, + { FL2FXCONST_SGL( 0.90998308703519f / 8.0), FL2FXCONST_SGL( 0.96715662938132f / 8.0) }, + { FL2FXCONST_SGL( 0.44844799194357f / 8.0), FL2FXCONST_SGL( 0.99211574628306f / 8.0) }, + { FL2FXCONST_SGL( 0.66614891079092f / 8.0), FL2FXCONST_SGL( 0.96590176169121f / 8.0) }, + { FL2FXCONST_SGL( 0.74922239129237f / 8.0), FL2FXCONST_SGL(-0.89879858826087f / 8.0) }, + { FL2FXCONST_SGL(-0.99571588506485f / 8.0), FL2FXCONST_SGL( 0.52785521494349f / 8.0) }, + { FL2FXCONST_SGL( 0.97401082477563f / 8.0), FL2FXCONST_SGL(-0.16855870075190f / 8.0) }, + { FL2FXCONST_SGL( 0.72683747733879f / 8.0), FL2FXCONST_SGL(-0.48060774432251f / 8.0) }, + { FL2FXCONST_SGL( 0.95432193457128f / 8.0), FL2FXCONST_SGL( 0.68849603408441f / 8.0) }, + { FL2FXCONST_SGL(-0.72962208425191f / 8.0), FL2FXCONST_SGL(-0.76608443420917f / 8.0) }, + { FL2FXCONST_SGL(-0.85359479233537f / 8.0), FL2FXCONST_SGL( 0.88738125901579f / 8.0) }, + { FL2FXCONST_SGL(-0.81412430338535f / 8.0), FL2FXCONST_SGL(-0.97480768049637f / 8.0) }, + { FL2FXCONST_SGL(-0.87930772356786f / 8.0), FL2FXCONST_SGL( 0.74748307690436f / 8.0) }, + { FL2FXCONST_SGL(-0.71573331064977f / 8.0), FL2FXCONST_SGL(-0.98570608178923f / 8.0) }, + { FL2FXCONST_SGL( 0.83524300028228f / 8.0), FL2FXCONST_SGL( 0.83702537075163f / 8.0) }, + { FL2FXCONST_SGL(-0.48086065601423f / 8.0), FL2FXCONST_SGL(-0.98848504923531f / 8.0) }, + { FL2FXCONST_SGL( 0.97139128574778f / 8.0), FL2FXCONST_SGL( 0.80093621198236f / 8.0) }, + { FL2FXCONST_SGL( 0.51992825347895f / 8.0), FL2FXCONST_SGL( 0.80247631400510f / 8.0) }, + { FL2FXCONST_SGL(-0.00848591195325f / 8.0), FL2FXCONST_SGL(-0.76670128000486f / 8.0) }, + { FL2FXCONST_SGL(-0.70294374303036f / 8.0), FL2FXCONST_SGL( 0.55359910445577f / 8.0) }, + { FL2FXCONST_SGL(-0.95894428168140f / 8.0), FL2FXCONST_SGL(-0.43265504344783f / 8.0) }, + { FL2FXCONST_SGL( 0.97079252950321f / 8.0), FL2FXCONST_SGL( 0.09325857238682f / 8.0) }, + { FL2FXCONST_SGL(-0.92404293670797f / 8.0), FL2FXCONST_SGL( 0.85507704027855f / 8.0) }, + { FL2FXCONST_SGL(-0.69506469500450f / 8.0), FL2FXCONST_SGL( 0.98633412625459f / 8.0) }, + { FL2FXCONST_SGL( 0.26559203620024f / 8.0), FL2FXCONST_SGL( 0.73314307966524f / 8.0) }, + { FL2FXCONST_SGL( 0.28038443336943f / 8.0), FL2FXCONST_SGL( 0.14537913654427f / 8.0) }, + { FL2FXCONST_SGL(-0.74138124825523f / 8.0), FL2FXCONST_SGL( 0.99310339807762f / 8.0) }, + { FL2FXCONST_SGL(-0.01752795995444f / 8.0), FL2FXCONST_SGL(-0.82616635284178f / 8.0) }, + { FL2FXCONST_SGL(-0.55126773094930f / 8.0), FL2FXCONST_SGL(-0.98898543862153f / 8.0) }, + { FL2FXCONST_SGL( 0.97960898850996f / 8.0), FL2FXCONST_SGL(-0.94021446752851f / 8.0) }, + { FL2FXCONST_SGL(-0.99196309146936f / 8.0), FL2FXCONST_SGL( 0.67019017358456f / 8.0) }, + { FL2FXCONST_SGL(-0.67684928085260f / 8.0), FL2FXCONST_SGL( 0.12631491649378f / 8.0) }, + { FL2FXCONST_SGL( 0.09140039465500f / 8.0), FL2FXCONST_SGL(-0.20537731453108f / 8.0) }, + { FL2FXCONST_SGL(-0.71658965751996f / 8.0), FL2FXCONST_SGL(-0.97788200391224f / 8.0) }, + { FL2FXCONST_SGL( 0.81014640078925f / 8.0), FL2FXCONST_SGL( 0.53722648362443f / 8.0) }, + { FL2FXCONST_SGL( 0.40616991671205f / 8.0), FL2FXCONST_SGL(-0.26469008598449f / 8.0) }, + { FL2FXCONST_SGL(-0.67680188682972f / 8.0), FL2FXCONST_SGL( 0.94502052337695f / 8.0) }, + { FL2FXCONST_SGL( 0.86849774348749f / 8.0), FL2FXCONST_SGL(-0.18333598647899f / 8.0) }, + { FL2FXCONST_SGL(-0.99500381284851f / 8.0), FL2FXCONST_SGL(-0.02634122068550f / 8.0) }, + { FL2FXCONST_SGL( 0.84329189340667f / 8.0), FL2FXCONST_SGL( 0.10406957462213f / 8.0) }, + { FL2FXCONST_SGL(-0.09215968531446f / 8.0), FL2FXCONST_SGL( 0.69540012101253f / 8.0) }, + { FL2FXCONST_SGL( 0.99956173327206f / 8.0), FL2FXCONST_SGL(-0.12358542001404f / 8.0) }, + { FL2FXCONST_SGL(-0.79732779473535f / 8.0), FL2FXCONST_SGL(-0.91582524736159f / 8.0) }, + { FL2FXCONST_SGL( 0.96349973642406f / 8.0), FL2FXCONST_SGL( 0.96640458041000f / 8.0) }, + { FL2FXCONST_SGL(-0.79942778496547f / 8.0), FL2FXCONST_SGL( 0.64323902822857f / 8.0) }, + { FL2FXCONST_SGL(-0.11566039853896f / 8.0), FL2FXCONST_SGL( 0.28587846253726f / 8.0) }, + { FL2FXCONST_SGL(-0.39922954514662f / 8.0), FL2FXCONST_SGL( 0.94129601616966f / 8.0) }, + { FL2FXCONST_SGL( 0.99089197565987f / 8.0), FL2FXCONST_SGL(-0.92062625581587f / 8.0) }, + { FL2FXCONST_SGL( 0.28631285179909f / 8.0), FL2FXCONST_SGL(-0.91035047143603f / 8.0) }, + { FL2FXCONST_SGL(-0.83302725605608f / 8.0), FL2FXCONST_SGL(-0.67330410892084f / 8.0) }, + { FL2FXCONST_SGL( 0.95404443402072f / 8.0), FL2FXCONST_SGL( 0.49162765398743f / 8.0) }, + { FL2FXCONST_SGL(-0.06449863579434f / 8.0), FL2FXCONST_SGL( 0.03250560813135f / 8.0) }, + { FL2FXCONST_SGL(-0.99575054486311f / 8.0), FL2FXCONST_SGL( 0.42389784469507f / 8.0) }, + { FL2FXCONST_SGL(-0.65501142790847f / 8.0), FL2FXCONST_SGL( 0.82546114655624f / 8.0) }, + { FL2FXCONST_SGL(-0.81254441908887f / 8.0), FL2FXCONST_SGL(-0.51627234660629f / 8.0) }, + { FL2FXCONST_SGL(-0.99646369485481f / 8.0), FL2FXCONST_SGL( 0.84490533520752f / 8.0) }, + { FL2FXCONST_SGL( 0.00287840603348f / 8.0), FL2FXCONST_SGL( 0.64768261158166f / 8.0) }, + { FL2FXCONST_SGL( 0.70176989408455f / 8.0), FL2FXCONST_SGL(-0.20453028573322f / 8.0) }, + { FL2FXCONST_SGL( 0.96361882270190f / 8.0), FL2FXCONST_SGL( 0.40706967140989f / 8.0) }, + { FL2FXCONST_SGL(-0.68883758192426f / 8.0), FL2FXCONST_SGL( 0.91338958840772f / 8.0) }, + { FL2FXCONST_SGL(-0.34875585502238f / 8.0), FL2FXCONST_SGL( 0.71472290693300f / 8.0) }, + { FL2FXCONST_SGL( 0.91980081243087f / 8.0), FL2FXCONST_SGL( 0.66507455644919f / 8.0) }, + { FL2FXCONST_SGL(-0.99009048343881f / 8.0), FL2FXCONST_SGL( 0.85868021604848f / 8.0) }, + { FL2FXCONST_SGL( 0.68865791458395f / 8.0), FL2FXCONST_SGL( 0.55660316809678f / 8.0) }, + { FL2FXCONST_SGL(-0.99484402129368f / 8.0), FL2FXCONST_SGL(-0.20052559254934f / 8.0) }, + { FL2FXCONST_SGL( 0.94214511408023f / 8.0), FL2FXCONST_SGL(-0.99696425367461f / 8.0) }, + { FL2FXCONST_SGL(-0.67414626793544f / 8.0), FL2FXCONST_SGL( 0.49548221180078f / 8.0) }, + { FL2FXCONST_SGL(-0.47339353684664f / 8.0), FL2FXCONST_SGL(-0.85904328834047f / 8.0) }, + { FL2FXCONST_SGL( 0.14323651387360f / 8.0), FL2FXCONST_SGL(-0.94145598222488f / 8.0) }, + { FL2FXCONST_SGL(-0.29268293575672f / 8.0), FL2FXCONST_SGL( 0.05759224927952f / 8.0) }, + { FL2FXCONST_SGL( 0.43793861458754f / 8.0), FL2FXCONST_SGL(-0.78904969892724f / 8.0) }, + { FL2FXCONST_SGL(-0.36345126374441f / 8.0), FL2FXCONST_SGL( 0.64874435357162f / 8.0) }, + { FL2FXCONST_SGL(-0.08750604656825f / 8.0), FL2FXCONST_SGL( 0.97686944362527f / 8.0) }, + { FL2FXCONST_SGL(-0.96495267812511f / 8.0), FL2FXCONST_SGL(-0.53960305946511f / 8.0) }, + { FL2FXCONST_SGL( 0.55526940659947f / 8.0), FL2FXCONST_SGL( 0.78891523734774f / 8.0) }, + { FL2FXCONST_SGL( 0.73538215752630f / 8.0), FL2FXCONST_SGL( 0.96452072373404f / 8.0) }, + { FL2FXCONST_SGL(-0.30889773919437f / 8.0), FL2FXCONST_SGL(-0.80664389776860f / 8.0) }, + { FL2FXCONST_SGL( 0.03574995626194f / 8.0), FL2FXCONST_SGL(-0.97325616900959f / 8.0) }, + { FL2FXCONST_SGL( 0.98720684660488f / 8.0), FL2FXCONST_SGL( 0.48409133691962f / 8.0) }, + { FL2FXCONST_SGL(-0.81689296271203f / 8.0), FL2FXCONST_SGL(-0.90827703628298f / 8.0) }, + { FL2FXCONST_SGL( 0.67866860118215f / 8.0), FL2FXCONST_SGL( 0.81284503870856f / 8.0) }, + { FL2FXCONST_SGL(-0.15808569732583f / 8.0), FL2FXCONST_SGL( 0.85279555024382f / 8.0) }, + { FL2FXCONST_SGL( 0.80723395114371f / 8.0), FL2FXCONST_SGL(-0.24717418514605f / 8.0) }, + { FL2FXCONST_SGL( 0.47788757329038f / 8.0), FL2FXCONST_SGL(-0.46333147839295f / 8.0) }, + { FL2FXCONST_SGL( 0.96367554763201f / 8.0), FL2FXCONST_SGL( 0.38486749303242f / 8.0) }, + { FL2FXCONST_SGL(-0.99143875716818f / 8.0), FL2FXCONST_SGL(-0.24945277239809f / 8.0) }, + { FL2FXCONST_SGL( 0.83081876925833f / 8.0), FL2FXCONST_SGL(-0.94780851414763f / 8.0) }, + { FL2FXCONST_SGL(-0.58753191905341f / 8.0), FL2FXCONST_SGL( 0.01290772389163f / 8.0) }, + { FL2FXCONST_SGL( 0.95538108220960f / 8.0), FL2FXCONST_SGL(-0.85557052096538f / 8.0) }, + { FL2FXCONST_SGL(-0.96490920476211f / 8.0), FL2FXCONST_SGL(-0.64020970923102f / 8.0) }, + { FL2FXCONST_SGL(-0.97327101028521f / 8.0), FL2FXCONST_SGL( 0.12378128133110f / 8.0) }, + { FL2FXCONST_SGL( 0.91400366022124f / 8.0), FL2FXCONST_SGL( 0.57972471346930f / 8.0) }, + { FL2FXCONST_SGL(-0.99925837363824f / 8.0), FL2FXCONST_SGL( 0.71084847864067f / 8.0) }, + { FL2FXCONST_SGL(-0.86875903507313f / 8.0), FL2FXCONST_SGL(-0.20291699203564f / 8.0) }, + { FL2FXCONST_SGL(-0.26240034795124f / 8.0), FL2FXCONST_SGL(-0.68264554369108f / 8.0) }, + { FL2FXCONST_SGL(-0.24664412953388f / 8.0), FL2FXCONST_SGL(-0.87642273115183f / 8.0) }, + { FL2FXCONST_SGL( 0.02416275806869f / 8.0), FL2FXCONST_SGL( 0.27192914288905f / 8.0) }, + { FL2FXCONST_SGL( 0.82068619590515f / 8.0), FL2FXCONST_SGL(-0.85087787994476f / 8.0) }, + { FL2FXCONST_SGL( 0.88547373760759f / 8.0), FL2FXCONST_SGL(-0.89636802901469f / 8.0) }, + { FL2FXCONST_SGL(-0.18173078152226f / 8.0), FL2FXCONST_SGL(-0.26152145156800f / 8.0) }, + { FL2FXCONST_SGL( 0.09355476558534f / 8.0), FL2FXCONST_SGL( 0.54845123045604f / 8.0) }, + { FL2FXCONST_SGL(-0.54668414224090f / 8.0), FL2FXCONST_SGL( 0.95980774020221f / 8.0) }, + { FL2FXCONST_SGL( 0.37050990604091f / 8.0), FL2FXCONST_SGL(-0.59910140383171f / 8.0) }, + { FL2FXCONST_SGL(-0.70373594262891f / 8.0), FL2FXCONST_SGL( 0.91227665827081f / 8.0) }, + { FL2FXCONST_SGL(-0.34600785879594f / 8.0), FL2FXCONST_SGL(-0.99441426144200f / 8.0) }, + { FL2FXCONST_SGL(-0.68774481731008f / 8.0), FL2FXCONST_SGL(-0.30238837956299f / 8.0) }, + { FL2FXCONST_SGL(-0.26843291251234f / 8.0), FL2FXCONST_SGL( 0.83115668004362f / 8.0) }, + { FL2FXCONST_SGL( 0.49072334613242f / 8.0), FL2FXCONST_SGL(-0.45359708737775f / 8.0) }, + { FL2FXCONST_SGL( 0.38975993093975f / 8.0), FL2FXCONST_SGL( 0.95515358099121f / 8.0) }, + { FL2FXCONST_SGL(-0.97757125224150f / 8.0), FL2FXCONST_SGL( 0.05305894580606f / 8.0) }, + { FL2FXCONST_SGL(-0.17325552859616f / 8.0), FL2FXCONST_SGL(-0.92770672250494f / 8.0) }, + { FL2FXCONST_SGL( 0.99948035025744f / 8.0), FL2FXCONST_SGL( 0.58285545563426f / 8.0) }, + { FL2FXCONST_SGL(-0.64946246527458f / 8.0), FL2FXCONST_SGL( 0.68645507104960f / 8.0) }, + { FL2FXCONST_SGL(-0.12016920576437f / 8.0), FL2FXCONST_SGL(-0.57147322153312f / 8.0) }, + { FL2FXCONST_SGL(-0.58947456517751f / 8.0), FL2FXCONST_SGL(-0.34847132454388f / 8.0) }, + { FL2FXCONST_SGL(-0.41815140454465f / 8.0), FL2FXCONST_SGL( 0.16276422358861f / 8.0) }, + { FL2FXCONST_SGL( 0.99885650204884f / 8.0), FL2FXCONST_SGL( 0.11136095490444f / 8.0) }, + { FL2FXCONST_SGL(-0.56649614128386f / 8.0), FL2FXCONST_SGL(-0.90494866361587f / 8.0) }, + { FL2FXCONST_SGL( 0.94138021032330f / 8.0), FL2FXCONST_SGL( 0.35281916733018f / 8.0) }, + { FL2FXCONST_SGL(-0.75725076534641f / 8.0), FL2FXCONST_SGL( 0.53650549640587f / 8.0) }, + { FL2FXCONST_SGL( 0.20541973692630f / 8.0), FL2FXCONST_SGL(-0.94435144369918f / 8.0) }, + { FL2FXCONST_SGL( 0.99980371023351f / 8.0), FL2FXCONST_SGL( 0.79835913565599f / 8.0) }, + { FL2FXCONST_SGL( 0.29078277605775f / 8.0), FL2FXCONST_SGL( 0.35393777921520f / 8.0) }, + { FL2FXCONST_SGL(-0.62858772103030f / 8.0), FL2FXCONST_SGL( 0.38765693387102f / 8.0) }, + { FL2FXCONST_SGL( 0.43440904467688f / 8.0), FL2FXCONST_SGL(-0.98546330463232f / 8.0) }, + { FL2FXCONST_SGL(-0.98298583762390f / 8.0), FL2FXCONST_SGL( 0.21021524625209f / 8.0) }, + { FL2FXCONST_SGL( 0.19513029146934f / 8.0), FL2FXCONST_SGL(-0.94239832251867f / 8.0) }, + { FL2FXCONST_SGL(-0.95476662400101f / 8.0), FL2FXCONST_SGL( 0.98364554179143f / 8.0) }, + { FL2FXCONST_SGL( 0.93379635304810f / 8.0), FL2FXCONST_SGL(-0.70881994583682f / 8.0) }, + { FL2FXCONST_SGL(-0.85235410573336f / 8.0), FL2FXCONST_SGL(-0.08342347966410f / 8.0) }, + { FL2FXCONST_SGL(-0.86425093011245f / 8.0), FL2FXCONST_SGL(-0.45795025029466f / 8.0) }, + { FL2FXCONST_SGL( 0.38879779059045f / 8.0), FL2FXCONST_SGL( 0.97274429344593f / 8.0) }, + { FL2FXCONST_SGL( 0.92045124735495f / 8.0), FL2FXCONST_SGL(-0.62433652524220f / 8.0) }, + { FL2FXCONST_SGL( 0.89162532251878f / 8.0), FL2FXCONST_SGL( 0.54950955570563f / 8.0) }, + { FL2FXCONST_SGL(-0.36834336949252f / 8.0), FL2FXCONST_SGL( 0.96458298020975f / 8.0) }, + { FL2FXCONST_SGL( 0.93891760988045f / 8.0), FL2FXCONST_SGL(-0.89968353740388f / 8.0) }, + { FL2FXCONST_SGL( 0.99267657565094f / 8.0), FL2FXCONST_SGL(-0.03757034316958f / 8.0) }, + { FL2FXCONST_SGL(-0.94063471614176f / 8.0), FL2FXCONST_SGL( 0.41332338538963f / 8.0) }, + { FL2FXCONST_SGL( 0.99740224117019f / 8.0), FL2FXCONST_SGL(-0.16830494996370f / 8.0) }, + { FL2FXCONST_SGL(-0.35899413170555f / 8.0), FL2FXCONST_SGL(-0.46633226649613f / 8.0) }, + { FL2FXCONST_SGL( 0.05237237274947f / 8.0), FL2FXCONST_SGL(-0.25640361602661f / 8.0) }, + { FL2FXCONST_SGL( 0.36703583957424f / 8.0), FL2FXCONST_SGL(-0.38653265641875f / 8.0) }, + { FL2FXCONST_SGL( 0.91653180367913f / 8.0), FL2FXCONST_SGL(-0.30587628726597f / 8.0) }, + { FL2FXCONST_SGL( 0.69000803499316f / 8.0), FL2FXCONST_SGL( 0.90952171386132f / 8.0) }, + { FL2FXCONST_SGL(-0.38658751133527f / 8.0), FL2FXCONST_SGL( 0.99501571208985f / 8.0) }, + { FL2FXCONST_SGL(-0.29250814029851f / 8.0), FL2FXCONST_SGL( 0.37444994344615f / 8.0) }, + { FL2FXCONST_SGL(-0.60182204677608f / 8.0), FL2FXCONST_SGL( 0.86779651036123f / 8.0) }, + { FL2FXCONST_SGL(-0.97418588163217f / 8.0), FL2FXCONST_SGL( 0.96468523666475f / 8.0) }, + { FL2FXCONST_SGL( 0.88461574003963f / 8.0), FL2FXCONST_SGL( 0.57508405276414f / 8.0) }, + { FL2FXCONST_SGL( 0.05198933055162f / 8.0), FL2FXCONST_SGL( 0.21269661669964f / 8.0) }, + { FL2FXCONST_SGL(-0.53499621979720f / 8.0), FL2FXCONST_SGL( 0.97241553731237f / 8.0) }, + { FL2FXCONST_SGL(-0.49429560226497f / 8.0), FL2FXCONST_SGL( 0.98183865291903f / 8.0) }, + { FL2FXCONST_SGL(-0.98935142339139f / 8.0), FL2FXCONST_SGL(-0.40249159006933f / 8.0) }, + { FL2FXCONST_SGL(-0.98081380091130f / 8.0), FL2FXCONST_SGL(-0.72856895534041f / 8.0) }, + { FL2FXCONST_SGL(-0.27338148835532f / 8.0), FL2FXCONST_SGL( 0.99950922447209f / 8.0) }, + { FL2FXCONST_SGL( 0.06310802338302f / 8.0), FL2FXCONST_SGL(-0.54539587529618f / 8.0) }, + { FL2FXCONST_SGL(-0.20461677199539f / 8.0), FL2FXCONST_SGL(-0.14209977628489f / 8.0) }, + { FL2FXCONST_SGL( 0.66223843141647f / 8.0), FL2FXCONST_SGL( 0.72528579940326f / 8.0) }, + { FL2FXCONST_SGL(-0.84764345483665f / 8.0), FL2FXCONST_SGL( 0.02372316801261f / 8.0) }, + { FL2FXCONST_SGL(-0.89039863483811f / 8.0), FL2FXCONST_SGL( 0.88866581484602f / 8.0) }, + { FL2FXCONST_SGL( 0.95903308477986f / 8.0), FL2FXCONST_SGL( 0.76744927173873f / 8.0) }, + { FL2FXCONST_SGL( 0.73504123909879f / 8.0), FL2FXCONST_SGL(-0.03747203173192f / 8.0) }, + { FL2FXCONST_SGL(-0.31744434966056f / 8.0), FL2FXCONST_SGL(-0.36834111883652f / 8.0) }, + { FL2FXCONST_SGL(-0.34110827591623f / 8.0), FL2FXCONST_SGL( 0.40211222807691f / 8.0) }, + { FL2FXCONST_SGL( 0.47803883714199f / 8.0), FL2FXCONST_SGL(-0.39423219786288f / 8.0) }, + { FL2FXCONST_SGL( 0.98299195879514f / 8.0), FL2FXCONST_SGL( 0.01989791390047f / 8.0) }, + { FL2FXCONST_SGL(-0.30963073129751f / 8.0), FL2FXCONST_SGL(-0.18076720599336f / 8.0) }, + { FL2FXCONST_SGL( 0.99992588229018f / 8.0), FL2FXCONST_SGL(-0.26281872094289f / 8.0) }, + { FL2FXCONST_SGL(-0.93149731080767f / 8.0), FL2FXCONST_SGL(-0.98313162570490f / 8.0) }, + { FL2FXCONST_SGL( 0.99923472302773f / 8.0), FL2FXCONST_SGL(-0.80142993767554f / 8.0) }, + { FL2FXCONST_SGL(-0.26024169633417f / 8.0), FL2FXCONST_SGL(-0.75999759855752f / 8.0) }, + { FL2FXCONST_SGL(-0.35712514743563f / 8.0), FL2FXCONST_SGL( 0.19298963768574f / 8.0) }, + { FL2FXCONST_SGL(-0.99899084509530f / 8.0), FL2FXCONST_SGL( 0.74645156992493f / 8.0) }, + { FL2FXCONST_SGL( 0.86557171579452f / 8.0), FL2FXCONST_SGL( 0.55593866696299f / 8.0) }, + { FL2FXCONST_SGL( 0.33408042438752f / 8.0), FL2FXCONST_SGL( 0.86185953874709f / 8.0) }, + { FL2FXCONST_SGL( 0.99010736374716f / 8.0), FL2FXCONST_SGL( 0.04602397576623f / 8.0) }, + { FL2FXCONST_SGL(-0.66694269691195f / 8.0), FL2FXCONST_SGL(-0.91643611810148f / 8.0) }, + { FL2FXCONST_SGL( 0.64016792079480f / 8.0), FL2FXCONST_SGL( 0.15649530836856f / 8.0) }, + { FL2FXCONST_SGL( 0.99570534804836f / 8.0), FL2FXCONST_SGL( 0.45844586038111f / 8.0) }, + { FL2FXCONST_SGL(-0.63431466947340f / 8.0), FL2FXCONST_SGL( 0.21079116459234f / 8.0) }, + { FL2FXCONST_SGL(-0.07706847005931f / 8.0), FL2FXCONST_SGL(-0.89581437101329f / 8.0) }, + { FL2FXCONST_SGL( 0.98590090577724f / 8.0), FL2FXCONST_SGL( 0.88241721133981f / 8.0) }, + { FL2FXCONST_SGL( 0.80099335254678f / 8.0), FL2FXCONST_SGL(-0.36851896710853f / 8.0) }, + { FL2FXCONST_SGL( 0.78368131392666f / 8.0), FL2FXCONST_SGL( 0.45506999802597f / 8.0) }, + { FL2FXCONST_SGL( 0.08707806671691f / 8.0), FL2FXCONST_SGL( 0.80938994918745f / 8.0) }, + { FL2FXCONST_SGL(-0.86811883080712f / 8.0), FL2FXCONST_SGL( 0.39347308654705f / 8.0) }, + { FL2FXCONST_SGL(-0.39466529740375f / 8.0), FL2FXCONST_SGL(-0.66809432114456f / 8.0) }, + { FL2FXCONST_SGL( 0.97875325649683f / 8.0), FL2FXCONST_SGL(-0.72467840967746f / 8.0) }, + { FL2FXCONST_SGL(-0.95038560288864f / 8.0), FL2FXCONST_SGL( 0.89563219587625f / 8.0) }, + { FL2FXCONST_SGL( 0.17005239424212f / 8.0), FL2FXCONST_SGL( 0.54683053962658f / 8.0) }, + { FL2FXCONST_SGL(-0.76910792026848f / 8.0), FL2FXCONST_SGL(-0.96226617549298f / 8.0) }, + { FL2FXCONST_SGL( 0.99743281016846f / 8.0), FL2FXCONST_SGL( 0.42697157037567f / 8.0) }, + { FL2FXCONST_SGL( 0.95437383549973f / 8.0), FL2FXCONST_SGL( 0.97002324109952f / 8.0) }, + { FL2FXCONST_SGL( 0.99578905365569f / 8.0), FL2FXCONST_SGL(-0.54106826257356f / 8.0) }, + { FL2FXCONST_SGL( 0.28058259829990f / 8.0), FL2FXCONST_SGL(-0.85361420634036f / 8.0) }, + { FL2FXCONST_SGL( 0.85256524470573f / 8.0), FL2FXCONST_SGL(-0.64567607735589f / 8.0) }, + { FL2FXCONST_SGL(-0.50608540105128f / 8.0), FL2FXCONST_SGL(-0.65846015480300f / 8.0) }, + { FL2FXCONST_SGL(-0.97210735183243f / 8.0), FL2FXCONST_SGL(-0.23095213067791f / 8.0) }, + { FL2FXCONST_SGL( 0.95424048234441f / 8.0), FL2FXCONST_SGL(-0.99240147091219f / 8.0) }, + { FL2FXCONST_SGL(-0.96926570524023f / 8.0), FL2FXCONST_SGL( 0.73775654896574f / 8.0) }, + { FL2FXCONST_SGL( 0.30872163214726f / 8.0), FL2FXCONST_SGL( 0.41514960556126f / 8.0) }, + { FL2FXCONST_SGL(-0.24523839572639f / 8.0), FL2FXCONST_SGL( 0.63206633394807f / 8.0) }, + { FL2FXCONST_SGL(-0.33813265086024f / 8.0), FL2FXCONST_SGL(-0.38661779441897f / 8.0) }, + { FL2FXCONST_SGL(-0.05826828420146f / 8.0), FL2FXCONST_SGL(-0.06940774188029f / 8.0) }, + { FL2FXCONST_SGL(-0.22898461455054f / 8.0), FL2FXCONST_SGL( 0.97054853316316f / 8.0) }, + { FL2FXCONST_SGL(-0.18509915019881f / 8.0), FL2FXCONST_SGL( 0.47565762892084f / 8.0) }, + { FL2FXCONST_SGL(-0.10488238045009f / 8.0), FL2FXCONST_SGL(-0.87769947402394f / 8.0) }, + { FL2FXCONST_SGL(-0.71886586182037f / 8.0), FL2FXCONST_SGL( 0.78030982480538f / 8.0) }, + { FL2FXCONST_SGL( 0.99793873738654f / 8.0), FL2FXCONST_SGL( 0.90041310491497f / 8.0) }, + { FL2FXCONST_SGL( 0.57563307626120f / 8.0), FL2FXCONST_SGL(-0.91034337352097f / 8.0) }, + { FL2FXCONST_SGL( 0.28909646383717f / 8.0), FL2FXCONST_SGL( 0.96307783970534f / 8.0) }, + { FL2FXCONST_SGL( 0.42188998312520f / 8.0), FL2FXCONST_SGL( 0.48148651230437f / 8.0) }, + { FL2FXCONST_SGL( 0.93335049681047f / 8.0), FL2FXCONST_SGL(-0.43537023883588f / 8.0) }, + { FL2FXCONST_SGL(-0.97087374418267f / 8.0), FL2FXCONST_SGL( 0.86636445711364f / 8.0) }, + { FL2FXCONST_SGL( 0.36722871286923f / 8.0), FL2FXCONST_SGL( 0.65291654172961f / 8.0) }, + { FL2FXCONST_SGL(-0.81093025665696f / 8.0), FL2FXCONST_SGL( 0.08778370229363f / 8.0) }, + { FL2FXCONST_SGL(-0.26240603062237f / 8.0), FL2FXCONST_SGL(-0.92774095379098f / 8.0) }, + { FL2FXCONST_SGL( 0.83996497984604f / 8.0), FL2FXCONST_SGL( 0.55839849139647f / 8.0) }, + { FL2FXCONST_SGL(-0.99909615720225f / 8.0), FL2FXCONST_SGL(-0.96024605713970f / 8.0) }, + { FL2FXCONST_SGL( 0.74649464155061f / 8.0), FL2FXCONST_SGL( 0.12144893606462f / 8.0) }, + { FL2FXCONST_SGL(-0.74774595569805f / 8.0), FL2FXCONST_SGL(-0.26898062008959f / 8.0) }, + { FL2FXCONST_SGL( 0.95781667469567f / 8.0), FL2FXCONST_SGL(-0.79047927052628f / 8.0) }, + { FL2FXCONST_SGL( 0.95472308713099f / 8.0), FL2FXCONST_SGL(-0.08588776019550f / 8.0) }, + { FL2FXCONST_SGL( 0.48708332746299f / 8.0), FL2FXCONST_SGL( 0.99999041579432f / 8.0) }, + { FL2FXCONST_SGL( 0.46332038247497f / 8.0), FL2FXCONST_SGL( 0.10964126185063f / 8.0) }, + { FL2FXCONST_SGL(-0.76497004940162f / 8.0), FL2FXCONST_SGL( 0.89210929242238f / 8.0) }, + { FL2FXCONST_SGL( 0.57397389364339f / 8.0), FL2FXCONST_SGL( 0.35289703373760f / 8.0) }, + { FL2FXCONST_SGL( 0.75374316974495f / 8.0), FL2FXCONST_SGL( 0.96705214651335f / 8.0) }, + { FL2FXCONST_SGL(-0.59174397685714f / 8.0), FL2FXCONST_SGL(-0.89405370422752f / 8.0) }, + { FL2FXCONST_SGL( 0.75087906691890f / 8.0), FL2FXCONST_SGL(-0.29612672982396f / 8.0) }, + { FL2FXCONST_SGL(-0.98607857336230f / 8.0), FL2FXCONST_SGL( 0.25034911730023f / 8.0) }, + { FL2FXCONST_SGL(-0.40761056640505f / 8.0), FL2FXCONST_SGL(-0.90045573444695f / 8.0) }, + { FL2FXCONST_SGL( 0.66929266740477f / 8.0), FL2FXCONST_SGL( 0.98629493401748f / 8.0) }, + { FL2FXCONST_SGL(-0.97463695257310f / 8.0), FL2FXCONST_SGL(-0.00190223301301f / 8.0) }, + { FL2FXCONST_SGL( 0.90145509409859f / 8.0), FL2FXCONST_SGL( 0.99781390365446f / 8.0) }, + { FL2FXCONST_SGL(-0.87259289048043f / 8.0), FL2FXCONST_SGL( 0.99233587353666f / 8.0) }, + { FL2FXCONST_SGL(-0.91529461447692f / 8.0), FL2FXCONST_SGL(-0.15698707534206f / 8.0) }, + { FL2FXCONST_SGL(-0.03305738840705f / 8.0), FL2FXCONST_SGL(-0.37205262859764f / 8.0) }, + { FL2FXCONST_SGL( 0.07223051368337f / 8.0), FL2FXCONST_SGL(-0.88805001733626f / 8.0) }, + { FL2FXCONST_SGL( 0.99498012188353f / 8.0), FL2FXCONST_SGL( 0.97094358113387f / 8.0) }, + { FL2FXCONST_SGL(-0.74904939500519f / 8.0), FL2FXCONST_SGL( 0.99985483641521f / 8.0) }, + { FL2FXCONST_SGL( 0.04585228574211f / 8.0), FL2FXCONST_SGL( 0.99812337444082f / 8.0) }, + { FL2FXCONST_SGL(-0.89054954257993f / 8.0), FL2FXCONST_SGL(-0.31791913188064f / 8.0) }, + { FL2FXCONST_SGL(-0.83782144651251f / 8.0), FL2FXCONST_SGL( 0.97637632547466f / 8.0) }, + { FL2FXCONST_SGL( 0.33454804933804f / 8.0), FL2FXCONST_SGL(-0.86231516800408f / 8.0) }, + { FL2FXCONST_SGL(-0.99707579362824f / 8.0), FL2FXCONST_SGL( 0.93237990079441f / 8.0) }, + { FL2FXCONST_SGL(-0.22827527843994f / 8.0), FL2FXCONST_SGL( 0.18874759397997f / 8.0) }, + { FL2FXCONST_SGL( 0.67248046289143f / 8.0), FL2FXCONST_SGL(-0.03646211390569f / 8.0) }, + { FL2FXCONST_SGL(-0.05146538187944f / 8.0), FL2FXCONST_SGL(-0.92599700120679f / 8.0) }, + { FL2FXCONST_SGL( 0.99947295749905f / 8.0), FL2FXCONST_SGL( 0.93625229707912f / 8.0) }, + { FL2FXCONST_SGL( 0.66951124390363f / 8.0), FL2FXCONST_SGL( 0.98905825623893f / 8.0) }, + { FL2FXCONST_SGL(-0.99602956559179f / 8.0), FL2FXCONST_SGL(-0.44654715757688f / 8.0) }, + { FL2FXCONST_SGL( 0.82104905483590f / 8.0), FL2FXCONST_SGL( 0.99540741724928f / 8.0) }, + { FL2FXCONST_SGL( 0.99186510988782f / 8.0), FL2FXCONST_SGL( 0.72023001312947f / 8.0) }, + { FL2FXCONST_SGL(-0.65284592392918f / 8.0), FL2FXCONST_SGL( 0.52186723253637f / 8.0) }, + { FL2FXCONST_SGL( 0.93885443798188f / 8.0), FL2FXCONST_SGL(-0.74895312615259f / 8.0) }, + { FL2FXCONST_SGL( 0.96735248738388f / 8.0), FL2FXCONST_SGL( 0.90891816978629f / 8.0) }, + { FL2FXCONST_SGL(-0.22225968841114f / 8.0), FL2FXCONST_SGL( 0.57124029781228f / 8.0) }, + { FL2FXCONST_SGL(-0.44132783753414f / 8.0), FL2FXCONST_SGL(-0.92688840659280f / 8.0) }, + { FL2FXCONST_SGL(-0.85694974219574f / 8.0), FL2FXCONST_SGL( 0.88844532719844f / 8.0) }, + { FL2FXCONST_SGL( 0.91783042091762f / 8.0), FL2FXCONST_SGL(-0.46356892383970f / 8.0) }, + { FL2FXCONST_SGL( 0.72556974415690f / 8.0), FL2FXCONST_SGL(-0.99899555770747f / 8.0) }, + { FL2FXCONST_SGL(-0.99711581834508f / 8.0), FL2FXCONST_SGL( 0.58211560180426f / 8.0) }, + { FL2FXCONST_SGL( 0.77638976371966f / 8.0), FL2FXCONST_SGL( 0.94321834873819f / 8.0) }, + { FL2FXCONST_SGL( 0.07717324253925f / 8.0), FL2FXCONST_SGL( 0.58638399856595f / 8.0) }, + { FL2FXCONST_SGL(-0.56049829194163f / 8.0), FL2FXCONST_SGL( 0.82522301569036f / 8.0) }, + { FL2FXCONST_SGL( 0.98398893639988f / 8.0), FL2FXCONST_SGL( 0.39467440420569f / 8.0) }, + { FL2FXCONST_SGL( 0.47546946844938f / 8.0), FL2FXCONST_SGL( 0.68613044836811f / 8.0) }, + { FL2FXCONST_SGL( 0.65675089314631f / 8.0), FL2FXCONST_SGL( 0.18331637134880f / 8.0) }, + { FL2FXCONST_SGL( 0.03273375457980f / 8.0), FL2FXCONST_SGL(-0.74933109564108f / 8.0) }, + { FL2FXCONST_SGL(-0.38684144784738f / 8.0), FL2FXCONST_SGL( 0.51337349030406f / 8.0) }, + { FL2FXCONST_SGL(-0.97346267944545f / 8.0), FL2FXCONST_SGL(-0.96549364384098f / 8.0) }, + { FL2FXCONST_SGL(-0.53282156061942f / 8.0), FL2FXCONST_SGL(-0.91423265091354f / 8.0) }, + { FL2FXCONST_SGL( 0.99817310731176f / 8.0), FL2FXCONST_SGL( 0.61133572482148f / 8.0) }, + { FL2FXCONST_SGL(-0.50254500772635f / 8.0), FL2FXCONST_SGL(-0.88829338134294f / 8.0) }, + { FL2FXCONST_SGL( 0.01995873238855f / 8.0), FL2FXCONST_SGL( 0.85223515096765f / 8.0) }, + { FL2FXCONST_SGL( 0.99930381973804f / 8.0), FL2FXCONST_SGL( 0.94578896296649f / 8.0) }, + { FL2FXCONST_SGL( 0.82907767600783f / 8.0), FL2FXCONST_SGL(-0.06323442598128f / 8.0) }, + { FL2FXCONST_SGL(-0.58660709669728f / 8.0), FL2FXCONST_SGL( 0.96840773806582f / 8.0) }, + { FL2FXCONST_SGL(-0.17573736667267f / 8.0), FL2FXCONST_SGL(-0.48166920859485f / 8.0) }, + { FL2FXCONST_SGL( 0.83434292401346f / 8.0), FL2FXCONST_SGL(-0.13023450646997f / 8.0) }, + { FL2FXCONST_SGL( 0.05946491307025f / 8.0), FL2FXCONST_SGL( 0.20511047074866f / 8.0) }, + { FL2FXCONST_SGL( 0.81505484574602f / 8.0), FL2FXCONST_SGL(-0.94685947861369f / 8.0) }, + { FL2FXCONST_SGL(-0.44976380954860f / 8.0), FL2FXCONST_SGL( 0.40894572671545f / 8.0) }, + { FL2FXCONST_SGL(-0.89746474625671f / 8.0), FL2FXCONST_SGL( 0.99846578838537f / 8.0) }, + { FL2FXCONST_SGL( 0.39677256130792f / 8.0), FL2FXCONST_SGL(-0.74854668609359f / 8.0) }, + { FL2FXCONST_SGL(-0.07588948563079f / 8.0), FL2FXCONST_SGL( 0.74096214084170f / 8.0) }, + { FL2FXCONST_SGL( 0.76343198951445f / 8.0), FL2FXCONST_SGL( 0.41746629422634f / 8.0) }, + { FL2FXCONST_SGL(-0.74490104699626f / 8.0), FL2FXCONST_SGL( 0.94725911744610f / 8.0) }, + { FL2FXCONST_SGL( 0.64880119792759f / 8.0), FL2FXCONST_SGL( 0.41336660830571f / 8.0) }, + { FL2FXCONST_SGL( 0.62319537462542f / 8.0), FL2FXCONST_SGL(-0.93098313552599f / 8.0) }, + { FL2FXCONST_SGL( 0.42215817594807f / 8.0), FL2FXCONST_SGL(-0.07712787385208f / 8.0) }, + { FL2FXCONST_SGL( 0.02704554141885f / 8.0), FL2FXCONST_SGL(-0.05417518053666f / 8.0) }, + { FL2FXCONST_SGL( 0.80001773566818f / 8.0), FL2FXCONST_SGL( 0.91542195141039f / 8.0) }, + { FL2FXCONST_SGL(-0.79351832348816f / 8.0), FL2FXCONST_SGL(-0.36208897989136f / 8.0) }, + { FL2FXCONST_SGL( 0.63872359151636f / 8.0), FL2FXCONST_SGL( 0.08128252493444f / 8.0) }, + { FL2FXCONST_SGL( 0.52890520960295f / 8.0), FL2FXCONST_SGL( 0.60048872455592f / 8.0) }, + { FL2FXCONST_SGL( 0.74238552914587f / 8.0), FL2FXCONST_SGL( 0.04491915291044f / 8.0) }, + { FL2FXCONST_SGL( 0.99096131449250f / 8.0), FL2FXCONST_SGL(-0.19451182854402f / 8.0) }, + { FL2FXCONST_SGL(-0.80412329643109f / 8.0), FL2FXCONST_SGL(-0.88513818199457f / 8.0) }, + { FL2FXCONST_SGL(-0.64612616129736f / 8.0), FL2FXCONST_SGL( 0.72198674804544f / 8.0) }, + { FL2FXCONST_SGL( 0.11657770663191f / 8.0), FL2FXCONST_SGL(-0.83662833815041f / 8.0) }, + { FL2FXCONST_SGL(-0.95053182488101f / 8.0), FL2FXCONST_SGL(-0.96939905138082f / 8.0) }, + { FL2FXCONST_SGL(-0.62228872928622f / 8.0), FL2FXCONST_SGL( 0.82767262846661f / 8.0) }, + { FL2FXCONST_SGL( 0.03004475787316f / 8.0), FL2FXCONST_SGL(-0.99738896333384f / 8.0) }, + { FL2FXCONST_SGL(-0.97987214341034f / 8.0), FL2FXCONST_SGL( 0.36526129686425f / 8.0) }, + { FL2FXCONST_SGL(-0.99986980746200f / 8.0), FL2FXCONST_SGL(-0.36021610299715f / 8.0) }, + { FL2FXCONST_SGL( 0.89110648599879f / 8.0), FL2FXCONST_SGL(-0.97894250343044f / 8.0) }, + { FL2FXCONST_SGL( 0.10407960510582f / 8.0), FL2FXCONST_SGL( 0.77357793811619f / 8.0) }, + { FL2FXCONST_SGL( 0.95964737821728f / 8.0), FL2FXCONST_SGL(-0.35435818285502f / 8.0) }, + { FL2FXCONST_SGL( 0.50843233159162f / 8.0), FL2FXCONST_SGL( 0.96107691266205f / 8.0) }, + { FL2FXCONST_SGL( 0.17006334670615f / 8.0), FL2FXCONST_SGL(-0.76854025314829f / 8.0) }, + { FL2FXCONST_SGL( 0.25872675063360f / 8.0), FL2FXCONST_SGL( 0.99893303933816f / 8.0) }, + { FL2FXCONST_SGL(-0.01115998681937f / 8.0), FL2FXCONST_SGL( 0.98496019742444f / 8.0) }, + { FL2FXCONST_SGL(-0.79598702973261f / 8.0), FL2FXCONST_SGL( 0.97138411318894f / 8.0) }, + { FL2FXCONST_SGL(-0.99264708948101f / 8.0), FL2FXCONST_SGL(-0.99542822402536f / 8.0) }, + { FL2FXCONST_SGL(-0.99829663752818f / 8.0), FL2FXCONST_SGL( 0.01877138824311f / 8.0) }, + { FL2FXCONST_SGL(-0.70801016548184f / 8.0), FL2FXCONST_SGL( 0.33680685948117f / 8.0) }, + { FL2FXCONST_SGL(-0.70467057786826f / 8.0), FL2FXCONST_SGL( 0.93272777501857f / 8.0) }, + { FL2FXCONST_SGL( 0.99846021905254f / 8.0), FL2FXCONST_SGL(-0.98725746254433f / 8.0) }, + { FL2FXCONST_SGL(-0.63364968534650f / 8.0), FL2FXCONST_SGL(-0.16473594423746f / 8.0) }, + { FL2FXCONST_SGL(-0.16258217500792f / 8.0), FL2FXCONST_SGL(-0.95939125400802f / 8.0) }, + { FL2FXCONST_SGL(-0.43645594360633f / 8.0), FL2FXCONST_SGL(-0.94805030113284f / 8.0) }, + { FL2FXCONST_SGL(-0.99848471702976f / 8.0), FL2FXCONST_SGL( 0.96245166923809f / 8.0) }, + { FL2FXCONST_SGL(-0.16796458968998f / 8.0), FL2FXCONST_SGL(-0.98987511890470f / 8.0) }, + { FL2FXCONST_SGL(-0.87979225745213f / 8.0), FL2FXCONST_SGL(-0.71725725041680f / 8.0) }, + { FL2FXCONST_SGL( 0.44183099021786f / 8.0), FL2FXCONST_SGL(-0.93568974498761f / 8.0) }, + { FL2FXCONST_SGL( 0.93310180125532f / 8.0), FL2FXCONST_SGL(-0.99913308068246f / 8.0) }, + { FL2FXCONST_SGL(-0.93941931782002f / 8.0), FL2FXCONST_SGL(-0.56409379640356f / 8.0) }, + { FL2FXCONST_SGL(-0.88590003188677f / 8.0), FL2FXCONST_SGL( 0.47624600491382f / 8.0) }, + { FL2FXCONST_SGL( 0.99971463703691f / 8.0), FL2FXCONST_SGL(-0.83889954253462f / 8.0) }, + { FL2FXCONST_SGL(-0.75376385639978f / 8.0), FL2FXCONST_SGL( 0.00814643438625f / 8.0) }, + { FL2FXCONST_SGL( 0.93887685615875f / 8.0), FL2FXCONST_SGL(-0.11284528204636f / 8.0) }, + { FL2FXCONST_SGL( 0.85126435782309f / 8.0), FL2FXCONST_SGL( 0.52349251543547f / 8.0) }, + { FL2FXCONST_SGL( 0.39701421446381f / 8.0), FL2FXCONST_SGL( 0.81779634174316f / 8.0) }, + { FL2FXCONST_SGL(-0.37024464187437f / 8.0), FL2FXCONST_SGL(-0.87071656222959f / 8.0) }, + { FL2FXCONST_SGL(-0.36024828242896f / 8.0), FL2FXCONST_SGL( 0.34655735648287f / 8.0) }, + { FL2FXCONST_SGL(-0.93388812549209f / 8.0), FL2FXCONST_SGL(-0.84476541096429f / 8.0) }, + { FL2FXCONST_SGL(-0.65298804552119f / 8.0), FL2FXCONST_SGL(-0.18439575450921f / 8.0) }, + { FL2FXCONST_SGL( 0.11960319006843f / 8.0), FL2FXCONST_SGL( 0.99899346780168f / 8.0) }, + { FL2FXCONST_SGL( 0.94292565553160f / 8.0), FL2FXCONST_SGL( 0.83163906518293f / 8.0) }, + { FL2FXCONST_SGL( 0.75081145286948f / 8.0), FL2FXCONST_SGL(-0.35533223142265f / 8.0) }, + { FL2FXCONST_SGL( 0.56721979748394f / 8.0), FL2FXCONST_SGL(-0.24076836414499f / 8.0) }, + { FL2FXCONST_SGL( 0.46857766746029f / 8.0), FL2FXCONST_SGL(-0.30140233457198f / 8.0) }, + { FL2FXCONST_SGL( 0.97312313923635f / 8.0), FL2FXCONST_SGL(-0.99548191630031f / 8.0) }, + { FL2FXCONST_SGL(-0.38299976567017f / 8.0), FL2FXCONST_SGL( 0.98516909715427f / 8.0) }, + { FL2FXCONST_SGL( 0.41025800019463f / 8.0), FL2FXCONST_SGL( 0.02116736935734f / 8.0) }, + { FL2FXCONST_SGL( 0.09638062008048f / 8.0), FL2FXCONST_SGL( 0.04411984381457f / 8.0) }, + { FL2FXCONST_SGL(-0.85283249275397f / 8.0), FL2FXCONST_SGL( 0.91475563922421f / 8.0) }, + { FL2FXCONST_SGL( 0.88866808958124f / 8.0), FL2FXCONST_SGL(-0.99735267083226f / 8.0) }, + { FL2FXCONST_SGL(-0.48202429536989f / 8.0), FL2FXCONST_SGL(-0.96805608884164f / 8.0) }, + { FL2FXCONST_SGL( 0.27572582416567f / 8.0), FL2FXCONST_SGL( 0.58634753335832f / 8.0) }, + { FL2FXCONST_SGL(-0.65889129659168f / 8.0), FL2FXCONST_SGL( 0.58835634138583f / 8.0) }, + { FL2FXCONST_SGL( 0.98838086953732f / 8.0), FL2FXCONST_SGL( 0.99994349600236f / 8.0) }, + { FL2FXCONST_SGL(-0.20651349620689f / 8.0), FL2FXCONST_SGL( 0.54593044066355f / 8.0) }, + { FL2FXCONST_SGL(-0.62126416356920f / 8.0), FL2FXCONST_SGL(-0.59893681700392f / 8.0) }, + { FL2FXCONST_SGL( 0.20320105410437f / 8.0), FL2FXCONST_SGL(-0.86879180355289f / 8.0) }, + { FL2FXCONST_SGL(-0.97790548600584f / 8.0), FL2FXCONST_SGL( 0.96290806999242f / 8.0) }, + { FL2FXCONST_SGL( 0.11112534735126f / 8.0), FL2FXCONST_SGL( 0.21484763313301f / 8.0) }, + { FL2FXCONST_SGL(-0.41368337314182f / 8.0), FL2FXCONST_SGL( 0.28216837680365f / 8.0) }, + { FL2FXCONST_SGL( 0.24133038992960f / 8.0), FL2FXCONST_SGL( 0.51294362630238f / 8.0) }, + { FL2FXCONST_SGL(-0.66393410674885f / 8.0), FL2FXCONST_SGL(-0.08249679629081f / 8.0) }, + { FL2FXCONST_SGL(-0.53697829178752f / 8.0), FL2FXCONST_SGL(-0.97649903936228f / 8.0) }, + { FL2FXCONST_SGL(-0.97224737889348f / 8.0), FL2FXCONST_SGL( 0.22081333579837f / 8.0) }, + { FL2FXCONST_SGL( 0.87392477144549f / 8.0), FL2FXCONST_SGL(-0.12796173740361f / 8.0) }, + { FL2FXCONST_SGL( 0.19050361015753f / 8.0), FL2FXCONST_SGL( 0.01602615387195f / 8.0) }, + { FL2FXCONST_SGL(-0.46353441212724f / 8.0), FL2FXCONST_SGL(-0.95249041539006f / 8.0) }, + { FL2FXCONST_SGL(-0.07064096339021f / 8.0), FL2FXCONST_SGL(-0.94479803205886f / 8.0) }, + { FL2FXCONST_SGL(-0.92444085484466f / 8.0), FL2FXCONST_SGL(-0.10457590187436f / 8.0) }, + { FL2FXCONST_SGL(-0.83822593578728f / 8.0), FL2FXCONST_SGL(-0.01695043208885f / 8.0) }, + { FL2FXCONST_SGL( 0.75214681811150f / 8.0), FL2FXCONST_SGL(-0.99955681042665f / 8.0) }, + { FL2FXCONST_SGL(-0.42102998829339f / 8.0), FL2FXCONST_SGL( 0.99720941999394f / 8.0) }, + { FL2FXCONST_SGL(-0.72094786237696f / 8.0), FL2FXCONST_SGL(-0.35008961934255f / 8.0) }, + { FL2FXCONST_SGL( 0.78843311019251f / 8.0), FL2FXCONST_SGL( 0.52851398958271f / 8.0) }, + { FL2FXCONST_SGL( 0.97394027897442f / 8.0), FL2FXCONST_SGL(-0.26695944086561f / 8.0) }, + { FL2FXCONST_SGL( 0.99206463477946f / 8.0), FL2FXCONST_SGL(-0.57010120849429f / 8.0) }, + { FL2FXCONST_SGL( 0.76789609461795f / 8.0), FL2FXCONST_SGL(-0.76519356730966f / 8.0) }, + { FL2FXCONST_SGL(-0.82002421836409f / 8.0), FL2FXCONST_SGL(-0.73530179553767f / 8.0) }, + { FL2FXCONST_SGL( 0.81924990025724f / 8.0), FL2FXCONST_SGL( 0.99698425250579f / 8.0) }, + { FL2FXCONST_SGL(-0.26719850873357f / 8.0), FL2FXCONST_SGL( 0.68903369776193f / 8.0) }, + { FL2FXCONST_SGL(-0.43311260380975f / 8.0), FL2FXCONST_SGL( 0.85321815947490f / 8.0) }, + { FL2FXCONST_SGL( 0.99194979673836f / 8.0), FL2FXCONST_SGL( 0.91876249766422f / 8.0) }, + { FL2FXCONST_SGL(-0.80692001248487f / 8.0), FL2FXCONST_SGL(-0.32627540663214f / 8.0) }, + { FL2FXCONST_SGL( 0.43080003649976f / 8.0), FL2FXCONST_SGL(-0.21919095636638f / 8.0) }, + { FL2FXCONST_SGL( 0.67709491937357f / 8.0), FL2FXCONST_SGL(-0.95478075822906f / 8.0) }, + { FL2FXCONST_SGL( 0.56151770568316f / 8.0), FL2FXCONST_SGL(-0.70693811747778f / 8.0) }, + { FL2FXCONST_SGL( 0.10831862810749f / 8.0), FL2FXCONST_SGL(-0.08628837174592f / 8.0) }, + { FL2FXCONST_SGL( 0.91229417540436f / 8.0), FL2FXCONST_SGL(-0.65987351408410f / 8.0) }, + { FL2FXCONST_SGL(-0.48972893932274f / 8.0), FL2FXCONST_SGL( 0.56289246362686f / 8.0) }, + { FL2FXCONST_SGL(-0.89033658689697f / 8.0), FL2FXCONST_SGL(-0.71656563987082f / 8.0) }, + { FL2FXCONST_SGL( 0.65269447475094f / 8.0), FL2FXCONST_SGL( 0.65916004833932f / 8.0) }, + { FL2FXCONST_SGL( 0.67439478141121f / 8.0), FL2FXCONST_SGL(-0.81684380846796f / 8.0) }, + { FL2FXCONST_SGL(-0.47770832416973f / 8.0), FL2FXCONST_SGL(-0.16789556203025f / 8.0) }, + { FL2FXCONST_SGL(-0.99715979260878f / 8.0), FL2FXCONST_SGL(-0.93565784007648f / 8.0) }, + { FL2FXCONST_SGL(-0.90889593602546f / 8.0), FL2FXCONST_SGL( 0.62034397054380f / 8.0) }, + { FL2FXCONST_SGL(-0.06618622548177f / 8.0), FL2FXCONST_SGL(-0.23812217221359f / 8.0) }, + { FL2FXCONST_SGL( 0.99430266919728f / 8.0), FL2FXCONST_SGL( 0.18812555317553f / 8.0) }, + { FL2FXCONST_SGL( 0.97686402381843f / 8.0), FL2FXCONST_SGL(-0.28664534366620f / 8.0) }, + { FL2FXCONST_SGL( 0.94813650221268f / 8.0), FL2FXCONST_SGL(-0.97506640027128f / 8.0) }, + { FL2FXCONST_SGL(-0.95434497492853f / 8.0), FL2FXCONST_SGL(-0.79607978501983f / 8.0) }, + { FL2FXCONST_SGL(-0.49104783137150f / 8.0), FL2FXCONST_SGL( 0.32895214359663f / 8.0) }, + { FL2FXCONST_SGL( 0.99881175120751f / 8.0), FL2FXCONST_SGL( 0.88993983831354f / 8.0) }, + { FL2FXCONST_SGL( 0.50449166760303f / 8.0), FL2FXCONST_SGL(-0.85995072408434f / 8.0) }, + { FL2FXCONST_SGL( 0.47162891065108f / 8.0), FL2FXCONST_SGL(-0.18680204049569f / 8.0) }, + { FL2FXCONST_SGL(-0.62081581361840f / 8.0), FL2FXCONST_SGL( 0.75000676218956f / 8.0) }, + { FL2FXCONST_SGL(-0.43867015250812f / 8.0), FL2FXCONST_SGL( 0.99998069244322f / 8.0) }, + { FL2FXCONST_SGL( 0.98630563232075f / 8.0), FL2FXCONST_SGL(-0.53578899600662f / 8.0) }, + { FL2FXCONST_SGL(-0.61510362277374f / 8.0), FL2FXCONST_SGL(-0.89515019899997f / 8.0) }, + { FL2FXCONST_SGL(-0.03841517601843f / 8.0), FL2FXCONST_SGL(-0.69888815681179f / 8.0) }, + { FL2FXCONST_SGL(-0.30102157304644f / 8.0), FL2FXCONST_SGL(-0.07667808922205f / 8.0) }, + { FL2FXCONST_SGL( 0.41881284182683f / 8.0), FL2FXCONST_SGL( 0.02188098922282f / 8.0) }, + { FL2FXCONST_SGL(-0.86135454941237f / 8.0), FL2FXCONST_SGL( 0.98947480909359f / 8.0) }, + { FL2FXCONST_SGL( 0.67226861393788f / 8.0), FL2FXCONST_SGL(-0.13494389011014f / 8.0) }, + { FL2FXCONST_SGL(-0.70737398842068f / 8.0), FL2FXCONST_SGL(-0.76547349325992f / 8.0) }, + { FL2FXCONST_SGL( 0.94044946687963f / 8.0), FL2FXCONST_SGL( 0.09026201157416f / 8.0) }, + { FL2FXCONST_SGL(-0.82386352534327f / 8.0), FL2FXCONST_SGL( 0.08924768823676f / 8.0) }, + { FL2FXCONST_SGL(-0.32070666698656f / 8.0), FL2FXCONST_SGL( 0.50143421908753f / 8.0) }, + { FL2FXCONST_SGL( 0.57593163224487f / 8.0), FL2FXCONST_SGL(-0.98966422921509f / 8.0) }, + { FL2FXCONST_SGL(-0.36326018419965f / 8.0), FL2FXCONST_SGL( 0.07440243123228f / 8.0) }, + { FL2FXCONST_SGL( 0.99979044674350f / 8.0), FL2FXCONST_SGL(-0.14130287347405f / 8.0) }, + { FL2FXCONST_SGL(-0.92366023326932f / 8.0), FL2FXCONST_SGL(-0.97979298068180f / 8.0) }, + { FL2FXCONST_SGL(-0.44607178518598f / 8.0), FL2FXCONST_SGL(-0.54233252016394f / 8.0) }, + { FL2FXCONST_SGL( 0.44226800932956f / 8.0), FL2FXCONST_SGL( 0.71326756742752f / 8.0) }, + { FL2FXCONST_SGL( 0.03671907158312f / 8.0), FL2FXCONST_SGL( 0.63606389366675f / 8.0) }, + { FL2FXCONST_SGL( 0.52175424682195f / 8.0), FL2FXCONST_SGL(-0.85396826735705f / 8.0) }, + { FL2FXCONST_SGL(-0.94701139690956f / 8.0), FL2FXCONST_SGL(-0.01826348194255f / 8.0) }, + { FL2FXCONST_SGL(-0.98759606946049f / 8.0), FL2FXCONST_SGL( 0.82288714303073f / 8.0) }, + { FL2FXCONST_SGL( 0.87434794743625f / 8.0), FL2FXCONST_SGL( 0.89399495655433f / 8.0) }, + { FL2FXCONST_SGL(-0.93412041758744f / 8.0), FL2FXCONST_SGL( 0.41374052024363f / 8.0) }, + { FL2FXCONST_SGL( 0.96063943315511f / 8.0), FL2FXCONST_SGL( 0.93116709541280f / 8.0) }, + { FL2FXCONST_SGL( 0.97534253457837f / 8.0), FL2FXCONST_SGL( 0.86150930812689f / 8.0) }, + { FL2FXCONST_SGL( 0.99642466504163f / 8.0), FL2FXCONST_SGL( 0.70190043427512f / 8.0) }, + { FL2FXCONST_SGL(-0.94705089665984f / 8.0), FL2FXCONST_SGL(-0.29580042814306f / 8.0) }, + { FL2FXCONST_SGL( 0.91599807087376f / 8.0), FL2FXCONST_SGL(-0.98147830385781f / 8.0) } +}; +//@} + +/* +static const FIXP_SGL harmonicPhase [2][4] = { + { 1.0, 0.0, -1.0, 0.0}, + { 0.0, 1.0, 0.0, -1.0} +}; +*/ + + +/* The CLDFB-80 is not linear phase (unsymmetric), but the exact + phase difference between adjacent bands, at exact positions + (in this case exactly in the frequency band centre), can of + course be determined anyway. While the standard symmetric QMF + bank has a phase difference of 0.5*pi, the CLDFB-80 + bank has the difference 0.2337*pi. */ +const FIXP_SGL harmonicPhaseX [2][4] = { + { FL2FXCONST_SGL( 7.423735494778151e-001), FL2FXCONST_SGL(-6.699862036159475e-001), + FL2FXCONST_SGL(-7.423735494778152e-001), FL2FXCONST_SGL( 6.699862036159474e-001) }, + { FL2FXCONST_SGL( 7.423735494778151e-001), FL2FXCONST_SGL( 6.699862036159476e-001), + FL2FXCONST_SGL(-7.423735494778151e-001), FL2FXCONST_SGL(-6.699862036159476e-001) } +}; + +/* tables for SBR and AAC LD */ +/* table for 8 time slot index */ +const int FDK_sbrDecoder_envelopeTable_8 [8][5] = { +/* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ +/* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ { 2, 0, 0, 1, -1 }, + /*[|-T-|-----]*/ { 2, 0, 0, 2, -1 }, + /*[--|T-|----]*/ { 3, 1, 1, 2, 4 }, + /*[---|T-|---]*/ { 3, 1, 1, 3, 5 }, + /*[----|T-|--]*/ { 3, 1, 1, 4, 6 }, + /*[-----|T--|]*/ { 2, 1, 1, 5, -1 }, + /*[------|T-|]*/ { 2, 1, 1, 6, -1 }, + /*[-------|T|]*/ { 2, 1, 1, 7, -1 }, +}; + +/* table for 15 time slot index */ +const int FDK_sbrDecoder_envelopeTable_15 [15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ { 2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ { 2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ { 3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ { 3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ { 3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ { 3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ { 3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ { 3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ { 3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ { 3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ { 2, 1, 1,10, -1, -1}, + /*[|-----------|T---|]*/ { 2, 1, 1,11, -1, -1}, + /*[|------------|T--|]*/ { 2, 1, 1,12, -1, -1}, + /*[|-------------|T-|]*/ { 2, 1, 1,13, -1, -1}, + /*[|--------------|T|]*/ { 2, 1, 1,14, -1, -1}, +}; + +/* table for 16 time slot index */ +const int FDK_sbrDecoder_envelopeTable_16 [16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ { 2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ { 2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ { 3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ { 3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ { 3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ { 3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ { 3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ { 3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ { 3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ { 3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ { 3, 1, 1,10, 14, -1}, + /*[|-----------|T----|]*/ { 2, 1, 1,11, -1, -1}, + /*[|------------|T---|]*/ { 2, 1, 1,12, -1, -1}, + /*[|-------------|T--|]*/ { 2, 1, 1,13, -1, -1}, + /*[|--------------|T-|]*/ { 2, 1, 1,14, -1, -1}, + /*[|---------------|T|]*/ { 2, 1, 1,15, -1, -1}, +}; + +/*! + \name FrameInfoDefaults + + Predefined envelope positions for the FIX-FIX case (static framing) +*/ +//@{ +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15 = { 0, 1, {0, 15, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 15, 0} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15 = { 0, 2, {0, 8, 15, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 15} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15 = { 0, 4, {0, 4, 8, 12, 15, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 15} }; +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15 = { 0, 8, {0, 2, 4, 6, 8, 10, 12, 14, 15}, {1, 1, 1, 1, 1, 1, 1, 1}, -1, 2, {0, 8, 15} }; +#endif + +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16 = { 0, 1, {0, 16, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 16, 0} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16 = { 0, 2, {0, 8, 16, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 16} }; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16 = { 0, 4, {0, 4, 8, 12, 16, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 16} }; + +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { 0, 8, {0, 2, 4, 6, 8, 10, 12, 14, 16}, {1, 1, 1, 1, 1, 1, 1, 1}, -1, 2, {0, 8, 16} }; +#endif + + +//@} + +/*! + \name SBR_HuffmanTables + + SBR Huffman Table Overview: \n + \n + o envelope level, 1.5 dB: \n + 1) sbr_huffBook_EnvLevel10T[120][2] \n + 2) sbr_huffBook_EnvLevel10F[120][2] \n + \n + o envelope balance, 1.5 dB: \n + 3) sbr_huffBook_EnvBalance10T[48][2] \n + 4) sbr_huffBook_EnvBalance10F[48][2] \n + \n + o envelope level, 3.0 dB: \n + 5) sbr_huffBook_EnvLevel11T[62][2] \n + 6) sbr_huffBook_EnvLevel11F[62][2] \n + \n + o envelope balance, 3.0 dB: \n + 7) sbr_huffBook_EnvBalance11T[24][2] \n + 8) sbr_huffBook_EnvBalance11F[24][2] \n + \n + o noise level, 3.0 dB: \n + 9) sbr_huffBook_NoiseLevel11T[62][2] \n + -) (sbr_huffBook_EnvLevel11F[62][2] is used for freq dir)\n + \n + o noise balance, 3.0 dB: \n + 10) sbr_huffBook_NoiseBalance11T[24][2]\n + -) (sbr_huffBook_EnvBalance11F[24][2] is used for freq dir)\n + \n + (1.5 dB is never used for noise) + +*/ +//@{ +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10T[120][2] = { + { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, + { 5, 6 }, { -62, -67 }, { 7, 8 }, { -61, -68 }, + { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, + { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, + { 17, 18 }, { -73, -56 }, { 19, 21 }, { -74, 20 }, + { -55, -75 }, { 22, 26 }, { 23, 24 }, { -54, -76 }, + { -77, 25 }, { -53, -78 }, { 27, 34 }, { 28, 29 }, + { -52, -79 }, { 30, 31 }, { -80, -51 }, { 32, 33 }, + { -83, -82 }, { -81, -50 }, { 35, 57 }, { 36, 40 }, + { 37, 38 }, { -88, -84 }, { -48, 39 }, { -90, -85 }, + { 41, 46 }, { 42, 43 }, { -49, -87 }, { 44, 45 }, + { -89, -86 }, {-124,-123 }, { 47, 50 }, { 48, 49 }, + {-122,-121 }, {-120,-119 }, { 51, 54 }, { 52, 53 }, + {-118,-117 }, {-116,-115 }, { 55, 56 }, {-114,-113 }, + {-112,-111 }, { 58, 89 }, { 59, 74 }, { 60, 67 }, + { 61, 64 }, { 62, 63 }, {-110,-109 }, {-108,-107 }, + { 65, 66 }, {-106,-105 }, {-104,-103 }, { 68, 71 }, + { 69, 70 }, {-102,-101 }, {-100, -99 }, { 72, 73 }, + { -98, -97 }, { -96, -95 }, { 75, 82 }, { 76, 79 }, + { 77, 78 }, { -94, -93 }, { -92, -91 }, { 80, 81 }, + { -47, -46 }, { -45, -44 }, { 83, 86 }, { 84, 85 }, + { -43, -42 }, { -41, -40 }, { 87, 88 }, { -39, -38 }, + { -37, -36 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, + { 93, 94 }, { -35, -34 }, { -33, -32 }, { 96, 97 }, + { -31, -30 }, { -29, -28 }, { 99, 102 }, { 100, 101 }, + { -27, -26 }, { -25, -24 }, { 103, 104 }, { -23, -22 }, + { -21, -20 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, + { -19, -18 }, { -17, -16 }, { 111, 112 }, { -15, -14 }, + { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, + { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10F[120][2] = { + { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 }, + { 5, 6 }, { -67, -62 }, { 7, 8 }, { -68, -61 }, + { 9, 10 }, { -69, -60 }, { 11, 13 }, { -70, 12 }, + { -59, -71 }, { 14, 16 }, { -58, 15 }, { -72, -57 }, + { 17, 19 }, { -73, 18 }, { -56, -74 }, { 20, 23 }, + { 21, 22 }, { -55, -75 }, { -54, -53 }, { 24, 27 }, + { 25, 26 }, { -76, -52 }, { -77, -51 }, { 28, 31 }, + { 29, 30 }, { -50, -78 }, { -79, -49 }, { 32, 36 }, + { 33, 34 }, { -48, -47 }, { -80, 35 }, { -81, -82 }, + { 37, 47 }, { 38, 41 }, { 39, 40 }, { -83, -46 }, + { -45, -84 }, { 42, 44 }, { -85, 43 }, { -44, -43 }, + { 45, 46 }, { -88, -87 }, { -86, -90 }, { 48, 66 }, + { 49, 56 }, { 50, 53 }, { 51, 52 }, { -92, -42 }, + { -41, -39 }, { 54, 55 }, {-105, -89 }, { -38, -37 }, + { 57, 60 }, { 58, 59 }, { -94, -91 }, { -40, -36 }, + { 61, 63 }, { -20, 62 }, {-115,-110 }, { 64, 65 }, + {-108,-107 }, {-101, -97 }, { 67, 89 }, { 68, 75 }, + { 69, 72 }, { 70, 71 }, { -95, -93 }, { -34, -27 }, + { 73, 74 }, { -22, -17 }, { -16,-124 }, { 76, 82 }, + { 77, 79 }, {-123, 78 }, {-122,-121 }, { 80, 81 }, + {-120,-119 }, {-118,-117 }, { 83, 86 }, { 84, 85 }, + {-116,-114 }, {-113,-112 }, { 87, 88 }, {-111,-109 }, + {-106,-104 }, { 90, 105 }, { 91, 98 }, { 92, 95 }, + { 93, 94 }, {-103,-102 }, {-100, -99 }, { 96, 97 }, + { -98, -96 }, { -35, -33 }, { 99, 102 }, { 100, 101 }, + { -32, -31 }, { -30, -29 }, { 103, 104 }, { -28, -26 }, + { -25, -24 }, { 106, 113 }, { 107, 110 }, { 108, 109 }, + { -23, -21 }, { -19, -18 }, { 111, 112 }, { -15, -14 }, + { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 }, + { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10T[48][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, + { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, + { -68, 9 }, { 10, 11 }, { -69, -59 }, { 12, 13 }, + { -70, -58 }, { 14, 28 }, { 15, 21 }, { 16, 18 }, + { -57, 17 }, { -71, -56 }, { 19, 20 }, { -88, -87 }, + { -86, -85 }, { 22, 25 }, { 23, 24 }, { -84, -83 }, + { -82, -81 }, { 26, 27 }, { -80, -79 }, { -78, -77 }, + { 29, 36 }, { 30, 33 }, { 31, 32 }, { -76, -75 }, + { -74, -73 }, { 34, 35 }, { -72, -55 }, { -54, -53 }, + { 37, 41 }, { 38, 39 }, { -52, -51 }, { -50, 40 }, + { -49, -48 }, { 42, 45 }, { 43, 44 }, { -47, -46 }, + { -45, -44 }, { 46, 47 }, { -43, -42 }, { -41, -40 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10F[48][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 11 }, { -69, -59 }, { -70, 12 }, + { -58, 13 }, { 14, 17 }, { -71, 15 }, { -57, 16 }, + { -56, -73 }, { 18, 32 }, { 19, 25 }, { 20, 22 }, + { -72, 21 }, { -88, -87 }, { 23, 24 }, { -86, -85 }, + { -84, -83 }, { 26, 29 }, { 27, 28 }, { -82, -81 }, + { -80, -79 }, { 30, 31 }, { -78, -77 }, { -76, -75 }, + { 33, 40 }, { 34, 37 }, { 35, 36 }, { -74, -55 }, + { -54, -53 }, { 38, 39 }, { -52, -51 }, { -50, -49 }, + { 41, 44 }, { 42, 43 }, { -48, -47 }, { -46, -45 }, + { 45, 46 }, { -44, -43 }, { -42, 47 }, { -41, -40 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11T[62][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 11 }, { -69, -59 }, { 12, 14 }, + { -70, 13 }, { -71, -58 }, { 15, 18 }, { 16, 17 }, + { -72, -57 }, { -73, -74 }, { 19, 22 }, { -56, 20 }, + { -55, 21 }, { -54, -77 }, { 23, 31 }, { 24, 25 }, + { -75, -76 }, { 26, 27 }, { -78, -53 }, { 28, 29 }, + { -52, -95 }, { -94, 30 }, { -93, -92 }, { 32, 47 }, + { 33, 40 }, { 34, 37 }, { 35, 36 }, { -91, -90 }, + { -89, -88 }, { 38, 39 }, { -87, -86 }, { -85, -84 }, + { 41, 44 }, { 42, 43 }, { -83, -82 }, { -81, -80 }, + { 45, 46 }, { -79, -51 }, { -50, -49 }, { 48, 55 }, + { 49, 52 }, { 50, 51 }, { -48, -47 }, { -46, -45 }, + { 53, 54 }, { -44, -43 }, { -42, -41 }, { 56, 59 }, + { 57, 58 }, { -40, -39 }, { -38, -37 }, { 60, 61 }, + { -36, -35 }, { -34, -33 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11F[62][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, + { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 }, + { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 }, + { 17, 19 }, { -56, 18 }, { -55, -73 }, { 20, 24 }, + { 21, 22 }, { -74, -54 }, { -53, 23 }, { -75, -76 }, + { 25, 30 }, { 26, 27 }, { -52, -51 }, { 28, 29 }, + { -77, -79 }, { -50, -49 }, { 31, 39 }, { 32, 35 }, + { 33, 34 }, { -78, -46 }, { -82, -88 }, { 36, 37 }, + { -83, -48 }, { -47, 38 }, { -86, -85 }, { 40, 47 }, + { 41, 44 }, { 42, 43 }, { -80, -44 }, { -43, -42 }, + { 45, 46 }, { -39, -87 }, { -84, -40 }, { 48, 55 }, + { 49, 52 }, { 50, 51 }, { -95, -94 }, { -93, -92 }, + { 53, 54 }, { -91, -90 }, { -89, -81 }, { 56, 59 }, + { 57, 58 }, { -45, -41 }, { -38, -37 }, { 60, 61 }, + { -36, -35 }, { -34, -33 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11T[24][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 16 }, { 11, 13 }, { -69, 12 }, + { -76, -75 }, { 14, 15 }, { -74, -73 }, { -72, -71 }, + { 17, 20 }, { 18, 19 }, { -70, -59 }, { -58, -57 }, + { 21, 22 }, { -56, -55 }, { -54, 23 }, { -53, -52 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11F[24][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 }, + { -60, 9 }, { 10, 13 }, { -69, 11 }, { -59, 12 }, + { -58, -76 }, { 14, 17 }, { 15, 16 }, { -75, -74 }, + { -73, -72 }, { 18, 21 }, { 19, 20 }, { -71, -70 }, + { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T[62][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 }, + { 9, 30 }, { 10, 15 }, { -60, 11 }, { -69, 12 }, + { 13, 14 }, { -59, -53 }, { -95, -94 }, { 16, 23 }, + { 17, 20 }, { 18, 19 }, { -93, -92 }, { -91, -90 }, + { 21, 22 }, { -89, -88 }, { -87, -86 }, { 24, 27 }, + { 25, 26 }, { -85, -84 }, { -83, -82 }, { 28, 29 }, + { -81, -80 }, { -79, -78 }, { 31, 46 }, { 32, 39 }, + { 33, 36 }, { 34, 35 }, { -77, -76 }, { -75, -74 }, + { 37, 38 }, { -73, -72 }, { -71, -70 }, { 40, 43 }, + { 41, 42 }, { -58, -57 }, { -56, -55 }, { 44, 45 }, + { -54, -52 }, { -51, -50 }, { 47, 54 }, { 48, 51 }, + { 49, 50 }, { -49, -48 }, { -47, -46 }, { 52, 53 }, + { -45, -44 }, { -43, -42 }, { 55, 58 }, { 56, 57 }, + { -41, -40 }, { -39, -38 }, { 59, 60 }, { -37, -36 }, + { -35, 61 }, { -34, -33 } +}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T[24][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { 4, 9 }, + { -66, 5 }, { -62, 6 }, { 7, 8 }, { -76, -75 }, + { -74, -73 }, { 10, 17 }, { 11, 14 }, { 12, 13 }, + { -72, -71 }, { -70, -69 }, { 15, 16 }, { -68, -67 }, + { -61, -60 }, { 18, 21 }, { 19, 20 }, { -59, -58 }, + { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 } +}; +//@} + + + + +/*! + \name parametric stereo + \brief constants used by the parametric stereo part of the decoder + +*/ + + +/* constants used in psbitdec.cpp */ + +/* FIX_BORDER can have 0, 1, 2, 4 envelopes */ +const UCHAR FDK_sbrDecoder_aFixNoEnvDecode[4] = {0, 1, 2, 4}; + + +/* IID & ICC Huffman codebooks */ +const SCHAR aBookPsIidTimeDecode[28][2] = { + { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 }, + { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 }, + { -60, 9 }, { -69, 10 }, { -59, 11 }, { -70, 12 }, + { -58, 13 }, { -57, 14 }, { -71, 15 }, { 16, 17 }, + { -56, -72 }, { 18, 21 }, { 19, 20 }, { -55, -78 }, + { -77, -76 }, { 22, 25 }, { 23, 24 }, { -75, -74 }, + { -73, -54 }, { 26, 27 }, { -53, -52 }, { -51, -50 } +}; + +const SCHAR aBookPsIidFreqDecode[28][2] = { + { -64, 1 }, { 2, 3 }, { -63, -65 }, { 4, 5 }, + { -62, -66 }, { 6, 7 }, { -61, -67 }, { 8, 9 }, + { -68, -60 }, { -59, 10 }, { -69, 11 }, { -58, 12 }, + { -70, 13 }, { -71, 14 }, { -57, 15 }, { 16, 17 }, + { -56, -72 }, { 18, 19 }, { -55, -54 }, { 20, 21 }, + { -73, -53 }, { 22, 24 }, { -74, 23 }, { -75, -78 }, + { 25, 26 }, { -77, -76 }, { -52, 27 }, { -51, -50 } +}; + +const SCHAR aBookPsIccTimeDecode[14][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, + { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, + { -68, 9 }, { -59, 10 }, { -69, 11 }, { -58, 12 }, + { -70, 13 }, { -71, -57 } +}; + +const SCHAR aBookPsIccFreqDecode[14][2] = { + { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 }, + { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 }, + { -59, 9 }, { -68, 10 }, { -58, 11 }, { -69, 12 }, + { -57, 13 }, { -70, -71 } +}; + +/* IID-fine Huffman codebooks */ + +const SCHAR aBookPsIidFineTimeDecode[60][2] = { + { 1, -64 }, { -63, 2 }, { 3, -65 }, { 4, 59 }, + { 5, 7 }, { 6, -67 }, { -68, -60 }, { -61, 8 }, + { 9, 11 }, { -59, 10 }, { -70, -58 }, { 12, 41 }, + { 13, 20 }, { 14, -71 }, { -55, 15 }, { -53, 16 }, + { 17, -77 }, { 18, 19 }, { -85, -84 }, { -46, -45 }, + { -57, 21 }, { 22, 40 }, { 23, 29 }, { -51, 24 }, + { 25, 26 }, { -83, -82 }, { 27, 28 }, { -90, -38 }, + { -92, -91 }, { 30, 37 }, { 31, 34 }, { 32, 33 }, + { -35, -34 }, { -37, -36 }, { 35, 36 }, { -94, -93 }, + { -89, -39 }, { 38, -79 }, { 39, -81 }, { -88, -40 }, + { -74, -54 }, { 42, -69 }, { 43, 44 }, { -72, -56 }, + { 45, 52 }, { 46, 50 }, { 47, -76 }, { -49, 48 }, + { -47, 49 }, { -87, -41 }, { -52, 51 }, { -78, -50 }, + { 53, -73 }, { 54, -75 }, { 55, 57 }, { 56, -80 }, + { -86, -42 }, { -48, 58 }, { -44, -43 }, { -66, -62 } +}; + + +const SCHAR aBookPsIidFineFreqDecode[60][2] = { + { 1, -64 }, { 2, 4 }, { 3, -65 }, { -66, -62 }, + { -63, 5 }, { 6, 7 }, { -67, -61 }, { 8, 9 }, + { -68, -60 }, { 10, 11 }, { -69, -59 }, { 12, 13 }, + { -70, -58 }, { 14, 18 }, { -57, 15 }, { 16, -72 }, + { -54, 17 }, { -75, -53 }, { 19, 37 }, { -56, 20 }, + { 21, -73 }, { 22, 29 }, { 23, -76 }, { 24, -78 }, + { 25, 28 }, { 26, 27 }, { -85, -43 }, { -83, -45 }, + { -81, -47 }, { -52, 30 }, { -50, 31 }, { 32, -79 }, + { 33, 34 }, { -82, -46 }, { 35, 36 }, { -90, -89 }, + { -92, -91 }, { 38, -71 }, { -55, 39 }, { 40, -74 }, + { 41, 50 }, { 42, -77 }, { -49, 43 }, { 44, 47 }, + { 45, 46 }, { -86, -42 }, { -88, -87 }, { 48, 49 }, + { -39, -38 }, { -41, -40 }, { -51, 51 }, { 52, 59 }, + { 53, 56 }, { 54, 55 }, { -35, -34 }, { -37, -36 }, + { 57, 58 }, { -94, -93 }, { -84, -44 }, { -80, -48 } +}; + +/* constants used in psdec.cpp */ + +const FIXP_DBL decayScaleFactTable[64] = { + + FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), FL2FXCONST_DBL(1.000000), + FL2FXCONST_DBL(0.950000), FL2FXCONST_DBL(0.900000), FL2FXCONST_DBL(0.850000), FL2FXCONST_DBL(0.800000), + FL2FXCONST_DBL(0.750000), FL2FXCONST_DBL(0.700000), FL2FXCONST_DBL(0.650000), FL2FXCONST_DBL(0.600000), + FL2FXCONST_DBL(0.550000), FL2FXCONST_DBL(0.500000), FL2FXCONST_DBL(0.450000), FL2FXCONST_DBL(0.400000), + FL2FXCONST_DBL(0.350000), FL2FXCONST_DBL(0.300000), FL2FXCONST_DBL(0.250000), FL2FXCONST_DBL(0.200000), + FL2FXCONST_DBL(0.150000), FL2FXCONST_DBL(0.100000), FL2FXCONST_DBL(0.050000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), + FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000), FL2FXCONST_DBL(0.000000) }; + +/* the values of the following 3 tables are shiftet right by 1 ! */ +const FIXP_DBL ScaleFactors[NO_IID_LEVELS] = { + + 0x5a5ded00, 0x59cd0400, 0x58c29680, 0x564c2e80, 0x52a3d480, + 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x24e9f640, 0x1b4a2940, 0x11b5c0a0, 0x0b4e2540, 0x0514ea90 +}; + +const FIXP_DBL ScaleFactorsFine[NO_IID_LEVELS_FINE] = { + + 0x5a825c00, 0x5a821c00, 0x5a815100, 0x5a7ed000, 0x5a76e600, + 0x5a5ded00, 0x5a39b880, 0x59f1fd00, 0x5964d680, 0x5852ca00, + 0x564c2e80, 0x54174480, 0x50ea7500, 0x4c8be080, 0x46df3080, + 0x40000000, 0x384ba5c0, 0x304c2980, 0x288dd240, 0x217a2900, + 0x1b4a2940, 0x13c5ece0, 0x0e2b0090, 0x0a178ef0, 0x072ab798, + 0x0514ea90, 0x02dc5944, 0x019bf87c, 0x00e7b173, 0x00824b8b, + 0x00494568 +}; +const FIXP_DBL Alphas[NO_ICC_LEVELS] = { + + 0x00000000, 0x0b6b5be0, 0x12485f80, 0x1da2fa40, + 0x2637ebc0, 0x3243f6c0, 0x466b7480, 0x6487ed80 +}; + +#if defined(ARCH_PREFER_MULT_32x16) +#define FIXP_PS FIXP_SGL +#define FXP_CAST(a) FX_DBL2FX_SGL((FIXP_DBL)a) +#define FL2FXCONST_PS FL2FXCONST_SGL +#else +#define FIXP_PS FIXP_DBL +#define FXP_CAST(x) ((FIXP_DBL)(x)) +#define FL2FXCONST_PS FL2FXCONST_DBL +#endif + +const FIXP_PS aAllpassLinkDecaySer[NO_SERIAL_ALLPASS_LINKS] = { +FXP_CAST(0x53625b00), FXP_CAST(0x4848af00), FXP_CAST(0x3ea94d00) }; + +const FIXP_PS aaFractDelayPhaseFactorReQmf[NO_QMF_CHANNELS] = { +FXP_CAST(0x68b92180), FXP_CAST(0xde396900), FXP_CAST(0x80650380), FXP_CAST(0xcb537e40), FXP_CAST(0x5beb8f00), FXP_CAST(0x72f29200), FXP_CAST(0xf1f43c50), FXP_CAST(0x83896280), +FXP_CAST(0xb9b99c00), FXP_CAST(0x4cda8f00), FXP_CAST(0x7a576e00), FXP_CAST(0x060799e0), FXP_CAST(0x89be5280), FXP_CAST(0xa9dab600), FXP_CAST(0x3be51b00), FXP_CAST(0x7eb91900), +FXP_CAST(0x19f4f540), FXP_CAST(0x92dcb380), FXP_CAST(0x9c1ad700), FXP_CAST(0x29761940), FXP_CAST(0x7ffbf500), FXP_CAST(0x2d3eb180), FXP_CAST(0x9eab0a00), FXP_CAST(0x90d0aa80), +FXP_CAST(0x1601bcc0), FXP_CAST(0x7e180e80), FXP_CAST(0x3f6b3940), FXP_CAST(0xacdeeb00), FXP_CAST(0x88435b00), FXP_CAST(0x0202a768), FXP_CAST(0x79194f80), FXP_CAST(0x5007fd00), +FXP_CAST(0xbd1ecf00), FXP_CAST(0x82a8d100), FXP_CAST(0xedf6e5e0), FXP_CAST(0x711f3500), FXP_CAST(0x5eac4480), FXP_CAST(0xcf0447c0), FXP_CAST(0x80245f80), FXP_CAST(0xda5cd4c0), +FXP_CAST(0x665c0800), FXP_CAST(0x6afbc500), FXP_CAST(0xe21e85e0), FXP_CAST(0x80c5e500), FXP_CAST(0xc7b003c0), FXP_CAST(0x59139f80), FXP_CAST(0x74a8e400), FXP_CAST(0xf5f51f40), +FXP_CAST(0x84896680), FXP_CAST(0xb6662b00), FXP_CAST(0x4999b600), FXP_CAST(0x7b76a300), FXP_CAST(0x0a0b0650), FXP_CAST(0x8b572b80), FXP_CAST(0xa6ec4580), FXP_CAST(0x384fda80), +FXP_CAST(0x7f3a1f00), FXP_CAST(0x1de19ec0), FXP_CAST(0x95045000), FXP_CAST(0x99a3e180), FXP_CAST(0x25a30740), FXP_CAST(0x7fdb9e80), FXP_CAST(0x30fbdb00), FXP_CAST(0xa153d500) }; + +const FIXP_PS aaFractDelayPhaseFactorImQmf[NO_QMF_CHANNELS] = { +FXP_CAST(0xb6663a80), FXP_CAST(0x84896200), FXP_CAST(0xf5f50c70), FXP_CAST(0x74a8dc80), FXP_CAST(0x5913ad00), FXP_CAST(0xc7b01480), FXP_CAST(0x80c5e300), FXP_CAST(0xe21e73a0), +FXP_CAST(0x6afbba80), FXP_CAST(0x665c1380), FXP_CAST(0xda5ce6c0), FXP_CAST(0x80246080), FXP_CAST(0xcf043640), FXP_CAST(0x5eac3800), FXP_CAST(0x711f3e00), FXP_CAST(0xedf6f8a0), +FXP_CAST(0x82a8d500), FXP_CAST(0xbd1ebe80), FXP_CAST(0x5007ee00), FXP_CAST(0x79195580), FXP_CAST(0x0202ba40), FXP_CAST(0x88436180), FXP_CAST(0xacdedc80), FXP_CAST(0x3f6b28c0), +FXP_CAST(0x7e181180), FXP_CAST(0x1601cf40), FXP_CAST(0x90d0b380), FXP_CAST(0x9eaafd80), FXP_CAST(0x2d3e9fc0), FXP_CAST(0x7ffbf580), FXP_CAST(0x29762b00), FXP_CAST(0x9c1ae280), +FXP_CAST(0x92dca980), FXP_CAST(0x19f4e2c0), FXP_CAST(0x7eb91680), FXP_CAST(0x3be52b80), FXP_CAST(0xa9dac400), FXP_CAST(0x89be4b80), FXP_CAST(0x06078710), FXP_CAST(0x7a576880), +FXP_CAST(0x4cda9e00), FXP_CAST(0xb9b9ac00), FXP_CAST(0x83895e00), FXP_CAST(0xf1f42990), FXP_CAST(0x72f28a00), FXP_CAST(0x5beb9c00), FXP_CAST(0xcb538f40), FXP_CAST(0x80650200), +FXP_CAST(0xde3956c0), FXP_CAST(0x68b91680), FXP_CAST(0x68b92c00), FXP_CAST(0xde397b40), FXP_CAST(0x80650500), FXP_CAST(0xcb536d00), FXP_CAST(0x5beb8180), FXP_CAST(0x72f29a80), +FXP_CAST(0xf1f44f10), FXP_CAST(0x83896700), FXP_CAST(0xb9b98c80), FXP_CAST(0x4cda8000), FXP_CAST(0x7a577380), FXP_CAST(0x0607acb8), FXP_CAST(0x89be5a00), FXP_CAST(0xa9daa800) }; + +const FIXP_PS aaFractDelayPhaseFactorReSubQmf20[NO_SUB_QMF_CHANNELS] = { +FXP_CAST(0x7e807380), FXP_CAST(0x72b9bb00), FXP_CAST(0x5c44ee80), FXP_CAST(0x3d3938c0), FXP_CAST(0x80000000), FXP_CAST(0x80000000), +FXP_CAST(0x72b9bb00), FXP_CAST(0x7e807380), FXP_CAST(0xba914700), FXP_CAST(0x050677b0), FXP_CAST(0x895cc380), FXP_CAST(0x834e4900) }; + +const FIXP_PS aaFractDelayPhaseFactorImSubQmf20[NO_SUB_QMF_CHANNELS] = { +FXP_CAST(0xec791720), FXP_CAST(0xc73ca080), FXP_CAST(0xa748ea00), FXP_CAST(0x8f976980), FXP_CAST(0x00000000), FXP_CAST(0x00000000), +FXP_CAST(0x38c35f80), FXP_CAST(0x1386e8e0), FXP_CAST(0x9477d000), FXP_CAST(0x80194380), FXP_CAST(0xcff26140), FXP_CAST(0x1ce70d40) }; + +const FIXP_PS aaFractDelayPhaseFactorSerReQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { +{FXP_CAST(0x63e52480), FXP_CAST(0x30fbc540), FXP_CAST(0x6d73af00)}, {FXP_CAST(0xc7b01280), FXP_CAST(0x89be5100), FXP_CAST(0xf7c31cb0)}, {FXP_CAST(0x83896200), FXP_CAST(0x7641af00), FXP_CAST(0x8aee2700)}, +{FXP_CAST(0x0202b330), FXP_CAST(0xcf043ac0), FXP_CAST(0x9bfab500)}, {FXP_CAST(0x7d572c80), FXP_CAST(0xcf043ac0), FXP_CAST(0x1893b960)}, {FXP_CAST(0x34ac7fc0), FXP_CAST(0x7641af00), FXP_CAST(0x7abf7980)}, +{FXP_CAST(0x99a3ee00), FXP_CAST(0x89be5100), FXP_CAST(0x58eead80)}, {FXP_CAST(0x9eab0580), FXP_CAST(0x30fbc540), FXP_CAST(0xd77dae40)}, {FXP_CAST(0x3be52140), FXP_CAST(0x30fbc540), FXP_CAST(0x819b8500)}, +{FXP_CAST(0x7b769d80), FXP_CAST(0x89be5100), FXP_CAST(0xb3a12280)}, {FXP_CAST(0xf9f86878), FXP_CAST(0x7641af00), FXP_CAST(0x37c519c0)}, {FXP_CAST(0x81e7ef80), FXP_CAST(0xcf043ac0), FXP_CAST(0x7ff16880)}, +{FXP_CAST(0xcf043cc0), FXP_CAST(0xcf043ac0), FXP_CAST(0x3e8b2340)}, {FXP_CAST(0x68b92280), FXP_CAST(0x7641af00), FXP_CAST(0xb9e4a900)}, {FXP_CAST(0x5eac3980), FXP_CAST(0x89be5100), FXP_CAST(0x80a05200)}, +{FXP_CAST(0xc094cd00), FXP_CAST(0x30fbc540), FXP_CAST(0xd051dc80)}, {FXP_CAST(0x85a89400), FXP_CAST(0x30fbc540), FXP_CAST(0x53483b00)}, {FXP_CAST(0x0a0af5e0), FXP_CAST(0x89be5100), FXP_CAST(0x7cb1b680)}, +{FXP_CAST(0x7eb91900), FXP_CAST(0x7641af00), FXP_CAST(0x2006e8c0)}, {FXP_CAST(0x2d3ea680), FXP_CAST(0xcf043ac0), FXP_CAST(0xa0ec1c00)}, {FXP_CAST(0x95044180), FXP_CAST(0xcf043ac0), FXP_CAST(0x880d2180)}, +{FXP_CAST(0xa4147300), FXP_CAST(0x7641af00), FXP_CAST(0xf0282870)}, {FXP_CAST(0x42e13f80), FXP_CAST(0x89be5100), FXP_CAST(0x694c4a00)}, {FXP_CAST(0x79195200), FXP_CAST(0x30fbc540), FXP_CAST(0x71374780)}, +{FXP_CAST(0xf1f43550), FXP_CAST(0x30fbc540), FXP_CAST(0xff6593ea)}, {FXP_CAST(0x80c5e280), FXP_CAST(0x89be5100), FXP_CAST(0x8e39ec00)}, {FXP_CAST(0xd689e480), FXP_CAST(0x7641af00), FXP_CAST(0x97648100)}, +{FXP_CAST(0x6d235300), FXP_CAST(0xcf043ac0), FXP_CAST(0x110a20c0)}, {FXP_CAST(0x5913a800), FXP_CAST(0xcf043ac0), FXP_CAST(0x785d4f80)}, {FXP_CAST(0xb9b99a00), FXP_CAST(0x7641af00), FXP_CAST(0x5e440880)}, +{FXP_CAST(0x88436100), FXP_CAST(0x89be5100), FXP_CAST(0xdece7000)}, {FXP_CAST(0x12091320), FXP_CAST(0x30fbc540), FXP_CAST(0x8309f800)}, {FXP_CAST(0x7f9afd00), FXP_CAST(0x30fbc540), FXP_CAST(0xada33f00)}, +{FXP_CAST(0x25a31700), FXP_CAST(0x89be5100), FXP_CAST(0x30cc3600)}, {FXP_CAST(0x90d0ab80), FXP_CAST(0x7641af00), FXP_CAST(0x7f7cbe80)}, {FXP_CAST(0xa9dabf00), FXP_CAST(0xcf043ac0), FXP_CAST(0x45182580)}, +{FXP_CAST(0x4999cb80), FXP_CAST(0xcf043ac0), FXP_CAST(0xc0681c80)}, {FXP_CAST(0x7641ac80), FXP_CAST(0x7641af00), FXP_CAST(0x80194380)}, {FXP_CAST(0xe9fe3300), FXP_CAST(0x89be5100), FXP_CAST(0xc95184c0)}, +{FXP_CAST(0x80246000), FXP_CAST(0x30fbc540), FXP_CAST(0x4d55d800)}, {FXP_CAST(0xde396fc0), FXP_CAST(0x30fbc540), FXP_CAST(0x7e324000)}, {FXP_CAST(0x711f3f00), FXP_CAST(0x89be5100), FXP_CAST(0x275ce480)}, +{FXP_CAST(0x53211700), FXP_CAST(0x7641af00), FXP_CAST(0xa6343580)}, {FXP_CAST(0xb3256780), FXP_CAST(0xcf043ac0), FXP_CAST(0x85997b80)}, {FXP_CAST(0x8b572680), FXP_CAST(0xcf043ac0), FXP_CAST(0xe89ba660)}, +{FXP_CAST(0x19f4f780), FXP_CAST(0x7641af00), FXP_CAST(0x64c4e100)}, {FXP_CAST(0x7ffbf580), FXP_CAST(0x89be5100), FXP_CAST(0x7493a380)}, {FXP_CAST(0x1de18100), FXP_CAST(0x30fbc540), FXP_CAST(0x070897f0)}, +{FXP_CAST(0x8d0d6a80), FXP_CAST(0x30fbc540), FXP_CAST(0x91ed6f00)}, {FXP_CAST(0xaff81380), FXP_CAST(0x89be5100), FXP_CAST(0x932db000)}, {FXP_CAST(0x5007fb00), FXP_CAST(0x7641af00), FXP_CAST(0x0970feb0)}, +{FXP_CAST(0x72f28d00), FXP_CAST(0xcf043ac0), FXP_CAST(0x758d6500)}, {FXP_CAST(0xe21e6cc0), FXP_CAST(0xcf043ac0), FXP_CAST(0x63436f80)}, {FXP_CAST(0x80040b00), FXP_CAST(0x7641af00), FXP_CAST(0xe63d7600)}, +{FXP_CAST(0xe60b1ae0), FXP_CAST(0x89be5100), FXP_CAST(0x84ea5c80)}, {FXP_CAST(0x74a8e100), FXP_CAST(0x30fbc540), FXP_CAST(0xa7f07500)}, {FXP_CAST(0x4cda8980), FXP_CAST(0x30fbc540), FXP_CAST(0x29a6d340)}, +{FXP_CAST(0xacdeda80), FXP_CAST(0x89be5100), FXP_CAST(0x7e93d600)}, {FXP_CAST(0x8ee0c980), FXP_CAST(0x7641af00), FXP_CAST(0x4b662680)}, {FXP_CAST(0x21c6a280), FXP_CAST(0xcf043ac0), FXP_CAST(0xc7258c80)}, +{FXP_CAST(0x7fdb9f00), FXP_CAST(0xcf043ac0), FXP_CAST(0x8006d500)}, {FXP_CAST(0x1601ba60), FXP_CAST(0x7641af00), FXP_CAST(0xc2830940)}, {FXP_CAST(0x89be4c80), FXP_CAST(0x89be5100), FXP_CAST(0x471cf100)}, +{FXP_CAST(0xb6664400), FXP_CAST(0x30fbc540), FXP_CAST(0x7f3fb800)}}; + +const FIXP_PS aaFractDelayPhaseFactorSerImQmf[NO_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { +{FXP_CAST(0xaff80c80), FXP_CAST(0x89be5100), FXP_CAST(0xbda29e00)}, {FXP_CAST(0x8d0d6f00), FXP_CAST(0x30fbc540), FXP_CAST(0x8043ee80)}, {FXP_CAST(0x1de18a20), FXP_CAST(0x30fbc540), FXP_CAST(0xcc3e7840)}, +{FXP_CAST(0x7ffbf500), FXP_CAST(0x89be5100), FXP_CAST(0x4fdfc180)}, {FXP_CAST(0x19f4ee40), FXP_CAST(0x7641af00), FXP_CAST(0x7d9e4c00)}, {FXP_CAST(0x8b572300), FXP_CAST(0xcf043ac0), FXP_CAST(0x244a2940)}, +{FXP_CAST(0xb3256f00), FXP_CAST(0xcf043ac0), FXP_CAST(0xa3f0a500)}, {FXP_CAST(0x53211e00), FXP_CAST(0x7641af00), FXP_CAST(0x86944500)}, {FXP_CAST(0x711f3a80), FXP_CAST(0x89be5100), FXP_CAST(0xebc72040)}, +{FXP_CAST(0xde3966c0), FXP_CAST(0x30fbc540), FXP_CAST(0x66b87e00)}, {FXP_CAST(0x80246080), FXP_CAST(0x30fbc540), FXP_CAST(0x73362c00)}, {FXP_CAST(0xe9fe3c40), FXP_CAST(0x89be5100), FXP_CAST(0x03d1d110)}, +{FXP_CAST(0x7641b000), FXP_CAST(0x7641af00), FXP_CAST(0x90520c80)}, {FXP_CAST(0x4999c380), FXP_CAST(0xcf043ac0), FXP_CAST(0x94e80a80)}, {FXP_CAST(0xa9dab800), FXP_CAST(0xcf043ac0), FXP_CAST(0x0ca570e0)}, +{FXP_CAST(0x90d0b000), FXP_CAST(0x7641af00), FXP_CAST(0x76c9bc80)}, {FXP_CAST(0x25a32000), FXP_CAST(0x89be5100), FXP_CAST(0x61338500)}, {FXP_CAST(0x7f9afc80), FXP_CAST(0x30fbc540), FXP_CAST(0xe318f060)}, +{FXP_CAST(0x120909c0), FXP_CAST(0x30fbc540), FXP_CAST(0x84124e00)}, {FXP_CAST(0x88435d80), FXP_CAST(0x89be5100), FXP_CAST(0xaa4d2f80)}, {FXP_CAST(0xb9b9a200), FXP_CAST(0x7641af00), FXP_CAST(0x2cae1800)}, +{FXP_CAST(0x5913ae80), FXP_CAST(0xcf043ac0), FXP_CAST(0x7f040680)}, {FXP_CAST(0x6d234e00), FXP_CAST(0xcf043ac0), FXP_CAST(0x48c6a100)}, {FXP_CAST(0xd689db80), FXP_CAST(0x7641af00), FXP_CAST(0xc44860c0)}, +{FXP_CAST(0x80c5e380), FXP_CAST(0x89be5100), FXP_CAST(0x80005d00)}, {FXP_CAST(0xf1f43eb0), FXP_CAST(0x30fbc540), FXP_CAST(0xc55a3a00)}, {FXP_CAST(0x79195500), FXP_CAST(0x30fbc540), FXP_CAST(0x49c3de00)}, +{FXP_CAST(0x42e13700), FXP_CAST(0x89be5100), FXP_CAST(0x7edc5b00)}, {FXP_CAST(0xa4146c80), FXP_CAST(0x7641af00), FXP_CAST(0x2b8c2c00)}, {FXP_CAST(0x95044680), FXP_CAST(0xcf043ac0), FXP_CAST(0xa968c100)}, +{FXP_CAST(0x2d3eaf40), FXP_CAST(0xcf043ac0), FXP_CAST(0x8460fd80)}, {FXP_CAST(0x7eb91780), FXP_CAST(0x7641af00), FXP_CAST(0xe44621e0)}, {FXP_CAST(0x0a0aec80), FXP_CAST(0x89be5100), FXP_CAST(0x61fb5c00)}, +{FXP_CAST(0x85a89100), FXP_CAST(0x30fbc540), FXP_CAST(0x76555780)}, {FXP_CAST(0xc094d500), FXP_CAST(0x30fbc540), FXP_CAST(0x0b71f790)}, {FXP_CAST(0x5eac4000), FXP_CAST(0x89be5100), FXP_CAST(0x94401a80)}, +{FXP_CAST(0x68b91d80), FXP_CAST(0x7641af00), FXP_CAST(0x90ea3980)}, {FXP_CAST(0xcf043440), FXP_CAST(0xcf043ac0), FXP_CAST(0x05067a08)}, {FXP_CAST(0x81e7f180), FXP_CAST(0xcf043ac0), FXP_CAST(0x73bb6d00)}, +{FXP_CAST(0xf9f871e0), FXP_CAST(0x7641af00), FXP_CAST(0x65ff0e00)}, {FXP_CAST(0x7b76a000), FXP_CAST(0x89be5100), FXP_CAST(0xea9664c0)}, {FXP_CAST(0x3be518c0), FXP_CAST(0x30fbc540), FXP_CAST(0x8633e880)}, +{FXP_CAST(0x9eaaff00), FXP_CAST(0x30fbc540), FXP_CAST(0xa4c84500)}, {FXP_CAST(0x99a3f400), FXP_CAST(0x89be5100), FXP_CAST(0x2571eac0)}, {FXP_CAST(0x34ac8840), FXP_CAST(0x7641af00), FXP_CAST(0x7dd82b00)}, +{FXP_CAST(0x7d572a80), FXP_CAST(0xcf043ac0), FXP_CAST(0x4eed8400)}, {FXP_CAST(0x0202a9c4), FXP_CAST(0xcf043ac0), FXP_CAST(0xcb249700)}, {FXP_CAST(0x83896000), FXP_CAST(0x7641af00), FXP_CAST(0x80318200)}, +{FXP_CAST(0xc7b01b00), FXP_CAST(0x89be5100), FXP_CAST(0xbeab7580)}, {FXP_CAST(0x63e52a80), FXP_CAST(0x30fbc540), FXP_CAST(0x4364b700)}, {FXP_CAST(0x63e51f00), FXP_CAST(0x30fbc540), FXP_CAST(0x7fa6bd00)}, +{FXP_CAST(0xc7b00a00), FXP_CAST(0x89be5100), FXP_CAST(0x32a67940)}, {FXP_CAST(0x83896400), FXP_CAST(0x7641af00), FXP_CAST(0xaf2fd200)}, {FXP_CAST(0x0202bc9c), FXP_CAST(0xcf043ac0), FXP_CAST(0x829e6e80)}, +{FXP_CAST(0x7d572e80), FXP_CAST(0xcf043ac0), FXP_CAST(0xdcde6b80)}, {FXP_CAST(0x34ac7700), FXP_CAST(0x7641af00), FXP_CAST(0x5ce4e280)}, {FXP_CAST(0x99a3e880), FXP_CAST(0x89be5100), FXP_CAST(0x79089c00)}, +{FXP_CAST(0x9eab0b80), FXP_CAST(0x30fbc540), FXP_CAST(0x1307ae80)}, {FXP_CAST(0x3be52980), FXP_CAST(0x30fbc540), FXP_CAST(0x98906880)}, {FXP_CAST(0x7b769b00), FXP_CAST(0x89be5100), FXP_CAST(0x8d51b300)}, +{FXP_CAST(0xf9f85f10), FXP_CAST(0x7641af00), FXP_CAST(0xfd62ee24)}, {FXP_CAST(0x81e7ee00), FXP_CAST(0xcf043ac0), FXP_CAST(0x70439680)}, {FXP_CAST(0xcf044580), FXP_CAST(0xcf043ac0), FXP_CAST(0x6a6d9600)}, +{FXP_CAST(0x68b92800), FXP_CAST(0x7641af00), FXP_CAST(0xf2275f80)}}; + +const FIXP_PS aaFractDelayPhaseFactorSerReSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { +{FXP_CAST(0x7e2df000), FXP_CAST(0x7a7d0580), FXP_CAST(0x7ed03e00)}, {FXP_CAST(0x6fec9a80), FXP_CAST(0x5133cc80), FXP_CAST(0x7573df00)}, {FXP_CAST(0x55063900), FXP_CAST(0x0c8bd360), FXP_CAST(0x636c0400)}, +{FXP_CAST(0x3084ca00), FXP_CAST(0xc3a94580), FXP_CAST(0x4a0d6700)}, {FXP_CAST(0x80000000), FXP_CAST(0x80000000), FXP_CAST(0x80000000)}, {FXP_CAST(0x80000000), FXP_CAST(0x80000000), FXP_CAST(0x80000000)}, +{FXP_CAST(0x6fec9a80), FXP_CAST(0x5133cc80), FXP_CAST(0x7573df00)}, {FXP_CAST(0x7e2df000), FXP_CAST(0x7a7d0580), FXP_CAST(0x7ed03e00)}, {FXP_CAST(0xa4c84280), FXP_CAST(0xb8e31300), FXP_CAST(0xd5af0140)}, +{FXP_CAST(0xf0f488a0), FXP_CAST(0x8275a100), FXP_CAST(0x1a72e360)}, {FXP_CAST(0x80aaa680), FXP_CAST(0x471ced00), FXP_CAST(0x9d2ead80)}, {FXP_CAST(0x9477d100), FXP_CAST(0x7d8a5f00), FXP_CAST(0x8151df80)}}; + +const FIXP_PS aaFractDelayPhaseFactorSerImSubQmf20[NO_SUB_QMF_CHANNELS][NO_SERIAL_ALLPASS_LINKS] = { +{FXP_CAST(0xea7d08a0), FXP_CAST(0xdad7f3c0), FXP_CAST(0xee9c9f60)}, {FXP_CAST(0xc1e54140), FXP_CAST(0x9d0dfe80), FXP_CAST(0xcd1e7300)}, {FXP_CAST(0xa051a580), FXP_CAST(0x809dc980), FXP_CAST(0xaf61c400)}, +{FXP_CAST(0x898d4e00), FXP_CAST(0x8f1d3400), FXP_CAST(0x97988280)}, {FXP_CAST(0x00000000), FXP_CAST(0x00000000), FXP_CAST(0x00000000)}, {FXP_CAST(0x00000000), FXP_CAST(0x00000000), FXP_CAST(0x00000000)}, +{FXP_CAST(0x3e1abec0), FXP_CAST(0x62f20180), FXP_CAST(0x32e18d00)}, {FXP_CAST(0x1582f760), FXP_CAST(0x25280c40), FXP_CAST(0x116360a0)}, {FXP_CAST(0xa6343800), FXP_CAST(0x6a6d9880), FXP_CAST(0x87327a00)}, +{FXP_CAST(0x80e32200), FXP_CAST(0xe70747c0), FXP_CAST(0x82c32b00)}, {FXP_CAST(0xf2f42420), FXP_CAST(0x6a6d9880), FXP_CAST(0xaea47080)}, {FXP_CAST(0x456eba00), FXP_CAST(0xe70747c0), FXP_CAST(0xedaa8640)}}; + +const FIXP_PS p8_13_20[13] = +{ + FL2FXCONST_PS(0.00746082949812f), FL2FXCONST_PS(0.02270420949825f), FL2FXCONST_PS(0.04546865930473f), FL2FXCONST_PS(0.07266113929591f), + FL2FXCONST_PS(0.09885108575264f), FL2FXCONST_PS(0.11793710567217f), FL2FXCONST_PS(0.125f ), FL2FXCONST_PS(0.11793710567217f), + FL2FXCONST_PS(0.09885108575264f), FL2FXCONST_PS(0.07266113929591f), FL2FXCONST_PS(0.04546865930473f), FL2FXCONST_PS(0.02270420949825f), + FL2FXCONST_PS(0.00746082949812f) +}; + +const FIXP_PS p2_13_20[13] = +{ + FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.01899487526049f), FL2FXCONST_PS(0.0f), FL2FXCONST_PS(-0.07293139167538f), + FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.30596630545168f), FL2FXCONST_PS(0.5f), FL2FXCONST_PS( 0.30596630545168f), + FL2FXCONST_PS(0.0f), FL2FXCONST_PS(-0.07293139167538f), FL2FXCONST_PS(0.0f), FL2FXCONST_PS( 0.01899487526049f), + FL2FXCONST_PS(0.0f) +}; + + + +const UCHAR aAllpassLinkDelaySer[] = { 3, 4, 5}; + +const UCHAR delayIndexQmf[NO_QMF_CHANNELS] = { + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +const UCHAR groupBorders20[NO_IID_GROUPS + 1] = +{ + 6, 7, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ + 9, 8, /* 2 subqmf subbands - 1st qmf subband */ + 10, 11, /* 2 subqmf subbands - 2nd qmf subband */ + 3, 4, 5, 6, 7, 8, + 9, 11, 14, 18, 23, 35, 64 +}; + +const UCHAR groupBorders34[NO_IID_GROUPS_HI_RES + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* 12 subqmf subbands - 0th qmf subband */ + 12, 13, 14, 15, 16, 17, 18, 19, /* 8 subqmf subbands - 1st qmf subband */ + 20, 21, 22, 23, /* 4 subqmf subbands - 2nd qmf subband */ + 24, 25, 26, 27, /* 4 subqmf subbands - 3nd qmf subband */ + 28, 29, 30, 31, /* 4 subqmf subbands - 4nd qmf subband */ + 32-27, 33-27, 34-27, 35-27, 36-27, 37-27, 38-27, + 40-27, 42-27, 44-27, 46-27, 48-27, 51-27, 54-27, + 57-27, 60-27, 64-27, 68-27, 91-27 +}; + +const UCHAR bins2groupMap20[NO_IID_GROUPS] = +{ + 1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 +}; + +const UCHAR quantizedIIDs[NO_IID_STEPS] = +{ + 2, 4, 7, 10, 14, 18, 25 +}; +const UCHAR quantizedIIDsFine[NO_IID_STEPS_FINE] = +{ + 2, 4, 6, 8, 10, 13, 16, 19, 22, 25, 30, 35, 40, 45, 50 +}; + +const UCHAR FDK_sbrDecoder_aNoIidBins[3] = {NO_LOW_RES_IID_BINS, + NO_MID_RES_IID_BINS, + NO_HI_RES_IID_BINS}; + +const UCHAR FDK_sbrDecoder_aNoIccBins[3] = {NO_LOW_RES_ICC_BINS, + NO_MID_RES_ICC_BINS, + NO_HI_RES_ICC_BINS}; + + + +/************************************************************************/ +/*! + \brief Create lookup tables for some arithmetic functions + + The tables would normally be defined as const arrays, + but initialization at run time allows to specify their accuracy. +*/ +/************************************************************************/ + +/* 1/x-table: (example for INV_TABLE_BITS 8) + + The table covers an input range from 0.5 to 1.0 with a step size of 1/512, + starting at 0.5 + 1/512. + Each table entry corresponds to an input interval starting 1/1024 below the + exact value and ending 1/1024 above it. + + The table is actually a 0.5/x-table, so that the output range is again + 0.5...1.0 and the exponent of the result must be increased by 1. + + Input range Index in table result + ------------------------------------------------------------------- + 0.500000...0.500976 - 0.5 / 0.500000 = 1.000000 + 0.500976...0.502930 0 0.5 / 0.501953 = 0.996109 + 0.502930...0.500488 1 0.5 / 0.503906 = 0.992248 + ... + 0.999023...1.000000 255 0.5 / 1.000000 = 0.500000 + + for (i=0; i=0.5 + FRACT_BITS-1 zero e.g |max| = 0 +\endverbatim + + Dynamic scaling is used to achieve sufficient accuracy even when the signal + energy is low. The dynamic framing of SBR produces a variable overlap area + where samples from the previous QMF-Analysis are stored. Depending on the + start position and stop position of the current SBR envelopes, the processing + buffer consists of differently scaled regions like illustrated in the below + figure. + + \image html scales.png Scale +*/ + + +#endif diff --git a/libSBRdec/src/sbrdec_drc.cpp b/libSBRdec/src/sbrdec_drc.cpp new file mode 100644 index 00000000..a834c0b0 --- /dev/null +++ b/libSBRdec/src/sbrdec_drc.cpp @@ -0,0 +1,525 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for SBR + +******************************************************************************/ + +#include "sbrdec_drc.h" + + +/* DRC - Offset table for QMF interpolation. */ +static const int offsetTab[2][16] = +{ + { 0, 4, 8, 12, 16, 20, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 1024 framing */ + { 0, 4, 8, 12, 16, 19, 22, 26, 0, 0, 0, 0, 0, 0, 0, 0 } /* 960 framing */ +}; + +/*! + \brief Initialize DRC QMF factors + + \hDrcData Handle to DRC channel data. + + \return none +*/ +void sbrDecoder_drcInitChannel ( + HANDLE_SBR_DRC_CHANNEL hDrcData ) +{ + int band; + + if (hDrcData == NULL) { + return; + } + + for (band = 0; band < (64); band++) { + hDrcData->prevFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + for (band = 0; band < SBRDEC_MAX_DRC_BANDS; band++) { + hDrcData->currFact_mag[band] = FL2FXCONST_DBL(0.5f); + hDrcData->nextFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + hDrcData->prevFact_exp = 1; + hDrcData->currFact_exp = 1; + hDrcData->nextFact_exp = 1; + + hDrcData->numBandsCurr = 1; + hDrcData->numBandsNext = 1; + + hDrcData->winSequenceCurr = 0; + hDrcData->winSequenceNext = 0; + + hDrcData->drcInterpolationSchemeCurr = 0; + hDrcData->drcInterpolationSchemeNext = 0; + + hDrcData->enable = 0; +} + + +/*! + \brief Swap DRC QMF scaling factors after they have been applied. + + \hDrcData Handle to DRC channel data. + + \return none +*/ +void sbrDecoder_drcUpdateChannel ( + HANDLE_SBR_DRC_CHANNEL hDrcData ) +{ + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + /* swap previous data */ + FDKmemcpy( hDrcData->currFact_mag, + hDrcData->nextFact_mag, + SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL) ); + + hDrcData->currFact_exp = hDrcData->nextFact_exp; + + hDrcData->numBandsCurr = hDrcData->numBandsNext; + + FDKmemcpy( hDrcData->bandTopCurr, + hDrcData->bandTopNext, + SBRDEC_MAX_DRC_BANDS * sizeof(USHORT) ); + + hDrcData->drcInterpolationSchemeCurr = hDrcData->drcInterpolationSchemeNext; + + hDrcData->winSequenceCurr = hDrcData->winSequenceNext; +} + + +/*! + \brief Apply DRC factors slot based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of one time slot. + \qmfImagSlot Pointer to the imaginary QMF data of one time slot. + \col Number of the time slot. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the time slot. + + \return None. +*/ +void sbrDecoder_drcApplySlot ( + HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, + FIXP_DBL *qmfImagSlot, + int col, + int numQmfSubSamples, + int maxShift + ) +{ + const int *offset; + + int band, bottomMdct, topMdct, bin, useLP; + int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */ + int frameLenFlag = (numQmfSubSamples == 30) ? 1 : 0; + + const FIXP_DBL *fact_mag = NULL; + INT fact_exp = 0; + UINT numBands = 0; + USHORT *bandTop = NULL; + int shortDrc = 0; + + FIXP_DBL alphaValue = FL2FXCONST_DBL(0.0f); + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + offset = offsetTab[frameLenFlag]; + + useLP = (qmfImagSlot == NULL) ? 1 : 0; + + col += indx; + bottomMdct = 0; + bin = 0; + + /* get respective data and calc interpolation factor */ + if (col < (numQmfSubSamples>>1)) { /* first half of current frame */ + if (hDrcData->winSequenceCurr != 2) { /* long window */ + int j = col + (numQmfSubSamples>>1); + + if (hDrcData->drcInterpolationSchemeCurr == 0) { + INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } + else { + if (j >= offset[hDrcData->drcInterpolationSchemeCurr - 1]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } + else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } + else if (col < numQmfSubSamples) { /* second half of current frame */ + if (hDrcData->winSequenceNext != 2) { /* next: long window */ + int j = col - (numQmfSubSamples>>1); + + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } + else { + if (j >= offset[hDrcData->drcInterpolationSchemeNext - 1]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } + else { /* next: short windows */ + if (hDrcData->winSequenceCurr != 2) { /* current: long window */ + alphaValue = (FIXP_DBL)0; + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } + else { /* current: short windows */ + shortDrc = 1; + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } + } + } + else { /* first half of next frame */ + if (hDrcData->winSequenceNext != 2) { /* long window */ + int j = col - (numQmfSubSamples>>1); + + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444444 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } + else { + if (j >= offset[hDrcData->drcInterpolationSchemeNext - 1]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } + else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + + col -= numQmfSubSamples; + } + + + /* process bands */ + for (band = 0; band < (int)numBands; band++) { + int bottomQmf, topQmf; + + FIXP_DBL drcFact_mag = (FIXP_DBL)MAXVAL_DBL; + + topMdct = (bandTop[band]+1) << 2; + + if (!shortDrc) { /* long window */ + if (frameLenFlag) { + /* 960 framing */ + bottomMdct = 30 * (bottomMdct / 30); + topMdct = 30 * (topMdct / 30); + + bottomQmf = fMultIfloor((FIXP_DBL)0x4444444, bottomMdct); + topQmf = fMultIfloor((FIXP_DBL)0x4444444, topMdct); + } + else { + /* 1024 framing */ + bottomMdct &= ~0x1f; + topMdct &= ~0x1f; + + bottomQmf = bottomMdct >> 5; + topQmf = topMdct >> 5; + } + + if (band == ((int)numBands-1)) { + topQmf = (64); + } + + for (bin = bottomQmf; bin < topQmf; bin++) { + FIXP_DBL drcFact1_mag = hDrcData->prevFact_mag[bin]; + FIXP_DBL drcFact2_mag = fact_mag[band]; + + /* normalize scale factors */ + if (hDrcData->prevFact_exp < maxShift) { + drcFact1_mag >>= maxShift - hDrcData->prevFact_exp; + } + if (fact_exp < maxShift) { + drcFact2_mag >>= maxShift - fact_exp; + } + + /* interpolate */ + if (alphaValue == (FIXP_DBL)0) { + drcFact_mag = drcFact1_mag; + } else if (alphaValue == (FIXP_DBL)MAXVAL_DBL) { + drcFact_mag = drcFact2_mag; + } else { + drcFact_mag = fMult(alphaValue, drcFact2_mag) + fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag); + } + + /* apply scaling */ + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + + /* save previous factors */ + if (col == (numQmfSubSamples>>1)-1) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + } + else { /* short windows */ + int startSample, stopSample; + FIXP_DBL invFrameSizeDiv8 = (frameLenFlag) ? (FIXP_DBL)0x1111111 : (FIXP_DBL)0x1000000; + + if (frameLenFlag) { + /* 960 framing */ + bottomMdct = 30/8 * (bottomMdct*8/30); + topMdct = 30/8 * (topMdct*8/30); + } + else { + /* 1024 framing */ + bottomMdct &= ~0x03; + topMdct &= ~0x03; + } + + /* startSample is truncated to the nearest corresponding start subsample in + the QMF of the short window bottom is present in:*/ + startSample = ((fMultIfloor( invFrameSizeDiv8, bottomMdct ) & 0x7) * numQmfSubSamples) >> 3; + + /* stopSample is rounded upwards to the nearest corresponding stop subsample + in the QMF of the short window top is present in. */ + stopSample = ((fMultIceil( invFrameSizeDiv8, topMdct ) & 0xf) * numQmfSubSamples) >> 3; + + bottomQmf = fMultIfloor( invFrameSizeDiv8, ((bottomMdct%(numQmfSubSamples<<2)) << 5) ); + topQmf = fMultIfloor( invFrameSizeDiv8, ((topMdct%(numQmfSubSamples<<2)) << 5) ); + + /* extend last band */ + if (band == ((int)numBands-1)) { + topQmf = (64); + stopSample = numQmfSubSamples; + } + + if (topQmf == 0) { + topQmf = (64); + } + + /* save previous factors */ + if (stopSample == numQmfSubSamples) { + int tmpBottom = bottomQmf; + + if (((numQmfSubSamples-1) & ~0x03) > startSample) { + tmpBottom = 0; /* band starts in previous short window */ + } + + for (bin = tmpBottom; bin < topQmf; bin++) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + + /* apply */ + if ((col >= startSample) && (col < stopSample)) { + if ((col & ~0x03) > startSample) { + bottomQmf = 0; /* band starts in previous short window */ + } + if (col < ((stopSample-1) & ~0x03)) { + topQmf = (64); /* band ends in next short window */ + } + + drcFact_mag = fact_mag[band]; + + /* normalize scale factor */ + if (fact_exp < maxShift) { + drcFact_mag >>= maxShift - fact_exp; + } + + /* apply scaling */ + for (bin = bottomQmf; bin < topQmf; bin++) { + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + } + } + } + + bottomMdct = topMdct; + } /* end of bands loop */ + + if (col == (numQmfSubSamples>>1)-1) { + hDrcData->prevFact_exp = fact_exp; + } +} + + +/*! + \brief Apply DRC factors frame based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of the whole frame. + \qmfImagSlot Pointer to the imaginary QMF data of the whole frame. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the frame. + + \return None. +*/ +void sbrDecoder_drcApply ( + HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, + FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, + int *scaleFactor + ) +{ + int col; + int maxShift = 0; + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable == 0) { + return; /* Avoid changing the scaleFactor even though the processing is disabled. */ + } + + /* get max scale factor */ + if (hDrcData->prevFact_exp > maxShift) { + maxShift = hDrcData->prevFact_exp; + } + if (hDrcData->currFact_exp > maxShift) { + maxShift = hDrcData->currFact_exp; + } + if (hDrcData->nextFact_exp > maxShift) { + maxShift = hDrcData->nextFact_exp; + } + + for (col = 0; col < numQmfSubSamples; col++) + { + FIXP_DBL *qmfSlotReal = QmfBufferReal[col]; + FIXP_DBL *qmfSlotImag = (QmfBufferImag == NULL) ? NULL : QmfBufferImag[col]; + + sbrDecoder_drcApplySlot ( + hDrcData, + qmfSlotReal, + qmfSlotImag, + col, + numQmfSubSamples, + maxShift + ); + } + + *scaleFactor += maxShift; +} + diff --git a/libSBRdec/src/sbrdec_drc.h b/libSBRdec/src/sbrdec_drc.h new file mode 100644 index 00000000..7eed53a0 --- /dev/null +++ b/libSBRdec/src/sbrdec_drc.h @@ -0,0 +1,151 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG-4 AAC Decoder ************************** + + Author(s): Christian Griebel + Description: Dynamic range control (DRC) decoder tool for SBR + +******************************************************************************/ + +#ifndef _SBRDEC_DRC_H_ +#define _SBRDEC_DRC_H_ + +#include "sbrdecoder.h" + + + +#define SBRDEC_MAX_DRC_CHANNELS (8) +#define SBRDEC_MAX_DRC_BANDS ( 16 ) + +typedef struct +{ + FIXP_DBL prevFact_mag[(64)]; + INT prevFact_exp; + + FIXP_DBL currFact_mag[SBRDEC_MAX_DRC_BANDS]; + FIXP_DBL nextFact_mag[SBRDEC_MAX_DRC_BANDS]; + INT currFact_exp; + INT nextFact_exp; + + UINT numBandsCurr; + UINT numBandsNext; + USHORT bandTopCurr[SBRDEC_MAX_DRC_BANDS]; + USHORT bandTopNext[SBRDEC_MAX_DRC_BANDS]; + + SHORT drcInterpolationSchemeCurr; + SHORT drcInterpolationSchemeNext; + + SHORT enable; + + UCHAR winSequenceCurr; + UCHAR winSequenceNext; + +} SBRDEC_DRC_CHANNEL; + +typedef SBRDEC_DRC_CHANNEL * HANDLE_SBR_DRC_CHANNEL; + + +void sbrDecoder_drcInitChannel ( + HANDLE_SBR_DRC_CHANNEL hDrcData ); + +void sbrDecoder_drcUpdateChannel ( + HANDLE_SBR_DRC_CHANNEL hDrcData ); + +void sbrDecoder_drcApplySlot ( + HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, + FIXP_DBL *qmfImagSlot, + int col, + int numQmfSubSamples, + int maxShift ); + +void sbrDecoder_drcApply ( + HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, + FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, + int *scaleFactor ); + + +#endif /* _SBRDEC_DRC_H_ */ diff --git a/libSBRdec/src/sbrdec_freq_sca.cpp b/libSBRdec/src/sbrdec_freq_sca.cpp new file mode 100644 index 00000000..8adfbb17 --- /dev/null +++ b/libSBRdec/src/sbrdec_freq_sca.cpp @@ -0,0 +1,812 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Frequency scale calculation +*/ + +#include "sbrdec_freq_sca.h" + +#include "transcendent.h" +#include "sbr_rom.h" +#include "env_extr.h" + +#include "genericStds.h" /* need log() for debug-code only */ + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + + +static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); +static void CalcBands(UCHAR * diff, UCHAR start, UCHAR stop, UCHAR num_bands); +static SBR_ERROR modifyBands(UCHAR max_band, UCHAR * diff, UCHAR length); +static void cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress); + + + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR +getStartBand(UINT fs, /*!< Output sampling frequency */ + UCHAR startFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags) /*!< Info to SBR mode */ +{ + INT band; + UINT fsMapped; + + fsMapped = fs; + + switch (fsMapped) { + case 96000: + case 88200: + band = FDK_sbrDecoder_sbr_start_freq_88[startFreq]; + break; + case 64000: + band = FDK_sbrDecoder_sbr_start_freq_64[startFreq]; + break; + case 48000: + band = FDK_sbrDecoder_sbr_start_freq_48[startFreq]; + break; + case 44100: + band = FDK_sbrDecoder_sbr_start_freq_44[startFreq]; + break; + case 32000: + band = FDK_sbrDecoder_sbr_start_freq_32[startFreq]; + break; + case 24000: + band = FDK_sbrDecoder_sbr_start_freq_24[startFreq]; + break; + case 22050: + band = FDK_sbrDecoder_sbr_start_freq_22[startFreq]; + break; + case 16000: + band = FDK_sbrDecoder_sbr_start_freq_16[startFreq]; + break; + default: + band = 255; + } + + return band; +} + + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR +getStopBand(UINT fs, /*!< Output sampling frequency */ + UCHAR stopFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags, /*!< Info to SBR mode */ + UCHAR k0) /*!< Start freq index */ +{ + UCHAR k2; + + if (stopFreq < 14) { + INT stopMin; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot+MAX_OCTAVE; + + if (fs < 32000) { + stopMin = (((2*6000*2*(64)) / fs) + 1) >> 1; + } + else { + if (fs < 64000) { + stopMin = (((2*8000*2*(64)) / fs) + 1) >> 1; + } + else { + stopMin = (((2*10000*2*(64)) / fs) + 1) >> 1; + } + } + + /* + Choose a stop band between k1 and 64 depending on stopFreq (0..13), + based on a logarithmic scale. + The vectors diff0 and diff1 are used temporarily here. + */ + CalcBands( diff0, stopMin, 64, 13); + shellsort( diff0, 13); + cumSum(stopMin, diff0, 13, diff1); + k2 = diff1[stopFreq]; + } + else if (stopFreq==14) + k2 = 2*k0; + else + k2 = 3*k0; + + /* Limit to Nyquist */ + if (k2 > (64)) + k2 = (64); + + + /* Range checks */ + /* 1 <= difference <= 48; 1 <= fs <= 96000 */ + if ( ((k2 - k0) > MAX_FREQ_COEFFS) || (k2 <= k0) ) { + return 255; + } + + if (headerDataFlags & (SBRDEC_SYNTAX_USAC|SBRDEC_SYNTAX_RSVD50)) { + /* 1 <= difference <= 35; 42000 <= fs <= 96000 */ + if ( (fs >= 42000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + return 255; + } + /* 1 <= difference <= 32; 46009 <= fs <= 96000 */ + if ( (fs >= 46009) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + return 255; + } + } + else { + /* 1 <= difference <= 35; fs == 44100 */ + if ( (fs == 44100) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS44100 ) ) { + return 255; + } + /* 1 <= difference <= 32; 48000 <= fs <= 96000 */ + if ( (fs >= 48000) && ( (k2 - k0) > MAX_FREQ_COEFFS_FS48000 ) ) { + return 255; + } + } + + return k2; +} + + +/*! + \brief Generates master frequency tables + + Frequency tables are calculated according to the selected domain + (linear/logarithmic) and granularity. + IEC 14496-3 4.6.18.3.2.1 + + \return errorCode, 0 if successful +*/ +SBR_ERROR +sbrdecUpdateFreqScale(UCHAR * v_k_master, /*!< Master table to be created */ + UCHAR *numMaster, /*!< Number of entries in master table */ + UINT fs, /*!< SBR working sampling rate */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ + UINT flags) +{ + FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ + INT dk=0; + + /* Internal variables */ + UCHAR k0, k2, i; + UCHAR num_bands0 = 0; + UCHAR num_bands1 = 0; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot+MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr=0; + + /* + Determine start band + */ + k0 = getStartBand(fs, hHeaderData->bs_data.startFreq, flags); + if (k0 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* + Determine stop band + */ + k2 = getStopBand(fs, hHeaderData->bs_data.stopFreq, flags, k0); + if (k2 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if(hHeaderData->bs_data.freqScale>0) { /* Bark */ + INT k1; + + if(hHeaderData->bs_data.freqScale==1) { + bpo_div16 = FL2FXCONST_SGL(12.0f/16.0f); + } + else if(hHeaderData->bs_data.freqScale==2) { + bpo_div16 = FL2FXCONST_SGL(10.0f/16.0f); + } + else { + bpo_div16 = FL2FXCONST_SGL(8.0f/16.0f); + } + + + if( 1000 * k2 > 2245 * k0 ) { /* Two or more regions */ + k1 = 2*k0; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + num_bands1 = numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale ); + if ( num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if ( num_bands1 < 1 ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + CalcBands(diff0, k0, k1, num_bands0); + shellsort( diff0, num_bands0); + if (diff0[0] == 0) { +#ifdef DEBUG_TOOLS +#endif + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + + CalcBands(diff1, k1, k2, num_bands1); + shellsort( diff1, num_bands1); + if(diff0[num_bands0-1] > diff1[0]) { + SBR_ERROR err; + + err = modifyBands(diff0[num_bands0-1],diff1, num_bands1); + if (err) + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Add 2nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ + + } + else { /* Only one region */ + k1=k2; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + if ( num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + CalcBands(diff0, k0, k1, num_bands0); + shellsort(diff0, num_bands0); + if (diff0[0] == 0) { +#ifdef DEBUG_TOOLS +#endif + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + *numMaster = num_bands0; /* Output nr of bands */ + + } + } + else { /* Linear mode */ + if (hHeaderData->bs_data.alterScale==0) { + dk = 1; + /* FLOOR to get to few number of bands (next lower even number) */ + num_bands0 = (k2 - k0) & 254; + } else { + dk = 2; + num_bands0 = ( ((k2 - k0) >> 1) + 1 ) & 254; /* ROUND to the closest fit */ + } + + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + /* We must return already here because 'i' can become negative below. */ + } + + k2_achived = k0 + num_bands0*dk; + k2_diff = k2 - k2_achived; + + for(i=0;i 0) { + incr = -1; + i = num_bands0-1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master);/* cumsum */ + *numMaster = num_bands0; /* Output nr of bands */ + } + + if (*numMaster < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + + /* + Print out the calculated table + */ + + return SBRDEC_OK; +} + + +/*! + \brief Calculate frequency ratio of one SBR band + + All SBR bands should span a constant frequency range in the logarithmic + domain. This function calculates the ratio of any SBR band's upper and lower + frequency. + + \return num_band-th root of k_start/k_stop +*/ +static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) +{ +/* Scaled bandfactor and step 1 bit right to avoid overflow + * use double data type */ + FIXP_DBL bandfactor = FL2FXCONST_DBL(0.25f); /* Start value */ + FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ + + int direction = 1; + +/* Because saturation can't be done in INT IIS, + * changed start and stop data type from FIXP_SGL to FIXP_DBL */ + FIXP_DBL start = k_start << (DFRACT_BITS-8); + FIXP_DBL stop = k_stop << (DFRACT_BITS-8); + + FIXP_DBL temp; + + int j, i=0; + + while ( step > FL2FXCONST_DBL(0.0f)) { + i++; + temp = stop; + + /* Calculate temp^num_bands: */ + for (j=0; j> 1); + direction = 1; + bandfactor = bandfactor + step; + } + else { /* Factor is too weak: make it stronger */ + if (direction == 1) + step = (FIXP_DBL)((LONG)step >> 1); + direction = 0; + bandfactor = bandfactor - step; + } + + if (i>100) { + step = FL2FXCONST_DBL(0.0f); + } + } + return FX_DBL2FX_SGL(bandfactor<<1); +} + + +/*! + \brief Calculate number of SBR bands between start and stop band + + Given the number of bands per octave, this function calculates how many + bands fit in the given frequency range. + When the warpFlag is set, the 'band density' is decreased by a factor + of 1/1.3 + + \return number of bands +*/ +static int +numberOfBands(FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ + int start, /*!< First QMF band of SBR frequency range */ + int stop, /*!< Last QMF band of SBR frequency range + 1 */ + int warpFlag) /*!< Stretching flag */ +{ + FIXP_SGL num_bands_div128; + int num_bands; + + num_bands_div128 = FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start,stop),bpo_div16)); + + if (warpFlag) { + /* Apply the warp factor of 1.3 to get wider bands. We use a value + of 32768/25200 instead of the exact value to avoid critical cases + of rounding. + */ + num_bands_div128 = FX_DBL2FX_SGL(fMult(num_bands_div128, FL2FXCONST_SGL(25200.0/32768.0))); + } + + /* add scaled 1 for rounding to even numbers: */ + num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL( 1.0f/128.0f ); + /* scale back to right aligned integer and double the value: */ + num_bands = 2 * ((LONG)num_bands_div128 >> (FRACT_BITS - 7)); + + return(num_bands); +} + + +/*! + \brief Calculate width of SBR bands + + Given the desired number of bands within the SBR frequency range, + this function calculates the width of each SBR band in QMF channels. + The bands get wider from start to stop (bark scale). +*/ +static void +CalcBands(UCHAR * diff, /*!< Vector of widths to be calculated */ + UCHAR start, /*!< Lower end of subband range */ + UCHAR stop, /*!< Upper end of subband range */ + UCHAR num_bands) /*!< Desired number of bands */ +{ + int i; + int previous; + int current; + FIXP_SGL exact, temp; + FIXP_SGL bandfactor = calcFactorPerBand(start, stop, num_bands); + + previous = stop; /* Start with highest QMF channel */ + exact = (FIXP_SGL)(stop << (FRACT_BITS-8)); /* Shift left to gain some accuracy */ + + for(i=num_bands-1; i>=0; i--) { + /* Calculate border of next lower sbr band */ + exact = FX_DBL2FX_SGL(fMult(exact,bandfactor)); + + /* Add scaled 0.5 for rounding: + We use a value 128/256 instead of 0.5 to avoid some critical cases of rounding. */ + temp = exact + FL2FXCONST_SGL(128.0/32768.0); + + /* scale back to right alinged integer: */ + current = (LONG)temp >> (FRACT_BITS-8); + + /* Save width of band i */ + diff[i] = previous - current; + previous = current; + } +} + + +/*! + \brief Calculate cumulated sum vector from delta vector +*/ +static void +cumSum(UCHAR start_value, UCHAR* diff, UCHAR length, UCHAR *start_adress) +{ + int i; + start_adress[0]=start_value; + for(i=1; i<=length; i++) + start_adress[i] = start_adress[i-1] + diff[i-1]; +} + + +/*! + \brief Adapt width of frequency bands in the second region + + If SBR spans more than 2 octaves, the upper part of a bark-frequency-scale + is calculated separately. This function tries to avoid that the second region + starts with a band smaller than the highest band of the first region. +*/ +static SBR_ERROR +modifyBands(UCHAR max_band_previous, UCHAR * diff, UCHAR length) +{ + int change = max_band_previous - diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first one */ + if ( change > (diff[length-1]-diff[0])>>1 ) + change = (diff[length-1]-diff[0])>>1; + + diff[0] += change; + diff[length-1] -= change; + shellsort(diff, length); + + return SBRDEC_OK; +} + + +/*! + \brief Update high resolution frequency band table +*/ +static void +sbrdecUpdateHiRes(UCHAR * h_hires, + UCHAR * num_hires, + UCHAR * v_k_master, + UCHAR num_bands, + UCHAR xover_band) +{ + UCHAR i; + + *num_hires = num_bands-xover_band; + + for(i=xover_band; i<=num_bands; i++) { + h_hires[i-xover_band] = v_k_master[i]; + } +} + + +/*! + \brief Build low resolution table out of high resolution table +*/ +static void +sbrdecUpdateLoRes(UCHAR * h_lores, + UCHAR * num_lores, + UCHAR * h_hires, + UCHAR num_hires) +{ + UCHAR i; + + if( (num_hires & 1) == 0) { + /* If even number of hires bands */ + *num_lores = num_hires >> 1; + /* Use every second lores=hires[0,2,4...] */ + for(i=0; i<=*num_lores; i++) + h_lores[i] = h_hires[i*2]; + } + else { + /* Odd number of hires, which means xover is odd */ + *num_lores = (num_hires+1) >> 1; + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0] = h_hires[0]; + for(i=1; i<=*num_lores; i++) { + h_lores[i] = h_hires[i*2-1]; + } + } +} + + +/*! + \brief Derive a low-resolution frequency-table from the master frequency table +*/ +void +sbrdecDownSampleLoRes(UCHAR *v_result, + UCHAR num_result, + UCHAR *freqBandTableRef, + UCHAR num_Ref) +{ + int step; + int i,j; + int org_length,result_length; + int v_index[MAX_FREQ_COEFFS>>1]; + + /* init */ + org_length = num_Ref; + result_length = num_result; + + v_index[0] = 0; /* Always use left border */ + i=0; + while(org_length > 0) { + /* Create downsample vector */ + i++; + step = org_length / result_length; + org_length = org_length - step; + result_length--; + v_index[i] = v_index[i-1] + step; + } + + for(j=0;j<=i;j++) { + /* Use downsample vector to index LoResolution vector */ + v_result[j]=freqBandTableRef[v_index[j]]; + } + +} + + +/*! + \brief Sorting routine +*/ +void shellsort(UCHAR *in, UCHAR n) +{ + + int i, j, v, w; + int inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc; i < n; i++) { + v = in[i]; + j = i; + while ((w=in[j-inc]) > v) { + in[j] = w; + j -= inc; + if (j < inc) + break; + } + in[j] = v; + } + } while (inc > 1); + +} + + + +/*! + \brief Reset frequency band tables + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) +{ + SBR_ERROR err = SBRDEC_OK; + int k2,kx, lsb, usb; + int intTemp; + UCHAR nBandsLo, nBandsHi; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + + /* Calculate master frequency function */ + err = sbrdecUpdateFreqScale(hFreq->v_k_master, + &hFreq->numMaster, + hHeaderData->sbrProcSmplRate, + hHeaderData, + flags); + + if ( err || (hHeaderData->bs_info.xover_band > hFreq->numMaster) ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Derive Hiresolution from master frequency function */ + sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, hFreq->numMaster, hHeaderData->bs_info.xover_band ); + /* Derive Loresolution from Hiresolution */ + sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], nBandsHi); + + + hFreq->nSfb[0] = nBandsLo; + hFreq->nSfb[1] = nBandsHi; + + /* Check index to freqBandTable[0] */ + if ( !(nBandsLo > 0) || (nBandsLo > (MAX_FREQ_COEFFS>>1)) ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + lsb = hFreq->freqBandTable[0][0]; + usb = hFreq->freqBandTable[0][nBandsLo]; + + /* Additional check for lsb */ + if ( (lsb > (32)) || (lsb >= usb) ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + + /* Calculate number of noise bands */ + + k2 = hFreq->freqBandTable[1][nBandsHi]; + kx = hFreq->freqBandTable[1][0]; + + if (hHeaderData->bs_data.noise_bands == 0) + { + hFreq->nNfb = 1; + } + else /* Calculate no of noise bands 1,2 or 3 bands/octave */ + { + /* Fetch number of octaves divided by 32 */ + intTemp = (LONG)FDK_getNumOctavesDiv8(kx,k2) >> 2; + + /* Integer-Multiplication with number of bands: */ + intTemp = intTemp * hHeaderData->bs_data.noise_bands; + + /* Add scaled 0.5 for rounding: */ + intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f/32.0f); + + /* Convert to right-aligned integer: */ + intTemp = intTemp >> (FRACT_BITS - 1 /*sign*/ - 5 /* rescale */); + + /* Compare with float calculation */ + FDK_ASSERT( intTemp == (int)((hHeaderData->bs_data.noise_bands * FDKlog( (float)k2/kx) / (float)(FDKlog(2.0)))+0.5) ); + + if( intTemp==0) + intTemp=1; + + hFreq->nNfb = intTemp; + } + + hFreq->nInvfBands = hFreq->nNfb; + + if( hFreq->nNfb > MAX_NOISE_COEFFS ) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Get noise bands */ + sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, + hFreq->nNfb, + hFreq->freqBandTable[0], + nBandsLo); + + + + + hFreq->lowSubband = lsb; + hFreq->highSubband = usb; + + return SBRDEC_OK; +} diff --git a/libSBRdec/src/sbrdec_freq_sca.h b/libSBRdec/src/sbrdec_freq_sca.h new file mode 100644 index 00000000..cfe4f0e7 --- /dev/null +++ b/libSBRdec/src/sbrdec_freq_sca.h @@ -0,0 +1,107 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Frequency scale prototypes +*/ +#ifndef __FREQ_SCA_H +#define __FREQ_SCA_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +int +sbrdecUpdateFreqScale(UCHAR * v_k_master, + UCHAR *numMaster, + HANDLE_SBR_HEADER_DATA headerData); + +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref); + +void shellsort(UCHAR *in, UCHAR n); + +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags); + +#endif diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp new file mode 100644 index 00000000..f9ded541 --- /dev/null +++ b/libSBRdec/src/sbrdecoder.cpp @@ -0,0 +1,1757 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief SBR decoder frontend + This module provides a frontend to the SBR decoder. The function openSBR() is called for + initialization. The function sbrDecoder_Apply() is called for each frame. sbr_Apply() will call the + required functions to decode the raw SBR data (provided by env_extr.cpp), to decode the envelope data and noise floor levels [decodeSbrData()], + and to finally apply SBR to the current frame [sbr_dec()]. + + \sa sbrDecoder_Apply(), \ref documentationOverview +*/ + +/*! + \page documentationOverview Overview of important information resources and source code documentation + + The primary source code documentation is based on generated and cross-referenced HTML files using +
doxygen. As part of this documentation + you can find more extensive descriptions about key concepts and algorithms at the following locations: + +

Programming

+ + \li Buffer management: sbrDecoder_Apply() and sbr_dec() + \li Internal scale factors to maximize SNR on fixed point processors: #QMF_SCALE_FACTOR + \li Special mantissa-exponent format: Created in requantizeEnvelopeData() and used in calculateSbrEnvelope() + +

Algorithmic details

+ \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref SBR_STANDARD_ELEMENT + \li Details about the bitstream decoder: env_extr.cpp + \li Details about the QMF filterbank and the provided polyphase implementation: qmf_dec.cpp + \li Details about the transposer: lpp_tran.cpp + \li Details about the envelope adjuster: env_calc.cpp + +*/ + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "sbr_dec.h" +#include "env_dec.h" +#include "sbr_crc.h" +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "lpp_tran.h" +#include "transcendent.h" + +#include "FDK_crc.h" + +#include "sbrdec_drc.h" + +#include "psbitdec.h" + + +/* Decoder library info */ +#define SBRDECODER_LIB_VL0 2 +#define SBRDECODER_LIB_VL1 2 +#define SBRDECODER_LIB_VL2 12 +#define SBRDECODER_LIB_TITLE "SBR Decoder" +#ifdef __ANDROID__ +#define SBRDECODER_LIB_BUILD_DATE "" +#define SBRDECODER_LIB_BUILD_TIME "" +#else +#define SBRDECODER_LIB_BUILD_DATE __DATE__ +#define SBRDECODER_LIB_BUILD_TIME __TIME__ +#endif + + + + +static UCHAR getHeaderSlot( UCHAR currentSlot, UCHAR hdrSlotUsage[(1)+1] ) +{ + UINT occupied = 0; + int s; + UCHAR slot = hdrSlotUsage[currentSlot]; + + FDK_ASSERT((1)+1 < 32); + + for (s = 0; s < (1)+1; s++) { + if ( (hdrSlotUsage[s] == slot) + && (s != slot) ) { + occupied = 1; + break; + } + } + + if (occupied) { + occupied = 0; + + for (s = 0; s < (1)+1; s++) { + occupied |= 1 << hdrSlotUsage[s]; + } + for (s = 0; s < (1)+1; s++) { + if ( !(occupied & 0x1) ) { + slot = s; + break; + } + occupied >>= 1; + } + } + + return slot; +} + +static void copySbrHeader( HANDLE_SBR_HEADER_DATA hDst, const HANDLE_SBR_HEADER_DATA hSrc ) +{ + /* copy the whole header memory (including pointers) */ + FDKmemcpy( hDst, hSrc, sizeof(SBR_HEADER_DATA) ); + + /* update pointers */ + hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo; + hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi; +} + +static int compareSbrHeader( const HANDLE_SBR_HEADER_DATA hHdr1, const HANDLE_SBR_HEADER_DATA hHdr2 ) +{ + int result = 0; + + /* compare basic data */ + result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0; + result |= (hHdr1->status != hHdr2->status) ? 1 : 0; + result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0; + result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0; + result |= (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; + result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0; + result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0; + + /* compare bitstream data */ + result |= FDKmemcmp( &hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS) ); + result |= FDKmemcmp( &hHdr1->bs_info, &hHdr2->bs_info, sizeof(SBR_HEADER_DATA_BS_INFO) ); + + /* compare frequency band data */ + result |= FDKmemcmp( &hHdr1->freqBandData, &hHdr2->freqBandData, (8+MAX_NUM_LIMITERS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableLo, hHdr2->freqBandData.freqBandTableLo, (MAX_FREQ_COEFFS/2+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableHi, hHdr2->freqBandData.freqBandTableHi, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.freqBandTableNoise, hHdr2->freqBandData.freqBandTableNoise, (MAX_NOISE_COEFFS+1)*sizeof(UCHAR) ); + result |= FDKmemcmp( hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, (MAX_FREQ_COEFFS+1)*sizeof(UCHAR) ); + + return result; +} + + +/*! + \brief Reset SBR decoder. + + Reset should only be called if SBR has been sucessfully detected by + an appropriate checkForPayload() function. + + \return Error code. +*/ +static +SBR_ERROR sbrDecoder_ResetElement ( + HANDLE_SBRDECODER self, + int sampleRateIn, + int sampleRateOut, + int samplesPerFrame, + const MP4_ELEMENT_ID elementID, + const int elementIndex, + const int overlap + ) +{ + SBR_ERROR sbrError = SBRDEC_OK; + HANDLE_SBR_HEADER_DATA hSbrHeader; + UINT qmfFlags = 0; + + int i, synDownsampleFac; + + /* Check in/out samplerates */ + if ( sampleRateIn < 6400 + || sampleRateIn > 48000 + ) + { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if ( sampleRateOut > 96000 ) + { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + /* Set QMF mode flags */ + if (self->flags & SBRDEC_LOW_POWER) + qmfFlags |= QMF_FLAG_LP; + + if (self->coreCodec == AOT_ER_AAC_ELD) { + if (self->flags & SBRDEC_LD_MPS_QMF) { + qmfFlags |= QMF_FLAG_MPSLDFB; + } else { + qmfFlags |= QMF_FLAG_CLDFB; + } + } + + /* Set downsampling factor for synthesis filter bank */ + if (sampleRateOut == 0) + { + /* no single rate mode */ + sampleRateOut = sampleRateIn<<1; /* In case of implicit signalling, assume dual rate SBR */ + } + + if ( sampleRateIn == sampleRateOut ) { + synDownsampleFac = 2; + self->flags |= SBRDEC_DOWNSAMPLE; + } else { + synDownsampleFac = 1; + self->flags &= ~SBRDEC_DOWNSAMPLE; + } + + self->synDownsampleFac = synDownsampleFac; + self->sampleRateOut = sampleRateOut; + + { + int i; + + for (i = 0; i < (1)+1; i++) + { + hSbrHeader = &(self->sbrHeader[elementIndex][i]); + + /* init a default header such that we can at least do upsampling later */ + sbrError = initHeaderData( + hSbrHeader, + sampleRateIn, + sampleRateOut, + samplesPerFrame, + self->flags + ); + } + } + + if (sbrError != SBRDEC_OK) { + goto bail; + } + + /* Init SBR channels going to be assigned to a SBR element */ + { + int ch; + + for (ch=0; chpSbrElement[elementIndex]->nChannels; ch++) + { + /* and create sbrDec */ + sbrError = createSbrDec (self->pSbrElement[elementIndex]->pSbrChannel[ch], + hSbrHeader, + &self->pSbrElement[elementIndex]->transposerSettings, + synDownsampleFac, + qmfFlags, + self->flags, + overlap, + ch ); + + if (sbrError != SBRDEC_OK) { + goto bail; + } + } + } + + //FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer)); + + if (self->numSbrElements == 1) { + switch ( self->coreCodec ) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + if (CreatePsDec ( &self->hParametricStereoDec, samplesPerFrame )) { + sbrError = SBRDEC_CREATE_ERROR; + goto bail; + } + break; + default: + break; + } + } + + /* Init frame delay slot handling */ + self->pSbrElement[elementIndex]->useFrameSlot = 0; + for (i = 0; i < ((1)+1); i++) { + self->pSbrElement[elementIndex]->useHeaderSlot[i] = i; + } + +bail: + + return sbrError; +} + + +SBR_ERROR sbrDecoder_Open ( HANDLE_SBRDECODER * pSelf ) +{ + HANDLE_SBRDECODER self = NULL; + SBR_ERROR sbrError = SBRDEC_OK; + + /* Get memory for this instance */ + self = GetRam_SbrDecoder(); + if (self == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + + self->workBuffer1 = GetRam_SbrDecWorkBuffer1(); + self->workBuffer2 = GetRam_SbrDecWorkBuffer2(); + + if ( self->workBuffer1 == NULL + || self->workBuffer2 == NULL ) + { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + + /* + Already zero because of calloc + self->numSbrElements = 0; + self->numSbrChannels = 0; + self->codecFrameSize = 0; + */ + + self->numDelayFrames = (1); /* set to the max value by default */ + + *pSelf = self; + +bail: + return sbrError; +} + +/** + * \brief determine if the given core codec AOT can be processed or not. + * \param coreCodec core codec audio object type. + * \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied. + */ +static +int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) +{ + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: + return 1; + default: + return 0; + } +} + +static +void sbrDecoder_DestroyElement ( + HANDLE_SBRDECODER self, + const int elementIndex + ) +{ + if (self->pSbrElement[elementIndex] != NULL) { + int ch; + + for (ch=0; chpSbrElement[elementIndex]->pSbrChannel[ch] != NULL) { + deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] ); + FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] ); + self->numSbrChannels -= 1; + } + } + FreeRam_SbrDecElement( &self->pSbrElement[elementIndex] ); + self->numSbrElements -= 1; + } +} + + +SBR_ERROR sbrDecoder_InitElement ( + HANDLE_SBRDECODER self, + const int sampleRateIn, + const int sampleRateOut, + const int samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const int elementIndex + ) +{ + SBR_ERROR sbrError = SBRDEC_OK; + int chCnt=0; + int nSbrElementsStart = self->numSbrElements; + + /* Check core codec AOT */ + if (! sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if ( elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE ) + { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if ( self->sampleRateIn == sampleRateIn + && self->codecFrameSize == samplesPerFrame + && self->coreCodec == coreCodec + && self->pSbrElement[elementIndex] != NULL + && self->pSbrElement[elementIndex]->elementID == elementID + && !(self->flags & SBRDEC_FORCE_RESET) + ) + { + /* Nothing to do */ + return SBRDEC_OK; + } + + self->sampleRateIn = sampleRateIn; + self->codecFrameSize = samplesPerFrame; + self->coreCodec = coreCodec; + + self->flags = 0; + self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0; + self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0; + self->flags |= (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL|SBRDEC_SYNTAX_DRM : 0; + + /* Init SBR elements */ + { + int elChannels, ch; + + if (self->pSbrElement[elementIndex] == NULL) { + self->pSbrElement[elementIndex] = GetRam_SbrDecElement(elementIndex); + if (self->pSbrElement[elementIndex] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + self->numSbrElements ++; + } else { + self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels; + } + + /* Save element ID for sanity checks and to have a fallback for concealment. */ + self->pSbrElement[elementIndex]->elementID = elementID; + + /* Determine amount of channels for this element */ + switch (elementID) { + case ID_NONE: + case ID_CPE: elChannels=2; + break; + case ID_LFE: + case ID_SCE: elChannels=1; + break; + default: elChannels=0; + break; + } + + /* Handle case of Parametric Stereo */ + if ( elementIndex == 0 && elementID == ID_SCE ) { + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + elChannels = 2; + break; + default: + break; + } + } + + self->pSbrElement[elementIndex]->nChannels = elChannels; + + for (ch=0; chpSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + self->pSbrElement[elementIndex]->pSbrChannel[ch] = GetRam_SbrDecChannel(chCnt); + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + } + self->numSbrChannels ++; + + sbrDecoder_drcInitChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.sbrDrcChannel ); + + /* Add reference pointer to workbuffers. */ + self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer1 = self->workBuffer1; + self->pSbrElement[elementIndex]->pSbrChannel[ch]->SbrDec.WorkBuffer2 = self->workBuffer2; + chCnt++; + } + if (elChannels == 1 && self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) { + deleteSbrDec( self->pSbrElement[elementIndex]->pSbrChannel[ch] ); + FreeRam_SbrDecChannel( &self->pSbrElement[elementIndex]->pSbrChannel[ch] ); + } + } + + /* clear error flags for all delay slots */ + FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, ((1)+1)*sizeof(UCHAR)); + + /* Initialize this instance */ + sbrError = sbrDecoder_ResetElement( + self, + sampleRateIn, + sampleRateOut, + samplesPerFrame, + elementID, + elementIndex, + (coreCodec == AOT_ER_AAC_ELD) ? 0 : (6) + ); + + + +bail: + if (sbrError != SBRDEC_OK) { + if (nSbrElementsStart < self->numSbrElements) { + /* Free the memory allocated for this element */ + sbrDecoder_DestroyElement( self, elementIndex ); + } else if ( (self->pSbrElement[elementIndex] != NULL) + && (elementIndex < (8))) + { /* Set error flag to trigger concealment */ + self->pSbrElement[elementIndex]->frameErrorFlag[self->pSbrElement[elementIndex]->useFrameSlot] = 1; + } + } + + return sbrError; +} + +/** + * \brief Apply decoded SBR header for one element. + * \param self SBR decoder instance handle + * \param hSbrHeader SBR header handle to be processed. + * \param hSbrChannel pointer array to the SBR element channels corresponding to the SBR header. + * \param headerStatus header status value returned from SBR header parser. + * \param numElementChannels amount of channels for the SBR element whos header is to be processed. + */ +static +SBR_ERROR sbrDecoder_HeaderUpdate( + HANDLE_SBRDECODER self, + HANDLE_SBR_HEADER_DATA hSbrHeader, + SBR_HEADER_STATUS headerStatus, + HANDLE_SBR_CHANNEL hSbrChannel[], + const int numElementChannels + ) +{ + SBR_ERROR errorStatus = SBRDEC_OK; + + /* + change of control data, reset decoder + */ + errorStatus = resetFreqBandTables(hSbrHeader, self->flags); + + if (errorStatus == SBRDEC_OK) { + if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) + { + /* As the default header would limit the frequency range, + lowSubband and highSubband must be patched. */ + hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands; + hSbrHeader->freqBandData.highSubband = hSbrHeader->numberOfAnalysisBands; + } + + /* Trigger a reset before processing this slot */ + hSbrHeader->status |= SBRDEC_HDR_STAT_RESET; + } + + return errorStatus; +} + +INT sbrDecoder_Header ( + HANDLE_SBRDECODER self, + HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, + const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex + ) +{ + SBR_HEADER_STATUS headerStatus; + HANDLE_SBR_HEADER_DATA hSbrHeader; + SBR_ERROR sbrError = SBRDEC_OK; + int headerIndex; + + if ( self == NULL || elementIndex > (8) ) + { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (! sbrDecoder_isCoreCodecValid(coreCodec)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + sbrError = sbrDecoder_InitElement( + self, + sampleRateIn, + sampleRateOut, + samplesPerFrame, + coreCodec, + elementID, + elementIndex + ); + + if (sbrError != SBRDEC_OK) { + goto bail; + } + + headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + + headerStatus = sbrGetHeaderData ( hSbrHeader, + hBs, + self->flags, + 0); + + + { + SBR_DECODER_ELEMENT *pSbrElement; + + pSbrElement = self->pSbrElement[elementIndex]; + + /* Sanity check */ + if (pSbrElement != NULL) { + if ( (elementID == ID_CPE && pSbrElement->nChannels != 2) + || (elementID != ID_CPE && pSbrElement->nChannels != 1) ) + { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if ( headerStatus == HEADER_RESET ) { + + sbrError = sbrDecoder_HeaderUpdate( + self, + hSbrHeader, + headerStatus, + pSbrElement->pSbrChannel, + pSbrElement->nChannels + ); + + if (sbrError == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } + /* else { + Since we already have overwritten the old SBR header the only way out is UPSAMPLING! + This will be prepared in the next step. + } */ + } + } + } +bail: + return sbrError; +} + + +SBR_ERROR sbrDecoder_SetParam (HANDLE_SBRDECODER self, + const SBRDEC_PARAM param, + const INT value ) +{ + SBR_ERROR errorStatus = SBRDEC_OK; + + /* configure the subsystems */ + switch (param) + { + case SBR_SYSTEM_BITSTREAM_DELAY: + if (value < 0 || value > (1)) { + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->numDelayFrames = (UCHAR)value; + } + break; + case SBR_QMF_MODE: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LOW_POWER; + } else { + self->flags &= ~SBRDEC_LOW_POWER; + } + } + break; + case SBR_LD_QMF_TIME_ALIGN: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LD_MPS_QMF; + } else { + self->flags &= ~SBRDEC_LD_MPS_QMF; + } + } + break; + case SBR_FLUSH_DATA: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FLUSH; + } + } + break; + case SBR_CLEAR_HISTORY: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FORCE_RESET; + } + } + break; + case SBR_BS_INTERRUPTION: + { + int elementIndex; + + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + break; + } + + /* Loop over SBR elements */ + for (elementIndex = 0; elementIndex < self->numSbrElements; elementIndex++) { + if (self->pSbrElement[elementIndex] != NULL) + { + HANDLE_SBR_HEADER_DATA hSbrHeader; + int headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + + /* Set sync state UPSAMPLING for the corresponding slot. + This switches off bitstream parsing until a new header arrives. */ + hSbrHeader->syncState = UPSAMPLING; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } } + } + break; + default: + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } /* switch(param) */ + + return (errorStatus); +} + +static +SBRDEC_DRC_CHANNEL * sbrDecoder_drcGetChannel( const HANDLE_SBRDECODER self, const INT channel ) +{ + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int elementIndex, elChanIdx=0, numCh=0; + + for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); elementIndex++) + { + SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex]; + int c, elChannels; + + elChanIdx = 0; + if (pSbrElement == NULL) break; + + /* Determine amount of channels for this element */ + switch (pSbrElement->elementID) { + case ID_CPE: elChannels = 2; + break; + case ID_LFE: + case ID_SCE: elChannels = 1; + break; + case ID_NONE: + default: elChannels = 0; + break; + } + + /* Limit with actual allocated element channels */ + elChannels = FDKmin(elChannels, pSbrElement->nChannels); + + for (c = 0; (c < elChannels) && (numCh <= channel); c++) { + if (pSbrElement->pSbrChannel[elChanIdx] != NULL) { + numCh++; + elChanIdx++; + } + } + } + elementIndex -= 1; + elChanIdx -= 1; + + if (elChanIdx < 0 || elementIndex < 0) { + return NULL; + } + + if ( self->pSbrElement[elementIndex] != NULL ) { + if ( self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL ) + { + pSbrDrcChannelData = &self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx]->SbrDec.sbrDrcChannel; + } + } + + return (pSbrDrcChannelData); +} + +SBR_ERROR sbrDecoder_drcFeedChannel ( HANDLE_SBRDECODER self, + INT ch, + UINT numBands, + FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, + USHORT *pBandTop ) +{ + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int band, isValidData = 0; + + if (self == NULL) { + return SBRDEC_NOT_INITIALIZED; + } + if (ch > (8) || pNextFact_mag == NULL) { + return SBRDEC_SET_PARAM_FAIL; + } + + /* Search for gain values different to 1.0f */ + for (band = 0; band < numBands; band += 1) { + if ( !((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && (nextFact_exp == 1)) + && !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && (nextFact_exp == 0)) ) { + isValidData = 1; + break; + } + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch ); + + if ( pSbrDrcChannelData != NULL ) { + if ( pSbrDrcChannelData->enable || isValidData ) + { /* Activate processing only with real and valid data */ + int i; + + pSbrDrcChannelData->enable = 1; + pSbrDrcChannelData->numBandsNext = numBands; + + pSbrDrcChannelData->winSequenceNext = winSequence; + pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme; + pSbrDrcChannelData->nextFact_exp = nextFact_exp; + + for (i = 0; i < (int)numBands; i++) { + pSbrDrcChannelData->bandTopNext[i] = pBandTop[i]; + pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i]; + } + } + } + + return SBRDEC_OK; +} + + +void sbrDecoder_drcDisable ( HANDLE_SBRDECODER self, + INT ch ) +{ + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + + if ( (self == NULL) + || (ch > (8)) + || (self->numSbrElements == 0) + || (self->numSbrChannels == 0) ) { + return; + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel( self, ch ); + + if ( pSbrDrcChannelData != NULL ) { + sbrDecoder_drcInitChannel( pSbrDrcChannelData ); + } +} + + + +SBR_ERROR sbrDecoder_Parse( + HANDLE_SBRDECODER self, + HANDLE_FDK_BITSTREAM hBs, + int *count, + int bsPayLen, + int crcFlag, + MP4_ELEMENT_ID prevElement, + int elementIndex, + int fGlobalIndependencyFlag + ) +{ + SBR_DECODER_ELEMENT *hSbrElement; + HANDLE_SBR_HEADER_DATA hSbrHeader = NULL; + HANDLE_SBR_CHANNEL *pSbrChannel; + + SBR_FRAME_DATA *hFrameDataLeft; + SBR_FRAME_DATA *hFrameDataRight; + + SBR_ERROR errorStatus = SBRDEC_OK; + SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; + + INT startPos; + INT CRCLen = 0; + HANDLE_FDK_BITSTREAM hBsOriginal = hBs; + FDK_CRCINFO crcInfo; /* shall be used for all other CRCs in the future (TBD) */ + INT crcReg = 0; + USHORT drmSbrCrc = 0; + + int stereo; + int fDoDecodeSbrData = 1; + + int lastSlot, lastHdrSlot = 0, thisHdrSlot; + + /* Reverse bits of DRM SBR payload */ + if ( (self->flags & SBRDEC_SYNTAX_DRM) && *count > 0 ) + { + UCHAR *bsBufferDrm = (UCHAR*)self->workBuffer1; + HANDLE_FDK_BITSTREAM hBsBwd = (HANDLE_FDK_BITSTREAM) (bsBufferDrm + (512)); + int dataBytes, dataBits; + + dataBits = *count; + + if (dataBits > ((512)*8)) { + /* do not flip more data than needed */ + dataBits = (512)*8; + } + + dataBytes = (dataBits+7)>>3; + + int j; + + if ((j = (int)FDKgetValidBits(hBs)) != 8) { + FDKpushBiDirectional(hBs, (j-8)); + } + + j = 0; + for ( ; dataBytes > 0; dataBytes--) + { + int i; + UCHAR tmpByte; + UCHAR buffer = 0x00; + + tmpByte = (UCHAR) FDKreadBits(hBs, 8); + for (i = 0; i < 4; i++) { + int shift = 2 * i + 1; + buffer |= (tmpByte & (0x08>>i)) << shift; + buffer |= (tmpByte & (0x10<> shift; + } + bsBufferDrm[j++] = buffer; + FDKpushBack(hBs, 16); + } + + FDKinitBitStream(hBsBwd, bsBufferDrm, (512), dataBits, BS_READER); + + /* Use reversed data */ + hBs = hBsBwd; + bsPayLen = *count; + } + + /* Remember start position of SBR element */ + startPos = FDKgetValidBits(hBs); + + /* SBR sanity checks */ + if ( self == NULL || self->pSbrElement[elementIndex] == NULL ) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } + + hSbrElement = self->pSbrElement[elementIndex]; + + lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot-1 : self->numDelayFrames; + lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot]; + thisHdrSlot = getHeaderSlot( hSbrElement->useFrameSlot, hSbrElement->useHeaderSlot ); /* Get a free header slot not used by frames not processed yet. */ + + /* Assign the free slot to store a new header if there is one. */ + hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot]; + + pSbrChannel = hSbrElement->pSbrChannel; + stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + + hFrameDataLeft = &self->pSbrElement[elementIndex]->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + hFrameDataRight = &self->pSbrElement[elementIndex]->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + + + /* reset PS flag; will be set after PS was found */ + self->flags &= ~SBRDEC_PS_DECODED; + + if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) { + /* Got a new header from extern (e.g. from an ASC) */ + headerStatus = HEADER_OK; + hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE; + } + else if (thisHdrSlot != lastHdrSlot) { + /* Copy the last header into this slot otherwise the + header compare will trigger more HEADER_RESETs than needed. */ + copySbrHeader( hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot] ); + } + + /* + Check if bit stream data is valid and matches the element context + */ + if ( ((prevElement != ID_SCE) && (prevElement != ID_CPE)) || prevElement != hSbrElement->elementID) { + /* In case of LFE we also land here, since there is no LFE SBR element (do upsampling only) */ + fDoDecodeSbrData = 0; + } + + if (fDoDecodeSbrData) + { + if ((INT)FDKgetValidBits(hBs) <= 0) { + fDoDecodeSbrData = 0; + } + } + + /* + SBR CRC-check + */ + if (fDoDecodeSbrData) + { + if (crcFlag) { + switch (self->coreCodec) { + case AOT_ER_AAC_ELD: + FDKpushFor (hBs, 10); + /* check sbrcrc later: we don't know the payload length now */ + break; + case AOT_DRM_AAC: + drmSbrCrc = (USHORT)FDKreadBits(hBs, 8); + /* Setup CRC decoder */ + FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8); + /* Start CRC region */ + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + break; + default: + CRCLen = bsPayLen - 10; /* change: 0 => i */ + if (CRCLen < 0) { + fDoDecodeSbrData = 0; + } else { + fDoDecodeSbrData = SbrCrcCheck (hBs, CRCLen); + } + break; + } + } + } /* if (fDoDecodeSbrData) */ + + /* + Read in the header data and issue a reset if change occured + */ + if (fDoDecodeSbrData) + { + int sbrHeaderPresent; + + { + sbrHeaderPresent = FDKreadBit(hBs); + } + + if ( sbrHeaderPresent ) { + headerStatus = sbrGetHeaderData (hSbrHeader, + hBs, + self->flags, + 1); + } + + if (headerStatus == HEADER_RESET) + { + errorStatus = sbrDecoder_HeaderUpdate( + self, + hSbrHeader, + headerStatus, + pSbrChannel, + hSbrElement->nChannels + ); + + if (errorStatus == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + } else { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + headerStatus = HEADER_ERROR; + } + } + + if (errorStatus != SBRDEC_OK) { + fDoDecodeSbrData = 0; + } + } /* if (fDoDecodeSbrData) */ + + /* + Print debugging output only if state has changed + */ + + /* read frame data */ + if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) { + int sbrFrameOk; + /* read the SBR element data */ + if (stereo) { + sbrFrameOk = sbrGetChannelPairElement(hSbrHeader, + hFrameDataLeft, + hFrameDataRight, + hBs, + self->flags, + self->pSbrElement[elementIndex]->transposerSettings.overlap); + } + else { + if (self->hParametricStereoDec != NULL) { + /* update slot index for PS bitstream parsing */ + self->hParametricStereoDec->bsLastSlot = self->hParametricStereoDec->bsReadSlot; + self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot; + } + sbrFrameOk = sbrGetSingleChannelElement(hSbrHeader, + hFrameDataLeft, + hBs, + self->hParametricStereoDec, + self->flags, + self->pSbrElement[elementIndex]->transposerSettings.overlap); + } + if (!sbrFrameOk) { + fDoDecodeSbrData = 0; + } + else { + INT valBits; + + if (bsPayLen > 0) { + valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs)); + } else { + valBits = (INT)FDKgetValidBits(hBs); + } + + if ( crcFlag ) { + switch (self->coreCodec) { + case AOT_ER_AAC_ELD: + { + /* late crc check for eld */ + INT payloadbits = (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos; + INT crcLen = payloadbits - 10; + FDKpushBack(hBs, payloadbits); + fDoDecodeSbrData = SbrCrcCheck (hBs, crcLen); + FDKpushFor(hBs, crcLen); + } + break; + case AOT_DRM_AAC: + /* End CRC region */ + FDKcrcEndReg(&crcInfo, hBs, crcReg); + /* Check CRC */ + if ((FDKcrcGetCRC(&crcInfo)^0xFF) != drmSbrCrc) { + fDoDecodeSbrData = 0; + } + break; + default: + break; + } + } + + /* sanity check of remaining bits */ + if (valBits < 0) { + fDoDecodeSbrData = 0; + } else { + switch (self->coreCodec) { + case AOT_SBR: + case AOT_PS: + case AOT_AAC_LC: + { + /* This sanity check is only meaningful with General Audio bitstreams */ + int alignBits = valBits & 0x7; + + if (valBits > alignBits) { + fDoDecodeSbrData = 0; + } + } + break; + default: + /* No sanity check available */ + break; + } + } + } + } else { + /* The returned bit count will not be the actual payload size since we did not + parse the frame data. Return an error so that the caller can react respectively. */ + errorStatus = SBRDEC_PARSE_ERROR; + } + + if (!fDoDecodeSbrData) { + /* Set error flag for this slot to trigger concealment */ + self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 1; + errorStatus = SBRDEC_PARSE_ERROR; + } else { + /* Everything seems to be ok so clear the error flag */ + self->pSbrElement[elementIndex]->frameErrorFlag[hSbrElement->useFrameSlot] = 0; + } + + if (!stereo) { + /* Turn coupling off explicitely to avoid access to absent right frame data + that might occur with corrupt bitstreams. */ + hFrameDataLeft->coupling = COUPLING_OFF; + } + +bail: + + if ( self->flags & SBRDEC_SYNTAX_DRM ) + { + hBs = hBsOriginal; + } + + if ( (errorStatus == SBRDEC_OK) + || ( (errorStatus == SBRDEC_PARSE_ERROR) + && (headerStatus != HEADER_ERROR) ) ) + { + int useOldHdr = ( (headerStatus == HEADER_NOT_PRESENT) + || (headerStatus == HEADER_ERROR) ) ? 1 : 0; + + if (!useOldHdr && (thisHdrSlot != lastHdrSlot)) { + useOldHdr |= ( compareSbrHeader( hSbrHeader, + &self->sbrHeader[elementIndex][lastHdrSlot] ) == 0 ) ? 1 : 0; + } + + if (useOldHdr != 0) { + /* Use the old header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; + } else { + /* Use the new header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot; + } + + /* Move frame pointer to the next slot which is up to be decoded/applied next */ + hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); + } + + *count -= startPos - FDKgetValidBits(hBs); + + return errorStatus; +} + + +/** + * \brief Render one SBR element into time domain signal. + * \param self SBR decoder handle + * \param timeData pointer to output buffer + * \param interleaved flag indicating interleaved channel output + * \param channelMapping pointer to UCHAR array where next 2 channel offsets are stored. + * \param elementIndex enumerating index of the SBR element to render. + * \param numInChannels number of channels from core coder (reading stride). + * \param numOutChannels pointer to a location to return number of output channels. + * \param psPossible flag indicating if PS is possible or not. + * \return SBRDEC_OK if successfull, else error code + */ +static SBR_ERROR +sbrDecoder_DecodeElement ( + HANDLE_SBRDECODER self, + INT_PCM *timeData, + const int interleaved, + const UCHAR *channelMapping, + const int elementIndex, + const int numInChannels, + int *numOutChannels, + const int psPossible + ) +{ + SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex]; + HANDLE_SBR_CHANNEL *pSbrChannel = self->pSbrElement[elementIndex]->pSbrChannel; + HANDLE_SBR_HEADER_DATA hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec; + + /* get memory for frame data from scratch */ + SBR_FRAME_DATA *hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + SBR_FRAME_DATA *hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + + SBR_ERROR errorStatus = SBRDEC_OK; + + + INT strideIn, strideOut, offset0, offset1; + INT codecFrameSize = self->codecFrameSize; + + int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + int numElementChannels = hSbrElement->nChannels; /* Number of channels of the current SBR element */ + + if (self->flags & SBRDEC_FLUSH) { + if ( self->numFlushedFrames > self->numDelayFrames ) { + int hdrIdx; + /* No valid SBR payload available, hence switch to upsampling (in all headers) */ + for (hdrIdx = 0; hdrIdx < ((1)+1); hdrIdx += 1) { + self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING; + } + } + else { + /* Move frame pointer to the next slot which is up to be decoded/applied next */ + hSbrElement->useFrameSlot = (hSbrElement->useFrameSlot+1) % (self->numDelayFrames+1); + /* Update header and frame data pointer because they have already been set */ + hSbrHeader = &self->sbrHeader[elementIndex][hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + hFrameDataRight = &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + } + + /* Update the header error flag */ + hSbrHeader->frameErrorFlag = hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot]; + + /* + Prepare filterbank for upsampling if no valid bit stream data is available. + */ + if ( hSbrHeader->syncState == SBR_NOT_INITIALIZED ) + { + errorStatus = initHeaderData( + hSbrHeader, + self->sampleRateIn, + self->sampleRateOut, + codecFrameSize, + self->flags + ); + + if (errorStatus != SBRDEC_OK) { + return errorStatus; + } + + hSbrHeader->syncState = UPSAMPLING; + + errorStatus = sbrDecoder_HeaderUpdate( + self, + hSbrHeader, + HEADER_NOT_PRESENT, + pSbrChannel, + hSbrElement->nChannels + ); + + if (errorStatus != SBRDEC_OK) { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + return errorStatus; + } + } + + /* reset */ + if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) { + int ch; + for (ch = 0 ; ch < numElementChannels; ch++) { + SBR_ERROR errorStatusTmp = SBRDEC_OK; + + errorStatusTmp = resetSbrDec ( + &pSbrChannel[ch]->SbrDec, + hSbrHeader, + &pSbrChannel[ch]->prevFrameData, + self->flags & SBRDEC_LOW_POWER, + self->synDownsampleFac + ); + + if (errorStatusTmp != SBRDEC_OK) { + errorStatus = errorStatusTmp; + } + } + hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET; + } + + /* decoding */ + if ( (hSbrHeader->syncState == SBR_ACTIVE) + || ((hSbrHeader->syncState == SBR_HEADER) && (hSbrHeader->frameErrorFlag == 0)) ) + { + errorStatus = SBRDEC_OK; + + decodeSbrData (hSbrHeader, + hFrameDataLeft, + &pSbrChannel[0]->prevFrameData, + (stereo) ? hFrameDataRight : NULL, + (stereo) ? &pSbrChannel[1]->prevFrameData : NULL); + + + /* Now we have a full parameter set and can do parameter + based concealment instead of plain upsampling. */ + hSbrHeader->syncState = SBR_ACTIVE; + } + + /* decode PS data if available */ + if (h_ps_d != NULL && psPossible) { + int applyPs = 1; + + /* define which frame delay line slot to process */ + h_ps_d->processSlot = hSbrElement->useFrameSlot; + + applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag); + self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0; + } + + /* Set strides for reading and writing */ + if (interleaved) { + strideIn = numInChannels; + if ( psPossible ) + strideOut = (numInChannels < 2) ? 2 : numInChannels; + else + strideOut = numInChannels; + offset0 = channelMapping[0]; + offset1 = channelMapping[1]; + } else { + strideIn = 1; + strideOut = 1; + offset0 = channelMapping[0]*2*codecFrameSize; + offset1 = channelMapping[1]*2*codecFrameSize; + } + + /* use same buffers for left and right channel and apply PS per timeslot */ + /* Process left channel */ +//FDKprintf("self->codecFrameSize %d\t%d\n",self->codecFrameSize,self->sampleRateIn); + sbr_dec (&pSbrChannel[0]->SbrDec, + timeData + offset0, + timeData + offset0, + &pSbrChannel[1]->SbrDec, + timeData + offset1, + strideIn, + strideOut, + hSbrHeader, + hFrameDataLeft, + &pSbrChannel[0]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), + h_ps_d, + self->flags, + codecFrameSize + ); + + if (stereo) { + /* Process right channel */ + sbr_dec (&pSbrChannel[1]->SbrDec, + timeData + offset1, + timeData + offset1, + NULL, + NULL, + strideIn, + strideOut, + hSbrHeader, + hFrameDataRight, + &pSbrChannel[1]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), + NULL, + self->flags, + codecFrameSize + ); + } + + if (h_ps_d != NULL) { + /* save PS status for next run */ + h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0 ; + } + + if ( psPossible + ) + { + FDK_ASSERT(strideOut > 1); + if ( !(self->flags & SBRDEC_PS_DECODED) ) { + /* A decoder which is able to decode PS has to produce a stereo output even if no PS data is availble. */ + /* So copy left channel to right channel. */ + int copyFrameSize = codecFrameSize * 2 / self->synDownsampleFac; + if (interleaved) { + INT_PCM *ptr; + INT i; + FDK_ASSERT(strideOut == 2); + + ptr = timeData; + for (i = copyFrameSize>>1; i--; ) + { + INT_PCM tmp; /* This temporal variable is required because some compilers can't do *ptr++ = *ptr++ correctly. */ + tmp = *ptr++; *ptr++ = tmp; + tmp = *ptr++; *ptr++ = tmp; + } + } else { + FDKmemcpy( timeData+copyFrameSize, timeData, copyFrameSize*sizeof(INT_PCM) ); + } + } + *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */ + } + + return errorStatus; +} + + +SBR_ERROR sbrDecoder_Apply ( HANDLE_SBRDECODER self, + INT_PCM *timeData, + int *numChannels, + int *sampleRate, + const UCHAR channelMapping[(8)], + const int interleaved, + const int coreDecodedOk, + UCHAR *psDecoded ) +{ + SBR_ERROR errorStatus = SBRDEC_OK; + + int psPossible = 0; + int sbrElementNum; + int numCoreChannels = *numChannels; + int numSbrChannels = 0; + + psPossible = *psDecoded; + + if (self->numSbrElements < 1) { + /* exit immediately to avoid access violations */ + return SBRDEC_CREATE_ERROR; + } + + /* Sanity check of allocated SBR elements. */ + for (sbrElementNum=0; sbrElementNumnumSbrElements; sbrElementNum++) { + if (self->pSbrElement[sbrElementNum] == NULL) { + return SBRDEC_CREATE_ERROR; + } + } + + if (self->numSbrElements != 1 || self->pSbrElement[0]->elementID != ID_SCE) { + psPossible = 0; + } + + + /* In case of non-interleaved time domain data and upsampling, make room for bigger SBR output. */ + if (self->synDownsampleFac == 1 && interleaved == 0) { + int c, outputFrameSize; + + outputFrameSize = + self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_channels + * self->pSbrElement[0]->pSbrChannel[0]->SbrDec.SynthesisQMF.no_col; + + for (c=numCoreChannels-1; c>0; c--) { + FDKmemmove(timeData + c*outputFrameSize, timeData + c*self->codecFrameSize , self->codecFrameSize*sizeof(INT_PCM)); + } + } + + + /* Make sure that even if no SBR data was found/parsed *psDecoded is returned 1 if psPossible was 0. */ + if (psPossible == 0) { + self->flags &= ~SBRDEC_PS_DECODED; + } + + if ( self->flags & SBRDEC_FLUSH ) { + /* flushing is signalized, hence increment the flush frame counter */ + self->numFlushedFrames++; + } + else { + /* no flushing is signalized, hence reset the flush frame counter */ + self->numFlushedFrames = 0; + } + + /* Loop over SBR elements */ + for (sbrElementNum = 0; sbrElementNumnumSbrElements; sbrElementNum++) + { + int numElementChan; + + if (psPossible && self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { + /* Disable PS and try decoding SBR mono. */ + psPossible = 0; + } + + numElementChan = (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; + + /* If core signal is bad then force upsampling */ + if ( ! coreDecodedOk ) { + self->pSbrElement[sbrElementNum]->frameErrorFlag[self->pSbrElement[sbrElementNum]->useFrameSlot] = 1; + } + + errorStatus = sbrDecoder_DecodeElement ( + self, + timeData, + interleaved, + channelMapping, + sbrElementNum, + numCoreChannels, + &numElementChan, + psPossible + ); + + if (errorStatus != SBRDEC_OK) { + goto bail; + } + + numSbrChannels += numElementChan; + channelMapping += numElementChan; + + if (numSbrChannels >= numCoreChannels) { + break; + } + } + + /* Update numChannels and samplerate */ + *numChannels = numSbrChannels; + *sampleRate = self->sampleRateOut; + *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; + + + + /* Clear reset and flush flag because everything seems to be done successfully. */ + self->flags &= ~SBRDEC_FORCE_RESET; + self->flags &= ~SBRDEC_FLUSH; + +bail: + + return errorStatus; +} + + +SBR_ERROR sbrDecoder_Close ( HANDLE_SBRDECODER *pSelf ) +{ + HANDLE_SBRDECODER self = *pSelf; + int i; + + if (self != NULL) + { + if (self->hParametricStereoDec != NULL) { + DeletePsDec ( &self->hParametricStereoDec ); + } + + if (self->workBuffer1 != NULL) { + FreeRam_SbrDecWorkBuffer1(&self->workBuffer1); + } + if (self->workBuffer2 != NULL) { + FreeRam_SbrDecWorkBuffer2(&self->workBuffer2); + } + + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement( self, i ); + } + + FreeRam_SbrDecoder(pSelf); + } + + return SBRDEC_OK; +} + + +INT sbrDecoder_GetLibInfo( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) + break; + } + if (i == FDK_MODULE_LAST) + return -1; + info += i; + + info->module_id = FDK_SBRDEC; + info->version = LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = (char *)SBRDECODER_LIB_BUILD_DATE; + info->build_time = (char *)SBRDECODER_LIB_BUILD_TIME; + info->title = (char *)SBRDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 + | CAPF_SBR_HQ + | CAPF_SBR_LP + | CAPF_SBR_PS_MPEG + | CAPF_SBR_DRM_BS + | CAPF_SBR_CONCEALMENT + | CAPF_SBR_DRC + ; + /* End of flags */ + + return 0; +} + + +UINT sbrDecoder_GetDelay( const HANDLE_SBRDECODER self ) +{ + UINT outputDelay = 0; + + if ( self != NULL) { + UINT flags = self->flags; + + /* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */ + + /* Are we initialized? */ + if ( (self->numSbrChannels > 0) + && (self->numSbrElements > 0) ) + { + /* Add QMF synthesis delay */ + if ( (flags & SBRDEC_ELD_GRID) + && IS_LOWDELAY(self->coreCodec) ) { + /* Low delay SBR: */ + { + outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ + if (flags & SBRDEC_LD_MPS_QMF) { + outputDelay += 32; + } + } + } + else if (!IS_USAC(self->coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) branch: */ + outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962; + } + } + } + + return (outputDelay); +} diff --git a/libSBRdec/src/transcendent.h b/libSBRdec/src/transcendent.h new file mode 100644 index 00000000..ad88bc92 --- /dev/null +++ b/libSBRdec/src/transcendent.h @@ -0,0 +1,355 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief FDK Fixed Point Arithmetic Library Interface +*/ + +#ifndef __TRANSCENDENT_H +#define __TRANSCENDENT_H + +#include "sbrdecoder.h" +#include "sbr_rom.h" + +/************************************************************************/ +/*! + \brief Get number of octaves between frequencies a and b + + The Result is scaled with 1/8. + The valid range for a and b is 1 to LOG_DUALIS_TABLE_SIZE. + + \return ld(a/b) / 8 +*/ +/************************************************************************/ +static inline FIXP_SGL FDK_getNumOctavesDiv8(INT a, /*!< lower band */ + INT b) /*!< upper band */ +{ + return ( (SHORT)((LONG)(CalcLdInt(b) - CalcLdInt(a))>>(FRACT_BITS-3)) ); +} + + +/************************************************************************/ +/*! + \brief Add two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/ +/************************************************************************/ +inline void FDK_add_MantExp(FIXP_SGL a_m, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_SGL b_m, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_SGL *ptrSum_m, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift>0)? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS-1)? shiftAbs : DFRACT_BITS-1; + shiftedMantissa = (shift>0)? (FX_SGL2FX_DBL(b_m) >> shiftAbs) : (FX_SGL2FX_DBL(a_m) >> shiftAbs); + otherMantissa = (shift>0)? FX_SGL2FX_DBL(a_m) : FX_SGL2FX_DBL(b_m); + *ptrSum_e = (shift>0)? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ( (accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || (accu <= FL2FXCONST_DBL(-0.5f)) ) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum_m = FX_DBL2FX_SGL(accu); + +} + +inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_DBL b, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_DBL *ptrSum, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift>0)? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS-1)? shiftAbs : DFRACT_BITS-1; + shiftedMantissa = (shift>0)? (b >> shiftAbs) : (a >> shiftAbs); + otherMantissa = (shift>0)? a : b; + *ptrSum_e = (shift>0)? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ( (accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || (accu <= FL2FXCONST_DBL(-0.5f)) ) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum = accu; + +} + +/************************************************************************/ +/*! + \brief Divide two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ + For performance reasons, the division is based on a table lookup + which limits accuracy. +*/ +/************************************************************************/ +static inline void FDK_divide_MantExp(FIXP_SGL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_SGL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_SGL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(FX_SGL2FX_DBL(b_m)); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (FRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift<0)? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS+1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index<0)? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index<0)? FX_SGL2FX_DBL(a_m >> 1) : fMultDiv2(bInv_m,a_m); + + postShift = CntLeadingZeros(ratio_m)-1; + + *ptrResult_m = FX_DBL2FX_SGL(ratio_m << postShift); + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +static inline void FDK_divide_MantExp(FIXP_DBL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_DBL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_DBL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(b_m); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (DFRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift<0)? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS+1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index<0)? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index<0)? (a_m >> 1) : fMultDiv2(bInv_m,a_m); + + postShift = CntLeadingZeros(ratio_m)-1; + + *ptrResult_m = ratio_m << postShift; + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +/*! + \brief Calculate the squareroot of a number given by mantissa and exponent + + Mantissa is in fract format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The operand is addressed via pointers and will be overwritten with the result. + + For performance reasons, the square root is based on a table lookup + which limits accuracy. +*/ +static inline void FDK_sqrt_MantExp(FIXP_DBL *mantissa, /*!< Pointer to mantissa */ + SCHAR *exponent, + const SCHAR *destScale) +{ + FIXP_DBL input_m = *mantissa; + int input_e = (int) *exponent; + FIXP_DBL result = FL2FXCONST_DBL(0.0f); + int result_e = -FRACT_BITS; + + /* Call lookup square root, which does internally normalization. */ + result = sqrtFixp_lookup(input_m, &input_e); + result_e = input_e; + + /* Write result */ + if (exponent==destScale) { + *mantissa = result; + *exponent = result_e; + } else { + int shift = result_e - *destScale; + *mantissa = (shift>=0) ? result << (INT)fixMin(DFRACT_BITS-1,shift) + : result >> (INT)fixMin(DFRACT_BITS-1,-shift); + *exponent = *destScale; + } +} + + +#endif diff --git a/libSBRenc/include/sbr_encoder.h b/libSBRenc/include/sbr_encoder.h new file mode 100644 index 00000000..aec03981 --- /dev/null +++ b/libSBRenc/include/sbr_encoder.h @@ -0,0 +1,430 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS *********************** + + Author(s): + Description: SBR encoder top level processing prototype + +******************************************************************************/ + +#ifndef __SBR_ENCODER_H +#define __SBR_ENCODER_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "FDK_bitstream.h" + +/* core coder helpers */ +#define MAX_TRANS_FAC 8 +#define MAX_CODEC_FRAME_RATIO 2 +#define MAX_PAYLOAD_SIZE 256 + +typedef enum codecType +{ + CODEC_AAC=0, + CODEC_AACLD=1, + CODEC_UNSPECIFIED=99 +} CODEC_TYPE; + + +typedef struct +{ + INT bitRate; + INT nChannels; + INT sampleFreq; + INT transFac; + INT standardBitrate; +} CODEC_PARAM; + +typedef enum +{ + SBR_MONO, + SBR_LEFT_RIGHT, + SBR_COUPLING, + SBR_SWITCH_LRC +} SBR_STEREO_MODE; + +/* bitstream syntax flags */ +enum +{ + SBR_SYNTAX_LOW_DELAY = 0x0001, + SBR_SYNTAX_SCALABLE = 0x0002, + SBR_SYNTAX_CRC = 0x0004, + SBR_SYNTAX_DRM_CRC = 0x0008 +}; + +typedef enum +{ + FREQ_RES_LOW = 0, + FREQ_RES_HIGH +} FREQ_RES; + +typedef struct +{ + CODEC_TYPE coreCoder; /*!< LC or ELD */ + UINT bitrateFrom; /*!< inclusive */ + UINT bitrateTo; /*!< exclusive */ + + UINT sampleRate; /*!< */ + UCHAR numChannels; /*!< */ + + UCHAR startFreq; /*!< bs_start_freq */ + UCHAR startFreqSpeech; /*!< bs_start_freq for speech config flag */ + UCHAR stopFreq; /*!< bs_stop_freq */ + UCHAR stopFreqSpeech; /*!< bs_stop_freq for speech config flag */ + + UCHAR numNoiseBands; /*!< */ + UCHAR noiseFloorOffset; /*!< */ + SCHAR noiseMaxLevel; /*!< */ + SBR_STEREO_MODE stereoMode; /*!< */ + UCHAR freqScale; /*!< */ +} sbrTuningTable_t; + +typedef struct sbrConfiguration +{ + /* + core coder dependent configurations + */ + CODEC_PARAM codecSettings; /*!< Core coder settings. To be set from core coder. */ + INT SendHeaderDataTime; /*!< SBR header send update frequency in ms. */ + INT useWaveCoding; /*!< Flag: usage of wavecoding tool. */ + INT crcSbr; /*!< Flag: usage of SBR-CRC. */ + INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this combination. */ + INT parametricCoding; /*!< Flag: usage of parametric coding tool. */ + INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core encoder. */ + FREQ_RES freq_res_fixfix[2];/*!< Frequency resolution of envelopes in frame class FIXFIX, for non-split case and split case */ + UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient frames: low (0) or variable (1) */ + + /* + core coder dependent tuning parameters + */ + INT tran_thr; /*!< SBR transient detector threshold (* 100). */ + INT noiseFloorOffset; /*!< Noise floor offset. */ + UINT useSpeechConfig; /*!< Flag: adapt tuning parameters according to speech. */ + + + + /* + core coder independent configurations + */ + INT sbrFrameSize; /*!< SBR frame size in samples. Will be calculated from core coder settings. */ + INT sbr_data_extra; /*!< Flag usage of data extra. */ + INT amp_res; /*!< Amplitude resolution. */ + INT ana_max_level; /*!< Noise insertion maximum level. */ + INT tran_fc; /*!< Transient detector start frequency. */ + INT tran_det_mode; /*!< Transient detector mode. */ + INT spread; /*!< Flag: usage of SBR spread. */ + INT stat; /*!< Flag: usage of static framing. */ + INT e; /*!< Number of envelopes when static framing is chosen. */ + SBR_STEREO_MODE stereoMode; /*!< SBR stereo mode. */ + INT deltaTAcrossFrames; /*!< Flag: allow time-delta coding. */ + FIXP_DBL dF_edge_1stEnv; /*!< Extra fraction delta-F coding is allowed to be more expensive. */ + FIXP_DBL dF_edge_incr; /*!< Increment dF_edge_1stEnv this much if dT-coding was used this frame. */ + INT sbr_invf_mode; /*!< Inverse filtering mode. */ + INT sbr_xpos_mode; /*!< Transposer mode. */ + INT sbr_xpos_ctrl; /*!< Transposer control. */ + INT sbr_xpos_level; /*!< Transposer 3rd order level. */ + INT startFreq; /*!< The start frequency table index. */ + INT stopFreq; /*!< The stop frequency table index. */ + INT useSaPan; /*!< Flag: usage of SAPAN stereo. */ + INT dynBwEnabled; /*!< Flag: usage of dynamic bandwidth. */ + INT bParametricStereo; /*!< Flag: usage of parametric stereo coding tool. */ + + /* + header_extra1 configuration + */ + UCHAR freqScale; /*!< Frequency grouping. */ + INT alterScale; /*!< Scale resolution. */ + INT sbr_noise_bands; /*!< Number of noise bands. */ + + + /* + header_extra2 configuration + */ + INT sbr_limiter_bands; /*!< Number of limiter bands. */ + INT sbr_limiter_gains; /*!< Gain of limiter. */ + INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */ + INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */ + UCHAR init_amp_res_FF; + FIXP_DBL threshold_AmpRes_FF_m; + SCHAR threshold_AmpRes_FF_e; +} sbrConfiguration, *sbrConfigurationPtr ; + +typedef struct SBR_CONFIG_DATA +{ + UINT sbrSyntaxFlags; /**< SBR syntax flags derived from AOT. */ + INT nChannels; /**< Number of channels. */ + + INT nSfb[2]; /**< Number of SBR scalefactor bands for LO_RES and HI_RES (?) */ + INT num_Master; /**< Number of elements in v_k_master. */ + INT sampleFreq; /**< SBR sampling frequency. */ + INT frameSize; + INT xOverFreq; /**< The SBR start frequency. */ + INT dynXOverFreq; /**< Used crossover frequency when dynamic bandwidth is enabled. */ + INT noQmfBands; /**< Number of QMF frequency bands. */ + INT noQmfSlots; /**< Number of QMF slots. */ + + UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only MAX_FREQ_COEFFS/2 +1 coeffs actually needed for lowres. */ + UCHAR *v_k_master; /**< Master BandTable where freqBandTable is derived from. */ + + + SBR_STEREO_MODE stereoMode; + INT noEnvChannels; /**< Number of envelope channels. */ + + INT useWaveCoding; /**< Flag indicates whether to use wave coding at all. */ + INT useParametricCoding; /**< Flag indicates whether to use para coding at all. */ + INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the fly. */ + INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . */ + UCHAR initAmpResFF; + FIXP_DBL thresholdAmpResFF_m; + SCHAR thresholdAmpResFF_e; +} SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA; + +typedef struct { + MP4_ELEMENT_ID elType; + INT bitRate; + int instanceTag; + UCHAR fParametricStereo; + UCHAR nChannelsInEl; + UCHAR ChannelIndex[2]; +} SBR_ELEMENT_INFO; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SBR_ENCODER *HANDLE_SBR_ENCODER; + +/** + * \brief Get the max required input buffer size including delay balancing space + * for N audio channels. + * \param noChannels Number of audio channels. + * \return Max required input buffer size in bytes. + */ +INT sbrEncoder_GetInBufferSize(int noChannels); + +INT sbrEncoder_Open( + HANDLE_SBR_ENCODER *phSbrEncoder, + INT nElements, + INT nChannels, + INT supportPS + ); + +/** + * \brief Get closest working bitrate to specified desired + * bitrate for a single SBR element. + * \param bitRate The desired target bit rate + * \param numChannels The amount of audio channels + * \param coreSampleRate The sample rate of the core coder + * \param aot The current Audio Object Type + * \return Closest working bit rate to bitRate value + */ +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot); + + +/** + * \brief Check whether downsampled SBR single rate is possible + * with given audio object type. + * \param aot The Audio object type. + * \return 0 when downsampled SBR is not possible, + * 1 when downsampled SBR is possible. + */ +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot); + +/** + * \brief Initialize SBR Encoder instance. + * \param phSbrEncoder Pointer to a SBR Encoder instance. + * \param elInfo Structure that describes the element/channel arrangement. + * \param noElements Amount of elements described in elInfo. + * \param inputBuffer Pointer to the encoder audio buffer + * \param bandwidth Returns the core audio encoder bandwidth (output) + * \param bufferOffset Returns the offset for the audio input data in order to do delay balancing. + * \param numChannels Input: Encoder input channels. output: core encoder channels. + * \param sampleRate Input: Encoder samplerate. output core encoder samplerate. + * \param downSampleFactor Input: Relation between SBR and core coder sampling rate; + * \param frameLength Input: Encoder frameLength. output core encoder frameLength. + * \param aot Input: Desired AOT. output AOT to be used after parameter checking. + * \param delay Input: core encoder delay. Output: total delay because of SBR. + * \param transformFactor The core encoder transform factor (blockswitching). + * \param headerPeriod Repetition rate of the SBR header: + * - (-1) means intern configuration. + * - (1-10) corresponds to header repetition rate in frames. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_Init( + HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], + int noElements, + INT_PCM *inputBuffer, + INT *coreBandwidth, + INT *inputBufferOffset, + INT *numChannels, + INT *sampleRate, + UINT *downSampleFactor, + INT *frameLength, + AUDIO_OBJECT_TYPE aot, + int *delay, + int transformFactor, + const int headerPeriod, + ULONG statesInitFlag + ); + +/** + * \brief Do delay line buffers housekeeping. To be called after each encoded audio frame. + * \param hEnvEnc SBR Encoder handle. + * \param timeBuffer Pointer to the encoder audio buffer. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hEnvEnc, + INT_PCM *timeBuffer + ); + +/** + * \brief Close SBR encoder instance. + * \param phEbrEncoder Handle of SBR encoder instance to be closed. + * \return void + */ +void sbrEncoder_Close(HANDLE_SBR_ENCODER *phEbrEncoder); + +/** + * \brief Encode SBR data of one complete audio frame. + * \param hEnvEncoder Handle of SBR encoder instance. + * \param samples Time samples, always interleaved. + * \param timeInStride Channel stride factor of samples buffer. + * \param sbrDataBits Size of SBR payload in bits. + * \param sbrData SBR payload. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, + INT_PCM *samples, + UINT timeInStride, + UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE] + ); + +/** + * \brief Write SBR headers of one SBR element. + * \param sbrEncoder Handle of the SBR encoder instance. + * \param hBs Handle of bit stream handle to write SBR header to. + * \param element_index Index of the SBR element which header should be written. + * \param fSendHeaders Flag indicating that the SBR encoder should send more headers in the SBR payload or not. + * \return void + */ +void sbrEncoder_GetHeader(HANDLE_SBR_ENCODER sbrEncoder, + HANDLE_FDK_BITSTREAM hBs, + INT element_index, + int fSendHeaders); + +/** + * \brief SBR encoder bitrate estimation. + * \param hSbrEncoder SBR encoder handle. + * \return Estimated bitrate. + */ +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder); + + +/** + * \brief Delay between input data and downsampled output data. + * \param hSbrEncoder SBR encoder handle. + * \return Delay. + */ +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Get decoder library version info. + * \param info Pointer to an allocated LIB_INFO struct, where library info is written to. + * \return 0 on sucess. + */ +INT sbrEncoder_GetLibInfo(LIB_INFO *info); + +void sbrPrintRAM(void); + +void sbrPrintROM(void); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef __SBR_MAIN_H */ diff --git a/libSBRenc/src/bit_sbr.cpp b/libSBRenc/src/bit_sbr.cpp new file mode 100644 index 00000000..9200e014 --- /dev/null +++ b/libSBRenc/src/bit_sbr.cpp @@ -0,0 +1,1057 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief SBR bit writing routines +*/ + + +#include "bit_sbr.h" + +#include "code_env.h" +#include "cmondata.h" +#include "sbr.h" + +#include "ps_main.h" + +typedef enum { + SBR_ID_SCE = 1, + SBR_ID_CPE +} SBR_ELEMENT_TYPE; + + +static INT encodeSbrData (HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, + SBR_ELEMENT_TYPE sbrElem, + INT coupling, + UINT sbrSyntaxFlags); + +static INT encodeSbrHeader (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData); + + +static INT encodeSbrHeaderData (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT encodeSbrSingleChannelElement (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream + ,HANDLE_PARAMETRIC_STEREO hParametricStereo + ,UINT sbrSyntaxFlags + ); + + + +static INT encodeSbrChannelPairElement (HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream, + INT coupling); + + +static INT encodeSbrGrid (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static int encodeLowDelaySbrGrid ( HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + int transmitFreqs); + +static INT encodeSbrDtdf (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT writeNoiseLevelData (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + INT coupling); + +static INT writeEnvelopeData (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + INT coupling); + +static INT writeSyntheticCodingData (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + + +static INT encodeExtendedData (HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream); + + + +static INT getSbrExtendedDataSize (HANDLE_PARAMETRIC_STEREO hParametricStereo); + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvSingleChannelElement + description: writes pure SBR single channel data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT +FDKsbrEnc_WriteEnvSingleChannelElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_COMMON_DATA cmonData, + UINT sbrSyntaxFlags + ) + +{ + INT payloadBits = 0; + + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if (sbrEnvData != NULL) { + + /* write header */ + payloadBits += encodeSbrHeader (sbrHeaderData, + sbrBitstreamData, + cmonData); + + + /* write data */ + payloadBits += encodeSbrData (sbrEnvData, + NULL, + hParametricStereo, + cmonData, + SBR_ID_SCE, + 0, + sbrSyntaxFlags); + + } + return payloadBits; +} + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvChannelPairElement + description: writes pure SBR channel pair data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT +FDKsbrEnc_WriteEnvChannelPairElement (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, + UINT sbrSyntaxFlags) + +{ + INT payloadBits = 0; + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if ((sbrEnvDataLeft != NULL) && (sbrEnvDataRight != NULL)) { + + /* write header */ + payloadBits += encodeSbrHeader (sbrHeaderData, + sbrBitstreamData, + cmonData); + + /* write data */ + payloadBits += encodeSbrData (sbrEnvDataLeft, + sbrEnvDataRight, + hParametricStereo, + cmonData, + SBR_ID_CPE, + sbrHeaderData->coupling, + sbrSyntaxFlags); + + } + return payloadBits; +} + +INT +FDKsbrEnc_CountSbrChannelPairElement (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, + UINT sbrSyntaxFlags) +{ + INT payloadBits; + INT bitPos = FDKgetValidBits(&cmonData->sbrBitbuf); + + payloadBits = FDKsbrEnc_WriteEnvChannelPairElement(sbrHeaderData, + hParametricStereo, + sbrBitstreamData, + sbrEnvDataLeft, + sbrEnvDataRight, + cmonData, + sbrSyntaxFlags); + + FDKpushBack(&cmonData->sbrBitbuf, (FDKgetValidBits(&cmonData->sbrBitbuf) - bitPos) ); + + return payloadBits; +} + + +void sbrEncoder_GetHeader(SBR_ENCODER *sbrEncoder, + HANDLE_FDK_BITSTREAM hBs, + INT element_index, + int fSendHeaders) +{ + encodeSbrHeaderData (&sbrEncoder->sbrElement[element_index]->sbrHeaderData, hBs); + + if (fSendHeaders == 0) { + /* Prevent header being embedded into the SBR payload. */ + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.NrSendHeaderData = -1; + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.HeaderActive = 0; + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.CountSendHeaderData = -1; + } +} + + +/***************************************************************************** + + functionname: encodeSbrHeader + description: encodes SBR Header information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +encodeSbrHeader (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData) +{ + INT payloadBits = 0; + + if (sbrBitstreamData->HeaderActive) { + payloadBits += FDKwriteBits (&cmonData->sbrBitbuf, 1, 1); + payloadBits += encodeSbrHeaderData (sbrHeaderData, + &cmonData->sbrBitbuf); + } + else { + payloadBits += FDKwriteBits (&cmonData->sbrBitbuf, 0, 1); + } + + cmonData->sbrHdrBits = payloadBits; + + return payloadBits; +} + + + +/***************************************************************************** + + functionname: encodeSbrHeaderData + description: writes sbr_header() + bs_protocol_version through bs_header_extra_2 + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +encodeSbrHeaderData (HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream) + +{ + INT payloadBits = 0; + if (sbrHeaderData != NULL) { + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_amp_res, + SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_start_frequency, + SI_SBR_START_FREQ_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_stop_frequency, + SI_SBR_STOP_FREQ_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_xover_band, + SI_SBR_XOVER_BAND_BITS); + + payloadBits += FDKwriteBits (hBitStream, 0, + SI_SBR_RESERVED_BITS); + + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->header_extra_1, + SI_SBR_HEADER_EXTRA_1_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->header_extra_2, + SI_SBR_HEADER_EXTRA_2_BITS); + + + if (sbrHeaderData->header_extra_1) { + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->freqScale, + SI_SBR_FREQ_SCALE_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->alterScale, + SI_SBR_ALTER_SCALE_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_noise_bands, + SI_SBR_NOISE_BANDS_BITS); + } /* sbrHeaderData->header_extra_1 */ + + if (sbrHeaderData->header_extra_2) { + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_limiter_bands, + SI_SBR_LIMITER_BANDS_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_limiter_gains, + SI_SBR_LIMITER_GAINS_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_interpol_freq, + SI_SBR_INTERPOL_FREQ_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrHeaderData->sbr_smoothing_length, + SI_SBR_SMOOTHING_LENGTH_BITS); + + } /* sbrHeaderData->header_extra_2 */ + } /* sbrHeaderData != NULL */ + + return payloadBits; +} + + +/***************************************************************************** + + functionname: encodeSbrData + description: encodes sbr Data information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +encodeSbrData (HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, + SBR_ELEMENT_TYPE sbrElem, + INT coupling, + UINT sbrSyntaxFlags) +{ + INT payloadBits = 0; + + switch (sbrElem) { + case SBR_ID_SCE: + payloadBits += encodeSbrSingleChannelElement (sbrEnvDataLeft, &cmonData->sbrBitbuf, hParametricStereo, sbrSyntaxFlags); + break; + case SBR_ID_CPE: + payloadBits += encodeSbrChannelPairElement (sbrEnvDataLeft, sbrEnvDataRight, hParametricStereo, &cmonData->sbrBitbuf, coupling); + break; + default: + /* we never should apply SBR to any other element type */ + FDK_ASSERT (0); + } + + cmonData->sbrDataBits = payloadBits; + + return payloadBits; +} + +#define MODE_FREQ_TANS 1 +#define MODE_NO_FREQ_TRAN 0 +#define LD_TRANSMISSION MODE_FREQ_TANS +static int encodeFreqs (int mode) { + return ((mode & MODE_FREQ_TANS) ? 1 : 0); +} + + +/***************************************************************************** + + functionname: encodeSbrSingleChannelElement + description: encodes sbr SCE information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +encodeSbrSingleChannelElement (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream + ,HANDLE_PARAMETRIC_STEREO hParametricStereo + ,UINT sbrSyntaxFlags + ) +{ + INT i, payloadBits = 0; + + payloadBits += FDKwriteBits (hBitStream, 0, SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + if (sbrEnvData->ldGrid) { + if ( sbrEnvData->hSbrBSGrid->frameClass != FIXFIXonly ) { + /* encode normal SbrGrid */ + payloadBits += encodeSbrGrid (sbrEnvData, hBitStream); + } else { + /* use FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid ( sbrEnvData, hBitStream, encodeFreqs(LD_TRANSMISSION)); + } + } + else + { + if (sbrSyntaxFlags & SBR_SYNTAX_SCALABLE) { + payloadBits += FDKwriteBits (hBitStream, 1, SI_SBR_COUPLING_BITS); + } + payloadBits += encodeSbrGrid (sbrEnvData, hBitStream); + } + + payloadBits += encodeSbrDtdf (sbrEnvData, hBitStream); + + for (i = 0; i < sbrEnvData->noOfnoisebands; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->sbr_invf_mode_vec[i], SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData (sbrEnvData, hBitStream, 0); + payloadBits += writeNoiseLevelData (sbrEnvData, hBitStream, 0); + + payloadBits += writeSyntheticCodingData (sbrEnvData,hBitStream); + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + + +/***************************************************************************** + + functionname: encodeSbrChannelPairElement + description: encodes sbr CPE information + returns: + input: + output: + +*****************************************************************************/ +static INT +encodeSbrChannelPairElement (HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream, + INT coupling) +{ + INT payloadBits = 0; + INT i = 0; + + payloadBits += FDKwriteBits (hBitStream, 0, SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + payloadBits += FDKwriteBits (hBitStream, coupling, SI_SBR_COUPLING_BITS); + + if (coupling) { + if (sbrEnvDataLeft->ldGrid) { + if ( sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly ) { + /* normal SbrGrid */ + payloadBits += encodeSbrGrid (sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid ( sbrEnvDataLeft, hBitStream, encodeFreqs(LD_TRANSMISSION)); + } + } else + payloadBits += encodeSbrGrid (sbrEnvDataLeft, hBitStream); + + payloadBits += encodeSbrDtdf (sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf (sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData (sbrEnvDataLeft, hBitStream,1); + payloadBits += writeNoiseLevelData (sbrEnvDataLeft, hBitStream,1); + payloadBits += writeEnvelopeData (sbrEnvDataRight, hBitStream,1); + payloadBits += writeNoiseLevelData (sbrEnvDataRight, hBitStream,1); + + payloadBits += writeSyntheticCodingData (sbrEnvDataLeft,hBitStream); + payloadBits += writeSyntheticCodingData (sbrEnvDataRight,hBitStream); + + } else { /* no coupling */ + FDK_ASSERT(sbrEnvDataLeft->ldGrid == sbrEnvDataRight->ldGrid); + + if (sbrEnvDataLeft->ldGrid || sbrEnvDataRight->ldGrid) { + /* sbrEnvDataLeft (left channel) */ + if ( sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid (sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid ( sbrEnvDataLeft, hBitStream, encodeFreqs(LD_TRANSMISSION)); + } + + /* sbrEnvDataRight (right channel) */ + if ( sbrEnvDataRight->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid (sbrEnvDataRight, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid ( sbrEnvDataRight, hBitStream, encodeFreqs(LD_TRANSMISSION)); + } + } else + { + payloadBits += encodeSbrGrid (sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrGrid (sbrEnvDataRight, hBitStream); + } + payloadBits += encodeSbrDtdf (sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf (sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + for (i = 0; i < sbrEnvDataRight->noOfnoisebands; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvDataRight->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData (sbrEnvDataLeft, hBitStream,0); + payloadBits += writeEnvelopeData (sbrEnvDataRight, hBitStream,0); + payloadBits += writeNoiseLevelData (sbrEnvDataLeft, hBitStream,0); + payloadBits += writeNoiseLevelData (sbrEnvDataRight, hBitStream,0); + + payloadBits += writeSyntheticCodingData (sbrEnvDataLeft,hBitStream); + payloadBits += writeSyntheticCodingData (sbrEnvDataRight,hBitStream); + + } /* coupling */ + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + +static INT ceil_ln2(INT x) +{ + INT tmp=-1; + while((1<<++tmp) < x); + return(tmp); +} + + +/***************************************************************************** + + functionname: encodeSbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; else counts them only + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static INT +encodeSbrGrid (HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream) +{ + INT payloadBits = 0; + INT i, temp; + INT bufferFrameStart = sbrEnvData->hSbrBSGrid->bufferFrameStart; + INT numberTimeSlots = sbrEnvData->hSbrBSGrid->numberTimeSlots; + + if (sbrEnvData->ldGrid) + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS_LD); + else + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS); + + switch (sbrEnvData->hSbrBSGrid->frameClass) { + case FIXFIXonly: + FDK_ASSERT(0 /* Fatal error in encodeSbrGrid! */); + break; + case FIXFIX: + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_env); + payloadBits += FDKwriteBits (hBitStream, temp, SBR_ENV_BITS); + if ((sbrEnvData->ldGrid) && (sbrEnvData->hSbrBSGrid->bs_num_env==1)) + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->currentAmpResFF, SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->v_f[0], SBR_RES_BITS); + + break; + + case FIXVAR: + case VARFIX: + if (sbrEnvData->hSbrBSGrid->frameClass == FIXVAR) + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - (bufferFrameStart + numberTimeSlots); + else + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - bufferFrameStart; + + payloadBits += FDKwriteBits (hBitStream, temp, SBR_ABS_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->n, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord[i] - 2) >> 1; + payloadBits += FDKwriteBits (hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->n + 2); + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n + 1; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], + SBR_RES_BITS); + } + break; + + case VARVAR: + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_0 - bufferFrameStart; + payloadBits += FDKwriteBits (hBitStream, temp, SBR_ABS_BITS); + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_1 - (bufferFrameStart + numberTimeSlots); + payloadBits += FDKwriteBits (hBitStream, temp, SBR_ABS_BITS); + + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_0, SBR_NUM_BITS); + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_1, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_0; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_0[i] - 2) >> 1; + payloadBits += FDKwriteBits (hBitStream, temp, SBR_REL_BITS); + } + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_1; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_1[i] - 2) >> 1; + payloadBits += FDKwriteBits (hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 2); + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + temp = sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 1; + + for (i = 0; i < temp; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->v_fLR[i], + SBR_RES_BITS); + } + break; + } + + return payloadBits; +} + +#define SBR_CLA_BITS_LD 1 +/***************************************************************************** + + functionname: encodeLowDelaySbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; + else counts them only + (this function only write the FIXFIXonly Bitstream data) + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static int +encodeLowDelaySbrGrid ( HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + int transmitFreqs + ) +{ + int payloadBits = 0; + int i; + + /* write FIXFIXonly Grid */ + /* write frameClass [1 bit] for FIXFIXonly Grid */ + payloadBits += FDKwriteBits(hBitStream, 1, SBR_CLA_BITS_LD); + + /* absolute Borders are fix: 0,X,X,X,nTimeSlots; so we dont have to transmit them */ + /* only transmit the transient position! */ + /* with this info (b1) we can reconstruct the Frame on Decoder side : */ + /* border[0] = 0; border[1] = b1; border[2]=b1+2; border[3] = nrTimeSlots */ + + /* use 3 or 4bits for transient border (border) */ + if (sbrEnvData->hSbrBSGrid->numberTimeSlots == 8) + payloadBits += FDKwriteBits ( hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 3); + else + payloadBits += FDKwriteBits ( hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 4); + + if (transmitFreqs) { + /* write FreqRes grid */ + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_env; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], SBR_RES_BITS); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrDtdf + description: writes bits that describes the direction of the envelopes of a frame + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +encodeSbrDtdf (HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream) +{ + INT i, payloadBits = 0, noOfNoiseEnvelopes; + + noOfNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < sbrEnvData->noOfEnvelopes; ++i) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->domain_vec[i], SBR_DIR_BITS); + } + for (i = 0; i < noOfNoiseEnvelopes; ++i) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->domain_vec_noise[i], SBR_DIR_BITS); + } + + return payloadBits; +} + + +/***************************************************************************** + + functionname: writeNoiseLevelData + description: writes bits corresponding to the noise-floor-level + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +writeNoiseLevelData (HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, INT coupling) +{ + INT j, i, payloadBits = 0; + INT nNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < nNoiseEnvelopes; i++) { + switch (sbrEnvData->domain_vec_noise[i]) { + case FREQ: + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits_balance); + } else { + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits); + } + + for (j = 1 + i * sbrEnvData->noOfnoisebands; j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseBalanceFreqC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceFreqL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseLevelFreqC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelFreqL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseFreqC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseFreqL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + + case TIME: + for (j = i * sbrEnvData->noOfnoisebands; j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseBalanceTimeC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceTimeL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseLevelTimeC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelTimeL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableNoiseLevelTimeC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelTimeL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + } + } + return payloadBits; +} + + +/***************************************************************************** + + functionname: writeEnvelopeData + description: writes bits corresponding to the envelope + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT +writeEnvelopeData (HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, INT coupling) +{ + INT payloadBits = 0, j, i, delta; + + for (j = 0; j < sbrEnvData->noOfEnvelopes; j++) { /* loop over all envelopes */ + if (sbrEnvData->domain_vec[j] == FREQ) { + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->ienvelope[j][0], sbrEnvData->si_sbr_start_env_bits_balance); + } else { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->ienvelope[j][0], sbrEnvData->si_sbr_start_env_bits); + } + } + + for (i = 1 - sbrEnvData->domain_vec[j]; i < sbrEnvData->noScfBands[j]; i++) { + delta = sbrEnvData->ienvelope[j][i]; + if (coupling && sbrEnvData->balance) { + FDK_ASSERT (fixp_abs (delta) <= sbrEnvData->codeBookScfLavBalance); + } else { + FDK_ASSERT (fixp_abs (delta) <= sbrEnvData->codeBookScfLav); + } + if (coupling) { + if (sbrEnvData->balance) { + if (sbrEnvData->domain_vec[j]) { + /* coupling && balance && TIME */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableBalanceTimeC[delta + sbrEnvData->codeBookScfLavBalance], + sbrEnvData->hufftableBalanceTimeL[delta + sbrEnvData->codeBookScfLavBalance]); + } else { + /* coupling && balance && FREQ */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableBalanceFreqC[delta + sbrEnvData->codeBookScfLavBalance], + sbrEnvData->hufftableBalanceFreqL[delta + sbrEnvData->codeBookScfLavBalance]); + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* coupling && !balance && TIME */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableLevelTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableLevelTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* coupling && !balance && FREQ */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableLevelFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableLevelFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* !coupling && TIME */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* !coupling && FREQ */ + payloadBits += FDKwriteBits (hBitStream, + sbrEnvData->hufftableFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } + } + return payloadBits; +} + + +/***************************************************************************** + + functionname: encodeExtendedData + description: writes bits corresponding to the extended data + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeExtendedData (HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream) +{ + INT extDataSize; + INT payloadBits = 0; + + extDataSize = getSbrExtendedDataSize(hParametricStereo); + + + if (extDataSize != 0) { + INT maxExtSize = (1<addHarmonicFlag, 1); + + if (sbrEnvData->addHarmonicFlag) { + for (i = 0; i < sbrEnvData->noHarmonics; i++) { + payloadBits += FDKwriteBits (hBitStream, sbrEnvData->addHarmonic[i], 1); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: getSbrExtendedDataSize + description: counts the number of bits needed for encoding the + extended data (including extension id) + + returns: number of bits needed for the extended data + input: + output: + +*****************************************************************************/ +static INT +getSbrExtendedDataSize (HANDLE_PARAMETRIC_STEREO hParametricStereo) +{ + INT extDataBits = 0; + + /* add your new extended data counting methods here */ + + /* + no extended data + */ + + if(hParametricStereo){ + /* PS extended data */ + extDataBits += SI_SBR_EXTENSION_ID_BITS; + extDataBits += FDKsbrEnc_PSEnc_WritePSData(hParametricStereo, NULL); + } + + return (extDataBits+7) >> 3; +} + + + + + diff --git a/libSBRenc/src/bit_sbr.h b/libSBRenc/src/bit_sbr.h new file mode 100644 index 00000000..de4ac89a --- /dev/null +++ b/libSBRenc/src/bit_sbr.h @@ -0,0 +1,258 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief SBR bit writing +*/ +#ifndef __BIT_SBR_H +#define __BIT_SBR_H + +#include "sbr_def.h" +#include "cmondata.h" +#include "fram_gen.h" + +struct SBR_ENV_DATA; + +struct SBR_BITSTREAM_DATA +{ + INT TotalBits; + INT PayloadBits; + INT FillBits; + INT HeaderActive; + INT NrSendHeaderData; /**< input from commandline */ + INT CountSendHeaderData; /**< modulo count. If < 0 then no counting is done (no SBR headers) */ +}; + +typedef struct SBR_BITSTREAM_DATA *HANDLE_SBR_BITSTREAM_DATA; + +struct SBR_HEADER_DATA +{ + AMP_RES sbr_amp_res; + INT sbr_start_frequency; + INT sbr_stop_frequency; + INT sbr_xover_band; + INT sbr_noise_bands; + INT sbr_data_extra; + INT header_extra_1; + INT header_extra_2; + INT sbr_lc_stereo_mode; + INT sbr_limiter_bands; + INT sbr_limiter_gains; + INT sbr_interpol_freq; + INT sbr_smoothing_length; + INT alterScale; + INT freqScale; + + /* + element of channelpairelement + */ + INT coupling; + INT prev_coupling; + + /* + element of singlechannelelement + */ + +}; +typedef struct SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + +struct SBR_ENV_DATA +{ + + INT sbr_xpos_ctrl; + FREQ_RES freq_res_fixfix[2]; + UCHAR fResTransIsLow; + + INVF_MODE sbr_invf_mode; + INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES]; + + XPOS_MODE sbr_xpos_mode; + + INT ienvelope[MAX_ENVELOPES][MAX_FREQ_COEFFS]; + + INT codeBookScfLavBalance; + INT codeBookScfLav; + const INT *hufftableTimeC; + const INT *hufftableFreqC; + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const INT *hufftableLevelTimeC; + const INT *hufftableBalanceTimeC; + const INT *hufftableLevelFreqC; + const INT *hufftableBalanceFreqC; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + + const UCHAR *hufftableNoiseTimeL; + const INT *hufftableNoiseTimeC; + const UCHAR *hufftableNoiseFreqL; + const INT *hufftableNoiseFreqC; + + const UCHAR *hufftableNoiseLevelTimeL; + const INT *hufftableNoiseLevelTimeC; + const UCHAR *hufftableNoiseBalanceTimeL; + const INT *hufftableNoiseBalanceTimeC; + const UCHAR *hufftableNoiseLevelFreqL; + const INT *hufftableNoiseLevelFreqC; + const UCHAR *hufftableNoiseBalanceFreqL; + const INT *hufftableNoiseBalanceFreqC; + + HANDLE_SBR_GRID hSbrBSGrid; + + INT noHarmonics; + INT addHarmonicFlag; + UCHAR addHarmonic[MAX_FREQ_COEFFS]; + + + /* calculated helper vars */ + INT si_sbr_start_env_bits_balance; + INT si_sbr_start_env_bits; + INT si_sbr_start_noise_bits_balance; + INT si_sbr_start_noise_bits; + + INT noOfEnvelopes; + INT noScfBands[MAX_ENVELOPES]; + INT domain_vec[MAX_ENVELOPES]; + INT domain_vec_noise[MAX_ENVELOPES]; + SCHAR sbr_noise_levels[MAX_FREQ_COEFFS]; + INT noOfnoisebands; + + INT balance; + AMP_RES init_sbr_amp_res; + AMP_RES currentAmpResFF; + FIXP_DBL ton_HF[SBR_GLOBAL_TONALITY_VALUES]; /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + FIXP_DBL global_tonality; + + /* extended data */ + INT extended_data; + INT extension_size; + INT extension_id; + UCHAR extended_data_buffer[SBR_EXTENDED_DATA_MAX_CNT]; + + UCHAR ldGrid; +}; +typedef struct SBR_ENV_DATA *HANDLE_SBR_ENV_DATA; + + + +INT FDKsbrEnc_WriteEnvSingleChannelElement(struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvData, + struct COMMON_DATA *cmonData, + UINT sbrSyntaxFlags); + + +INT FDKsbrEnc_WriteEnvChannelPairElement(struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, + struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, + UINT sbrSyntaxFlags); + + + +INT FDKsbrEnc_CountSbrChannelPairElement (struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, + struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, + UINT sbrSyntaxFlags); + + + +/* debugging and tuning functions */ + +/*#define SBR_ENV_STATISTICS */ + + +/*#define SBR_PAYLOAD_MONITOR*/ + +#endif diff --git a/libSBRenc/src/cmondata.h b/libSBRenc/src/cmondata.h new file mode 100644 index 00000000..32e6993c --- /dev/null +++ b/libSBRenc/src/cmondata.h @@ -0,0 +1,110 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Core Coder's and SBR's shared data structure definition +*/ +#ifndef __SBR_CMONDATA_H +#define __SBR_CMONDATA_H + +#include "FDK_bitstream.h" + + +struct COMMON_DATA { + INT sbrHdrBits; /**< number of SBR header bits */ + INT sbrDataBits; /**< number of SBR data bits */ + INT sbrFillBits; /**< number of SBR fill bits */ + FDK_BITSTREAM sbrBitbuf; /**< the SBR data bitbuffer */ + FDK_BITSTREAM tmpWriteBitbuf; /**< helper var for writing header*/ + INT xOverFreq; /**< the SBR crossover frequency */ + INT dynBwEnabled; /**< indicates if dynamic bandwidth is enabled */ + INT sbrNumChannels; /**< number of channels (meaning mono or stereo) */ + INT dynXOverFreqEnc; /**< encoder dynamic crossover frequency */ +}; + +typedef struct COMMON_DATA *HANDLE_COMMON_DATA; + + + +#endif diff --git a/libSBRenc/src/code_env.cpp b/libSBRenc/src/code_env.cpp new file mode 100644 index 00000000..e1a28d5f --- /dev/null +++ b/libSBRenc/src/code_env.cpp @@ -0,0 +1,641 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "code_env.h" +#include "sbr_rom.h" + +/***************************************************************************** + + functionname: FDKsbrEnc_InitSbrHuffmanTables + description: initializes Huffman Tables dependent on chosen amp_res + returns: error handle + input: + output: + +*****************************************************************************/ +INT +FDKsbrEnc_InitSbrHuffmanTables (HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res) +{ + if ( (!henv) || (!hnoise) || (!sbrEnvData) ) + return (1); /* not init. */ + + sbrEnvData->init_sbr_amp_res = amp_res; + + switch (amp_res) { + case SBR_AMP_RES_3_0: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC11T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL11T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL11F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE11; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV11; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_env_bits_balance = SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0; + break; + + case SBR_AMP_RES_1_5: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC10T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL10T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL10F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC10F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL10F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL10F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE10; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV10; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_1_5; + sbrEnvData->si_sbr_start_env_bits_balance = SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5; + break; + + default: + return (1); /* undefined amp_res mode */ + } + + /* these are common to both amp_res values */ + /*Noise data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableNoiseLevelTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseLevelTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseBalanceTimeC = bookSbrNoiseBalanceC11T; + sbrEnvData->hufftableNoiseBalanceTimeL = bookSbrNoiseBalanceL11T; + + sbrEnvData->hufftableNoiseLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableNoiseBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableNoiseBalanceFreqL = bookSbrEnvBalanceL11F; + + + /*Right/Left - coding */ + sbrEnvData->hufftableNoiseTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->si_sbr_start_noise_bits = SI_SBR_START_NOISE_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_noise_bits_balance = SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0; + + + /* init envelope tables and codebooks */ + henv->codeBookScfLavBalanceTime = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavBalanceFreq = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavLevelTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavLevelFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + + henv->hufftableLevelTimeL = sbrEnvData->hufftableLevelTimeL; + henv->hufftableBalanceTimeL = sbrEnvData->hufftableBalanceTimeL; + henv->hufftableTimeL = sbrEnvData->hufftableTimeL; + henv->hufftableLevelFreqL = sbrEnvData->hufftableLevelFreqL; + henv->hufftableBalanceFreqL = sbrEnvData->hufftableBalanceFreqL; + henv->hufftableFreqL = sbrEnvData->hufftableFreqL; + + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + + henv->start_bits = sbrEnvData->si_sbr_start_env_bits; + henv->start_bits_balance = sbrEnvData->si_sbr_start_env_bits_balance; + + + /* init noise tables and codebooks */ + + hnoise->codeBookScfLavBalanceTime = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavBalanceFreq = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavLevelTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavLevelFreq = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavFreq = CODE_BOOK_SCF_LAV11; + + hnoise->hufftableLevelTimeL = sbrEnvData->hufftableNoiseLevelTimeL; + hnoise->hufftableBalanceTimeL = sbrEnvData->hufftableNoiseBalanceTimeL; + hnoise->hufftableTimeL = sbrEnvData->hufftableNoiseTimeL; + hnoise->hufftableLevelFreqL = sbrEnvData->hufftableNoiseLevelFreqL; + hnoise->hufftableBalanceFreqL = sbrEnvData->hufftableNoiseBalanceFreqL; + hnoise->hufftableFreqL = sbrEnvData->hufftableNoiseFreqL; + + + hnoise->start_bits = sbrEnvData->si_sbr_start_noise_bits; + hnoise->start_bits_balance = sbrEnvData->si_sbr_start_noise_bits_balance; + + /* No delta coding in time from the previous frame due to 1.5dB FIx-FIX rule */ + henv->upDate = 0; + hnoise->upDate = 0; + return (0); +} + +/******************************************************************************* + Functionname: indexLow2High + ******************************************************************************* + + Description: Nice small patch-functions in order to cope with non-factor-2 + ratios between high-res and low-res + + Arguments: INT offset, INT index, FREQ_RES res + + Return: INT + +*******************************************************************************/ +static INT indexLow2High(INT offset, INT index, FREQ_RES res) +{ + + if(res == FREQ_RES_LOW) + { + if (offset >= 0) + { + if (index < offset) + return(index); + else + return(2*index - offset); + } + else + { + offset = -offset; + if (index < offset) + return(2*index+index); + else + return(2*index + offset); + } + } + else + return(index); +} + + + +/******************************************************************************* + Functionname: mapLowResEnergyVal + ******************************************************************************* + + Description: + + Arguments: INT currVal,INT* prevData, INT offset, INT index, FREQ_RES res + + Return: none + +*******************************************************************************/ +static void mapLowResEnergyVal(SCHAR currVal, SCHAR* prevData, INT offset, INT index, FREQ_RES res) +{ + + if(res == FREQ_RES_LOW) + { + if (offset >= 0) + { + if(index < offset) + prevData[index] = currVal; + else + { + prevData[2*index - offset] = currVal; + prevData[2*index+1 - offset] = currVal; + } + } + else + { + offset = -offset; + if (index < offset) + { + prevData[3*index] = currVal; + prevData[3*index+1] = currVal; + prevData[3*index+2] = currVal; + } + else + { + prevData[2*index + offset] = currVal; + prevData[2*index + 1 + offset] = currVal; + } + } + } + else + prevData[index] = currVal; +} + + + +/******************************************************************************* + Functionname: computeBits + ******************************************************************************* + + Description: + + Arguments: INT delta, + INT codeBookScfLavLevel, + INT codeBookScfLavBalance, + const UCHAR * hufftableLevel, + const UCHAR * hufftableBalance, INT coupling, INT channel) + + Return: INT + +*******************************************************************************/ +static INT +computeBits (SCHAR *delta, + INT codeBookScfLavLevel, + INT codeBookScfLavBalance, + const UCHAR * hufftableLevel, + const UCHAR * hufftableBalance, INT coupling, INT channel) +{ + INT index; + INT delta_bits = 0; + + if (coupling) { + if (channel == 1) + { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavBalance); + else + index = fixMin(*delta, codeBookScfLavBalance); + + if (index != *delta) { + *delta = index; + return (10000); + } + + delta_bits = hufftableBalance[index + codeBookScfLavBalance]; + } + else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + } + else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + + return (delta_bits); +} + + + + +/******************************************************************************* + Functionname: FDKsbrEnc_codeEnvelope + ******************************************************************************* + + Description: + + Arguments: INT *sfb_nrg, + const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE * h_sbrCodeEnvelope, + INT *directionVec, INT scalable, INT nEnvelopes, INT channel, + INT headerActive) + + Return: none + h_sbrCodeEnvelope->sfb_nrg_prev is modified ! + sfb_nrg is modified + h_sbrCodeEnvelope->update is modfied ! + *directionVec is modified + +*******************************************************************************/ +void +FDKsbrEnc_codeEnvelope(SCHAR *sfb_nrg, + const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE *h_sbrCodeEnvelope, + INT *directionVec, + INT coupling, + INT nEnvelopes, + INT channel, + INT headerActive) +{ + INT i, no_of_bands, band; + FIXP_DBL tmp1,tmp2,tmp3,dF_edge_1stEnv; + SCHAR *ptr_nrg; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + INT offset = h_sbrCodeEnvelope->offset; + INT envDataTableCompFactor; + + INT delta_F_bits = 0, delta_T_bits = 0; + INT use_dT; + + SCHAR delta_F[MAX_FREQ_COEFFS]; + SCHAR delta_T[MAX_FREQ_COEFFS]; + SCHAR last_nrg, curr_nrg; + + tmp1 = FL2FXCONST_DBL(0.5f) >> (DFRACT_BITS-16-1); + tmp2 = h_sbrCodeEnvelope->dF_edge_1stEnv >> (DFRACT_BITS-16); + tmp3 = (FIXP_DBL)(((INT)(LONG)h_sbrCodeEnvelope->dF_edge_incr*h_sbrCodeEnvelope->dF_edge_incr_fac) >> (DFRACT_BITS-16)); + + dF_edge_1stEnv = tmp1 + tmp2 + tmp3; + + if (coupling) { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavLevelTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavLevelFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavBalanceTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavBalanceFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableLevelTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableBalanceTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableLevelFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableBalanceFreqL; + } + else { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableFreqL; + } + + if(coupling == 1 && channel == 1) + envDataTableCompFactor = 1; /*should be one when the new huffman-tables are ready*/ + else + envDataTableCompFactor = 0; + + + if (h_sbrCodeEnvelope->deltaTAcrossFrames == 0) + h_sbrCodeEnvelope->upDate = 0; + + /* no delta coding in time in case of a header */ + if (headerActive) + h_sbrCodeEnvelope->upDate = 0; + + + for (i = 0; i < nEnvelopes; i++) + { + if (freq_res[i] == FREQ_RES_HIGH) + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + else + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW]; + + + ptr_nrg = sfb_nrg; + curr_nrg = *ptr_nrg; + + delta_F[0] = curr_nrg >> envDataTableCompFactor; + + if (coupling && channel == 1) + delta_F_bits = h_sbrCodeEnvelope->start_bits_balance; + else + delta_F_bits = h_sbrCodeEnvelope->start_bits; + + + if(h_sbrCodeEnvelope->upDate != 0) + { + delta_T[0] = (curr_nrg - h_sbrCodeEnvelope->sfb_nrg_prev[0]) >> envDataTableCompFactor; + + delta_T_bits = computeBits (&delta_T[0], + codeBookScfLavLevelTime, + codeBookScfLavBalanceTime, + hufftableLevelTimeL, + hufftableBalanceTimeL, coupling, channel); + } + + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, 0, freq_res[i]); + + /* ensure that nrg difference is not higher than codeBookScfLavXXXFreq */ + if ( coupling && channel == 1 ) { + for (band = no_of_bands - 1; band > 0; band--) { + if ( ptr_nrg[band] - ptr_nrg[band-1] > codeBookScfLavBalanceFreq ) { + ptr_nrg[band-1] = ptr_nrg[band] - codeBookScfLavBalanceFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if ( ptr_nrg[band-1] - ptr_nrg[band] > codeBookScfLavBalanceFreq ) { + ptr_nrg[band] = ptr_nrg[band-1] - codeBookScfLavBalanceFreq; + } + } + } + else { + for (band = no_of_bands - 1; band > 0; band--) { + if ( ptr_nrg[band] - ptr_nrg[band-1] > codeBookScfLavLevelFreq ) { + ptr_nrg[band-1] = ptr_nrg[band] - codeBookScfLavLevelFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if ( ptr_nrg[band-1] - ptr_nrg[band] > codeBookScfLavLevelFreq ) { + ptr_nrg[band] = ptr_nrg[band-1] - codeBookScfLavLevelFreq; + } + } + } + + + /* Coding loop*/ + for (band = 1; band < no_of_bands; band++) + { + last_nrg = (*ptr_nrg); + ptr_nrg++; + curr_nrg = (*ptr_nrg); + + delta_F[band] = (curr_nrg - last_nrg) >> envDataTableCompFactor; + + delta_F_bits += computeBits (&delta_F[band], + codeBookScfLavLevelFreq, + codeBookScfLavBalanceFreq, + hufftableLevelFreqL, + hufftableBalanceFreqL, coupling, channel); + + if(h_sbrCodeEnvelope->upDate != 0) + { + delta_T[band] = curr_nrg - h_sbrCodeEnvelope->sfb_nrg_prev[indexLow2High(offset, band, freq_res[i])]; + delta_T[band] = delta_T[band] >> envDataTableCompFactor; + } + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, band, freq_res[i]); + + if(h_sbrCodeEnvelope->upDate != 0) + { + delta_T_bits += computeBits (&delta_T[band], + codeBookScfLavLevelTime, + codeBookScfLavBalanceTime, + hufftableLevelTimeL, + hufftableBalanceTimeL, coupling, channel); + } + } + + /* Replace sfb_nrg with deltacoded samples and set flag */ + if (i == 0) { + INT tmp_bits; + tmp_bits = (((delta_T_bits * dF_edge_1stEnv) >> (DFRACT_BITS-18)) + (FIXP_DBL)1) >> 1; + use_dT = (h_sbrCodeEnvelope->upDate != 0 && (delta_F_bits > tmp_bits)); + } + else + use_dT = (delta_T_bits < delta_F_bits && h_sbrCodeEnvelope->upDate != 0); + + if (use_dT) + { + directionVec[i] = TIME; + FDKmemcpy (sfb_nrg, delta_T, no_of_bands * sizeof (SCHAR)); + } + else { + h_sbrCodeEnvelope->upDate = 0; + directionVec[i] = FREQ; + FDKmemcpy (sfb_nrg, delta_F, no_of_bands * sizeof (SCHAR)); + } + sfb_nrg += no_of_bands; + h_sbrCodeEnvelope->upDate = 1; + } + +} + + +/******************************************************************************* + Functionname: FDKsbrEnc_InitSbrCodeEnvelope + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +INT +FDKsbrEnc_InitSbrCodeEnvelope (HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, + INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr) +{ + + FDKmemclear(h_sbrCodeEnvelope,sizeof(SBR_CODE_ENVELOPE)); + + h_sbrCodeEnvelope->deltaTAcrossFrames = deltaTAcrossFrames; + h_sbrCodeEnvelope->dF_edge_1stEnv = dF_edge_1stEnv; + h_sbrCodeEnvelope->dF_edge_incr = dF_edge_incr; + h_sbrCodeEnvelope->dF_edge_incr_fac = 0; + h_sbrCodeEnvelope->upDate = 0; + h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] = nSfb[FREQ_RES_LOW]; + h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH] = nSfb[FREQ_RES_HIGH]; + h_sbrCodeEnvelope->offset = 2*h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] - h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + + return (0); +} diff --git a/libSBRenc/src/code_env.h b/libSBRenc/src/code_env.h new file mode 100644 index 00000000..50a365e6 --- /dev/null +++ b/libSBRenc/src/code_env.h @@ -0,0 +1,153 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief DPCM Envelope coding +*/ + +#ifndef __CODE_ENV_H +#define __CODE_ENV_H + +#include "sbr_def.h" +#include "bit_sbr.h" +#include "fram_gen.h" + +typedef struct +{ + INT offset; + INT upDate; + INT nSfb[2]; + SCHAR sfb_nrg_prev[MAX_FREQ_COEFFS]; + INT deltaTAcrossFrames; + FIXP_DBL dF_edge_1stEnv; + FIXP_DBL dF_edge_incr; + INT dF_edge_incr_fac; + + + INT codeBookScfLavTime; + INT codeBookScfLavFreq; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + + INT start_bits; + INT start_bits_balance; + + + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; +} +SBR_CODE_ENVELOPE; +typedef SBR_CODE_ENVELOPE *HANDLE_SBR_CODE_ENVELOPE; + + + +void +FDKsbrEnc_codeEnvelope (SCHAR *sfb_nrg, + const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE * h_sbrCodeEnvelope, + INT *directionVec, INT coupling, INT nEnvelopes, INT channel, + INT headerActive); + +INT +FDKsbrEnc_InitSbrCodeEnvelope (HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, + INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr); + +INT +FDKsbrEnc_InitSbrHuffmanTables (struct SBR_ENV_DATA* sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res); + +#endif diff --git a/libSBRenc/src/env_bit.cpp b/libSBRenc/src/env_bit.cpp new file mode 100644 index 00000000..ea311835 --- /dev/null +++ b/libSBRenc/src/env_bit.cpp @@ -0,0 +1,250 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#include "env_bit.h" +#include "cmondata.h" + + +#ifndef min +#define min(a,b) ( a < b ? a:b) +#endif + +#ifndef max +#define max(a,b) ( a > b ? a:b) +#endif + +/* ***************************** crcAdvance **********************************/ +/** + * @fn + * @brief updates crc data register + * @return none + * + * This function updates the crc register + * + */ +static void crcAdvance(USHORT crcPoly, + USHORT crcMask, + USHORT *crc, + ULONG bValue, + INT bBits + ) +{ + INT i; + USHORT flag; + + for (i=bBits-1; i>=0; i--) { + flag = ((*crc) & crcMask) ? (1) : (0) ; + flag ^= (bValue & (1<sbrBitbuf, BS_WRITER); + + FDKinitBitStream(&hCmonData->tmpWriteBitbuf, memoryBase, + memorySize, 0, BS_WRITER); + + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) + { /* Init and start CRC region */ + FDKwriteBits (&hCmonData->sbrBitbuf, 0x0, SI_SBR_DRM_CRC_BITS); + FDKcrcInit( hCrcInfo, 0x001d, 0xFFFF, SI_SBR_DRM_CRC_BITS ); + crcRegion = FDKcrcStartReg( hCrcInfo, &hCmonData->sbrBitbuf, 0 ); + } else { + FDKwriteBits (&hCmonData->sbrBitbuf, 0x0, SI_SBR_CRC_BITS); + } + } + + return (crcRegion); +} + + +/* ************************** FDKsbrEnc_AssembleSbrBitstream *******************************/ +/** + * @fn + * @brief Formats the SBR payload + * @return nothing + * + * Also the CRC will be calculated here. + * + */ + +void +FDKsbrEnc_AssembleSbrBitstream( HANDLE_COMMON_DATA hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, + INT crcRegion, + UINT sbrSyntaxFlags) +{ + USHORT crcReg = SBR_CRCINIT; + INT numCrcBits,i; + + /* check if SBR is present */ + if ( hCmonData==NULL ) + return; + + hCmonData->sbrFillBits = 0; /* Fill bits are written only for GA streams */ + + if ( sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC ) + { + /* + * Calculate and write DRM CRC + */ + FDKcrcEndReg( hCrcInfo, &hCmonData->sbrBitbuf, crcRegion ); + FDKwriteBits( &hCmonData->tmpWriteBitbuf, FDKcrcGetCRC(hCrcInfo)^0xFF, SI_SBR_DRM_CRC_BITS ); + } + else + { + if ( !(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ) + { + /* Do alignment here, because its defined as part of the sbr_extension_data */ + int sbrLoad = hCmonData->sbrHdrBits + hCmonData->sbrDataBits; + + if ( sbrSyntaxFlags & SBR_SYNTAX_CRC ) { + sbrLoad += SI_SBR_CRC_BITS; + } + + sbrLoad += 4; /* Do byte Align with 4 bit offset. ISO/IEC 14496-3:2005(E) page 39. */ + + hCmonData->sbrFillBits = (8 - (sbrLoad % 8)) % 8; + + /* + append fill bits + */ + FDKwriteBits(&hCmonData->sbrBitbuf, 0, hCmonData->sbrFillBits ); + + FDK_ASSERT(FDKgetValidBits(&hCmonData->sbrBitbuf) % 8 == 4); + } + + /* + calculate crc + */ + if ( sbrSyntaxFlags & SBR_SYNTAX_CRC ) { + FDK_BITSTREAM tmpCRCBuf = hCmonData->sbrBitbuf; + FDKresetBitbuffer( &tmpCRCBuf, BS_READER ); + + numCrcBits = hCmonData->sbrHdrBits + hCmonData->sbrDataBits + hCmonData->sbrFillBits; + + for(i=0;itmpWriteBitbuf, crcReg, SI_SBR_CRC_BITS); + } + } + + FDKsyncCache(&hCmonData->tmpWriteBitbuf); +} + diff --git a/libSBRenc/src/env_bit.h b/libSBRenc/src/env_bit.h new file mode 100644 index 00000000..038a32ad --- /dev/null +++ b/libSBRenc/src/env_bit.h @@ -0,0 +1,126 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#ifndef BIT_ENV_H +#define BIT_ENV_H + +#include "sbr_encoder.h" +#include "FDK_crc.h" + +/* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY (0x0233) +#define SBR_CRC_MASK (0x0200) +#define SBR_CRC_RANGE (0x03FF) +#define SBR_CRC_MAXREGS 1 +#define SBR_CRCINIT (0x0) + + +#define SI_SBR_CRC_ENABLE_BITS 0 +#define SI_SBR_CRC_BITS 10 +#define SI_SBR_DRM_CRC_BITS 8 + + +struct COMMON_DATA; + +INT FDKsbrEnc_InitSbrBitstream(struct COMMON_DATA *hCmonData, + UCHAR *memoryBase, + INT memorySize, + HANDLE_FDK_CRCINFO hCrcInfo, + UINT sbrSyntaxFlags); + +void +FDKsbrEnc_AssembleSbrBitstream (struct COMMON_DATA *hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, + INT crcReg, + UINT sbrSyntaxFlags); + + + + + +#endif /* #ifndef BIT_ENV_H */ diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp new file mode 100644 index 00000000..06d73739 --- /dev/null +++ b/libSBRenc/src/env_est.cpp @@ -0,0 +1,2031 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "env_est.h" +#include "tran_det.h" + +#include "qmf.h" + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "cmondata.h" +#include "sbr_ram.h" + + +#include "genericStds.h" + +#define QUANT_ERROR_THRES 200 +#define Y_NRG_SCALE 5 /* noCols = 32 -> shift(5) */ + + +static const UCHAR panTable[2][10] = { { 0, 2, 4, 6, 8,12,16,20,24}, + { 0, 2, 4, 8,12, 0, 0, 0, 0 } }; +static const UCHAR maxIndex[2] = {9, 5}; + + +/****************************************************************************** + Functionname: FDKsbrEnc_GetTonality +******************************************************************************/ +/***************************************************************************/ +/*! + + \brief Calculates complete energy per band from the energy values + of the QMF subsamples. + + \brief quotaMatrix - calculated in FDKsbrEnc_CalculateTonalityQuotas() + \brief noEstPerFrame - number of estimations per frame + \brief startIndex - start index for the quota matrix + \brief Energies - energy matrix + \brief startBand - start band + \brief stopBand - number of QMF bands + \brief numberCols - number of QMF subsamples + + \return mean tonality of the 5 bands with the highest energy + scaled by 2^(RELAXATION_SHIFT+2)*RELAXATION_FRACT + +****************************************************************************/ +static FIXP_DBL FDKsbrEnc_GetTonality( + const FIXP_DBL *const *quotaMatrix, + const INT noEstPerFrame, + const INT startIndex, + const FIXP_DBL *const *Energies, + const UCHAR startBand, + const INT stopBand, + const INT numberCols + ) +{ + UCHAR b, e, k; + INT no_enMaxBand[SBR_MAX_ENERGY_VALUES] = { -1, -1, -1, -1, -1 }; + FIXP_DBL energyMax[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) }; + FIXP_DBL energyMaxMin = MAXVAL_DBL; /* min. energy in energyMax array */ + UCHAR posEnergyMaxMin = 0; /* min. energy in energyMax array position */ + FIXP_DBL tonalityBand[SBR_MAX_ENERGY_VALUES] = { FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f) }; + FIXP_DBL globalTonality = FL2FXCONST_DBL(0.0f); + FIXP_DBL energyBand[QMF_CHANNELS]; + INT maxNEnergyValues; /* max. number of max. energy values */ + + /*** Sum up energies for each band ***/ + FDK_ASSERT(numberCols==15||numberCols==16); + /* numberCols is always 15 or 16 for ELD. In case of 16 bands, the + energyBands are initialized with the [15]th column. + The rest of the column energies are added in the next step. */ + if (numberCols==15) { + for (b=startBand; b>4; + } + } + + for (k=0; k<15; k++) { + for (b=startBand; b>4; + } + } + + /*** Determine 5 highest band-energies ***/ + maxNEnergyValues = fMin(SBR_MAX_ENERGY_VALUES, stopBand-startBand); + + /* Get min. value in energyMax array */ + energyMaxMin = energyMax[0] = energyBand[startBand]; + no_enMaxBand[0] = startBand; + posEnergyMaxMin = 0; + for (k=1; k energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + + for (b=startBand+maxNEnergyValues; b energyMaxMin) { + energyMax[posEnergyMaxMin] = energyBand[b]; + no_enMaxBand[posEnergyMaxMin] = b; + + /* Again, get min. value in energyMax array */ + energyMaxMin = energyMax[0]; + posEnergyMaxMin = 0; + for (k=1; k energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + } + } + /*** End determine 5 highest band-energies ***/ + + /* Get tonality values for 5 highest energies */ + for (e=0; e> 1; + } + globalTonality += tonalityBand[e] >> 2; /* headroom of 2+1 (max. 5 additions) */ + } + + return globalTonality; +} + +/***************************************************************************/ +/*! + + \brief Calculates energy form real and imaginary part of + the QMF subsamples + + \return none + +****************************************************************************/ +LNK_SECTION_CODE_L1 +static void +FDKsbrEnc_getEnergyFromCplxQmfData(FIXP_DBL **RESTRICT energyValues,/*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT imagValues, /*!< the imaginary part of the QMF subsamples */ + INT numberBands, /*!< number of QMF bands */ + INT numberCols, /*!< number of QMF subsamples */ + INT *qmfScale, /*!< sclefactor of QMF subsamples */ + INT *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, QMF_CHANNELS*QMF_MAX_TIME_SLOTS/2); + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k=0; k= DFRACT_BITS-1) { + scale = (FRACT_BITS-1-*qmfScale); + } + /* prevent scaling of QFM values to -1.f */ + scale = fixMax(0,scale-1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k=0; k> 1; + + tr1 <<= scale; + ti1 <<= scale; + energy += fPow2AddDiv2(fPow2Div2(tr1), ti1) >> 1; + + /* Write timeslot pair energy to scratch */ + *nrgValues++ = energy; + max_val = fixMax(max_val, energy); + + /* Write back scaled QMF values */ + r0[j] = tr0; r1[j] = tr1; i0[j] = ti0; i1[j] = ti1; + } + } + } + /* energyScale: scalefactor energies of current frame */ + *energyScale = 2*(*qmfScale)-1; /* if qmfScale > 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k=0; k>1; k++) { + scaleValues(energyValues[k], nrgValues, numberBands, scale); + nrgValues += numberBands; + } + *energyScale += scale; + } + + /* Free Scratch buffer */ + C_ALLOC_SCRATCH_END(tmpNrg, FIXP_DBL, QMF_CHANNELS*QMF_MAX_TIME_SLOTS/2); +} + +LNK_SECTION_CODE_L1 +static void +FDKsbrEnc_getEnergyFromCplxQmfDataFull(FIXP_DBL **RESTRICT energyValues,/*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT imagValues, /*!< the imaginary part of the QMF subsamples */ + int numberBands, /*!< number of QMF bands */ + int numberCols, /*!< number of QMF subsamples */ + int *qmfScale, /*!< sclefactor of QMF subsamples */ + int *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, QMF_MAX_TIME_SLOTS*QMF_CHANNELS/2); + + FDK_ASSERT(numberBands <= QMF_CHANNELS); + FDK_ASSERT(numberCols <= QMF_MAX_TIME_SLOTS/2); + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k=0; k= DFRACT_BITS-1) { + scale = (FRACT_BITS-1-*qmfScale); + } + /* prevent scaling of QFM values to -1.f */ + scale = fixMax(0,scale-1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k=0; k 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k=0; k 0 ? 1 : -1; + + nrgVal *= sign; + + min_val = FDK_INT_MAX; + panIndex = 0; + for (i = 0; i < maxIndex[ampRes]; i++) { + val = fixp_abs ((nrgVal - (INT)panTable[ampRes][i])); + + if (val < min_val) { + min_val = val; + panIndex = i; + } + } + + *quantError=min_val; + + return panTable[ampRes][maxIndex[ampRes]-1] + sign * panTable[ampRes][panIndex]; +} + + +/***************************************************************************/ +/*! + + \brief Quantisation of the noise floor levels + + \return void + +****************************************************************************/ +static void +sbrNoiseFloorLevelsQuantisation(SCHAR *RESTRICT iNoiseLevels, /*! quantized noise levels */ + FIXP_DBL *RESTRICT NoiseLevels, /*! the noise levels */ + INT coupling /*! the coupling flag */ + ) +{ + INT i; + INT tmp, dummy; + + /* Quantisation, similar to sfb quant... */ + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + /* tmp = NoiseLevels[i] > (PFLOAT)30.0f ? 30: (INT) (NoiseLevels[i] + (PFLOAT)0.5); */ + /* 30>>6 = 0.46875 */ + if ((FIXP_DBL)NoiseLevels[i] > FL2FXCONST_DBL(0.46875f)) { + tmp = 30; + } + else { + /* tmp = (INT)((FIXP_DBL)NoiseLevels[i] + (FL2FXCONST_DBL(0.5f)>>(*/ /* FRACT_BITS+ */ /* 6-1)));*/ + /* tmp = tmp >> (DFRACT_BITS-1-6); */ /* conversion to integer happens here */ + /* rounding is done by shifting one bit less than necessary to the right, adding '1' and then shifting the final bit */ + tmp = ((((INT)NoiseLevels[i])>>(DFRACT_BITS-1-LD_DATA_SHIFT)) ); /* conversion to integer */ + if (tmp != 0) + tmp += 1; + } + + if (coupling) { + tmp = tmp < -30 ? -30 : tmp; + tmp = mapPanorama (tmp,1,&dummy); + } + iNoiseLevels[i] = tmp; + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of noise floor for coupling + + \return void + +****************************************************************************/ +static void +coupleNoiseFloor(FIXP_DBL *RESTRICT noise_level_left, /*! noise level left (modified)*/ + FIXP_DBL *RESTRICT noise_level_right /*! noise level right (modified)*/ + ) +{ + FIXP_DBL cmpValLeft,cmpValRight; + INT i; + FIXP_DBL temp1,temp2; + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + + /* Calculation of the power function using ld64: + z = x^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64; + z = CalcInvLd64(z'); + */ + cmpValLeft = NOISE_FLOOR_OFFSET_64 - noise_level_left[i]; + cmpValRight = NOISE_FLOOR_OFFSET_64 - noise_level_right[i]; + + if (cmpValRight < FL2FXCONST_DBL(0.0f)) { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + } + else { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + temp1 = temp1 << (DFRACT_BITS-1-LD_DATA_SHIFT-1); /* INT to fract conversion of result, if input of CalcInvLdData is positiv */ + } + + if (cmpValLeft < FL2FXCONST_DBL(0.0f)) { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + } + else { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + temp2 = temp2 << (DFRACT_BITS-1-LD_DATA_SHIFT-1); /* INT to fract conversion of result, if input of CalcInvLdData is positiv */ + } + + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - (CalcLdData(((temp1>>1) + (temp2>>1)))); /* no scaling needed! both values are dfract */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - (CalcLdData(((temp1>>1) + (temp2>>1))) + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - (CalcLdData(((temp1>>(7+1)) + (temp2>>1))) + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = (CalcLdData(temp2) + FL2FXCONST_DBL(0.109375f)) - CalcLdData(temp1); + } + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - (CalcLdData(((temp1>>1) + (temp2>>(7+1)))) + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - (CalcLdData(temp1) + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + } + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of energy starting in lower band (li) up to upper band (ui) + over slots (start_pos) to (stop_pos) + + \return void + +****************************************************************************/ +static FIXP_DBL +getEnvSfbEnergy(INT li, /*! lower band */ + INT ui, /*! upper band */ + INT start_pos, /*! start slot */ + INT stop_pos, /*! stop slot */ + INT border_pos, /*! slots scaling border */ + FIXP_DBL **YBuffer, /*! sfb energy buffer */ + INT YBufferSzShift, /*! Energy buffer index scale */ + INT scaleNrg0, /*! scaling of lower slots */ + INT scaleNrg1) /*! scaling of upper slots */ +{ + /* use dynamic scaling for outer energy loop; + energies are critical and every bit is important */ + int sc0, sc1, k, l; + + FIXP_DBL nrgSum, nrg1, nrg2, accu1, accu2; + INT dynScale, dynScale1, dynScale2; + if(ui-li==0) dynScale = DFRACT_BITS-1; + else + dynScale = CalcLdInt(ui-li)>>(DFRACT_BITS-1-LD_DATA_SHIFT); + + sc0 = fixMin(scaleNrg0,Y_NRG_SCALE); sc1 = fixMin(scaleNrg1,Y_NRG_SCALE); + /* dynScale{1,2} is set such that the right shift below is positive */ + dynScale1 = fixMin((scaleNrg0-sc0),dynScale); + dynScale2 = fixMin((scaleNrg1-sc1),dynScale); + nrgSum = accu1 = accu2 = (FIXP_DBL)0; + + for (k = li; k < ui; k++) { + nrg1 = nrg2 = (FIXP_DBL)0; + for (l = start_pos; l < border_pos; l++) { + nrg1 += YBuffer[l>>YBufferSzShift][k] >> sc0; + } + for (; l < stop_pos; l++) { + nrg2 += YBuffer[l>>YBufferSzShift][k] >> sc1; + } + accu1 += (nrg1>>dynScale1); + accu2 += (nrg2>>dynScale2); + } + /* This shift factor is always positive. See comment above. */ + nrgSum += ( accu1 >> fixMin((scaleNrg0-sc0-dynScale1),(DFRACT_BITS-1)) ) + + ( accu2 >> fixMin((scaleNrg1-sc1-dynScale2),(DFRACT_BITS-1)) ); + + return nrgSum; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL +mhLoweringEnergy(FIXP_DBL nrg, INT M) +{ + /* + Compensating for the fact that we in the decoder map the "average energy to every QMF + band, and use this when we calculate the boost-factor. Since the mapped energy isn't + the average energy but the maximum energy in case of missing harmonic creation, we will + in the boost function calculate that too much limiting has been applied and hence we will + boost the signal although it isn't called for. Hence we need to compensate for this by + lowering the transmitted energy values for the sines so they will get the correct level + after the boost is applied. + */ + if(M > 2){ + INT tmpScale; + tmpScale = CountLeadingBits(nrg); + nrg <<= tmpScale; + nrg = fMult(nrg, FL2FXCONST_DBL(0.398107267f)); /* The maximum boost is 1.584893, so the maximum attenuation should be square(1/1.584893) = 0.398107267 */ + nrg >>= tmpScale; + } + else{ + if(M > 1){ + nrg >>= 1; + } + } + + return nrg; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in none missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL nmhLoweringEnergy( + FIXP_DBL nrg, + const FIXP_DBL nrgSum, + const INT nrgSum_scale, + const INT M + ) +{ + if (nrg>FL2FXCONST_DBL(0)) { + int sc=0; + /* gain = nrgSum / (nrg*(M+1)) */ + FIXP_DBL gain = fMult(fDivNorm(nrgSum, nrg, &sc), GetInvInt(M+1)); + sc += nrgSum_scale; + + /* reduce nrg if gain smaller 1.f */ + if ( !((sc>=0) && ( gain > ((FIXP_DBL)MAXVAL_DBL>>sc) )) ) { + nrg = fMult(scaleValue(gain,sc), nrg); + } + } + return nrg; +} + +/***************************************************************************/ +/*! + + \brief calculates the envelope values from the energies, depending on + framing and stereo mode + + \return void + +****************************************************************************/ +static void +calculateSbrEnvelope (FIXP_DBL **RESTRICT YBufferLeft, /*! energy buffer left */ + FIXP_DBL **RESTRICT YBufferRight, /*! energy buffer right */ + int *RESTRICT YBufferScaleLeft, /*! scale energy buffer left */ + int *RESTRICT YBufferScaleRight, /*! scale energy buffer right */ + const SBR_FRAME_INFO *frame_info, /*! frame info vector */ + SCHAR *RESTRICT sfb_nrgLeft, /*! sfb energy buffer left */ + SCHAR *RESTRICT sfb_nrgRight, /*! sfb energy buffer right */ + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_ENV_CHANNEL h_sbr, /*! envelope channel handle */ + SBR_STEREO_MODE stereoMode, /*! stereo coding mode */ + INT* maxQuantError, /*! maximum quantization error, for panorama. */ + int YBufferSzShift) /*! Energy buffer index scale */ + +{ + int i, j, m = 0; + INT no_of_bands, start_pos, stop_pos, li, ui; + FREQ_RES freq_res; + + INT ca = 2 - h_sbr->encEnvData.init_sbr_amp_res; + INT oneBitLess = 0; + if (ca == 2) + oneBitLess = 1; /* LD_DATA_SHIFT => ld64 scaling; one bit less for rounding */ + + INT quantError; + INT nEnvelopes = frame_info->nEnvelopes; + INT short_env = frame_info->shortEnv - 1; + INT timeStep = h_sbr->sbrExtractEnvelope.time_step; + INT commonScale,scaleLeft0,scaleLeft1; + INT scaleRight0=0,scaleRight1=0; + + commonScale = fixMin(YBufferScaleLeft[0],YBufferScaleLeft[1]); + + if (stereoMode == SBR_COUPLING) { + commonScale = fixMin(commonScale,YBufferScaleRight[0]); + commonScale = fixMin(commonScale,YBufferScaleRight[1]); + } + + commonScale = commonScale - 7; + + scaleLeft0 = YBufferScaleLeft[0] - commonScale; + scaleLeft1 = YBufferScaleLeft[1] - commonScale ; + FDK_ASSERT ((scaleLeft0 >= 0) && (scaleLeft1 >= 0)); + + if (stereoMode == SBR_COUPLING) { + scaleRight0 = YBufferScaleRight[0] - commonScale; + scaleRight1 = YBufferScaleRight[1] - commonScale; + FDK_ASSERT ((scaleRight0 >= 0) && (scaleRight1 >= 0)); + *maxQuantError = 0; + } + + for (i = 0; i < nEnvelopes; i++) { + + FIXP_DBL pNrgLeft[QMF_MAX_TIME_SLOTS]; + FIXP_DBL pNrgRight[QMF_MAX_TIME_SLOTS]; + int envNrg_scale; + FIXP_DBL envNrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL envNrgRight = FL2FXCONST_DBL(0.0f); + int missingHarmonic[QMF_MAX_TIME_SLOTS]; + int count[QMF_MAX_TIME_SLOTS]; + + start_pos = timeStep * frame_info->borders[i]; + stop_pos = timeStep * frame_info->borders[i + 1]; + freq_res = frame_info->freqRes[i]; + no_of_bands = h_con->nSfb[freq_res]; + envNrg_scale = DFRACT_BITS-fNormz((FIXP_DBL)no_of_bands); + + if (i == short_env) { + stop_pos -= fixMax(2, timeStep); /* consider at least 2 QMF slots less for short envelopes (envelopes just before transients) */ + } + + for (j = 0; j < no_of_bands; j++) { + FIXP_DBL nrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgRight = FL2FXCONST_DBL(0.0f); + + li = h_con->freqBandTable[freq_res][j]; + ui = h_con->freqBandTable[freq_res][j + 1]; + + if(freq_res == FREQ_RES_HIGH){ + if(j == 0 && ui-li > 1){ + li++; + } + } + else{ + if(j == 0 && ui-li > 2){ + li++; + } + } + + /* + Find out whether a sine will be missing in the scale-factor + band that we're currently processing. + */ + missingHarmonic[j] = 0; + + if(h_sbr->encEnvData.addHarmonicFlag){ + + if(freq_res == FREQ_RES_HIGH){ + if(h_sbr->encEnvData.addHarmonic[j]){ /*A missing sine in the current band*/ + missingHarmonic[j] = 1; + } + } + else{ + INT i; + INT startBandHigh = 0; + INT stopBandHigh = 0; + + while(h_con->freqBandTable[FREQ_RES_HIGH][startBandHigh] < h_con->freqBandTable[FREQ_RES_LOW][j]) + startBandHigh++; + while(h_con->freqBandTable[FREQ_RES_HIGH][stopBandHigh] < h_con->freqBandTable[FREQ_RES_LOW][j + 1]) + stopBandHigh++; + + for(i = startBandHigh; iencEnvData.addHarmonic[i]){ + missingHarmonic[j] = 1; + } + } + } + } + + /* + If a sine is missing in a scalefactorband, with more than one qmf channel + use the nrg from the channel with the largest nrg rather than the mean. + Compensate for the boost calculation in the decdoder. + */ + int border_pos = fixMin(stop_pos, h_sbr->sbrExtractEnvelope.YBufferWriteOffset<>envNrg_scale); + envNrgRight += (nrgRight>>envNrg_scale); + } /* j */ + + for (j = 0; j < no_of_bands; j++) { + + FIXP_DBL nrgLeft2 = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgLeft = pNrgLeft[j]; + FIXP_DBL nrgRight = pNrgRight[j]; + + /* None missing harmonic Energy lowering compensation */ + if(!missingHarmonic[j] && h_sbr->fLevelProtect) { + /* in case of missing energy in base band, + reduce reference energy to prevent overflows in decoder output */ + nrgLeft = nmhLoweringEnergy(nrgLeft, envNrgLeft, envNrg_scale, no_of_bands); + if (stereoMode == SBR_COUPLING) { + nrgRight = nmhLoweringEnergy(nrgRight, envNrgRight, envNrg_scale, no_of_bands); + } + } + + if (stereoMode == SBR_COUPLING) { + /* calc operation later with log */ + nrgLeft2 = nrgLeft; + nrgLeft = (nrgRight + nrgLeft) >> 1; + } + + /* nrgLeft = f20_log2(nrgLeft / (PFLOAT)(count * h_sbr->sbrQmf.no_channels))+(PFLOAT)44; */ + /* If nrgLeft == 0 then the Log calculations below do fail. */ + if (nrgLeft > FL2FXCONST_DBL(0.0f)) + { + FIXP_DBL tmp0,tmp1,tmp2,tmp3; + INT tmpScale; + + tmpScale = CountLeadingBits(nrgLeft); + nrgLeft = nrgLeft << tmpScale; + + tmp0 = CalcLdData(nrgLeft); /* scaled by 1/64 */ + tmp1 = ((FIXP_DBL) (commonScale+tmpScale)) << (DFRACT_BITS-1-LD_DATA_SHIFT-1); /* scaled by 1/64 */ + tmp2 = ((FIXP_DBL)(count[j]*h_con->noQmfBands)) << (DFRACT_BITS-1-14-1); + tmp2 = CalcLdData(tmp2); /* scaled by 1/64 */ + tmp3 = FL2FXCONST_DBL(0.6875f-0.21875f-0.015625f)>>1; /* scaled by 1/64 */ + + nrgLeft = ((tmp0-tmp2)>>1) + (tmp3 - tmp1); + } else { + nrgLeft = FL2FXCONST_DBL(-1.0f); + } + + /* ld64 to integer conversion */ + nrgLeft = fixMin(fixMax(nrgLeft,FL2FXCONST_DBL(0.0f)),(FL2FXCONST_DBL(0.5f)>>oneBitLess)); + nrgLeft = (FIXP_DBL)(LONG)nrgLeft >> (DFRACT_BITS-1-LD_DATA_SHIFT-1-oneBitLess-1); + sfb_nrgLeft[m] = ((INT)nrgLeft+1)>>1; /* rounding */ + + if (stereoMode == SBR_COUPLING) { + FIXP_DBL scaleFract; + int sc0, sc1; + + nrgLeft2 = fixMax((FIXP_DBL)0x1, nrgLeft2); + nrgRight = fixMax((FIXP_DBL)0x1, nrgRight); + + sc0 = CountLeadingBits(nrgLeft2); + sc1 = CountLeadingBits(nrgRight); + + scaleFract = ((FIXP_DBL)(sc0-sc1)) << (DFRACT_BITS-1-LD_DATA_SHIFT); /* scale value in ld64 representation */ + nrgRight = CalcLdData(nrgLeft2<> (DFRACT_BITS-1-LD_DATA_SHIFT-1-oneBitLess); + nrgRight = (nrgRight+(FIXP_DBL)1)>>1; /* rounding */ + + sfb_nrgRight[m] = mapPanorama (nrgRight,h_sbr->encEnvData.init_sbr_amp_res,&quantError); + + *maxQuantError = fixMax(quantError, *maxQuantError); + } + + m++; + } /* j */ + + /* Do energy compensation for sines that are present in two + QMF-bands in the original, but will only occur in one band in + the decoder due to the synthetic sine coding.*/ + if (h_con->useParametricCoding) { + m-=no_of_bands; + for (j = 0; j < no_of_bands; j++) { + if (freq_res==FREQ_RES_HIGH && h_sbr->sbrExtractEnvelope.envelopeCompensation[j]){ + sfb_nrgLeft[m] -= (ca * fixp_abs((INT)h_sbr->sbrExtractEnvelope.envelopeCompensation[j])); + } + sfb_nrgLeft[m] = fixMax(0, sfb_nrgLeft[m]); + m++; + } + } /* useParametricCoding */ + + } /* i*/ +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Analysis subband filtering. + -Encoding SA and pan parameters (if enabled). + -Transient detection. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void +FDKsbrEnc_extractSbrEnvelope1 ( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL hEnvChan, + HANDLE_COMMON_DATA hCmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData + ) +{ + + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + + if (sbrExtrEnv->YBufferSzShift == 0) + FDKsbrEnc_getEnergyFromCplxQmfDataFull(&sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, + h_con->noQmfBands, + sbrExtrEnv->no_cols, + &hEnvChan->qmfScale, + &sbrExtrEnv->YBufferScale[1]); + else + FDKsbrEnc_getEnergyFromCplxQmfData(&sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, + h_con->noQmfBands, + sbrExtrEnv->no_cols, + &hEnvChan->qmfScale, + &sbrExtrEnv->YBufferScale[1]); + + + + /* + Precalculation of Tonality Quotas COEFF Transform OK + */ + FDKsbrEnc_CalculateTonalityQuotas(&hEnvChan->TonCorr, + sbrExtrEnv->rBuffer, + sbrExtrEnv->iBuffer, + h_con->freqBandTable[HI][h_con->nSfb[HI]], + hEnvChan->qmfScale); + + + if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FIXP_DBL tonality = FDKsbrEnc_GetTonality ( + hEnvChan->TonCorr.quotaMatrix, + hEnvChan->TonCorr.numberOfEstimatesPerFrame, + hEnvChan->TonCorr.startIndexMatrix, + sbrExtrEnv->YBuffer + sbrExtrEnv->YBufferWriteOffset, + h_con->freqBandTable[HI][0]+1, + h_con->noQmfBands, + sbrExtrEnv->no_cols + ); + + hEnvChan->encEnvData.ton_HF[1] = hEnvChan->encEnvData.ton_HF[0]; + hEnvChan->encEnvData.ton_HF[0] = tonality; + + /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + hEnvChan->encEnvData.global_tonality = (hEnvChan->encEnvData.ton_HF[0]>>1) + (hEnvChan->encEnvData.ton_HF[1]>>1); + } + + + + /* + Transient detection COEFF Transform OK + */ + if(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + FDKsbrEnc_fastTransientDetect( + &hEnvChan->sbrFastTransientDetector, + sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, + sbrExtrEnv->YBufferWriteOffset, + eData->transient_info + ); + + } + else + { + FDKsbrEnc_transientDetect(&hEnvChan->sbrTransientDetector, + sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, + eData->transient_info, + sbrExtrEnv->YBufferWriteOffset, + sbrExtrEnv->YBufferSzShift, + sbrExtrEnv->time_step, + hEnvChan->SbrEnvFrame.frameMiddleSlot); + } + + + + /* + Generate flags for 2 env in a FIXFIX-frame. + Remove this function to get always 1 env per FIXFIX-frame. + */ + + /* + frame Splitter COEFF Transform OK + */ + FDKsbrEnc_frameSplitter(sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, + &hEnvChan->sbrTransientDetector, + h_con->freqBandTable[1], + eData->transient_info, + sbrExtrEnv->YBufferWriteOffset, + sbrExtrEnv->YBufferSzShift, + h_con->nSfb[1], + sbrExtrEnv->time_step, + sbrExtrEnv->no_cols, + &hEnvChan->encEnvData.global_tonality); + + +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Determine time/frequency division of current granule. + -Sending transient info to bitstream. + -Set amp_res to 1.5 dB if the current frame contains only one envelope. + -Lock dynamic bandwidth frequency change if the next envelope not starts on a + frame boundary. + -MDCT transposer (needed to detect where harmonics will be missing). + -Spectrum Estimation (used for pulse train and missing harmonics detection). + -Pulse train detection. + -Inverse Filtering detection. + -Waveform Coding. + -Missing Harmonics detection. + -Extract envelope of current frame. + -Noise floor estimation. + -Noise floor quantisation and coding. + -Encode envelope of current frame. + -Send the encoded data to the bitstream. + -Write to bitstream. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void +FDKsbrEnc_extractSbrEnvelope2 ( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL h_envChan0, + HANDLE_ENV_CHANNEL h_envChan1, + HANDLE_COMMON_DATA hCmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData, + int clearOutput + ) +{ + HANDLE_ENV_CHANNEL h_envChan[MAX_NUM_CHANNELS] = {h_envChan0, h_envChan1}; + int ch, i, j, c, YSzShift = h_envChan[0]->sbrExtractEnvelope.YBufferSzShift; + + SBR_STEREO_MODE stereoMode = h_con->stereoMode; + int nChannels = h_con->nChannels; + FDK_ASSERT(nChannels <= MAX_NUM_CHANNELS); + const int *v_tuning; + static const int v_tuningHEAAC[6] = { 0, 2, 4, 0, 0, 0 }; + + static const int v_tuningELD[6] = { 0, 2, 3, 0, 0, 0 }; + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + v_tuning = v_tuningELD; + else + v_tuning = v_tuningHEAAC; + + + /* + Select stereo mode. + */ + if (stereoMode == SBR_COUPLING) { + if (eData[0].transient_info[1] && eData[1].transient_info[1]) { + eData[0].transient_info[0] = fixMin(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } + else { + if (eData[0].transient_info[1] && !eData[1].transient_info[1]) { + eData[1].transient_info[0] = eData[0].transient_info[0]; + } + else { + if (!eData[0].transient_info[1] && eData[1].transient_info[1]) + eData[0].transient_info[0] = eData[1].transient_info[0]; + else { + eData[0].transient_info[0] = fixMax(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } + } + } + } + + /* + Determine time/frequency division of current granule + */ + eData[0].frame_info = FDKsbrEnc_frameInfoGenerator(&h_envChan[0]->SbrEnvFrame, + eData[0].transient_info, + h_envChan[0]->sbrExtractEnvelope.pre_transient_info, + h_envChan[0]->encEnvData.ldGrid, + v_tuning); + + h_envChan[0]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + + /* AAC LD patch for transient prediction */ + if (h_envChan[0]->encEnvData.ldGrid && eData[0].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[0]->SbrEnvFrame.SbrFrameInfo.shortEnv = h_envChan[0]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + + switch (stereoMode) { + case SBR_LEFT_RIGHT: + case SBR_SWITCH_LRC: + eData[1].frame_info = FDKsbrEnc_frameInfoGenerator(&h_envChan[1]->SbrEnvFrame, + eData[1].transient_info, + h_envChan[1]->sbrExtractEnvelope.pre_transient_info, + h_envChan[1]->encEnvData.ldGrid, + v_tuning); + + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[1]->SbrEnvFrame.SbrGrid; + + if (h_envChan[1]->encEnvData.ldGrid && eData[1].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[1]->SbrEnvFrame.SbrFrameInfo.shortEnv = h_envChan[1]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + /* compare left and right frame_infos */ + if (eData[0].frame_info->nEnvelopes != eData[1].frame_info->nEnvelopes) { + stereoMode = SBR_LEFT_RIGHT; + } else { + for (i = 0; i < eData[0].frame_info->nEnvelopes + 1; i++) { + if (eData[0].frame_info->borders[i] != eData[1].frame_info->borders[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + for (i = 0; i < eData[0].frame_info->nEnvelopes; i++) { + if (eData[0].frame_info->freqRes[i] != eData[1].frame_info->freqRes[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + if (eData[0].frame_info->shortEnv != eData[1].frame_info->shortEnv) { + stereoMode = SBR_LEFT_RIGHT; + } + } + break; + case SBR_COUPLING: + eData[1].frame_info = eData[0].frame_info; + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + break; + case SBR_MONO: + /* nothing to do */ + break; + default: + FDK_ASSERT (0); + } + + + for (ch = 0; ch < nChannels;ch++) + { + HANDLE_ENV_CHANNEL hEnvChan = h_envChan[ch]; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + + + /* + Send transient info to bitstream and store for next call + */ + sbrExtrEnv->pre_transient_info[0] = ed->transient_info[0];/* tran_pos */ + sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1];/* tran_flag */ + hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes = ed->frame_info->nEnvelopes; /* number of envelopes of current frame */ + + /* + Check if the current frame is divided into one envelope only. If so, set the amplitude + resolution to 1.5 dB, otherwise may set back to chosen value + */ + if( ( hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX ) + && ( ed->nEnvelopes == 1 ) ) + { + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + /* Note: global_tonaliy_float_value == ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0))); + threshold_float_value == ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); */ + /* decision of SBR_AMP_RES */ + if (fIsLessThan( /* global_tonality > threshold ? */ + h_con->thresholdAmpResFF_m, h_con->thresholdAmpResFF_e, + hEnvChan->encEnvData.global_tonality, RELAXATION_SHIFT+2 ) + ) + { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } + else { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0; + } + } else { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } + + if ( hEnvChan->encEnvData.currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { + + FDKsbrEnc_InitSbrHuffmanTables(&hEnvChan->encEnvData, + &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, + hEnvChan->encEnvData.currentAmpResFF); + } + } + else { + if(sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res ) { + + FDKsbrEnc_InitSbrHuffmanTables(&hEnvChan->encEnvData, + &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, + sbrHeaderData->sbr_amp_res); + } + } + + if (!clearOutput) { + + /* + Tonality correction parameter extraction (inverse filtering level, noise floor additional sines). + */ + FDKsbrEnc_TonCorrParamExtr(&hEnvChan->TonCorr, + hEnvChan->encEnvData.sbr_invf_mode_vec, + ed->noiseFloor, + &hEnvChan->encEnvData.addHarmonicFlag, + hEnvChan->encEnvData.addHarmonic, + sbrExtrEnv->envelopeCompensation, + ed->frame_info, + ed->transient_info, + h_con->freqBandTable[HI], + h_con->nSfb[HI], + hEnvChan->encEnvData.sbr_xpos_mode, + h_con->sbrSyntaxFlags); + + } + + /* Low energy in low band fix */ + if ( hEnvChan->sbrTransientDetector.prevLowBandEnergy < hEnvChan->sbrTransientDetector.prevHighBandEnergy + && hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03) + /* The fix needs the non-fast transient detector running. + It sets prevLowBandEnergy and prevHighBandEnergy. */ + && !(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + ) + { + int i; + + hEnvChan->fLevelProtect = 1; + + for (i=0; iencEnvData.sbr_invf_mode_vec[i] = INVF_HIGH_LEVEL; + } else { + hEnvChan->fLevelProtect = 0; + } + + hEnvChan->encEnvData.sbr_invf_mode = hEnvChan->encEnvData.sbr_invf_mode_vec[0]; + + hEnvChan->encEnvData.noOfnoisebands = hEnvChan->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + + } /* ch */ + + + + /* + Save number of scf bands per envelope + */ + for (ch = 0; ch < nChannels;ch++) { + for (i = 0; i < eData[ch].nEnvelopes; i++){ + h_envChan[ch]->encEnvData.noScfBands[i] = + (eData[ch].frame_info->freqRes[i] == FREQ_RES_HIGH ? h_con->nSfb[FREQ_RES_HIGH] : h_con->nSfb[FREQ_RES_LOW]); + } + } + + /* + Extract envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + calculateSbrEnvelope (h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, + h_con, h_envChan[0], SBR_MONO, NULL, YSzShift); + break; + case SBR_LEFT_RIGHT: + calculateSbrEnvelope (h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, + h_con, h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope (h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info,eData[1].sfb_nrg, NULL, + h_con, h_envChan[1], SBR_MONO, NULL, YSzShift); + break; + case SBR_COUPLING: + calculateSbrEnvelope (h_envChan[0]->sbrExtractEnvelope.YBuffer, h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg, eData[1].sfb_nrg, + h_con, h_envChan[0], SBR_COUPLING, &fData->maxQuantError, YSzShift); + break; + case SBR_SWITCH_LRC: + calculateSbrEnvelope (h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, + h_con, h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope (h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info, eData[1].sfb_nrg, NULL, + h_con, h_envChan[1], SBR_MONO,NULL, YSzShift); + calculateSbrEnvelope (h_envChan[0]->sbrExtractEnvelope.YBuffer, h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg_coupling, eData[1].sfb_nrg_coupling, + h_con, h_envChan[0], SBR_COUPLING, &fData->maxQuantError, YSzShift); + break; + } + + + + /* + Noise floor quantisation and coding. + */ + + switch (stereoMode) { + case SBR_MONO: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + case SBR_LEFT_RIGHT: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level,eData[0].noiseFloor, 0); + + FDKsbrEnc_codeEnvelope (eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level,eData[1].noiseFloor, 0); + + FDKsbrEnc_codeEnvelope (eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + + case SBR_COUPLING: + coupleNoiseFloor(eData[0].noiseFloor,eData[1].noiseFloor); + + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level,eData[0].noiseFloor, 0); + + FDKsbrEnc_codeEnvelope (eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level,eData[1].noiseFloor, 1); + + FDKsbrEnc_codeEnvelope (eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + break; + case SBR_SWITCH_LRC: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level,eData[0].noiseFloor, 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level,eData[1].noiseFloor, 0); + coupleNoiseFloor(eData[0].noiseFloor,eData[1].noiseFloor); + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level_coupling,eData[0].noiseFloor, 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level_coupling,eData[1].noiseFloor, 1); + break; + } + + + + /* + Encode envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + FDKsbrEnc_codeEnvelope (eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_LEFT_RIGHT: + sbrHeaderData->coupling = 0; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + + FDKsbrEnc_codeEnvelope (eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope (eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, + eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_COUPLING: + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + FDKsbrEnc_codeEnvelope (eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope (eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, + eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + break; + case SBR_SWITCH_LRC: + { + INT payloadbitsLR; + INT payloadbitsCOUPLING; + + SCHAR sfbNrgPrevTemp[MAX_NUM_CHANNELS][MAX_FREQ_COEFFS]; + SCHAR noisePrevTemp[MAX_NUM_CHANNELS][MAX_NUM_NOISE_COEFFS]; + INT upDateNrgTemp[MAX_NUM_CHANNELS]; + INT upDateNoiseTemp[MAX_NUM_CHANNELS]; + INT domainVecTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + INT domainVecNoiseTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + + INT tempFlagRight = 0; + INT tempFlagLeft = 0; + + /* + Store previous values, in order to be able to "undo" what is being done. + */ + + for(ch = 0; ch < nChannels;ch++){ + FDKmemcpy (sfbNrgPrevTemp[ch], h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof (SCHAR)); + + FDKmemcpy (noisePrevTemp[ch], h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + MAX_NUM_NOISE_COEFFS * sizeof (SCHAR)); + + upDateNrgTemp[ch] = h_envChan[ch]->sbrCodeEnvelope.upDate; + upDateNoiseTemp[ch] = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + if(sbrHeaderData->prev_coupling){ + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + + /* + Code ordinary Left/Right stereo + */ + FDKsbrEnc_codeEnvelope (eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, 0, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope (eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, 0, + eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) + { + h_envChan[0]->encEnvData.ienvelope[i][j] = eData[0].sfb_nrg[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = eData[1].sfb_nrg[c]; + c++; + } + } + + + + FDKsbrEnc_codeEnvelope (eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = eData[0].noise_level[i]; + + + FDKsbrEnc_codeEnvelope (eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = eData[1].noise_level[i]; + + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + payloadbitsLR = FDKsbrEnc_CountSbrChannelPairElement (sbrHeaderData, + hParametricStereo, + sbrBitstreamData, + &h_envChan[0]->encEnvData, + &h_envChan[1]->encEnvData, + hCmonData, + h_con->sbrSyntaxFlags); + + /* + swap saved stored with current values + */ + for(ch = 0; ch < nChannels;ch++){ + INT itmp; + for(i=0;isbrCodeEnvelope.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev[i]=sfbNrgPrevTemp[ch][i]; + sfbNrgPrevTemp[ch][i]=itmp; + } + for(i=0;isbrCodeNoiseFloor.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev[i]=noisePrevTemp[ch][i]; + noisePrevTemp[ch][i]=itmp; + } + /* swap update flags */ + itmp = h_envChan[ch]->sbrCodeEnvelope.upDate; + h_envChan[ch]->sbrCodeEnvelope.upDate=upDateNrgTemp[ch]; + upDateNrgTemp[ch] = itmp; + + itmp = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + h_envChan[ch]->sbrCodeNoiseFloor.upDate=upDateNoiseTemp[ch]; + upDateNoiseTemp[ch]=itmp; + + /* + save domain vecs + */ + FDKmemcpy(domainVecTemp[ch],h_envChan[ch]->encEnvData.domain_vec,sizeof(INT)*MAX_ENVELOPES); + FDKmemcpy(domainVecNoiseTemp[ch],h_envChan[ch]->encEnvData.domain_vec_noise,sizeof(INT)*MAX_ENVELOPES); + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + + if(!sbrHeaderData->prev_coupling){ + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + + /* + Coupling + */ + + FDKsbrEnc_codeEnvelope (eData[0].sfb_nrg_coupling, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, 1, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + FDKsbrEnc_codeEnvelope (eData[1].sfb_nrg_coupling, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, 1, + eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) { + h_envChan[0]->encEnvData.ienvelope[i][j] = eData[0].sfb_nrg_coupling[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = eData[1].sfb_nrg_coupling[c]; + c++; + } + } + + FDKsbrEnc_codeEnvelope (eData[0].noise_level_coupling, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = eData[0].noise_level_coupling[i]; + + + FDKsbrEnc_codeEnvelope (eData[1].noise_level_coupling, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = eData[1].noise_level_coupling[i]; + + sbrHeaderData->coupling = 1; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + tempFlagLeft = h_envChan[0]->encEnvData.addHarmonicFlag; + tempFlagRight = h_envChan[1]->encEnvData.addHarmonicFlag; + + payloadbitsCOUPLING = + FDKsbrEnc_CountSbrChannelPairElement (sbrHeaderData, + hParametricStereo, + sbrBitstreamData, + &h_envChan[0]->encEnvData, + &h_envChan[1]->encEnvData, + hCmonData, + h_con->sbrSyntaxFlags); + + + h_envChan[0]->encEnvData.addHarmonicFlag = tempFlagLeft; + h_envChan[1]->encEnvData.addHarmonicFlag = tempFlagRight; + + if (payloadbitsCOUPLING < payloadbitsLR) { + + /* + copy coded coupling envelope and noise data to l/r + */ + for(ch = 0; ch < nChannels;ch++){ + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + FDKmemcpy (ed->sfb_nrg, ed->sfb_nrg_coupling, + MAX_NUM_ENVELOPE_VALUES * sizeof (SCHAR)); + FDKmemcpy (ed->noise_level, ed->noise_level_coupling, + MAX_NUM_NOISE_VALUES * sizeof (SCHAR)); + } + + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + } + else{ + /* + restore saved l/r items + */ + for(ch = 0; ch < nChannels;ch++){ + + FDKmemcpy (h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + sfbNrgPrevTemp[ch], MAX_FREQ_COEFFS * sizeof (SCHAR)); + + h_envChan[ch]->sbrCodeEnvelope.upDate = upDateNrgTemp[ch]; + + FDKmemcpy (h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + noisePrevTemp[ch], MAX_NUM_NOISE_COEFFS * sizeof (SCHAR)); + + FDKmemcpy (h_envChan[ch]->encEnvData.domain_vec,domainVecTemp[ch],sizeof(INT)*MAX_ENVELOPES); + FDKmemcpy (h_envChan[ch]->encEnvData.domain_vec_noise,domainVecNoiseTemp[ch],sizeof(INT)*MAX_ENVELOPES); + + h_envChan[ch]->sbrCodeNoiseFloor.upDate = upDateNoiseTemp[ch]; + } + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + } + } + break; + } /* switch */ + + + /* tell the envelope encoders how long it has been, since we last sent + a frame starting with a dF-coded envelope */ + if (stereoMode == SBR_MONO ) { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME) + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + else + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } + else { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME || + h_envChan[1]->encEnvData.domain_vec[0] == TIME) { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac++; + } + else { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } + } + + /* + Send the encoded data to the bitstream + */ + for(ch = 0; ch < nChannels;ch++){ + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + c = 0; + for (i = 0; i < ed->nEnvelopes; i++) { + for (j = 0; j < h_envChan[ch]->encEnvData.noScfBands[i]; j++) { + h_envChan[ch]->encEnvData.ienvelope[i][j] = ed->sfb_nrg[c]; + + c++; + } + } + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++){ + h_envChan[ch]->encEnvData.sbr_noise_levels[i] = ed->noise_level[i]; + } + }/* ch */ + + + /* + Write bitstream + */ + if (nChannels == 2) { + FDKsbrEnc_WriteEnvChannelPairElement(sbrHeaderData, + hParametricStereo, + sbrBitstreamData, + &h_envChan[0]->encEnvData, + &h_envChan[1]->encEnvData, + hCmonData, + h_con->sbrSyntaxFlags); + } + else { + FDKsbrEnc_WriteEnvSingleChannelElement(sbrHeaderData, + hParametricStereo, + sbrBitstreamData, + &h_envChan[0]->encEnvData, + hCmonData, + h_con->sbrSyntaxFlags); + } + + /* + * Update buffers. + */ + for (ch=0; chsbrExtractEnvelope.no_cols >> h_envChan[ch]->sbrExtractEnvelope.YBufferSzShift; + for (i = 0; i < h_envChan[ch]->sbrExtractEnvelope.YBufferWriteOffset; i++) { + FDKmemcpy(h_envChan[ch]->sbrExtractEnvelope.YBuffer[i], + h_envChan[ch]->sbrExtractEnvelope.YBuffer[i + YBufferLength], + sizeof(FIXP_DBL)*QMF_CHANNELS); + } + h_envChan[ch]->sbrExtractEnvelope.YBufferScale[0] = h_envChan[ch]->sbrExtractEnvelope.YBufferScale[1]; + } + + sbrHeaderData->prev_coupling = sbrHeaderData->coupling; +} + +/***************************************************************************/ +/*! + + \brief creates an envelope extractor handle + + \return error status + +****************************************************************************/ +INT +FDKsbrEnc_CreateExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel + ,INT chInEl + ,UCHAR* dynamic_RAM + ) +{ + INT i; + FIXP_DBL* YBuffer = GetRam_Sbr_envYBuffer(channel); + + FDKmemclear(hSbrCut,sizeof(SBR_EXTRACT_ENVELOPE)); + hSbrCut->p_YBuffer = YBuffer; + + + for (i = 0; i < (QMF_MAX_TIME_SLOTS>>1); i++) { + hSbrCut->YBuffer[i] = YBuffer + (i*QMF_CHANNELS); + } + FIXP_DBL *YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + INT n=0; + for (; i < QMF_MAX_TIME_SLOTS; i++,n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n*QMF_CHANNELS); + } + + FIXP_DBL* rBuffer = GetRam_Sbr_envRBuffer(0, dynamic_RAM); + FIXP_DBL* iBuffer = GetRam_Sbr_envIBuffer(0, dynamic_RAM); + + for (i = 0; i < QMF_MAX_TIME_SLOTS; i++) { + hSbrCut->rBuffer[i] = rBuffer + (i*QMF_CHANNELS); + hSbrCut->iBuffer[i] = iBuffer + (i*QMF_CHANNELS); + } + + return 0; +} + + +/***************************************************************************/ +/*! + + \brief Initialize an envelope extractor instance. + + \return error status + +****************************************************************************/ +INT +FDKsbrEnc_InitExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + int no_cols, + int no_rows, + int start_index, + int time_slots, + int time_step, + int tran_off, + ULONG statesInitFlag + ,int chInEl + ,UCHAR* dynamic_RAM + ,UINT sbrSyntaxFlags + ) +{ + int YBufferLength, rBufferLength; + int i; + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + int off = TRANSIENT_OFFSET_LD; +#ifndef FULL_DELAY + hSbrCut->YBufferWriteOffset = (no_cols>>1)+off*time_step; +#else + hSbrCut->YBufferWriteOffset = no_cols+off*time_step; +#endif + } else + { + hSbrCut->YBufferWriteOffset = tran_off*time_step; + } + hSbrCut->rBufferReadOffset = 0; + + + YBufferLength = hSbrCut->YBufferWriteOffset + no_cols; + rBufferLength = no_cols; + + hSbrCut->pre_transient_info[0] = 0; + hSbrCut->pre_transient_info[1] = 0; + + + hSbrCut->no_cols = no_cols; + hSbrCut->no_rows = no_rows; + hSbrCut->start_index = start_index; + + hSbrCut->time_slots = time_slots; + hSbrCut->time_step = time_step; + + FDK_ASSERT(no_rows <= QMF_CHANNELS); + + /* Use half the Energy values if time step is 2 or greater */ + if (time_step >= 2) + hSbrCut->YBufferSzShift = 1; + else + hSbrCut->YBufferSzShift = 0; + + YBufferLength >>= hSbrCut->YBufferSzShift; + hSbrCut->YBufferWriteOffset >>= hSbrCut->YBufferSzShift; + + FDK_ASSERT(YBufferLength<=QMF_MAX_TIME_SLOTS); + + FIXP_DBL *YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + INT n=0; + for (i=(QMF_MAX_TIME_SLOTS>>1); i < QMF_MAX_TIME_SLOTS; i++,n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n*QMF_CHANNELS); + } + + if(statesInitFlag) { + for (i=0; iYBuffer[i],QMF_CHANNELS*sizeof(FIXP_DBL)); + } + } + + for (i = 0; i < rBufferLength; i++) { + FDKmemclear( hSbrCut->rBuffer[i],QMF_CHANNELS*sizeof(FIXP_DBL)); + FDKmemclear( hSbrCut->iBuffer[i],QMF_CHANNELS*sizeof(FIXP_DBL)); + } + + FDKmemclear (hSbrCut->envelopeCompensation,sizeof(UCHAR)*MAX_FREQ_COEFFS); + + if(statesInitFlag) { + hSbrCut->YBufferScale[0] = hSbrCut->YBufferScale[1] = FRACT_BITS-1; + } + + return (0); +} + + + + +/***************************************************************************/ +/*! + + \brief deinitializes an envelope extractor handle + + \return void + +****************************************************************************/ + +void +FDKsbrEnc_deleteExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut) +{ + + if (hSbrCut) { + FreeRam_Sbr_envYBuffer(&hSbrCut->p_YBuffer); + } +} + +INT +FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr) +{ + return hSbr->no_rows*((hSbr->YBufferWriteOffset)*2 /* mult 2 because nrg's are grouped half */ + - hSbr->rBufferReadOffset ); /* in reference hold half spec and calc nrg's on overlapped spec */ + +} + + + + diff --git a/libSBRenc/src/env_est.h b/libSBRenc/src/env_est.h new file mode 100644 index 00000000..e17a9742 --- /dev/null +++ b/libSBRenc/src/env_est.h @@ -0,0 +1,225 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Envelope estimation structs and prototypes +*/ +#ifndef __ENV_EST_H +#define __ENV_EST_H + +#include "sbr_def.h" +#include "sbr_encoder.h" /* SBR econfig structs */ +#include "ps_main.h" +#include "bit_sbr.h" +#include "fram_gen.h" +#include "tran_det.h" +#include "code_env.h" +#include "ton_corr.h" + +typedef struct +{ + FIXP_DBL *rBuffer[QMF_MAX_TIME_SLOTS]; + FIXP_DBL *iBuffer[QMF_MAX_TIME_SLOTS]; + + FIXP_DBL *p_YBuffer; + + FIXP_DBL *YBuffer[QMF_MAX_TIME_SLOTS]; + int YBufferScale[2]; + + UCHAR envelopeCompensation[MAX_FREQ_COEFFS]; + UCHAR pre_transient_info[2]; + + + int YBufferWriteOffset; + int YBufferSzShift; + int rBufferReadOffset; + + int no_cols; + int no_rows; + int start_index; + + int time_slots; + int time_step; +} +SBR_EXTRACT_ENVELOPE; +typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE; + +struct ENV_CHANNEL +{ + FAST_TRAN_DETECTOR sbrFastTransientDetector; + SBR_TRANSIENT_DETECTOR sbrTransientDetector; + SBR_CODE_ENVELOPE sbrCodeEnvelope; + SBR_CODE_ENVELOPE sbrCodeNoiseFloor; + SBR_EXTRACT_ENVELOPE sbrExtractEnvelope; + + + SBR_ENVELOPE_FRAME SbrEnvFrame; + SBR_TON_CORR_EST TonCorr; + + struct SBR_ENV_DATA encEnvData; + + int qmfScale; + UCHAR fLevelProtect; +}; +typedef struct ENV_CHANNEL *HANDLE_ENV_CHANNEL; + +/************ Function Declarations ***************/ + +INT +FDKsbrEnc_CreateExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel + ,INT chInEl + ,UCHAR* dynamic_RAM + ); + + +INT +FDKsbrEnc_InitExtractSbrEnvelope ( + HANDLE_SBR_EXTRACT_ENVELOPE hSbr, + int no_cols, + int no_rows, + int start_index, + int time_slots, int time_step, int tran_off, + ULONG statesInitFlag + ,int chInEl + ,UCHAR* dynamic_RAM + ,UINT sbrSyntaxFlags + ); + +void FDKsbrEnc_deleteExtractSbrEnvelope (HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut); + +typedef struct { + FREQ_RES res[MAX_NUM_NOISE_VALUES]; + int maxQuantError; + +} SBR_FRAME_TEMP_DATA; + +typedef struct { + const SBR_FRAME_INFO *frame_info; + FIXP_DBL noiseFloor[MAX_NUM_NOISE_VALUES]; + SCHAR sfb_nrg_coupling[MAX_NUM_ENVELOPE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR sfb_nrg[MAX_NUM_ENVELOPE_VALUES]; + SCHAR noise_level_coupling[MAX_NUM_NOISE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR noise_level[MAX_NUM_NOISE_VALUES]; + UCHAR transient_info[3]; + UCHAR nEnvelopes; +} SBR_ENV_TEMP_DATA; + +/* + * Extract features from QMF data. Afterwards, the QMF data is not required anymore. + */ +void +FDKsbrEnc_extractSbrEnvelope1( + HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL h_envChan, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData + ); + + +/* + * Process the previously features extracted by FDKsbrEnc_extractSbrEnvelope1 + * and create/encode SBR envelopes. + */ +void +FDKsbrEnc_extractSbrEnvelope2( + HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL sbrEnvChannel0, + HANDLE_ENV_CHANNEL sbrEnvChannel1, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData, + int clearOutput + ); + +INT +FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr); + +#endif diff --git a/libSBRenc/src/fram_gen.cpp b/libSBRenc/src/fram_gen.cpp new file mode 100644 index 00000000..9a35111c --- /dev/null +++ b/libSBRenc/src/fram_gen.cpp @@ -0,0 +1,2065 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "fram_gen.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +static const SBR_FRAME_INFO frameInfo1_2048 = { + 1, + { 0, 16}, + {FREQ_RES_HIGH}, + 0, + 1, + {0, 16} }; + +static const SBR_FRAME_INFO frameInfo2_2048 = { + 2, + { 0, 8, 16}, + {FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 8, 16} }; + +static const SBR_FRAME_INFO frameInfo4_2048 = { + 4, + { 0, 4, 8, 12, 16}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 8, 16} }; + +static const SBR_FRAME_INFO frameInfo1_2304 = { + 1, + { 0, 18}, + {FREQ_RES_HIGH}, + 0, + 1, + { 0, 18} }; + +static const SBR_FRAME_INFO frameInfo2_2304 = { + 2, + { 0, 9, 18}, + {FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 9, 18} }; + +static const SBR_FRAME_INFO frameInfo4_2304 = { + 4, + { 0, 5, 9, 14, 18}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 9, 18} }; + +static const SBR_FRAME_INFO frameInfo1_1920 = { + 1, + { 0, 15}, + {FREQ_RES_HIGH}, + 0, + 1, + { 0, 15} }; + +static const SBR_FRAME_INFO frameInfo2_1920 = { + 2, + { 0, 8, 15}, + {FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 8, 15} }; + +static const SBR_FRAME_INFO frameInfo4_1920 = { + 4, + { 0, 4, 8, 12, 15}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 8, 15} }; + +static const SBR_FRAME_INFO frameInfo1_1152 = { + 1, + { 0, 9}, + {FREQ_RES_HIGH}, + 0, + 1, + { 0, 9} }; + +static const SBR_FRAME_INFO frameInfo2_1152 = { + 2, + { 0, 5, 9}, + {FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 5, 9} }; + +static const SBR_FRAME_INFO frameInfo4_1152 = { + 4, + { 0, 2, 5, + 7, 9}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + { 0, 5, 9} }; + + +/* AACLD frame info */ +static const SBR_FRAME_INFO frameInfo1_512LD = { + 1, + {0, 8}, + {FREQ_RES_HIGH}, + 0, + 1, + {0, 8}}; + +static const SBR_FRAME_INFO frameInfo2_512LD = { + 2, + {0, 4, 8}, + {FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 4, 8}}; + +static const SBR_FRAME_INFO frameInfo4_512LD = { + 4, + {0, 2, 4, 6, 8}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 4, 8}}; + +static int +calcFillLengthMax (int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ + ); + +static void +fillFrameTran (const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ + ); + +static void fillFramePre (INT dmax, INT *v_bord, INT *length_v_bord, + INT *v_freq, INT *length_v_freq, INT bmin, + INT rest); + +static void fillFramePost (INT *parts, INT *d, INT dmax, INT *v_bord, + INT *length_v_bord, INT *v_freq, + INT *length_v_freq, INT bmax, + INT bufferFrameStart, INT numberTimeSlots, INT fmax); + +static void fillFrameInter (INT *nL, const int *v_tuningSegm, INT *v_bord, + INT *length_v_bord, INT bmin, INT *v_freq, + INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, + INT dmin, INT dmax, INT numberTimeSlots); + +static void calcFrameClass (FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, INT tranFlag, + INT *spreadFlag); + +static void specialCase (INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT *parts, INT d); + +static void calcCmonBorder (INT *i_cmon, INT *i_tran, INT *v_bord, + INT *length_v_bord, INT tran, + INT bufferFrameStart, INT numberTimeSlots); + +static void keepForFollowUp (INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, + INT *v_bord, INT *length_v_bord, INT *v_freq, + INT i_cmon, INT i_tran, INT parts, INT numberTimeSlots); + +static void calcCtrlSignal (HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, + INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, + INT spreadFlag, INT nL); + +static void ctrlSignal2FrameInfo (HANDLE_SBR_GRID hSbrGrid, + HANDLE_SBR_FRAME_INFO hFrameInfo, + FREQ_RES *freq_res_fixfix); + + +/* table for 8 time slot index */ +static const int envelopeTable_8 [8][5] = { +/* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ +/* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ { 2, 0, 0, 1, -1 }, + /*[|-T-|-----]*/ { 2, 0, 0, 2, -1 }, + /*[--|T-|----]*/ { 3, 1, 1, 2, 4 }, + /*[---|T-|---]*/ { 3, 1, 1, 3, 5 }, + /*[----|T-|--]*/ { 3, 1, 1, 4, 6 }, + /*[-----|T--|]*/ { 2, 1, 1, 5, -1 }, + /*[------|T-|]*/ { 2, 1, 1, 6, -1 }, + /*[-------|T|]*/ { 2, 1, 1, 7, -1 }, +}; + +/* table for 16 time slot index */ +static const int envelopeTable_16 [16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ { 2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ { 2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ { 3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ { 3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ { 3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ { 3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ { 3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ { 3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ { 3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ { 3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ { 3, 1, 1,10, 14, -1}, + /*[|-----------|T----|]*/ { 2, 1, 1,11, -1, -1}, + /*[|------------|T---|]*/ { 2, 1, 1,12, -1, -1}, + /*[|-------------|T--|]*/ { 2, 1, 1,13, -1, -1}, + /*[|--------------|T-|]*/ { 2, 1, 1,14, -1, -1}, + /*[|---------------|T|]*/ { 2, 1, 1,15, -1, -1}, +}; + +/* table for 15 time slot index */ +static const int envelopeTable_15 [15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ { 2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ { 2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ { 3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ { 3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ { 3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ { 3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ { 3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ { 3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ { 3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ { 3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ { 2, 1, 1,10, -1, -1}, + /*[|-----------|T---|]*/ { 2, 1, 1,11, -1, -1}, + /*[|------------|T--|]*/ { 2, 1, 1,12, -1, -1}, + /*[|-------------|T-|]*/ { 2, 1, 1,13, -1, -1}, + /*[|--------------|T|]*/ { 2, 1, 1,14, -1, -1}, +}; + +static const int minFrameTranDistance = 4; + +static const FREQ_RES freqRes_table_8[] = {FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, + FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}; + +static const FREQ_RES freqRes_table_16[16] = { + /* size of envelope */ +/* 0-4 */ FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, +/* 5-9 */ FREQ_RES_LOW, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, +/* 10-16 */ FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, + FREQ_RES_HIGH }; + +static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, + int tranPosInternal, + int numberTimeSlots, + UCHAR fResTransIsLow + ); + + +/*! + Functionname: FDKsbrEnc_frameInfoGenerator + + Description: produces the FRAME_INFO struct for the current frame + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + v_pre_transient_info - pointer to transient info vector + v_transient_info - pointer to previous transient info vector + v_tuning - pointer to tuning vector + + Return: frame_info - pointer to SBR_FRAME_INFO struct + +*******************************************************************************/ +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, + UCHAR *v_transient_info_pre, + int ldGrid, + const int *v_tuning) +{ + INT numEnv, tranPosInternal=0, bmin=0, bmax=0, parts, d, i_cmon=0, i_tran=0, nL; + INT fmax = 0; + + INT *v_bord = hSbrEnvFrame->v_bord; + INT *v_freq = hSbrEnvFrame->v_freq; + INT *v_bordFollow = hSbrEnvFrame->v_bordFollow; + INT *v_freqFollow = hSbrEnvFrame->v_freqFollow; + + + INT *length_v_bordFollow = &hSbrEnvFrame->length_v_bordFollow; + INT *length_v_freqFollow = &hSbrEnvFrame->length_v_freqFollow; + INT *length_v_bord = &hSbrEnvFrame->length_v_bord; + INT *length_v_freq = &hSbrEnvFrame->length_v_freq; + INT *spreadFlag = &hSbrEnvFrame->spreadFlag; + INT *i_tranFollow = &hSbrEnvFrame->i_tranFollow; + INT *i_fillFollow = &hSbrEnvFrame->i_fillFollow; + FRAME_CLASS *frameClassOld = &hSbrEnvFrame->frameClassOld; + FRAME_CLASS frameClass = FIXFIX; + + + INT allowSpread = hSbrEnvFrame->allowSpread; + INT numEnvStatic = hSbrEnvFrame->numEnvStatic; + INT staticFraming = hSbrEnvFrame->staticFraming; + INT dmin = hSbrEnvFrame->dmin; + INT dmax = hSbrEnvFrame->dmax; + + INT bufferFrameStart = hSbrEnvFrame->SbrGrid.bufferFrameStart; + INT numberTimeSlots = hSbrEnvFrame->SbrGrid.numberTimeSlots; + INT frameMiddleSlot = hSbrEnvFrame->frameMiddleSlot; + + INT tranPos = v_transient_info[0]; + INT tranFlag = v_transient_info[1]; + + const int *v_tuningSegm = v_tuning; + const int *v_tuningFreq = v_tuning + 3; + + hSbrEnvFrame->v_tuningSegm = v_tuningSegm; + + if (ldGrid) { + /* in case there was a transient at the very end of the previous frame, start with a transient envelope */ + if ( !tranFlag && v_transient_info_pre[1] && (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance) ){ + tranFlag = 1; + tranPos = 0; + } + } + + /* + * Synopsis: + * + * The frame generator creates the time-/frequency-grid for one SBR frame. + * Input signals are provided by the transient detector and the frame + * splitter (transientDetectNew() & FrameSplitter() in tran_det.c). The + * framing is controlled by adjusting tuning parameters stored in + * FRAME_GEN_TUNING. The parameter values are dependent on frame lengths + * and bitrates, and may in the future be signal dependent. + * + * The envelope borders are stored for frame generator internal use in + * aBorders. The contents of aBorders represent positions along the time + * axis given in the figures in fram_gen.h (the "frame-generator" rows). + * The unit is "time slot". The figures in fram_gen.h also define the + * detection ranges for the transient detector. For every border in + * aBorders, there is a corresponding entry in aFreqRes, which defines the + * frequency resolution of the envelope following (delimited by) the + * border. + * + * When no transients are present, FIXFIX class frames are used. The + * frame splitter decides whether to use one or two envelopes in the + * FIXFIX frame. "Sparse transients" (separated by a few frames without + * transients) are handeled by [FIXVAR, VARFIX] pairs or (depending on + * tuning and transient position relative the nominal frame boundaries) + * by [FIXVAR, VARVAR, VARFIX] triples. "Tight transients" (in + * consecutive frames) are handeled by [..., VARVAR, VARVAR, ...] + * sequences. + * + * The generator assumes that transients are "sparse", and designs + * borders for [FIXVAR, VARFIX] pairs right away, where the first frame + * corresponds to the present frame. At the next call of the generator + * it is known whether the transient actually is "sparse" or not. If + * 'yes', the already calculated VARFIX borders are used. If 'no', new + * borders, meeting the requirements of the "tight" transient, are + * calculated. + * + * The generator produces two outputs: A "clear-text bitstream" stored in + * SBR_GRID, and a straight-forward representation of the grid stored in + * SBR_FRAME_INFO. The former is subsequently converted to the actual + * bitstream sbr_grid() (encodeSbrGrid() in bit_sbr.c). The latter is + * used by other encoder functions, such as the envelope estimator + * (calculateSbrEnvelope() in env_est.c) and the noise floor and missing + * harmonics detector (TonCorrParamExtr() in nf_est.c). + */ + + if (staticFraming) { + /*-------------------------------------------------------------------------- + Ignore transient detector + ---------------------------------------------------------------------------*/ + + frameClass = FIXFIX; + numEnv = numEnvStatic; /* {1,2,4,8} */ + *frameClassOld = FIXFIX; /* for change to dyn */ + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + } + else { + /*-------------------------------------------------------------------------- + Calculate frame class to use + ---------------------------------------------------------------------------*/ + calcFrameClass (&frameClass, frameClassOld, tranFlag, spreadFlag); + + /* patch for new frame class FIXFIXonly for AAC LD */ + if (tranFlag && ldGrid) { + frameClass = FIXFIXonly; + *frameClassOld = FIXFIX; + } + + /* + * every transient is processed below by inserting + * + * - one border at the onset of the transient + * - one or more "decay borders" (after the onset of the transient) + * - optionally one "attack border" (before the onset of the transient) + * + * those borders are referred to as "mandatory borders" and are + * defined by the 'segmentLength' array in FRAME_GEN_TUNING + * + * the frequency resolutions of the corresponding envelopes are + * defined by the 'segmentRes' array in FRAME_GEN_TUNING + */ + + /*-------------------------------------------------------------------------- + Design frame (or follow-up old design) + ---------------------------------------------------------------------------*/ + if (tranFlag) { /* Always for FixVar, often but not always for VarVar */ + /*-------------------------------------------------------------------------- + Design part of T/F-grid around the new transient + ---------------------------------------------------------------------------*/ + + tranPosInternal = frameMiddleSlot + tranPos + bufferFrameStart ; /* FH 00-06-26 */ + /* + add mandatory borders around transient + */ + + fillFrameTran ( v_tuningSegm, + v_tuningFreq, + tranPosInternal, + v_bord, + length_v_bord, + v_freq, + length_v_freq, + &bmin, + &bmax ); + + /* make sure we stay within the maximum SBR frame overlap */ + fmax = calcFillLengthMax(tranPos, numberTimeSlots); + } + + switch (frameClass) { + + case FIXFIXonly: + FDK_ASSERT(ldGrid); + tranPosInternal = tranPos; + generateFixFixOnly ( &(hSbrEnvFrame->SbrFrameInfo), + &(hSbrEnvFrame->SbrGrid), + tranPosInternal, + numberTimeSlots, + hSbrEnvFrame->fResTransIsLow + ); + + return &(hSbrEnvFrame->SbrFrameInfo); + + case FIXVAR: + + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + ---------------------------------------------------------------------------*/ + + /*-------------------------------------------------------------------------- + Fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFramePre (dmax, v_bord, length_v_bord, v_freq, length_v_freq, + bmin, bmin - bufferFrameStart); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Fill region after new transient: + ---------------------------------------------------------------------------*/ + fillFramePost (&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /* no fill, short last envelope */ + specialCase (spreadFlag, allowSpread, v_bord, length_v_bord, + v_freq, length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder (&i_cmon, &i_tran, v_bord, length_v_bord, tranPosInternal, + bufferFrameStart, numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp (v_bordFollow, length_v_bordFollow, v_freqFollow, + length_v_freqFollow, i_tranFollow, i_fillFollow, + v_bord, length_v_bord, v_freq, i_cmon, i_tran, parts, numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal (&hSbrEnvFrame->SbrGrid, frameClass, + v_bord, *length_v_bord, v_freq, *length_v_freq, + i_cmon, i_tran, *spreadFlag, DC); + break; + case VARFIX: + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal (&hSbrEnvFrame->SbrGrid, frameClass, + v_bordFollow, *length_v_bordFollow, v_freqFollow, + *length_v_freqFollow, DC, *i_tranFollow, + *spreadFlag, DC); + break; + case VARVAR: + if (*spreadFlag) { /* spread across three frames */ + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal (&hSbrEnvFrame->SbrGrid, + frameClass, v_bordFollow, *length_v_bordFollow, + v_freqFollow, *length_v_freqFollow, DC, + *i_tranFollow, *spreadFlag, DC); + + *spreadFlag = 0; + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + v_bordFollow[0] = hSbrEnvFrame->SbrGrid.bs_abs_bord_1 - numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[0] = 1; + *length_v_bordFollow = 1; + *length_v_freqFollow = 1; + + *i_tranFollow = -DC; + *i_fillFollow = -DC; + } + else { + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + adapt or fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFrameInter (&nL, v_tuningSegm, v_bord, length_v_bord, bmin, + v_freq, length_v_freq, v_bordFollow, + length_v_bordFollow, v_freqFollow, + length_v_freqFollow, *i_fillFollow, dmin, dmax, + numberTimeSlots); + + /*-------------------------------------------------------------------------- + Fill after transient: + ---------------------------------------------------------------------------*/ + fillFramePost (&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /*% no fill, short last envelope */ + specialCase (spreadFlag, allowSpread, v_bord, length_v_bord, + v_freq, length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder (&i_cmon, &i_tran, v_bord, length_v_bord, tranPosInternal, + bufferFrameStart, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp (v_bordFollow, length_v_bordFollow, + v_freqFollow, length_v_freqFollow, + i_tranFollow, i_fillFollow, v_bord, + length_v_bord, v_freq, i_cmon, i_tran, parts, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal (&hSbrEnvFrame->SbrGrid, + frameClass, v_bord, *length_v_bord, v_freq, + *length_v_freq, i_cmon, i_tran, 0, nL); + } + break; + case FIXFIX: + if (tranPos == 0) + numEnv = 1; + else + numEnv = 2; + + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + + break; + default: + FDK_ASSERT(0); + } + } + + /*------------------------------------------------------------------------- + Convert control signal to frame info struct + ---------------------------------------------------------------------------*/ + ctrlSignal2FrameInfo (&hSbrEnvFrame->SbrGrid, + &hSbrEnvFrame->SbrFrameInfo, + hSbrEnvFrame->freq_res_fixfix); + + return &hSbrEnvFrame->SbrFrameInfo; +} + + +/***************************************************************************/ +/*! + \brief Gnerates frame info for FIXFIXonly frame class used for low delay version + + \return nothing + ****************************************************************************/ +static void generateFixFixOnly ( HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, + int tranPosInternal, + int numberTimeSlots, + UCHAR fResTransIsLow + ) +{ + int nEnv, i, k=0, tranIdx; + const int *pTable = NULL; + const FREQ_RES *freqResTable = NULL; + + switch (numberTimeSlots) { + case 8: + pTable = envelopeTable_8[tranPosInternal]; + freqResTable = freqRes_table_8; + break; + case 15: + pTable = envelopeTable_15[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + case 16: + pTable = envelopeTable_16[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + } + + /* look number of envolpes in table */ + nEnv = pTable[0]; + /* look up envolpe distribution in table */ + for (i=1; iborders[i] = pTable[i+2]; + + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + + /* adjust segment-frequency-resolution according to the segment-length */ + for (i=0; iborders[i+1] - hSbrFrameInfo->borders[i]; + if (!fResTransIsLow) + hSbrFrameInfo->freqRes[i] = freqResTable[k]; + else + hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; + + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i]; + } + + hSbrFrameInfo->nEnvelopes = nEnv; + hSbrFrameInfo->shortEnv = pTable[2]; + /* transient idx */ + tranIdx = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[tranIdx?tranIdx:1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + hSbrFrameInfo->nNoiseEnvelopes = 2; + + hSbrGrid->frameClass = FIXFIXonly; + hSbrGrid->bs_abs_bord = tranPosInternal; + hSbrGrid->bs_num_env = nEnv; + +} + + + +/******************************************************************************* + Functionname: FDKsbrEnc_initFrameInfoGenerator + ******************************************************************************* + + Description: + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + allowSpread - commandline parameter + numEnvStatic - commandline parameter + staticFraming - commandline parameter + + Return: none + +*******************************************************************************/ +void +FDKsbrEnc_initFrameInfoGenerator ( + HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, + INT numEnvStatic, + INT staticFraming, + INT timeSlots, + const FREQ_RES* freq_res_fixfix + ,UCHAR fResTransIsLow, + INT ldGrid + ) +{ /* FH 00-06-26 */ + + FDKmemclear(hSbrEnvFrame,sizeof(SBR_ENVELOPE_FRAME )); + + + /* Initialisation */ + hSbrEnvFrame->frameClassOld = FIXFIX; + hSbrEnvFrame->spreadFlag = 0; + + hSbrEnvFrame->allowSpread = allowSpread; + hSbrEnvFrame->numEnvStatic = numEnvStatic; + hSbrEnvFrame->staticFraming = staticFraming; + hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0]; + hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1]; + hSbrEnvFrame->fResTransIsLow = fResTransIsLow; + + hSbrEnvFrame->length_v_bord = 0; + hSbrEnvFrame->length_v_bordFollow = 0; + + hSbrEnvFrame->length_v_freq = 0; + hSbrEnvFrame->length_v_freqFollow = 0; + + hSbrEnvFrame->i_tranFollow = 0; + hSbrEnvFrame->i_fillFollow = 0; + + hSbrEnvFrame->SbrGrid.numberTimeSlots = timeSlots; + + if (ldGrid) { + /*case CODEC_AACLD:*/ + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 16; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + } else + switch(timeSlots){ + case NUMBER_TIME_SLOTS_1920: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1920; + break; + case NUMBER_TIME_SLOTS_2048: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1152: + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 8; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1152; + break; + case NUMBER_TIME_SLOTS_2304: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 15; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2304; + break; + default: + FDK_ASSERT(0); + } + +} + + +/******************************************************************************* + Functionname: fillFrameTran + ******************************************************************************* + + Description: Add mandatory borders, as described by the tuning vector + and the current transient position + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + bmin - int pointer to bmin (call by reference) + bmax - int pointer to bmax (call by reference) + not modified: + tran - position of transient + v_tuningSegm - int pointer to v_tuningSegm vector + v_tuningFreq - int pointer to v_tuningFreq vector + + Return: none + +*******************************************************************************/ +static void +fillFrameTran (const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ + ) +{ + int bord, i; + + *length_v_bord = 0; + *length_v_freq = 0; + + /* add attack env leading border (optional) */ + if (v_tuningSegm[0]) { + /* v_bord = [(Ba)] start of attack env */ + FDKsbrEnc_AddRight (v_bord, length_v_bord, (tran - v_tuningSegm[0])); + + /* v_freq = [(Fa)] res of attack env */ + FDKsbrEnc_AddRight (v_freq, length_v_freq, v_tuningFreq[0]); + } + + /* add attack env trailing border/first decay env leading border */ + bord = tran; + FDKsbrEnc_AddRight (v_bord, length_v_bord, tran); /* v_bord = [(Ba),Bd1] */ + + /* add first decay env trailing border/2:nd decay env leading border */ + if (v_tuningSegm[1]) { + bord += v_tuningSegm[1]; + + /* v_bord = [(Ba),Bd1,Bd2] */ + FDKsbrEnc_AddRight (v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1] */ + FDKsbrEnc_AddRight (v_freq, length_v_freq, v_tuningFreq[1]); + } + + /* add 2:nd decay env trailing border (optional) */ + if (v_tuningSegm[2] != 0) { + bord += v_tuningSegm[2]; + + /* v_bord = [(Ba),Bd1, Bd2,(Bd3)] */ + FDKsbrEnc_AddRight (v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1,(Fd2)] */ + FDKsbrEnc_AddRight (v_freq, length_v_freq, v_tuningFreq[2]); + } + + /* v_freq = [(Fa),Fd1,(Fd2),1] */ + FDKsbrEnc_AddRight (v_freq, length_v_freq, 1); + + + /* calc min and max values of mandatory borders */ + *bmin = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] < *bmin) + *bmin = v_bord[i]; + + *bmax = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] > *bmax) + *bmax = v_bord[i]; + +} + + + +/******************************************************************************* + Functionname: fillFramePre + ******************************************************************************* + + Description: Add borders before mandatory borders, if needed + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + dmax - int value + bmin - int value + rest - int value + + Return: none + +*******************************************************************************/ +static void +fillFramePre (INT dmax, + INT *v_bord, INT *length_v_bord, + INT *v_freq, INT *length_v_freq, + INT bmin, INT rest) +{ + /* + input state: + v_bord = [(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [(Fa),Fd1,(Fd2),1 ] + */ + + INT parts, d, j, S, s = 0, segm, bord; + + /* + start with one envelope + */ + + parts = 1; + d = rest; + + /* + calc # of additional envelopes and corresponding lengths + */ + + while (d > dmax) { + parts++; + + segm = rest / parts; + S = (segm - 2)>>1; + s = fixMin (8, 2 * S + 2); + d = rest - (parts - 1) * s; + } + + /* + add borders before mandatory borders + */ + + bord = bmin; + + for (j = 0; j <= parts - 2; j++) { + bord = bord - s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] */ + FDKsbrEnc_AddLeft (v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 ] */ + FDKsbrEnc_AddLeft (v_freq, length_v_freq, 1); + } +} + +/***************************************************************************/ +/*! + \brief Overlap control + + Calculate max length of trailing fill segments, such that we always get a + border within the frame overlap region + + \return void + +****************************************************************************/ +static int +calcFillLengthMax (int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ + ) +{ + int fmax; + + /* + calculate transient position within envelope buffer + */ + switch (numberTimeSlots) + { + case NUMBER_TIME_SLOTS_2048: + if (tranPos < 4) + fmax = 6; + else if (tranPos == 4 || tranPos == 5) + fmax = 4; + else + fmax = 8; + break; + + case NUMBER_TIME_SLOTS_1920: + if (tranPos < 4) + fmax = 5; + else if (tranPos == 4 || tranPos == 5) + fmax = 3; + else + fmax = 7; + break; + + default: + fmax = 8; + break; + } + + return fmax; +} + +/******************************************************************************* + Functionname: fillFramePost + ******************************************************************************* + + Description: -Add borders after mandatory borders, if needed + Make a preliminary design of next frame, + assuming no transient is present there + + Arguments: + modified: + parts - int pointer to parts (call by reference) + d - int pointer to d (call by reference) + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + bmax - int value + dmax - int value + + Return: none + +*******************************************************************************/ +static void +fillFramePost (INT *parts, INT *d, INT dmax, INT *v_bord, INT *length_v_bord, + INT *v_freq, INT *length_v_freq, INT bmax, + INT bufferFrameStart, INT numberTimeSlots, INT fmax) +{ + INT j, rest, segm, S, s = 0, bord; + + /* + input state: + v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [...,(1 ),(Fa),Fd1,(Fd2),1 ] + */ + + rest = bufferFrameStart + 2 * numberTimeSlots - bmax; + *d = rest; + + if (*d > 0) { + *parts = 1; /* start with one envelope */ + + /* calc # of additional envelopes and corresponding lengths */ + + while (*d > dmax) { + *parts = *parts + 1; + + segm = rest / (*parts); + S = (segm - 2)>>1; + s = fixMin (fmax, 2 * S + 2); + *d = rest - (*parts - 1) * s; + } + + /* add borders after mandatory borders */ + + bord = bmax; + for (j = 0; j <= *parts - 2; j++) { + bord += s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3),(Bf)] */ + FDKsbrEnc_AddRight (v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 , 1! ,1] */ + FDKsbrEnc_AddRight (v_freq, length_v_freq, 1); + } + } + else { + *parts = 1; + + /* remove last element from v_bord and v_freq */ + + *length_v_bord = *length_v_bord - 1; + *length_v_freq = *length_v_freq - 1; + + } +} + + + +/******************************************************************************* + Functionname: fillFrameInter + ******************************************************************************* + + Description: + + Arguments: nL - + v_tuningSegm - + v_bord - + length_v_bord - + bmin - + v_freq - + length_v_freq - + v_bordFollow - + length_v_bordFollow - + v_freqFollow - + length_v_freqFollow - + i_fillFollow - + dmin - + dmax - + + Return: none + +*******************************************************************************/ +static void +fillFrameInter (INT *nL, const int *v_tuningSegm, INT *v_bord, INT *length_v_bord, + INT bmin, INT *v_freq, INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, INT dmin, + INT dmax, INT numberTimeSlots) +{ + INT middle, b_new, numBordFollow, bordMaxFollow, i; + + if (numberTimeSlots != NUMBER_TIME_SLOTS_1152) { + + /* % remove fill borders: */ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /* remove even more borders if needed */ + middle = bmin - bordMaxFollow; + while (middle < 0) { + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + *nL = numBordFollow - 1; + + b_new = *length_v_bord; + + + if (middle <= dmax) { + if (middle >= dmin) { /* concatenate */ + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, *length_v_freqFollow); + } + + else { + if (v_tuningSegm[0] != 0) { /* remove one new border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft (v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + else { + if (*length_v_bordFollow > 1) { /* remove one old border and concatenate */ + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } + else { /* remove new "transient" border and concatenate */ + + for (i = 0; i < *length_v_bord - 1; i++) + v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) + v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } + } + } + else { /* middle > dmax */ + + fillFramePre (dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, *length_v_freqFollow); + } + + + } + else { /* numberTimeSlots==NUMBER_TIME_SLOTS_1152 */ + + INT l,m; + + + /*------------------------------------------------------------------------ + remove fill borders + ------------------------------------------------------------------------*/ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /*------------------------------------------------------------------------ + remove more borders if necessary to eliminate overlap + ------------------------------------------------------------------------*/ + + /* check for overlap */ + middle = bmin - bordMaxFollow; + + /* intervals: + i) middle < 0 : overlap, must remove borders + ii) 0 <= middle < dmin : no overlap but too tight, must remove borders + iii) dmin <= middle <= dmax : ok, just concatenate + iv) dmax <= middle : too wide, must add borders + */ + + /* first remove old non-fill-borders... */ + while (middle < 0) { + + /* ...but don't remove all of them */ + if (numBordFollow == 1) + break; + + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + /* if this isn't enough, remove new non-fill borders */ + if (middle < 0) + { + for (l = 0, m = 0 ; l < *length_v_bord ; l++) + { + if(v_bord[l]> bordMaxFollow) + { + v_bord[m] = v_bord[l]; + v_freq[m] = v_freq[l]; + m++; + } + } + + *length_v_bord = l; + *length_v_freq = l; + + bmin = v_bord[0]; + + } + + /*------------------------------------------------------------------------ + update modified follow-up data + ------------------------------------------------------------------------*/ + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + + /* left relative borders correspond to follow-up */ + *nL = numBordFollow - 1; + + /*------------------------------------------------------------------------ + take care of intervals ii through iv + ------------------------------------------------------------------------*/ + + /* now middle should be >= 0 */ + middle = bmin - bordMaxFollow; + + if (middle <= dmin) /* (ii) */ + { + b_new = *length_v_bord; + + if (v_tuningSegm[0] != 0) + { + /* remove new "luxury" border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft (v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + + } + else if (*length_v_bordFollow > 1) + { + /* remove old border and concatenate */ + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } + else + { + /* remove new border and concatenate */ + for (i = 0; i < *length_v_bord - 1; i++) + v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) + v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } + else if ((middle >= dmin) && (middle <= dmax)) /* (iii) */ + { + /* concatenate */ + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, *length_v_freqFollow); + + } + else /* (iv) */ + { + fillFramePre (dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft (v_bord, length_v_bord, v_bordFollow, *length_v_bordFollow); + FDKsbrEnc_AddVecLeft (v_freq, length_v_freq, v_freqFollow, *length_v_freqFollow); + } + } +} + + + +/******************************************************************************* + Functionname: calcFrameClass + ******************************************************************************* + + Description: + + Arguments: INT* frameClass, INT* frameClassOld, INT tranFlag, INT* spreadFlag) + + Return: none + +*******************************************************************************/ +static void +calcFrameClass (FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, INT tranFlag, + INT *spreadFlag) +{ + + switch (*frameClassOld) { + case FIXFIXonly: + case FIXFIX: + if (tranFlag) *frameClass = FIXVAR; + else *frameClass = FIXFIX; + break; + case FIXVAR: + if (tranFlag) { *frameClass = VARVAR; *spreadFlag = 0; } + else { + if (*spreadFlag) *frameClass = VARVAR; + else *frameClass = VARFIX; + } + break; + case VARFIX: + if (tranFlag) *frameClass = FIXVAR; + else *frameClass = FIXFIX; + break; + case VARVAR: + if (tranFlag) { *frameClass = VARVAR; *spreadFlag = 0; } + else { + if (*spreadFlag) *frameClass = VARVAR; + else *frameClass = VARFIX; + } + break; + }; + + *frameClassOld = *frameClass; +} + + + +/******************************************************************************* + Functionname: specialCase + ******************************************************************************* + + Description: + + Arguments: spreadFlag + allowSpread + v_bord + length_v_bord + v_freq + length_v_freq + parts + d + + Return: none + +*******************************************************************************/ +static void +specialCase (INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, INT *parts, + INT d) +{ + INT L; + + L = *length_v_bord; + + if (allowSpread) { /* add one "step 8" */ + *spreadFlag = 1; + FDKsbrEnc_AddRight (v_bord, length_v_bord, v_bord[L - 1] + 8); + FDKsbrEnc_AddRight (v_freq, length_v_freq, 1); + (*parts)++; + } + else { + if (d == 1) { /* stretch one slot */ + *length_v_bord = L - 1; + *length_v_freq = L - 1; + } + else { + if ((v_bord[L - 1] - v_bord[L - 2]) > 2) { /* compress one quant step */ + v_bord[L - 1] = v_bord[L - 1] - 2; + v_freq[*length_v_freq - 1] = 0; /* use low res for short segment */ + } + } + } +} + + + +/******************************************************************************* + Functionname: calcCmonBorder + ******************************************************************************* + + Description: + + Arguments: i_cmon + i_tran + v_bord + length_v_bord + tran + + Return: none + +*******************************************************************************/ +static void +calcCmonBorder (INT *i_cmon, INT *i_tran, INT *v_bord, INT *length_v_bord, + INT tran, INT bufferFrameStart, INT numberTimeSlots) +{ /* FH 00-06-26 */ + INT i; + + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= bufferFrameStart + numberTimeSlots) { /* FH 00-06-26 */ + *i_cmon = i; + break; + } + + /* keep track of transient: */ + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= tran) { + *i_tran = i; + break; + } + else + *i_tran = EMPTY; +} + +/******************************************************************************* + Functionname: keepForFollowUp + ******************************************************************************* + + Description: + + Arguments: v_bordFollow + length_v_bordFollow + v_freqFollow + length_v_freqFollow + i_tranFollow + i_fillFollow + v_bord + length_v_bord + v_freq + i_cmon + i_tran + parts) + + Return: none + +*******************************************************************************/ +static void +keepForFollowUp (INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT i_cmon, INT i_tran, + INT parts, INT numberTimeSlots) +{ /* FH 00-06-26 */ + INT L, i, j; + + L = *length_v_bord; + + (*length_v_bordFollow) = 0; + (*length_v_freqFollow) = 0; + + for (j = 0, i = i_cmon; i < L; i++, j++) { + v_bordFollow[j] = v_bord[i] - numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[j] = v_freq[i]; + (*length_v_bordFollow)++; + (*length_v_freqFollow)++; + } + if (i_tran != EMPTY) + *i_tranFollow = i_tran - i_cmon; + else + *i_tranFollow = EMPTY; + *i_fillFollow = L - (parts - 1) - i_cmon; + +} + +/******************************************************************************* + Functionname: calcCtrlSignal + ******************************************************************************* + + Description: + + Arguments: hSbrGrid + frameClass + v_bord + length_v_bord + v_freq + length_v_freq + i_cmon + i_tran + spreadFlag + nL + + Return: none + +*******************************************************************************/ +static void +calcCtrlSignal (HANDLE_SBR_GRID hSbrGrid, + FRAME_CLASS frameClass, INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, INT spreadFlag, + INT nL) +{ + + + INT i, r, a, n, p, b, aL, aR, ntot, nmax, nR; + + INT *v_f = hSbrGrid->v_f; + INT *v_fLR = hSbrGrid->v_fLR; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_rL = hSbrGrid->bs_rel_bord_0; + INT *v_rR = hSbrGrid->bs_rel_bord_1; + + INT length_v_r = 0; + INT length_v_rR = 0; + INT length_v_rL = 0; + + switch (frameClass) { + case FIXVAR: + /* absolute border: */ + + a = v_bord[i_cmon]; + + /* relative borders: */ + length_v_r = 0; + i = i_cmon; + + while (i >= 1) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_r, &length_v_r, r); + i--; + } + + + /* number of relative borders: */ + n = length_v_r; + + + /* freq res: */ + for (i = 0; i < i_cmon; i++) + v_f[i] = v_freq[i_cmon - 1 - i]; + v_f[i_cmon] = 1; + + /* pointer: */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0) ; + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARFIX: + /* absolute border: */ + a = v_bord[0]; + + /* relative borders: */ + length_v_r = 0; + + for (i = 1; i < length_v_bord; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_r, &length_v_r, r); + } + + /* number of relative borders: */ + n = length_v_r; + + /* freq res: */ + FDKmemcpy (v_f, v_freq, length_v_freq * sizeof (INT)); + + + /* pointer: */ + p = (i_tran >= 0 && i_tran != EMPTY) ? (i_tran + 1) : (0) ; + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARVAR: + if (spreadFlag) { + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + + /* number of relative borders: */ + ntot = b - 2; + + nmax = 2; /* n: {0,1,2} */ + if (ntot > nmax) { + nL = nmax; + nR = ntot - nmax; + } + else { + nL = ntot; + nR = 0; + } + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_tran > 0 && i_tran != EMPTY) ? (b - i_tran) : (0) ; + + /* freq res: */ + + for (i = 0; i < b - 1; i++) + v_fLR[i] = v_freq[i]; + } + else { + + length_v_bord = i_cmon + 1; + length_v_freq = i_cmon + 1; + + + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + /* number of relative borders: */ + ntot = b - 2; + nR = ntot - nL; + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight (v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0) ; + + /* freq res: */ + for (i = 0; i < b - 1; i++) + v_fLR[i] = v_freq[i]; + } + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord_0 = aL; + hSbrGrid->bs_abs_bord_1 = aR; + hSbrGrid->bs_num_rel_0 = nL; + hSbrGrid->bs_num_rel_1 = nR; + hSbrGrid->p = p; + + break; + + default: + /* do nothing */ + break; + } +} + +/******************************************************************************* + Functionname: createDefFrameInfo + ******************************************************************************* + + Description: Copies the default (static) frameInfo structs to the frameInfo + passed by reference; only used for FIXFIX frames + + Arguments: hFrameInfo - HANLDE_SBR_FRAME_INFO + nEnv - INT + nTimeSlots - INT + + Return: none; hSbrFrameInfo contains a copy of the default frameInfo + + Written: Andreas Schneider + Revised: +*******************************************************************************/ +static void +createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, INT nTimeSlots) +{ + switch (nEnv) { + case 1: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy (hSbrFrameInfo, &frameInfo1_1920, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy (hSbrFrameInfo, &frameInfo1_2048, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy (hSbrFrameInfo, &frameInfo1_1152, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy (hSbrFrameInfo, &frameInfo1_2304, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy (hSbrFrameInfo, &frameInfo1_512LD, sizeof (SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy (hSbrFrameInfo, &frameInfo2_1920, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy (hSbrFrameInfo, &frameInfo2_2048, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy (hSbrFrameInfo, &frameInfo2_1152, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy (hSbrFrameInfo, &frameInfo2_2304, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy (hSbrFrameInfo, &frameInfo2_512LD, sizeof (SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy (hSbrFrameInfo, &frameInfo4_1920, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy (hSbrFrameInfo, &frameInfo4_2048, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy (hSbrFrameInfo, &frameInfo4_1152, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy (hSbrFrameInfo, &frameInfo4_2304, sizeof (SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy (hSbrFrameInfo, &frameInfo4_512LD, sizeof (SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + default: + FDK_ASSERT(0); + } +} + + +/******************************************************************************* + Functionname: ctrlSignal2FrameInfo + ******************************************************************************* + + Description: Convert "clear-text" sbr_grid() to "frame info" used by the + envelope and noise floor estimators. + This is basically (except for "low level" calculations) the + bitstream decoder defined in the MPEG-4 standard, sub clause + 4.6.18.3.3, Time / Frequency Grid. See inline comments for + explanation of the shorten and noise border algorithms. + + Arguments: hSbrGrid - source + hSbrFrameInfo - destination + freq_res_fixfix - frequency resolution for FIXFIX frames + + Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct + +*******************************************************************************/ +static void +ctrlSignal2FrameInfo ( + HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */ + HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */ + FREQ_RES *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */ + ) +{ + INT frameSplit = 0; + INT nEnv = 0, border = 0, i, k, p /*?*/; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_f = hSbrGrid->v_f; + + FRAME_CLASS frameClass = hSbrGrid->frameClass; + INT bufferFrameStart = hSbrGrid->bufferFrameStart; + INT numberTimeSlots = hSbrGrid->numberTimeSlots; + + switch (frameClass) { + case FIXFIX: + createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots); + + frameSplit = (hSbrFrameInfo->nEnvelopes > 1); + for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] = freq_res_fixfix[frameSplit]; + } + break; + + case FIXVAR: + case VARFIX: + nEnv = hSbrGrid->n + 1; /* read n [SBR_NUM_BITS bits] */ /*? snd*/ + FDK_ASSERT(nEnv <= MAX_ENVELOPES_FIXVAR_VARFIX); + + hSbrFrameInfo->nEnvelopes = nEnv; + + border = hSbrGrid->bs_abs_bord; /* read the absolute border */ + + if (nEnv == 1) + hSbrFrameInfo->nNoiseEnvelopes = 1; + else + hSbrFrameInfo->nNoiseEnvelopes = 2; + + break; + + default: + /* do nothing */ + break; + } + + switch (frameClass) { + case FIXVAR: + hSbrFrameInfo->borders[0] = bufferFrameStart; /* start-position of 1st envelope */ + + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < nEnv - 1; k++, i--) { + border -= v_r[k]; + hSbrFrameInfo->borders[i] = border; + } + + /* make either envelope nr. nEnv + 1 - p short; or don't shorten if p == 0 */ + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0, i = nEnv - 1; k < nEnv; k++, i--) { + hSbrFrameInfo->freqRes[i] = (FREQ_RES)v_f[k]; + } + + /* if either there is no short envelope or the last envelope is short... */ + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + + break; + + case VARFIX: + /* in this case 'border' indicates the start of the 1st envelope */ + hSbrFrameInfo->borders[0] = border; + + for (k = 0; k < nEnv - 1; k++) { + border += v_r[k]; + hSbrFrameInfo->borders[k + 1] = border; + } + + hSbrFrameInfo->borders[nEnv] = bufferFrameStart + numberTimeSlots; + + p = hSbrGrid->p; + if (p == 0 || p == 1) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = p - 1; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)v_f[k]; + } + + switch (p) { + case 0: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[1]; + break; + case 1: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + break; + default: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + break; + } + break; + + case VARVAR: + nEnv = hSbrGrid->bs_num_rel_0 + hSbrGrid->bs_num_rel_1 + 1; + FDK_ASSERT(nEnv <= MAX_ENVELOPES_VARVAR); /* just to be sure */ + hSbrFrameInfo->nEnvelopes = nEnv; + + hSbrFrameInfo->borders[0] = border = hSbrGrid->bs_abs_bord_0; + + for (k = 0, i = 1; k < hSbrGrid->bs_num_rel_0; k++, i++) { + border += hSbrGrid->bs_rel_bord_0[k]; + hSbrFrameInfo->borders[i] = border; + } + + border = hSbrGrid->bs_abs_bord_1; + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < hSbrGrid->bs_num_rel_1; k++, i--) { + border -= hSbrGrid->bs_rel_bord_1[k]; + hSbrFrameInfo->borders[i] = border; + } + + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)hSbrGrid->v_fLR[k]; + } + + if (nEnv == 1) { + hSbrFrameInfo->nNoiseEnvelopes = 1; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + hSbrFrameInfo->bordersNoise[1] = hSbrGrid->bs_abs_bord_1; + } else { + hSbrFrameInfo->nNoiseEnvelopes = 2; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + hSbrFrameInfo->bordersNoise[2] = hSbrGrid->bs_abs_bord_1; + } + break; + + default: + /* do nothing */ + break; + } + + if (frameClass == VARFIX || frameClass == FIXVAR) { + hSbrFrameInfo->bordersNoise[0] = hSbrFrameInfo->borders[0]; + if (nEnv == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv]; + } else { + hSbrFrameInfo->bordersNoise[2] = hSbrFrameInfo->borders[nEnv]; + } + } +} + diff --git a/libSBRenc/src/fram_gen.h b/libSBRenc/src/fram_gen.h new file mode 100644 index 00000000..00473d47 --- /dev/null +++ b/libSBRenc/src/fram_gen.h @@ -0,0 +1,309 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Framing generator prototypes and structs +*/ +#ifndef _FRAM_GEN_H +#define _FRAM_GEN_H + +#include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */ +#include "sbr_encoder.h" /* for FREQ_RES */ + +#define MAX_ENVELOPES_VARVAR MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */ +#define MAX_ENVELOPES_FIXVAR_VARFIX 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */ +#define MAX_NUM_REL 3 /*!< maximum number of relative borders in any VAR frame */ + +/* SBR frame class definitions */ +typedef enum { + FIXFIX = 0, /*!< bs_frame_class: leading and trailing frame borders are fixed */ + FIXVAR, /*!< bs_frame_class: leading frame border is fixed, trailing frame border is variable */ + VARFIX, /*!< bs_frame_class: leading frame border is variable, trailing frame border is fixed */ + VARVAR /*!< bs_frame_class: leading and trailing frame borders are variable */ + ,FIXFIXonly /*!< bs_frame_class: leading border fixed (0), trailing border fixed (nrTimeSlots) and encased borders are dynamically derived from the tranPos */ +}FRAME_CLASS; + + +/* helper constants */ +#define DC 4711 /*!< helper constant: don't care */ +#define EMPTY (-99) /*!< helper constant: empty */ + + +/* system constants: AAC+SBR, DRM Frame-Length */ +#define FRAME_MIDDLE_SLOT_1920 4 +#define NUMBER_TIME_SLOTS_1920 15 + +#define LD_PRETRAN_OFF 3 +#define FRAME_MIDDLE_SLOT_512LD 4 +#define NUMBER_TIME_SLOTS_512LD 8 +#define TRANSIENT_OFFSET_LD 0 + + + +/* +system constants: AAC+SBR or aacPRO (hybrid format), Standard Frame-Length, Multi-Rate +--------------------------------------------------------------------------- +Number of slots (numberTimeSlots): 16 (NUMBER_TIME_SLOTS_2048) +Detector-offset (frameMiddleSlot): 4 +Overlap : 3 +Buffer-offset : 8 (BUFFER_FRAME_START_2048 = 0) + + + |<------------tranPos---------->| + |c|d|e|f|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 +................................................................................ + +|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| + +frame-generator:0 16 24 32 +analysis-buffer:8 24 32 40 +*/ +#define FRAME_MIDDLE_SLOT_2048 4 +#define NUMBER_TIME_SLOTS_2048 16 + + +/* +system constants: mp3PRO, Multi-Rate & Single-Rate +-------------------------------------------------- +Number of slots (numberTimeSlots): 9 (NUMBER_TIME_SLOTS_1152) +Detector-offset (frameMiddleSlot): 4 (FRAME_MIDDLE_SLOT_1152) +Overlap : 3 +Buffer-offset : 4.5 (BUFFER_FRAME_START_1152 = 0) + + + |<----tranPos---->| + |5|6|7|8|0|1|2|3|4|5|6|7|8| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 0 1 2 3 + ............................................. + + -|-|-|-|-B-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-| + +frame-generator: 0 9 13 18 +analysis-buffer: 4.5 13.5 22.5 +*/ +#define FRAME_MIDDLE_SLOT_1152 4 +#define NUMBER_TIME_SLOTS_1152 9 + + +/* system constants: Layer2+SBR */ +#define FRAME_MIDDLE_SLOT_2304 8 +#define NUMBER_TIME_SLOTS_2304 18 + + +/*! + \struct SBR_GRID + \brief sbr_grid() signals to be converted to bitstream elements + + The variables hold the signals (e.g. lengths and numbers) in "clear text" +*/ + +typedef struct +{ + /* system constants */ + INT bufferFrameStart; /*!< frame generator vs analysis buffer time alignment (currently set to 0, offset added elsewhere) */ + INT numberTimeSlots; /*!< number of SBR timeslots per frame */ + + /* will be adjusted for every frame */ + FRAME_CLASS frameClass; /*!< SBR frame class */ + INT bs_num_env; /*!< bs_num_env, number of envelopes for FIXFIX */ + INT bs_abs_bord; /*!< bs_abs_bord, absolute border for VARFIX and FIXVAR */ + INT n; /*!< number of relative borders for VARFIX and FIXVAR */ + INT p; /*!< pointer-to-transient-border */ + INT bs_rel_bord[MAX_NUM_REL]; /*!< bs_rel_bord, relative borders for all VAR */ + INT v_f[MAX_ENVELOPES_FIXVAR_VARFIX]; /*!< envelope frequency resolutions for FIXVAR and VARFIX */ + + INT bs_abs_bord_0; /*!< bs_abs_bord_0, leading absolute border for VARVAR */ + INT bs_abs_bord_1; /*!< bs_abs_bord_1, trailing absolute border for VARVAR */ + INT bs_num_rel_0; /*!< bs_num_rel_0, number of relative borders associated with leading absolute border for VARVAR */ + INT bs_num_rel_1; /*!< bs_num_rel_1, number of relative borders associated with trailing absolute border for VARVAR */ + INT bs_rel_bord_0[MAX_NUM_REL]; /*!< bs_rel_bord_0, relative borders associated with leading absolute border for VARVAR */ + INT bs_rel_bord_1[MAX_NUM_REL]; /*!< bs_rel_bord_1, relative borders associated with trailing absolute border for VARVAR */ + INT v_fLR[MAX_ENVELOPES_VARVAR]; /*!< envelope frequency resolutions for VARVAR */ + +} +SBR_GRID; +typedef SBR_GRID *HANDLE_SBR_GRID; + + + +/*! + \struct SBR_FRAME_INFO + \brief time/frequency grid description for one frame +*/ +typedef struct +{ + INT nEnvelopes; /*!< number of envelopes */ + INT borders[MAX_ENVELOPES+1]; /*!< envelope borders in SBR timeslots */ + FREQ_RES freqRes[MAX_ENVELOPES]; /*!< frequency resolution of each envelope */ + INT shortEnv; /*!< number of an envelope to be shortened (starting at 1) or 0 for no shortened envelope */ + INT nNoiseEnvelopes; /*!< number of noise floors */ + INT bordersNoise[MAX_NOISE_ENVELOPES+1];/*!< noise floor borders in SBR timeslots */ +} +SBR_FRAME_INFO; +/* WARNING: When rearranging the elements of this struct keep in mind that the static + * initializations in the corresponding C-file have to be rearranged as well! + * snd 2002/01/23 + */ +typedef SBR_FRAME_INFO *HANDLE_SBR_FRAME_INFO; + + +/*! + \struct SBR_ENVELOPE_FRAME + \brief frame generator main struct + + Contains tuning parameters, time/frequency grid description, sbr_grid() bitstream elements, and generator internal signals +*/ +typedef struct +{ + /* system constants */ + INT frameMiddleSlot; /*!< transient detector offset in SBR timeslots */ + + /* basic tuning parameters */ + INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of bs_frame_class = FIXFIX */ + INT numEnvStatic; /*!< number of envelopes per frame for static framing */ + FREQ_RES freq_res_fixfix[2]; /*!< envelope frequency resolution to use for bs_frame_class = FIXFIX; single env and split */ + UCHAR fResTransIsLow; /*!< frequency resolution for transient frames - always low (0) or according to table (1) */ + + /* expert tuning parameters */ + const int *v_tuningSegm; /*!< segment lengths to use around transient */ + const int *v_tuningFreq; /*!< frequency resolutions to use around transient */ + INT dmin; /*!< minimum length of dependent segments */ + INT dmax; /*!< maximum length of dependent segments */ + INT allowSpread; /*!< 1: allow isolated transient to influence grid of 3 consecutive frames */ + + /* internally used signals */ + FRAME_CLASS frameClassOld; /*!< frame class used for previous frame */ + INT spreadFlag; /*!< 1: use VARVAR instead of VARFIX to follow up old transient */ + + INT v_bord[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< borders for current frame and preliminary borders for next frame (fixed borders excluded) */ + INT length_v_bord; /*!< helper variable: length of v_bord */ + INT v_freq[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< frequency resolutions for current frame and preliminary resolutions for next frame */ + INT length_v_freq; /*!< helper variable: length of v_freq */ + + INT v_bordFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary borders for current frame (calculated during previous frame) */ + INT length_v_bordFollow; /*!< helper variable: length of v_bordFollow */ + INT i_tranFollow; /*!< points to transient border in v_bordFollow (may be negative, see keepForFollowUp()) */ + INT i_fillFollow; /*!< points to first fill border in v_bordFollow */ + INT v_freqFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary frequency resolutions for current frame (calculated during previous frame) */ + INT length_v_freqFollow; /*!< helper variable: length of v_freqFollow */ + + + /* externally needed signals */ + SBR_GRID SbrGrid; /*!< sbr_grid() signals to be converted to bitstream elements */ + SBR_FRAME_INFO SbrFrameInfo; /*!< time/frequency grid description for one frame */ +} +SBR_ENVELOPE_FRAME; +typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME; + + + +void +FDKsbrEnc_initFrameInfoGenerator ( + HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, + INT numEnvStatic, + INT staticFraming, + INT timeSlots, + const FREQ_RES* freq_res_fixfix + ,UCHAR fResTransIsLow, + INT ldGrid + ); + +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator (HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, + UCHAR *v_transient_info_pre, + int ldGrid, + const int *v_tuning); + +#endif diff --git a/libSBRenc/src/invf_est.cpp b/libSBRenc/src/invf_est.cpp new file mode 100644 index 00000000..32df6d9d --- /dev/null +++ b/libSBRenc/src/invf_est.cpp @@ -0,0 +1,529 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "invf_est.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define MAX_NUM_REGIONS 10 +#define SCALE_FAC_QUO 512.0f +#define SCALE_FAC_NRG 256.0f + +#ifndef min +#define min(a,b) ( a < b ? a:b) +#endif + +#ifndef max +#define max(a,b) ( a > b ? a:b) +#endif + +static const FIXP_DBL quantStepsSbr[4] = { 0x00400000, 0x02800000, 0x03800000, 0x04c00000 } ; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL quantStepsOrig[4] = { 0x00000000, 0x00c00000, 0x01c00000, 0x02800000 } ; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL nrgBorders[4] = { 0x0c800000, 0x0f000000, 0x11800000, 0x14000000 } ; /* table scaled with SCALE_FAC_NRG */ + +static const DETECTOR_PARAMETERS detectorParamsAAC = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { /* Region space. */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ + },/*------------------------ regionOrig ---------------------------------*/ + { /* Region space transient. */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ + },/*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +static const FIXP_DBL hysteresis = 0x00400000 ; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */ + +/* + * AAC+SBR PARAMETERS for Speech + *********************************/ +static const DETECTOR_PARAMETERS detectorParamsAACSpeech = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { /* Region space. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ + },/*------------------------ regionOrig ---------------------------------*/ + { /* Region space transient. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, INVF_OFF} /* | */ + },/*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +/* + * Smoothing filters. + ************************/ +typedef const FIXP_DBL FIR_FILTER[5]; + +static const FIR_FILTER fir_0 = { 0x7fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } ; +static const FIR_FILTER fir_1 = { 0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, 0x00000000 } ; +static const FIR_FILTER fir_2 = { 0x10000000, 0x30000000, 0x40000000, 0x00000000, 0x00000000 } ; +static const FIR_FILTER fir_3 = { 0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, 0x00000000 } ; +static const FIR_FILTER fir_4 = { 0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, 0x2aaaaa80 } ; + + +static const FIR_FILTER *const fir_table[5] = { + &fir_0, + &fir_1, + &fir_2, + &fir_3, + &fir_4 +}; + +/**************************************************************************/ +/*! + \brief Calculates the values used for the detector. + + + \return none + +*/ +/**************************************************************************/ +static void +calculateDetectorValues(FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + FIXP_DBL *nrgVector, /*!< Energy vector. */ + DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ + INT startChannel, /*!< Start channel. */ + INT stopChannel, /*!< Stop channel. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT numberOfStrongest /*!< The number of sorted tonal components to be considered. */ + ) +{ + INT i,temp, j; + + const FIXP_DBL* filter = *fir_table[INVF_SMOOTHING_LENGTH]; + FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; + FIXP_DBL origQuota, sbrQuota; + FIXP_DBL invIndex, invChannel, invTemp; + FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; + + FDKmemclear(quotaVecOrig,64*sizeof(FIXP_DBL)); + FDKmemclear(quotaVecSbr,64*sizeof(FIXP_DBL)); + + invIndex = GetInvInt(stopIndex-startIndex); + invChannel = GetInvInt(stopChannel-startChannel); + + /* + Calculate the mean value, over the current time segment, for the original, the HFR + and the difference, over all channels in the current frequency range. + NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). + */ + + /* The original, the sbr signal and the total energy */ + detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); + for(j=startIndex; javgNrg += fMult(nrgVector[j], invIndex); + } + + /* + Calculate the mean value, over the current frequency range, for the original, the HFR + and the difference. Also calculate the same mean values for the three vectors, but only + includeing the x strongest copmponents. + */ + + origQuota = FL2FXCONST_DBL(0.0f); + sbrQuota = FL2FXCONST_DBL(0.0f); + for(i=startChannel; iorigQuotaMax = quotaVecOrig[stopChannel - 1]; + detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; + + /* + Buffer values + */ + FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->origQuotaMeanStrongest, detectorValues->origQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMeanStrongest, detectorValues->sbrQuotaMeanStrongest + 1, INVF_SMOOTHING_LENGTH*sizeof(FIXP_DBL)); + + detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota<<1; + detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota<<1; + detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = origQuotaMeanStrongest<<1; + detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = sbrQuotaMeanStrongest<<1; + + /* + Filter values + */ + detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + + for(i=0;iorigQuotaMeanFilt += fMult(detectorValues->origQuotaMean[i], filter[i]); + detectorValues->sbrQuotaMeanFilt += fMult(detectorValues->sbrQuotaMean[i], filter[i]); + detectorValues->origQuotaMeanStrongestFilt += fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); + detectorValues->sbrQuotaMeanStrongestFilt += fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); + } +} + +/**************************************************************************/ +/*! + \brief Returns the region in which the input value belongs. + + + + \return region. + +*/ +/**************************************************************************/ +static INT +findRegion(FIXP_DBL currVal, /*!< The current value. */ + const FIXP_DBL *borders, /*!< The border of the regions. */ + const INT numBorders /*!< The number of borders. */ + ) +{ + INT i; + + if(currVal < borders[0]){ + return 0; + } + + for(i = 1; i < numBorders; i++){ + if( currVal >= borders[i-1] && currVal < borders[i]){ + return i; + } + } + + if(currVal >= borders[numBorders-1]){ + return numBorders; + } + + return 0; /* We never get here, it's just to avoid compiler warnings.*/ +} + +/**************************************************************************/ +/*! + \brief Makes a clever decision based on the quota vector. + + + \return decision on which invf mode to use + +*/ +/**************************************************************************/ +static INVF_MODE +decisionAlgorithm(const DETECTOR_PARAMETERS *detectorParams, /*!< Struct with the detector parameters. */ + DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ + INT transientFlag, /*!< Flag indicating if there is a transient present.*/ + INT* prevRegionSbr, /*!< The previous region in which the Sbr value was. */ + INT* prevRegionOrig /*!< The previous region in which the Orig value was. */ + ) +{ + INT invFiltLevel, regionSbr, regionOrig, regionNrg; + + /* + Current thresholds. + */ + const FIXP_DBL *quantStepsSbr = detectorParams->quantStepsSbr; + const FIXP_DBL *quantStepsOrig = detectorParams->quantStepsOrig; + const FIXP_DBL *nrgBorders = detectorParams->nrgBorders; + const INT numRegionsSbr = detectorParams->numRegionsSbr; + const INT numRegionsOrig = detectorParams->numRegionsOrig; + const INT numRegionsNrg = detectorParams->numRegionsNrg; + + FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; + FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; + + /* + Current detector values. + */ + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL nrg; + + /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = log(16)/64.0; 0.6875 = 44/64.0 */ + origQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ + sbrQuotaMeanFilt = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt,(FIXP_DBL)1)) + FL2FXCONST_DBL(0.31143075889f)))) << 0; /* scaled by 1/2^9 */ + /* If energy is zero then we will get different results for different word lengths. */ + nrg = (fMultDiv2(FL2FXCONST_DBL(2.f*0.375f), (FIXP_DBL)(CalcLdData(detectorValues->avgNrg+(FIXP_DBL)1) + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ + + FDKmemcpy(quantStepsSbrTmp,quantStepsSbr,numRegionsSbr*sizeof(FIXP_DBL)); + FDKmemcpy(quantStepsOrigTmp,quantStepsOrig,numRegionsOrig*sizeof(FIXP_DBL)); + + if(*prevRegionSbr < numRegionsSbr) + quantStepsSbrTmp[*prevRegionSbr] = quantStepsSbr[*prevRegionSbr] + hysteresis; + if(*prevRegionSbr > 0) + quantStepsSbrTmp[*prevRegionSbr - 1] = quantStepsSbr[*prevRegionSbr - 1] - hysteresis; + + if(*prevRegionOrig < numRegionsOrig) + quantStepsOrigTmp[*prevRegionOrig] = quantStepsOrig[*prevRegionOrig] + hysteresis; + if(*prevRegionOrig > 0) + quantStepsOrigTmp[*prevRegionOrig - 1] = quantStepsOrig[*prevRegionOrig - 1] - hysteresis; + + regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); + regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); + regionNrg = findRegion(nrg,nrgBorders,numRegionsNrg); + + *prevRegionSbr = regionSbr; + *prevRegionOrig = regionOrig; + + /* Use different settings if a transient is present*/ + invFiltLevel = (transientFlag == 1) ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] + : detectorParams->regionSpace[regionSbr][regionOrig]; + + /* Compensate for low energy.*/ + invFiltLevel = max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg],0); + + return (INVF_MODE) (invFiltLevel); +} + +/**************************************************************************/ +/*! + \brief Estiamtion of the inverse filtering level required + in the decoder. + + A second order LPC is calculated for every filterbank channel, using + the covariance method. THe ratio between the energy of the predicted + signal and the energy of the non-predictable signal is calcualted. + + \return none. + +*/ +/**************************************************************************/ +void +FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the original. */ + FIXP_DBL *nrgVector, /*!< The energy vector. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT transientFlag, /*!< Flag indicating if a transient is present or not.*/ + INVF_MODE* infVec /*!< Vector holding the inverse filtering levels. */ + ) +{ + INT band; + + /* + * Do the inverse filtering level estimation. + *****************************************************/ + for(band = 0 ; band < hInvFilt->noDetectorBands; band++){ + INT startChannel = hInvFilt->freqBandTableInvFilt[band]; + INT stopChannel = hInvFilt->freqBandTableInvFilt[band+1]; + + + calculateDetectorValues( quotaMatrix, + indexVector, + nrgVector, + &hInvFilt->detectorValues[band], + startChannel, + stopChannel, + startIndex, + stopIndex, + hInvFilt->numberOfStrongest); + + infVec[band]= decisionAlgorithm( hInvFilt->detectorParams, + &hInvFilt->detectorValues[band], + transientFlag, + &hInvFilt->prevRegionSbr[band], + &hInvFilt->prevRegionOrig[band]); + } + +} + + +/**************************************************************************/ +/*! + \brief Initialize an instance of the inverse filtering level estimator. + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_initInvFiltDetector (HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */ + INT* freqBandTableDetector, /*!< Frequency band table for the inverse filtering. */ + INT numDetectorBands, /*!< Number of inverse filtering bands. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/ + ) +{ + INT i; + + FDKmemclear( hInvFilt,sizeof(SBR_INV_FILT_EST)); + + hInvFilt->detectorParams = (useSpeechConfig) ? &detectorParamsAACSpeech + : &detectorParamsAAC ; + + hInvFilt->noDetectorBandsMax = numDetectorBands; + + /* + Memory initialisation + */ + for(i=0;inoDetectorBandsMax;i++){ + FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES)); + hInvFilt->prevInvfMode[i] = INVF_OFF; + hInvFilt->prevRegionOrig[i] = 0; + hInvFilt->prevRegionSbr[i] = 0; + } + + /* + Reset the inverse fltering detector. + */ + FDKsbrEnc_resetInvFiltDetector(hInvFilt, + freqBandTableDetector, + hInvFilt->noDetectorBandsMax); + + return (0); +} + + +/**************************************************************************/ +/*! + \brief resets sbr inverse filtering structure. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + INT* freqBandTableDetector, /*!< Frequency band table for the inverse filtering. */ + INT numDetectorBands) /*!< Number of inverse filtering bands. */ +{ + + hInvFilt->numberOfStrongest = 1; + FDKmemcpy(hInvFilt->freqBandTableInvFilt,freqBandTableDetector,(numDetectorBands+1)*sizeof(INT)); + hInvFilt->noDetectorBands = numDetectorBands; + + return (0); +} + + diff --git a/libSBRenc/src/invf_est.h b/libSBRenc/src/invf_est.h new file mode 100644 index 00000000..2bd2a783 --- /dev/null +++ b/libSBRenc/src/invf_est.h @@ -0,0 +1,175 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Inverse Filtering detection prototypes +*/ +#ifndef _INV_FILT_DET_H +#define _INV_FILT_DET_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define INVF_SMOOTHING_LENGTH 2 + +typedef struct +{ + const FIXP_DBL *quantStepsSbr; + const FIXP_DBL *quantStepsOrig; + const FIXP_DBL *nrgBorders; + INT numRegionsSbr; + INT numRegionsOrig; + INT numRegionsNrg; + INVF_MODE regionSpace[5][5]; + INVF_MODE regionSpaceTransient[5][5]; + INT EnergyCompFactor[5]; + +}DETECTOR_PARAMETERS; + +typedef struct +{ + FIXP_DBL origQuotaMean[INVF_SMOOTHING_LENGTH+1]; + FIXP_DBL sbrQuotaMean[INVF_SMOOTHING_LENGTH+1]; + FIXP_DBL origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH+1]; + FIXP_DBL sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH+1]; + + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL origQuotaMeanStrongestFilt; + FIXP_DBL sbrQuotaMeanStrongestFilt; + + FIXP_DBL origQuotaMax; + FIXP_DBL sbrQuotaMax; + + FIXP_DBL avgNrg; +}DETECTOR_VALUES; + + + +typedef struct +{ + INT numberOfStrongest; + + INT prevRegionSbr[MAX_NUM_NOISE_VALUES]; + INT prevRegionOrig[MAX_NUM_NOISE_VALUES]; + + INT freqBandTableInvFilt[MAX_NUM_NOISE_VALUES]; + INT noDetectorBands; + INT noDetectorBandsMax; + + const DETECTOR_PARAMETERS *detectorParams; + + INVF_MODE prevInvfMode[MAX_NUM_NOISE_VALUES]; + DETECTOR_VALUES detectorValues[MAX_NUM_NOISE_VALUES]; + + FIXP_DBL nrgAvg; + FIXP_DBL wmQmf[MAX_NUM_NOISE_VALUES]; +} +SBR_INV_FILT_EST; + +typedef SBR_INV_FILT_EST *HANDLE_SBR_INV_FILT_EST; + +void +FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + FIXP_DBL ** quotaMatrix, + FIXP_DBL *nrgVector, + SCHAR *indexVector, + INT startIndex, + INT stopIndex, + INT transientFlag, + INVF_MODE* infVec); + +INT +FDKsbrEnc_initInvFiltDetector (HANDLE_SBR_INV_FILT_EST hInvFilt, + INT* freqBandTableDetector, + INT numDetectorBands, + UINT useSpeechConfig); + +INT +FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + INT* freqBandTableDetector, + INT numDetectorBands); + +#endif /* _QMF_INV_FILT_H */ + diff --git a/libSBRenc/src/mh_det.cpp b/libSBRenc/src/mh_det.cpp new file mode 100644 index 00000000..bc80a15b --- /dev/null +++ b/libSBRenc/src/mh_det.cpp @@ -0,0 +1,1471 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "mh_det.h" + +#include "sbr_ram.h" +#include "sbr_misc.h" + + +#include "genericStds.h" + +#define SFM_SHIFT 2 /* Attention: SFM_SCALE depends on SFM_SHIFT */ +#define SFM_SCALE (MAXVAL_DBL >> SFM_SHIFT) /* 1.0 >> SFM_SHIFT */ + + +/*!< Detector Parameters for AAC core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAac = { +9, /*!< deltaTime */ +{ +FL2FXCONST_DBL(20.0f*RELAXATION_FLOAT), /*!< thresHoldDiff */ +FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldDiffGuide */ +FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT), /*!< thresHoldTone */ +FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */ +FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldToneGuide */ +FL2FXCONST_DBL(0.3f)>>SFM_SHIFT, /*!< sfmThresSbr */ +FL2FXCONST_DBL(0.1f)>>SFM_SHIFT, /*!< sfmThresOrig */ +FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ +FL2FXCONST_DBL(0.5f), /*!< decayGuideDiff */ +FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ +FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ +FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< derivThresAboveLD64 */ +}, +50 /*!< maxComp */ +}; + +/*!< Detector Parameters for AAC LD core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAacLd = { +16, /*!< Delta time. */ +{ +FL2FXCONST_DBL(25.0f*RELAXATION_FLOAT), /*!< thresHoldDiff */ +FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< tresHoldDiffGuide */ +FL2FXCONST_DBL(15.0f*RELAXATION_FLOAT), /*!< thresHoldTone */ +FL2FXCONST_DBL((1.0f/15.0f)*RELAXATION_FLOAT), /*!< invThresHoldTone */ +FL2FXCONST_DBL(1.26f*RELAXATION_FLOAT), /*!< thresHoldToneGuide */ +FL2FXCONST_DBL(0.3f)>>SFM_SHIFT, /*!< sfmThresSbr */ +FL2FXCONST_DBL(0.1f)>>SFM_SHIFT, /*!< sfmThresOrig */ +FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ +FL2FXCONST_DBL(0.2f), /*!< decayGuideDiff */ +FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ +FL2FXCONST_DBL(-0.000112993269), /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ +FL2FXCONST_DBL(-0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< derivThresAboveLD64 */ +}, +50 /*!< maxComp */ +}; + + +/**************************************************************************/ +/*! + \brief Calculates the difference in tonality between original and SBR + for a given time and frequency region. + + The values for pDiffMapped2Scfb are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ +static void diff(FIXP_DBL *RESTRICT pTonalityOrig, + FIXP_DBL *pDiffMapped2Scfb, + const UCHAR *RESTRICT pFreqBandTable, + INT nScfb, + SCHAR *indexVector) +{ + UCHAR i, ll, lu, k; + FIXP_DBL maxValOrig, maxValSbr, tmp; + INT scale; + + for(i=0; i < nScfb; i++){ + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i+1]; + + maxValOrig = FL2FXCONST_DBL(0.0f); + maxValSbr = FL2FXCONST_DBL(0.0f); + + for(k=ll;k= RELAXATION)) { + tmp = fDivNorm(maxValOrig, maxValSbr, &scale); + pDiffMapped2Scfb[i] = scaleValue(fMult(tmp,RELAXATION_FRACT), fixMax(-(DFRACT_BITS-1),(scale-RELAXATION_SHIFT))); + } + else { + pDiffMapped2Scfb[i] = maxValOrig; + } + } +} + + +/**************************************************************************/ +/*! + \brief Calculates a flatness measure of the tonality measures. + + Calculation of the power function and using scalefactor for basis: + Using log2: + z = (2^k * x)^y; + z' = CalcLd(z) = y*CalcLd(x) + y*k; + z = CalcInvLd(z'); + + Using ld64: + z = (2^k * x)^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64 + y*k/64; + z = CalcInvLd64(z'); + + The values pSfmOrigVec and pSfmSbrVec are scaled by the factor 1/4.0 + + \return none. + +*/ +/**************************************************************************/ +static void calculateFlatnessMeasure(FIXP_DBL *pQuotaBuffer, + SCHAR *indexVector, + FIXP_DBL *pSfmOrigVec, + FIXP_DBL *pSfmSbrVec, + const UCHAR *pFreqBandTable, + INT nSfb) +{ + INT i,j; + FIXP_DBL invBands,tmp1,tmp2; + INT shiftFac0,shiftFacSum0; + INT shiftFac1,shiftFacSum1; + FIXP_DBL accu; + + for(i=0;i>2); + pSfmSbrVec[i] = (FIXP_DBL)(MAXVAL_DBL>>2); + + if(lu - ll > 1){ + FIXP_DBL amOrig,amTransp,gmOrig,gmTransp,sfmOrig,sfmTransp; + invBands = GetInvInt(lu-ll); + shiftFacSum0 = 0; + shiftFacSum1 = 0; + amOrig = amTransp = FL2FXCONST_DBL(0.0f); + gmOrig = gmTransp = (FIXP_DBL)MAXVAL_DBL; + + for(j= ll; j FL2FXCONST_DBL(0.0f)) { + + tmp1 = CalcLdData(gmOrig); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum0 << (DFRACT_BITS-1-8); + tmp2 = fMultDiv2(invBands, accu) << (2+1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmOrig = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } + else { + gmOrig = FL2FXCONST_DBL(0.0f); + } + + if (gmTransp > FL2FXCONST_DBL(0.0f)) { + + tmp1 = CalcLdData(gmTransp); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum1 << (DFRACT_BITS-1-8); + tmp2 = fMultDiv2(invBands, accu) << (2+1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmTransp = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } + else { + gmTransp = FL2FXCONST_DBL(0.0f); + } + if ( amOrig != FL2FXCONST_DBL(0.0f) ) + pSfmOrigVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmOrig,amOrig,SFM_SCALE); + + if ( amTransp != FL2FXCONST_DBL(0.0f) ) + pSfmSbrVec[i] = FDKsbrEnc_LSI_divide_scale_fract(gmTransp,amTransp,SFM_SCALE); + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates the input to the missing harmonics detection. + + + \return none. + +*/ +/**************************************************************************/ +static void calculateDetectorInput(FIXP_DBL **RESTRICT pQuotaBuffer, /*!< Pointer to tonality matrix. */ + SCHAR *RESTRICT indexVector, + FIXP_DBL **RESTRICT tonalityDiff, + FIXP_DBL **RESTRICT pSfmOrig, + FIXP_DBL **RESTRICT pSfmSbr, + const UCHAR *freqBandTable, + INT nSfb, + INT noEstPerFrame, + INT move) +{ + INT est; + + /* + New estimate. + */ + for (est=0; est < noEstPerFrame; est++) { + + diff(pQuotaBuffer[est+move], + tonalityDiff[est+move], + freqBandTable, + nSfb, + indexVector); + + calculateFlatnessMeasure(pQuotaBuffer[est+ move], + indexVector, + pSfmOrig[est + move], + pSfmSbr[est + move], + freqBandTable, + nSfb); + } +} + + +/**************************************************************************/ +/*! + \brief Checks that the detection is not due to a LP filter + + This function determines if a newly detected missing harmonics is not + in fact just a low-pass filtere input signal. If so, the detection is + removed. + + \return none. + +*/ +/**************************************************************************/ +static void removeLowPassDetection(UCHAR *RESTRICT pAddHarmSfb, + UCHAR **RESTRICT pDetectionVectors, + INT start, + INT stop, + INT nSfb, + const UCHAR *RESTRICT pFreqBandTable, + FIXP_DBL *RESTRICT pNrgVector, + THRES_HOLDS mhThresh) + +{ + INT i,est; + INT maxDerivPos = pFreqBandTable[nSfb]; + INT numBands = pFreqBandTable[nSfb]; + FIXP_DBL nrgLow,nrgHigh; + FIXP_DBL nrgLD64,nrgLowLD64,nrgHighLD64,nrgDiffLD64; + FIXP_DBL valLD64,maxValLD64,maxValAboveLD64; + INT bLPsignal = 0; + + maxValLD64 = FL2FXCONST_DBL(-1.0f); + for(i = numBands - 1 - 2; i > pFreqBandTable[0];i--){ + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){ + nrgLowLD64 = CalcLdData(nrgLow>>1); + nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1)); + valLD64 = nrgDiffLD64-nrgLowLD64; + if(valLD64 > maxValLD64){ + maxDerivPos = i; + maxValLD64 = valLD64; + } + if(maxValLD64 > mhThresh.derivThresMaxLD64) { + break; + } + } + } + + /* Find the largest "gradient" above. (should be relatively flat, hence we expect a low value + if the signal is LP.*/ + maxValAboveLD64 = FL2FXCONST_DBL(-1.0f); + for(i = numBands - 1 - 2; i > maxDerivPos + 2;i--){ + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if(nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh){ + nrgLowLD64 = CalcLdData(nrgLow>>1); + nrgDiffLD64 = CalcLdData((nrgLow>>1)-(nrgHigh>>1)); + valLD64 = nrgDiffLD64-nrgLowLD64; + if(valLD64 > maxValAboveLD64){ + maxValAboveLD64 = valLD64; + } + } + else { + if(nrgHigh != FL2FXCONST_DBL(0.0f) && nrgHigh > nrgLow){ + nrgHighLD64 = CalcLdData(nrgHigh>>1); + nrgDiffLD64 = CalcLdData((nrgHigh>>1)-(nrgLow>>1)); + valLD64 = nrgDiffLD64-nrgHighLD64; + if(valLD64 > maxValAboveLD64){ + maxValAboveLD64 = valLD64; + } + } + } + } + + if(maxValLD64 > mhThresh.derivThresMaxLD64 && maxValAboveLD64 < mhThresh.derivThresAboveLD64){ + bLPsignal = 1; + + for(i = maxDerivPos - 1; i > maxDerivPos - 5 && i >= 0 ; i--){ + if(pNrgVector[i] != FL2FXCONST_DBL(0.0f) && pNrgVector[i] > pNrgVector[maxDerivPos + 2]){ + nrgDiffLD64 = CalcLdData((pNrgVector[i]>>1)-(pNrgVector[maxDerivPos + 2]>>1)); + nrgLD64 = CalcLdData(pNrgVector[i]>>1); + valLD64 = nrgDiffLD64-nrgLD64; + if(valLD64 < mhThresh.derivThresBelowLD64) { + bLPsignal = 0; + break; + } + } + else{ + bLPsignal = 0; + break; + } + } + } + + if(bLPsignal){ + for(i=0;i= pFreqBandTable[i] && maxDerivPos < pFreqBandTable[i+1]) + break; + } + + if(pAddHarmSfb[i]){ + pAddHarmSfb[i] = 0; + for(est = start; est < stop ; est++){ + pDetectionVectors[est][i] = 0; + } + } + } +} + +/**************************************************************************/ +/*! + \brief Checks if it is allowed to detect a missing tone, that wasn't + detected previously. + + + \return newDetectionAllowed flag. + +*/ +/**************************************************************************/ +static INT isDetectionOfNewToneAllowed(const SBR_FRAME_INFO *pFrameInfo, + INT *pDetectionStartPos, + INT noEstPerFrame, + INT prevTransientFrame, + INT prevTransientPos, + INT prevTransientFlag, + INT transientPosOffset, + INT transientFlag, + INT transientPos, + INT deltaTime, + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector) +{ + INT transientFrame, newDetectionAllowed; + + + /* Determine if this is a frame where a transient starts... + * If the transient flag was set the previous frame but not the + * transient frame flag, the transient frame flag is set in the current frame. + *****************************************************************************/ + transientFrame = 0; + if(transientFlag){ + if(transientPos + transientPosOffset < pFrameInfo->borders[pFrameInfo->nEnvelopes]) + transientFrame = 1; + if(noEstPerFrame > 1){ + if(transientPos + transientPosOffset > h_sbrMissingHarmonicsDetector->timeSlots >> 1){ + *pDetectionStartPos = noEstPerFrame; + } + else{ + *pDetectionStartPos = noEstPerFrame >> 1; + } + + } + else{ + *pDetectionStartPos = noEstPerFrame; + } + } + else{ + if(prevTransientFlag && !prevTransientFrame){ + transientFrame = 1; + *pDetectionStartPos = 0; + } + } + + /* + * Determine if detection of new missing harmonics are allowed. + * If the frame contains a transient it's ok. If the previous + * frame contained a transient it needs to be sufficiently close + * to the start of the current frame. + ****************************************************************/ + newDetectionAllowed = 0; + if(transientFrame){ + newDetectionAllowed = 1; + } + else { + if(prevTransientFrame && + fixp_abs(pFrameInfo->borders[0] - (prevTransientPos + transientPosOffset - + h_sbrMissingHarmonicsDetector->timeSlots)) < deltaTime) + newDetectionAllowed = 1; + *pDetectionStartPos = 0; + } + + h_sbrMissingHarmonicsDetector->previousTransientFlag = transientFlag; + h_sbrMissingHarmonicsDetector->previousTransientFrame = transientFrame; + h_sbrMissingHarmonicsDetector->previousTransientPos = transientPos; + + return (newDetectionAllowed); +} + + +/**************************************************************************/ +/*! + \brief Cleans up the detection after a transient. + + + \return none. + +*/ +/**************************************************************************/ +static void transientCleanUp(FIXP_DBL **quotaBuffer, + INT nSfb, + UCHAR **detectionVectors, + UCHAR *pAddHarmSfb, + UCHAR *pPrevAddHarmSfb, + INT ** signBuffer, + const UCHAR *pFreqBandTable, + INT start, + INT stop, + INT newDetectionAllowed, + FIXP_DBL *pNrgVector, + THRES_HOLDS mhThresh) +{ + INT i,j,li, ui,est; + + for(est=start; est < stop; est++) { + for(i=0; i maxVal1){ + maxVal1 = quotaBuffer[est][j]; + maxPos1 = j; + maxPosTime1 = est; + } + } + } + + li = pFreqBandTable[i+1]; + ui = pFreqBandTable[i+2]; + + /* Find maximum tonality in the the two scf bands.*/ + maxPosTime2 = start; + maxPos2 = li; + maxVal2 = quotaBuffer[start][li]; + for(est = start; est < stop; est++){ + for(j = li; j maxVal2){ + maxVal2 = quotaBuffer[est][j]; + maxPos2 = j; + maxPosTime2 = est; + } + } + } + + /* If the maximum values are in adjacent QMF-channels, we need to remove + the lowest of the two.*/ + if(maxPos2-maxPos1 < 2){ + + if(pPrevAddHarmSfb[i] == 1 && pPrevAddHarmSfb[i+1] == 0){ + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i+1] = 0; + for(est=start; est maxVal2){ + if(signBuffer[maxPosTime1][maxPos2] < 0 && signBuffer[maxPosTime1][maxPos1] > 0){ + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i+1] = 0; + for(est=start; est 0){ + /* Keep the upper, remove the lower.*/ + pAddHarmSfb[i] = 0; + for(est=start; est 0) + pAddHarmSfb[i] = 0; + } + } +} + + +/*****************************************************************************/ +/*! + \brief Detection for one tonality estimate. + + This is the actual missing harmonics detection, using information from the + previous detection. + + If a missing harmonic was detected (in a previous frame) due to too high + tonality differences, but there was not enough tonality difference in the + current frame, the detection algorithm still continues to trace the strongest + tone in the scalefactor band (assuming that this is the tone that is going to + be replaced in the decoder). This is done to avoid abrupt endings of sines + fading out (e.g. in the glockenspiel). + + The function also tries to estimate where one sine is going to be replaced + with multiple sines (due to the patching). This is done by comparing the + tonality flatness measure of the original and the SBR signal. + + The function also tries to estimate (for the scalefactor bands only + containing one qmf subband) when a strong tone in the original will be + replaced by a strong tone in the adjacent QMF subband. + + \return none. + +*/ +/**************************************************************************/ +static void detection(FIXP_DBL *quotaBuffer, + FIXP_DBL *pDiffVecScfb, + INT nSfb, + UCHAR *pHarmVec, + const UCHAR *pFreqBandTable, + FIXP_DBL *sfmOrig, + FIXP_DBL *sfmSbr, + GUIDE_VECTORS guideVectors, + GUIDE_VECTORS newGuideVectors, + THRES_HOLDS mhThresh) +{ + + INT i,j,ll, lu; + FIXP_DBL thresTemp,thresOrig; + + /* + * Do detection on the difference vector, i.e. the difference between + * the original and the transposed. + *********************************************************************/ + for(i=0;i thresTemp){ + pHarmVec[i] = 1; + newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i]; + } + else{ + /* If the guide wasn't zero, but the current level is to low, + start tracking the decay on the tone in the original rather + than the difference.*/ + if(guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)){ + guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide; + } + } + } + + /* + * Trace tones in the original signal that at one point + * have been detected because they will be replaced by + * multiple tones in the sbr signal. + ****************************************************/ + + for(i=0;i thresOrig){ + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } + } + + /* + * Check for multiple sines in the transposed signal, + * where there is only one in the original. + ****************************************************/ + thresOrig = mhThresh.thresHoldTone; + + for(i=0;i 1){ + for(j= ll;j thresOrig && (sfmSbr[i] > mhThresh.sfmThresSbr && sfmOrig[i] < mhThresh.sfmThresOrig)){ + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } + else{ + if(i < nSfb -1){ + ll = pFreqBandTable[i]; + + if(i>0){ + if(quotaBuffer[ll] > mhThresh.thresHoldTone && (pDiffVecScfb[i+1] < mhThresh.invThresHoldTone || pDiffVecScfb[i-1] < mhThresh.invThresHoldTone)){ + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } + else{ + if(quotaBuffer[ll] > mhThresh.thresHoldTone && pDiffVecScfb[i+1] < mhThresh.invThresHoldTone){ + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } + } + } + } + } +} + + +/**************************************************************************/ +/*! + \brief Do detection for every tonality estimate, using forward prediction. + + + \return none. + +*/ +/**************************************************************************/ +static void detectionWithPrediction(FIXP_DBL **quotaBuffer, + FIXP_DBL **pDiffVecScfb, + INT ** signBuffer, + INT nSfb, + const UCHAR* pFreqBandTable, + FIXP_DBL **sfmOrig, + FIXP_DBL **sfmSbr, + UCHAR **detectionVectors, + UCHAR *pPrevAddHarmSfb, + GUIDE_VECTORS *guideVectors, + INT noEstPerFrame, + INT detectionStart, + INT totNoEst, + INT newDetectionAllowed, + INT *pAddHarmFlag, + UCHAR *pAddHarmSfb, + FIXP_DBL *pNrgVector, + const DETECTOR_PARAMETERS_MH *mhParams) +{ + INT est = 0,i; + INT start; + + FDKmemclear(pAddHarmSfb,nSfb*sizeof(UCHAR)); + + if(newDetectionAllowed){ + + /* Since we don't want to use the transient region for detection (since the tonality values + tend to be a bit unreliable for this region) the guide-values are copied to the current + starting point. */ + if(totNoEst > 1){ + start = detectionStart+1; + + if (start != 0) { + FDKmemcpy(guideVectors[start].guideVectorDiff,guideVectors[0].guideVectorDiff,nSfb*sizeof(FIXP_DBL)); + FDKmemcpy(guideVectors[start].guideVectorOrig,guideVectors[0].guideVectorOrig,nSfb*sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[start-1].guideVectorDetected,nSfb*sizeof(UCHAR)); + } + } + else{ + start = 0; + } + } + else{ + start = 0; + } + + + for(est = start; est < totNoEst; est++){ + + /* + * Do detection on the current frame using + * guide-info from the previous. + *******************************************/ + if(est > 0){ + FDKmemcpy(guideVectors[est].guideVectorDetected,detectionVectors[est-1],nSfb*sizeof(UCHAR)); + } + + FDKmemclear(detectionVectors[est], nSfb*sizeof(UCHAR)); + + if(est < totNoEst-1){ + FDKmemclear(guideVectors[est+1].guideVectorDiff,nSfb*sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est+1].guideVectorOrig,nSfb*sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est+1].guideVectorDetected,nSfb*sizeof(UCHAR)); + + detection(quotaBuffer[est], + pDiffVecScfb[est], + nSfb, + detectionVectors[est], + pFreqBandTable, + sfmOrig[est], + sfmSbr[est], + guideVectors[est], + guideVectors[est+1], + mhParams->thresHolds); + } + else{ + FDKmemclear(guideVectors[est].guideVectorDiff,nSfb*sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorOrig,nSfb*sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorDetected,nSfb*sizeof(UCHAR)); + + detection(quotaBuffer[est], + pDiffVecScfb[est], + nSfb, + detectionVectors[est], + pFreqBandTable, + sfmOrig[est], + sfmSbr[est], + guideVectors[est], + guideVectors[est], + mhParams->thresHolds); + } + } + + + /* Clean up the detection.*/ + transientCleanUp(quotaBuffer, + nSfb, + detectionVectors, + pAddHarmSfb, + pPrevAddHarmSfb, + signBuffer, + pFreqBandTable, + start, + totNoEst, + newDetectionAllowed, + pNrgVector, + mhParams->thresHolds); + + + /* Set flag... */ + *pAddHarmFlag = 0; + for(i=0; i maxVal){ + maxVal = pTonalityMatrix[est][l]; + maxPosF = l; + maxPosT = est; + } + } + } + + /* + * If the maximum tonality is at the lower border of the + * scalefactor band, we check the sign of the adjacent channels + * to see if this sine is shared by the lower channel. If so, the + * energy of the single sine will be present in two scalefactor bands + * in the SBR data, which will cause problems in the decoder, when we + * add a sine to just one of the channels. + *********************************************************************/ + if(maxPosF == ll && scfBand){ + if(!pAddHarmSfb[scfBand - 1]) { /* No detection below*/ + if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && pSignMatrix[maxPosT][maxPosF] < 0) { + /* The comp value is calulated as the tonallity value, i.e we want to + reduce the envelope data for this channel with as much as the tonality + that is spread from the channel above. (ld64(RELAXATION) = 0.31143075889) */ + tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + /* limit the comp-value*/ + if (compValue > maxComp) + compValue = maxComp; + + pEnvComp[scfBand-1] = compValue; + } + } + } + + /* + * Same as above, but for the upper end of the scalefactor-band. + ***************************************************************/ + if(maxPosF == lu-1 && scfBand+1 < nSfb){ /* Upper border*/ + if(!pAddHarmSfb[scfBand + 1]) { + if (pSignMatrix[maxPosT][maxPosF] > 0 && pSignMatrix[maxPosT][maxPosF + 1] < 0) { + tmp = fixp_abs((FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT-1)) + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + if (compValue > maxComp) + compValue = maxComp; + + pEnvComp[scfBand+1] = compValue; + } + } + } + } + } + + if(newDetectionAllowed == 0){ + for(scfBand=0;scfBanddetectionVectors; + INT move = h_sbrMHDet->move; + INT noEstPerFrame = h_sbrMHDet->noEstPerFrame; + INT totNoEst = h_sbrMHDet->totNoEst; + INT prevTransientFlag = h_sbrMHDet->previousTransientFlag; + INT prevTransientFrame = h_sbrMHDet->previousTransientFrame; + INT transientPosOffset = h_sbrMHDet->transientPosOffset; + INT prevTransientPos = h_sbrMHDet->previousTransientPos; + GUIDE_VECTORS* guideVectors = h_sbrMHDet->guideVectors; + INT deltaTime = h_sbrMHDet->mhParams->deltaTime; + INT maxComp = h_sbrMHDet->mhParams->maxComp; + + int est; + + /* + Buffer values. + */ + FDK_ASSERT(move<=(MAX_NO_OF_ESTIMATES>>1)); + FDK_ASSERT(noEstPerFrame<=(MAX_NO_OF_ESTIMATES>>1)); + + FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES]; + + for (est=0; est < MAX_NO_OF_ESTIMATES/2; est++) { + sfmSbr[est] = h_sbrMHDet->sfmSbr[est]; + sfmOrig[est] = h_sbrMHDet->sfmOrig[est]; + tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est]; + } + + C_ALLOC_SCRATCH_START(scratch_mem, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS)); + FIXP_DBL *scratch = scratch_mem; + for (; est < MAX_NO_OF_ESTIMATES; est++) { + sfmSbr[est] = scratch; scratch+=MAX_FREQ_COEFFS; + sfmOrig[est] = scratch; scratch+=MAX_FREQ_COEFFS; + tonalityDiff[est] = scratch; scratch+=MAX_FREQ_COEFFS; + } + + + + /* Determine if we're allowed to detect "missing harmonics" that wasn't detected before. + In order to be allowed to do new detection, there must be a transient in the current + frame, or a transient in the previous frame sufficiently close to the current frame. */ + newDetectionAllowed = isDetectionOfNewToneAllowed(pFrameInfo, + &transientDetStart, + noEstPerFrame, + prevTransientFrame, + prevTransientPos, + prevTransientFlag, + transientPosOffset, + transientFlag, + transientPos, + deltaTime, + h_sbrMHDet); + + /* Calulate the variables that will be used subsequently for the actual detection */ + calculateDetectorInput(pQuotaBuffer, + indexVector, + tonalityDiff, + sfmOrig, + sfmSbr, + freqBandTable, + nSfb, + noEstPerFrame, + move); + + /* Do the actual detection using information from previous detections */ + detectionWithPrediction(pQuotaBuffer, + tonalityDiff, + pSignBuffer, + nSfb, + freqBandTable, + sfmOrig, + sfmSbr, + detectionVectors, + h_sbrMHDet->guideScfb, + guideVectors, + noEstPerFrame, + transientDetStart, + totNoEst, + newDetectionAllowed, + pAddHarmonicsFlag, + pAddHarmonicsScaleFactorBands, + pNrgVector, + h_sbrMHDet->mhParams); + + /* Calculate the comp vector, so that the energy can be + compensated for a sine between two QMF-bands. */ + calculateCompVector(pAddHarmonicsScaleFactorBands, + pQuotaBuffer, + pSignBuffer, + envelopeCompensation, + nSfb, + freqBandTable, + totNoEst, + maxComp, + h_sbrMHDet->prevEnvelopeCompensation, + newDetectionAllowed); + + for (est=0; est < move; est++) { + FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + } + C_ALLOC_SCRATCH_END(scratch, FIXP_DBL, (3*MAX_NO_OF_ESTIMATES/2*MAX_FREQ_COEFFS)); + + +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_CreateSbrMissingHarmonicsDetector ( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, + INT chan) +{ + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + INT i; + + UCHAR* detectionVectors = GetRam_Sbr_detectionVectors(chan); + UCHAR* guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan); + FIXP_DBL* guideVectorDiff = GetRam_Sbr_guideVectorDiff(chan); + FIXP_DBL* guideVectorOrig = GetRam_Sbr_guideVectorOrig(chan); + + FDKmemclear (hs,sizeof(SBR_MISSING_HARMONICS_DETECTOR)); + + hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan); + hs->guideScfb = GetRam_Sbr_guideScfb(chan); + + for(i=0; iguideVectors[i].guideVectorDiff = guideVectorDiff + (i*MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorOrig = guideVectorOrig + (i*MAX_FREQ_COEFFS); + hs->detectionVectors[i] = detectionVectors + (i*MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorDetected = guideVectorDetected + (i*MAX_FREQ_COEFFS); + } + + return 0; +} + + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_InitSbrMissingHarmonicsDetector ( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, + INT sampleFreq, + INT frameSize, + INT nSfb, + INT qmfNoChannels, + INT totNoEst, + INT move, + INT noEstPerFrame, + UINT sbrSyntaxFlags + ) +{ + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + int i; + + FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES); + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + switch(frameSize){ + case 1024: + case 512: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 16; + break; + case 960: + case 480: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 15; + break; + default: + return -1; + } + } else + { + switch(frameSize){ + case 2048: + case 1024: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + hs->timeSlots = NUMBER_TIME_SLOTS_2048; + break; + case 1920: + case 960: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + hs->timeSlots = NUMBER_TIME_SLOTS_1920; + break; + default: + return -1; + } + } + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + hs->mhParams = ¶msAacLd; + } else + hs->mhParams = ¶msAac; + + hs->qmfNoChannels = qmfNoChannels; + hs->sampleFreq = sampleFreq; + hs->nSfb = nSfb; + + hs->totNoEst = totNoEst; + hs->move = move; + hs->noEstPerFrame = noEstPerFrame; + + for(i=0; iguideVectors[i].guideVectorDiff,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemclear (hs->guideVectors[i].guideVectorOrig,sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemclear (hs->detectionVectors[i],sizeof(UCHAR)*MAX_FREQ_COEFFS); + FDKmemclear (hs->guideVectors[i].guideVectorDetected,sizeof(UCHAR)*MAX_FREQ_COEFFS); + } + + //for(i=0; itonalityDiff[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemclear (hs->sfmOrig[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + FDKmemclear (hs->sfmSbr[i],sizeof(FIXP_DBL)*MAX_FREQ_COEFFS); + } + + FDKmemclear ( hs->prevEnvelopeCompensation, sizeof(UCHAR)*MAX_FREQ_COEFFS); + FDKmemclear ( hs->guideScfb, sizeof(UCHAR)*MAX_FREQ_COEFFS); + + hs->previousTransientFlag = 0; + hs->previousTransientFrame = 0; + hs->previousTransientPos = 0; + + return (0); +} + +/**************************************************************************/ +/*! + \brief Deletes an instance of the missing harmonics detector. + + + \return none. + +*/ +/**************************************************************************/ +void +FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet) +{ + if (hSbrMHDet) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + + FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]); + FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected); + FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff); + FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig); + FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation); + FreeRam_Sbr_guideScfb(&hs->guideScfb); + + } +} + +/**************************************************************************/ +/*! + \brief Resets an instance of the missing harmonics detector. + + + \return error code, noError if OK. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_ResetSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb) +{ + int i; + FIXP_DBL tempGuide[MAX_FREQ_COEFFS]; + UCHAR tempGuideInt[MAX_FREQ_COEFFS]; + INT nSfbPrev; + + nSfbPrev = hSbrMissingHarmonicsDetector->nSfb; + hSbrMissingHarmonicsDetector->nSfb = nSfb; + + FDKmemcpy( tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, nSfbPrev * sizeof(UCHAR) ); + + if ( nSfb > nSfbPrev ) { + for ( i = 0; i < (nSfb - nSfbPrev); i++ ) { + hSbrMissingHarmonicsDetector->guideScfb[i] = 0; + } + + for ( i = 0; i < nSfbPrev; i++ ) { + hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } + else { + for ( i = 0; i < nSfb; i++ ) { + hSbrMissingHarmonicsDetector->guideScfb[i] = tempGuideInt[i + (nSfbPrev-nSfb)]; + } + } + + FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, nSfbPrev * sizeof(FIXP_DBL) ); + + if (nSfb > nSfbPrev ) { + for ( i = 0; i < (nSfb - nSfbPrev); i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f); + } + + for ( i = 0; i < nSfbPrev; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } + else { + for ( i = 0; i < nSfb; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = tempGuide[i + (nSfbPrev-nSfb)]; + } + } + + FDKmemcpy ( tempGuide, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, nSfbPrev * sizeof(FIXP_DBL) ); + + if ( nSfb > nSfbPrev ) { + for ( i = 0; i< (nSfb - nSfbPrev); i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f); + } + + for ( i = 0; i < nSfbPrev; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } + else { + for ( i = 0; i < nSfb; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = tempGuide[i + (nSfbPrev-nSfb)]; + } + } + + FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, nSfbPrev * sizeof(UCHAR) ); + + if ( nSfb > nSfbPrev ) { + for ( i = 0; i < (nSfb - nSfbPrev); i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0; + } + + for ( i = 0; i < nSfbPrev; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } + else { + for ( i = 0; i < nSfb; i++ ) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = tempGuideInt[i + (nSfbPrev-nSfb)]; + } + } + + FDKmemcpy ( tempGuideInt, hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, nSfbPrev * sizeof(UCHAR) ); + + if ( nSfb > nSfbPrev ) { + for ( i = 0; i < (nSfb - nSfbPrev); i++ ) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0; + } + + for ( i = 0; i < nSfbPrev; i++ ) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } + else { + for ( i = 0; i < nSfb; i++ ) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = tempGuideInt[i + (nSfbPrev-nSfb)]; + } + } + + return 0; +} + diff --git a/libSBRenc/src/mh_det.h b/libSBRenc/src/mh_det.h new file mode 100644 index 00000000..74c2a991 --- /dev/null +++ b/libSBRenc/src/mh_det.h @@ -0,0 +1,196 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief missing harmonics detection header file +*/ + +#ifndef __MH_DETECT_H +#define __MH_DETECT_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +typedef struct +{ + FIXP_DBL thresHoldDiff; /*!< threshold for tonality difference */ + FIXP_DBL thresHoldDiffGuide; /*!< threshold for tonality difference for the guide */ + FIXP_DBL thresHoldTone; /*!< threshold for tonality for a sine */ + FIXP_DBL invThresHoldTone; + FIXP_DBL thresHoldToneGuide; /*!< threshold for tonality for a sine for the guide */ + FIXP_DBL sfmThresSbr; /*!< tonality flatness measure threshold for the SBR signal.*/ + FIXP_DBL sfmThresOrig; /*!< tonality flatness measure threshold for the original signal.*/ + FIXP_DBL decayGuideOrig; /*!< decay value of the tonality value of the guide for the tone. */ + FIXP_DBL decayGuideDiff; /*!< decay value of the tonality value of the guide for the tonality difference. */ + FIXP_DBL derivThresMaxLD64; /*!< threshold for detecting LP character in a signal. */ + FIXP_DBL derivThresBelowLD64; /*!< threshold for detecting LP character in a signal. */ + FIXP_DBL derivThresAboveLD64; /*!< threshold for detecting LP character in a signal. */ +}THRES_HOLDS; + +typedef struct +{ + INT deltaTime; /*!< maximum allowed transient distance (from frame border in number of qmf subband sample) + for a frame to be considered a transient frame.*/ + THRES_HOLDS thresHolds; /*!< the thresholds used for detection. */ + INT maxComp; /*!< maximum alllowed compensation factor for the envelope data. */ +}DETECTOR_PARAMETERS_MH; + +typedef struct +{ + FIXP_DBL *guideVectorDiff; + FIXP_DBL *guideVectorOrig; + UCHAR* guideVectorDetected; +}GUIDE_VECTORS; + + +typedef struct +{ + INT qmfNoChannels; + INT nSfb; + INT sampleFreq; + INT previousTransientFlag; + INT previousTransientFrame; + INT previousTransientPos; + + INT noVecPerFrame; + INT transientPosOffset; + + INT move; + INT totNoEst; + INT noEstPerFrame; + INT timeSlots; + + UCHAR *guideScfb; + UCHAR *prevEnvelopeCompensation; + UCHAR *detectionVectors[MAX_NO_OF_ESTIMATES]; + FIXP_DBL tonalityDiff[MAX_NO_OF_ESTIMATES/2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmOrig[MAX_NO_OF_ESTIMATES/2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmSbr[MAX_NO_OF_ESTIMATES/2][MAX_FREQ_COEFFS]; + const DETECTOR_PARAMETERS_MH *mhParams; + GUIDE_VECTORS guideVectors[MAX_NO_OF_ESTIMATES]; +} +SBR_MISSING_HARMONICS_DETECTOR; + +typedef SBR_MISSING_HARMONICS_DETECTOR *HANDLE_SBR_MISSING_HARMONICS_DETECTOR; + +void +FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + FIXP_DBL ** pQuotaBuffer, + INT ** pSignBuffer, + SCHAR *indexVector, + const SBR_FRAME_INFO *pFrameInfo, + const UCHAR* pTranInfo, + INT* pAddHarmonicsFlag, + UCHAR* pAddHarmonicsScaleFactorBands, + const UCHAR* freqBandTable, + INT nSfb, + UCHAR * envelopeCompensation, + FIXP_DBL *pNrgVector); + +INT +FDKsbrEnc_CreateSbrMissingHarmonicsDetector ( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, + INT chan); + +INT +FDKsbrEnc_InitSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + INT sampleFreq, + INT frameSize, + INT nSfb, + INT qmfNoChannels, + INT totNoEst, + INT move, + INT noEstPerFrame, + UINT sbrSyntaxFlags); + +void +FDKsbrEnc_DeleteSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector); + + +INT +FDKsbrEnc_ResetSbrMissingHarmonicsDetector (HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb); + +#endif diff --git a/libSBRenc/src/nf_est.cpp b/libSBRenc/src/nf_est.cpp new file mode 100644 index 00000000..a4c55741 --- /dev/null +++ b/libSBRenc/src/nf_est.cpp @@ -0,0 +1,584 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "nf_est.h" + +#include "sbr_misc.h" + +#include "genericStds.h" + +/* smoothFilter[4] = {0.05857864376269f, 0.2f, 0.34142135623731f, 0.4f}; */ +static const FIXP_DBL smoothFilter[4] = { 0x077f813d, 0x19999995, 0x2bb3b1f5, 0x33333335 }; + +/* static const INT smoothFilterLength = 4; */ + +static const FIXP_DBL QuantOffset = (INT)0xfc000000; /* ld64(0.25) */ + +#ifndef min +#define min(a,b) ( a < b ? a:b) +#endif + +#ifndef max +#define max(a,b) ( a > b ? a:b) +#endif + +#define NOISE_FLOOR_OFFSET_SCALING (4) + + + +/**************************************************************************/ +/*! + \brief The function applies smoothing to the noise levels. + + + + \return none + +*/ +/**************************************************************************/ +static void +smoothingOfNoiseLevels(FIXP_DBL *NoiseLevels, /*!< pointer to noise-floor levels.*/ + INT nEnvelopes, /*!< Number of noise floor envelopes.*/ + INT noNoiseBands, /*!< Number of noise bands for every noise floor envelope. */ + FIXP_DBL prevNoiseLevels[NF_SMOOTHING_LENGTH][MAX_NUM_NOISE_VALUES],/*!< Previous noise floor envelopes. */ + const FIXP_DBL *smoothFilter, /*!< filter used for smoothing the noise floor levels. */ + INT transientFlag) /*!< flag indicating if a transient is present*/ + +{ + INT i,band,env; + FIXP_DBL accu; + + for(env = 0; env < nEnvelopes; env++){ + if(transientFlag){ + for (i = 0; i < NF_SMOOTHING_LENGTH; i++){ + FDKmemcpy(prevNoiseLevels[i],NoiseLevels+env*noNoiseBands,noNoiseBands*sizeof(FIXP_DBL)); + } + } + else { + for (i = 1; i < NF_SMOOTHING_LENGTH; i++){ + FDKmemcpy(prevNoiseLevels[i - 1],prevNoiseLevels[i],noNoiseBands*sizeof(FIXP_DBL)); + } + FDKmemcpy(prevNoiseLevels[NF_SMOOTHING_LENGTH - 1],NoiseLevels+env*noNoiseBands,noNoiseBands*sizeof(FIXP_DBL)); + } + + for (band = 0; band < noNoiseBands; band++){ + accu = FL2FXCONST_DBL(0.0f); + for (i = 0; i < NF_SMOOTHING_LENGTH; i++){ + accu += fMultDiv2(smoothFilter[i], prevNoiseLevels[i][band]); + } + FDK_ASSERT( (band + env*noNoiseBands) < MAX_NUM_NOISE_VALUES); + NoiseLevels[band+ env*noNoiseBands] = accu<<1; + } + } +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + + The noiseLevel samples are scaled by the factor 0.25 + + \return none + +*/ +/**************************************************************************/ +static void +qmfBasedNoiseFloorDetection(FIXP_DBL *noiseLevel, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL ** quotaMatrixOrig, /*!< Matrix holding the quota values of the original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT startChannel, /*!< Start channel of the current noise floor band.*/ + INT stopChannel, /*!< Stop channel of the current noise floor band. */ + FIXP_DBL ana_max_level, /*!< Maximum level of the adaptive noise.*/ + FIXP_DBL noiseFloorOffset, /*!< Noise floor offset. */ + INT missingHarmonicFlag, /*!< Flag indicating if a strong tonal component is missing.*/ + FIXP_DBL weightFac, /*!< Weightening factor for the difference between orig and sbr. */ + INVF_MODE diffThres, /*!< Threshold value to control the inverse filtering decision.*/ + INVF_MODE inverseFilteringLevel) /*!< Inverse filtering level of the current band.*/ +{ + INT scale, l, k; + FIXP_DBL meanOrig=FL2FXCONST_DBL(0.0f), meanSbr=FL2FXCONST_DBL(0.0f), diff; + FIXP_DBL invIndex = GetInvInt(stopIndex-startIndex); + FIXP_DBL invChannel = GetInvInt(stopChannel-startChannel); + FIXP_DBL accu; + + /* + Calculate the mean value, over the current time segment, for the original, the HFR + and the difference, over all channels in the current frequency range. + */ + + if(missingHarmonicFlag == 1){ + for(l = startChannel; l < stopChannel;l++){ + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for(k = startIndex ; k < stopIndex; k++){ + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig = fixMax(meanOrig,(accu<<1)); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for(k = startIndex ; k < stopIndex; k++){ + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr = fixMax(meanSbr,(accu<<1)); + + } + } + else{ + for(l = startChannel; l < stopChannel;l++){ + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for(k = startIndex ; k < stopIndex; k++){ + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig += fMult((accu<<1), invChannel); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for(k = startIndex ; k < stopIndex; k++){ + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr += fMult((accu<<1), invChannel); + } + } + + /* Small fix to avoid noise during silent passages.*/ + if( meanOrig <= FL2FXCONST_DBL(0.000976562f*RELAXATION_FLOAT) && + meanSbr <= FL2FXCONST_DBL(0.000976562f*RELAXATION_FLOAT) ) + { + meanOrig = FL2FXCONST_DBL(101.5936673f*RELAXATION_FLOAT); + meanSbr = FL2FXCONST_DBL(101.5936673f*RELAXATION_FLOAT); + } + + meanOrig = fixMax(meanOrig,RELAXATION); + meanSbr = fixMax(meanSbr,RELAXATION); + + if (missingHarmonicFlag == 1 || + inverseFilteringLevel == INVF_MID_LEVEL || + inverseFilteringLevel == INVF_LOW_LEVEL || + inverseFilteringLevel == INVF_OFF || + inverseFilteringLevel <= diffThres) + { + diff = RELAXATION; + } + else { + accu = fDivNorm(meanSbr, meanOrig, &scale); + + diff = fixMax( RELAXATION, + fMult(RELAXATION_FRACT,fMult(weightFac,accu)) >>( RELAXATION_SHIFT-scale ) ) ; + } + + /* + * noise Level is now a positive value, i.e. + * the more harmonic the signal is the higher noise level, + * this makes no sense so we change the sign. + *********************************************************/ + accu = fDivNorm(diff, meanOrig, &scale); + scale -= 2; + + if ( (scale>0) && (accu > ((FIXP_DBL)MAXVAL_DBL)>>scale) ) { + *noiseLevel = (FIXP_DBL)MAXVAL_DBL; + } + else { + *noiseLevel = scaleValue(accu, scale); + } + + /* + * Add a noise floor offset to compensate for bias in the detector + *****************************************************************/ + if(!missingHarmonicFlag) { + *noiseLevel = fixMin(fMult(*noiseLevel, noiseFloorOffset), (FIXP_DBL)MAXVAL_DBL>>NOISE_FLOOR_OFFSET_SCALING) << NOISE_FLOOR_OFFSET_SCALING; + } + + /* + * check to see that we don't exceed the maximum allowed level + **************************************************************/ + *noiseLevel = fixMin(*noiseLevel, ana_max_level); /* ana_max_level is scaled with factor 0.25 */ +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + The function calls the Noisefloor estimation function + for the time segments decided based upon the transient + information. The block is always divided into one or two segments. + + + \return none + +*/ +/**************************************************************************/ +void +FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + const SBR_FRAME_INFO *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ + int transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ + UINT sbrSyntaxFlags + ) + +{ + + INT nNoiseEnvelopes, startPos[2], stopPos[2], env, band; + + INT noNoiseBands = h_sbrNoiseFloorEstimate->noNoiseBands; + INT *freqBandTable = h_sbrNoiseFloorEstimate->freqBandTableQmf; + + nNoiseEnvelopes = frame_info->nNoiseEnvelopes; + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + nNoiseEnvelopes = 1; + startPos[0] = startIndex; + stopPos[0] = startIndex + min(numberOfEstimatesPerFrame,2); + } else + if(nNoiseEnvelopes == 1){ + startPos[0] = startIndex; + stopPos[0] = startIndex + 2; + } + else{ + startPos[0] = startIndex; + stopPos[0] = startIndex + 1; + startPos[1] = startIndex + 1; + stopPos[1] = startIndex + 2; + } + + /* + * Estimate the noise floor. + **************************************/ + for(env = 0; env < nNoiseEnvelopes; env++){ + for(band = 0; band < noNoiseBands; band++){ + FDK_ASSERT( (band + env*noNoiseBands) < MAX_NUM_NOISE_VALUES); + qmfBasedNoiseFloorDetection(&noiseLevels[band + env*noNoiseBands], + quotaMatrixOrig, + indexVector, + startPos[env], + stopPos[env], + freqBandTable[band], + freqBandTable[band+1], + h_sbrNoiseFloorEstimate->ana_max_level, + h_sbrNoiseFloorEstimate->noiseFloorOffset[band], + missingHarmonicsFlag, + h_sbrNoiseFloorEstimate->weightFac, + h_sbrNoiseFloorEstimate->diffThres, + pInvFiltLevels[band]); + } + } + + + /* + * Smoothing of the values. + **************************/ + smoothingOfNoiseLevels(noiseLevels, + nNoiseEnvelopes, + h_sbrNoiseFloorEstimate->noNoiseBands, + h_sbrNoiseFloorEstimate->prevNoiseLevels, + h_sbrNoiseFloorEstimate->smoothFilter, + transientFrame); + + + /* quantisation*/ + for(env = 0; env < nNoiseEnvelopes; env++){ + for(band = 0; band < noNoiseBands; band++){ + FDK_ASSERT( (band + env*noNoiseBands) < MAX_NUM_NOISE_VALUES); + noiseLevels[band + env*noNoiseBands] = + (FIXP_DBL)NOISE_FLOOR_OFFSET_64 - (FIXP_DBL)CalcLdData(noiseLevels[band + env*noNoiseBands]+(FIXP_DBL)1) + QuantOffset; + } + } +} + +/**************************************************************************/ +/*! + \brief + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +static INT +downSampleLoRes(INT *v_result, /*!< */ + INT num_result, /*!< */ + const UCHAR *freqBandTableRef,/*!< */ + INT num_Ref) /*!< */ +{ + INT step; + INT i,j; + INT org_length,result_length; + INT v_index[MAX_FREQ_COEFFS/2]; + + /* init */ + org_length=num_Ref; + result_length=num_result; + + v_index[0]=0; /* Always use left border */ + i=0; + while(org_length > 0) /* Create downsample vector */ + { + i++; + step=org_length/result_length; /* floor; */ + org_length=org_length - step; + result_length--; + v_index[i]=v_index[i-1]+step; + } + + if(i != num_result ) /* Should never happen */ + return (1);/* error downsampling */ + + for(j=0;j<=i;j++) /* Use downsample vector to index LoResolution vector. */ + { + v_result[j]=freqBandTableRef[v_index[j]]; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the noise floor level estimation module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_InitSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech */ + ) +{ + INT i, qexp, qtmp; + FIXP_DBL tmp, exp; + + FDKmemclear(h_sbrNoiseFloorEstimate,sizeof(SBR_NOISE_FLOOR_ESTIMATE)); + + h_sbrNoiseFloorEstimate->smoothFilter = smoothFilter; + if (useSpeechConfig) { + h_sbrNoiseFloorEstimate->weightFac = (FIXP_DBL)MAXVAL_DBL; + h_sbrNoiseFloorEstimate->diffThres = INVF_LOW_LEVEL; + } + else { + h_sbrNoiseFloorEstimate->weightFac = FL2FXCONST_DBL(0.25f); + h_sbrNoiseFloorEstimate->diffThres = INVF_MID_LEVEL; + } + + h_sbrNoiseFloorEstimate->timeSlots = timeSlots; + h_sbrNoiseFloorEstimate->noiseBands = noiseBands; + + /* h_sbrNoiseFloorEstimate->ana_max_level is scaled by 0.25 */ + switch(ana_max_level) + { + case 6: + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + case 3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.5); + break; + case -3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.125); + break; + default: + /* Should not enter here */ + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + } + + /* + calculate number of noise bands and allocate + */ + if(FDKsbrEnc_resetSbrNoiseFloorEstimate(h_sbrNoiseFloorEstimate,freqBandTable,nSfb)) + return(1); + + if(noiseFloorOffset == 0) { + tmp = ((FIXP_DBL)MAXVAL_DBL)>>NOISE_FLOOR_OFFSET_SCALING; + } + else { + /* noiseFloorOffset has to be smaller than 12, because + the result of the calculation below must be smaller than 1: + (2^(noiseFloorOffset/3))*2^4<1 */ + FDK_ASSERT(noiseFloorOffset<12); + + /* Assumes the noise floor offset in tuning table are in q31 */ + /* Change the qformat here when non-zero values would be filled */ + exp = fDivNorm((FIXP_DBL)noiseFloorOffset, 3, &qexp); + tmp = fPow(2, DFRACT_BITS-1, exp, qexp, &qtmp); + tmp = scaleValue(tmp, qtmp-NOISE_FLOOR_OFFSET_SCALING); + } + + for(i=0;inoNoiseBands;i++) { + h_sbrNoiseFloorEstimate->noiseFloorOffset[i] = tmp; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Resets the current instance of the noise floor estiamtion + module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_resetSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb) /*!< Number of bands in the frequency band table. */ +{ + INT k2,kx; + + /* + * Calculate number of noise bands + ***********************************/ + k2=freqBandTable[nSfb]; + kx=freqBandTable[0]; + if(h_sbrNoiseFloorEstimate->noiseBands == 0){ + h_sbrNoiseFloorEstimate->noNoiseBands = 1; + } + else{ + /* + * Calculate number of noise bands 1,2 or 3 bands/octave + ********************************************************/ + FIXP_DBL tmp, ratio, lg2; + INT ratio_e, qlg2, nNoiseBands; + + ratio = fDivNorm(k2, kx, &ratio_e); + lg2 = fLog2(ratio, ratio_e, &qlg2); + tmp = fMult((FIXP_DBL)(h_sbrNoiseFloorEstimate->noiseBands<<24), lg2); + tmp = scaleValue(tmp, qlg2-23); + + nNoiseBands = (INT)((tmp + (FIXP_DBL)1) >> 1); + + + if (nNoiseBands > MAX_NUM_NOISE_COEFFS ) { + nNoiseBands = MAX_NUM_NOISE_COEFFS; + } + + if( nNoiseBands == 0 ) { + nNoiseBands = 1; + } + + h_sbrNoiseFloorEstimate->noNoiseBands = nNoiseBands; + + } + + + return(downSampleLoRes(h_sbrNoiseFloorEstimate->freqBandTableQmf, + h_sbrNoiseFloorEstimate->noNoiseBands, + freqBandTable,nSfb)); +} + +/**************************************************************************/ +/*! + \brief Deletes the current instancce of the noise floor level + estimation module. + + + \return none + +*/ +/**************************************************************************/ +void +FDKsbrEnc_deleteSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate) /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ +{ + + if (h_sbrNoiseFloorEstimate) { + /* + nothing to do + */ + } +} diff --git a/libSBRenc/src/nf_est.h b/libSBRenc/src/nf_est.h new file mode 100644 index 00000000..f26f74ff --- /dev/null +++ b/libSBRenc/src/nf_est.h @@ -0,0 +1,147 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Noise floor estimation structs and prototypes +*/ + +#ifndef __NF_EST_H +#define __NF_EST_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +#define NF_SMOOTHING_LENGTH 4 /*!< Smoothing length of the noise floors. */ + +typedef struct +{ + FIXP_DBL prevNoiseLevels[NF_SMOOTHING_LENGTH][MAX_NUM_NOISE_VALUES]; /*!< The previous noise levels. */ + FIXP_DBL noiseFloorOffset[MAX_NUM_NOISE_VALUES]; /*!< Noise floor offset, scaled with NOISE_FLOOR_OFFSET_SCALING */ + const FIXP_DBL *smoothFilter; /*!< Smoothing filter to use. */ + FIXP_DBL ana_max_level; /*!< Max level allowed. */ + FIXP_DBL weightFac; /*!< Weightening factor for the difference between orig and sbr. */ + INT freqBandTableQmf[MAX_NUM_NOISE_VALUES + 1]; /*!< Frequncy band table for the noise floor bands.*/ + INT noNoiseBands; /*!< Number of noisebands. */ + INT noiseBands; /*!< NoiseBands switch 4 bit.*/ + INT timeSlots; /*!< Number of timeslots in a frame. */ + INVF_MODE diffThres; /*!< Threshold value to control the inverse filtering decision */ +} +SBR_NOISE_FLOOR_ESTIMATE; + +typedef SBR_NOISE_FLOOR_ESTIMATE *HANDLE_SBR_NOISE_FLOOR_ESTIMATE; + +void +FDKsbrEnc_sbrNoiseFloorEstimateQmf(HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + const SBR_FRAME_INFO *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the original. */ + SCHAR* indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per frame. */ + INT transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE* pInvFiltLevels, /*!< Pointer to the vector holding the inverse filtering levels. */ + UINT sbrSyntaxFlags + ); + +INT +FDKsbrEnc_InitSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech */ + ); + +INT +FDKsbrEnc_resetSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb); /*!< Number of bands in the frequency band table. */ + +void +FDKsbrEnc_deleteSbrNoiseFloorEstimate (HANDLE_SBR_NOISE_FLOOR_ESTIMATE h_sbrNoiseFloorEstimate); /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct */ + +#endif diff --git a/libSBRenc/src/ps_bitenc.cpp b/libSBRenc/src/ps_bitenc.cpp new file mode 100644 index 00000000..420ea150 --- /dev/null +++ b/libSBRenc/src/ps_bitenc.cpp @@ -0,0 +1,698 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial author: N. Rettelbach + contents/description: Parametric Stereo bitstream encoder + +******************************************************************************/ + +#include "ps_main.h" + + +#include "ps_const.h" +#include "ps_bitenc.h" + +static +inline UCHAR FDKsbrEnc_WriteBits_ps(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) +{ + /* hBitStream == NULL happens here intentionally */ + if(hBitStream!=NULL){ + FDKwriteBits(hBitStream, value, numberOfBits); + } + return numberOfBits; +} + +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 +#define EXTENSION_ID_PS_CODING 2 +#define PS_EXT_ID_V0 0 + +static const INT iidDeltaCoarse_Offset = 14; +static const INT iidDeltaCoarse_MaxVal = 28; +static const INT iidDeltaFine_Offset = 30; +static const INT iidDeltaFine_MaxVal = 60; + +/* PS Stereo Huffmantable: iidDeltaFreqCoarse */ +static const UINT iidDeltaFreqCoarse_Length[] = +{ + 17, 17, 17, 17, 16, 15, 13, 10, 9, 7, + 6, 5, 4, 3, 1, 3, 4, 5, 6, 6, + 8, 11, 13, 14, 14, 15, 17, 18, 18 +}; +static const UINT iidDeltaFreqCoarse_Code[] = +{ + 0x0001fffb, 0x0001fffc, 0x0001fffd, 0x0001fffa, 0x0000fffc, 0x00007ffc, 0x00001ffd, 0x000003fe, 0x000001fe, 0x0000007e, + 0x0000003c, 0x0000001d, 0x0000000d, 0x00000005, 0000000000, 0x00000004, 0x0000000c, 0x0000001c, 0x0000003d, 0x0000003e, + 0x000000fe, 0x000007fe, 0x00001ffc, 0x00003ffc, 0x00003ffd, 0x00007ffd, 0x0001fffe, 0x0003fffe, 0x0003ffff +}; + +/* PS Stereo Huffmantable: iidDeltaFreqFine */ +static const UINT iidDeltaFreqFine_Length[] = +{ + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, + 18, 17, 17, 16, 16, 15, 14, 14, 13, 12, + 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, + 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 11, 12, 13, 14, 14, 15, 16, 16, 17, 17, + 18, 17, 18, 18, 18, 18, 18, 18, 18, 18, + 18 +}; +static const UINT iidDeltaFreqFine_Code[] = +{ + 0x0001feb4, 0x0001feb5, 0x0001fd76, 0x0001fd77, 0x0001fd74, 0x0001fd75, 0x0001fe8a, 0x0001fe8b, 0x0001fe88, 0x0000fe80, + 0x0001feb6, 0x0000fe82, 0x0000feb8, 0x00007f42, 0x00007fae, 0x00003faf, 0x00001fd1, 0x00001fe9, 0x00000fe9, 0x000007ea, + 0x000007fb, 0x000003fb, 0x000001fb, 0x000001ff, 0x0000007c, 0x0000003c, 0x0000001c, 0x0000000c, 0000000000, 0x00000001, + 0x00000001, 0x00000002, 0x00000001, 0x0000000d, 0x0000001d, 0x0000003d, 0x0000007d, 0x000000fc, 0x000001fc, 0x000003fc, + 0x000003f4, 0x000007eb, 0x00000fea, 0x00001fea, 0x00001fd6, 0x00003fd0, 0x00007faf, 0x00007f43, 0x0000feb9, 0x0000fe83, + 0x0001feb7, 0x0000fe81, 0x0001fe89, 0x0001fe8e, 0x0001fe8f, 0x0001fe8c, 0x0001fe8d, 0x0001feb2, 0x0001feb3, 0x0001feb0, + 0x0001feb1 +}; + +/* PS Stereo Huffmantable: iidDeltaTimeCoarse */ +static const UINT iidDeltaTimeCoarse_Length[] = +{ + 19, 19, 19, 20, 20, 20, 17, 15, 12, 10, + 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, + 13, 14, 17, 19, 20, 20, 20, 20, 20 +}; +static const UINT iidDeltaTimeCoarse_Code[] = +{ + 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, 0x000ffffa, 0x0001fffd, 0x00007ffe, 0x00000ffe, 0x000003fe, + 0x000000fe, 0x0000003e, 0x0000000e, 0x00000002, 0000000000, 0x00000006, 0x0000001e, 0x0000007e, 0x000001fe, 0x000007fe, + 0x00001ffe, 0x00003ffe, 0x0001fffc, 0x0007fff8, 0x000ffffb, 0x000ffffc, 0x000ffffd, 0x000ffffe, 0x000fffff +}; + +/* PS Stereo Huffmantable: iidDeltaTimeFine */ +static const UINT iidDeltaTimeFine_Length[] = +{ + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, + 15, 15, 15, 15, 15, 14, 14, 13, 13, 13, + 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, + 1, 2, 5, 6, 7, 8, 9, 10, 11, 11, + 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16 +}; +static const UINT iidDeltaTimeFine_Code[] = +{ + 0x00004ed4, 0x00004ed5, 0x00004ece, 0x00004ecf, 0x00004ecc, 0x00004ed6, 0x00004ed8, 0x00004f46, 0x00004f60, 0x00002718, + 0x00002719, 0x00002764, 0x00002765, 0x0000276d, 0x000027b1, 0x000013b7, 0x000013d6, 0x000009c7, 0x000009e9, 0x000009ed, + 0x000004ee, 0x000004f7, 0x00000278, 0x00000139, 0x0000009a, 0x0000009f, 0x00000020, 0x00000011, 0x0000000a, 0x00000003, + 0x00000001, 0000000000, 0x0000000b, 0x00000012, 0x00000021, 0x0000004c, 0x0000009b, 0x0000013a, 0x00000279, 0x00000270, + 0x000004ef, 0x000004e2, 0x000009ea, 0x000009d8, 0x000013d7, 0x000013d0, 0x000027b2, 0x000027a2, 0x0000271a, 0x0000271b, + 0x00004f66, 0x00004f67, 0x00004f61, 0x00004f47, 0x00004ed9, 0x00004ed7, 0x00004ecd, 0x00004ed2, 0x00004ed3, 0x00004ed0, + 0x00004ed1 +}; + +static const INT iccDelta_Offset = 7; +static const INT iccDelta_MaxVal = 14; +/* PS Stereo Huffmantable: iccDeltaFreq */ +static const UINT iccDeltaFreq_Length[] = +{ + 14, 14, 12, 10, 7, 5, 3, 1, 2, 4, + 6, 8, 9, 11, 13 +}; +static const UINT iccDeltaFreq_Code[] = +{ + 0x00003fff, 0x00003ffe, 0x00000ffe, 0x000003fe, 0x0000007e, 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000001fe, 0x000007fe, 0x00001ffe +}; + +/* PS Stereo Huffmantable: iccDeltaTime */ +static const UINT iccDeltaTime_Length[] = +{ + 14, 13, 11, 9, 7, 5, 3, 1, 2, 4, + 6, 8, 10, 12, 14 +}; +static const UINT iccDeltaTime_Code[] = +{ + 0x00003ffe, 0x00001ffe, 0x000007fe, 0x000001fe, 0x0000007e, 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000003fe, 0x00000ffe, 0x00003fff +}; + + + +static const INT ipdDelta_Offset = 0; +static const INT ipdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: ipdDeltaFreq */ +static const UINT ipdDeltaFreq_Length[] = +{ + 1, 3, 4, 4, 4, 4, 4, 4 +}; +static const UINT ipdDeltaFreq_Code[] = +{ + 0x00000001, 0000000000, 0x00000006, 0x00000004, 0x00000002, 0x00000003, 0x00000005, 0x00000007 +}; + +/* PS Stereo Huffmantable: ipdDeltaTime */ +static const UINT ipdDeltaTime_Length[] = +{ + 1, 3, 4, 5, 5, 4, 4, 3 +}; +static const UINT ipdDeltaTime_Code[] = +{ + 0x00000001, 0x00000002, 0x00000002, 0x00000003, 0x00000002, 0000000000, 0x00000003, 0x00000003 +}; + + +static const INT opdDelta_Offset = 0; +static const INT opdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: opdDeltaFreq */ +static const UINT opdDeltaFreq_Length[] = +{ + 1, 3, 4, 4, 5, 5, 4, 3 +}; +static const UINT opdDeltaFreq_Code[] = +{ + 0x00000001, 0x00000001, 0x00000006, 0x00000004, 0x0000000f, 0x0000000e, 0x00000005, 0000000000, +}; + +/* PS Stereo Huffmantable: opdDeltaTime */ +static const UINT opdDeltaTime_Length[] = +{ + 1, 3, 4, 5, 5, 4, 4, 3 +}; +static const UINT opdDeltaTime_Code[] = +{ + 0x00000001, 0x00000002, 0x00000001, 0x00000007, 0x00000006, 0000000000, 0x00000002, 0x00000003 +}; + +static INT getNoBands(const INT mode) +{ + INT noBands = 0; + + switch (mode) { + case 0: case 3: /* coarse */ + noBands = PS_BANDS_COARSE; + break; + case 1: case 4: /* mid */ + noBands = PS_BANDS_MID; + break; + case 2: case 5: /* fine not supported */ + default: /* coarse as default */ + noBands = PS_BANDS_COARSE; + } + + return noBands; +} + +static INT getIIDRes(INT iidMode) +{ + if(iidMode<3) + return PS_IID_RES_COARSE; + else + return PS_IID_RES_FINE; +} + +static INT +encodeDeltaFreq(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *val, + const INT nBands, + const UINT *codeTable, + const UINT *lengthTable, + const INT tableOffset, + const INT maxVal, + INT *error) +{ + INT bitCnt = 0; + INT lastVal = 0; + INT band; + + for(band=0;bandmaxVal) || (delta<0) ) { + *error = 1; + delta = delta>0?maxVal:0; + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +static INT +encodeDeltaTime(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *val, + const INT *valLast, + const INT nBands, + const UINT *codeTable, + const UINT *lengthTable, + const INT tableOffset, + const INT maxVal, + INT *error) +{ + INT bitCnt = 0; + INT band; + + for(band=0;bandmaxVal) || (delta<0) ) { + *error = 1; + delta = delta>0?maxVal:0; + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *iidVal, + const INT *iidValLast, + const INT nBands, + const PS_IID_RESOLUTION res, + const PS_DELTA mode, + INT *error) +{ + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + bitCnt = 0; + + switch(mode) { + case PS_DELTA_FREQ: + switch(res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaFreqCoarse_Code; + lengthTable = iidDeltaFreqCoarse_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, + lengthTable, iidDeltaCoarse_Offset, + iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaFreqFine_Code; + lengthTable = iidDeltaFreqFine_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, + lengthTable, iidDeltaFine_Offset, + iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + case PS_DELTA_TIME: + switch(res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaTimeCoarse_Code; + lengthTable = iidDeltaTimeCoarse_Length; + bitCnt += encodeDeltaTime(hBitBuf, iidVal, iidValLast, nBands, codeTable, + lengthTable, iidDeltaCoarse_Offset, + iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaTimeFine_Code; + lengthTable = iidDeltaTimeFine_Length; + bitCnt += encodeDeltaTime(hBitBuf, iidVal, iidValLast, nBands, codeTable, + lengthTable, iidDeltaFine_Offset, + iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + default: + *error = 1; + } + + return bitCnt; +} + + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *iccVal, + const INT *iccValLast, + const INT nBands, + const PS_DELTA mode, + INT *error) +{ + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch(mode) { + case PS_DELTA_FREQ: + codeTable = iccDeltaFreq_Code; + lengthTable = iccDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iccVal, nBands, codeTable, + lengthTable, iccDelta_Offset, iccDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = iccDeltaTime_Code; + lengthTable = iccDeltaTime_Length; + + bitCnt += encodeDeltaTime(hBitBuf, iccVal, iccValLast, nBands, codeTable, + lengthTable, iccDelta_Offset, iccDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *ipdVal, + const INT *ipdValLast, + const INT nBands, + const PS_DELTA mode, + INT *error) +{ + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch(mode) { + case PS_DELTA_FREQ: + codeTable = ipdDeltaFreq_Code; + lengthTable = ipdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, ipdVal, nBands, codeTable, + lengthTable, ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = ipdDeltaTime_Code; + lengthTable = ipdDeltaTime_Length; + + bitCnt += encodeDeltaTime(hBitBuf, ipdVal, ipdValLast, nBands, codeTable, + lengthTable, ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *opdVal, + const INT *opdValLast, + const INT nBands, + const PS_DELTA mode, + INT *error) +{ + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch(mode) { + case PS_DELTA_FREQ: + codeTable = opdDeltaFreq_Code; + lengthTable = opdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, opdVal, nBands, codeTable, + lengthTable, opdDelta_Offset, opdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = opdDeltaTime_Code; + lengthTable = opdDeltaTime_Length; + + bitCnt += encodeDeltaTime(hBitBuf, opdVal, opdValLast, nBands, codeTable, + lengthTable, opdDelta_Offset, opdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +static INT encodeIpdOpd(HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf ) +{ + INT bitCnt = 0; + INT error = 0; + INT env; + + FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIpdOpd, 1); + + if(psOut->enableIpdOpd==1) { + INT *ipdLast = psOut->ipdLast; + INT *opdLast = psOut->opdLast; + + for(env=0; envnEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->deltaIPD[env], 1); + bitCnt += FDKsbrEnc_EncodeIpd( hBitBuf, + psOut->ipd[env], + ipdLast, + getNoBands(psOut->iidMode), + psOut->deltaIPD[env], + &error); + + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->deltaOPD[env], 1); + bitCnt += FDKsbrEnc_EncodeOpd( hBitBuf, + psOut->opd[env], + opdLast, + getNoBands(psOut->iidMode), + psOut->deltaOPD[env], + &error ); + } + /* reserved bit */ + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, 0, 1); + } + + + return bitCnt; +} + +static INT getEnvIdx(const INT nEnvelopes, const INT frameClass) +{ + INT envIdx = 0; + + switch(nEnvelopes) { + case 0: + envIdx = 0; + break; + + case 1: + if (frameClass==0) + envIdx = 1; + else + envIdx = 0; + break; + + case 2: + if (frameClass==0) + envIdx = 2; + else + envIdx = 1; + break; + + case 3: + envIdx = 2; + break; + + case 4: + envIdx = 3; + break; + + default: + /* unsupported number of envelopes */ + envIdx = 0; + } + + return envIdx; +} + + +static INT encodePSExtension(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf ) +{ + INT bitCnt = 0; + + if(psOut->enableIpdOpd==1) { + INT ipdOpdBits = 0; + INT extSize = (2 + encodeIpdOpd(psOut,NULL)+7)>>3; + + if(extSize<15) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, extSize, 4); + } + else { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 15 , 4); + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, (extSize-15), 8); + } + + /* write ipd opd data */ + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, PS_EXT_ID_V0, 2); + ipdOpdBits += encodeIpdOpd(psOut, hBitBuf ); + + /* byte align the ipd opd data */ + if(ipdOpdBits%8) + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, (8-(ipdOpdBits%8)) ); + + bitCnt += ipdOpdBits; + } + + return (bitCnt); +} + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf ) +{ + INT psExtEnable = 0; + INT bitCnt = 0; + INT error = 0; + INT env; + + if(psOut != NULL){ + + /* PS HEADER */ + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->enablePSHeader, 1); + + if(psOut->enablePSHeader) { + + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->enableIID, 1); + if(psOut->enableIID) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->iidMode, 3); + } + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->enableICC, 1); + if(psOut->enableICC) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->iccMode, 3); + } + if(psOut->enableIpdOpd) { + psExtEnable = 1; + } + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psExtEnable, 1); + } + + /* Frame class, number of envelopes */ + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->frameClass, 1); + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, getEnvIdx(psOut->nEnvelopes, psOut->frameClass), 2); + + if(psOut->frameClass==1) { + for(env=0; envnEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->frameBorder[env], 5); + } + } + + if(psOut->enableIID==1) { + INT *iidLast = psOut->iidLast; + for(env=0; envnEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->deltaIID[env], 1); + bitCnt += FDKsbrEnc_EncodeIid( hBitBuf, + psOut->iid[env], + iidLast, + getNoBands(psOut->iidMode), + (PS_IID_RESOLUTION)getIIDRes(psOut->iidMode), + psOut->deltaIID[env], + &error ); + + iidLast = psOut->iid[env]; + } + } + + if(psOut->enableICC==1) { + INT *iccLast = psOut->iccLast; + for(env=0; envnEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps( hBitBuf, psOut->deltaICC[env], 1); + bitCnt += FDKsbrEnc_EncodeIcc( hBitBuf, + psOut->icc[env], + iccLast, + getNoBands(psOut->iccMode), + psOut->deltaICC[env], + &error); + + iccLast = psOut->icc[env]; + } + } + + if(psExtEnable!=0) { + bitCnt += encodePSExtension(psOut, hBitBuf); + } + + } /* if(psOut != NULL) */ + + return bitCnt; +} + diff --git a/libSBRenc/src/ps_bitenc.h b/libSBRenc/src/ps_bitenc.h new file mode 100644 index 00000000..e98fe589 --- /dev/null +++ b/libSBRenc/src/ps_bitenc.h @@ -0,0 +1,177 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial author: N. Rettelbach + contents/description: Parametric Stereo bitstream encoder + +******************************************************************************/ + +#include "ps_main.h" +#include "ps_const.h" +#include "FDK_bitstream.h" + +#ifndef PS_BITENC_H +#define PS_BITENC_H + +typedef struct T_PS_OUT { + + INT enablePSHeader; + INT enableIID; + INT iidMode; + INT enableICC; + INT iccMode; + INT enableIpdOpd; + + INT frameClass; + INT nEnvelopes; + /* ENV data */ + INT frameBorder[PS_MAX_ENVELOPES]; + + /* iid data */ + PS_DELTA deltaIID[PS_MAX_ENVELOPES]; + INT iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidLast[PS_MAX_BANDS]; + + /* icc data */ + PS_DELTA deltaICC[PS_MAX_ENVELOPES]; + INT icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccLast[PS_MAX_BANDS]; + + /* ipd data */ + PS_DELTA deltaIPD[PS_MAX_ENVELOPES]; + INT ipd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT ipdLast[PS_MAX_BANDS]; + + /* opd data */ + PS_DELTA deltaOPD[PS_MAX_ENVELOPES]; + INT opd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT opdLast[PS_MAX_BANDS]; + +} PS_OUT, *HANDLE_PS_OUT; + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *iidVal, + const INT *iidValLast, + const INT nBands, + const PS_IID_RESOLUTION res, + const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *iccVal, + const INT *iccValLast, + const INT nBands, + const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *ipdVal, + const INT *ipdValLast, + const INT nBands, + const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, + const INT *opdVal, + const INT *opdValLast, + const INT nBands, + const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* #ifndef PS_BITENC_H */ diff --git a/libSBRenc/src/ps_const.h b/libSBRenc/src/ps_const.h new file mode 100644 index 00000000..633d210a --- /dev/null +++ b/libSBRenc/src/ps_const.h @@ -0,0 +1,148 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial author: N. Rettelbach + contents/description: Parametric Stereo constants + +******************************************************************************/ + +#ifndef PS_CONST_H +#define PS_CONST_H + +#define MAX_PS_CHANNELS ( 2 ) +#define HYBRID_MAX_QMF_BANDS ( 3 ) +#define HYBRID_FILTER_LENGTH ( 13 ) +#define HYBRID_FILTER_DELAY ( (HYBRID_FILTER_LENGTH-1)/2 ) + +#define HYBRID_FRAMESIZE ( QMF_MAX_TIME_SLOTS ) +#define HYBRID_READ_OFFSET ( 10 ) + +#define MAX_HYBRID_BANDS ( (QMF_CHANNELS-HYBRID_MAX_QMF_BANDS+10) ) + + +typedef enum { + PS_RES_COARSE = 0, + PS_RES_MID = 1, + PS_RES_FINE = 2 +} PS_RESOLUTION; + +typedef enum { + PS_BANDS_COARSE = 10, + PS_BANDS_MID = 20, + PS_MAX_BANDS = PS_BANDS_MID +} PS_BANDS; + +typedef enum { + PS_IID_RES_COARSE=0, + PS_IID_RES_FINE +} PS_IID_RESOLUTION; + +typedef enum { + PS_ICC_ROT_A=0, + PS_ICC_ROT_B +} PS_ICC_ROTATION_MODE; + +typedef enum { + PS_DELTA_FREQ, + PS_DELTA_TIME +} PS_DELTA; + + +typedef enum { + PS_MAX_ENVELOPES = 4 + +} PS_CONSTS; + +typedef enum { + PSENC_OK = 0x0000, /*!< No error happened. All fine. */ + PSENC_INVALID_HANDLE = 0x0020, /*!< Handle passed to function call was invalid. */ + PSENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + PSENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + PSENC_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an unexpected error. */ + +} FDK_PSENC_ERROR; + + +#endif diff --git a/libSBRenc/src/ps_encode.cpp b/libSBRenc/src/ps_encode.cpp new file mode 100644 index 00000000..fec39e89 --- /dev/null +++ b/libSBRenc/src/ps_encode.cpp @@ -0,0 +1,1054 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial Authors: M. Neuendorf, N. Rettelbach, M. Multrus + Contents/Description: PS parameter extraction, encoding + +******************************************************************************/ +/*! + \file + \brief PS parameter extraction, encoding functions +*/ + +#include "ps_main.h" + + +#include "sbr_ram.h" +#include "ps_encode.h" + +#include "qmf.h" + +#include "ps_const.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, FIXP_DBL *Z, INT n) +{ + for (INT i=0; i>1) + (Y[i]>>1); +} + +#define LOG10_2_10 3.01029995664f /* 10.0f*log10(2.f) */ + +static const INT iidGroupBordersLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES + 1] = +{ + 0, 1, 2, 3, 4, 5, /* 6 subqmf subbands - 0th qmf subband */ + 6, 7, /* 2 subqmf subbands - 1st qmf subband */ + 8, 9, /* 2 subqmf subbands - 2nd qmf subband */ + 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71 +}; + +static const UCHAR iidGroupWidthLdLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = +{ + 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 5 +}; + + +static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = +{ + 1, 0, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ + 4, 5, /* 2 subqmf subbands - 1st qmf subband */ + 6, 7, /* 2 subqmf subbands - 2nd qmf subband */ + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 +}; + + +typedef enum { + MAX_TIME_DIFF_FRAMES = 20, + MAX_PS_NOHEADER_CNT = 10, + MAX_NOENV_CNT = 10, + DO_NOT_USE_THIS_MODE = 0x7FFFFF +} __PS_CONSTANTS; + + + +static const FIXP_DBL iidQuant_fx[15] = { + (FIXP_DBL)0xce000000, (FIXP_DBL)0xdc000000, (FIXP_DBL)0xe4000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf2000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, + (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, (FIXP_DBL)0x0e000000, (FIXP_DBL)0x14000000, (FIXP_DBL)0x1c000000, (FIXP_DBL)0x24000000, (FIXP_DBL)0x32000000 +}; + +static const FIXP_DBL iidQuantFine_fx[31] = { + (FIXP_DBL)0x9c000001, (FIXP_DBL)0xa6000001, (FIXP_DBL)0xb0000001, (FIXP_DBL)0xba000001, (FIXP_DBL)0xc4000000, (FIXP_DBL)0xce000000, (FIXP_DBL)0xd4000000, (FIXP_DBL)0xda000000, + (FIXP_DBL)0xe0000000, (FIXP_DBL)0xe6000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf0000000, (FIXP_DBL)0xf4000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, + (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x10000000, (FIXP_DBL)0x14000000, (FIXP_DBL)0x1a000000, (FIXP_DBL)0x20000000, (FIXP_DBL)0x26000000, + (FIXP_DBL)0x2c000000, (FIXP_DBL)0x32000000, (FIXP_DBL)0x3c000000, (FIXP_DBL)0x45ffffff, (FIXP_DBL)0x4fffffff, (FIXP_DBL)0x59ffffff, (FIXP_DBL)0x63ffffff +}; + + + +static const FIXP_DBL iccQuant[8] = { + (FIXP_DBL)0x7fffffff, (FIXP_DBL)0x77ef9d7f, (FIXP_DBL)0x6babc97f, (FIXP_DBL)0x4ceaf27f, (FIXP_DBL)0x2f0ed3c0, (FIXP_DBL)0x00000000, (FIXP_DBL)0xb49ba601, (FIXP_DBL)0x80000000 +}; + +static FDK_PSENC_ERROR InitPSData( + HANDLE_PS_DATA hPsData + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if(hPsData == NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + int i, env; + FDKmemclear(hPsData,sizeof(PS_DATA)); + + for (i=0; iiidIdxLast[i] = 0; + hPsData->iccIdxLast[i] = 0; + } + + hPsData->iidEnable = hPsData->iidEnableLast = 0; + hPsData->iccEnable = hPsData->iccEnableLast = 0; + hPsData->iidQuantMode = hPsData->iidQuantModeLast = PS_IID_RES_COARSE; + hPsData->iccQuantMode = hPsData->iccQuantModeLast = PS_ICC_ROT_A; + + for(env=0; enviccDiffMode[env] = PS_DELTA_FREQ; + hPsData->iccDiffMode[env] = PS_DELTA_FREQ; + + for (i=0; iiidIdx[env][i] = 0; + hPsData->iccIdx[env][i] = 0; + } + } + + hPsData->nEnvelopesLast = 0; + + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + return error; +} + +static FIXP_DBL quantizeCoef( const FIXP_DBL *RESTRICT input, + const INT nBands, + const FIXP_DBL *RESTRICT quantTable, + const INT idxOffset, + const INT nQuantSteps, + INT *RESTRICT quantOut) +{ + INT idx, band; + FIXP_DBL quantErr = FL2FXCONST_DBL(0.f); + + for (band=0; band>1)-(quantTable[idx+1]>>1)) > + fixp_abs((input[band]>>1)-(quantTable[idx]>>1)) ) + { + break; + } + } + quantErr += (fixp_abs(input[band]-quantTable[idx])>>PS_QUANT_SCALE); /* don't scale before subtraction; diff smaller (64-25)/64 */ + quantOut[band] = idx - idxOffset; + } + + return quantErr; +} + +static INT getICCMode(const INT nBands, + const INT rotType) +{ + INT mode = 0; + + switch(nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + } + if(rotType==PS_ICC_ROT_B){ + mode += 3; + } + + return mode; +} + + +static INT getIIDMode(const INT nBands, + const INT iidRes) +{ + INT mode = 0; + + switch(nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + break; + } + + if(iidRes == PS_IID_RES_FINE){ + mode += 3; + } + + return mode; +} + + +static INT envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT psBands, + INT nEnvelopes) +{ + #define THRESH_SCALE 7 + + INT reducible = 1; /* true */ + INT e = 0, b = 0; + FIXP_DBL dIid = FL2FXCONST_DBL(0.f); + FIXP_DBL dIcc = FL2FXCONST_DBL(0.f); + + FIXP_DBL iidErrThreshold, iccErrThreshold; + FIXP_DBL iidMeanError, iccMeanError; + + /* square values to prevent sqrt, + multiply bands to prevent division; bands shifted DFRACT_BITS instead (DFRACT_BITS-1) because fMultDiv2 used*/ + iidErrThreshold = fMultDiv2 ( FL2FXCONST_DBL(6.5f*6.5f/(IID_SCALE_FT*IID_SCALE_FT)), (FIXP_DBL)(psBands<<((DFRACT_BITS)-THRESH_SCALE)) ); + iccErrThreshold = fMultDiv2 ( FL2FXCONST_DBL(0.75f*0.75f), (FIXP_DBL)(psBands<<((DFRACT_BITS)-THRESH_SCALE)) ); + + if (nEnvelopes <= 1) { + reducible = 0; + } else { + + /* mean error criterion */ + for (e=0; (e < nEnvelopes/2) && (reducible!=0 ) ; e++) { + iidMeanError = iccMeanError = FL2FXCONST_DBL(0.f); + for(b=0; b>1) - (iid[2*e+1][b]>>1); /* scale 1 bit; squared -> 2 bit */ + dIcc = (icc[2*e][b]>>1) - (icc[2*e+1][b]>>1); + iidMeanError += fPow2Div2(dIid)>>(5-1); /* + (bands=20) scale = 5 */ + iccMeanError += fPow2Div2(dIcc)>>(5-1); + } /* --> scaling = 7 bit = THRESH_SCALE !! */ + + /* instead sqrt values are squared! + instead of division, multiply threshold with psBands + scaling necessary!! */ + + /* quit as soon as threshold is reached */ + if ( (iidMeanError > (iidErrThreshold)) || + (iccMeanError > (iccErrThreshold)) ) { + reducible = 0; + } + } + } /* nEnvelopes != 1 */ + + return reducible; +} + + +static void processIidData(PS_DATA *psData, + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + const INT psBands, + const INT nEnvelopes, + const FIXP_DBL quantErrorThreshold) +{ + INT iidIdxFine [PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxCoarse[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + + FIXP_DBL errIID = FL2FXCONST_DBL(0.f); + FIXP_DBL errIIDFine = FL2FXCONST_DBL(0.f); + INT bitsIidFreq = 0; + INT bitsIidTime = 0; + INT bitsFineTot = 0; + INT bitsCoarseTot = 0; + INT error = 0; + INT env, band; + INT diffMode[PS_MAX_ENVELOPES], diffModeFine[PS_MAX_ENVELOPES]; + INT loudnDiff = 0; + INT iidTransmit = 0; + + bitsIidFreq = bitsIidTime = 0; + + /* Quantize IID coefficients */ + for(env=0;enviidEnable = 0; + for(env=0;env fMultI(FL2FXCONST_DBL(0.7f),iidTransmit)){ /* 0.7f empiric value */ + psData->iidEnable = 1; + } + + /* if iid not active -> RESET data */ + if(psData->iidEnable==0) { + psData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + for(env=0;enviidDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iidIdx[env], sizeof(INT)*psBands); + } + return; + } + + /* count COARSE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], NULL, psBands, PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); + + if( (psData->iidTimeCnt>=MAX_TIME_DIFF_FRAMES) || (psData->iidQuantModeLast==PS_IID_RES_FINE) ) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } + else { + bitsIidTime = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], psData->iidIdxLast, psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if(bitsIidTime>bitsIidFreq) { + diffMode[0] = PS_DELTA_FREQ; + bitsCoarseTot = bitsIidFreq; + } + else { + diffMode[0] = PS_DELTA_TIME; + bitsCoarseTot = bitsIidTime; + } + + /* count COARSE quantization bits for following envelopes*/ + for(env=1;envbitsIidFreq) { + diffMode[env] = PS_DELTA_FREQ; + bitsCoarseTot += bitsIidFreq; + } + else { + diffMode[env] = PS_DELTA_TIME; + bitsCoarseTot += bitsIidTime; + } + } + + + /* count FINE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], NULL, psBands, PS_IID_RES_FINE, PS_DELTA_FREQ, &error); + + if( (psData->iidTimeCnt>=MAX_TIME_DIFF_FRAMES) || (psData->iidQuantModeLast==PS_IID_RES_COARSE) ) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } + else { + bitsIidTime = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], psData->iidIdxLast, psBands, PS_IID_RES_FINE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if(bitsIidTime>bitsIidFreq) { + diffModeFine[0] = PS_DELTA_FREQ; + bitsFineTot = bitsIidFreq; + } + else { + diffModeFine[0] = PS_DELTA_TIME; + bitsFineTot = bitsIidTime; + } + + /* count FINE quantization bits for following envelopes*/ + for(env=1;envbitsIidFreq) { + diffModeFine[env] = PS_DELTA_FREQ; + bitsFineTot += bitsIidFreq; + } + else { + diffModeFine[env] = PS_DELTA_TIME; + bitsFineTot += bitsIidTime; + } + } + + if(bitsFineTot == bitsCoarseTot){ + /* if same number of bits is needed, use the quantization with lower error */ + if(errIIDFine < errIID){ + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } else { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } else { + /* const FIXP_DBL minThreshold = FL2FXCONST_DBL(0.2f/(IID_SCALE_FT*PS_QUANT_SCALE_FT)*(psBands*nEnvelopes)); */ + const FIXP_DBL minThreshold = (FIXP_DBL)((LONG)0x00019999 * (psBands*nEnvelopes)); + + /* decision RES_FINE vs RES_COARSE */ + /* test if errIIDFine*quantErrorThreshold < errIID */ + /* shiftVal 2 comes from scaling of quantErrorThreshold */ + if(fixMax(((errIIDFine>>1)+(minThreshold>>1))>>1, fMult(quantErrorThreshold,errIIDFine)) < (errIID>>2) ) { + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } + else if(fixMax(((errIID>>1)+(minThreshold>>1))>>1, fMult(quantErrorThreshold,errIID)) < (errIIDFine>>2) ) { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } + + /* decision RES_FINE vs RES_COARSE */ + if(bitsFineTotiidQuantMode = PS_IID_RES_FINE; + for(env=0;enviidDiffMode[env] = diffModeFine[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxFine[env], psBands*sizeof(INT)); + } + } + else { + psData->iidQuantMode = PS_IID_RES_COARSE; + for(env=0;enviidDiffMode[env] = diffMode[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxCoarse[env], psBands*sizeof(INT)); + } + } + + /* Count DELTA_TIME encoding streaks */ + for(env=0;enviidDiffMode[env]==PS_DELTA_TIME) + psData->iidTimeCnt++; + else + psData->iidTimeCnt=0; + } +} + + +static INT similarIid(PS_DATA *psData, + const INT psBands, + const INT nEnvelopes) +{ + const INT diffThr = (psData->iidQuantMode == PS_IID_RES_COARSE) ? 2 : 3; + const INT sumDiffThr = diffThr * psBands/4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes==1)) { + similar = 1; + for (env=0; enviidIdx[env][b] - psData->iidIdxLast[b]); + sumDiff += diff; + if ( (diff > diffThr) /* more than x quantization steps in any band */ + || (sumDiff > sumDiffThr) ) { /* more than x quantisations steps overall difference */ + similar = 0; + } + b++; + } while ((b0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + + +static INT similarIcc(PS_DATA *psData, + const INT psBands, + const INT nEnvelopes) +{ + const INT diffThr = 2; + const INT sumDiffThr = diffThr * psBands/4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes==1)) { + similar = 1; + for (env=0; enviccIdx[env][b] - psData->iccIdxLast[b]); + sumDiff += diff; + if ( (diff > diffThr) /* more than x quantisation step in any band */ + || (sumDiff > sumDiffThr) ) { /* more than x quantisations steps overall difference */ + similar = 0; + } + b++; + } while ((b0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + +static void processIccData(PS_DATA *psData, + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], /* const input values: unable to declare as const, since it does not poINT to const memory */ + const INT psBands, + const INT nEnvelopes) +{ + FIXP_DBL errICC = FL2FXCONST_DBL(0.f); + INT env, band; + INT bitsIccFreq, bitsIccTime; + INT error = 0; + INT inCoherence=0, iccTransmit=0; + INT *iccIdxLast; + + iccIdxLast = psData->iccIdxLast; + + /* Quantize ICC coefficients */ + for(env=0;enviccIdx[env]); + } + + /* Check if ICC coefficients should be used */ + psData->iccEnable = 0; + for(env=0;enviccIdx[env][band]; + iccTransmit ++; + } + } + if(inCoherence > fMultI(FL2FXCONST_DBL(0.5f),iccTransmit)){ /* 0.5f empiric value */ + psData->iccEnable = 1; + } + + if(psData->iccEnable==0) { + psData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + for(env=0;enviccDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iccIdx[env], sizeof(INT)*psBands); + } + return; + } + + for(env=0;enviccIdx[env], NULL, psBands, PS_DELTA_FREQ, &error); + + if(psData->iccTimeCnticcIdx[env], iccIdxLast, psBands, PS_DELTA_TIME, &error); + } + else { + bitsIccTime = DO_NOT_USE_THIS_MODE; + } + + if(bitsIccFreq>bitsIccTime) { + psData->iccDiffMode[env] = PS_DELTA_TIME; + psData->iccTimeCnt++; + } + else { + psData->iccDiffMode[env] = PS_DELTA_FREQ; + psData->iccTimeCnt=0; + } + iccIdxLast = psData->iccIdx[env]; + } +} + +static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, + INT psBands) +{ + INT i=0; + INT env=0; + for(env=0; env>(LD_DATA_SHIFT+1)) ); + IID = fixMax( IID, (FIXP_DBL)(MINVAL_DBL>>(LD_DATA_SHIFT+1)) ); + iid[env][i] = IID << (LD_DATA_SHIFT+1); + } + } +} + +static void calculateICC(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, + INT psBands) +{ + INT i = 0; + INT env = 0; + INT border = psBands; + + switch (psBands) { + case PS_BANDS_COARSE: + border = 5; + break; + case PS_BANDS_MID: + border = 11; + break; + default: + break; + } + + for(env=0; env>1) + (ldPwrR[env][i]>>1) + (FIXP_DBL)1) ); + INT scale, invScale = CountLeadingBits(invNrg); + + scale = (DFRACT_BITS-1) - invScale; + ICC = fMult(pwrCr[env][i], invNrg<>1)>>1) - (FIXP_DBL)((sc1-1)<<(DFRACT_BITS-1-LD_DATA_SHIFT)) ); + + FIXP_DBL invNrg = CalcInvLdData ( -((ldPwrL[env][i]>>1) + (ldPwrR[env][i]>>1) + (FIXP_DBL)1) ); + sc1 = CountLeadingBits(invNrg); + invNrg <<= sc1; + + sc2 = CountLeadingBits(ICC); + ICC = fMult(ICC<>= -sc1; + } + else { + if (ICC >= ((FIXP_DBL)MAXVAL_DBL>>sc1) ) + ICC = (FIXP_DBL)MAXVAL_DBL; + else + ICC <<= sc1; + } + + icc[env][i] = ICC; + } + } +} + +void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode) +{ + INT group, bin; + INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + FDKmemclear(hPsEncode->psBandNrgScale, PS_MAX_BANDS*sizeof(SCHAR)); + + for (group=0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin = bin>>1; + } + + hPsEncode->psBandNrgScale[bin] = (hPsEncode->psBandNrgScale[bin]==0) + ? (hPsEncode->iidGroupWidthLd[group] + 5) + : (fixMax(hPsEncode->iidGroupWidthLd[group],hPsEncode->psBandNrgScale[bin]) + 1) ; + + } +} + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode( + HANDLE_PS_ENCODE *phPsEncode + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (phPsEncode==NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + HANDLE_PS_ENCODE hPsEncode = NULL; + if (NULL==(hPsEncode = GetRam_PsEncode())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hPsEncode,sizeof(PS_ENCODE)); + *phPsEncode = hPsEncode; /* return allocated handle */ + } +bail: + return error; +} + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode( + HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL==hPsEncode) { + error = PSENC_INVALID_HANDLE; + } + else { + if (PSENC_OK != (InitPSData(&hPsEncode->psData))) { + goto bail; + } + + switch(psEncMode){ + case PS_BANDS_COARSE: + case PS_BANDS_MID: + hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; + hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; + FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1)*sizeof(INT)); + FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(INT)); + FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) *sizeof(UCHAR)); + break; + default: + error = PSENC_INIT_ERROR; + goto bail; + } + + hPsEncode->psEncMode = psEncMode; + hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold; + FDKsbrEnc_initPsBandNrgScale(hPsEncode); + } +bail: + return error; +} + + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode( + HANDLE_PS_ENCODE *phPsEncode + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL !=phPsEncode) { + FreeRam_PsEncode(phPsEncode); + } + + return error; +} + +typedef struct { + FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + +} PS_PWR_DATA; + + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, + HANDLE_PS_OUT hPsOut, + UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, + const INT sendHeader + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + HANDLE_PS_DATA hPsData = &hPsEncode->psData; + FIXP_DBL iid [PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL icc [PS_MAX_ENVELOPES][PS_MAX_BANDS]; + int envBorder[PS_MAX_ENVELOPES+1]; + + int group, bin, col, subband, band; + int i = 0; + + int env = 0; + int psBands = (int) hPsEncode->psEncMode; + int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES); + + C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1); + + for(env=0; envpwrL[env][band] = pwrData->pwrR[env][band] = pwrData->pwrCr[env][band] = pwrData->pwrCi[env][band] = FIXP_DBL(1); + } + + /**** calculate energies and correlation ****/ + + /* start with hybrid data */ + for (group=0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* determine group border */ + int bScale = hPsEncode->psBandNrgScale[bin]; + + FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin]; + FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin]; + FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin]; + FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin]; + + int scale = (int)dynBandScale[bin]; + for (col=envBorder[env]; coliidGroupBorders[group]; subband < hPsEncode->iidGroupBorders[group+1]; subband++) { + FIXP_QMF l_real = (hybridData[col][0][0][subband]) << scale; + FIXP_QMF l_imag = (hybridData[col][0][1][subband]) << scale; + FIXP_QMF r_real = (hybridData[col][1][0][subband]) << scale; + FIXP_QMF r_imag = (hybridData[col][1][1][subband]) << scale; + + pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale; + pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale; + pwrCr_env_bin += (fMultDiv2(l_real, r_real) + fMultDiv2(l_imag, r_imag)) >> bScale; + pwrCi_env_bin += (fMultDiv2(r_real, l_imag) - fMultDiv2(l_real, r_imag)) >> bScale; + } + } + /* assure, nrg's of left and right channel are not negative; necessary on 16 bit multiply units */ + pwrData->pwrL[env][bin] = fixMax((FIXP_DBL)0,pwrL_env_bin); + pwrData->pwrR[env][bin] = fixMax((FIXP_DBL)0,pwrR_env_bin); + + pwrData->pwrCr[env][bin] = pwrCr_env_bin; + pwrData->pwrCi[env][bin] = pwrCi_env_bin; + + } /* nIidGroups */ + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[env], pwrData->ldPwrL[env], psBands); + LdDataVector(pwrData->pwrR[env], pwrData->ldPwrR[env], psBands); + + } /* nEnvelopes */ + + /* calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands); + + /*** Envelope Reduction ***/ + while (envelopeReducible(iid,icc,psBands,nEnvelopes)) { + int e=0; + /* sum energies of two neighboring envelopes */ + nEnvelopes >>= 1; + for (e=0; epwrL[2*e], pwrData->pwrL[2*e+1], pwrData->pwrL[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrR[2*e], pwrData->pwrR[2*e+1], pwrData->pwrR[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCr[2*e],pwrData->pwrCr[2*e+1],pwrData->pwrCr[e],psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCi[2*e],pwrData->pwrCi[2*e+1],pwrData->pwrCi[e],psBands); + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[e], pwrData->ldPwrL[e], psBands); + LdDataVector(pwrData->pwrR[e], pwrData->ldPwrR[e], psBands); + + /* reduce number of envelopes and adjust borders */ + envBorder[e] = envBorder[2*e]; + } + envBorder[nEnvelopes] = envBorder[2*nEnvelopes]; + + /* re-calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->ldPwrL, pwrData->ldPwrR, pwrData->pwrCr, pwrData->pwrCi, icc, nEnvelopes, psBands); + } + + + /* */ + if(sendHeader) { + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + /*** Parameter processing, quantisation etc ***/ + processIidData(hPsData, iid, psBands, nEnvelopes, hPsEncode->iidQuantErrorThreshold); + processIccData(hPsData, icc, psBands, nEnvelopes); + + + /*** Initialize output struct ***/ + + /* PS Header on/off ? */ + if( (hPsData->headerCntiidQuantMode == hPsData->iidQuantModeLast) && (hPsData->iccQuantMode == hPsData->iccQuantModeLast) ) + && ( (hPsData->iidEnable == hPsData->iidEnableLast) && (hPsData->iccEnable == hPsData->iccEnableLast) ) ) { + hPsOut->enablePSHeader = 0; + } + else { + hPsOut->enablePSHeader = 1; + hPsData->headerCnt = 0; + } + + /* nEnvelopes = 0 ? */ + if ( (hPsData->noEnvCnt < MAX_NOENV_CNT) + && (similarIid(hPsData, psBands, nEnvelopes)) + && (similarIcc(hPsData, psBands, nEnvelopes)) ) { + hPsOut->nEnvelopes = nEnvelopes = 0; + hPsData->noEnvCnt++; + } else { + hPsData->noEnvCnt = 0; + } + + + if (nEnvelopes>0) { + + hPsOut->enableIID = hPsData->iidEnable; + hPsOut->iidMode = getIIDMode(psBands, hPsData->iidQuantMode); + + hPsOut->enableICC = hPsData->iccEnable; + hPsOut->iccMode = getICCMode(psBands, hPsData->iccQuantMode); + + hPsOut->enableIpdOpd = 0; + hPsOut->frameClass = 0; + hPsOut->nEnvelopes = nEnvelopes; + + for(env=0; envframeBorder[env] = envBorder[env+1]; + } + + for(env=0; envnEnvelopes; env++) { + hPsOut->deltaIID[env] = (PS_DELTA)hPsData->iidDiffMode[env]; + + for(band=0; bandiid[env][band] = hPsData->iidIdx[env][band]; + } + } + + for(env=0; envnEnvelopes; env++) { + hPsOut->deltaICC[env] = (PS_DELTA)hPsData->iccDiffMode[env]; + for(band=0; bandicc[env][band] = hPsData->iccIdx[env][band]; + } + } + + /* IPD OPD not supported right now */ + FDKmemclear(hPsOut->ipd, PS_MAX_ENVELOPES*PS_MAX_BANDS*sizeof(PS_DELTA)); + for(env=0; envdeltaIPD[env] = PS_DELTA_FREQ; + hPsOut->deltaOPD[env] = PS_DELTA_FREQ; + } + + FDKmemclear(hPsOut->ipdLast, PS_MAX_BANDS*sizeof(INT)); + FDKmemclear(hPsOut->opdLast, PS_MAX_BANDS*sizeof(INT)); + + for(band=0; bandiidLast[band] = hPsData->iidIdxLast[band]; + hPsOut->iccLast[band] = hPsData->iccIdxLast[band]; + } + + /* save iids and iccs for differential time coding in the next frame */ + hPsData->nEnvelopesLast = nEnvelopes; + hPsData->iidEnableLast = hPsData->iidEnable; + hPsData->iccEnableLast = hPsData->iccEnable; + hPsData->iidQuantModeLast = hPsData->iidQuantMode; + hPsData->iccQuantModeLast = hPsData->iccQuantMode; + for (i=0; iiidIdxLast[i] = hPsData->iidIdx[nEnvelopes-1][i]; + hPsData->iccIdxLast[i] = hPsData->iccIdx[nEnvelopes-1][i]; + } + } /* Envelope > 0 */ + + C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1) + + return error; +} + diff --git a/libSBRenc/src/ps_encode.h b/libSBRenc/src/ps_encode.h new file mode 100644 index 00000000..f728d477 --- /dev/null +++ b/libSBRenc/src/ps_encode.h @@ -0,0 +1,187 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial author: M. Neuendorf, N. Rettelbach, M. Multrus + contents/description: PS Parameter extraction, encoding + +******************************************************************************/ +/*! + \file + \brief PS parameter extraction, encoding functions +*/ + +#ifndef __INCLUDED_PS_ENCODE_H +#define __INCLUDED_PS_ENCODE_H + +#include "ps_const.h" +#include "ps_bitenc.h" + + +#define IID_SCALE_FT (64.f) /* maxVal in Quant tab is +/- 50 */ +#define IID_SCALE 6 /* maxVal in Quant tab is +/- 50 */ +#define IID_MAXVAL (1< QuantScale 64 */ +#define PS_QUANT_SCALE 6 /* error smaller (64-25)/64 * 20 bands * 4 env -> QuantScale 6 bit */ + + +#define QMF_GROUPS_LO_RES 12 +#define SUBQMF_GROUPS_LO_RES 10 +#define QMF_GROUPS_HI_RES 18 +#define SUBQMF_GROUPS_HI_RES 30 + + +typedef struct T_PS_DATA { + + INT iidEnable; + INT iidEnableLast; + INT iidQuantMode; + INT iidQuantModeLast; + INT iidDiffMode[PS_MAX_ENVELOPES]; + INT iidIdx [PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxLast [PS_MAX_BANDS]; + + INT iccEnable; + INT iccEnableLast; + INT iccQuantMode; + INT iccQuantModeLast; + INT iccDiffMode[PS_MAX_ENVELOPES]; + INT iccIdx [PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccIdxLast [PS_MAX_BANDS]; + + INT nEnvelopesLast; + + INT headerCnt; + INT iidTimeCnt; + INT iccTimeCnt; + INT noEnvCnt; + +} PS_DATA, *HANDLE_PS_DATA; + + +typedef struct T_PS_ENCODE{ + + PS_DATA psData; + + PS_BANDS psEncMode; + INT nQmfIidGroups; + INT nSubQmfIidGroups; + INT iidGroupBorders[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES + 1]; + INT subband2parameterIndex[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + UCHAR iidGroupWidthLd[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + FIXP_DBL iidQuantErrorThreshold; + + UCHAR psBandNrgScale [PS_MAX_BANDS]; + +} PS_ENCODE; + + +typedef struct T_PS_ENCODE *HANDLE_PS_ENCODE; + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode( + HANDLE_PS_ENCODE *phPsEncode + ); + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode( + HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold + ); + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode( + HANDLE_PS_ENCODE *phPsEncode + ); + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, + HANDLE_PS_OUT hPsOut, + UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, + const INT sendHeader + ); + +#endif diff --git a/libSBRenc/src/ps_main.cpp b/libSBRenc/src/ps_main.cpp new file mode 100644 index 00000000..ab183e2d --- /dev/null +++ b/libSBRenc/src/ps_main.cpp @@ -0,0 +1,618 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/***************************** MPEG Audio Encoder *************************** + + Initial Authors: M. Multrus + Contents/Description: PS Wrapper, Downmix + +******************************************************************************/ + +#include "ps_main.h" + + +/* Includes ******************************************************************/ + +#include "ps_const.h" +#include "ps_bitenc.h" + +#include "sbr_ram.h" + +/*--------------- function declarations --------------------*/ +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, + FIXP_QMF *maxBandValue, + SCHAR *dmxScale + ); + +/*------------- function definitions ----------------*/ +FDK_PSENC_ERROR PSEnc_Create( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (phParametricStereo==NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + int i; + HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL; + + if (NULL==(hParametricStereo = GetRam_ParamStereo())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO)); + + if (PSENC_OK != (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) { + goto bail; + } + + for (i=0; ifdkHybAnaFilter[i], + hParametricStereo->__staticHybAnaStatesLF[i], + sizeof(hParametricStereo->__staticHybAnaStatesLF[i]), + hParametricStereo->__staticHybAnaStatesHF[i], + sizeof(hParametricStereo->__staticHybAnaStatesHF[i]) + ) !=0 ) + { + error = PSENC_MEMORY_ERROR; + goto bail; + } + } + + *phParametricStereo = hParametricStereo; /* return allocated handle */ + } +bail: + return error; +} + +FDK_PSENC_ERROR PSEnc_Init( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, + INT noQmfBands + ,UCHAR *dynamic_RAM + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if ( (NULL==hParametricStereo) || (NULL==hPsEncConfig) ) { + error = PSENC_INVALID_HANDLE; + } + else { + int ch, i; + + hParametricStereo->initPS = 1; + hParametricStereo->noQmfSlots = noQmfSlots; + hParametricStereo->noQmfBands = noQmfBands; + + /* clear delay lines */ + FDKmemclear(hParametricStereo->qmfDelayLines, sizeof(hParametricStereo->qmfDelayLines)); + + hParametricStereo->qmfDelayScale = FRACT_BITS-1; + + /* create configuration for hybrid filter bank */ + for (ch=0; chfdkHybAnaFilter[ch], + THREE_TO_TEN, + QMF_CHANNELS, + QMF_CHANNELS, + 1 + ); + } /* ch */ + + FDKhybridSynthesisInit( + &hParametricStereo->fdkHybSynFilter, + THREE_TO_TEN, + QMF_CHANNELS, + QMF_CHANNELS + ); + + /* determine average delay */ + hParametricStereo->psDelay = (HYBRID_FILTER_DELAY*hParametricStereo->noQmfBands); + + if ( (hPsEncConfig->maxEnvelopes < PSENC_NENV_1) || (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX) ) { + hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT; + } + hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes; + + if (PSENC_OK != (error = FDKsbrEnc_InitPSEncode(hParametricStereo->hPsEncode, (PS_BANDS) hPsEncConfig->nStereoBands, hPsEncConfig->iidQuantErrorThreshold))){ + goto bail; + } + + for (ch = 0; chpHybridData[i+HYBRID_READ_OFFSET][ch][0] = &pDynReal[i*MAX_HYBRID_BANDS]; + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][ch][1] = &pDynImag[i*MAX_HYBRID_BANDS];; + } + + for (i=0; ipHybridData[i][ch][0] = hParametricStereo->__staticHybridData[i][ch][0]; + hParametricStereo->pHybridData[i][ch][1] = hParametricStereo->__staticHybridData[i][ch][1]; + } + } /* ch */ + + /* clear static hybrid buffer */ + FDKmemclear(hParametricStereo->__staticHybridData, sizeof(hParametricStereo->__staticHybridData)); + + /* clear bs buffer */ + FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut)); + + hParametricStereo->psOut[0].enablePSHeader = 1; /* write ps header in first frame */ + + /* clear scaling buffer */ + FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR)*PS_MAX_BANDS); + FDKmemclear(hParametricStereo->maxBandValue, sizeof(FIXP_QMF)*PS_MAX_BANDS); + + } /* valid handle */ +bail: + return error; +} + + +FDK_PSENC_ERROR PSEnc_Destroy( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL!=phParametricStereo) { + HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo; + if(hParametricStereo != NULL){ + FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode); + FreeRam_ParamStereo(phParametricStereo); + } + } + + return error; +} + +static FDK_PSENC_ERROR ExtractPSParameters( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const int sendHeader, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2] + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } + else { + /* call ps encode function */ + if (hParametricStereo->initPS){ + hParametricStereo->psOut[1] = hParametricStereo->psOut[0]; + } + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + + if (PSENC_OK != (error = FDKsbrEnc_PSEncode( + hParametricStereo->hPsEncode, + &hParametricStereo->psOut[1], + hParametricStereo->dynBandScale, + hParametricStereo->maxEnvelopes, + hybridData, + hParametricStereo->noQmfSlots, + sendHeader))) + { + goto bail; + } + + if (hParametricStereo->initPS) { + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + hParametricStereo->initPS = 0; + } + } +bail: + return error; +} + + +static FDK_PSENC_ERROR DownmixPSQmfData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + FIXP_QMF **RESTRICT mixRealQmfData, + FIXP_QMF **RESTRICT mixImagQmfData, + INT_PCM *downsampledOutSignal, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT noQmfSlots, + const INT psQmfScale[MAX_PS_CHANNELS], + SCHAR *qmfScale + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + + if(hParametricStereo == NULL){ + error = PSENC_INVALID_HANDLE; + } + else { + int n, k; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_QMF, 2*QMF_CHANNELS) + + /* define scalings */ + int dynQmfScale = fixMax(0, hParametricStereo->dmxScale-1); /* scale one bit more for addition of left and right */ + int downmixScale = psQmfScale[0] - dynQmfScale; + const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */ + + for (n = 0; n>1) < fMult(maxStereoScaleFactor,tmpScaleFactor) ) { + + int sc_num = CountLeadingBits(stereoScaleFactor) ; + int sc_denum = CountLeadingBits(tmpScaleFactor) ; + sc = -(sc_num-sc_denum); + + tmpScaleFactor = schur_div((stereoScaleFactor<<(sc_num))>>1, + tmpScaleFactor<>=1; + } + stereoScaleFactor = sqrtFixp(tmpScaleFactor); + stereoScaleFactor <<= (sc>>1); + } + else { + stereoScaleFactor = maxStereoScaleFactor; + } + + /* write data to hybrid output */ + tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftReal + tmpRightReal))>>dynScale; + tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, (FIXP_QMF)(tmpLeftImag + tmpRightImag))>>dynScale; + + } /* hybrid bands - k */ + + FDKhybridSynthesisApply( + &hParametricStereo->fdkHybSynFilter, + tmpHybrid[0], + tmpHybrid[1], + mixRealQmfData[n], + mixImagQmfData[n]); + + qmfSynthesisFilteringSlot( + sbrSynthQmf, + mixRealQmfData[n], + mixImagQmfData[n], + downmixScale-7, + downmixScale-7, + downsampledOutSignal+(n*sbrSynthQmf->no_channels), + 1, + pWorkBuffer); + + } /* slots */ + + *qmfScale = -downmixScale + 7; + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_QMF, 2*QMF_CHANNELS) + + { + const INT noQmfSlots2 = hParametricStereo->noQmfSlots>>1; + const int noQmfBands = hParametricStereo->noQmfBands; + + INT scale, i, j, slotOffset; + + FIXP_QMF tmp[2][QMF_CHANNELS]; + + for (i=0; iqmfDelayLines[0][i], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], noQmfBands*sizeof(FIXP_QMF)); + + FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], mixRealQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], mixImagQmfData[i+noQmfSlots2], noQmfBands*sizeof(FIXP_QMF)); + + FDKmemcpy(mixRealQmfData[i+noQmfSlots2], mixRealQmfData[i], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(mixImagQmfData[i+noQmfSlots2], mixImagQmfData[i], noQmfBands*sizeof(FIXP_QMF)); + + FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands*sizeof(FIXP_QMF)); + FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands*sizeof(FIXP_QMF)); + } + + if (hParametricStereo->qmfDelayScale > *qmfScale) { + scale = hParametricStereo->qmfDelayScale - *qmfScale; + slotOffset = 0; + } + else { + scale = *qmfScale - hParametricStereo->qmfDelayScale; + slotOffset = noQmfSlots2; + } + + for (i=0; i>= scale; + mixImagQmfData[i+slotOffset][j] >>= scale; + } + } + + scale = *qmfScale; + *qmfScale = FDKmin(*qmfScale, hParametricStereo->qmfDelayScale); + hParametricStereo->qmfDelayScale = scale; + } + + } /* valid handle */ + + return error; +} + + +INT FDKsbrEnc_PSEnc_WritePSData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream + ) +{ + return ( (hParametricStereo!=NULL) ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) : 0 ); +} + + +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + INT_PCM *samples[2], + UINT timeInStride, + QMF_FILTER_BANK **hQmfAnalysis, + FIXP_QMF **RESTRICT downmixedRealQmfData, + FIXP_QMF **RESTRICT downmixedImagQmfData, + INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + SCHAR *qmfScale, + const int sendHeader + ) +{ + FDK_PSENC_ERROR error = PSENC_OK; + INT psQmfScale[MAX_PS_CHANNELS] = {0}; + int psCh, i; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_QMF, 4*QMF_CHANNELS) + + for (psCh = 0; psChno_col; i++) { + + qmfAnalysisFilteringSlot( + hQmfAnalysis[psCh], + &pWorkBuffer[2*QMF_CHANNELS], /* qmfReal[QMF_CHANNELS] */ + &pWorkBuffer[3*QMF_CHANNELS], /* qmfImag[QMF_CHANNELS] */ + samples[psCh]+i*(hQmfAnalysis[psCh]->no_channels*timeInStride), + timeInStride, + &pWorkBuffer[0*QMF_CHANNELS] /* qmf workbuffer 2*QMF_CHANNELS */ + ); + + FDKhybridAnalysisApply( + &hParametricStereo->fdkHybAnaFilter[psCh], + &pWorkBuffer[2*QMF_CHANNELS], /* qmfReal[QMF_CHANNELS] */ + &pWorkBuffer[3*QMF_CHANNELS], /* qmfImag[QMF_CHANNELS] */ + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][0], + hParametricStereo->pHybridData[i+HYBRID_READ_OFFSET][psCh][1] + ); + + } /* no_col loop i */ + + psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor; + + } /* for psCh */ + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_QMF, 4*QMF_CHANNELS) + + /* find best scaling in new QMF and Hybrid data */ + psFindBestScaling( hParametricStereo, + &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->dynBandScale, + hParametricStereo->maxBandValue, + &hParametricStereo->dmxScale ) ; + + + /* extract the ps parameters */ + if(PSENC_OK != (error = ExtractPSParameters(hParametricStereo, sendHeader, &hParametricStereo->pHybridData[0]))){ + goto bail; + } + + /* save hybrid date for next frame */ + for (i=0; ipHybridData[i][0][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, real */ + FDKmemcpy(hParametricStereo->pHybridData[i][0][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][0][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* left, imag */ + FDKmemcpy(hParametricStereo->pHybridData[i][1][0], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][0], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, real */ + FDKmemcpy(hParametricStereo->pHybridData[i][1][1], hParametricStereo->pHybridData[HYBRID_FRAMESIZE+i][1][1], MAX_HYBRID_BANDS*sizeof(FIXP_DBL)); /* right, imag */ + } + + /* downmix and hybrid synthesis */ + if (PSENC_OK != (error = DownmixPSQmfData(hParametricStereo, sbrSynthQmf, downmixedRealQmfData, downmixedImagQmfData, downsampledOutSignal, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) { + goto bail; + } + +bail: + + return error; +} + +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, + FIXP_QMF *maxBandValue, + SCHAR *dmxScale + ) +{ + HANDLE_PS_ENCODE hPsEncode = hParametricStereo->hPsEncode; + + INT group, bin, col, band; + const INT frameSize = hParametricStereo->noQmfSlots; + const INT psBands = (INT) hPsEncode->psEncMode; + const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + /* group wise scaling */ + FIXP_QMF maxVal [2][PS_MAX_BANDS]; + FIXP_QMF maxValue = FL2FXCONST_DBL(0.f); + + FDKmemclear(maxVal, sizeof(maxVal)); + + /* start with hybrid data */ + for (group=0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* QMF downmix scaling */ + { + FIXP_QMF tmp = maxVal[0][bin]; + int i; + for (col=0; coliidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) { + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i])); + } + } + maxVal[0][bin] = tmp; + + tmp = maxVal[1][bin]; + for (col=frameSize-HYBRID_READ_OFFSET; coliidGroupBorders[group]; i < hPsEncode->iidGroupBorders[group+1]; i++) { + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_QMF)fixp_abs(hybridData[col][1][1][i])); + } + } + maxVal[1][bin] = tmp; + } + } /* nIidGroups */ + + /* convert maxSpec to maxScaling, find scaling space */ + for (band=0; band>1][QMF_CHANNELS]; + int qmfDelayScale; + + INT psDelay; + UINT maxEnvelopes; + UCHAR dynBandScale[PS_MAX_BANDS]; + FIXP_DBL maxBandValue[PS_MAX_BANDS]; + SCHAR dmxScale; + INT initPS; + INT noQmfSlots; + INT noQmfBands; + + FIXP_DBL __staticHybAnaStatesLF[MAX_PS_CHANNELS][2*HYBRID_FILTER_LENGTH*HYBRID_MAX_QMF_BANDS]; + FIXP_DBL __staticHybAnaStatesHF[MAX_PS_CHANNELS][2*HYBRID_FILTER_DELAY*(QMF_CHANNELS-HYBRID_MAX_QMF_BANDS)]; + FDK_ANA_HYB_FILTER fdkHybAnaFilter[MAX_PS_CHANNELS]; + FDK_SYN_HYB_FILTER fdkHybSynFilter; + +} PARAMETRIC_STEREO; + + +typedef struct T_PSENC_CONFIG { + INT frameSize; + INT qmfFilterMode; + INT sbrPsDelay; + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG maxEnvelopes; + FIXP_DBL iidQuantErrorThreshold; + +} PSENC_CONFIG, *HANDLE_PSENC_CONFIG; + +typedef struct T_PARAMETRIC_STEREO *HANDLE_PARAMETRIC_STEREO; + + +/** + * \brief Create a parametric stereo encoder instance. + * + * \param phParametricStereo A pointer to a parametric stereo handle to be allocated. Initialized on return. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_MEMORY_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Create( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ); + + +/** + * \brief Initialize a parametric stereo encoder instance. + * + * \param hParametricStereo Meta Data handle. + * \param hPsEncConfig Filled parametric stereo configuration structure. + * \param noQmfSlots Number of slots within one audio frame. + * \param noQmfBands Number of QMF bands. + * \param dynamic_RAM Pointer to preallocated workbuffer. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_INIT_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Init( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, + INT noQmfBands + ,UCHAR *dynamic_RAM + ); + + +/** + * \brief Destroy parametric stereo encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phParametricStereo Pointer to the parametric stereo handle to be deallocated. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, on failure. + */ +FDK_PSENC_ERROR PSEnc_Destroy( + HANDLE_PARAMETRIC_STEREO *phParametricStereo + ); + + +/** + * \brief Apply parametric stereo processing. + * + * \param hParametricStereo Meta Data handle. + * \param samples Pointer to 2 channel audio input signal. + * \param timeInStride, Stride factor of input buffer. + * \param hQmfAnalysis, Pointer to QMF analysis filterbanks. + * \param downmixedRealQmfData Pointer to real QMF buffer to be written to. + * \param downmixedImagQmfData Pointer to imag QMF buffer to be written to. + * \param downsampledOutSignal Pointer to buffer where to write downmixed timesignal. + * \param sbrSynthQmf Pointer to QMF synthesis filterbank. + * \param qmfScale Return scaling factor of the qmf data. + * \param sendHeader Signal whether to write header data. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_ENCODE_ERROR, on failure. + */ +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + INT_PCM *samples[2], + UINT timeInStride, + QMF_FILTER_BANK **hQmfAnalysis, + FIXP_QMF **RESTRICT downmixedRealQmfData, + FIXP_QMF **RESTRICT downmixedImagQmfData, + INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, + SCHAR *qmfScale, + const int sendHeader + ); + + +/** + * \brief Write parametric stereo bitstream. + * + * Write ps_data() element to bitstream and return number of written bits. + * Returns number of written bits only, if hBitstream == NULL. + * + * \param hParametricStereo Meta Data handle. + * \param hBitstream Bitstream buffer handle. + * + * \return + * - number of written bits. + */ +INT FDKsbrEnc_PSEnc_WritePSData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream + ); + +#endif /* __INCLUDED_PS_MAIN_H */ diff --git a/libSBRenc/src/resampler.cpp b/libSBRenc/src/resampler.cpp new file mode 100644 index 00000000..4adb2430 --- /dev/null +++ b/libSBRenc/src/resampler.cpp @@ -0,0 +1,507 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief FDK resampler tool box: + \author M. Werner +*/ + +#include "resampler.h" + +#include "genericStds.h" + + +/**************************************************************************/ +/* BIQUAD Filter Specifications */ +/**************************************************************************/ + +#define B1 0 +#define B2 1 +#define A1 2 +#define A2 3 + +#define BQC(x) FL2FXCONST_SGL(x/2) + + +struct FILTER_PARAM { + const FIXP_SGL *coeffa; /*! SOS matrix One row/section. Scaled using BQC(). Order of coefficients: B1,B2,A1,A2. B0=A0=1.0 */ + FIXP_DBL g; /*! overall gain */ + int Wc; /*! normalized passband bandwidth at input samplerate * 1000 */ + int noCoeffs; /*! number of filter coeffs */ + int delay; /*! delay in samples at input samplerate */ +}; + +#define BIQUAD_COEFSTEP 4 + +/** + *\brief Low Pass + Wc = 0,5, order 30, Stop Band -96dB. Wc criteria is "almost 0dB passband", not the usual -3db gain point. + [b,a]=cheby2(30,96,0.505) + [sos,g]=tf2sos(b,a) + bandwidth 0.48 + */ +static const FIXP_SGL sos48[] = { + BQC(1.98941075681938), BQC(0.999999996890811), BQC(0.863264527201963), BQC( 0.189553799960663), + BQC(1.90733804822445), BQC(1.00000001736189), BQC(0.836321575841691), BQC( 0.203505809266564), + BQC(1.75616665495325), BQC(0.999999946079721), BQC(0.784699225121588), BQC( 0.230471265506986), + BQC(1.55727745512726), BQC(1.00000011737815), BQC(0.712515423588351), BQC( 0.268752723900498), + BQC(1.33407591943643), BQC(0.999999795953228), BQC(0.625059117330989), BQC( 0.316194685288965), + BQC(1.10689898412458), BQC(1.00000035057114), BQC(0.52803514366398), BQC( 0.370517843224669), + BQC(0.89060371078454), BQC(0.999999343962822), BQC(0.426920462165257), BQC( 0.429608200207746), + BQC(0.694438261209433), BQC( 1.0000008629792), BQC(0.326530699561716), BQC( 0.491714450654174), + BQC(0.523237800935322), BQC(1.00000101349782), BQC(0.230829556274851), BQC( 0.555559034843281), + BQC(0.378631165929563), BQC(0.99998986482665), BQC(0.142906422036095), BQC( 0.620338874442411), + BQC(0.260786911308437), BQC(1.00003261460178), BQC(0.0651008576256505), BQC( 0.685759923926262), + BQC(0.168409429188098), BQC(0.999933049695828), BQC(-0.000790067789975562), BQC( 0.751905896602325), + BQC(0.100724533818628), BQC(1.00009472669872), BQC(-0.0533772830257041), BQC( 0.81930744384525), + BQC(0.0561434357867363), BQC(0.999911636304276), BQC(-0.0913550299236405), BQC( 0.88883625875915), + BQC(0.0341680678662057), BQC(1.00003667508676), BQC(-0.113405185536697), BQC( 0.961756638268446) +}; + +#ifdef RS_BIQUAD_SCATTERGAIN +static const FIXP_DBL g48 = FL2FXCONST_DBL(0.67436532061161992682404480717671 - 0.001); +#else +static const FIXP_DBL g48 = FL2FXCONST_DBL(0.002712866530047) - (FIXP_DBL)0x8000; +#endif + +static const struct FILTER_PARAM param_set48 = { + sos48, + g48, + 480, + 15, + 4 /* LF 2 */ +}; + +/** + *\brief Low Pass + Wc = 0,5, order 24, Stop Band -96dB. Wc criteria is "almost 0dB passband", not the usual -3db gain point. + [b,a]=cheby2(24,96,0.5) + [sos,g]=tf2sos(b,a) + bandwidth 0.45 + */ +static const FIXP_SGL sos45[] = { + BQC(1.982962601444), BQC(1.00000000007504), BQC(0.646113303737836), BQC( 0.10851149979981), + BQC(1.85334094281111), BQC(0.999999999677192), BQC(0.612073220102006), BQC( 0.130022141698044), + BQC(1.62541051415425), BQC(1.00000000080398), BQC(0.547879702855959), BQC( 0.171165825133192), + BQC(1.34554656923247), BQC(0.9999999980169), BQC(0.460373914508491), BQC( 0.228677463376354), + BQC(1.05656568503116), BQC(1.00000000569363), BQC(0.357891894038287), BQC( 0.298676843912185), + BQC(0.787967587877312), BQC(0.999999984415017), BQC(0.248826893211877), BQC( 0.377441803512978), + BQC(0.555480971120497), BQC(1.00000003583307), BQC(0.140614263345315), BQC( 0.461979302213679), + BQC(0.364986207070964), BQC(0.999999932084303), BQC(0.0392669446074516), BQC( 0.55033451180825), + BQC(0.216827267631558), BQC(1.00000010534682), BQC(-0.0506232228865103), BQC( 0.641691581560946), + BQC(0.108951672277119), BQC(0.999999871167516), BQC(-0.125584840183225), BQC( 0.736367748771803), + BQC(0.0387988607229035), BQC(1.00000011205574), BQC(-0.182814849097974), BQC( 0.835802108714964), + BQC(0.0042866175809225), BQC(0.999999954830813), BQC(-0.21965740617151), BQC( 0.942623047782363) +}; + +#ifdef RS_BIQUAD_SCATTERGAIN +static const FIXP_DBL g45 = FL2FXCONST_DBL(0.60547428891341319051142629706723 - 0.001); +#else +static const FIXP_DBL g45 = FL2FXCONST_DBL(0.00242743980909524) - (FIXP_DBL)0x8000; +#endif + +static const struct FILTER_PARAM param_set45 = { + sos45, + g45, + 450, + 12, + 4 /* LF 2 */ +}; + +/* + Created by Octave 2.1.73, Mon Oct 13 17:31:32 2008 CEST + Wc = 0,5, order 16, Stop Band -96dB damping. + [b,a]=cheby2(16,96,0.5) + [sos,g]=tf2sos(b,a) + bandwidth = 0.41 + */ + +static const FIXP_SGL sos41[] = +{ + BQC(1.96193625292), BQC(0.999999999999964), BQC(0.169266178786789), BQC(0.0128823300475907), + BQC(1.68913437662092), BQC(1.00000000000053), BQC(0.124751503206552), BQC(0.0537472273950989), + BQC(1.27274692366017), BQC(0.999999999995674), BQC(0.0433108625178357), BQC(0.131015753236317), + BQC(0.85214175088395), BQC(1.00000000001813), BQC(-0.0625658152550408), BQC(0.237763778993806), + BQC(0.503841579939009), BQC(0.999999999953223), BQC(-0.179176128722865), BQC(0.367475236424474), + BQC(0.249990711986162), BQC(1.00000000007952), BQC(-0.294425165824676), BQC(0.516594857170212), + BQC(0.087971668680286), BQC(0.999999999915528), BQC(-0.398956566777928), BQC(0.686417767801123), + BQC(0.00965373325350294), BQC(1.00000000003744), BQC(-0.48579173764817), BQC(0.884931534239068) +}; + +#ifdef RS_BIQUAD_SCATTERGAIN +static const FIXP_DBL g41 = FL2FXCONST_DBL(0.44578514476476679750811222123569); +#else +static const FIXP_DBL g41 = FL2FXCONST_DBL(0.00155956951169248); +#endif + +static const struct FILTER_PARAM param_set41 = { + sos41, + g41, + 410, + 8, + 5 /* LF 3 */ +}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 17:55:33 2008 CEST + Wc = 0,5, order 12, Stop Band -96dB damping. + [b,a]=cheby2(12,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos35[] = +{ + BQC(1.93299325235762), BQC(0.999999999999985), BQC(-0.140733187246596), BQC(0.0124139497836062), + BQC(1.4890416764109), BQC(1.00000000000011), BQC(-0.198215402588504), BQC(0.0746730616584138), + BQC(0.918450161309795), BQC(0.999999999999619), BQC(-0.30133912791941), BQC(0.192276468839529), + BQC(0.454877024246818), BQC(1.00000000000086), BQC(-0.432337328809815), BQC(0.356852933642815), + BQC(0.158017147118507), BQC(0.999999999998876), BQC(-0.574817494249777), BQC(0.566380436970833), + BQC(0.0171834649478749), BQC(1.00000000000055), BQC(-0.718581178041165), BQC(0.83367484487889) +}; + +#ifdef RS_BIQUAD_SCATTERGAIN +static const FIXP_DBL g35 = FL2FXCONST_DBL(0.34290853574973898694521267606792); +#else +static const FIXP_DBL g35 = FL2FXCONST_DBL(0.00162580994125131); +#endif + +static const struct FILTER_PARAM param_set35 = { + sos35, + g35, + 350, + 6, + 4 +}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 18:15:38 2008 CEST + Wc = 0,5, order 8, Stop Band -96dB damping. + [b,a]=cheby2(8,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos25[] = +{ + BQC(1.85334094301225), BQC(1.0), BQC(-0.702127214212663), BQC(0.132452403998767), + BQC(1.056565682167), BQC(0.999999999999997), BQC(-0.789503667880785), BQC(0.236328693569128), + BQC(0.364986307455489), BQC(0.999999999999996), BQC(-0.955191189843375), BQC(0.442966457936379), + BQC(0.0387985751642125), BQC(1.0), BQC(-1.19817786088084), BQC(0.770493895456328) +}; + +#ifdef RS_BIQUAD_SCATTERGAIN +static const FIXP_DBL g25 = FL2FXCONST_DBL(0.17533917408936346960080259950471); +#else +static const FIXP_DBL g25 = FL2FXCONST_DBL(0.000945182835294559); +#endif + +static const struct FILTER_PARAM param_set25 = { + sos25, + g25, + 250, + 4, + 5 +}; + +/* Must be sorted in descending order */ +static const struct FILTER_PARAM *const filter_paramSet[] = { + ¶m_set48, + ¶m_set45, + ¶m_set41, + ¶m_set35, + ¶m_set25 +}; + + +/**************************************************************************/ +/* Resampler Functions */ +/**************************************************************************/ + + +/*! + \brief Reset downsampler instance and clear delay lines + + \return success of operation +*/ + +INT FDKaacEnc_InitDownsampler(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + int Wc, /*!< normalized cutoff freq * 1000* */ + int ratio) /*!< downsampler ratio (only 2 supported at the momment) */ + +{ + UINT i; + const struct FILTER_PARAM *currentSet=NULL; + + FDK_ASSERT(ratio == 2); + FDKmemclear(DownSampler->downFilter.states, sizeof(DownSampler->downFilter.states)); + DownSampler->downFilter.ptr = 0; + + /* + find applicable parameter set + */ + currentSet = filter_paramSet[0]; + for(i=1;iWc <= Wc) { + break; + } + currentSet = filter_paramSet[i]; + } + + DownSampler->downFilter.coeffa = currentSet->coeffa; + + + DownSampler->downFilter.gain = currentSet->g; + FDK_ASSERT(currentSet->noCoeffs <= MAXNR_SECTIONS*2); + + DownSampler->downFilter.noCoeffs = currentSet->noCoeffs; + DownSampler->delay = currentSet->delay; + DownSampler->downFilter.Wc = currentSet->Wc; + + DownSampler->ratio = ratio; + DownSampler->pending = ratio-1; + return(1); +} + + +/*! + \brief faster simple folding operation + Filter: + H(z) = A(z)/B(z) + with + A(z) = a[0]*z^0 + a[1]*z^1 + a[2]*z^2 ... a[n]*z^n + + \return filtered value +*/ + +static inline INT_PCM AdvanceFilter(LP_FILTER *downFilter, /*!< pointer to iir filter instance */ + INT_PCM *pInput, /*!< input of filter */ + int downRatio, + int inStride) +{ + INT_PCM output; + int i, n; + + +#ifdef RS_BIQUAD_SCATTERGAIN +#define BIQUAD_SCALE 3 +#else +#define BIQUAD_SCALE 12 +#endif + + FIXP_DBL y = FL2FXCONST_DBL(0.0f); + FIXP_DBL input; + + for (n=0; nstates; + const FIXP_SGL *coeff = downFilter->coeffa; + int s1,s2; + + s1 = downFilter->ptr; + s2 = s1 ^ 1; + +#if (SAMPLE_BITS == 16) + input = ((FIXP_DBL)pInput[n*inStride]) << (DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE); +#elif (SAMPLE_BITS == 32) + input = pInput[n*inStride] >> BIQUAD_SCALE; +#else +#error NOT IMPLEMENTED +#endif + +#ifndef RS_BIQUAD_SCATTERGAIN /* Merged Direct form I */ + + FIXP_BQS state1, state2, state1b, state2b; + + state1 = states[0][s1]; + state2 = states[0][s2]; + + /* Loop over sections */ + for (i=0; inoCoeffs; i++) + { + FIXP_DBL state0; + + /* Load merged states (from next section) */ + state1b = states[i+1][s1]; + state2b = states[i+1][s2]; + + state0 = input + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); + y = state0 - fMult(state1b, coeff[A1]) - fMult(state2b, coeff[A2]); + + /* Store new feed forward merge state */ + states[i+1][s2] = y<<1; + /* Store new feed backward state */ + states[i][s2] = input<<1; + + /* Feedback output to next section. */ + input = y; + + /* Transfer merged states */ + state1 = state1b; + state2 = state2b; + + /* Step to next coef set */ + coeff += BIQUAD_COEFSTEP; + } + downFilter->ptr ^= 1; + } + /* Apply global gain */ + y = fMult(y, downFilter->gain); + +#else /* Direct form II */ + + /* Loop over sections */ + for (i=0; inoCoeffs; i++) + { + FIXP_BQS state1, state2; + FIXP_DBL state0; + + /* Load states */ + state1 = states[i][s1]; + state2 = states[i][s2]; + + state0 = input - fMult(state1, coeff[A1]) - fMult(state2, coeff[A2]); + y = state0 + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); + /* Apply scattered gain */ + y = fMult(y, downFilter->gain); + + /* Store new state in normalized form */ +#ifdef RS_BIQUAD_STATES16 + /* Do not saturate any state value ! The result would be unacceptable. Rounding makes SNR around 10dB better. */ + states[i][s2] = (FIXP_BQS)(LONG)((state0 + (FIXP_DBL)(1<<(DFRACT_BITS-FRACT_BITS-2))) >> (DFRACT_BITS-FRACT_BITS-1)); +#else + states[i][s2] = state0<<1; +#endif + + /* Feedback output to next section. */ + input=y; + + /* Step to next coef set */ + coeff += BIQUAD_COEFSTEP; + } + downFilter->ptr ^= 1; + } + +#endif + + /* Apply final gain/scaling to output */ +#if (SAMPLE_BITS == 16) + output = (INT_PCM) SATURATE_RIGHT_SHIFT(y+(FIXP_DBL)(1<<(DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE-1)), DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); + //output = (INT_PCM) SATURATE_RIGHT_SHIFT(y, DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); +#else + output = SATURATE_LEFT_SHIFT(y, BIQUAD_SCALE, SAMPLE_BITS); +#endif + + + return output; +} + + + + +/*! + \brief FDKaacEnc_Downsample numInSamples of type INT_PCM + Returns number of output samples in numOutSamples + + \return success of operation +*/ + +INT FDKaacEnc_Downsample(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT inStride, /*!< increment of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples, /*!< pointer tp number of output samples */ + INT outStride /*!< increment of output samples */ + ) +{ + INT i; + *numOutSamples=0; + + for(i=0; iratio) + { + *outSamples = AdvanceFilter(&(DownSampler->downFilter), &inSamples[i*inStride], DownSampler->ratio, inStride); + outSamples += outStride; + } + *numOutSamples = numInSamples/DownSampler->ratio; + + return 0; +} + diff --git a/libSBRenc/src/resampler.h b/libSBRenc/src/resampler.h new file mode 100644 index 00000000..0192970a --- /dev/null +++ b/libSBRenc/src/resampler.h @@ -0,0 +1,151 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#ifndef __RESAMPLER_H +#define __RESAMPLER_H +/*! + \file + \brief Fixed Point Resampler Tool Box +*/ + +#include "common_fix.h" + + +/**************************************************************************/ +/* BIQUAD Filter Structure */ +/**************************************************************************/ + +#define MAXNR_SECTIONS (15) + +#ifdef RS_BIQUAD_STATES16 +typedef FIXP_SGL FIXP_BQS; +#else +typedef FIXP_DBL FIXP_BQS; +#endif + +typedef struct +{ + FIXP_BQS states[MAXNR_SECTIONS+1][2]; /*! state buffer */ + const FIXP_SGL *coeffa; /*! pointer to filter coeffs */ + FIXP_DBL gain; /*! overall gain factor */ + int Wc; /*! normalized cutoff freq * 1000 */ + int noCoeffs; /*! number of filter coeffs sets */ + int ptr; /*! index to rinbuffers */ +} LP_FILTER; + + +/**************************************************************************/ +/* Downsampler Structure */ +/**************************************************************************/ + +typedef struct +{ + LP_FILTER downFilter; /*! filter instance */ + int ratio; /*! downsampling ration */ + int delay; /*! downsampling delay (source fs) */ + int pending; /*! number of pending output samples */ +} DOWNSAMPLER; + + +/** + * \brief Initialized a given downsampler structure. + */ +INT FDKaacEnc_InitDownsampler(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT Wc, /*!< normalized cutoff freq * 1000 */ + INT ratio); /*!< downsampler ratio */ + +/** + * \brief Downsample a set of audio samples. numInSamples must be at least equal to the + * downsampler ratio. + */ +INT FDKaacEnc_Downsample(DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT inStride, /*!< increment of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples, /*!< pointer tp number of output samples */ + INT outstride); /*!< increment of output samples */ + + + +#endif /* __RESAMPLER_H */ diff --git a/libSBRenc/src/sbr.h b/libSBRenc/src/sbr.h new file mode 100644 index 00000000..c74ad2ae --- /dev/null +++ b/libSBRenc/src/sbr.h @@ -0,0 +1,166 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Main SBR structs definitions +*/ + +#ifndef __SBR_H +#define __SBR_H + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "tran_det.h" +#include "code_env.h" +#include "env_est.h" +#include "cmondata.h" + +#include "qmf.h" +#include "resampler.h" + +#include "ton_corr.h" + + +/* SBR bitstream delay */ + #define DELAY_FRAMES 2 + + +typedef struct SBR_CHANNEL { + struct ENV_CHANNEL hEnvChannel; + //INT_PCM *pDSOutBuffer; /**< Pointer to downsampled audio output of SBR encoder */ + DOWNSAMPLER downSampler; + +} SBR_CHANNEL; +typedef SBR_CHANNEL* HANDLE_SBR_CHANNEL; + +typedef struct SBR_ELEMENT { + HANDLE_SBR_CHANNEL sbrChannel[2]; + QMF_FILTER_BANK *hQmfAnalysis[2]; + SBR_CONFIG_DATA sbrConfigData; + SBR_HEADER_DATA sbrHeaderData; + SBR_BITSTREAM_DATA sbrBitstreamData; + COMMON_DATA CmonData; + INT dynXOverFreqDelay[5]; /**< to delay a frame (I don't like it that much that way - hrc) */ + SBR_ELEMENT_INFO elInfo; + + UCHAR payloadDelayLine[1+DELAY_FRAMES][MAX_PAYLOAD_SIZE]; + UINT payloadDelayLineSize[1+DELAY_FRAMES]; /* Sizes in bits */ + +} SBR_ELEMENT, *HANDLE_SBR_ELEMENT; + +typedef struct SBR_ENCODER +{ + HANDLE_SBR_ELEMENT sbrElement[(8)]; + HANDLE_SBR_CHANNEL pSbrChannel[(8)]; + QMF_FILTER_BANK QmfAnalysis[(8)]; + DOWNSAMPLER lfeDownSampler; + int lfeChIdx; /* -1 default for no lfe, else assign channel index */ + int noElements; /* Number of elements */ + int nChannels; /* Total channel count across all elements. */ + int frameSize; /* SBR framelength. */ + int bufferOffset; /* Offset for SBR parameter extraction in time domain input buffer. */ + int downsampledOffset; /* Offset of downsampled/mixed output for core encoder. */ + int downmixSize; /* Size in samples of downsampled/mixed output for core encoder. */ + INT downSampleFactor; /* Sampling rate relation between the SBR and the core encoder. */ + int fTimeDomainDownsampling; /* Flag signalling time domain downsampling instead of QMF downsampling. */ + int nBitstrDelay; /* Amount of SBR frames to be delayed in bitstream domain. */ + INT estimateBitrate; /* estimate bitrate of SBR encoder */ + INT inputDataDelay; /* delay caused by downsampler, in/out buffer at sbrEncoder_EncodeFrame */ + + UCHAR* dynamicRam; + UCHAR* pSBRdynamic_RAM; + + HANDLE_PARAMETRIC_STEREO hParametricStereo; + QMF_FILTER_BANK qmfSynthesisPS; + + /* parameters describing allocation volume of present instance */ + INT maxElements; + INT maxChannels; + INT supportPS; + + +} SBR_ENCODER; + + +#endif /* __SBR_H */ diff --git a/libSBRenc/src/sbr_def.h b/libSBRenc/src/sbr_def.h new file mode 100644 index 00000000..85ac587f --- /dev/null +++ b/libSBRenc/src/sbr_def.h @@ -0,0 +1,275 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief SBR main definitions +*/ +#ifndef __SBR_DEF_H +#define __SBR_DEF_H + +#include "common_fix.h" + +#define noError 0 +#define HANDLE_ERROR_INFO INT +#define ERROR(a,b) 1 +#define handBack + +/* #define SBR_ENV_STATISTICS_BITRATE */ +#undef SBR_ENV_STATISTICS_BITRATE + +/* #define SBR_ENV_STATISTICS */ +#undef SBR_ENV_STATISTICS + +/* #define SBR_PAYLOAD_MONITOR */ +#undef SBR_PAYLOAD_MONITOR + +#define SWAP(a,b) tempr=a, a=b, b=tempr +#define TRUE 1 +#define FALSE 0 + + +/* Constants */ +#define EPS 1e-12 +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define RELAXATION_FLOAT (1e-6f) +#define RELAXATION (FL2FXCONST_DBL(RELAXATION_FLOAT)) +#define RELAXATION_FRACT (FL2FXCONST_DBL(0.524288f)) /* 0.524288f is fractional part of RELAXATION */ +#define RELAXATION_SHIFT (19) +#define RELAXATION_LD64 (FL2FXCONST_DBL(0.31143075889f))/* (ld64(RELAXATION) */ + +/************ Definitions ***************/ +#define SBR_COMP_MODE_DELTA 0 +#define SBR_COMP_MODE_CTS 1 +#define SBR_MAX_ENERGY_VALUES 5 +#define SBR_GLOBAL_TONALITY_VALUES 2 + +#define MAX_NUM_CHANNELS 2 + +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NUM_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NUM_NOISE_COEFFS*MAX_NOISE_ENVELOPES) + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) +#define MAX_ENVELOPES 5 +#define MAX_FREQ_COEFFS 48 + +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + + +#define QMF_CHANNELS 64 +#define QMF_FILTER_LENGTH 640 +#define QMF_MAX_TIME_SLOTS 32 +#define NO_OF_ESTIMATES_LC 4 +#define NO_OF_ESTIMATES_LD 3 +#define MAX_NO_OF_ESTIMATES 4 + + +#define NOISE_FLOOR_OFFSET 6 +#define NOISE_FLOOR_OFFSET_64 (FL2FXCONST_DBL(0.09375f)) + +#define LOW_RES 0 +#define HIGH_RES 1 + +#define LO 0 +#define HI 1 + +#define LENGTH_SBR_FRAME_INFO 35 /* 19 */ + +#define SBR_NSFB_LOW_RES 9 /* 8 */ +#define SBR_NSFB_HIGH_RES 18 /* 16 */ + + +#define SBR_XPOS_CTRL_DEFAULT 2 + +#define SBR_FREQ_SCALE_DEFAULT 2 +#define SBR_ALTER_SCALE_DEFAULT 1 +#define SBR_NOISE_BANDS_DEFAULT 2 + +#define SBR_LIMITER_BANDS_DEFAULT 2 +#define SBR_LIMITER_GAINS_DEFAULT 2 +#define SBR_LIMITER_GAINS_INFINITE 3 +#define SBR_INTERPOL_FREQ_DEFAULT 1 +#define SBR_SMOOTHING_LENGTH_DEFAULT 0 + + +/* sbr_header */ +#define SI_SBR_AMP_RES_BITS 1 +#define SI_SBR_COUPLING_BITS 1 +#define SI_SBR_START_FREQ_BITS 4 +#define SI_SBR_STOP_FREQ_BITS 4 +#define SI_SBR_XOVER_BAND_BITS 3 +#define SI_SBR_RESERVED_BITS 2 +#define SI_SBR_DATA_EXTRA_BITS 1 +#define SI_SBR_HEADER_EXTRA_1_BITS 1 +#define SI_SBR_HEADER_EXTRA_2_BITS 1 + +/* sbr_header extra 1 */ +#define SI_SBR_FREQ_SCALE_BITS 2 +#define SI_SBR_ALTER_SCALE_BITS 1 +#define SI_SBR_NOISE_BANDS_BITS 2 + +/* sbr_header extra 2 */ +#define SI_SBR_LIMITER_BANDS_BITS 2 +#define SI_SBR_LIMITER_GAINS_BITS 2 +#define SI_SBR_INTERPOL_FREQ_BITS 1 +#define SI_SBR_SMOOTHING_LENGTH_BITS 1 + +/* sbr_grid */ +#define SBR_CLA_BITS 2 /*!< size of bs_frame_class */ +#define SBR_CLA_BITS_LD 1 /*!< size of bs_frame_class */ +#define SBR_ENV_BITS 2 /*!< size of bs_num_env_raw */ +#define SBR_ABS_BITS 2 /*!< size of bs_abs_bord_raw for HE-AAC */ +#define SBR_NUM_BITS 2 /*!< size of bs_num_rel */ +#define SBR_REL_BITS 2 /*!< size of bs_rel_bord_raw */ +#define SBR_RES_BITS 1 /*!< size of bs_freq_res_flag */ +#define SBR_DIR_BITS 1 /*!< size of bs_df_flag */ + + +/* sbr_data */ +#define SI_SBR_INVF_MODE_BITS 2 + + +#define SI_SBR_START_ENV_BITS_AMP_RES_3_0 6 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0 5 + +#define SI_SBR_START_ENV_BITS_AMP_RES_1_5 7 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5 6 + + +#define SI_SBR_EXTENDED_DATA_BITS 1 +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 + +#define SBR_EXTENDED_DATA_MAX_CNT (15+255) + +#define EXTENSION_ID_PS_CODING 2 + +/* Envelope coding constants */ +#define FREQ 0 +#define TIME 1 + +/* qmf data scaling */ +#define QMF_SCALE_OFFSET 7 + +/* huffman tables */ +#define CODE_BOOK_SCF_LAV00 60 +#define CODE_BOOK_SCF_LAV01 31 +#define CODE_BOOK_SCF_LAV10 60 +#define CODE_BOOK_SCF_LAV11 31 +#define CODE_BOOK_SCF_LAV_BALANCE11 12 +#define CODE_BOOK_SCF_LAV_BALANCE10 24 + +typedef enum +{ + SBR_AMP_RES_1_5=0, + SBR_AMP_RES_3_0 +} +AMP_RES; + +typedef enum +{ + XPOS_MDCT, + XPOS_MDCT_CROSS, + XPOS_LC, + XPOS_RESERVED, + XPOS_SWITCHED /* not a real choice but used here to control behaviour */ +} +XPOS_MODE; + +typedef enum +{ + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} +INVF_MODE; + +#endif diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp new file mode 100644 index 00000000..c7c57972 --- /dev/null +++ b/libSBRenc/src/sbr_encoder.cpp @@ -0,0 +1,2443 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools *********************** + + Author(s): Andreas Ehret, Tobias Chalupka + Description: SBR encoder top level processing. + +******************************************************************************/ + +#include "sbr_encoder.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "sbrenc_freq_sca.h" +#include "env_bit.h" +#include "cmondata.h" +#include "sbr_misc.h" +#include "sbr.h" +#include "qmf.h" + +#include "ps_main.h" + +#define SBRENCODER_LIB_VL0 3 +#define SBRENCODER_LIB_VL1 3 +#define SBRENCODER_LIB_VL2 12 + + + +/***************************************************************************/ +/* + * SBR Delay balancing definitions. + */ + +/* + input buffer (1ch) + + |------------ 1537 -------------|-----|---------- 2048 -------------| + (core2sbr delay ) ds (read, core and ds area) +*/ + +#define SFB(dwnsmp) (32 << (dwnsmp-1)) /* SBR Frequency bands: 64 for dual-rate, 32 for single-rate */ +#define STS(fl) (((fl)==1024)?32:30) /* SBR Time Slots: 32 for core frame length 1024, 30 for core frame length 960 */ + +#define DELAY_QMF_ANA(dwnsmp) ((320<<((dwnsmp)-1)) - (32<<((dwnsmp)-1))) /* Full bandwidth */ +#define DELAY_HYB_ANA (10*64) /* + 0.5 */ /* */ +#define DELAY_HYB_SYN (6*64 - 32) /* */ +#define DELAY_QMF_POSTPROC(dwnsmp) (32*(dwnsmp)) /* QMF postprocessing delay */ +#define DELAY_DEC_QMF(dwnsmp) (6 * SFB(dwnsmp) ) /* Decoder QMF overlap */ +#define DELAY_QMF_SYN (2) /* NO_POLY/2=2.5, rounded down to 2 */ +#define DELAY_QMF_DS (32) /* QMF synthesis for downsampled time signal */ + +/* Delay in QMF paths */ +#define DELAY_SBR(fl,dwnsmp) (DELAY_QMF_ANA(dwnsmp) + (SFB(dwnsmp)*STS(fl) - 1) + DELAY_QMF_SYN) +#define DELAY_PS(fl,dwnsmp) (DELAY_QMF_ANA(dwnsmp) + DELAY_HYB_ANA + DELAY_DEC_QMF(dwnsmp) + (SFB(dwnsmp)*STS(fl)-1) + DELAY_HYB_SYN + DELAY_QMF_SYN) +#define DELAY_ELDSBR(fl,dwnsmp) ( ( ((fl)/2)*(dwnsmp) ) - 1 + DELAY_QMF_POSTPROC(dwnsmp) ) + +/* Delay differences for SBR and SBR+PS */ +#define MAX_DS_FILTER_DELAY (5) /* the additional max downsampler filter delay (source fs) */ +#define DELAY_AAC2SBR(fl,dwnsmp) ((DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + DELAY_QMF_SYN) - DELAY_SBR((fl),(dwnsmp))) +#define DELAY_ELD2SBR(fl,dwnsmp) ((DELAY_QMF_POSTPROC(dwnsmp)) - DELAY_ELDSBR(fl,dwnsmp)) +#define DELAY_AAC2PS(fl,dwnsmp) ((DELAY_QMF_ANA(dwnsmp) + DELAY_QMF_DS + /*(DELAY_AAC(fl)*2) + */ DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + DELAY_HYB_SYN + DELAY_QMF_SYN) - DELAY_PS(fl,dwnsmp)) /* 2048 - 463*2 */ + +/* Assumption: The sample delay resulting of of DELAY_AAC2PS is always smaller than the sample delay implied by DELAY_AAC2SBR */ +#define MAX_SAMPLE_DELAY (DELAY_AAC2SBR(1024,2) + MAX_DS_FILTER_DELAY) /* maximum delay: frame length of 1024 and dual-rate sbr */ + +/***************************************************************************/ + + + +#define INVALID_TABLE_IDX -1 + +/***************************************************************************/ +/*! + + \brief Selects the SBR tuning settings to use dependent on number of + channels, bitrate, sample rate and core coder + + \return Index to the appropriate table + +****************************************************************************/ +#define DISTANCE_CEIL_VALUE 5000000 +static INT +getSbrTuningTableIndex(UINT bitrate, /*! the total bitrate in bits/sec */ + UINT numChannels,/*! the number of channels for the core coder */ + UINT sampleRate, /*! the sampling rate of the core coder */ + AUDIO_OBJECT_TYPE core, + UINT *pBitRateClosest + ) +{ + int i, bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1, found = 0; + UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE; + + #define isForThisCore(i) \ + ( ( sbrTuningTable[i].coreCoder == CODEC_AACLD && core == AOT_ER_AAC_ELD ) || \ + ( sbrTuningTable[i].coreCoder == CODEC_AAC && core != AOT_ER_AAC_ELD ) ) + + for (i=0; i < sbrTuningTableSize ; i++) { + if ( isForThisCore(i) ) /* tuning table is for this core codec */ + { + if ( numChannels == sbrTuningTable [i].numChannels + && sampleRate == sbrTuningTable [i].sampleRate ) + { + found = 1; + if ((bitrate >= sbrTuningTable [i].bitrateFrom) && + (bitrate < sbrTuningTable [i].bitrateTo)) { + bitRateClosestLower = bitrate; + bitRateClosestUpper = bitrate; + //FDKprintf("entry %d\n", i); + return i ; + } else { + if ( sbrTuningTable [i].bitrateFrom > bitrate ) { + if (sbrTuningTable [i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = sbrTuningTable [i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if ( sbrTuningTable [i].bitrateTo <= bitrate ) { + if (sbrTuningTable [i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = sbrTuningTable [i].bitrateTo-1; + bitRateClosestUpperIndex = i; + } + } + } + } + } + } + + if (pBitRateClosest != NULL) + { + /* If there was at least one matching tuning entry found then pick the least distance bit rate */ + if (found) + { + int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo; + } + if ( distanceUpper < distanceLower ) + { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } else { + *pBitRateClosest = 0; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief Selects the PS tuning settings to use dependent on bitrate + and core coder + + \return Index to the appropriate table + +****************************************************************************/ +static INT +getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest){ + + INT i, paramSets = sizeof (psTuningTable) / sizeof (psTuningTable [0]); + int bitRateClosestLowerIndex=-1, bitRateClosestUpperIndex=-1; + UINT bitRateClosestUpper = 0, bitRateClosestLower=DISTANCE_CEIL_VALUE; + + for (i = 0 ; i < paramSets ; i++) { + if ((bitrate >= psTuningTable [i].bitrateFrom) && + (bitrate < psTuningTable [i].bitrateTo)) { + return i ; + } else { + if ( psTuningTable [i].bitrateFrom > bitrate ) { + if (psTuningTable [i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = psTuningTable [i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if ( psTuningTable [i].bitrateTo <= bitrate ) { + if (psTuningTable [i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = psTuningTable [i].bitrateTo-1; + bitRateClosestUpperIndex = i; + } + } + } + } + + if (pBitRateClosest != NULL) + { + int distanceUpper=DISTANCE_CEIL_VALUE, distanceLower=DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = sbrTuningTable [bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = bitrate - sbrTuningTable [bitRateClosestUpperIndex].bitrateTo; + } + if ( distanceUpper < distanceLower ) + { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief In case of downsampled SBR we may need to lower the stop freq + of a tuning setting to fit into the lower half of the + spectrum ( which is sampleRate/4 ) + + \return the adapted stop frequency index (-1 -> error) + + \ingroup SbrEncCfg + +****************************************************************************/ +static INT +FDKsbrEnc_GetDownsampledStopFreq ( + const INT sampleRateCore, + const INT startFreq, + INT stopFreq, + const INT downSampleFactor + ) +{ + INT maxStopFreqRaw = sampleRateCore / 2; + INT startBand, stopBand; + HANDLE_ERROR_INFO err; + + while (stopFreq > 0 && FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > maxStopFreqRaw) { + stopFreq--; + } + + if (FDKsbrEnc_getSbrStopFreqRAW( stopFreq, sampleRateCore) > maxStopFreqRaw) + return -1; + + err = FDKsbrEnc_FindStartAndStopBand ( + sampleRateCore<<(downSampleFactor-1), + sampleRateCore, + 32<<(downSampleFactor-1), + startFreq, + stopFreq, + &startBand, + &stopBand + ); + if (err) + return -1; + + return stopFreq; +} + + +/***************************************************************************/ +/*! + + \brief tells us, if for the given coreCoder, bitrate, number of channels + and input sampling rate an SBR setting is available. If yes, it + tells us also the core sampling rate we would need to run with + + \return a flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT +FDKsbrEnc_IsSbrSettingAvail ( + UINT bitrate, /*! the total bitrate in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 means constant bitrate */ + UINT numOutputChannels, /*! the number of channels for the core coder */ + UINT sampleRateInput, /*! the input sample rate [in Hz] */ + UINT sampleRateCore, /*! the core's sampling rate */ + AUDIO_OBJECT_TYPE core + ) +{ + INT idx = INVALID_TABLE_IDX; + + if (sampleRateInput < 16000) + return 0; + + if (bitrate==0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitrate = 24000; + else if (vbrMode < 40) + bitrate = 28000; + else if (vbrMode < 60) + bitrate = 32000; + else if (vbrMode < 75) + bitrate = 40000; + else + bitrate = 48000; + bitrate *= numOutputChannels; + } + + idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core, NULL); + + return (idx == INVALID_TABLE_IDX ? 0 : 1); +} + + +/***************************************************************************/ +/*! + + \brief Adjusts the SBR settings according to the chosen core coder + settings which are accessible via config->codecSettings + + \return A flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT +FDKsbrEnc_AdjustSbrSettings (const sbrConfigurationPtr config, /*! output, modified */ + UINT bitRate, /*! the total bitrate in bits/sec */ + UINT numChannels, /*! the core coder number of channels */ + UINT sampleRateCore, /*! the core coder sampling rate in Hz */ + UINT sampleRateSbr, /*! the sbr coder sampling rate in Hz */ + UINT transFac, /*! the short block to long block ratio */ + UINT standardBitrate, /*! the standard bitrate per channel in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 poor quality .. 100 high quality*/ + UINT useSpeechConfig, /*!< adapt tuning parameters for speech ? */ + UINT lcsMode, /*! the low complexity stereo mode */ + UINT bParametricStereo, /*!< use parametric stereo */ + AUDIO_OBJECT_TYPE core) /* Core audio codec object type */ +{ + INT idx = INVALID_TABLE_IDX; + /* set the core codec settings */ + config->codecSettings.bitRate = bitRate; + config->codecSettings.nChannels = numChannels; + config->codecSettings.sampleFreq = sampleRateCore; + config->codecSettings.transFac = transFac; + config->codecSettings.standardBitrate = standardBitrate; + + if (bitRate < 28000) { + config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL; + config->threshold_AmpRes_FF_e = 7; + } + else if (bitRate >= 28000 && bitRate <= 48000) { + /* The float threshold is 75 + 0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore tonality are scaled by this + 2/3 is because the original implementation divides the tonality values by 3, here it's divided by 2 + 128 compensates the necessary shiftfactor of 7 */ + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(75.0f*0.524288f/(2.0f/3.0f)/128.0f); + config->threshold_AmpRes_FF_e = 7; + } + else if (bitRate > 48000) { + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0); + config->threshold_AmpRes_FF_e = 0; + } + + if (bitRate==0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitRate = 24000; + else if (vbrMode < 40) + bitRate = 28000; + else if (vbrMode < 60) + bitRate = 32000; + else if (vbrMode < 75) + bitRate = 40000; + else + bitRate = 48000; + bitRate *= numChannels; + /* fix to enable mono vbrMode<40 @ 44.1 of 48kHz */ + if (numChannels==1) { + if (sampleRateSbr==44100 || sampleRateSbr==48000) { + if (vbrMode<40) bitRate = 32000; + } + } + } + + idx = getSbrTuningTableIndex(bitRate,numChannels,sampleRateCore, core, NULL); + + if (idx != INVALID_TABLE_IDX) { + config->startFreq = sbrTuningTable[idx].startFreq ; + config->stopFreq = sbrTuningTable[idx].stopFreq ; + if (useSpeechConfig) { + config->startFreq = sbrTuningTable[idx].startFreqSpeech; + config->stopFreq = sbrTuningTable[idx].stopFreqSpeech; + } + + /* Adapt stop frequency in case of downsampled SBR - only 32 bands then */ + if (1 == config->downSampleFactor) { + INT dsStopFreq = FDKsbrEnc_GetDownsampledStopFreq( + sampleRateCore, + config->startFreq, + config->stopFreq, + config->downSampleFactor + ); + if (dsStopFreq < 0) { + return 0; + } + + config->stopFreq = dsStopFreq; + } + + config->sbr_noise_bands = sbrTuningTable[idx].numNoiseBands ; + if (core == AOT_ER_AAC_ELD) + config->init_amp_res_FF = SBR_AMP_RES_1_5; + config->noiseFloorOffset= sbrTuningTable[idx].noiseFloorOffset; + + config->ana_max_level = sbrTuningTable[idx].noiseMaxLevel ; + config->stereoMode = sbrTuningTable[idx].stereoMode ; + config->freqScale = sbrTuningTable[idx].freqScale ; + + if (numChannels == 1) { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= (useSpeechConfig?24000U:20000U)) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 36000) + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + if (bitRate < 26000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + } + else { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= 28000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 72000) { + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency resolution for split frames */ + } + if (bitRate < 52000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency resolution for non-split frames */ + config->fResTransIsLow = 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + if (bitRate <= 28000) { + /* + additionally restrict frequency resolution in FIXFIX frames + to further reduce SBR payload size */ + config->freq_res_fixfix[0] = FREQ_RES_LOW; + config->freq_res_fixfix[1] = FREQ_RES_LOW; + } + } + + /* adjust usage of parametric coding dependent on bitrate and speech config flag */ + if (useSpeechConfig) + config->parametricCoding = 0; + + if (core == AOT_ER_AAC_ELD) { + if (bitRate < 28000) + config->init_amp_res_FF = SBR_AMP_RES_3_0; + config->SendHeaderDataTime = -1; + } + + if (numChannels == 1) { + if (bitRate < 16000) { + config->parametricCoding = 0; + } + } + else { + if (bitRate < 20000) { + config->parametricCoding = 0; + } + } + + config->useSpeechConfig = useSpeechConfig; + + /* PS settings */ + config->bParametricStereo = bParametricStereo; + + return 1 ; + } + else { + return 0 ; + } +} + +/***************************************************************************** + + functionname: FDKsbrEnc_InitializeSbrDefaults + description: initializes the SBR confifuration + returns: error status + input: - core codec type, + - factor of SBR to core frame length, + - core frame length + output: initialized SBR configuration + +*****************************************************************************/ +static UINT +FDKsbrEnc_InitializeSbrDefaults (sbrConfigurationPtr config, + INT downSampleFactor, + UINT codecGranuleLen + ,const INT isLowDelay + ) +{ + if ( (downSampleFactor < 1 || downSampleFactor > 2) || + (codecGranuleLen*downSampleFactor > QMF_CHANNELS*QMF_MAX_TIME_SLOTS) ) + return(0); /* error */ + + config->SendHeaderDataTime = 1000; + config->useWaveCoding = 0; + config->crcSbr = 0; + config->dynBwSupported = 1; + if (isLowDelay) + config->tran_thr = 6000; + else + config->tran_thr = 13000; + + config->parametricCoding = 1; + + config->sbrFrameSize = codecGranuleLen * downSampleFactor; + config->downSampleFactor = downSampleFactor; + + /* sbr default parameters */ + config->sbr_data_extra = 0; + config->amp_res = SBR_AMP_RES_3_0 ; + config->tran_fc = 0 ; + config->tran_det_mode = 1 ; + config->spread = 1 ; + config->stat = 0 ; + config->e = 1 ; + config->deltaTAcrossFrames = 1 ; + config->dF_edge_1stEnv = FL2FXCONST_DBL(0.3f) ; + config->dF_edge_incr = FL2FXCONST_DBL(0.3f) ; + + config->sbr_invf_mode = INVF_SWITCHED; + config->sbr_xpos_mode = XPOS_LC; + config->sbr_xpos_ctrl = SBR_XPOS_CTRL_DEFAULT; + config->sbr_xpos_level = 0; + config->useSaPan = 0; + config->dynBwEnabled = 0; + + + /* the following parameters are overwritten by the FDKsbrEnc_AdjustSbrSettings() function since + they are included in the tuning table */ + config->stereoMode = SBR_SWITCH_LRC; + config->ana_max_level = 6; + config->noiseFloorOffset = 0; + config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */ + config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */ + config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */ + config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */ + config->fResTransIsLow = 0; /* for transient frames, set variable frequency resolution according to freqResTable */ + + /* header_extra_1 */ + config->freqScale = SBR_FREQ_SCALE_DEFAULT; + config->alterScale = SBR_ALTER_SCALE_DEFAULT; + config->sbr_noise_bands = SBR_NOISE_BANDS_DEFAULT; + + /* header_extra_2 */ + config->sbr_limiter_bands = SBR_LIMITER_BANDS_DEFAULT; + config->sbr_limiter_gains = SBR_LIMITER_GAINS_DEFAULT; + config->sbr_interpol_freq = SBR_INTERPOL_FREQ_DEFAULT; + config->sbr_smoothing_length = SBR_SMOOTHING_LENGTH_DEFAULT; + + return 1; +} + + +/***************************************************************************** + + functionname: DeleteEnvChannel + description: frees memory of one SBR channel + returns: - + input: handle of channel + output: released handle + +*****************************************************************************/ +static void +deleteEnvChannel (HANDLE_ENV_CHANNEL hEnvCut) +{ + if (hEnvCut) { + + FDKsbrEnc_DeleteTonCorrParamExtr(&hEnvCut->TonCorr); + + FDKsbrEnc_deleteExtractSbrEnvelope (&hEnvCut->sbrExtractEnvelope); + } + +} + + +/***************************************************************************** + + functionname: sbrEncoder_ChannelClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void +sbrEncoder_ChannelClose(HANDLE_SBR_CHANNEL hSbrChannel) +{ + if (hSbrChannel != NULL) + { + deleteEnvChannel (&hSbrChannel->hEnvChannel); + } +} + +/***************************************************************************** + + functionname: sbrEncoder_ElementClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void +sbrEncoder_ElementClose(HANDLE_SBR_ELEMENT *phSbrElement) +{ + HANDLE_SBR_ELEMENT hSbrElement = *phSbrElement; + + if (hSbrElement!=NULL) { + if (hSbrElement->sbrConfigData.v_k_master) + FreeRam_Sbr_v_k_master(&hSbrElement->sbrConfigData.v_k_master); + if (hSbrElement->sbrConfigData.freqBandTable[LO]) + FreeRam_Sbr_freqBandTableLO(&hSbrElement->sbrConfigData.freqBandTable[LO]); + if (hSbrElement->sbrConfigData.freqBandTable[HI]) + FreeRam_Sbr_freqBandTableHI(&hSbrElement->sbrConfigData.freqBandTable[HI]); + + FreeRam_SbrElement(phSbrElement); + } + return ; + +} + + +void sbrEncoder_Close (HANDLE_SBR_ENCODER *phSbrEncoder) +{ + HANDLE_SBR_ENCODER hSbrEncoder = *phSbrEncoder; + + if (hSbrEncoder != NULL) + { + int el, ch; + + for (el=0; el<(8); el++) + { + if (hSbrEncoder->sbrElement[el]!=NULL) { + sbrEncoder_ElementClose(&hSbrEncoder->sbrElement[el]); + } + } + + /* Close sbr Channels */ + for (ch=0; ch<(8); ch++) + { + if (hSbrEncoder->pSbrChannel[ch]) { + sbrEncoder_ChannelClose(hSbrEncoder->pSbrChannel[ch]); + FreeRam_SbrChannel(&hSbrEncoder->pSbrChannel[ch]); + } + + if (hSbrEncoder->QmfAnalysis[ch].FilterStates) + FreeRam_Sbr_QmfStatesAnalysis((FIXP_QAS**)&hSbrEncoder->QmfAnalysis[ch].FilterStates); + + + } + + if (hSbrEncoder->hParametricStereo) + PSEnc_Destroy(&hSbrEncoder->hParametricStereo); + if (hSbrEncoder->qmfSynthesisPS.FilterStates) + FreeRam_PsQmfStatesSynthesis((FIXP_DBL**)&hSbrEncoder->qmfSynthesisPS.FilterStates); + + /* Release Overlay */ + FreeRam_SbrDynamic_RAM((FIXP_DBL**)&hSbrEncoder->pSBRdynamic_RAM); + + + FreeRam_SbrEncoder(phSbrEncoder); + } + +} + +/***************************************************************************** + + functionname: updateFreqBandTable + description: updates vk_master + returns: - + input: config handle + output: error info + +*****************************************************************************/ +static INT updateFreqBandTable( + HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + const INT downSampleFactor + ) +{ + INT k0, k2; + + if( FDKsbrEnc_FindStartAndStopBand ( + sbrConfigData->sampleFreq, + sbrConfigData->sampleFreq >> (downSampleFactor-1), + sbrConfigData->noQmfBands, + sbrHeaderData->sbr_start_frequency, + sbrHeaderData->sbr_stop_frequency, + &k0, + &k2 + ) + ) + return(1); + + + if( FDKsbrEnc_UpdateFreqScale( + sbrConfigData->v_k_master, + &sbrConfigData->num_Master, + k0, + k2, + sbrHeaderData->freqScale, + sbrHeaderData->alterScale + ) + ) + return(1); + + + sbrHeaderData->sbr_xover_band=0; + + + if( FDKsbrEnc_UpdateHiRes( + sbrConfigData->freqBandTable[HI], + &sbrConfigData->nSfb[HI], + sbrConfigData->v_k_master, + sbrConfigData->num_Master, + &sbrHeaderData->sbr_xover_band + ) + ) + return(1); + + + FDKsbrEnc_UpdateLoRes( + sbrConfigData->freqBandTable[LO], + &sbrConfigData->nSfb[LO], + sbrConfigData->freqBandTable[HI], + sbrConfigData->nSfb[HI] + ); + + + sbrConfigData->xOverFreq = (sbrConfigData->freqBandTable[LOW_RES][0] * sbrConfigData->sampleFreq / sbrConfigData->noQmfBands+1)>>1; + + return (0); +} + + +/***************************************************************************** + + functionname: resetEnvChannel + description: resets parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static INT resetEnvChannel (HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv) +{ + /* note !!! hEnv->encEnvData.noOfnoisebands will be updated later in function FDKsbrEnc_extractSbrEnvelope !!!*/ + hEnv->TonCorr.sbrNoiseFloorEstimate.noiseBands = sbrHeaderData->sbr_noise_bands; + + + if(FDKsbrEnc_ResetTonCorrParamExtr(&hEnv->TonCorr, + sbrConfigData->xposCtrlSwitch, + sbrConfigData->freqBandTable[HI][0], + sbrConfigData->v_k_master, + sbrConfigData->num_Master, + sbrConfigData->sampleFreq, + sbrConfigData->freqBandTable, + sbrConfigData->nSfb, + sbrConfigData->noQmfBands)) + return(1); + + hEnv->sbrCodeNoiseFloor.nSfb[LO] = hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + hEnv->sbrCodeNoiseFloor.nSfb[HI] = hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + hEnv->sbrCodeEnvelope.nSfb[LO] = sbrConfigData->nSfb[LO]; + hEnv->sbrCodeEnvelope.nSfb[HI] = sbrConfigData->nSfb[HI]; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + + hEnv->sbrCodeEnvelope.upDate = 0; + hEnv->sbrCodeNoiseFloor.upDate = 0; + + return (0); +} + +/* ****************************** FDKsbrEnc_SbrGetXOverFreq ******************************/ +/** + * @fn + * @brief calculates the closest possible crossover frequency + * @return the crossover frequency SBR accepts + * + */ +static INT +FDKsbrEnc_SbrGetXOverFreq(HANDLE_SBR_ELEMENT hEnv, /*!< handle to SBR encoder instance */ + INT xoverFreq) /*!< from core coder suggested crossover frequency */ +{ + INT band; + INT lastDiff, newDiff; + INT cutoffSb; + + UCHAR *RESTRICT pVKMaster = hEnv->sbrConfigData.v_k_master; + + /* Check if there is a matching cutoff frequency in the master table */ + cutoffSb = (4*xoverFreq * hEnv->sbrConfigData.noQmfBands / hEnv->sbrConfigData.sampleFreq + 1)>>1; + lastDiff = cutoffSb; + for (band = 0; band < hEnv->sbrConfigData.num_Master; band++) { + + newDiff = fixp_abs((INT)pVKMaster[band] - cutoffSb); + + if(newDiff >= lastDiff) { + band--; + break; + } + + lastDiff = newDiff; + } + + return ((pVKMaster[band] * hEnv->sbrConfigData.sampleFreq/hEnv->sbrConfigData.noQmfBands+1)>>1); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvEncodeFrame + description: performs the sbr envelope calculation for one element + returns: + input: + output: + +*****************************************************************************/ +INT +FDKsbrEnc_EnvEncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, + int iElement, + INT_PCM *samples, /*!< time samples, always interleaved */ + UINT timeInStride, /*!< time buffer channel interleaving stride */ + UINT *sbrDataBits, /*!< Size of SBR payload */ + UCHAR *sbrData, /*!< SBR payload */ + int clearOutput /*!< Do not consider any input signal */ + ) +{ + HANDLE_SBR_ELEMENT hSbrElement = NULL; + FDK_CRCINFO crcInfo; + INT crcReg; + INT ch; + INT band; + INT cutoffSb; + INT newXOver; + + if (hEnvEncoder == NULL) + return -1; + + hSbrElement = hEnvEncoder->sbrElement[iElement]; + + if (hSbrElement == NULL) + return -1; + + + /* header bitstream handling */ + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData = &hSbrElement->sbrBitstreamData; + + INT psHeaderActive = 0; + sbrBitstreamData->HeaderActive = 0; + + /* Anticipate PS header because of internal PS bitstream delay in order to be in sync with SBR header. */ + if ( sbrBitstreamData->CountSendHeaderData==(sbrBitstreamData->NrSendHeaderData-1) ) + { + psHeaderActive = 1; + } + + /* Signal SBR header to be written into bitstream */ + if ( sbrBitstreamData->CountSendHeaderData==0 ) + { + sbrBitstreamData->HeaderActive = 1; + } + + /* Increment header interval counter */ + if (sbrBitstreamData->NrSendHeaderData == 0) { + sbrBitstreamData->CountSendHeaderData = 1; + } + else { + if (sbrBitstreamData->CountSendHeaderData >= 0) { + sbrBitstreamData->CountSendHeaderData++; + sbrBitstreamData->CountSendHeaderData %= sbrBitstreamData->NrSendHeaderData; + } + } + + if (hSbrElement->CmonData.dynBwEnabled ) { + INT i; + for ( i = 4; i > 0; i-- ) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->dynXOverFreqDelay[i-1]; + + hSbrElement->dynXOverFreqDelay[0] = hSbrElement->CmonData.dynXOverFreqEnc; + if (hSbrElement->dynXOverFreqDelay[1] > hSbrElement->dynXOverFreqDelay[2]) + newXOver = hSbrElement->dynXOverFreqDelay[2]; + else + newXOver = hSbrElement->dynXOverFreqDelay[1]; + + /* has the crossover frequency changed? */ + if ( hSbrElement->sbrConfigData.dynXOverFreq != newXOver ) { + + /* get corresponding master band */ + cutoffSb = ((4* newXOver * hSbrElement->sbrConfigData.noQmfBands + / hSbrElement->sbrConfigData.sampleFreq)+1)>>1; + + for ( band = 0; band < hSbrElement->sbrConfigData.num_Master; band++ ) { + if ( cutoffSb == hSbrElement->sbrConfigData.v_k_master[band] ) + break; + } + FDK_ASSERT( band < hSbrElement->sbrConfigData.num_Master ); + + hSbrElement->sbrConfigData.dynXOverFreq = newXOver; + hSbrElement->sbrHeaderData.sbr_xover_band = band; + hSbrElement->sbrBitstreamData.HeaderActive=1; + psHeaderActive = 1; /* ps header is one frame delayed */ + + /* + update vk_master table + */ + if(updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + hEnvEncoder->downSampleFactor + )) + return(1); + + + /* reset SBR channels */ + INT nEnvCh = hSbrElement->sbrConfigData.nChannels; + for ( ch = 0; ch < nEnvCh; ch++ ) { + if(resetEnvChannel (&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel)) + return(1); + + } + } + } + + /* + allocate space for dummy header and crc + */ + crcReg = FDKsbrEnc_InitSbrBitstream(&hSbrElement->CmonData, + hSbrElement->payloadDelayLine[hEnvEncoder->nBitstrDelay], + MAX_PAYLOAD_SIZE*sizeof(UCHAR), + &crcInfo, + hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* Temporal Envelope Data */ + SBR_FRAME_TEMP_DATA _fData; + SBR_FRAME_TEMP_DATA *fData = &_fData; + SBR_ENV_TEMP_DATA eData[MAX_NUM_CHANNELS]; + + /* Init Temporal Envelope Data */ + { + int i; + + FDKmemclear(&eData[0], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(&eData[1], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(fData, sizeof(SBR_FRAME_TEMP_DATA)); + + for(i=0; ires[i] = FREQ_RES_HIGH; + } + + + if (!clearOutput) + { + /* + * Transform audio data into QMF domain + */ + for(ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) + { + HANDLE_ENV_CHANNEL h_envChan = &hSbrElement->sbrChannel[ch]->hEnvChannel; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &h_envChan->sbrExtractEnvelope; + + if(hSbrElement->elInfo.fParametricStereo == 0) + { + QMF_SCALE_FACTOR tmpScale; + FIXP_DBL **pQmfReal, **pQmfImag; + C_AALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2) + + + /* Obtain pointers to QMF buffers. */ + pQmfReal = sbrExtrEnv->rBuffer; + pQmfImag = sbrExtrEnv->iBuffer; + + qmfAnalysisFiltering( hSbrElement->hQmfAnalysis[ch], + pQmfReal, + pQmfImag, + &tmpScale, + samples + hSbrElement->elInfo.ChannelIndex[ch], + timeInStride, + qmfWorkBuffer ); + + h_envChan->qmfScale = tmpScale.lb_scale + 7; + + + C_AALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, QMF_CHANNELS*2) + + } /* fParametricStereo == 0 */ + + + /* + Parametric Stereo processing + */ + if (hSbrElement->elInfo.fParametricStereo) + { + INT error = noError; + + + /* Limit Parametric Stereo to one instance */ + FDK_ASSERT(ch == 0); + + + if(error == noError){ + /* parametric stereo processing: + - input: + o left and right time domain samples + - processing: + o stereo qmf analysis + o stereo hybrid analysis + o ps parameter extraction + o downmix + hybrid synthesis + - output: + o downmixed qmf data is written to sbrExtrEnv->rBuffer and sbrExtrEnv->iBuffer + */ + SCHAR qmfScale; + INT_PCM* pSamples[2] = {samples + hSbrElement->elInfo.ChannelIndex[0],samples + hSbrElement->elInfo.ChannelIndex[1]}; + error = FDKsbrEnc_PSEnc_ParametricStereoProcessing( hEnvEncoder->hParametricStereo, + pSamples, + timeInStride, + hSbrElement->hQmfAnalysis, + sbrExtrEnv->rBuffer, + sbrExtrEnv->iBuffer, + samples + hSbrElement->elInfo.ChannelIndex[ch], + &hEnvEncoder->qmfSynthesisPS, + &qmfScale, + psHeaderActive ); + if (noError != error) + { + error = handBack(error); + } + h_envChan->qmfScale = (int)qmfScale; + } + + + } /* if (hEnvEncoder->hParametricStereo) */ + + /* + + Extract Envelope relevant things from QMF data + + */ + FDKsbrEnc_extractSbrEnvelope1( + &hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrBitstreamData, + h_envChan, + &hSbrElement->CmonData, + &eData[ch], + fData + ); + + } /* hEnvEncoder->sbrConfigData.nChannels */ + } + + /* + Process Envelope relevant things and calculate envelope data and write payload + */ + FDKsbrEnc_extractSbrEnvelope2( + &hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + (hSbrElement->elInfo.fParametricStereo) ? hEnvEncoder->hParametricStereo : NULL, + &hSbrElement->sbrBitstreamData, + &hSbrElement->sbrChannel[0]->hEnvChannel, + &hSbrElement->sbrChannel[1]->hEnvChannel, + &hSbrElement->CmonData, + eData, + fData, + clearOutput + ); + + /* + format payload, calculate crc + */ + FDKsbrEnc_AssembleSbrBitstream(&hSbrElement->CmonData, &crcInfo, crcReg, hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* + save new payload, set to zero length if greater than MAX_PAYLOAD_SIZE + */ + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = FDKgetValidBits(&hSbrElement->CmonData.sbrBitbuf); + + if(hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] > (MAX_PAYLOAD_SIZE<<3)) + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay]=0; + + /* While filling the Delay lines, sbrData is NULL */ + if (sbrData) { + *sbrDataBits = hSbrElement->payloadDelayLineSize[0]; + FDKmemcpy(sbrData, hSbrElement->payloadDelayLine[0], (hSbrElement->payloadDelayLineSize[0]+7)>>3); + + + } + + +/*******************************/ + + if (hEnvEncoder->fTimeDomainDownsampling) + { + int ch; + int nChannels = hSbrElement->sbrConfigData.nChannels; + + for (ch=0; ch < nChannels; ch++) + { + INT nOutSamples; + + FDKaacEnc_Downsample(&hSbrElement->sbrChannel[ch]->downSampler, + samples + hSbrElement->elInfo.ChannelIndex[ch] + hEnvEncoder->bufferOffset, + hSbrElement->sbrConfigData.frameSize, + timeInStride, + samples + hSbrElement->elInfo.ChannelIndex[ch], + &nOutSamples, + hEnvEncoder->nChannels); + } + } /* downsample */ + + + return (0); +} + +/***************************************************************************** + + functionname: createEnvChannel + description: initializes parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ + +static INT +createEnvChannel (HANDLE_ENV_CHANNEL hEnv, + INT channel + ,UCHAR* dynamic_RAM + ) +{ + FDKmemclear(hEnv,sizeof (struct ENV_CHANNEL)); + + if ( FDKsbrEnc_CreateTonCorrParamExtr(&hEnv->TonCorr, + channel) ) + { + return(1); + } + + if ( FDKsbrEnc_CreateExtractSbrEnvelope (&hEnv->sbrExtractEnvelope, + channel + ,/*chan*/0 + ,dynamic_RAM + ) ) + { + return(1); + } + + return 0; +} + +/***************************************************************************** + + functionname: initEnvChannel + description: initializes parameters + returns: error status + input: + output: + +*****************************************************************************/ +static INT +initEnvChannel ( HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv, + sbrConfigurationPtr params, + ULONG statesInitFlag + ,INT chanInEl + ,UCHAR* dynamic_RAM + ) +{ + int frameShift, tran_off=0; + INT e; + INT tran_fc; + INT timeSlots, timeStep, startIndex; + INT noiseBands[2] = { 3, 3 }; + + e = 1 << params->e; + + FDK_ASSERT(params->e >= 0); + + hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0]; + hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1]; + hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow; + + hEnv->fLevelProtect = 0; + + hEnv->encEnvData.ldGrid = (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0; + + hEnv->encEnvData.sbr_xpos_mode = (XPOS_MODE)params->sbr_xpos_mode; + + if (hEnv->encEnvData.sbr_xpos_mode == XPOS_SWITCHED) { + /* + no other type than XPOS_MDCT or XPOS_SPEECH allowed, + but enable switching + */ + sbrConfigData->switchTransposers = TRUE; + hEnv->encEnvData.sbr_xpos_mode = XPOS_MDCT; + } + else { + sbrConfigData->switchTransposers = FALSE; + } + + hEnv->encEnvData.sbr_xpos_ctrl = params->sbr_xpos_ctrl; + + + /* extended data */ + if(params->parametricCoding) { + hEnv->encEnvData.extended_data = 1; + } + else { + hEnv->encEnvData.extended_data = 0; + } + + hEnv->encEnvData.extension_size = 0; + + startIndex = QMF_FILTER_PROTOTYPE_SIZE - sbrConfigData->noQmfBands; + + switch (params->sbrFrameSize) { + case 2304: + timeSlots = 18; + break; + case 2048: + case 1024: + case 512: + timeSlots = 16; + break; + case 1920: + case 960: + case 480: + timeSlots = 15; + break; + case 1152: + timeSlots = 9; + break; + default: + return (1); /* Illegal frame size */ + } + + timeStep = sbrConfigData->noQmfSlots / timeSlots; + + if ( FDKsbrEnc_InitTonCorrParamExtr(params->sbrFrameSize, + &hEnv->TonCorr, + sbrConfigData, + timeSlots, + params->sbr_xpos_ctrl, + params->ana_max_level, + sbrHeaderData->sbr_noise_bands, + params->noiseFloorOffset, + params->useSpeechConfig) ) + return(1); + + hEnv->encEnvData.noOfnoisebands = hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + noiseBands[0] = hEnv->encEnvData.noOfnoisebands; + noiseBands[1] = hEnv->encEnvData.noOfnoisebands; + + hEnv->encEnvData.sbr_invf_mode = (INVF_MODE)params->sbr_invf_mode; + + if (hEnv->encEnvData.sbr_invf_mode == INVF_SWITCHED) { + hEnv->encEnvData.sbr_invf_mode = INVF_MID_LEVEL; + hEnv->TonCorr.switchInverseFilt = TRUE; + } + else { + hEnv->TonCorr.switchInverseFilt = FALSE; + } + + + tran_fc = params->tran_fc; + + if (tran_fc == 0) { + tran_fc = fixMin (5000, FDKsbrEnc_getSbrStartFreqRAW (sbrHeaderData->sbr_start_frequency,params->codecSettings.sampleFreq)); + } + + tran_fc = (tran_fc*4*sbrConfigData->noQmfBands/sbrConfigData->sampleFreq + 1)>>1; + + if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + frameShift = LD_PRETRAN_OFF; + tran_off = LD_PRETRAN_OFF + FRAME_MIDDLE_SLOT_512LD*timeStep; + } else + { + frameShift = 0; + switch (timeSlots) { + /* The factor of 2 is by definition. */ + case NUMBER_TIME_SLOTS_2048: tran_off = 8 + FRAME_MIDDLE_SLOT_2048 * timeStep; break; + case NUMBER_TIME_SLOTS_1920: tran_off = 7 + FRAME_MIDDLE_SLOT_1920 * timeStep; break; + default: return 1; + } + } + if ( FDKsbrEnc_InitExtractSbrEnvelope (&hEnv->sbrExtractEnvelope, + sbrConfigData->noQmfSlots, + sbrConfigData->noQmfBands, startIndex, + timeSlots, timeStep, tran_off, + statesInitFlag + ,chanInEl + ,dynamic_RAM + ,sbrConfigData->sbrSyntaxFlags + ) ) + return(1); + + if(FDKsbrEnc_InitSbrCodeEnvelope (&hEnv->sbrCodeEnvelope, + sbrConfigData->nSfb, + params->deltaTAcrossFrames, + params->dF_edge_1stEnv, + params->dF_edge_incr)) + return(1); + + if(FDKsbrEnc_InitSbrCodeEnvelope (&hEnv->sbrCodeNoiseFloor, + noiseBands, + params->deltaTAcrossFrames, + 0,0)) + return(1); + + sbrConfigData->initAmpResFF = params->init_amp_res_FF; + + if(FDKsbrEnc_InitSbrHuffmanTables (&hEnv->encEnvData, + &hEnv->sbrCodeEnvelope, + &hEnv->sbrCodeNoiseFloor, + sbrHeaderData->sbr_amp_res)) + return(1); + + FDKsbrEnc_initFrameInfoGenerator (&hEnv->SbrEnvFrame, + params->spread, + e, + params->stat, + timeSlots, + hEnv->encEnvData.freq_res_fixfix, + hEnv->encEnvData.fResTransIsLow, + hEnv->encEnvData.ldGrid + ); + + if(sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + { + INT bandwidth_qmf_slot = (sbrConfigData->sampleFreq>>1) / (sbrConfigData->noQmfBands); + if(FDKsbrEnc_InitSbrFastTransientDetector( + &hEnv->sbrFastTransientDetector, + sbrConfigData->noQmfSlots, + bandwidth_qmf_slot, + sbrConfigData->noQmfBands, + sbrConfigData->freqBandTable[0][0] + )) + return(1); + } + + /* The transient detector has to be initialized also if the fast transient + detector was active, because the values from the transient detector + structure are used. */ + if(FDKsbrEnc_InitSbrTransientDetector (&hEnv->sbrTransientDetector, + sbrConfigData->sbrSyntaxFlags, + sbrConfigData->frameSize, + sbrConfigData->sampleFreq, + params, + tran_fc, + sbrConfigData->noQmfSlots, + sbrConfigData->noQmfBands, + hEnv->sbrExtractEnvelope.YBufferWriteOffset, + hEnv->sbrExtractEnvelope.YBufferSzShift, + frameShift, + tran_off + )) + return(1); + + + sbrConfigData->xposCtrlSwitch = params->sbr_xpos_ctrl; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + hEnv->encEnvData.addHarmonicFlag = 0; + + return (0); +} + +INT sbrEncoder_Open( + HANDLE_SBR_ENCODER *phSbrEncoder, + INT nElements, + INT nChannels, + INT supportPS + ) +{ + INT i; + INT errorStatus = 1; + HANDLE_SBR_ENCODER hSbrEncoder = NULL; + + if (phSbrEncoder==NULL + ) + { + goto bail; + } + + hSbrEncoder = GetRam_SbrEncoder(); + if (hSbrEncoder==NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder, sizeof(SBR_ENCODER)); + + hSbrEncoder->pSBRdynamic_RAM = (UCHAR*)GetRam_SbrDynamic_RAM(); + hSbrEncoder->dynamicRam = hSbrEncoder->pSBRdynamic_RAM; + + for (i=0; isbrElement[i] = GetRam_SbrElement(i); + if (hSbrEncoder->sbrElement[i]==NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder->sbrElement[i], sizeof(SBR_ELEMENT)); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] = GetRam_Sbr_freqBandTableLO(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] = GetRam_Sbr_freqBandTableHI(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master = GetRam_Sbr_v_k_master(i); + if ( (hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO]==NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI]==NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master==NULL) ) + { + goto bail; + } + } + + for (i=0; ipSbrChannel[i] = GetRam_SbrChannel(i); + if (hSbrEncoder->pSbrChannel[i]==NULL) { + goto bail; + } + + if ( createEnvChannel(&hSbrEncoder->pSbrChannel[i]->hEnvChannel, + i + ,hSbrEncoder->dynamicRam + ) ) + { + goto bail; + } + + } + + for (i=0; iQmfAnalysis[i].FilterStates = GetRam_Sbr_QmfStatesAnalysis(i); + if (hSbrEncoder->QmfAnalysis[i].FilterStates==NULL) { + goto bail; + } + } + + if (supportPS) { + if (PSEnc_Create(&hSbrEncoder->hParametricStereo)) + { + goto bail; + } + + hSbrEncoder->qmfSynthesisPS.FilterStates = GetRam_PsQmfStatesSynthesis(); + if (hSbrEncoder->qmfSynthesisPS.FilterStates==NULL) { + goto bail; + } + } /* supportPS */ + + *phSbrEncoder = hSbrEncoder; + + errorStatus = 0; + return errorStatus; + +bail: + /* Close SBR encoder instance */ + sbrEncoder_Close(&hSbrEncoder); + return errorStatus; +} + +static +INT FDKsbrEnc_Reallocate( + HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], + const INT noElements) +{ + INT totalCh = 0; + INT totalQmf = 0; + INT coreEl; + INT el=-1; + + hSbrEncoder->lfeChIdx = -1; /* default value, until lfe found */ + + for (coreEl=0; coreEllfeChIdx = elInfo[coreEl].ChannelIndex[0]; + } + continue; + } + + SBR_ELEMENT_INFO *pelInfo = &elInfo[coreEl]; + HANDLE_SBR_ELEMENT hSbrElement = hSbrEncoder->sbrElement[el]; + + int ch; + for ( ch = 0; ch < pelInfo->nChannelsInEl; ch++ ) { + hSbrElement->sbrChannel[ch] = hSbrEncoder->pSbrChannel[totalCh]; + totalCh++; + } + /* analysis QMF */ + for ( ch = 0; ch < ((pelInfo->fParametricStereo)?2:pelInfo->nChannelsInEl); ch++ ) { + hSbrElement->elInfo.ChannelIndex[ch] = pelInfo->ChannelIndex[ch]; + hSbrElement->hQmfAnalysis[ch] = &hSbrEncoder->QmfAnalysis[totalQmf++]; + } + + /* Copy Element info */ + hSbrElement->elInfo.elType = pelInfo->elType; + hSbrElement->elInfo.instanceTag = pelInfo->instanceTag; + hSbrElement->elInfo.nChannelsInEl = pelInfo->nChannelsInEl; + hSbrElement->elInfo.fParametricStereo = pelInfo->fParametricStereo; + } /* coreEl */ + + return 0; +} + + + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvInit + description: initializes parameters + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static +INT FDKsbrEnc_EnvInit ( + HANDLE_SBR_ELEMENT hSbrElement, + sbrConfigurationPtr params, + INT *coreBandWith, + AUDIO_OBJECT_TYPE aot, + int nBitstrDelay, + int nElement, + const int headerPeriod, + ULONG statesInitFlag, + int fTimeDomainDownsampling + ,UCHAR *dynamic_RAM + ) +{ + UCHAR *bitstreamBuffer; + int ch, i; + + if ((params->codecSettings.nChannels < 1) || (params->codecSettings.nChannels > MAX_NUM_CHANNELS)){ + return(1); + } + + /* initialize the encoder handle and structs*/ + bitstreamBuffer = hSbrElement->payloadDelayLine[nBitstrDelay]; + + /* init and set syntax flags */ + hSbrElement->sbrConfigData.sbrSyntaxFlags = 0; + + switch (aot) { + case AOT_ER_AAC_ELD: + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_LOW_DELAY; + break; + default: + break; + } + if (params->crcSbr) { + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_CRC; + } + + hSbrElement->sbrConfigData.noQmfBands = QMF_CHANNELS>>(2-params->downSampleFactor); + switch (hSbrElement->sbrConfigData.noQmfBands) + { + case 64: hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize>>6; + break; + case 32: hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize>>5; + break; + default: hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize>>6; + return(2); + } + + FDKinitBitStream(&hSbrElement->CmonData.sbrBitbuf, bitstreamBuffer, MAX_PAYLOAD_SIZE*sizeof(UCHAR), 0, BS_WRITER); + + /* + now initialize sbrConfigData, sbrHeaderData and sbrBitstreamData, + */ + hSbrElement->sbrConfigData.nChannels = params->codecSettings.nChannels; + + if(params->codecSettings.nChannels == 2) + hSbrElement->sbrConfigData.stereoMode = params->stereoMode; + else + hSbrElement->sbrConfigData.stereoMode = SBR_MONO; + + hSbrElement->sbrConfigData.frameSize = params->sbrFrameSize; + + hSbrElement->sbrConfigData.sampleFreq = params->downSampleFactor * params->codecSettings.sampleFreq; + + hSbrElement->sbrBitstreamData.CountSendHeaderData = 0; + if (params->SendHeaderDataTime > 0 ) { + + if (headerPeriod==-1) { + + hSbrElement->sbrBitstreamData.NrSendHeaderData = (INT)(params->SendHeaderDataTime * hSbrElement->sbrConfigData.sampleFreq + / (1000 * hSbrElement->sbrConfigData.frameSize)); + hSbrElement->sbrBitstreamData.NrSendHeaderData = fixMax(hSbrElement->sbrBitstreamData.NrSendHeaderData,1); + } + else { + /* assure header period at least once per second */ + hSbrElement->sbrBitstreamData.NrSendHeaderData = fixMin(fixMax(headerPeriod,1),(hSbrElement->sbrConfigData.sampleFreq/hSbrElement->sbrConfigData.frameSize)); + } + } + else { + hSbrElement->sbrBitstreamData.NrSendHeaderData = 0; + } + + hSbrElement->sbrHeaderData.sbr_data_extra = params->sbr_data_extra; + hSbrElement->sbrBitstreamData.HeaderActive = 0; + hSbrElement->sbrHeaderData.sbr_start_frequency = params->startFreq; + hSbrElement->sbrHeaderData.sbr_stop_frequency = params->stopFreq; + hSbrElement->sbrHeaderData.sbr_xover_band = 0; + hSbrElement->sbrHeaderData.sbr_lc_stereo_mode = 0; + + /* data_extra */ + if (params->sbr_xpos_ctrl!= SBR_XPOS_CTRL_DEFAULT) + hSbrElement->sbrHeaderData.sbr_data_extra = 1; + + hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res; + + /* header_extra_1 */ + hSbrElement->sbrHeaderData.freqScale = params->freqScale; + hSbrElement->sbrHeaderData.alterScale = params->alterScale; + hSbrElement->sbrHeaderData.sbr_noise_bands = params->sbr_noise_bands; + hSbrElement->sbrHeaderData.header_extra_1 = 0; + + if ((params->freqScale != SBR_FREQ_SCALE_DEFAULT) || + (params->alterScale != SBR_ALTER_SCALE_DEFAULT) || + (params->sbr_noise_bands != SBR_NOISE_BANDS_DEFAULT)) + { + hSbrElement->sbrHeaderData.header_extra_1 = 1; + } + + /* header_extra_2 */ + hSbrElement->sbrHeaderData.sbr_limiter_bands = params->sbr_limiter_bands; + hSbrElement->sbrHeaderData.sbr_limiter_gains = params->sbr_limiter_gains; + + if ((hSbrElement->sbrConfigData.sampleFreq > 48000) && + (hSbrElement->sbrHeaderData.sbr_start_frequency >= 9)) + { + hSbrElement->sbrHeaderData.sbr_limiter_gains = SBR_LIMITER_GAINS_INFINITE; + } + + hSbrElement->sbrHeaderData.sbr_interpol_freq = params->sbr_interpol_freq; + hSbrElement->sbrHeaderData.sbr_smoothing_length = params->sbr_smoothing_length; + hSbrElement->sbrHeaderData.header_extra_2 = 0; + + if ((params->sbr_limiter_bands != SBR_LIMITER_BANDS_DEFAULT) || + (params->sbr_limiter_gains != SBR_LIMITER_GAINS_DEFAULT) || + (params->sbr_interpol_freq != SBR_INTERPOL_FREQ_DEFAULT) || + (params->sbr_smoothing_length != SBR_SMOOTHING_LENGTH_DEFAULT)) + { + hSbrElement->sbrHeaderData.header_extra_2 = 1; + } + + /* other switches */ + hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding; + hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding; + hSbrElement->sbrConfigData.thresholdAmpResFF_m = params->threshold_AmpRes_FF_m; + hSbrElement->sbrConfigData.thresholdAmpResFF_e = params->threshold_AmpRes_FF_e; + + /* init freq band table */ + if(updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + params->downSampleFactor + )) + { + return(1); + } + + /* now create envelope ext and QMF for each available channel */ + for ( ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++ ) { + + if ( initEnvChannel(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel, + params, + statesInitFlag + ,ch + ,dynamic_RAM + ) ) + { + return(1); + } + + + } /* nChannels */ + + /* reset and intialize analysis qmf */ + for ( ch = 0; ch < ((hSbrElement->elInfo.fParametricStereo)?2:hSbrElement->sbrConfigData.nChannels); ch++ ) + { + int err; + UINT qmfFlags = (hSbrElement->sbrConfigData.sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? QMF_FLAG_CLDFB : 0; + if (statesInitFlag) + qmfFlags &= ~QMF_FLAG_KEEP_STATES; + else + qmfFlags |= QMF_FLAG_KEEP_STATES; + + err = qmfInitAnalysisFilterBank( hSbrElement->hQmfAnalysis[ch], + (FIXP_QAS*)hSbrElement->hQmfAnalysis[ch]->FilterStates, + hSbrElement->sbrConfigData.noQmfSlots, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, + qmfFlags ); + if (0!=err) { + return err; + } + } + + /* */ + hSbrElement->CmonData.xOverFreq = hSbrElement->sbrConfigData.xOverFreq; + hSbrElement->CmonData.dynBwEnabled = (params->dynBwSupported && params->dynBwEnabled); + hSbrElement->CmonData.dynXOverFreqEnc = FDKsbrEnc_SbrGetXOverFreq( hSbrElement, hSbrElement->CmonData.xOverFreq); + for ( i = 0; i < 5; i++ ) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->CmonData.dynXOverFreqEnc; + hSbrElement->CmonData.sbrNumChannels = hSbrElement->sbrConfigData.nChannels; + hSbrElement->sbrConfigData.dynXOverFreq = hSbrElement->CmonData.xOverFreq; + + /* Update Bandwith to be passed to the core encoder */ + *coreBandWith = hSbrElement->CmonData.xOverFreq; + + return(0); + } + +INT sbrEncoder_GetInBufferSize(int noChannels) +{ + INT temp; + + temp = (2048); + temp += 1024 + MAX_SAMPLE_DELAY; + temp *= noChannels; + temp *= sizeof(INT_PCM); + return temp; +} + +/* + * Encode Dummy SBR payload frames to fill the delay lines. + */ +static +INT FDKsbrEnc_DelayCompensation ( + HANDLE_SBR_ENCODER hEnvEnc, + INT_PCM *timeBuffer + ) +{ + int n, el; + + for (n=hEnvEnc->nBitstrDelay; n>0; n--) + { + for (el=0; elnoElements; el++) + { + if (FDKsbrEnc_EnvEncodeFrame( + hEnvEnc, + el, + timeBuffer + hEnvEnc->downsampledOffset, + hEnvEnc->sbrElement[el]->sbrConfigData.nChannels, + NULL, + NULL, + 1 + )) + return -1; + } + sbrEncoder_UpdateBuffers(hEnvEnc, timeBuffer); + } + return 0; +} + +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, UINT coreSampleRate, AUDIO_OBJECT_TYPE aot) +{ + UINT newBitRate; + INT index; + + FDK_ASSERT(numChannels > 0 && numChannels <= 2); + if (aot == AOT_PS) { + if (numChannels == 2) { + index = getPsTuningTableIndex(bitRate, &newBitRate); + if (index == INVALID_TABLE_IDX) { + bitRate = newBitRate; + } + /* Set numChannels to 1 because for PS we need a SBR SCE (mono) element. */ + numChannels = 1; + } else { + return 0; + } + } + index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot, &newBitRate); + if (index != INVALID_TABLE_IDX) { + newBitRate = bitRate; + } + + return newBitRate; +} + +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot) +{ + UINT isPossible=(AOT_PS==aot)?0:1; + return isPossible; +} + +INT sbrEncoder_Init( + HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], + int noElements, + INT_PCM *inputBuffer, + INT *coreBandwidth, + INT *inputBufferOffset, + INT *numChannels, + INT *coreSampleRate, + UINT *downSampleFactor, + INT *frameLength, + AUDIO_OBJECT_TYPE aot, + int *delay, + int transformFactor, + const int headerPeriod, + ULONG statesInitFlag + ) +{ + HANDLE_ERROR_INFO errorInfo = noError; + sbrConfiguration sbrConfig[(8)]; + INT error = 0; + INT lowestBandwidth; + /* Save input parameters */ + INT inputSampleRate = *coreSampleRate; + int coreFrameLength = *frameLength; + int inputBandWidth = *coreBandwidth; + int inputChannels = *numChannels; + + int downsampledOffset = 0; + int sbrOffset = 0; + int downsamplerDelay = 0; + int timeDomainDownsample = 0; + int nBitstrDelay = 0; + int highestSbrStartFreq, highestSbrStopFreq; + int lowDelay = 0; + int usePs = 0; + + /* check whether SBR setting is available for the current encoder configuration (bitrate, samplerate) */ + if (!sbrEncoder_IsSingleRatePossible(aot)) { + *downSampleFactor = 2; + } + + + + if ( aot==AOT_PS || aot==AOT_DABPLUS_PS ) { + usePs = 1; + } + if ( aot==AOT_ER_AAC_ELD ) { + lowDelay = 1; + } + else if ( aot==AOT_ER_AAC_LD ) { + error = 1; + goto bail; + } + + /* Parametric Stereo */ + if ( usePs ) { + if ( *numChannels == 2 && noElements == 1) { + /* Override Element type in case of Parametric stereo */ + elInfo[0].elType = ID_SCE; + elInfo[0].fParametricStereo = 1; + elInfo[0].nChannelsInEl = 1; + /* core encoder gets downmixed mono signal */ + *numChannels = 1; + } else { + error = 1; + goto bail; + } + } /* usePs */ + + /* set the core's sample rate */ + switch (*downSampleFactor) { + case 1: + *coreSampleRate = inputSampleRate; + break; + case 2: + *coreSampleRate = inputSampleRate>>1; + break; + default: + *coreSampleRate = inputSampleRate>>1; + return 0; /* return error */ + } + + /* check whether SBR setting is available for the current encoder configuration (bitrate, coreSampleRate) */ + { + int delayDiff = 0; + int el, coreEl; + + /* Check if every element config is feasible */ + for (coreEl=0; coreEl 0) { + /* + * We must tweak the balancing into a situation where the downsampled path + * is the one to be delayed, because delaying the QMF domain input, also delays + * the downsampled audio, counteracting to the purpose of delay balancing. + */ + while ( delayDiff > 0 ) + { + /* Encoder delay increases */ + { + *delay += coreFrameLength * *downSampleFactor; + /* Add one frame delay to SBR path */ + delayDiff -= coreFrameLength * *downSampleFactor; + } + nBitstrDelay += 1; + } + } else + { + *delay += fixp_abs(delayDiff); + } + + if (delayDiff < 0) { + /* Delay AAC data */ + delayDiff = -delayDiff; + /* Multiply downsampled offset by AAC core channels. Divide by 2 because of half samplerate of downsampled data. */ + FDK_ASSERT(*downSampleFactor>0 && *downSampleFactor<=2); + downsampledOffset = (delayDiff*(*numChannels))>>(*downSampleFactor-1); + sbrOffset = 0; + } else { + /* Delay SBR input */ + if ( delayDiff > (int)coreFrameLength * (int)*downSampleFactor ) + { + /* Do bitstream frame-wise delay balancing if we have more than SBR framelength samples delay difference */ + delayDiff -= coreFrameLength * *downSampleFactor; + nBitstrDelay = 1; + } + /* Multiply input offset by input channels */ + sbrOffset = delayDiff*(*numChannels); + downsampledOffset = 0; + } + hSbrEncoder->nBitstrDelay = nBitstrDelay; + hSbrEncoder->nChannels = *numChannels; + hSbrEncoder->frameSize = coreFrameLength * *downSampleFactor; + hSbrEncoder->fTimeDomainDownsampling = timeDomainDownsample; + hSbrEncoder->downSampleFactor = *downSampleFactor; + hSbrEncoder->estimateBitrate = 0; + hSbrEncoder->inputDataDelay = 0; + + + /* Open SBR elements */ + el = -1; + highestSbrStartFreq = highestSbrStopFreq = 0; + lowestBandwidth = 99999; + + /* Loop through each core encoder element and get a matching SBR element config */ + for (coreEl=0; coreElnoElements = el+1; + + FDKsbrEnc_Reallocate(hSbrEncoder, + elInfo, + noElements); + + for (el=0; elnoElements; el++) { + + int bandwidth = *coreBandwidth; + + /* Use lowest common bandwidth */ + sbrConfig[el].startFreq = highestSbrStartFreq; + sbrConfig[el].stopFreq = highestSbrStopFreq; + + /* initialize SBR element, and get core bandwidth */ + error = FDKsbrEnc_EnvInit(hSbrEncoder->sbrElement[el], + &sbrConfig[el], + &bandwidth, + aot, + nBitstrDelay, + el, + headerPeriod, + statesInitFlag, + hSbrEncoder->fTimeDomainDownsampling + ,hSbrEncoder->dynamicRam + ); + + if (error != 0) { + error = 2; + goto bail; + } + + /* Get lowest core encoder bandwidth to be returned later. */ + lowestBandwidth = fixMin(lowestBandwidth, bandwidth); + + } /* second element loop */ + + /* Initialize a downsampler for each channel in each SBR element */ + if (hSbrEncoder->fTimeDomainDownsampling) + { + for (el=0; elnoElements; el++) + { + HANDLE_SBR_ELEMENT hSbrEl = hSbrEncoder->sbrElement[el]; + INT Wc, ch; + + /* Calculated required normalized cutoff frequency (Wc = 1.0 -> lowestBandwidth = inputSampleRate/2) */ + Wc = (2*lowestBandwidth)*1000 / inputSampleRate; + + for (ch=0; chelInfo.nChannelsInEl; ch++) + { + FDKaacEnc_InitDownsampler (&hSbrEl->sbrChannel[ch]->downSampler, Wc, *downSampleFactor); + FDK_ASSERT (hSbrEl->sbrChannel[ch]->downSampler.delay <=MAX_DS_FILTER_DELAY); + } + + downsamplerDelay = hSbrEl->sbrChannel[0]->downSampler.delay; + } /* third element loop */ + + /* lfe */ + FDKaacEnc_InitDownsampler (&hSbrEncoder->lfeDownSampler, 0, *downSampleFactor); + + /* Add the resampler additional delay to get the final delay and buffer offset values. */ + if (sbrOffset > 0 || downsampledOffset <= ((downsamplerDelay * (*numChannels))>>(*downSampleFactor-1))) { + sbrOffset += (downsamplerDelay - downsampledOffset) * (*numChannels) ; + *delay += downsamplerDelay - downsampledOffset; + downsampledOffset = 0; + } else { + downsampledOffset -= (downsamplerDelay * (*numChannels))>>(*downSampleFactor-1); + sbrOffset = 0; + } + + hSbrEncoder->inputDataDelay = downsamplerDelay; + } + + /* Assign core encoder Bandwidth */ + *coreBandwidth = lowestBandwidth; + + /* Estimate sbr bitrate, 2.5 kBit/s per sbr channel */ + hSbrEncoder->estimateBitrate += 2500 * (*numChannels); + + /* initialize parametric stereo */ + if (usePs) + { + PSENC_CONFIG psEncConfig; + FDK_ASSERT(hSbrEncoder->noElements == 1); + INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL); + + psEncConfig.frameSize = coreFrameLength; //sbrConfig.sbrFrameSize; + psEncConfig.qmfFilterMode = 0; + psEncConfig.sbrPsDelay = 0; + + /* tuning parameters */ + if (psTuningTableIdx != INVALID_TABLE_IDX) { + psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands; + psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes; + psEncConfig.iidQuantErrorThreshold = (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold; + + /* calculation is not quite linear, increased number of envelopes causes more bits */ + /* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope configuration */ + hSbrEncoder->estimateBitrate += ( (((*coreSampleRate) * 5 * psEncConfig.nStereoBands * psEncConfig.maxEnvelopes) / hSbrEncoder->frameSize)); + + } else { + error = ERROR(CDI, "Invalid ps tuning table index."); + goto bail; + } + + qmfInitSynthesisFilterBank(&hSbrEncoder->qmfSynthesisPS, + (FIXP_DBL*)hSbrEncoder->qmfSynthesisPS.FilterStates, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands>>1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands>>1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands>>1, + (statesInitFlag) ? 0 : QMF_FLAG_KEEP_STATES); + + if(errorInfo == noError){ + /* update delay */ + psEncConfig.sbrPsDelay = FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0]->sbrChannel[0]->hEnvChannel.sbrExtractEnvelope); + + if(noError != (errorInfo = PSEnc_Init( hSbrEncoder->hParametricStereo, + &psEncConfig, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands + ,hSbrEncoder->dynamicRam + ))) + { + errorInfo = handBack(errorInfo); + } + } + + /* QMF analysis + Hybrid analysis + Hybrid synthesis + QMF synthesis + downsampled input buffer delay */ + hSbrEncoder->inputDataDelay = (64*10/2) + (6*64) + (0) + (64*10/2-64+1) + ((*downSampleFactor)*downsampledOffset); + } + + hSbrEncoder->downsampledOffset = downsampledOffset; + { + hSbrEncoder->downmixSize = coreFrameLength*(*numChannels); + } + + hSbrEncoder->bufferOffset = sbrOffset; + /* Delay Compensation: fill bitstream delay buffer with zero input signal */ + if ( hSbrEncoder->nBitstrDelay > 0 ) + { + error = FDKsbrEnc_DelayCompensation (hSbrEncoder, inputBuffer); + if (error != 0) + goto bail; + } + + /* Set Output frame length */ + *frameLength = coreFrameLength * *downSampleFactor; + /* Input buffer offset */ + *inputBufferOffset = fixMax(sbrOffset, downsampledOffset); + + + } + + return error; + +bail: + /* Restore input settings */ + *coreSampleRate = inputSampleRate; + *frameLength = coreFrameLength; + *numChannels = inputChannels; + *coreBandwidth = inputBandWidth; + + return error; + } + + +INT +sbrEncoder_EncodeFrame( HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *samples, + UINT timeInStride, + UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE] + ) +{ + INT error; + int el; + + for (el=0; elnoElements; el++) + { + if (hSbrEncoder->sbrElement[el] != NULL) + { + error = FDKsbrEnc_EnvEncodeFrame( + hSbrEncoder, + el, + samples + hSbrEncoder->downsampledOffset, + timeInStride, + &sbrDataBits[el], + sbrData[el], + 0 + ); + if (error) + return error; + } + } + + if ( ( hSbrEncoder->lfeChIdx!=-1) && (hSbrEncoder->downSampleFactor > 1) ) + { /* lfe downsampler */ + INT nOutSamples; + + FDKaacEnc_Downsample(&hSbrEncoder->lfeDownSampler, + samples + hSbrEncoder->downsampledOffset + hSbrEncoder->bufferOffset + hSbrEncoder->lfeChIdx, + hSbrEncoder->frameSize, + timeInStride, + samples + hSbrEncoder->downsampledOffset + hSbrEncoder->lfeChIdx, + &nOutSamples, + hSbrEncoder->nChannels); + + + } + + return 0; +} + + +INT sbrEncoder_UpdateBuffers( + HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *timeBuffer + ) + { + if ( hSbrEncoder->downsampledOffset > 0 ) { + /* Move delayed downsampled data */ + FDKmemcpy ( timeBuffer, + timeBuffer + hSbrEncoder->downmixSize, + sizeof(INT_PCM) * (hSbrEncoder->downsampledOffset) ); + } else { + /* Move delayed input data */ + FDKmemcpy ( timeBuffer, + timeBuffer + hSbrEncoder->nChannels * hSbrEncoder->frameSize, + sizeof(INT_PCM) * hSbrEncoder->bufferOffset ); + } + if ( hSbrEncoder->nBitstrDelay > 0 ) + { + int el; + + for (el=0; elnoElements; el++) + { + FDKmemmove ( hSbrEncoder->sbrElement[el]->payloadDelayLine[0], + hSbrEncoder->sbrElement[el]->payloadDelayLine[1], + sizeof(UCHAR) * (hSbrEncoder->nBitstrDelay*MAX_PAYLOAD_SIZE) ); + + FDKmemmove( &hSbrEncoder->sbrElement[el]->payloadDelayLineSize[0], + &hSbrEncoder->sbrElement[el]->payloadDelayLineSize[1], + sizeof(UINT) * (hSbrEncoder->nBitstrDelay) ); + } + } + return 0; + } + + +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder) +{ + INT estimateBitrate = 0; + + if(hSbrEncoder) { + estimateBitrate += hSbrEncoder->estimateBitrate; + } + + return estimateBitrate; +} + +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder) +{ + INT delay = -1; + + if(hSbrEncoder) { + delay = hSbrEncoder->inputDataDelay; + } + return delay; +} + + +INT sbrEncoder_GetLibInfo( LIB_INFO *info ) +{ + int i; + + if (info == NULL) { + return -1; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_SBRENC; + info->version = LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = "SBR Encoder"; + + /* Set flags */ + info->flags = 0 + | CAPF_SBR_HQ + | CAPF_SBR_PS_MPEG + ; + /* End of flags */ + + return 0; +} diff --git a/libSBRenc/src/sbr_misc.cpp b/libSBRenc/src/sbr_misc.cpp new file mode 100644 index 00000000..c673b81a --- /dev/null +++ b/libSBRenc/src/sbr_misc.cpp @@ -0,0 +1,272 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Sbr miscellaneous helper functions +*/ +#include "sbr_misc.h" + + +void FDKsbrEnc_Shellsort_fract (FIXP_DBL *in, INT n) +{ + FIXP_DBL v; + INT i, j; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i-1]; + j = i; + while (in[j-inc-1] > v) { + in[j-1] = in[j-inc-1]; + j -= inc; + if (j <= inc) + break; + } + in[j-1] = v; + } + } while (inc > 1); + +} + +/* Sorting routine */ +void FDKsbrEnc_Shellsort_int (INT *in, INT n) +{ + + INT i, j, v; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i-1]; + j = i; + while (in[j-inc-1] > v) { + in[j-1] = in[j-inc-1]; + j -= inc; + if (j <= inc) + break; + } + in[j-1] = v; + } + } while (inc > 1); + +} + + + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecLeft + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src + + Return: none + +*******************************************************************************/ +void +FDKsbrEnc_AddVecLeft (INT *dst, INT *length_dst, INT *src, INT length_src) +{ + INT i; + + for (i = length_src - 1; i >= 0; i--) + FDKsbrEnc_AddLeft (dst, length_dst, src[i]); +} + + +/******************************************************************************* + Functionname: FDKsbrEnc_AddLeft + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void +FDKsbrEnc_AddLeft (INT *vector, INT *length_vector, INT value) +{ + INT i; + + for (i = *length_vector; i > 0; i--) + vector[i] = vector[i - 1]; + vector[0] = value; + (*length_vector)++; +} + + +/******************************************************************************* + Functionname: FDKsbrEnc_AddRight + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void +FDKsbrEnc_AddRight (INT *vector, INT *length_vector, INT value) +{ + vector[*length_vector] = value; + (*length_vector)++; +} + + + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecRight + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src) + + Return: none + +*******************************************************************************/ +void +FDKsbrEnc_AddVecRight (INT *dst, INT *length_dst, INT *src, INT length_src) +{ + INT i; + for (i = 0; i < length_src; i++) + FDKsbrEnc_AddRight (dst, length_dst, src[i]); +} + + +/***************************************************************************** + + functionname: FDKsbrEnc_LSI_divide_scale_fract + + description: Calculates division with best precision and scales the result. + + return: num*scale/denom + +*****************************************************************************/ +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, FIXP_DBL scale) +{ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0f); + if (num != FL2FXCONST_DBL(0.0f)) { + + INT shiftCommon; + INT shiftNum = CountLeadingBits(num); + INT shiftDenom = CountLeadingBits(denom); + INT shiftScale = CountLeadingBits(scale); + + num = num << shiftNum; + scale = scale << shiftScale; + + tmp = fMultDiv2(num,scale); + + if ( denom > (tmp >> fixMin(shiftNum+shiftScale-1,(DFRACT_BITS-1))) ) { + denom = denom << shiftDenom; + tmp = schur_div(tmp,denom,15); + shiftCommon = fixMin((shiftNum-shiftDenom+shiftScale-1),(DFRACT_BITS-1)); + if (shiftCommon < 0) + tmp <<= -shiftCommon; + else + tmp >>= shiftCommon; + } + else { + tmp = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL; + } + } + + return (tmp); +} + diff --git a/libSBRenc/src/sbr_misc.h b/libSBRenc/src/sbr_misc.h new file mode 100644 index 00000000..f471974f --- /dev/null +++ b/libSBRenc/src/sbr_misc.h @@ -0,0 +1,106 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Sbr miscellaneous helper functions prototypes + \author +*/ + +#ifndef _SBR_MISC_H +#define _SBR_MISC_H + +#include "sbr_encoder.h" + +/* Sorting routines */ +void FDKsbrEnc_Shellsort_fract (FIXP_DBL *in, INT n); +void FDKsbrEnc_Shellsort_int (INT *in, INT n); + +void FDKsbrEnc_AddLeft (INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddRight (INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddVecLeft (INT *dst, INT *length_dst, INT *src, INT length_src); +void FDKsbrEnc_AddVecRight (INT *dst, INT *length_vector_dst, INT *src, INT length_src); + +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, FIXP_DBL scale); + +#endif diff --git a/libSBRenc/src/sbr_ram.cpp b/libSBRenc/src/sbr_ram.cpp new file mode 100644 index 00000000..ee6c37f7 --- /dev/null +++ b/libSBRenc/src/sbr_ram.cpp @@ -0,0 +1,222 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Memory layout + + + This module declares all static and dynamic memory spaces +*/ +#include "sbr_ram.h" + +#include "sbr.h" +#include "genericStds.h" + +C_ALLOC_MEM (Ram_SbrDynamic_RAM, FIXP_DBL, ((SBR_ENC_DYN_RAM_SIZE)/sizeof(FIXP_DBL))) + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the encoder +*/ +/* @{ */ + +/*! static sbr encoder instance for one encoder (2 channels) + all major static and dynamic memory areas are located + in module sbr_ram and sbr rom +*/ +C_ALLOC_MEM (Ram_SbrEncoder, SBR_ENCODER, 1) +C_ALLOC_MEM2(Ram_SbrChannel, SBR_CHANNEL, 1, (8)) +C_ALLOC_MEM2(Ram_SbrElement, SBR_ELEMENT, 1, (8)) + +/*! Filter states for QMF-analysis.
+ Dimension: #MAXNRSBRCHANNELS * #SBR_QMF_FILTER_LENGTH +*/ +C_AALLOC_MEM2_L (Ram_Sbr_QmfStatesAnalysis, FIXP_QAS, QMF_FILTER_LENGTH, (8), SECT_DATA_L1) + + +/*! Matrix holding the quota values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2_L (Ram_Sbr_quotaMatrix, FIXP_DBL, (MAX_NO_OF_ESTIMATES*QMF_CHANNELS), (8), SECT_DATA_L1) + +/*! Matrix holding the sign values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2 (Ram_Sbr_signMatrix, INT, (MAX_NO_OF_ESTIMATES*QMF_CHANNELS), (8)) + +/*! Frequency band table (low res)
+ Dimension #MAX_FREQ_COEFFS/2+1 +*/ +C_ALLOC_MEM2 (Ram_Sbr_freqBandTableLO, UCHAR, (MAX_FREQ_COEFFS/2+1), (8)) + +/*! Frequency band table (high res)
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2 (Ram_Sbr_freqBandTableHI, UCHAR, (MAX_FREQ_COEFFS+1), (8)) + +/*! vk matser table
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2 (Ram_Sbr_v_k_master, UCHAR, (MAX_FREQ_COEFFS+1), (8)) + + +/* + Missing harmonics detection +*/ + +/*! sbr_detectionVectors
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2 (Ram_Sbr_detectionVectors, UCHAR, (MAX_NO_OF_ESTIMATES*MAX_FREQ_COEFFS), (8)) + +/*! sbr_prevCompVec[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2 (Ram_Sbr_prevEnvelopeCompensation, UCHAR, MAX_FREQ_COEFFS, (8)) +/*! sbr_guideScfb[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2 (Ram_Sbr_guideScfb, UCHAR, MAX_FREQ_COEFFS, (8)) + +/*! sbr_guideVectorDetected
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2 (Ram_Sbr_guideVectorDetected, UCHAR, (MAX_NO_OF_ESTIMATES*MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2 (Ram_Sbr_guideVectorDiff, FIXP_DBL, (MAX_NO_OF_ESTIMATES*MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2 (Ram_Sbr_guideVectorOrig, FIXP_DBL, (MAX_NO_OF_ESTIMATES*MAX_FREQ_COEFFS), (8)) + +/* + Static Parametric Stereo memory +*/ +C_AALLOC_MEM_L(Ram_PsQmfStatesSynthesis, FIXP_DBL, QMF_FILTER_LENGTH/2, SECT_DATA_L1) + +C_ALLOC_MEM_L (Ram_PsEncode, PS_ENCODE, 1, SECT_DATA_L1) +C_ALLOC_MEM (Ram_ParamStereo, PARAMETRIC_STEREO, 1) + + + +/* @} */ + + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core encoder. +*/ +/* @{ */ + + /*! Energy buffer for envelope extraction
+ Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_SLOTS * #SBR_QMF_CHANNELS + */ + C_ALLOC_MEM2 (Ram_Sbr_envYBuffer, FIXP_DBL, (QMF_MAX_TIME_SLOTS/2 * QMF_CHANNELS), (8)) + + FIXP_DBL* GetRam_Sbr_envYBuffer (int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((FIXP_DBL*) (dynamic_RAM + OFFSET_NRG + (n*Y_2_BUF_BYTE) )); + } + + /* + * QMF data + */ + /* The SBR encoder uses a single channel overlapping buffer set (always n=0), but PS does not. */ + FIXP_DBL* GetRam_Sbr_envRBuffer (int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE)) )); + } + FIXP_DBL* GetRam_Sbr_envIBuffer (int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM!=0); + return ((FIXP_DBL*) (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE)))); + } + + + + +/* @} */ + + + + + diff --git a/libSBRenc/src/sbr_ram.h b/libSBRenc/src/sbr_ram.h new file mode 100644 index 00000000..7e3d0c8b --- /dev/null +++ b/libSBRenc/src/sbr_ram.h @@ -0,0 +1,187 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! +\file +\brief Memory layout + +*/ +#ifndef __SBR_RAM_H +#define __SBR_RAM_H + +#include "sbr_def.h" +#include "env_est.h" +#include "sbr_encoder.h" +#include "sbr.h" + + + +#include "ps_main.h" +#include "ps_encode.h" + + +#define ENV_TRANSIENTS_BYTE ( (sizeof(FIXP_DBL)*(MAX_NUM_CHANNELS*3*QMF_MAX_TIME_SLOTS)) ) + + #define ENV_R_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) + #define ENV_I_BUFF_BYTE ( (sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) + #define Y_BUF_CH_BYTE ( (2*sizeof(FIXP_DBL)*((QMF_MAX_TIME_SLOTS) * MAX_HYBRID_BANDS)) ) + + +#define ENV_R_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) ) +#define ENV_I_BUF_PS_BYTE ( (sizeof(FIXP_DBL)*QMF_MAX_TIME_SLOTS * QMF_CHANNELS / 2) ) + +#define TON_BUF_CH_BYTE ( (sizeof(FIXP_DBL)*(MAX_NO_OF_ESTIMATES*MAX_FREQ_COEFFS)) ) + +#define Y_2_BUF_BYTE ( Y_BUF_CH_BYTE>>1 ) + + +/* Workbuffer RAM - Allocation */ +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + | OFFSET_QMF | OFFSET_NRG | + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + ------------------------- ------------------------- + | | 0.5 * | + | sbr_envRBuffer | sbr_envYBuffer_size | + | sbr_envIBuffer | | + ------------------------- ------------------------- + +*/ + #define BUF_NRG_SIZE ( (MAX_NUM_CHANNELS * Y_2_BUF_BYTE) ) + #define BUF_QMF_SIZE (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) + + /* Size of the shareable memory region than can be reused */ + #define SBR_ENC_DYN_RAM_SIZE ( BUF_QMF_SIZE + BUF_NRG_SIZE ) + + #define OFFSET_QMF ( 0 ) + #define OFFSET_NRG ( OFFSET_QMF + BUF_QMF_SIZE ) + + +/* + ***************************************************************************************************** + */ + + H_ALLOC_MEM(Ram_SbrDynamic_RAM, FIXP_DBL) + + H_ALLOC_MEM(Ram_SbrEncoder, SBR_ENCODER) + H_ALLOC_MEM(Ram_SbrChannel, SBR_CHANNEL) + H_ALLOC_MEM(Ram_SbrElement, SBR_ELEMENT) + + H_ALLOC_MEM(Ram_Sbr_quotaMatrix, FIXP_DBL) + H_ALLOC_MEM(Ram_Sbr_signMatrix, INT) + + H_ALLOC_MEM(Ram_Sbr_QmfStatesAnalysis, FIXP_QAS) + + H_ALLOC_MEM(Ram_Sbr_freqBandTableLO, UCHAR) + H_ALLOC_MEM(Ram_Sbr_freqBandTableHI, UCHAR) + H_ALLOC_MEM(Ram_Sbr_v_k_master, UCHAR) + + H_ALLOC_MEM(Ram_Sbr_detectionVectors, UCHAR) + H_ALLOC_MEM(Ram_Sbr_prevEnvelopeCompensation, UCHAR) + H_ALLOC_MEM(Ram_Sbr_guideScfb, UCHAR) + H_ALLOC_MEM(Ram_Sbr_guideVectorDetected, UCHAR) + + /* Dynamic Memory Allocation */ + + H_ALLOC_MEM(Ram_Sbr_envYBuffer, FIXP_DBL) + FIXP_DBL* GetRam_Sbr_envYBuffer (int n, UCHAR* dynamic_RAM); + FIXP_DBL* GetRam_Sbr_envRBuffer (int n, UCHAR* dynamic_RAM); + FIXP_DBL* GetRam_Sbr_envIBuffer (int n, UCHAR* dynamic_RAM); + + H_ALLOC_MEM(Ram_Sbr_guideVectorDiff, FIXP_DBL) + H_ALLOC_MEM(Ram_Sbr_guideVectorOrig, FIXP_DBL) + + + H_ALLOC_MEM(Ram_PsQmfStatesSynthesis, FIXP_DBL) + + H_ALLOC_MEM(Ram_PsEncode, PS_ENCODE) + + FIXP_DBL* FDKsbrEnc_SliceRam_PsRqmf (FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots); + FIXP_DBL* FDKsbrEnc_SliceRam_PsIqmf (FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, int n, int i, int qmfSlots); + + H_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO) + + + +#endif + diff --git a/libSBRenc/src/sbr_rom.cpp b/libSBRenc/src/sbr_rom.cpp new file mode 100644 index 00000000..7a51668b --- /dev/null +++ b/libSBRenc/src/sbr_rom.cpp @@ -0,0 +1,795 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Definition of constant tables + + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbr_rom.h" +#include "genericStds.h" + +//@{ +/******************************************************************************* + + Table Overview: + + o envelope level, 1.5 dB: + 1a) v_Huff_envelopeLevelC10T[121] + 1b) v_Huff_envelopeLevelL10T[121] + 2a) v_Huff_envelopeLevelC10F[121] + 2b) v_Huff_envelopeLevelL10F[121] + + o envelope balance, 1.5 dB: + 3a) bookSbrEnvBalanceC10T[49] + 3b) bookSbrEnvBalanceL10T[49] + 4a) bookSbrEnvBalanceC10F[49] + 4b) bookSbrEnvBalanceL10F[49] + + o envelope level, 3.0 dB: + 5a) v_Huff_envelopeLevelC11T[63] + 5b) v_Huff_envelopeLevelL11T[63] + 6a) v_Huff_envelopeLevelC11F[63] + 6b) v_Huff_envelopeLevelC11F[63] + + o envelope balance, 3.0 dB: + 7a) bookSbrEnvBalanceC11T[25] + 7b) bookSbrEnvBalanceL11T[25] + 8a) bookSbrEnvBalanceC11F[25] + 8b) bookSbrEnvBalanceL11F[25] + + o noise level, 3.0 dB: + 9a) v_Huff_NoiseLevelC11T[63] + 9b) v_Huff_NoiseLevelL11T[63] + - ) (v_Huff_envelopeLevelC11F[63] is used for freq dir) + - ) (v_Huff_envelopeLevelL11F[63] is used for freq dir) + + o noise balance, 3.0 dB: + 10a) bookSbrNoiseBalanceC11T[25] + 10b) bookSbrNoiseBalanceL11T[25] + - ) (bookSbrEnvBalanceC11F[25] is used for freq dir) + - ) (bookSbrEnvBalanceL11F[25] is used for freq dir) + + + (1.5 dB is never used for noise) + +********************************************************************************/ + + +/*******************************************************************************/ +/* table : envelope level, 1.5 dB */ +/* theor range : [-58,58], CODE_BOOK_SCF_LAV = 58 */ +/* implem range: [-60,60], CODE_BOOK_SCF_LAV10 = 60 */ +/* raw stats : envelopeLevel_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10T[121] = +{ + 0x0003FFD6, 0x0003FFD7, 0x0003FFD8, 0x0003FFD9, 0x0003FFDA, 0x0003FFDB, 0x0007FFB8, 0x0007FFB9, + 0x0007FFBA, 0x0007FFBB, 0x0007FFBC, 0x0007FFBD, 0x0007FFBE, 0x0007FFBF, 0x0007FFC0, 0x0007FFC1, + 0x0007FFC2, 0x0007FFC3, 0x0007FFC4, 0x0007FFC5, 0x0007FFC6, 0x0007FFC7, 0x0007FFC8, 0x0007FFC9, + 0x0007FFCA, 0x0007FFCB, 0x0007FFCC, 0x0007FFCD, 0x0007FFCE, 0x0007FFCF, 0x0007FFD0, 0x0007FFD1, + 0x0007FFD2, 0x0007FFD3, 0x0001FFE6, 0x0003FFD4, 0x0000FFF0, 0x0001FFE9, 0x0003FFD5, 0x0001FFE7, + 0x0000FFF1, 0x0000FFEC, 0x0000FFED, 0x0000FFEE, 0x00007FF4, 0x00003FF9, 0x00003FF7, 0x00001FFA, + 0x00001FF9, 0x00000FFB, 0x000007FC, 0x000003FC, 0x000001FD, 0x000000FD, 0x0000007D, 0x0000003D, + 0x0000001D, 0x0000000D, 0x00000005, 0x00000001, 0x00000000, 0x00000004, 0x0000000C, 0x0000001C, + 0x0000003C, 0x0000007C, 0x000000FC, 0x000001FC, 0x000003FD, 0x00000FFA, 0x00001FF8, 0x00003FF6, + 0x00003FF8, 0x00007FF5, 0x0000FFEF, 0x0001FFE8, 0x0000FFF2, 0x0007FFD4, 0x0007FFD5, 0x0007FFD6, + 0x0007FFD7, 0x0007FFD8, 0x0007FFD9, 0x0007FFDA, 0x0007FFDB, 0x0007FFDC, 0x0007FFDD, 0x0007FFDE, + 0x0007FFDF, 0x0007FFE0, 0x0007FFE1, 0x0007FFE2, 0x0007FFE3, 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, + 0x0007FFE7, 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, 0x0007FFEC, 0x0007FFED, 0x0007FFEE, + 0x0007FFEF, 0x0007FFF0, 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, + 0x0007FFF7, 0x0007FFF8, 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, 0x0007FFFD, 0x0007FFFE, + 0x0007FFFF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10T[121] = +{ + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x11, 0x12, 0x10, 0x11, 0x12, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x0E, 0x0E, 0x0D, + 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x10, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 +}; + + +/* direction: freq + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10F[121] = +{ + 0x0007FFE7, 0x0007FFE8, 0x000FFFD2, 0x000FFFD3, 0x000FFFD4, 0x000FFFD5, 0x000FFFD6, 0x000FFFD7, + 0x000FFFD8, 0x0007FFDA, 0x000FFFD9, 0x000FFFDA, 0x000FFFDB, 0x000FFFDC, 0x0007FFDB, 0x000FFFDD, + 0x0007FFDC, 0x0007FFDD, 0x000FFFDE, 0x0003FFE4, 0x000FFFDF, 0x000FFFE0, 0x000FFFE1, 0x0007FFDE, + 0x000FFFE2, 0x000FFFE3, 0x000FFFE4, 0x0007FFDF, 0x000FFFE5, 0x0007FFE0, 0x0003FFE8, 0x0007FFE1, + 0x0003FFE0, 0x0003FFE9, 0x0001FFEF, 0x0003FFE5, 0x0001FFEC, 0x0001FFED, 0x0001FFEE, 0x0000FFF4, + 0x0000FFF3, 0x0000FFF0, 0x00007FF7, 0x00007FF6, 0x00003FFA, 0x00001FFA, 0x00001FF9, 0x00000FFA, + 0x00000FF8, 0x000007F9, 0x000003FB, 0x000001FC, 0x000001FA, 0x000000FB, 0x0000007C, 0x0000003C, + 0x0000001C, 0x0000000C, 0x00000005, 0x00000001, 0x00000000, 0x00000004, 0x0000000D, 0x0000001D, + 0x0000003D, 0x000000FA, 0x000000FC, 0x000001FB, 0x000003FA, 0x000007F8, 0x000007FA, 0x000007FB, + 0x00000FF9, 0x00000FFB, 0x00001FF8, 0x00001FFB, 0x00003FF8, 0x00003FF9, 0x0000FFF1, 0x0000FFF2, + 0x0001FFEA, 0x0001FFEB, 0x0003FFE1, 0x0003FFE2, 0x0003FFEA, 0x0003FFE3, 0x0003FFE6, 0x0003FFE7, + 0x0003FFEB, 0x000FFFE6, 0x0007FFE2, 0x000FFFE7, 0x000FFFE8, 0x000FFFE9, 0x000FFFEA, 0x000FFFEB, + 0x000FFFEC, 0x0007FFE3, 0x000FFFED, 0x000FFFEE, 0x000FFFEF, 0x000FFFF0, 0x0007FFE4, 0x000FFFF1, + 0x0003FFEC, 0x000FFFF2, 0x000FFFF3, 0x0007FFE5, 0x0007FFE6, 0x000FFFF4, 0x000FFFF5, 0x000FFFF6, + 0x000FFFF7, 0x000FFFF8, 0x000FFFF9, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, 0x000FFFFD, 0x000FFFFE, + 0x000FFFFF +}; + + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10F[121] = +{ + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, + 0x13, 0x13, 0x14, 0x12, 0x14, 0x14, 0x14, 0x13, 0x14, 0x14, 0x14, 0x13, 0x14, 0x13, 0x12, 0x13, + 0x12, 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0F, 0x0F, 0x0E, 0x0D, 0x0D, 0x0C, + 0x0C, 0x0B, 0x0A, 0x09, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x08, 0x08, 0x09, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x10, 0x10, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x14, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x13, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, 0x12, 0x14, 0x14, 0x13, 0x13, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 +}; + + +/*******************************************************************************/ +/* table : envelope balance, 1.5 dB */ +/* theor range : [-48,48], CODE_BOOK_SCF_LAV = 48 */ +/* implem range: same but mapped to [-24,24], CODE_BOOK_SCF_LAV_BALANCE10 = 24 */ +/* raw stats : envelopePan_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10T[49] = +{ + 0x0000FFE4, 0x0000FFE5, 0x0000FFE6, 0x0000FFE7, 0x0000FFE8, 0x0000FFE9, 0x0000FFEA, 0x0000FFEB, + 0x0000FFEC, 0x0000FFED, 0x0000FFEE, 0x0000FFEF, 0x0000FFF0, 0x0000FFF1, 0x0000FFF2, 0x0000FFF3, + 0x0000FFF4, 0x0000FFE2, 0x00000FFC, 0x000007FC, 0x000001FE, 0x0000007E, 0x0000001E, 0x00000006, + 0x00000000, 0x00000002, 0x0000000E, 0x0000003E, 0x000000FE, 0x000007FD, 0x00000FFD, 0x00007FF0, + 0x0000FFE3, 0x0000FFF5, 0x0000FFF6, 0x0000FFF7, 0x0000FFF8, 0x0000FFF9, 0x0000FFFA, 0x0001FFF6, + 0x0001FFF7, 0x0001FFF8, 0x0001FFF9, 0x0001FFFA, 0x0001FFFB, 0x0001FFFC, 0x0001FFFD, 0x0001FFFE, + 0x0001FFFF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10T[49] = +{ + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x0C, 0x0B, 0x09, 0x07, 0x05, 0x03, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0B, 0x0C, 0x0F, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11 +}; + + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10F[49] = +{ + 0x0003FFE2, 0x0003FFE3, 0x0003FFE4, 0x0003FFE5, 0x0003FFE6, 0x0003FFE7, 0x0003FFE8, 0x0003FFE9, + 0x0003FFEA, 0x0003FFEB, 0x0003FFEC, 0x0003FFED, 0x0003FFEE, 0x0003FFEF, 0x0003FFF0, 0x0000FFF7, + 0x0001FFF0, 0x00003FFC, 0x000007FE, 0x000007FC, 0x000000FE, 0x0000007E, 0x0000000E, 0x00000002, + 0x00000000, 0x00000006, 0x0000001E, 0x0000003E, 0x000001FE, 0x000007FD, 0x00000FFE, 0x00007FFA, + 0x0000FFF6, 0x0003FFF1, 0x0003FFF2, 0x0003FFF3, 0x0003FFF4, 0x0003FFF5, 0x0003FFF6, 0x0003FFF7, + 0x0003FFF8, 0x0003FFF9, 0x0003FFFA, 0x0003FFFB, 0x0003FFFC, 0x0003FFFD, 0x0003FFFE, 0x0007FFFE, + 0x0007FFFF +}; + + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10F[49] = +{ + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x10, + 0x11, 0x0E, 0x0B, 0x0B, 0x08, 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, 0x09, 0x0B, 0x0C, 0x0F, + 0x10, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, + 0x13 +}; + + +/*******************************************************************************/ +/* table : envelope level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : envelopeLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11T[63] = { + 0x0003FFED, 0x0003FFEE, 0x0007FFDE, 0x0007FFDF, 0x0007FFE0, 0x0007FFE1, 0x0007FFE2, 0x0007FFE3, + 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, 0x0007FFE7, 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, + 0x0007FFEC, 0x0001FFF4, 0x0000FFF7, 0x0000FFF9, 0x0000FFF8, 0x00003FFB, 0x00003FFA, 0x00003FF8, + 0x00001FFA, 0x00000FFC, 0x000007FC, 0x000000FE, 0x0000003E, 0x0000000E, 0x00000002, 0x00000000, + 0x00000006, 0x0000001E, 0x0000007E, 0x000001FE, 0x000007FD, 0x00001FFB, 0x00003FF9, 0x00003FFC, + 0x00007FFA, 0x0000FFF6, 0x0001FFF5, 0x0003FFEC, 0x0007FFED, 0x0007FFEE, 0x0007FFEF, 0x0007FFF0, + 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, 0x0007FFF7, 0x0007FFF8, + 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, 0x0007FFFD, 0x0007FFFE, 0x0007FFFF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11T[63] = { + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x11, 0x10, 0x10, 0x10, 0x0E, 0x0E, 0x0E, 0x0D, 0x0C, 0x0B, 0x08, 0x06, 0x04, 0x02, 0x01, + 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 +}; + + +/* direction: freq + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11F[63] = { + 0x000FFFF0, 0x000FFFF1, 0x000FFFF2, 0x000FFFF3, 0x000FFFF4, 0x000FFFF5, 0x000FFFF6, 0x0003FFF3, + 0x0007FFF5, 0x0007FFEE, 0x0007FFEF, 0x0007FFF6, 0x0003FFF4, 0x0003FFF2, 0x000FFFF7, 0x0007FFF0, + 0x0001FFF5, 0x0003FFF0, 0x0001FFF4, 0x0000FFF7, 0x0000FFF6, 0x00007FF8, 0x00003FFB, 0x00000FFD, + 0x000007FD, 0x000003FD, 0x000001FD, 0x000000FD, 0x0000003E, 0x0000000E, 0x00000002, 0x00000000, + 0x00000006, 0x0000001E, 0x000000FC, 0x000001FC, 0x000003FC, 0x000007FC, 0x00000FFC, 0x00001FFC, + 0x00003FFA, 0x00007FF9, 0x00007FFA, 0x0000FFF8, 0x0000FFF9, 0x0001FFF6, 0x0001FFF7, 0x0003FFF5, + 0x0003FFF6, 0x0003FFF1, 0x000FFFF8, 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, 0x000FFFF9, 0x0007FFF7, + 0x0007FFF4, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, 0x000FFFFD, 0x000FFFFE, 0x000FFFFF +}; + + +/* direction: freq + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11F[63] = { + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x14, 0x13, + 0x11, 0x12, 0x11, 0x10, 0x10, 0x0F, 0x0E, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01, + 0x03, 0x05, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x11, 0x11, 0x12, + 0x12, 0x12, 0x14, 0x13, 0x13, 0x13, 0x14, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 +}; + + + +/*******************************************************************************/ +/* table : envelope balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 */ +/* raw stats : envelopeBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11T[25] = +{ + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, 0x00001FF7, 0x00001FF8, 0x00000FF8, + 0x000000FE, 0x0000007E, 0x0000000E, 0x00000006, 0x00000000, 0x00000002, 0x0000001E, 0x0000003E, + 0x000001FE, 0x00001FF9, 0x00001FFA, 0x00001FFB, 0x00001FFC, 0x00001FFD, 0x00001FFE, 0x00003FFE, + 0x00003FFF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11T[25] = +{ + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x08, 0x07, 0x04, 0x03, 0x01, 0x02, 0x05, 0x06, + 0x09, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E +}; + + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11F[25] = +{ + 0x00001FF7, 0x00001FF8, 0x00001FF9, 0x00001FFA, 0x00001FFB, 0x00003FF8, 0x00003FF9, 0x000007FC, + 0x000000FE, 0x0000007E, 0x0000000E, 0x00000002, 0x00000000, 0x00000006, 0x0000001E, 0x0000003E, + 0x000001FE, 0x00000FFA, 0x00001FF6, 0x00003FFA, 0x00003FFB, 0x00003FFC, 0x00003FFD, 0x00003FFE, + 0x00003FFF +}; + + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11F[25] = +{ + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0B, 0x08, 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, + 0x09, 0x0C, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E +}; + + +/*******************************************************************************/ +/* table : noise level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : noiseLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_NoiseLevelC11T[63] = { + 0x00001FCE, 0x00001FCF, 0x00001FD0, 0x00001FD1, 0x00001FD2, 0x00001FD3, 0x00001FD4, 0x00001FD5, + 0x00001FD6, 0x00001FD7, 0x00001FD8, 0x00001FD9, 0x00001FDA, 0x00001FDB, 0x00001FDC, 0x00001FDD, + 0x00001FDE, 0x00001FDF, 0x00001FE0, 0x00001FE1, 0x00001FE2, 0x00001FE3, 0x00001FE4, 0x00001FE5, + 0x00001FE6, 0x00001FE7, 0x000007F2, 0x000000FD, 0x0000003E, 0x0000000E, 0x00000006, 0x00000000, + 0x00000002, 0x0000001E, 0x000000FC, 0x000003F8, 0x00001FCC, 0x00001FE8, 0x00001FE9, 0x00001FEA, + 0x00001FEB, 0x00001FEC, 0x00001FCD, 0x00001FED, 0x00001FEE, 0x00001FEF, 0x00001FF0, 0x00001FF1, + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, 0x00001FF7, 0x00001FF8, 0x00001FF9, + 0x00001FFA, 0x00001FFB, 0x00001FFC, 0x00001FFD, 0x00001FFE, 0x00003FFE, 0x00003FFF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_NoiseLevelL11T[63] = { + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000B, 0x00000008, 0x00000006, 0x00000004, 0x00000003, 0x00000001, + 0x00000002, 0x00000005, 0x00000008, 0x0000000A, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000E, 0x0000000E +}; + + +/*******************************************************************************/ +/* table : noise balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 */ +/* raw stats : noiseBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrNoiseBalanceC11T[25] = +{ + 0x000000EC, 0x000000ED, 0x000000EE, 0x000000EF, 0x000000F0, 0x000000F1, 0x000000F2, 0x000000F3, + 0x000000F4, 0x000000F5, 0x0000001C, 0x00000002, 0x00000000, 0x00000006, 0x0000003A, 0x000000F6, + 0x000000F7, 0x000000F8, 0x000000F9, 0x000000FA, 0x000000FB, 0x000000FC, 0x000000FD, 0x000000FE, + 0x000000FF +}; + + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrNoiseBalanceL11T[25] = +{ + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x05, 0x02, 0x01, 0x03, 0x06, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 +}; + +/* + tuningTable +*/ +const sbrTuningTable_t sbrTuningTable[] = +{ + /* Some of the low bitrates are commented out here, this is because the + encoder could lose frames at those bitrates and throw an error because + it has insufficient bits to encode for some test items. + */ + + /*** HE-AAC section ***/ + /* sf,sfsp,sf,sfsp,nnb,nfo,saml,SM,FS*/ + + /*** mono ***/ + + /* 8/16 kHz dual rate */ + { CODEC_AAC, 8000, 10000, 8000, 1, 7, 6, 11,10, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 10000, 12000, 8000, 1, 11, 7, 13,12, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 12000, 16001, 8000, 1, 14,10, 13,13, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 16000, 24000, 8000, 1, 14,10, 14,14, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 24000, 32000, 8000, 1, 14,10, 14,14, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 32000, 48001, 8000, 1, 14,11, 15,15, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ /* bitrates higher than 48000 not supported by AAC core */ + + /* 11/22 kHz dual rate */ + { CODEC_AAC, 8000, 10000, 11025, 1, 5, 4, 6, 6, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 10000, 12000, 11025, 1, 8, 5, 12, 9, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 12000, 16000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3 }, + { CODEC_AAC, 16000, 20000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3 }, /* at such "high" bitrates it's better to upsample the input */ + { CODEC_AAC, 20000, 24001, 11025, 1, 13, 9, 13, 8, 1, 0, 6, SBR_MONO, 3 }, /* signal by a factor of 2 before sending it into the encoder */ + { CODEC_AAC, 24000, 32000, 11025, 1, 14,10, 14, 9, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 32000, 48000, 11025, 1, 15,11, 15,10, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 48000, 64001, 11025, 1, 15,11, 15,10, 2, 0, 3, SBR_MONO, 1 }, /* placebo */ + + /* 12/24 kHz dual rate */ + { CODEC_AAC, 8000, 10000, 12000, 1, 4, 3, 6, 6, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ + { CODEC_AAC, 10000, 12000, 12000, 1, 7, 4, 11, 8, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 10 kbit/s */ + { CODEC_AAC, 12000, 16000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ + { CODEC_AAC, 16000, 20000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ /* at such "high" bitrates it's better to upsample the input */ + { CODEC_AAC, 20000, 24001, 12000, 1, 12, 8, 12, 8, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 20 kbit/s */ /* signal by a factor of 2 before sending it into the encoder */ + { CODEC_AAC, 24000, 32000, 12000, 1, 13, 9, 13, 9, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 32000, 48000, 12000, 1, 14,10, 14,10, 2, 0, 3, SBR_MONO, 2 }, /* placebo */ + { CODEC_AAC, 48000, 64001, 12000, 1, 14,11, 15,11, 2, 0, 3, SBR_MONO, 1 }, /* placebo */ + + /* 16/32 kHz dual rate */ + { CODEC_AAC, 8000, 10000, 16000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ + { CODEC_AAC, 10000, 12000, 16000, 1, 2, 1, 6, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 10 kbit/s */ + { CODEC_AAC, 12000, 16000, 16000, 1, 4, 2, 6, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ + { CODEC_AAC, 16000, 18000, 16000, 1, 4, 2, 8, 3, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ + { CODEC_AAC, 18000, 22000, 16000, 1, 6, 5,11, 7, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 22000, 28000, 16000, 1, 10, 9,12, 8, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 16000, 1, 12,12,13,13, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 16000, 1, 14,14,13,13, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 64001, 16000, 1, 14,14,13,13, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ + + /* 22.05/44.1 kHz dual rate */ + /* { CODEC_AAC, 8000, 11369, 22050, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, */ /* nominal: 8 kbit/s */ /* encoder can not work stable at this extremely low bitrate */ + { CODEC_AAC, 11369, 16000, 22050, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ + { CODEC_AAC, 16000, 18000, 22050, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ + { CODEC_AAC, 18000, 22000, 22050, 1, 4, 4, 8, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 22000, 28000, 22050, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 22050, 1, 10,10, 9, 9, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 22050, 1, 11,11,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 64001, 22050, 1, 13,13,12,12, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ + + /* 24/48 kHz dual rate */ + /* { CODEC_AAC, 8000, 12000, 24000, 1, 1, 1, 1, 1, 1, 0, 6, SBR_MONO, 3 }, */ /* nominal: 8 kbit/s */ /* encoder can not work stable at this extremely low bitrate */ + { CODEC_AAC, 12000, 16000, 24000, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 12 kbit/s */ + { CODEC_AAC, 16000, 18000, 24000, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s */ + { CODEC_AAC, 18000, 22000, 24000, 1, 4, 3, 8, 5, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 22000, 28000, 24000, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 24000, 1, 10,10, 9, 9, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 24000, 1, 11,11,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 64001, 24000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ + + /* 32/64 kHz dual rate */ /* placebo settings */ + { CODEC_AAC, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* lowest range */ + { CODEC_AAC, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2 }, /* lowest range */ + { CODEC_AAC, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1 }, /* low range */ + { CODEC_AAC, 72000,100000, 32000, 1, 11,11,10,10, 2, 0, 3, SBR_MONO, 1 }, /* SBR sweet spot */ + { CODEC_AAC, 100000,160001, 32000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* backwards compatible */ + + /* 44.1/88.2 kHz dual rate */ /* placebo settings */ + { CODEC_AAC, 24000, 36000, 44100, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 36000, 60000, 44100, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 60000, 72000, 44100, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1 }, /* low range */ + { CODEC_AAC, 72000,100000, 44100, 1, 11,11,10,10, 2, 0, 3, SBR_MONO, 1 }, /* SBR sweet spot */ + { CODEC_AAC, 100000,160001, 44100, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* backwards compatible */ + + /* 48/96 kHz dual rate */ /* not yet finally tuned */ + { CODEC_AAC, 32000, 36000, 48000, 1, 4, 4, 9, 9, 2, 0, 3, SBR_MONO, 3 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 36000, 60000, 48000, 1, 7, 7,10,10, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 40 */ + { CODEC_AAC, 60000, 72000, 48000, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */ + { CODEC_AAC, 72000,100000, 48000, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */ + { CODEC_AAC, 100000,160001, 48000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ + + /*** stereo ***/ + /* 08/16 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 8000, 2, 6, 6, 9, 7, 1, 0,-3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ /* placebo */ + { CODEC_AAC, 24000, 28000, 8000, 2, 9, 9, 11, 9, 1, 0,-3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 8000, 2, 11, 9, 11, 9, 2, 0,-3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 8000, 2, 13,11, 13,11, 2, 0,-3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 8000, 2, 14,12, 13,12, 2, 0,-3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 8000, 2, 14,14, 13,13, 3, 0,-3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 8000, 2, 14,14, 13,13, 3, 0,-3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 8000, 2, 14,14, 13,13, 3, 0,-3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 11/22 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 11025, 2, 7, 5, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ /* placebo */ + { CODEC_AAC, 24000, 28000, 11025, 2, 10, 8,10, 8, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 11025, 2, 12, 8,12, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 11025, 2, 13, 9,13, 9, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 11025, 2, 14,11,13,11, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 11025, 2, 15,15,13,13, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 11025, 2, 15,15,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 11025, 2, 15,15,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 12/24 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 12000, 2, 6, 4, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ /* placebo */ + { CODEC_AAC, 24000, 28000, 12000, 2, 9, 7,10, 8, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 12000, 2, 11, 7,12, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 12000, 2, 12, 9,12, 9, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 12000, 2, 13,12,13,12, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 12000, 2, 14,14,13,13, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 12000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 12000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 16/32 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 16000, 2, 4, 2, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 24000, 28000, 16000, 2, 8, 7,10, 8, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 16000, 2, 10, 9,12,11, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 16000, 2, 13,13,13,13, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 16000, 2, 14,14,13,13, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 22.05/44.1 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 22050, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 24000, 28000, 22050, 2, 5, 4, 6, 5, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 32000, 22050, 2, 5, 4, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 28 kbit/s */ + { CODEC_AAC, 32000, 36000, 22050, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 22050, 2, 10,10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 22050, 2, 12,12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 22050, 2, 13,13,10,10, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 22050, 2, 14,14,12,12, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 22050, 2, 14,14,12,12, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 24/48 kHz dual rate */ + { CODEC_AAC, 16000, 24000, 24000, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 20 kbit/s */ + { CODEC_AAC, 24000, 28000, 24000, 2, 5, 5, 6, 6, 1, 0, -3, SBR_SWITCH_LRC, 3 }, /* nominal: 24 kbit/s */ + { CODEC_AAC, 28000, 36000, 24000, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AAC, 36000, 44000, 24000, 2, 10,10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AAC, 44000, 52000, 24000, 2, 12,12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AAC, 52000, 60000, 24000, 2, 13,13,10,10, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AAC, 60000, 76000, 24000, 2, 14,14,12,12, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AAC, 76000,128001, 24000, 2, 14,14,12,12, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 32/64 kHz dual rate */ /* placebo settings */ + { CODEC_AAC, 32000, 60000, 32000, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, 3 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 80000,112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* low range */ + { CODEC_AAC, 112000,144000, 32000, 2, 11,11,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* SBR sweet spot */ + { CODEC_AAC, 144000,256001, 32000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* backwards compatible */ + + /* 44.1/88.2 kHz dual rate */ /* placebo settings */ + { CODEC_AAC, 32000, 60000, 44100, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, 3 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 80000,112000, 44100, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* low range */ + { CODEC_AAC, 112000,144000, 44100, 2, 11,11,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* SBR sweet spot */ + { CODEC_AAC, 144000,256001, 44100, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* backwards compatible */ + + /* 48/96 kHz dual rate */ /* not yet finally tuned */ + { CODEC_AAC, 36000, 60000, 48000, 2, 4, 4, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, 3 }, /* lowest range (multichannel rear) */ + { CODEC_AAC, 60000, 80000, 48000, 2, 7, 7, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 64 */ + { CODEC_AAC, 80000,112000, 48000, 2, 9, 9,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 96 */ + { CODEC_AAC, 112000,144000, 48000, 2, 11,11,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 128 */ + { CODEC_AAC, 144000,256001, 48000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 192 */ + + + /** AAC LOW DELAY SECTION **/ + + /* 24 kHz dual rate - 12kHz singlerate is not allowed (deactivated in FDKsbrEnc_IsSbrSettingAvail()) */ + { CODEC_AACLD, 8000, 32000, 12000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 8 kbit/s */ + + /*** mono ***/ + /* 16/32 kHz dual rate not yet tuned ->alb copied from non LD tables*/ + { CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3 }, /* nominal: 16 kbit/s wrr: tuned */ + { CODEC_AACLD, 18000, 22000, 16000, 1, 7, 7,12,12, 1, 6, 9, SBR_MONO, 3 }, /* nominal: 20 kbit/s wrr: tuned */ + { CODEC_AACLD, 22000, 28000, 16000, 1, 6, 6, 9, 9, 2, 3, 6, SBR_MONO, 3 }, /* nominal: 24 kbit/s wrr: tuned */ + { CODEC_AACLD, 28000, 36000, 16000, 1, 8, 8,12, 7, 2, 9,12, SBR_MONO, 3 }, /* jgr: special */ /* wrr: tuned */ + { CODEC_AACLD, 36000, 44000, 16000, 1, 10,14,12,13, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 44000, 64001, 16000, 1, 11,14,13,13, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ + + /* 22.05/44.1 kHz dual rate */ + { CODEC_AACLD, 18000, 22000, 22050, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 3 }, /* nominal: 20 kbit/s */ + { CODEC_AACLD, 22000, 28000, 22050, 1, 5, 5, 6, 6, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ + { CODEC_AACLD, 28000, 36000, 22050, 1, 7, 8, 8, 8, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AACLD, 36000, 44000, 22050, 1, 9, 9, 9, 9, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 44000, 52000, 22050, 1, 12,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 48 kbit/s */ + { CODEC_AACLD, 52000, 64001, 22050, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 56 kbit/s */ + + /* 24/48 kHz dual rate */ + { CODEC_AACLD, 20000, 22000, 24000, 1, 3, 4, 8, 8, 2, 0, 6, SBR_MONO, 2 }, /* nominal: 20 kbit/s */ + { CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 24 kbit/s */ + { CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 8, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 56000, 64001, 24000, 1, 13,11,11,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 kbit/s */ + + /* 32/64 kHz dual rate */ /* placebo settings */ /*jgr: new, copy from CODEC_AAC */ + { CODEC_AACLD, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* lowest range */ + { CODEC_AACLD, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2 }, /* lowest range */ + { CODEC_AACLD, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1 }, /* low range */ + { CODEC_AACLD, 72000,100000, 32000, 1, 11,11,10,10, 2, 0, 3, SBR_MONO, 1 }, /* SBR sweet spot */ + { CODEC_AACLD, 100000,160001, 32000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* backwards compatible */ + + /* 44/88 kHz dual rate */ /* not yet finally tuned */ + { CODEC_AACLD, 36000, 60000, 44100, 1, 8, 7, 6, 9, 2, 0, 3, SBR_MONO, 2 }, /* nominal: 40 */ + { CODEC_AACLD, 60000, 72000, 44100, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */ + { CODEC_AACLD, 72000,100000, 44100, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */ + { CODEC_AACLD, 100000,160001, 44100, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ + + /* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR */ + { CODEC_AACLD, 36000, 60000, 48000, 1, 4, 7, 4, 4, 2, 0, 3, SBR_MONO, 3 }, /* nominal: 40 */ + { CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9,10,10, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 64 */ + { CODEC_AACLD, 72000,100000, 48000, 1, 11,11,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 80 */ + { CODEC_AACLD, 100000,160001, 48000, 1, 13,13,11,11, 2, 0, 3, SBR_MONO, 1 }, /* nominal: 128 */ + + /*** stereo ***/ + /* 16/32 kHz dual rate not yet tuned ->alb copied from non LD tables*/ + { CODEC_AACLD, 32000, 36000, 16000, 2, 10, 9,12,11, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AACLD, 36000, 44000, 16000, 2, 13,13,13,13, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 44000, 52000, 16000, 2, 10, 9,11, 9, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* tune12 nominal: 48 kbit/s */ + { CODEC_AACLD, 52000, 60000, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AACLD, 60000, 76000, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AACLD, 76000,128001, 16000, 2, 14,14,13,13, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 22.05/44.1 kHz dual rate */ + { CODEC_AACLD, 32000, 36000, 22050, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AACLD, 36000, 44000, 22050, 2, 5, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 44000, 52000, 22050, 2, 7,10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AACLD, 52000, 60000, 22050, 2, 9,11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AACLD, 60000, 76000, 22050, 2, 10,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AACLD, 76000, 82000, 22050, 2, 12,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + { CODEC_AACLD, 82000,128001, 22050, 2, 13,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + + /* 24/48 kHz dual rate */ + { CODEC_AACLD, 32000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 32 kbit/s */ + { CODEC_AACLD, 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 40 kbit/s */ + { CODEC_AACLD, 44000, 52000, 24000, 2, 6,10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 48 kbit/s */ + { CODEC_AACLD, 52000, 60000, 24000, 2, 9,11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, 1 }, /* nominal: 56 kbit/s */ + { CODEC_AACLD, 60000, 76000, 24000, 2, 11,12,10,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 64 kbit/s */ + { CODEC_AACLD, 76000, 88000, 24000, 2, 12,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 80 kbit/s */ + { CODEC_AACLD, 88000,128001, 24000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 92 kbit/s */ + + /* 32/64 kHz dual rate */ /* placebo settings */ /*jgr: new, copy from CODEC_AAC */ + { CODEC_AACLD, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* lowest range (multichannel rear) */ + { CODEC_AACLD, 80000,112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* low range */ + { CODEC_AACLD, 112000,144000, 32000, 2, 11,11,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* SBR sweet spot */ + { CODEC_AACLD, 144000,256001, 32000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* backwards compatible */ + + /* 44.1/88.2 kHz dual rate */ /* placebo settings */ /*wrr: new, copy from CODEC_AAC */ + { CODEC_AACLD, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, 2 }, /* lowest range (multichannel rear) */ + { CODEC_AACLD, 80000,112000, 44100, 2, 10,10, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* hlm 11-08-29 */ + { CODEC_AACLD, 112000,144000, 44100, 2, 12,12,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* hlm 11-08-29 */ + { CODEC_AACLD, 144000,256001, 44100, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* backwards compatible */ + + /* 48/96 kHz dual rate */ /* not yet finally tuned */ /*wrr: new, copy from CODEC_AAC */ + { CODEC_AACLD, 60000, 80000, 48000, 2, 7, 7,10,10, 2, 0, -3, SBR_SWITCH_LRC, 2 }, /* nominal: 64 */ + { CODEC_AACLD, 80000,112000, 48000, 2, 9, 9,10,10, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 96 */ + { CODEC_AACLD, 112000,144000, 48000, 2, 11,11,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* nominal: 128 */ + { CODEC_AACLD, 144000,176000, 48000, 2, 12,12,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* hlm 09-10-19 */ + { CODEC_AACLD, 176000,256001, 48000, 2, 13,13,11,11, 3, 0, -3, SBR_LEFT_RIGHT, 1 }, /* hlm 09-10-19 */ + +}; + +const int sbrTuningTableSize = sizeof(sbrTuningTable)/sizeof(sbrTuningTable[0]); + +const psTuningTable_t psTuningTable[4] = +{ + { 8000, 22000, PSENC_STEREO_BANDS_10, PSENC_NENV_1, FL2FXCONST_DBL(3.0f/4.0f) }, + { 22000, 28000, PSENC_STEREO_BANDS_20, PSENC_NENV_1, FL2FXCONST_DBL(2.0f/4.0f) }, + { 28000, 36000, PSENC_STEREO_BANDS_20, PSENC_NENV_2, FL2FXCONST_DBL(1.5f/4.0f) }, + { 36000, 160001, PSENC_STEREO_BANDS_20, PSENC_NENV_4, FL2FXCONST_DBL(1.1f/4.0f) }, +}; + + +//@} + + + diff --git a/libSBRenc/src/sbr_rom.h b/libSBRenc/src/sbr_rom.h new file mode 100644 index 00000000..afa924e4 --- /dev/null +++ b/libSBRenc/src/sbr_rom.h @@ -0,0 +1,127 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! +\file +\brief Declaration of constant tables + +*/ +#ifndef __SBR_ROM_H +#define __SBR_ROM_H + +#include "sbr_def.h" +#include "sbr_encoder.h" + +#include "ps_main.h" + +/* + huffman tables +*/ +extern const INT v_Huff_envelopeLevelC10T[121]; +extern const UCHAR v_Huff_envelopeLevelL10T[121]; +extern const INT v_Huff_envelopeLevelC10F[121]; +extern const UCHAR v_Huff_envelopeLevelL10F[121]; +extern const INT bookSbrEnvBalanceC10T[49]; +extern const UCHAR bookSbrEnvBalanceL10T[49]; +extern const INT bookSbrEnvBalanceC10F[49]; +extern const UCHAR bookSbrEnvBalanceL10F[49]; +extern const INT v_Huff_envelopeLevelC11T[63]; +extern const UCHAR v_Huff_envelopeLevelL11T[63]; +extern const INT v_Huff_envelopeLevelC11F[63]; +extern const UCHAR v_Huff_envelopeLevelL11F[63]; +extern const INT bookSbrEnvBalanceC11T[25]; +extern const UCHAR bookSbrEnvBalanceL11T[25]; +extern const INT bookSbrEnvBalanceC11F[25]; +extern const UCHAR bookSbrEnvBalanceL11F[25]; +extern const INT v_Huff_NoiseLevelC11T[63]; +extern const UCHAR v_Huff_NoiseLevelL11T[63]; +extern const INT bookSbrNoiseBalanceC11T[25]; +extern const UCHAR bookSbrNoiseBalanceL11T[25]; + +extern const sbrTuningTable_t sbrTuningTable[]; +extern const int sbrTuningTableSize; + +extern const psTuningTable_t psTuningTable[4]; + + +#endif diff --git a/libSBRenc/src/sbrenc_freq_sca.cpp b/libSBRenc/src/sbrenc_freq_sca.cpp new file mode 100644 index 00000000..30bc5ca1 --- /dev/null +++ b/libSBRenc/src/sbrenc_freq_sca.cpp @@ -0,0 +1,691 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief frequency scale + \author Tobias Chalupka +*/ + +#include "sbrenc_freq_sca.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +/* StartFreq */ +static INT getStartFreq(INT fsCore, const INT start_freq); + +/* StopFreq */ +static INT getStopFreq(INT fsCore, const INT stop_freq); + +static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor); +static void CalcBands(INT * diff, INT start , INT stop , INT num_bands); +static INT modifyBands(INT max_band, INT * diff, INT length); +static void cumSum(INT start_value, INT* diff, INT length, UCHAR *start_adress); + + + +/******************************************************************************* + Functionname: FDKsbrEnc_getSbrStartFreqRAW + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ + +INT +FDKsbrEnc_getSbrStartFreqRAW (INT startFreq, INT fsCore) +{ + INT result; + + if ( startFreq < 0 || startFreq > 15) { + return -1; + } + /* Update startFreq struct */ + result = getStartFreq(fsCore, startFreq); + + result = (result*(fsCore>>5)+1)>>1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); + +} /* End FDKsbrEnc_getSbrStartFreqRAW */ + + +/******************************************************************************* + Functionname: getSbrStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_getSbrStopFreqRAW (INT stopFreq, INT fsCore) +{ + INT result; + + if ( stopFreq < 0 || stopFreq > 13) + return -1; + + /* Uppdate stopFreq struct */ + result = getStopFreq(fsCore, stopFreq); + result = (result*(fsCore>>5)+1)>>1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); +} /* End getSbrStopFreq */ + + +/******************************************************************************* + Functionname: getStartFreq + ******************************************************************************* + Description: + + Arguments: fsCore - core sampling rate + + + Return: + *******************************************************************************/ +static INT +getStartFreq(INT fsCore, const INT start_freq) +{ + INT k0_min; + + switch(fsCore){ + case 8000: k0_min = 24; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 11025: k0_min = 17; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 12000: k0_min = 16; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 16000: k0_min = 16; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 22050: k0_min = 12; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 24000: k0_min = 11; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 32000: k0_min = 10; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 44100: k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 48000: k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 96000: k0_min = 3; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + default: + k0_min=11; /* illegal fs */ + } + + + switch (fsCore) { + + case 8000: + { + INT v_offset[]= {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; + return (k0_min + v_offset[start_freq]); + } + case 11025: + { + INT v_offset[]= {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13}; + return (k0_min + v_offset[start_freq]); + } + case 12000: + { + INT v_offset[]= {-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 16000: + { + INT v_offset[]= {-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 22050: + case 24000: + case 32000: + { + INT v_offset[]= {-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20}; + return (k0_min + v_offset[start_freq]); + } + case 44100: + case 48000: + case 96000: + { + INT v_offset[]= {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24}; + return (k0_min + v_offset[start_freq]); + } + default: + { + INT v_offset[]= {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33}; + return (k0_min + v_offset[start_freq]); + } + } +} /* End getStartFreq */ + + +/******************************************************************************* + Functionname: getStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ + static INT +getStopFreq(INT fsCore, const INT stop_freq) +{ + INT result,i; + INT k1_min; + INT v_dstop[13]; + + INT *v_stop_freq = NULL; + INT v_stop_freq_16[14] = {48,49,50,51,52,54,55,56,57,59,60,61,63,64}; + INT v_stop_freq_22[14] = {35,37,38,40,42,44,46,48,51,53,56,58,61,64}; + INT v_stop_freq_24[14] = {32,34,36,38,40,42,44,46,49,52,55,58,61,64}; + INT v_stop_freq_32[14] = {32,34,36,38,40,42,44,46,49,52,55,58,61,64}; + INT v_stop_freq_44[14] = {23,25,27,29,32,34,37,40,43,47,51,55,59,64}; + INT v_stop_freq_48[14] = {21,23,25,27,30,32,35,38,42,45,49,54,59,64}; + INT v_stop_freq_64[14] = {20,22,24,26,29,31,34,37,41,45,49,54,59,64}; + INT v_stop_freq_88[14] = {15,17,19,21,23,26,29,33,37,41,46,51,57,64}; + INT v_stop_freq_96[14] = {13,15,17,19,21,24,27,31,35,39,44,50,57,64}; + INT v_stop_freq_192[14] = {7, 8,10,12,14,16,19,23,27,32,38,46,54,64}; + + switch(fsCore){ + case 8000: k1_min = 48; + v_stop_freq =v_stop_freq_16; + break; + case 11025: k1_min = 35; + v_stop_freq =v_stop_freq_22; + break; + case 12000: k1_min = 32; + v_stop_freq =v_stop_freq_24; + break; + case 16000: k1_min = 32; + v_stop_freq =v_stop_freq_32; + break; + case 22050: k1_min = 23; + v_stop_freq =v_stop_freq_44; + break; + case 24000: k1_min = 21; + v_stop_freq =v_stop_freq_48; + break; + case 32000: k1_min = 20; + v_stop_freq =v_stop_freq_64; + break; + case 44100: k1_min = 15; + v_stop_freq =v_stop_freq_88; + break; + case 48000: k1_min = 13; + v_stop_freq =v_stop_freq_96; + break; + case 96000: k1_min = 7; + v_stop_freq =v_stop_freq_192; + break; + default: + k1_min = 21; /* illegal fs */ + } + + /* if no valid core samplingrate is used this loop produces + a segfault, because v_stop_freq is not initialized */ + /* Ensure increasing bandwidth */ + for(i = 0; i <= 12; i++) { + v_dstop[i] = v_stop_freq[i+1] - v_stop_freq[i]; + } + + FDKsbrEnc_Shellsort_int(v_dstop, 13); /* Sort bandwidth changes */ + + result = k1_min; + for(i = 0; i < stop_freq; i++) { + result = result + v_dstop[i]; + } + + return(result); + +}/* End getStopFreq */ + + +/******************************************************************************* + Functionname: FDKsbrEnc_FindStartAndStopBand + ******************************************************************************* + Description: + + Arguments: srSbr SBR sampling freqency + srCore AAC core sampling freqency + noChannels Number of QMF channels + startFreq SBR start frequency in QMF bands + stopFreq SBR start frequency in QMF bands + + *k0 Output parameter + *k2 Output parameter + + Return: Error code (0 is OK) + *******************************************************************************/ +INT +FDKsbrEnc_FindStartAndStopBand( + const INT srSbr, + const INT srCore, + const INT noChannels, + const INT startFreq, + const INT stopFreq, + INT *k0, + INT *k2 + ) +{ + + /* Update startFreq struct */ + *k0 = getStartFreq(srCore, startFreq); + + /* Test if start freq is outside corecoder range */ + if( srSbr*noChannels < *k0 * srCore ) { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling frequency) */ + } + + /*Update stopFreq struct */ + if ( stopFreq < 14 ) { + *k2 = getStopFreq(srCore, stopFreq); + } else if( stopFreq == 14 ) { + *k2 = 2 * *k0; + } else { + *k2 = 3 * *k0; + } + + /* limit to Nyqvist */ + if (*k2 > noChannels) { + *k2 = noChannels; + } + + + + /* Test for invalid k0 k2 combinations */ + if ( (srCore == 22050) && ( (*k2 - *k0) > MAX_FREQ_COEFFS_FS44100 ) ) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for fs=44.1kHz */ + + if ( (srCore >= 24000) && ( (*k2 - *k0) > MAX_FREQ_COEFFS_FS48000 ) ) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for fs>=48kHz */ + + if ((*k2 - *k0) > MAX_FREQ_COEFFS) + return (1);/*Number of bands exceeds valid range of MAX_FREQ_COEFFS */ + + if ((*k2 - *k0) < 0) + return (1);/* Number of bands is negative */ + + + return(0); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateFreqScale + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT +FDKsbrEnc_UpdateFreqScale( + UCHAR *v_k_master, + INT *h_num_bands, + const INT k0, + const INT k2, + const INT freqScale, + const INT alterScale + ) + +{ + + INT b_p_o = 0; /* bands_per_octave */ + FIXP_DBL warp = FL2FXCONST_DBL(0.0f); + INT dk = 0; + + /* Internal variables */ + INT k1 = 0, i; + INT num_bands0; + INT num_bands1; + INT diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + INT *diff0 = diff_tot; + INT *diff1 = diff_tot+MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; + + /* Init */ + if (freqScale==1) b_p_o = 12; + if (freqScale==2) b_p_o = 10; + if (freqScale==3) b_p_o = 8; + + + if(freqScale > 0) /*Bark*/ + { + if(alterScale==0) + warp = FL2FXCONST_DBL(0.5f); /* 1.0/(1.0*2.0) */ + else + warp = FL2FXCONST_DBL(1.0f/2.6f); /* 1.0/(1.3*2.0); */ + + + if(4*k2 >= 9*k0) /*two or more regions (how many times the basis band is copied)*/ + { + k1=2*k0; + + num_bands0=numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + num_bands1=numberOfBands(b_p_o, k1, k2, warp); + + CalcBands(diff0, k0, k1, num_bands0);/*CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int( diff0, num_bands0);/*SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1);/* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */ + + CalcBands(diff1, k1, k2, num_bands1); /* CalcBands2 => diff1 */ + FDKsbrEnc_Shellsort_int( diff1, num_bands1); /* SortBands sort diff1 */ + if(diff0[num_bands0-1] > diff1[0]) /* max(1) > min(2) */ + { + if(modifyBands(diff0[num_bands0-1],diff1, num_bands1)) + return(1); + } + + /* Add 2'nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *h_num_bands=num_bands0+num_bands1; /* Output nr of bands */ + + } + else /* one region */ + { + k1=k2; + + num_bands0=numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + CalcBands(diff0, k0, k1, num_bands0);/* CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int( diff0, num_bands0); /* SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master);/* cumsum */ + *h_num_bands=num_bands0; /* Output nr of bands */ + + } + } + else /* Linear mode */ + { + if (alterScale==0) { + dk = 1; + num_bands0 = 2 * ((k2 - k0)/2); /* FLOOR to get to few number of bands*/ + } else { + dk = 2; + num_bands0 = 2 * (((k2 - k0)/dk +1)/2); /* ROUND to get closest fit */ + } + + k2_achived = k0 + num_bands0*dk; + k2_diff = k2 - k2_achived; + + for(i=0;i 0) { + incr = -1; + i = num_bands0-1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master);/* cumsum */ + *h_num_bands=num_bands0; /* Output nr of bands */ + + } + + if (*h_num_bands < 1) + return(1); /*To small sbr area */ + + return (0); +}/* End FDKsbrEnc_UpdateFreqScale */ + +static INT +numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor) +{ + INT result=0; + /* result = 2* (INT) ( (double)b_p_o * (double)(FDKlog((double)stop/(double)start)/FDKlog((double)2)) * (double)FX_DBL2FL(warp_factor) + 0.5); */ + result = ( ( b_p_o * fMult( (CalcLdInt(stop) - CalcLdInt(start)), warp_factor) + (FL2FX_DBL(0.5f)>>LD_DATA_SHIFT) + ) >> ((DFRACT_BITS-1)-LD_DATA_SHIFT) ) << 1; /* do not optimize anymore (rounding!!) */ + + return(result); +} + + +static void +CalcBands(INT * diff, INT start , INT stop , INT num_bands) +{ + INT i, qb, qe, qtmp; + INT previous; + INT current; + FIXP_DBL base, exp, tmp; + + previous=start; + for(i=1; i<= num_bands; i++) + { + base = fDivNorm((FIXP_DBL)stop, (FIXP_DBL)start, &qb); + exp = fDivNorm((FIXP_DBL)i, (FIXP_DBL)num_bands, &qe); + tmp = fPow(base, qb, exp, qe, &qtmp); + tmp = fMult(tmp, (FIXP_DBL)(start<<24)); + current = (INT)scaleValue(tmp, qtmp-23); + current = (current+1) >> 1; /* rounding*/ + diff[i-1] = current-previous; + previous = current; + } + +}/* End CalcBands */ + + +static void +cumSum(INT start_value, INT* diff, INT length, UCHAR *start_adress) +{ + INT i; + start_adress[0]=start_value; + for(i=1;i<=length;i++) + start_adress[i]=start_adress[i-1]+diff[i-1]; +} /* End cumSum */ + + +static INT +modifyBands(INT max_band_previous, INT * diff, INT length) +{ + INT change=max_band_previous-diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first one */ + if ( change > (diff[length-1] - diff[0]) / 2 ) + change = (diff[length-1] - diff[0]) / 2; + + diff[0] += change; + diff[length-1] -= change; + FDKsbrEnc_Shellsort_int(diff, length); + + return(0); +}/* End modifyBands */ + + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateHiRes + ******************************************************************************* + Description: + + + Arguments: + + Return: + *******************************************************************************/ +INT +FDKsbrEnc_UpdateHiRes( + UCHAR *h_hires, + INT *num_hires, + UCHAR *v_k_master, + INT num_master, + INT *xover_band + ) +{ + INT i; + INT max1,max2; + + if( (v_k_master[*xover_band] > 32 ) || /* v_k_master[*xover_band] > noQMFChannels(dualRate)/divider */ + ( *xover_band > num_master ) ) { + /* xover_band error, too big for this startFreq. Will be clipped */ + + /* Calculate maximum value for xover_band */ + max1=0; + max2=num_master; + while( (v_k_master[max1+1] < 32 ) && /* noQMFChannels(dualRate)/divider */ + ( (max1+1) < max2) ) + { + max1++; + } + + *xover_band=max1; + } + + *num_hires = num_master - *xover_band; + for(i = *xover_band; i <= num_master; i++) + { + h_hires[i - *xover_band] = v_k_master[i]; + } + + return (0); +}/* End FDKsbrEnc_UpdateHiRes */ + + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateLoRes + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +void +FDKsbrEnc_UpdateLoRes(UCHAR * h_lores, INT *num_lores, UCHAR * h_hires, INT num_hires) +{ + INT i; + + if(num_hires%2 == 0) /* if even number of hires bands */ + { + *num_lores=num_hires/2; + /* Use every second lores=hires[0,2,4...] */ + for(i=0;i<=*num_lores;i++) + h_lores[i]=h_hires[i*2]; + + } + else /* odd number of hires which means xover is odd */ + { + *num_lores=(num_hires+1)/2; + + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0]=h_hires[0]; + for(i=1;i<=*num_lores;i++) + { + h_lores[i]=h_hires[i*2-1]; + } + } + +}/* End FDKsbrEnc_UpdateLoRes */ diff --git a/libSBRenc/src/sbrenc_freq_sca.h b/libSBRenc/src/sbrenc_freq_sca.h new file mode 100644 index 00000000..6f2bb847 --- /dev/null +++ b/libSBRenc/src/sbrenc_freq_sca.h @@ -0,0 +1,137 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief frequency scale prototypes +*/ +#ifndef __FREQ_SCA2_H +#define __FREQ_SCA2_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + + +INT +FDKsbrEnc_UpdateFreqScale( + UCHAR *v_k_master, + INT *h_num_bands, + const INT k0, + const INT k2, + const INT freq_scale, + const INT alter_scale + ); + +INT +FDKsbrEnc_UpdateHiRes( + UCHAR *h_hires, + INT *num_hires, + UCHAR *v_k_master, + INT num_master, + INT *xover_band + ); + +void FDKsbrEnc_UpdateLoRes( + UCHAR *v_lores, + INT *num_lores, + UCHAR *v_hires, + INT num_hires + ); + +INT +FDKsbrEnc_FindStartAndStopBand( + const INT srSbr, + const INT srCore, + const INT noChannels, + const INT startFreq, + const INT stop_freq, + INT *k0, + INT *k2 + ); + +INT FDKsbrEnc_getSbrStartFreqRAW (INT startFreq, INT fsCore); +INT FDKsbrEnc_getSbrStopFreqRAW (INT stopFreq, INT fsCore); +#endif diff --git a/libSBRenc/src/ton_corr.cpp b/libSBRenc/src/ton_corr.cpp new file mode 100644 index 00000000..af5afbaf --- /dev/null +++ b/libSBRenc/src/ton_corr.cpp @@ -0,0 +1,881 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "ton_corr.h" + +#include "sbr_ram.h" +#include "sbr_misc.h" +#include "genericStds.h" +#include "autocorr2nd.h" + + + +/*************************************************************************** + + Send autoCorrSecondOrder to mlfile + +****************************************************************************/ + +/**************************************************************************/ +/*! + \brief Calculates the tonal to noise ration for different frequency bands + and time segments. + + The ratio between the predicted energy (tonal energy A) and the total + energy (A + B) is calculated. This is converted to the ratio between + the predicted energy (tonal energy A) and the non-predictable energy + (noise energy B). Hence the quota-matrix contains A/B = q/(1-q). + + The samples in nrgVector are scaled by 1.0/16.0 + The samples in pNrgVectorFreq are scaled by 1.0/2.0 + The samples in quotaMatrix are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ + +void +FDKsbrEnc_CalculateTonalityQuotas( HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + FIXP_DBL **RESTRICT sourceBufferReal, /*!< The real part of the QMF-matrix. */ + FIXP_DBL **RESTRICT sourceBufferImag, /*!< The imaginary part of the QMF-matrix. */ + INT usb, /*!< upper side band, highest + 1 QMF band in the SBR range. */ + INT qmfScale /*!< sclefactor of QMF subsamples */ + ) +{ + INT i, k, r, r2, timeIndex, autoCorrScaling; + + INT startIndexMatrix = hTonCorr->startIndexMatrix; + INT totNoEst = hTonCorr->numberOfEstimates; + INT noEstPerFrame = hTonCorr->numberOfEstimatesPerFrame; + INT move = hTonCorr->move; + INT noQmfChannels = hTonCorr->noQmfChannels; /* Numer of Bands */ + INT buffLen = hTonCorr->bufferLength; /* Numer of Slots */ + INT stepSize = hTonCorr->stepSize; + INT *pBlockLength = hTonCorr->lpcLength; + INT** RESTRICT signMatrix = hTonCorr->signMatrix; + FIXP_DBL* RESTRICT nrgVector = hTonCorr->nrgVector; + FIXP_DBL** RESTRICT quotaMatrix = hTonCorr->quotaMatrix; + FIXP_DBL* RESTRICT pNrgVectorFreq = hTonCorr->nrgVectorFreq; + +#define BAND_V_SIZE QMF_MAX_TIME_SLOTS +#define NUM_V_COMBINE 8 /* Must be a divisor of 64 and fulfill the ASSERTs below */ + + FIXP_DBL *realBuf; + FIXP_DBL *imagBuf; + + FIXP_DBL alphar[2],alphai[2],fac; + + C_ALLOC_SCRATCH_START(ac, ACORR_COEFS, 1); + C_ALLOC_SCRATCH_START(realBufRef, FIXP_DBL, 2*BAND_V_SIZE*NUM_V_COMBINE); + + realBuf = realBufRef; + imagBuf = realBuf + BAND_V_SIZE*NUM_V_COMBINE; + + + FDK_ASSERT(buffLen <= BAND_V_SIZE); + FDK_ASSERT(sizeof(FIXP_DBL)*NUM_V_COMBINE*BAND_V_SIZE*2 < (1024*sizeof(FIXP_DBL)-sizeof(ACORR_COEFS)) ); + + /* + * Buffering of the quotaMatrix and the quotaMatrixTransp. + *********************************************************/ + for(i = 0 ; i < move; i++){ + FDKmemcpy(quotaMatrix[i],quotaMatrix[i + noEstPerFrame],noQmfChannels * sizeof(FIXP_DBL)); + FDKmemcpy(signMatrix[i],signMatrix[i + noEstPerFrame],noQmfChannels * sizeof(INT)); + } + + FDKmemmove(nrgVector,nrgVector+noEstPerFrame,move*sizeof(FIXP_DBL)); + FDKmemclear(nrgVector+startIndexMatrix,(totNoEst-startIndexMatrix)*sizeof(FIXP_DBL)); + FDKmemclear(pNrgVectorFreq,noQmfChannels * sizeof(FIXP_DBL)); + + /* + * Calculate the quotas for the current time steps. + **************************************************/ + + for (r = 0; r < usb; r++) + { + int blockLength; + + k = hTonCorr->nextSample; /* startSample */ + timeIndex = startIndexMatrix; + /* Copy as many as possible Band accross all Slots at once */ + if (realBuf != realBufRef) { + realBuf -= BAND_V_SIZE; + imagBuf -= BAND_V_SIZE; + } else { + realBuf += BAND_V_SIZE*(NUM_V_COMBINE-1); + imagBuf += BAND_V_SIZE*(NUM_V_COMBINE-1); + for (i = 0; i < buffLen; i++) { + int v; + FIXP_DBL *ptr; + ptr = realBuf+i; + for (v=0; vdet == FL2FXCONST_DBL(0.0f)){ + alphar[1] = alphai[1] = FL2FXCONST_DBL(0.0f); + + alphar[0] = (ac->r01r)>>2; + alphai[0] = (ac->r01i)>>2; + + fac = fMultDiv2(ac->r00r, ac->r11r)>>1; + } + else{ + alphar[1] = (fMultDiv2(ac->r01r, ac->r12r)>>1) - (fMultDiv2(ac->r01i, ac->r12i)>>1) - (fMultDiv2(ac->r02r, ac->r11r)>>1); + alphai[1] = (fMultDiv2(ac->r01i, ac->r12r)>>1) + (fMultDiv2(ac->r01r, ac->r12i)>>1) - (fMultDiv2(ac->r02i, ac->r11r)>>1); + + alphar[0] = (fMultDiv2(ac->r01r, ac->det)>>(ac->det_scale+1)) + fMult(alphar[1], ac->r12r) + fMult(alphai[1], ac->r12i); + alphai[0] = (fMultDiv2(ac->r01i, ac->det)>>(ac->det_scale+1)) + fMult(alphai[1], ac->r12r) - fMult(alphar[1], ac->r12i); + + fac = fMultDiv2(ac->r00r, fMult(ac->det, ac->r11r))>>(ac->det_scale+1); + } + + if(fac == FL2FXCONST_DBL(0.0f)){ + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + signMatrix[timeIndex][r] = 0; + } + else { + /* quotaMatrix is scaled with the factor RELAXATION + parse RELAXATION in fractional part and shift factor: 1/(1/0.524288 * 2^RELAXATION_SHIFT) */ + FIXP_DBL tmp,num,denom; + INT numShift,denomShift,commonShift; + INT sign; + + num = fMultDiv2(alphar[0], ac->r01r) + fMultDiv2(alphai[0], ac->r01i) - fMultDiv2(alphar[1], fMult(ac->r02r, ac->r11r)) - fMultDiv2(alphai[1], fMult(ac->r02i, ac->r11r)); + num = fixp_abs(num); + + denom = (fac>>1) + (fMultDiv2(fac,RELAXATION_FRACT)>>RELAXATION_SHIFT) - num; + denom = fixp_abs(denom); + + num = fMult(num,RELAXATION_FRACT); + + numShift = CountLeadingBits(num) - 2; + num = scaleValue(num, numShift); + + denomShift = CountLeadingBits(denom); + denom = (FIXP_DBL)denom << denomShift; + + if ((num > FL2FXCONST_DBL(0.0f)) && (denom != FL2FXCONST_DBL(0.0f))) { + commonShift = fixMin(numShift - denomShift + RELAXATION_SHIFT, DFRACT_BITS-1); + if (commonShift < 0) { + commonShift = -commonShift; + tmp = schur_div(num,denom,16); + commonShift = fixMin(commonShift,CountLeadingBits(tmp)); + quotaMatrix[timeIndex][r] = tmp << commonShift; + } + else { + quotaMatrix[timeIndex][r] = schur_div(num,denom,16) >> commonShift; + } + } + else { + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + } + + if (ac->r11r != FL2FXCONST_DBL(0.0f)) { + if ( ( (ac->r01r >= FL2FXCONST_DBL(0.0f) ) && ( ac->r11r >= FL2FXCONST_DBL(0.0f) ) ) + ||( (ac->r01r < FL2FXCONST_DBL(0.0f) ) && ( ac->r11r < FL2FXCONST_DBL(0.0f) ) ) ) { + sign = 1; + } + else { + sign = -1; + } + } + else { + sign = 1; + } + + if(sign < 0) { + r2 = r; /* (INT) pow(-1, band); */ + } + else { + r2 = r + 1; /* (INT) pow(-1, band+1); */ + } + signMatrix[timeIndex][r] = 1 - 2*(r2 & 0x1); + } + + nrgVector[timeIndex] += ((ac->r00r) >> fixMin(DFRACT_BITS-1,(2*qmfScale+autoCorrScaling + SCALE_NRGVEC))); + /* pNrgVectorFreq[r] finally has to be divided by noEstPerFrame, replaced division by shifting with one */ + pNrgVectorFreq[r] = pNrgVectorFreq[r] + ((ac->r00r) >> fixMin(DFRACT_BITS-1,(2*qmfScale+autoCorrScaling + SCALE_NRGVEC))); + + blockLength = pBlockLength[1]; + k += stepSize; + timeIndex++; + } + } + + + C_ALLOC_SCRATCH_END(realBuf, FIXP_DBL, 2*BAND_V_SIZE*NUM_V_COMBINE); + C_ALLOC_SCRATCH_END(ac, ACORR_COEFS, 1); +} + +/**************************************************************************/ +/*! + \brief Extracts the parameters required in the decoder to obtain the + correct tonal to noise ratio after SBR. + + Estimates the tonal to noise ratio of the original signal (using LPC). + Predicts the tonal to noise ration of the SBR signal (in the decoder) by + patching the tonal to noise ratio values similar to the patching of the + lowband in the decoder. Given the tonal to noise ratio of the original + and the SBR signal, it estimates the required amount of inverse filtering, + additional noise as well as any additional sines. + + \return none. + +*/ +/**************************************************************************/ +void +FDKsbrEnc_TonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr,/*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE* infVec, /*!< Vector where the inverse filtering levels will be stored. */ + FIXP_DBL * noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT* missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any strong sines are missing.*/ + UCHAR * missingHarmonicsIndex, /*!< Vector indicating where sines are missing. */ + UCHAR * envelopeCompensation, /*!< Vector to store compensation values for the energies in. */ + const SBR_FRAME_INFO *frameInfo, /*!< Frame info struct, contains the time and frequency grid of the current frame.*/ + UCHAR* transientInfo, /*!< Transient info.*/ + UCHAR* freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags + ) +{ + INT band; + INT transientFlag = transientInfo[1] ; /*!< Flag indicating if a transient is present in the current frame. */ + INT transientPos = transientInfo[0]; /*!< Position of the transient.*/ + INT transientFrame, transientFrameInvfEst; + INVF_MODE* infVecPtr; + + + /* Determine if this is a frame where a transient starts... + + The detection of noise-floor, missing harmonics and invf_est, is not in sync for the + non-buf-opt decoder such as AAC. Hence we need to keep track on the transient in the + present frame as well as in the next. + */ + transientFrame = 0; + if(hTonCorr->transientNextFrame){ /* The transient was detected in the previous frame, but is actually */ + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + + if(transientFlag){ + if(transientPos + hTonCorr->transientPosOffset >= frameInfo->borders[frameInfo->nEnvelopes]){ + hTonCorr->transientNextFrame = 1; + } + } + } + else{ + if(transientFlag){ + if(transientPos + hTonCorr->transientPosOffset < frameInfo->borders[frameInfo->nEnvelopes]){ + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + } + else{ + hTonCorr->transientNextFrame = 1; + } + } + } + transientFrameInvfEst = transientFrame; + + + /* + Estimate the required invese filtereing level. + */ + if (hTonCorr->switchInverseFilt) + FDKsbrEnc_qmfInverseFilteringDetector(&hTonCorr->sbrInvFilt, + hTonCorr->quotaMatrix, + hTonCorr->nrgVector, + hTonCorr->indexVector, + hTonCorr->frameStartIndexInvfEst, + hTonCorr->numberOfEstimatesPerFrame + hTonCorr->frameStartIndexInvfEst, + transientFrameInvfEst, + infVec); + + /* + Detect what tones will be missing. + */ + if (xposType == XPOS_LC ){ + FDKsbrEnc_SbrMissingHarmonicsDetectorQmf(&hTonCorr->sbrMissingHarmonicsDetector, + hTonCorr->quotaMatrix, + hTonCorr->signMatrix, + hTonCorr->indexVector, + frameInfo, + transientInfo, + missingHarmonicFlag, + missingHarmonicsIndex, + freqBandTable, + nSfb, + envelopeCompensation, + hTonCorr->nrgVectorFreq); + } + else{ + *missingHarmonicFlag = 0; + FDKmemclear(missingHarmonicsIndex,nSfb*sizeof(UCHAR)); + } + + + + /* + Noise floor estimation + */ + + infVecPtr = hTonCorr->sbrInvFilt.prevInvfMode; + + FDKsbrEnc_sbrNoiseFloorEstimateQmf(&hTonCorr->sbrNoiseFloorEstimate, + frameInfo, + noiseLevels, + hTonCorr->quotaMatrix, + hTonCorr->indexVector, + *missingHarmonicFlag, + hTonCorr->frameStartIndex, + hTonCorr->numberOfEstimatesPerFrame, + transientFrame, + infVecPtr, + sbrSyntaxFlags); + + + /* Store the invfVec data for the next frame...*/ + for(band = 0 ; band < hTonCorr->sbrInvFilt.noDetectorBands; band++){ + hTonCorr->sbrInvFilt.prevInvfMode[band] = infVec[band]; + } +} + +/**************************************************************************/ +/*! + \brief Searches for the closest match in the frequency master table. + + + + \return closest entry. + +*/ +/**************************************************************************/ +static INT +findClosestEntry(INT goalSb, + UCHAR *v_k_master, + INT numMaster, + INT direction) +{ + INT index; + + if( goalSb <= v_k_master[0] ) + return v_k_master[0]; + + if( goalSb >= v_k_master[numMaster] ) + return v_k_master[numMaster]; + + if(direction) { + index = 0; + while( v_k_master[index] < goalSb ) { + index++; + } + } else { + index = numMaster; + while( v_k_master[index] > goalSb ) { + index--; + } + } + + return v_k_master[index]; +} + + +/**************************************************************************/ +/*! + \brief resets the patch + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +static INT +resetPatch(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency. */ + INT noChannels) /*!< Number of QMF-channels. */ +{ + INT patch,k,i; + INT targetStopBand; + + PATCH_PARAM *patchParam = hTonCorr->patchParam; + + INT sbGuard = hTonCorr->guard; + INT sourceStartBand; + INT patchDistance; + INT numBandsInPatch; + + INT lsb = v_k_master[0]; /* Lowest subband related to the synthesis filterbank */ + INT usb = v_k_master[numMaster]; /* Stop subband related to the synthesis filterbank */ + INT xoverOffset = highBandStartSb - v_k_master[0]; /* Calculate distance in subbands between k0 and kx */ + + INT goalSb; + + + /* + * Initialize the patching parameter + */ + + if (xposctrl == 1) { + lsb += xoverOffset; + xoverOffset = 0; + } + + goalSb = (INT)( (2 * noChannels * 16000 + (fs>>1)) / fs ); /* 16 kHz band */ + goalSb = findClosestEntry(goalSb, v_k_master, numMaster, 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = hTonCorr->shiftStartSb + xoverOffset; + targetStopBand = lsb + xoverOffset; + + /* even (odd) numbered channel must be patched to even (odd) numbered channel */ + patch = 0; + while(targetStopBand < usb) { + + /* To many patches */ + if (patch >= MAX_NUM_PATCHES) + return(1); /*Number of patches to high */ + + patchParam[patch].guardStartBand = targetStopBand; + targetStopBand += sbGuard; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = goalSb - targetStopBand; /* get the desired range of the patch */ + + if ( numBandsInPatch >= lsb - sourceStartBand ) { + /* desired number bands are not available -> patch whole source range */ + patchDistance = targetStopBand - sourceStartBand; /* get the targetOffset */ + patchDistance = patchDistance & ~1; /* rounding off odd numbers and make all even */ + numBandsInPatch = lsb - (targetStopBand - patchDistance); + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + /* desired number bands are available -> get the minimal even patching distance */ + patchDistance = numBandsInPatch + targetStopBand - lsb; /* get minimal distance */ + patchDistance = (patchDistance + 1) & ~1; /* rounding up odd numbers and make all even */ + + if (numBandsInPatch <= 0) { + patch--; + } else { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + } + + /* All patches but first */ + sourceStartBand = hTonCorr->shiftStartSb; + + /* Check if we are close to goalSb */ + if( fixp_abs(targetStopBand - goalSb) < 3) { + goalSb = usb; + } + + patch++; + + } + + patch--; + + /* if highest patch contains less than three subband: skip it */ + if ( patchParam[patch].numBandsInPatch < 3 && patch > 0 ) { + patch--; + targetStopBand = patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; + } + + hTonCorr->noOfPatches = patch + 1; + + + /* Assign the index-vector, so we know where to look for the high-band. + -1 represents a guard-band. */ + for(k = 0; k < hTonCorr->patchParam[0].guardStartBand; k++) + hTonCorr->indexVector[k] = k; + + for(i = 0; i < hTonCorr->noOfPatches; i++) + { + INT sourceStart = hTonCorr->patchParam[i].sourceStartBand; + INT targetStart = hTonCorr->patchParam[i].targetStartBand; + INT numberOfBands = hTonCorr->patchParam[i].numBandsInPatch; + INT startGuardBand = hTonCorr->patchParam[i].guardStartBand; + + for(k = 0; k < (targetStart- startGuardBand); k++) + hTonCorr->indexVector[startGuardBand+k] = -1; + + for(k = 0; k < numberOfBands; k++) + hTonCorr->indexVector[targetStart+k] = sourceStart+k; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Creates an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT +FDKsbrEnc_CreateTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan) /*!< Channel index, needed for mem allocation */ +{ + INT i; + FIXP_DBL* quotaMatrix = GetRam_Sbr_quotaMatrix(chan); + INT* signMatrix = GetRam_Sbr_signMatrix(chan); + + FDKmemclear(hTonCorr, sizeof(SBR_TON_CORR_EST)); + + for (i=0; iquotaMatrix[i] = quotaMatrix + (i*QMF_CHANNELS); + hTonCorr->signMatrix[i] = signMatrix + (i*QMF_CHANNELS); + } + + FDKsbrEnc_CreateSbrMissingHarmonicsDetector (&hTonCorr->sbrMissingHarmonicsDetector, chan); + + return 0; +} + + + +/**************************************************************************/ +/*! + \brief Initialize an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT +FDKsbrEnc_InitTonCorrParamExtr (INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig) /*!< Speech or music tuning. */ +{ + INT nCols = sbrCfg->noQmfSlots; + INT fs = sbrCfg->sampleFreq; + INT noQmfChannels = sbrCfg->noQmfBands; + + INT highBandStartSb = sbrCfg->freqBandTable[LOW_RES][0]; + UCHAR *v_k_master = sbrCfg->v_k_master; + INT numMaster = sbrCfg->num_Master; + + UCHAR **freqBandTable = sbrCfg->freqBandTable; + INT *nSfb = sbrCfg->nSfb; + + INT i; + + /* + Reset the patching and allocate memory for the quota matrix. + Assuming parameters for the LPC analysis. + */ + if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + switch (timeSlots) { + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 7 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 8 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + } + } else + switch (timeSlots) { + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 16; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 15; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + break; + default: + return -1; + } + + hTonCorr->bufferLength = nCols; + hTonCorr->stepSize = hTonCorr->lpcLength[0] + LPC_ORDER; /* stepSize[0] implicitly 0. */ + + hTonCorr->nextSample = LPC_ORDER; /* firstSample */ + hTonCorr->move = hTonCorr->numberOfEstimates - hTonCorr->numberOfEstimatesPerFrame; /* Number of estimates to move when buffering.*/ + hTonCorr->startIndexMatrix = hTonCorr->numberOfEstimates - hTonCorr->numberOfEstimatesPerFrame; /* Where to store the latest estimations in the tonality Matrix.*/ + hTonCorr->frameStartIndex = 0; /* Where in the tonality matrix the current frame (to be sent to the decoder) starts. */ + hTonCorr->prevTransientFlag = 0; + hTonCorr->transientNextFrame = 0; + + hTonCorr->noQmfChannels = noQmfChannels; + + for (i=0; inumberOfEstimates; i++) { + FDKmemclear (hTonCorr->quotaMatrix[i] , sizeof(FIXP_DBL)*noQmfChannels); + FDKmemclear (hTonCorr->signMatrix[i] , sizeof(INT)*noQmfChannels); + } + + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if(resetPatch(hTonCorr, + xposCtrl, + highBandStartSb, + v_k_master, + numMaster, + fs, + noQmfChannels)) + return(1); + + if(FDKsbrEnc_InitSbrNoiseFloorEstimate (&hTonCorr->sbrNoiseFloorEstimate, + ana_max_level, + freqBandTable[LO], + nSfb[LO], + noiseBands, + noiseFloorOffset, + timeSlots, + useSpeechConfig)) + return(1); + + + if(FDKsbrEnc_initInvFiltDetector(&hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands, + useSpeechConfig)) + return(1); + + + + if(FDKsbrEnc_InitSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, + fs, + frameSize, + nSfb[HI], + noQmfChannels, + hTonCorr->numberOfEstimates, + hTonCorr->move, + hTonCorr->numberOfEstimatesPerFrame, + sbrCfg->sbrSyntaxFlags)) + return(1); + + + + return (0); +} + + + +/**************************************************************************/ +/*! + \brief resets tonality correction parameter module. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT +FDKsbrEnc_ResetTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR ** freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT* nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ + ) +{ + + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if(resetPatch(hTonCorr, + xposctrl, + highBandStartSb, + v_k_master, + numMaster, + fs, + noQmfChannels)) + return(1); + + + + /* Reset the noise floor estimate.*/ + if(FDKsbrEnc_resetSbrNoiseFloorEstimate (&hTonCorr->sbrNoiseFloorEstimate, + freqBandTable[LO], + nSfb[LO])) + return(1); + + /* + Reset the inveerse filtereing detector. + */ + if(FDKsbrEnc_resetInvFiltDetector(&hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands)) + return(1); +/* Reset the missing harmonics detector. */ + if(FDKsbrEnc_ResetSbrMissingHarmonicsDetector (&hTonCorr->sbrMissingHarmonicsDetector, + nSfb[HI])) + return(1); + + return (0); +} + + + + + +/**************************************************************************/ +/*! + \brief Deletes the tonality correction paramtere module. + + + + \return none + +*/ +/**************************************************************************/ +void +FDKsbrEnc_DeleteTonCorrParamExtr (HANDLE_SBR_TON_CORR_EST hTonCorr) /*!< Handle to SBR_TON_CORR struct. */ +{ + + if (hTonCorr) { + + FreeRam_Sbr_quotaMatrix(hTonCorr->quotaMatrix); + + FreeRam_Sbr_signMatrix(hTonCorr->signMatrix); + + FDKsbrEnc_DeleteSbrMissingHarmonicsDetector (&hTonCorr->sbrMissingHarmonicsDetector); + } +} diff --git a/libSBRenc/src/ton_corr.h b/libSBRenc/src/ton_corr.h new file mode 100644 index 00000000..504ab03f --- /dev/null +++ b/libSBRenc/src/ton_corr.h @@ -0,0 +1,212 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief General tonality correction detector module. +*/ +#ifndef _TON_CORR_EST_H +#define _TON_CORR_EST_H + +#include "sbr_encoder.h" +#include "mh_det.h" +#include "nf_est.h" +#include "invf_est.h" + + +#define MAX_NUM_PATCHES 6 +#define SCALE_NRGVEC 4 + +/** parameter set for one single patch */ +typedef struct { + INT sourceStartBand; /*!< first band in lowbands where to take the samples from */ + INT sourceStopBand; /*!< first band in lowbands which is not included in the patch anymore */ + INT guardStartBand; /*!< first band in highbands to be filled with zeros in order to + reduce interferences between patches */ + INT targetStartBand; /*!< first band in highbands to be filled with whitened lowband signal */ + INT targetBandOffs; /*!< difference between 'startTargetBand' and 'startSourceBand' */ + INT numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + + + + +typedef struct +{ + INT switchInverseFilt; /*!< Flag to enable dynamic adaption of invf. detection */ + INT noQmfChannels; + INT bufferLength; /*!< Length of the r and i buffers. */ + INT stepSize; /*!< Stride for the lpc estimate. */ + INT numberOfEstimates; /*!< The total number of estiamtes, available in the quotaMatrix.*/ + UINT numberOfEstimatesPerFrame; /*!< The number of estimates per frame available in the quotaMatrix.*/ + INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/ + INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/ + INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. */ + INT frameStartIndex; /*!< The start index for the current frame in the r and i buffers. */ + INT startIndexMatrix; /*!< The start index for the current frame in the quotaMatrix. */ + INT frameStartIndexInvfEst; /*!< The start index of the inverse filtering, not the same as the others, + dependent on what decoder is used (buffer opt, or no buffer opt). */ + INT prevTransientFlag; /*!< The transisent flag (from the transient detector) for the previous frame. */ + INT transientNextFrame; /*!< Flag to indicate that the transient will show up in the next frame. */ + INT transientPosOffset; /*!< An offset value to match the transient pos as calculated by the transient detector + with the actual position in the frame.*/ + + INT *signMatrix[MAX_NO_OF_ESTIMATES]; /*!< Matrix holding the sign of each channe, i.e. indicating in what + part of a QMF channel a possible sine is. */ + + FIXP_DBL *quotaMatrix[MAX_NO_OF_ESTIMATES];/*!< Matrix holding the quota values for all estimates, all channels. */ + + FIXP_DBL nrgVector[MAX_NO_OF_ESTIMATES]; /*!< Vector holding the averaged energies for every QMF band. */ + FIXP_DBL nrgVectorFreq[QMF_CHANNELS]; /*!< Vector holding the averaged energies for every QMF channel */ + + SCHAR indexVector[QMF_CHANNELS]; /*!< Index vector poINTing to the correct lowband channel, + when indexing a highband channel, -1 represents a guard band */ + PATCH_PARAM patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + INT guard; /*!< number of guardbands between every patch */ + INT shiftStartSb; /*!< lowest subband of source range to be included in the patches */ + INT noOfPatches; /*!< number of patches */ + + SBR_MISSING_HARMONICS_DETECTOR sbrMissingHarmonicsDetector; /*!< SBR_MISSING_HARMONICS_DETECTOR struct. */ + SBR_NOISE_FLOOR_ESTIMATE sbrNoiseFloorEstimate; /*!< SBR_NOISE_FLOOR_ESTIMATE struct. */ + SBR_INV_FILT_EST sbrInvFilt; /*!< SBR_INV_FILT_EST struct. */ +} +SBR_TON_CORR_EST; + +typedef SBR_TON_CORR_EST *HANDLE_SBR_TON_CORR_EST; + +void +FDKsbrEnc_TonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE* infVec, /*!< Vector where the inverse filtering levels will be stored. */ + FIXP_DBL * noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT* missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any strong sines are missing.*/ + UCHAR* missingHarmonicsIndex, /*!< Vector indicating where sines are missing. */ + UCHAR* envelopeCompensation, /*!< Vector to store compensation values for the energies in. */ + const SBR_FRAME_INFO *frameInfo, /*!< Frame info struct, contains the time and frequency grid of the current frame.*/ + UCHAR* transientInfo, /*!< Transient info.*/ + UCHAR * freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags + ); + +INT +FDKsbrEnc_CreateTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan); /*!< Channel index, needed for mem allocation */ + +INT +FDKsbrEnc_InitTonCorrParamExtr(INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig /*!< Speech or music tuning. */ + ); + +void +FDKsbrEnc_DeleteTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr); /*!< Handle to SBR_TON_CORR struct. */ + + +void +FDKsbrEnc_CalculateTonalityQuotas(HANDLE_SBR_TON_CORR_EST hTonCorr, + FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + INT usb, + INT qmfScale /*!< sclefactor of QMF subsamples */ + ); + +INT +FDKsbrEnc_ResetTonCorrParamExtr(HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR** freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT* nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ + ); +#endif + diff --git a/libSBRenc/src/tran_det.cpp b/libSBRenc/src/tran_det.cpp new file mode 100644 index 00000000..0e35ec34 --- /dev/null +++ b/libSBRenc/src/tran_det.cpp @@ -0,0 +1,1069 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +#include "tran_det.h" + +#include "fram_gen.h" +#include "sbr_ram.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */ + +/* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */ +#define ABS_THRES ((FIXP_DBL)16) + +/******************************************************************************* + Functionname: spectralChange + ******************************************************************************* + \brief Calculates a measure for the spectral change within the frame + + The function says how good it would be to split the frame at the given border + position into 2 envelopes. + + The return value delta_sum is scaled with the factor 1/64 + + \return calculated value +*******************************************************************************/ +#define NRG_SHIFT 3 /* for energy summation */ + +static FIXP_DBL spectralChange(FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], + INT *scaleEnergies, + FIXP_DBL EnergyTotal, + INT nSfb, + INT start, + INT border, + INT YBufferWriteOffset, + INT stop, + INT *result_e) +{ + INT i,j; + INT len1,len2; + SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e=19, energies_e_add; + SCHAR prevEnergies_e_diff, newEnergies_e_diff; + FIXP_DBL tmp0,tmp1; + FIXP_DBL accu1,accu2,accu1_init,accu2_init; + FIXP_DBL delta, delta_sum; + INT accu_e, tmp_e; + + delta_sum = FL2FXCONST_DBL(0.0f); + *result_e = 0; + + len1 = border-start; + len2 = stop-border; + + /* prefer borders near the middle of the frame */ + FIXP_DBL pos_weight; + pos_weight = FL2FXCONST_DBL(0.5f) - (len1*GetInvInt(len1+len2)); + pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - (fMult(pos_weight, pos_weight)<<2); + + /*** Calc scaling for energies ***/ + FDK_ASSERT(scaleEnergies[0] >= 0); + FDK_ASSERT(scaleEnergies[1] >= 0); + + energies_e = 19 - FDKmin(scaleEnergies[0], scaleEnergies[1]); + + /* limit shift for energy accumulation, energies_e can be -10 min. */ + if (energies_e < -10) { + energies_e_add = -10 - energies_e; + energies_e = -10; + } else if (energies_e > 17) { + energies_e_add = energies_e - 17; + energies_e = 17; + } else { + energies_e_add = 0; + } + + /* compensate scaling differences between scaleEnergies[0] and scaleEnergies[1] */ + prevEnergies_e_diff = scaleEnergies[0] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT; + newEnergies_e_diff = scaleEnergies[1] - FDKmin(scaleEnergies[0], scaleEnergies[1]) + energies_e_add + NRG_SHIFT; + + prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS-1); + newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS-1); + + for (i=start; i>=1; + accu2>>=1; + if (accu_e & 1) { + accu_e++; + accu1>>=1; + accu2>>=1; + } + + delta_sum += fMult(sqrtFixp(accu1+accu2), delta); + *result_e = ((accu_e>>1) + LD_DATA_SHIFT); + } + + energyTotal_e+=1; /* for a defined square result exponent, the exponent has to be even */ + EnergyTotal<<=1; + delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e)); + *result_e = *result_e + (tmp_e-(energyTotal_e>>1)); + + return fMult(delta_sum, pos_weight); + +} + + +/******************************************************************************* + Functionname: addLowbandEnergies + ******************************************************************************* + \brief Calculates total lowband energy + + The input values Energies[0] (low-band) are scaled by the factor + 2^(14-*scaleEnergies[0]) + The input values Energies[1] (high-band) are scaled by the factor + 2^(14-*scaleEnergies[1]) + + \return total energy in the lowband, scaled by the factor 2^19 +*******************************************************************************/ +static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, + int *scaleEnergies, + int YBufferWriteOffset, + int nrgSzShift, + int tran_off, + UCHAR *freqBandTable, + int slots) +{ + FIXP_DBL nrgTotal; + FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f); + int tran_offdiv2 = tran_off>>nrgSzShift; + int ts,k; + + /* Sum up lowband energy from one frame at offset tran_off */ + /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */ + for (ts=tran_offdiv2; ts> 6; + } + } + for (; ts>nrgSzShift); ts++) { + for (k = 0; k < freqBandTable[0]; k++) { + accu2 += Energies[ts][k] >> 9; + } + } + + nrgTotal = ( scaleValueSaturate(accu1, 1-scaleEnergies[0]) ) + + ( scaleValueSaturate(accu2, 4-scaleEnergies[1]) ); + + return(nrgTotal); +} + + +/******************************************************************************* + Functionname: addHighbandEnergies + ******************************************************************************* + \brief Add highband energies + + Highband energies are mapped to an array with smaller dimension: + Its time resolution is only 1 SBR-timeslot and its frequency resolution + is 1 SBR-band. Therefore the data to be fed into the spectralChange + function is reduced. + + The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for + slots=YBufferWriteOffset. + + \return total energy in the highband, scaled by factor 2^19 +*******************************************************************************/ + +static FIXP_DBL addHighbandEnergies(FIXP_DBL **RESTRICT Energies, /*!< input */ + INT *scaleEnergies, + INT YBufferWriteOffset, + FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], /*!< Combined output */ + UCHAR *RESTRICT freqBandTable, + INT nSfb, + INT sbrSlots, + INT timeStep) +{ + INT i,j,k,slotIn,slotOut,scale[2]; + INT li,ui; + FIXP_DBL nrgTotal; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + + /* Combine QMF-timeslots to SBR-timeslots, + combine QMF-bands to SBR-bands, + combine Left and Right channel */ + for (slotOut=0; slotOut>1][k] >> 5); + } + } + EnergiesM[slotOut][j] = accu; + } + } + + /* scale energies down before add up */ + scale[0] = fixMin(8,scaleEnergies[0]); + scale[1] = fixMin(8,scaleEnergies[1]); + + if ((scaleEnergies[0]-scale[0]) > (DFRACT_BITS-1) || (scaleEnergies[1]-scale[0]) > (DFRACT_BITS-1)) + nrgTotal = FL2FXCONST_DBL(0.0f); + else { + /* Now add all energies */ + accu = FL2FXCONST_DBL(0.0f); + + for (slotOut=0; slotOut> scale[0]); + } + } + nrgTotal = accu >> (scaleEnergies[0]-scale[0]); + + for (slotOut=YBufferWriteOffset; slotOut> scale[0]); + } + } + nrgTotal = accu >> (scaleEnergies[1]-scale[1]); + } + + return(nrgTotal); +} + + +/******************************************************************************* + Functionname: FDKsbrEnc_frameSplitter + ******************************************************************************* + \brief Decides if a FIXFIX-frame shall be splitted into 2 envelopes + + If no transient has been detected before, the frame can still be splitted + into 2 envelopes. +*******************************************************************************/ +void +FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, + INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UCHAR *freqBandTable, + UCHAR *tran_vector, + int YBufferWriteOffset, + int YBufferSzShift, + int nSfb, + int timeStep, + int no_cols, + FIXP_DBL* tonality) +{ + if (tran_vector[1]==0) /* no transient was detected */ + { + FIXP_DBL delta; + INT delta_e; + FIXP_DBL (*EnergiesM)[MAX_FREQ_COEFFS]; + FIXP_DBL EnergyTotal,newLowbandEnergy,newHighbandEnergy; + INT border; + INT sbrSlots = fMultI(GetInvInt(timeStep),no_cols); + C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS) + + FDK_ASSERT( sbrSlots * timeStep == no_cols ); + + EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM; + + /* + Get Lowband-energy over a range of 2 frames (Look half a frame back and ahead). + */ + newLowbandEnergy = addLowbandEnergies(Energies, + scaleEnergies, + YBufferWriteOffset, + YBufferSzShift, + h_sbrTransientDetector->tran_off, + freqBandTable, + no_cols); + + newHighbandEnergy = addHighbandEnergies(Energies, + scaleEnergies, + YBufferWriteOffset, + EnergiesM, + freqBandTable, + nSfb, + sbrSlots, + timeStep); + + { + /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame look-behind + newLowbandEnergy: Corresponds to 1 frame, starting in the middle of the current frame */ + EnergyTotal = (newLowbandEnergy + h_sbrTransientDetector->prevLowBandEnergy) >> 1; + EnergyTotal += newHighbandEnergy; + /* The below border should specify the same position as the middle border + of a FIXFIX-frame with 2 envelopes. */ + border = (sbrSlots+1) >> 1; + + if ( (INT)EnergyTotal&0xffffffe0 && (scaleEnergies[0]<32 || scaleEnergies[1]<32) ) /* i.e. > 31 */ { + delta = spectralChange(EnergiesM, + scaleEnergies, + EnergyTotal, + nSfb, + 0, + border, + YBufferWriteOffset, + sbrSlots, + &delta_e + ); + } else { + delta = FL2FXCONST_DBL(0.0f); + delta_e = 0; + + /* set tonality to 0 when energy is very low, since the amplitude + resolution should then be low as well */ + *tonality = FL2FXCONST_DBL(0.0f); + } + + + if ( fIsLessThan(h_sbrTransientDetector->split_thr_m, h_sbrTransientDetector->split_thr_e, delta, delta_e) ) { + tran_vector[0] = 1; /* Set flag for splitting */ + } else { + tran_vector[0] = 0; + } + + } + + /* Update prevLowBandEnergy */ + h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy; + h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy; + C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, NUMBER_TIME_SLOTS_2304*MAX_FREQ_COEFFS) + } +} + +/* + * Calculate transient energy threshold for each QMF band + */ +static void +calculateThresholds(FIXP_DBL **RESTRICT Energies, + INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, + int YBufferWriteOffset, + int YBufferSzShift, + int noCols, + int noRows, + int tran_off) +{ + FIXP_DBL mean_val,std_val,temp; + FIXP_DBL i_noCols; + FIXP_DBL i_noCols1; + FIXP_DBL accu,accu0,accu1; + int scaleFactor0,scaleFactor1,commonScale; + int i,j; + + i_noCols = GetInvInt(noCols + tran_off ) << YBufferSzShift; + i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift; + + /* calc minimum scale of energies of previous and current frame */ + commonScale = fixMin(scaleEnergies[0],scaleEnergies[1]); + + /* calc scalefactors to adapt energies to common scale */ + scaleFactor0 = fixMin((scaleEnergies[0]-commonScale), (DFRACT_BITS-1)); + scaleFactor1 = fixMin((scaleEnergies[1]-commonScale), (DFRACT_BITS-1)); + + FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0)); + + /* calculate standard deviation in every subband */ + for (i=0; i>YBufferSzShift); + int endEnergy = ((noCols>>YBufferSzShift)+tran_off); + int shift; + + /* calculate mean value over decimated energy values (downsampled by 2). */ + accu0 = accu1 = FL2FXCONST_DBL(0.0f); + + for (j=startEnergy; j> scaleFactor0) + (accu1 >> scaleFactor1); /* average */ + shift = fixMax(0,CountLeadingBits(mean_val)-6); /* -6 to keep room for accumulating upto N = 24 values */ + + /* calculate standard deviation */ + accu = FL2FXCONST_DBL(0.0f); + + /* summe { ((mean_val-nrg)^2) * i_noCols1 } */ + for (j=startEnergy; j> scaleFactor0))<> scaleFactor1))<>shift; /* standard deviation */ + + /* + Take new threshold as average of calculated standard deviation ratio + and old threshold if greater than absolute threshold + */ + temp = ( commonScale<=(DFRACT_BITS-1) ) + ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale) + : (FIXP_DBL) 0; + + thresholds[i] = fixMax(ABS_THRES,temp); + + FDK_ASSERT(commonScale >= 0); + } +} + +/* + * Calculate transient levels for each QMF time slot. + */ +static void +extractTransientCandidates(FIXP_DBL **RESTRICT Energies, + INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, + FIXP_DBL *RESTRICT transients, + int YBufferWriteOffset, + int YBufferSzShift, + int noCols, + int start_band, + int stop_band, + int tran_off, + int addPrevSamples) +{ + FIXP_DBL i_thres; + C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS); + FIXP_DBL *RESTRICT pEnergiesTemp = EnergiesTemp; + int tmpScaleEnergies0, tmpScaleEnergies1; + int endCond; + int startEnerg,endEnerg; + int i,j,jIndex,jpBM; + + tmpScaleEnergies0 = scaleEnergies[0]; + tmpScaleEnergies1 = scaleEnergies[1]; + + /* Scale value for first energies, upto YBufferWriteOffset */ + tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL); + /* Scale value for first energies, from YBufferWriteOffset upwards */ + tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL); + + FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0)); + + /* Keep addPrevSamples extra previous transient candidates. */ + FDKmemmove(transients, transients + noCols - addPrevSamples, (tran_off+addPrevSamples) * sizeof (FIXP_DBL)); + FDKmemclear(transients + tran_off + addPrevSamples, noCols * sizeof (FIXP_DBL)); + + endCond = noCols; /* Amount of new transient values to be calculated. */ + startEnerg = (tran_off-3)>>YBufferSzShift; /* >>YBufferSzShift because of amount of energy values. -3 because of neighbors being watched. */ + endEnerg = ((noCols+ (YBufferWriteOffset<>YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */ + + /* Compute differential values with two different weightings in every subband */ + for (i=start_band; i=256) + i_thres = (LONG)( (LONG)MAXVAL_DBL / ((((LONG)thresholds[i]))+1) )<<(32-24); + else + i_thres = (LONG)MAXVAL_DBL; + + /* Copy one timeslot and de-scale and de-squish */ + if (YBufferSzShift == 1) { + for(j=startEnerg; j>tmpScaleEnergies0; + } + for(; j<=endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[(j<<1)+1] = EnergiesTemp[j<<1] = tmp>>tmpScaleEnergies1; + } + } else { + for(j=startEnerg; j>tmpScaleEnergies0; + } + for(; j<=endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[j] = tmp>>tmpScaleEnergies1; + } + } + + /* Detect peaks in energy values. */ + + jIndex = tran_off; + jpBM = jIndex+addPrevSamples; + + for (j=endCond; j--; jIndex++, jpBM++) + { + + FIXP_DBL delta, tran; + int d; + + delta = (FIXP_DBL)0; + tran = (FIXP_DBL)0; + + for (d=1; d<4; d++) { + delta += pEnergiesTemp[jIndex+d]; /* R */ + delta -= pEnergiesTemp[jIndex-d]; /* L */ + delta -= thres; + + if ( delta > (FIXP_DBL)0 ) { + tran += fMult(i_thres, delta); + } + } + transients[jpBM] += tran; + } + } + C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2*QMF_MAX_TIME_SLOTS); +} + +void +FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran, + FIXP_DBL **Energies, + INT *scaleEnergies, + UCHAR *transient_info, + int YBufferWriteOffset, + int YBufferSzShift, + int timeStep, + int frameMiddleBorder) +{ + int no_cols = h_sbrTran->no_cols; + int qmfStartSample; + int addPrevSamples; + int timeStepShift=0; + int i, cond; + + /* Where to start looking for transients in the transient candidate buffer */ + qmfStartSample = timeStep * frameMiddleBorder; + /* We need to look one value backwards in the transients, so we might need one more previous value. */ + addPrevSamples = (qmfStartSample > 0) ? 0: 1; + + switch (timeStep) { + case 1: timeStepShift = 0; break; + case 2: timeStepShift = 1; break; + case 4: timeStepShift = 2; break; + } + + calculateThresholds(Energies, + scaleEnergies, + h_sbrTran->thresholds, + YBufferWriteOffset, + YBufferSzShift, + h_sbrTran->no_cols, + h_sbrTran->no_rows, + h_sbrTran->tran_off); + + extractTransientCandidates(Energies, + scaleEnergies, + h_sbrTran->thresholds, + h_sbrTran->transients, + YBufferWriteOffset, + YBufferSzShift, + h_sbrTran->no_cols, + 0, + h_sbrTran->no_rows, + h_sbrTran->tran_off, + addPrevSamples ); + + transient_info[0] = 0; + transient_info[1] = 0; + transient_info[2] = 0; + + /* Offset by the amount of additional previous transient candidates being kept. */ + qmfStartSample += addPrevSamples; + + /* Check for transients in second granule (pick the last value of subsequent values) */ + for (i=qmfStartSample; itransients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) ) + && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + transient_info[0] = (i - qmfStartSample)>>timeStepShift; + transient_info[1] = 1; + break; + } + } + + if ( h_sbrTran->frameShift != 0) { + /* transient prediction for LDSBR */ + /* Check for transients in first qmf-slots of second frame */ + for (i=qmfStartSample+no_cols; iframeShift; i++) { + + cond = (h_sbrTran->transients[i] < fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1]) ) + && (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + int pos = (int) ( (i - qmfStartSample-no_cols) >> timeStepShift ); + if ((pos < 3) && (transient_info[1]==0)) { + transient_info[2] = 1; + } + break; + } + } + } +} + +int +FDKsbrEnc_InitSbrTransientDetector(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, + INT sampleFreq, + sbrConfigurationPtr params, + int tran_fc, + int no_cols, + int no_rows, + int YBufferWriteOffset, + int YBufferSzShift, + int frameShift, + int tran_off) +{ + INT totalBitrate = params->codecSettings.standardBitrate * params->codecSettings.nChannels; + INT codecBitrate = params->codecSettings.bitRate; + FIXP_DBL bitrateFactor_m, framedur_fix; + INT bitrateFactor_e, tmp_e; + + FDKmemclear(h_sbrTransientDetector,sizeof(SBR_TRANSIENT_DETECTOR)); + + h_sbrTransientDetector->frameShift = frameShift; + h_sbrTransientDetector->tran_off = tran_off; + + if(codecBitrate) { + bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, (FIXP_DBL)(codecBitrate<<2),&bitrateFactor_e); + bitrateFactor_e += 2; + } + else { + bitrateFactor_m = FL2FXCONST_DBL(1.0/4.0); + bitrateFactor_e = 2; + } + + framedur_fix = fDivNorm(frameSize, sampleFreq); + + /* The longer the frames, the more often should the FIXFIX- + case transmit 2 envelopes instead of 1. + Frame durations below 10 ms produce the highest threshold + so that practically always only 1 env is transmitted. */ + FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010); + + tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001)); + tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e); + + bitrateFactor_e = (tmp_e + bitrateFactor_e); + + if(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + bitrateFactor_e--; /* divide by 2 */ + } + + FDK_ASSERT(no_cols <= QMF_MAX_TIME_SLOTS); + FDK_ASSERT(no_rows <= QMF_CHANNELS); + + h_sbrTransientDetector->no_cols = no_cols; + h_sbrTransientDetector->tran_thr = (FIXP_DBL)((params->tran_thr << (32-24-1)) / no_rows); + h_sbrTransientDetector->tran_fc = tran_fc; + h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m); + h_sbrTransientDetector->split_thr_e = bitrateFactor_e; + h_sbrTransientDetector->no_rows = no_rows; + h_sbrTransientDetector->mode = params->tran_det_mode; + h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f); + + return (0); +} + + +#define ENERGY_SCALING_SIZE 32 + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, + const INT bandwidth_qmf_slot, + const INT no_qmf_channels, + const INT sbr_qmf_1st_band + ) +{ + + int i, e; + int buff_size; + FIXP_DBL myExp; + FIXP_DBL myExpSlot; + + h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD; + h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame; + + buff_size = h_sbrFastTransientDetector->nTimeSlots + h_sbrFastTransientDetector->lookahead; + + for(i=0; i< buff_size; i++) { + h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->transientCandidates[i] = 0; + } + + FDK_ASSERT(bandwidth_qmf_slot > 0.f); + h_sbrFastTransientDetector->stopBand = fMin(TRAN_DET_STOP_FREQ/bandwidth_qmf_slot, no_qmf_channels); + h_sbrFastTransientDetector->startBand = fMin(sbr_qmf_1st_band, h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS); + + FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels); + FDK_ASSERT(h_sbrFastTransientDetector->startBand < h_sbrFastTransientDetector->stopBand); + FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1); + FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1); + + /* the energy weighting and adding up has a headroom of 6 Bits, + so up to 64 bands can be added without potential overflow. */ + FDK_ASSERT(h_sbrFastTransientDetector->stopBand - h_sbrFastTransientDetector->startBand <= 64); + + /* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter. + The following lines map this to the QMF bandwidth. */ + #define EXP_E 7 /* QMF_CHANNELS (=64) multiplications max, max. allowed sum is 0.5 */ + myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, (FIXP_DBL)bandwidth_qmf_slot, &e); + myExp = scaleValueSaturate(myExp, e+0+DFRACT_BITS-1-EXP_E); + myExpSlot = myExp; + + for(i=0; idBf_m[i] = dBf_m; + h_sbrFastTransientDetector->dBf_e[i] = dBf_e; + + } + + /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */ + /* ... */ + + return 0; +} + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, + const int *const scaleEnergies, + const INT YBufferWriteOffset, + UCHAR *const tran_vector + ) +{ + int timeSlot, band; + + FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio */ + int max_delta_energy_scale; /* helper to store scale of maximum energy ratio */ + int ind_max = 0; /* helper to store index of maximum energy ratio */ + int isTransientInFrame = 0; + + const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots; + const int lookahead = h_sbrFastTransientDetector->lookahead; + const int startBand = h_sbrFastTransientDetector->startBand; + const int stopBand = h_sbrFastTransientDetector->stopBand; + + int * transientCandidates = h_sbrFastTransientDetector->transientCandidates; + + FIXP_DBL * energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots; + int * energy_timeSlots_scale = h_sbrFastTransientDetector->energy_timeSlots_scale; + + FIXP_DBL * delta_energy = h_sbrFastTransientDetector->delta_energy; + int * delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale; + + const FIXP_DBL thr = TRAN_DET_THRSHLD; + const INT thr_scale = TRAN_DET_THRSHLD_SCALE; + + /*reset transient info*/ + tran_vector[2] = 0; + + /* reset transient candidates */ + FDKmemclear(transientCandidates+lookahead, nTimeSlots*sizeof(int)); + + for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + int i, norm; + FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f); + int headroomEnSlot = DFRACT_BITS-1; + + FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f); + FIXP_DBL denominator; + INT denominator_scale; + + /* determine minimum headroom of energy values for this timeslot */ + for(band = startBand; band < stopBand; band++) { + int tmp_headroom = fNormz(Energies[timeSlot][band])-1; + if(tmp_headroom < headroomEnSlot){ + headroomEnSlot = tmp_headroom; + } + } + + for(i = 0, band = startBand; band < stopBand; band++, i++) { + /* energy is weighted by weightingfactor stored in dBf_m array */ + /* dBf_m index runs from 0 to stopBand-startband */ + /* energy shifted by calculated headroom for maximum precision */ + FIXP_DBL weightedEnergy = fMult(Energies[timeSlot][band]<dBf_m[i]); + + /* energy is added up */ + /* shift by 6 to have a headroom for maximum 64 additions */ + /* shift by dBf_e to handle weighting factor dependent scale factors */ + tmpE += weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i])); + } + + /* store calculated energy for timeslot */ + energy_timeSlots[timeSlot] = tmpE; + + /* calculate overall scale factor for energy of this timeslot */ + /* = original scale factor of energies (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or -scaleEnergies[1]+2*QMF_SCALE_OFFSET */ + /* depending on YBufferWriteOffset) */ + /* + weighting factor scale (10) */ + /* + adding up scale factor ( 6) */ + /* - headroom of energy value (headroomEnSlot) */ + if(timeSlot < YBufferWriteOffset){ + energy_timeSlots_scale[timeSlot] = (-scaleEnergies[0]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot; + } else { + energy_timeSlots_scale[timeSlot] = (-scaleEnergies[1]+2*QMF_SCALE_OFFSET) + (10+6) - headroomEnSlot; + } + + /* Add a small energy to the denominator, thus making the transient + detection energy-dependent. Loud transients are being detected, + silent ones not. */ + + /* make sure that smallNRG does not overflow */ + if ( -energy_timeSlots_scale[timeSlot-1] + 1 > 5 ) + { + denominator = smallNRG; + denominator_scale = 0; + } else { + /* Leave an additional headroom of 1 bit for this addition. */ + smallNRG = scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot-1] + 1)); + denominator = (energy_timeSlots[timeSlot-1]>>1) + smallNRG; + denominator_scale = energy_timeSlots_scale[timeSlot-1]+1; + } + + delta_energy[timeSlot] = fDivNorm(energy_timeSlots[timeSlot], denominator, &norm); + delta_energy_scale[timeSlot] = energy_timeSlots_scale[timeSlot] - denominator_scale + norm; + } + + /*get transient candidates*/ + /* For every timeslot, check if delta(E) exceeds the threshold. If it did, + it could potentially be marked as a transient candidate. However, the 2 + slots before the current one must not be transients with an energy higher + than 1.4*E(current). If both aren't transients or if the energy of the + current timesolot is more than 1.4 times higher than the energy in the + last or the one before the last slot, it is marked as a transient.*/ + + FDK_ASSERT(lookahead >= 2); + for(timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + FIXP_DBL energy_cur_slot_weighted = fMult(energy_timeSlots[timeSlot],FL2FXCONST_DBL(1.0f/1.4f)); + if( !fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, thr_scale) && + ( ((transientCandidates[timeSlot-2]==0) && (transientCandidates[timeSlot-1]==0)) || + !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-1], energy_timeSlots_scale[timeSlot-1] ) || + !fIsLessThan(energy_cur_slot_weighted, energy_timeSlots_scale[timeSlot], energy_timeSlots[timeSlot-2], energy_timeSlots_scale[timeSlot-2] ) + ) + ) +{ + /* in case of strong transients, subsequent + * qmf slots might be recognized as transients. */ + transientCandidates[timeSlot] = 1; + } + } + + /*get transient with max energy*/ + max_delta_energy = FL2FXCONST_DBL(0.0f); + max_delta_energy_scale = 0; + ind_max = 0; + isTransientInFrame = 0; + for(timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) { + int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale); + if(transientCandidates[timeSlot] && ( (delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > (max_delta_energy >> (scale - max_delta_energy_scale)) ) ) { + max_delta_energy = delta_energy[timeSlot]; + max_delta_energy_scale = scale; + ind_max = timeSlot; + isTransientInFrame = 1; + } + } + + /*from all transient candidates take the one with the biggest energy*/ + if(isTransientInFrame) { + tran_vector[0] = ind_max; + tran_vector[1] = 1; + } else { + /*reset transient info*/ + tran_vector[0] = tran_vector[1] = 0; + } + + /*check for transients in lookahead*/ + for(timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) { + if(transientCandidates[timeSlot]) { + tran_vector[2] = 1; + } + } + + /*update buffers*/ + for(timeSlot = 0; timeSlot < lookahead; timeSlot++) { + transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot]; + + /* fixpoint stuff */ + energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot]; + energy_timeSlots_scale[timeSlot] = energy_timeSlots_scale[nTimeSlots + timeSlot]; + + delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot]; + delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot]; + } +} + diff --git a/libSBRenc/src/tran_det.h b/libSBRenc/src/tran_det.h new file mode 100644 index 00000000..6fe1023c --- /dev/null +++ b/libSBRenc/src/tran_det.h @@ -0,0 +1,203 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*! + \file + \brief Transient detector prototypes +*/ +#ifndef __TRAN_DET_H +#define __TRAN_DET_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +typedef struct +{ + FIXP_DBL transients[QMF_MAX_TIME_SLOTS+(QMF_MAX_TIME_SLOTS/2)]; + FIXP_DBL thresholds[QMF_CHANNELS]; + FIXP_DBL tran_thr; /* Master threshold for transient signals */ + FIXP_DBL split_thr_m; /* Threshold for splitting FIXFIX-frames into 2 env */ + INT split_thr_e; /* Scale for splitting threshold */ + FIXP_DBL prevLowBandEnergy; /* Energy of low band */ + FIXP_DBL prevHighBandEnergy; /* Energy of high band */ + INT tran_fc; /* Number of lowband subbands to discard */ + INT no_cols; + INT no_rows; + INT mode; + + int frameShift; + int tran_off; /* Offset for reading energy values. */ +} +SBR_TRANSIENT_DETECTOR; + + +typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR; + +#define TRAN_DET_LOOKAHEAD 2 +#define TRAN_DET_START_FREQ 4500 /*start frequency for transient detection*/ +#define TRAN_DET_STOP_FREQ 13500 /*stop frequency for transient detection*/ +#define TRAN_DET_MIN_QMFBANDS 4 /* minimum qmf bands for transient detection */ +#define QMF_HP_dBd_SLOPE_FIX FL2FXCONST_DBL(0.00075275f) /* 0.002266f/10 * log2(10) */ +#define TRAN_DET_THRSHLD FL2FXCONST_DBL(3.2f/4.f) +#define TRAN_DET_THRSHLD_SCALE (2) + +typedef struct +{ + INT transientCandidates[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT nTimeSlots; + INT lookahead; + INT startBand; + INT stopBand; + + FIXP_DBL dBf_m[QMF_CHANNELS]; + INT dBf_e[QMF_CHANNELS]; + + FIXP_DBL energy_timeSlots[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT energy_timeSlots_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL delta_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT delta_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL lowpass_energy[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; + INT lowpass_energy_scale[QMF_MAX_TIME_SLOTS + TRAN_DET_LOOKAHEAD]; +#if defined (FTD_LOG) + FDKFILE *ftd_log; +#endif +} +FAST_TRAN_DETECTOR; +typedef FAST_TRAN_DETECTOR *HANDLE_FAST_TRAN_DET; + + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, + const INT bandwidth_qmf_slot, + const INT no_qmf_channels, + const INT sbr_qmf_1st_band + ); + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, + const int *const scaleEnergies, + const INT YBufferWriteOffset, + UCHAR *const tran_vector + ); + +void +FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + FIXP_DBL **Energies, + INT *scaleEnergies, + UCHAR *tran_vector, + int YBufferWriteOffset, + int YBufferSzShift, + int timeStep, + int frameMiddleBorder); + +int +FDKsbrEnc_InitSbrTransientDetector (HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, + INT sampleFreq, + sbrConfigurationPtr params, + int tran_fc, + int no_cols, + int no_rows, + int YBufferWriteOffset, + int YBufferSzShift, + int frameShift, + int tran_off); + +void +FDKsbrEnc_frameSplitter(FIXP_DBL **Energies, + INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UCHAR *freqBandTable, + UCHAR *tran_vector, + int YBufferWriteOffset, + int YBufferSzShift, + int nSfb, + int timeStep, + int no_cols, + FIXP_DBL* tonality); +#endif diff --git a/libSYS/include/FDK_audio.h b/libSYS/include/FDK_audio.h new file mode 100644 index 00000000..9a787fb8 --- /dev/null +++ b/libSYS/include/FDK_audio.h @@ -0,0 +1,645 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Manuel Jander + +******************************************************************************/ + +/** \file FDK_audio.h + * \brief Global audio struct and constant definitions. + */ + +#ifndef FDK_AUDIO_H +#define FDK_AUDIO_H + +#include "machine_type.h" +#include "genericStds.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * File format identifiers. + */ +typedef enum +{ + FF_UNKNOWN = -1, /**< Unknown format. */ + FF_RAW = 0, /**< No container, bit stream data conveyed "as is". */ + + FF_MP4_3GPP = 3, /**< 3GPP file format. */ + FF_MP4_MP4F = 4, /**< MPEG-4 File format. */ + + FF_RAWPACKETS = 5, /**< Proprietary raw packet file. */ + + FF_DRMCT = 12 /**< Digital Radio Mondial (DRM30/DRM+) CT proprietary file format. */ + +} FILE_FORMAT; + +/** + * Transport type identifiers. + */ +typedef enum +{ + TT_UNKNOWN = -1, /**< Unknown format. */ + TT_MP4_RAW = 0, /**< "as is" access units (packet based since there is obviously no sync layer) */ + TT_MP4_ADIF = 1, /**< ADIF bitstream format. */ + TT_MP4_ADTS = 2, /**< ADTS bitstream format. */ + + TT_MP4_LATM_MCP1 = 6, /**< Audio Mux Elements with muxConfigPresent = 1 */ + TT_MP4_LATM_MCP0 = 7, /**< Audio Mux Elements with muxConfigPresent = 0, out of band StreamMuxConfig */ + + TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ + + TT_DRM = 12, /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ + TT_DABPLUS = 13, /**< Digital Audio Broadcastong (DAB+) superframes bitstream format. */ + + TT_MP1_L1 = 16, /**< MPEG 1 Audio Layer 1 audio bitstream. */ + TT_MP1_L2 = 17, /**< MPEG 1 Audio Layer 2 audio bitstream. */ + TT_MP1_L3 = 18, /**< MPEG 1 Audio Layer 3 audio bitstream. */ + + TT_RSVD50 = 50 /**< */ + +} TRANSPORT_TYPE; + +#define TT_IS_PACKET(x) \ + ( ((x) == TT_MP4_RAW) \ + || ((x) == TT_DRM) \ + || ((x) == TT_MP4_LATM_MCP0) \ + || ((x) == TT_MP4_LATM_MCP1) ) + +/** + * Audio Object Type definitions. + */ +typedef enum +{ + AOT_NONE = -1, + AOT_NULL_OBJECT = 0, + AOT_AAC_MAIN = 1, /**< Main profile */ + AOT_AAC_LC = 2, /**< Low Complexity object */ + AOT_AAC_SSR = 3, + AOT_AAC_LTP = 4, + AOT_SBR = 5, + AOT_AAC_SCAL = 6, + AOT_TWIN_VQ = 7, + AOT_CELP = 8, + AOT_HVXC = 9, + AOT_RSVD_10 = 10, /**< (reserved) */ + AOT_RSVD_11 = 11, /**< (reserved) */ + AOT_TTSI = 12, /**< TTSI Object */ + AOT_MAIN_SYNTH = 13, /**< Main Synthetic object */ + AOT_WAV_TAB_SYNTH = 14, /**< Wavetable Synthesis object */ + AOT_GEN_MIDI = 15, /**< General MIDI object */ + AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */ + AOT_ER_AAC_LC = 17, /**< Error Resilient(ER) AAC Low Complexity */ + AOT_RSVD_18 = 18, /**< (reserved) */ + AOT_ER_AAC_LTP = 19, /**< Error Resilient(ER) AAC LTP object */ + AOT_ER_AAC_SCAL = 20, /**< Error Resilient(ER) AAC Scalable object */ + AOT_ER_TWIN_VQ = 21, /**< Error Resilient(ER) TwinVQ object */ + AOT_ER_BSAC = 22, /**< Error Resilient(ER) BSAC object */ + AOT_ER_AAC_LD = 23, /**< Error Resilient(ER) AAC LowDelay object */ + AOT_ER_CELP = 24, /**< Error Resilient(ER) CELP object */ + AOT_ER_HVXC = 25, /**< Error Resilient(ER) HVXC object */ + AOT_ER_HILN = 26, /**< Error Resilient(ER) HILN object */ + AOT_ER_PARA = 27, /**< Error Resilient(ER) Parametric object */ + AOT_RSVD_28 = 28, /**< might become SSC */ + AOT_PS = 29, /**< PS, Parametric Stereo (includes SBR) */ + AOT_MPEGS = 30, /**< MPEG Surround */ + + AOT_ESCAPE = 31, /**< Signal AOT uses more than 5 bits */ + + AOT_MP3ONMP4_L1 = 32, /**< MPEG-Layer1 in mp4 */ + AOT_MP3ONMP4_L2 = 33, /**< MPEG-Layer2 in mp4 */ + AOT_MP3ONMP4_L3 = 34, /**< MPEG-Layer3 in mp4 */ + AOT_RSVD_35 = 35, /**< might become DST */ + AOT_RSVD_36 = 36, /**< might become ALS */ + AOT_AAC_SLS = 37, /**< AAC + SLS */ + AOT_SLS = 38, /**< SLS */ + AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */ + + AOT_USAC = 42, /**< USAC */ + AOT_SAOC = 43, /**< SAOC */ + AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ + + AOT_DABPLUS_AAC_LC = 135, /**< Virtual AOT for DAB plus AAC-LC */ + AOT_DABPLUS_SBR = 136, /**< Virtual AOT for DAB plus HE-AAC */ + AOT_DABPLUS_PS = 137, /**< Virtual AOT for DAB plus HE-AAC v2 */ + + + /* Pseudo AOTs */ + AOT_DRM_AAC = 143, /**< Virtual AOT for DRM (ER-AAC-SCAL without SBR) */ + AOT_DRM_SBR = 144, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR) */ + AOT_DRM_MPEG_PS = 145 /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ + +} AUDIO_OBJECT_TYPE; + +#define CAN_DO_PS(aot) \ + ((aot) == AOT_AAC_LC \ +|| (aot) == AOT_SBR \ +|| (aot) == AOT_PS \ +|| (aot) == AOT_ER_BSAC \ +|| (aot) == AOT_DRM_AAC) + +#define IS_USAC(aot) \ + ((aot) == AOT_USAC) + +#define IS_LOWDELAY(aot) \ + ((aot) == AOT_ER_AAC_LD \ +|| (aot) == AOT_ER_AAC_ELD) + +/** Channel Mode ( 1-7 equals MPEG channel configurations, others are arbitrary). */ +typedef enum { + MODE_INVALID = -1, + MODE_UNKNOWN = 0, + MODE_1 = 1, /**< C */ + MODE_2 = 2, /**< L+R */ + MODE_1_2 = 3, /**< C, L+R */ + MODE_1_2_1 = 4, /**< C, L+R, Rear */ + MODE_1_2_2 = 5, /**< C, L+R, LS+RS */ + MODE_1_2_2_1 = 6, /**< C, L+R, LS+RS, LFE */ + MODE_1_2_2_2_1 = 7, /**< C, LC+RC, L+R, LS+RS, LFE */ + + + MODE_1_1 = 16, /**< 2 SCEs (dual mono) */ + MODE_1_1_1_1 = 17, /**< 4 SCEs */ + MODE_1_1_1_1_1_1 = 18, /**< 6 SCEs */ + MODE_1_1_1_1_1_1_1_1 = 19, /**< 8 SCEs */ + MODE_1_1_1_1_1_1_1_1_1_1_1_1 = 20, /**< 12 SCEs */ + + MODE_2_2 = 21, /**< 2 CPEs */ + MODE_2_2_2 = 22, /**< 3 CPEs */ + MODE_2_2_2_2 = 23, /**< 4 CPEs */ + MODE_2_2_2_2_2_2 = 24, /**< 6 CPEs */ + + MODE_2_1 = 30, /**< CPE,SCE (ARIB standard B32) */ + + MODE_7_1_REAR_SURROUND = 33, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ + MODE_7_1_FRONT_CENTER = 34 /**< C, LC+RC, L+R, LS+RS, LFE */ + +} CHANNEL_MODE; + +/** + * Speaker description tags. + * Do not change the enumeration values unless it keeps the following segmentation: + * - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe) + * - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom) + */ +typedef enum { + ACT_NONE = 0x00, + ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */ + ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */ + ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */ + ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */ + + ACT_TOP = 0x10, /*!< Top speaker area (for combination with speaker positions) */ + ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */ + ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */ + ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */ + + ACT_BOTTOM = 0x20, /*!< Bottom speaker area (for combination with speaker positions) */ + ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */ + ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */ + ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */ + +} AUDIO_CHANNEL_TYPE; + +typedef enum +{ + SIG_UNKNOWN = -1, + SIG_IMPLICIT = 0, + SIG_EXPLICIT_BW_COMPATIBLE = 1, + SIG_EXPLICIT_HIERARCHICAL = 2 + +} SBR_PS_SIGNALING; + +/** + * Audio Codec flags. + */ +#define AC_ER_VCB11 0x000001 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use virtual codebooks */ +#define AC_ER_RVLC 0x000002 /*!< aacSpectralDataResilienceFlag flag (from ASC): 1 means use huffman codeword reordering */ +#define AC_ER_HCR 0x000004 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use virtual codebooks */ +#define AC_SCALABLE 0x000008 /*!< AAC Scalable*/ +#define AC_ELD 0x000010 /*!< AAC-ELD */ +#define AC_LD 0x000020 /*!< AAC-LD */ +#define AC_ER 0x000040 /*!< ER syntax */ +#define AC_BSAC 0x000080 /*!< BSAC */ +#define AC_USAC 0x000100 /*!< USAC */ +#define AC_USAC_TW 0x000200 /*!< USAC time warped filter bank is active */ +#define AC_USAC_NOISE 0x000400 /*!< USAC noise filling is active */ +#define AC_USAC_HBE 0x000800 /*!< USAC harmonic bandwidth extension is active */ +#define AC_RSVD50 0x001000 /*!< Rsvd50 */ +#define AC_SBR_PRESENT 0x002000 /*!< SBR present flag (from ASC) */ +#define AC_SBRCRC 0x004000 /*!< SBR CRC present flag. Only relevant for AAC-ELD for now. */ +#define AC_PS_PRESENT 0x008000 /*!< PS present flag (from ASC or implicit) */ +#define AC_MPS_PRESENT 0x010000 /*!< MPS present flag (from ASC or implicit) */ +#define AC_DRM 0x020000 /*!< DRM bit stream syntax */ +#define AC_INDEP 0x040000 /*!< Independency flag */ +#define AC_MPS_RES 0x080000 /*!< MPS residual individual channel data. */ +#define AC_DAB 0x800000 /*!< DAB bit stream syntax */ +#define AC_LD_MPS 0x01000000 /*!< Low Delay MPS. */ + + +/* CODER_CONFIG::flags */ +#define CC_MPEG_ID 0x00100000 +#define CC_IS_BASELAYER 0x00200000 +#define CC_PROTECTION 0x00400000 +#define CC_SBR 0x00800000 +#define CC_SBRCRC 0x00010000 +#define CC_RVLC 0x01000000 +#define CC_VCB11 0x02000000 +#define CC_HCR 0x04000000 +#define CC_PSEUDO_SURROUND 0x08000000 +#define CC_USAC_NOISE 0x10000000 +#define CC_USAC_TW 0x20000000 +#define CC_USAC_HBE 0x40000000 + +/** Generic audio coder configuration structure. */ +typedef struct { + AUDIO_OBJECT_TYPE aot; /**< Audio Object Type (AOT). */ + AUDIO_OBJECT_TYPE extAOT; /**< Extension Audio Object Type (SBR). */ + CHANNEL_MODE channelMode; /**< Channel mode. */ + INT samplingRate; /**< Sampling rate. */ + INT extSamplingRate; /**< Extended samplerate (SBR). */ + INT bitRate; /**< Average bitrate. */ + int samplesPerFrame; /**< Number of PCM samples per codec frame and audio channel. */ + int noChannels; /**< Number of audio channels. */ + int bitsFrame; + int nSubFrames; /**< Amount of encoder subframes. 1 means no subframing. */ + int BSACnumOfSubFrame; /**< The number of the sub-frames which are grouped and transmitted in a super-frame (BSAC). */ + int BSAClayerLength; /**< The average length of the large-step layers in bytes (BSAC). */ + UINT flags; /**< flags */ + UCHAR matrixMixdownA; /**< Matrix mixdown index to put into PCE. Default value 0 means no mixdown coefficient, + valid values are 1-4 which correspond to matrix_mixdown_idx 0-3. */ + UCHAR headerPeriod; /**< Frame period for sending in band configuration buffers in the transport layer. */ + + UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */ + UCHAR sbrMode; /**< USAC SBR mode */ + SBR_PS_SIGNALING sbrSignaling;/**< 0: implicit signaling, 1: backwards compatible explicit signaling, 2: hierarcical explicit signaling */ + + UCHAR sbrPresent; + UCHAR psPresent; +} CODER_CONFIG; + +/** MP4 Element IDs. */ +typedef enum +{ + ID_NONE = -1, /**< Invalid Element helper ID. */ + ID_SCE = 0, /**< Single Channel Element. */ + ID_CPE = 1, /**< Channel Pair Element. */ + ID_CCE = 2, /**< Coupling Channel Element. */ + ID_LFE = 3, /**< LFE Channel Element. */ + ID_DSE = 4, /**< Currently one Data Stream Element for ancillary data is supported. */ + ID_PCE = 5, /**< Program Config Element. */ + ID_FIL = 6, /**< Fill Element. */ + ID_END = 7, /**< Arnie (End Element = Terminator). */ + ID_EXT = 8, /**< Extension Payload (ER only). */ + ID_SCAL = 9, /**< AAC scalable element (ER only). */ + ID_LAST +} MP4_ELEMENT_ID; + +#define IS_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_SCE \ +|| (elementId) == ID_CPE \ +|| (elementId) == ID_LFE) + +#define EXT_ID_BITS 4 /**< Size in bits of extension payload type tags. */ + +/** Extension payload types. */ +typedef enum { + EXT_FIL = 0x00, + EXT_FILL_DATA = 0x01, + EXT_DATA_ELEMENT = 0x02, + EXT_DATA_LENGTH = 0x03, + EXT_LDSAC_DATA = 0x09, + EXT_SAOC_DATA = 0x0a, + EXT_DYNAMIC_RANGE = 0x0b, + EXT_SAC_DATA = 0x0c, + EXT_SBR_DATA = 0x0d, + EXT_SBR_DATA_CRC = 0x0e +} EXT_PAYLOAD_TYPE; + + +/** + * Proprietary raw packet file configuration data type identifier. + */ +typedef enum +{ + TC_NOTHING = 0, /* No configuration available -> in-band configuration. */ + TC_RAW_ASC, /* Configuration data field is a raw AudioSpecificConfig. */ + TC_RAW_SMC, /* Configuration data field is a raw StreamMuxConfig. */ + TC_RAW_SDC /* Configuration data field is a raw Drm SDC. */ + +} TP_CONFIG_TYPE; + +/* + * ############################################################################################## + * Library identification and error handling + * ############################################################################################## + */ +/* \cond */ +#define MODULE_ID_MASK (0x000000ff) +#define MODULE_ID_SHIFT (24) + +typedef enum { + FDK_NONE = 0, + FDK_TOOLS = 1, + FDK_SYSLIB = 2, + FDK_AACDEC = 3, + FDK_AACENC = 4, + FDK_SBRDEC = 5, + FDK_SBRENC = 6, + FDK_TPDEC = 7, + FDK_TPENC = 8, + FDK_MPSDEC = 9, + FDK_MPEGFILEREAD = 10, + FDK_MPEGFILEWRITE = 11, + FDK_MP2DEC = 12, + FDK_DABDEC = 13, + FDK_DABPARSE = 14, + FDK_DRMDEC = 15, + FDK_DRMPARSE = 16, + FDK_AACLDENC = 17, + FDK_MP2ENC = 18, + FDK_MP3ENC = 19, + FDK_MP3DEC = 20, + FDK_MP3HEADPHONE = 21, + FDK_MP3SDEC = 22, + FDK_MP3SENC = 23, + FDK_EAEC = 24, + FDK_DABENC = 25, + FDK_DMBDEC = 26, + FDK_FDREVERB = 27, + FDK_DRMENC = 28, + FDK_METADATATRANSCODER = 29, + FDK_AC3DEC = 30, + FDK_PCMDMX = 31, + + FDK_MODULE_LAST + +} FDK_MODULE_ID; + +/* AAC capability flags */ +#define CAPF_AAC_LC 0x00000001 /**< Support flag for AAC Low Complexity. */ +#define CAPF_ER_AAC_LD 0x00000002 /**< Support flag for AAC Low Delay with Error Resilience tools. */ +#define CAPF_ER_AAC_SCAL 0x00000004 /**< Support flag for AAC Scalable. */ +#define CAPF_ER_AAC_LC 0x00000008 /**< Support flag for AAC Low Complexity with Error Resilience tools. */ +#define CAPF_AAC_480 0x00000010 /**< Support flag for AAC with 480 framelength. */ +#define CAPF_AAC_512 0x00000020 /**< Support flag for AAC with 512 framelength. */ +#define CAPF_AAC_960 0x00000040 /**< Support flag for AAC with 960 framelength. */ +#define CAPF_AAC_1024 0x00000080 /**< Support flag for AAC with 1024 framelength. */ +#define CAPF_AAC_HCR 0x00000100 /**< Support flag for AAC with Huffman Codeword Reordering. */ +#define CAPF_AAC_VCB11 0x00000200 /**< Support flag for AAC Virtual Codebook 11. */ +#define CAPF_AAC_RVLC 0x00000400 /**< Support flag for AAC Reversible Variable Length Coding. */ +#define CAPF_AAC_MPEG4 0x00000800 /**< Support flag for MPEG file format. */ +#define CAPF_AAC_DRC 0x00001000 /**< Support flag for AAC Dynamic Range Control. */ +#define CAPF_AAC_CONCEALMENT 0x00002000 /**< Support flag for AAC concealment. */ +#define CAPF_AAC_DRM_BSFORMAT 0x00004000 /**< Support flag for AAC DRM bistream format. */ +#define CAPF_ER_AAC_ELD 0x00008000 /**< Support flag for AAC Enhanced Low Delay with Error Resilience tools. */ +#define CAPF_ER_AAC_BSAC 0x00010000 /**< Support flag for AAC BSAC. */ +#define CAPF_AAC_SUPERFRAMING 0x00020000 /**< Support flag for AAC Superframing. */ + +/* Transport capability flags */ +#define CAPF_ADTS 0x00000001 /**< Support flag for ADTS transport format. */ +#define CAPF_ADIF 0x00000002 /**< Support flag for ADIF transport format. */ +#define CAPF_LATM 0x00000004 /**< Support flag for LATM transport format. */ +#define CAPF_LOAS 0x00000008 /**< Support flag for LOAS transport format. */ +#define CAPF_RAWPACKETS 0x00000010 /**< Support flag for RAW PACKETS transport format. */ +#define CAPF_DRM 0x00000020 /**< Support flag for DRM/DRM+ transport format. */ +#define CAPF_RSVD50 0x00000040 /**< Support flag for RSVD50 transport format */ + +/* SBR capability flags */ +#define CAPF_SBR_LP 0x00000001 /**< Support flag for SBR Low Power mode. */ +#define CAPF_SBR_HQ 0x00000002 /**< Support flag for SBR High Quality mode. */ +#define CAPF_SBR_DRM_BS 0x00000004 /**< Support flag for */ +#define CAPF_SBR_CONCEALMENT 0x00000008 /**< Support flag for SBR concealment. */ +#define CAPF_SBR_DRC 0x00000010 /**< Support flag for SBR Dynamic Range Control. */ +#define CAPF_SBR_PS_MPEG 0x00000020 /**< Support flag for MPEG Parametric Stereo. */ +#define CAPF_SBR_PS_DRM 0x00000040 /**< Support flag for DRM Parametric Stereo. */ + +/* MP2 encoder capability flags */ +#define CAPF_MP2ENC_SS 0x00000001 /**< Support flag for Seamless Switching. */ +#define CAPF_MP2ENC_DAB 0x00000002 /**< Support flag for Layer2 DAB. */ + +/* DAB capability flags */ +#define CAPF_DAB_MP2 0x00000001 /**< Support flag for Layer2 DAB. */ +#define CAPF_DAB_AAC 0x00000002 /**< Support flag for DAB+ (HE-AAC v2). */ +#define CAPF_DAB_PAD 0x00000004 /**< Support flag for PAD extraction. */ +#define CAPF_DAB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ +#define CAPF_DAB_SURROUND 0x00000010 /**< Support flag for DAB Surround (MPS). */ + +/* DMB capability flags */ +#define CAPF_DMB_BSAC 0x00000001 /**< Support flag for ER AAC BSAC. */ +#define CAPF_DMB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ +#define CAPF_DMB_SURROUND 0x00000010 /**< Support flag for DMB Surround (MPS). */ + +/* PCM up/downmmix capability flags */ +#define CAPF_DMX_BLIND 0x00000001 /**< Support flag for blind downmixing. */ +#define CAPF_DMX_PCE 0x00000002 /**< Support flag for guided downmix with data from MPEG-2/4 Program Config Elements (PCE). */ +#define CAPF_DMX_ARIB 0x00000004 /**< Support flag for PCE guided downmix with slightly different equations and levels to fulfill ARIB standard. */ +#define CAPF_DMX_DVB 0x00000008 /**< Support flag for guided downmix with data from DVB ancillary data fields. */ +#define CAPF_DMX_CH_EXP 0x00000010 /**< Support flag for simple upmixing by dublicating channels or adding zero channels. */ +/* \endcond */ + + +/* + * ############################################################################################## + * Library versioning + * ############################################################################################## + */ + +/** + * Convert each member of version numbers to one single numeric version representation. + * \param lev0 1st level of version number. + * \param lev1 2nd level of version number. + * \param lev2 3rd level of version number. + */ +#define LIB_VERSION(lev0, lev1, lev2) ((lev0<<24 & 0xff000000) | \ + (lev1<<16 & 0x00ff0000) | \ + (lev2<<8 & 0x0000ff00)) + +/** + * Build text string of version. + */ +#define LIB_VERSION_STRING(info) FDKsprintf((info)->versionStr, "%d.%d.%d", (((info)->version >> 24) & 0xff), (((info)->version >> 16) & 0xff), (((info)->version >> 8 ) & 0xff)) + +/** + * Library information. + */ +typedef struct LIB_INFO +{ + const char* title; + const char* build_date; + const char* build_time; + FDK_MODULE_ID module_id; + INT version; + UINT flags; + char versionStr[32]; +} LIB_INFO; + +/** Initialize library info. */ +static inline void FDKinitLibInfo( LIB_INFO* info ) +{ + int i; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + info[i].module_id = FDK_NONE; + } +} + +/** Aquire supported features of library. */ +static inline UINT FDKlibInfo_getCapabilities( const LIB_INFO* info, FDK_MODULE_ID module_id ) +{ + int i; + + for (i=0; i + #ifndef _tstof /* For Visual Studio 6 */ + #ifdef _UNICODE + #include + #define _tstof(x) (float) wcstod(x, NULL) /* For Visual Studio 6 */ + #else + #define _tstof atof + #endif + #endif + + #ifndef _tstol /* For Visual Studio 6 */ + #ifdef _UNICODE + #define _tstol _wtol + #else + #define _tstol atol + #endif + #endif + + #ifndef _tstoi /* For Visual Studio 6 */ + #ifdef _UNICODE + #define _tstoi _wtoi + #else + #define _tstoi atoi + #endif + #endif + + #ifndef TEXTCHAR + #define TEXTCHAR char + #endif + + #ifndef _TEXT + #define _TEXT + #endif + +#else /* WIN32 */ + + #define TEXTCHAR char + #define _tcslen(a) FDKstrlen(a) + #define _tcscpy strcpy + #define _tcscmp FDKstrcmp + #define _tcsncmp FDKstrncmp + #define _tscanf scanf + #define _TEXT(x) x + #define _tfopen fopen + #define _ftprintf fprintf + #define _tcsncpy FDKstrncpy + #define _tstof FDKatof + #define _tstol FDKatol + #define _tstoi FDKatoi + #define _tcstol strtol + #define _istdigit isdigit +#endif /* WIN32 */ + +/* \endcond */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Scans argc, argv and a scanf style format string for parameters and stores the + * values in the variable number of pointers passed to the function. + + For example: + \code + #define ARG_PARAM "(-a %d) (-v %1)" + #define ARG_VALUE &config->aot, &verbose + int nFoundArgs = IIS_ScanCmdl(argc, argv, ARG_PARAM, ARG_VALUE); + \endcode + wheras the wild-cards (\%d, \%1, ..) define the data type of the argument: + - \%1 boolean (e. g. -x) + - \%d integer (e. g. -x 23) + - \%f float (e. g. -x 3.4) + - \%y double (e. g. -x 31415926535897932384626433832795028841971693993751) + - \%s string (e. g. -x "file.dat") + - \%u unsigned character (e. g. -x 3) + - \%c signed character (e. g. -x -3) + More examples on how to use it are located in every (encoder/decoder) example framework. + + * \param argc Number of arguments. + * \param argv Complete character string of the command line arguments. + * \param pReqArgs A list of parameters and a corresponding list of memory addresses to + * assign each parameter to. + * + * \return Number of found arguments. + */ +INT IIS_ScanCmdl(INT argc, TEXTCHAR* argv[], const TEXTCHAR* pReqArgs, ...); + +#ifdef __cplusplus +} +#endif + +/** + * Reads a text file, assembles argc and argv parameters for each text line + * and calls the given function for each set of argc, argv parameters. + * + * \param param_filename Name of text file that should be parsed. + * \param pFunction Pointer to function that should be called for every text line found. + * + * \return 0 on success, 1 on failure. + */ +INT IIS_ProcessCmdlList(const TEXTCHAR* param_filename, int (*pFunction)(int, TEXTCHAR**)); + + +#endif /* __PARSER_H */ diff --git a/libSYS/include/conv_string.h b/libSYS/include/conv_string.h new file mode 100644 index 00000000..0409dc0c --- /dev/null +++ b/libSYS/include/conv_string.h @@ -0,0 +1,136 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + +******************************************************************************/ + +/** \file conv_string.h + * \brief String conversion functions. + */ + +#ifndef _CONV_STRING_H +#define _CONV_STRING_H + + + +#include "genericStds.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \brief Convert a bitbuffer to a hex string. + * \param string Hex string. + * \param charBuf Input buffer that has to be converted. + * \param charBufLength Size of the input buffer. + * \return Error code. + */ +INT charBuf2HexString(char *string, UCHAR *charBuf, INT charBufLength); + +/** + * \brief Convert a hex string to bits. + * \param string Hex string that has to be converted. + * \param charBuf Output buffer holding the bits, will be filled up with zeros. + * \param charBufLength Size of the output buffer. + * \return Error code. + */ +INT hexString2CharBuf(const char *string, UCHAR *charBuf, UINT charBufLength); + +/** + * \brief Convert a character representing a hex sign to the appropriate value. + * \param c Character that has to be converted. + * \return Converted value (value between 0 and 15), if 16, an error has occured. + */ +UCHAR hexChar2Dec(const char c); + +#ifdef __cplusplus +} +#endif + + +#endif /* _CONV_STRING_H */ diff --git a/libSYS/include/genericStds.h b/libSYS/include/genericStds.h new file mode 100644 index 00000000..fe4dc36a --- /dev/null +++ b/libSYS/include/genericStds.h @@ -0,0 +1,480 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + +******************************************************************************/ + +/** \file genericStds.h + \brief Generic Run-Time Support function wrappers and heap allocation monitoring. + */ + +#if !defined(__GENERICSTDS_H__) +#define __GENERICSTDS_H__ + +#include "machine_type.h" + + +/* Always increase verbosity of memory allocation in case of a debug built. DEBUG is defined globally in that case. */ +#if defined(DEBUG) || defined(FDK_DEBUG) +//#define MEMORY_MEASUREMENT +#endif + +#ifndef M_PI + #define M_PI 3.14159265358979323846 /*! Pi. Only used in example projects. */ +#endif + + +/* #define _CRT_SECURE_NO_DEPRECATE */ + + +/** + * Identifiers for various memory locations. They are used along with memory allocation + * functions like FDKcalloc_L() to specify the requested memory's location. + */ +typedef enum { + /* Internal */ + SECT_DATA_L1 = 0x2000, + SECT_DATA_L2, + SECT_DATA_L1_A, + SECT_DATA_L1_B, + SECT_CONSTDATA_L1, + + /* External */ + SECT_DATA_EXTERN = 0x4000, + SECT_CONSTDATA_EXTERN + +} MEMORY_SECTION; + + +/** + * The H_ prefix indicates header file version, the C_* prefix indicates the corresponding + * object version. + * + * Declaring memory areas requires to specify a unique name and a data type. Use the H_ macro + * for this purpose inside a header file. + * + * For defining a memory area your require additionally one or two sizes, depending if the + * memory should be organized into one or two dimensions. + * + * The macros containing the keyword AALLOC instead of ALLOC also do take care of returning + * aligned memory addresses (beyond the natural alignment of its type). The preprocesor macro + * ::ALIGNMENT_DEFAULT indicates the aligment to be used (this is hardware specific). + * + * The _L suffix indicates that the memory will be located in a specific section. This is + * useful to allocate critical memory section into fast internal SRAM for example. + * + */ + +#define H_ALLOC_MEM(name,type) type * Get ## name(int n=0); void Free ## name(type** p); \ + UINT GetRequiredMem ## name(void); + +/** See #H_ALLOC_MEM for description. */ +#define H_ALLOC_MEM_OVERLAY(name,type) type * Get ## name(int n=0); void Free ## name(type** p); \ + UINT GetRequiredMem ## name(void); + + + /** See #H_ALLOC_MEM for description. */ + #define C_ALLOC_MEM(name,type,num) \ + type * Get ## name(int n) { FDK_ASSERT((n) == 0); return ((type*)FDKcalloc(num, sizeof(type))); } \ + void Free ## name(type** p) { if (p != NULL) { FDKfree(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((num) * sizeof(type)); } + + /** See #H_ALLOC_MEM for description. */ + #define C_ALLOC_MEM_STATIC(name,type,num) \ + static type * Get ## name(int n) { FDK_ASSERT((n) == 0); return ((type*)FDKcalloc(num, sizeof(type))); } \ + static void Free ## name(type** p) { if (p != NULL) { FDKfree(*p); *p=NULL; } } \ + static UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((num) * sizeof(type)); } + + /** See #H_ALLOC_MEM for description. */ + #define C_ALLOC_MEM2(name,type,n1,n2) \ + type * Get ## name (int n) { FDK_ASSERT((n) < (n2)); return ((type*)FDKcalloc(n1, sizeof(type))); } \ + void Free ## name(type** p) { if (p != NULL) { FDKfree(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); } + + /** See #H_ALLOC_MEM for description. */ + #define C_AALLOC_MEM(name,type,num) \ + type * Get ## name(int n) { FDK_ASSERT((n) == 0); return ((type*)FDKaalloc((num)*sizeof(type), ALIGNMENT_DEFAULT)); } \ + void Free ## name(type** p) { if (p != NULL) { FDKafree(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + sizeof(void *)); } + + /** See #H_ALLOC_MEM for description. */ + #define C_AALLOC_MEM2(name,type,n1,n2) \ + type * Get ## name (int n) { FDK_ASSERT((n) < (n2)); return ((type*)FDKaalloc((n1)*sizeof(type), ALIGNMENT_DEFAULT)); } \ + void Free ## name(type** p) { if (p != NULL) { FDKafree(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + sizeof(void *)) * (n2); } + + /** See #H_ALLOC_MEM for description. */ + #define C_ALLOC_MEM_L(name,type,num,s) \ + type * Get ## name(int n) { FDK_ASSERT((n) == 0); return ((type*)FDKcalloc_L(num, sizeof(type), s)); } \ + void Free ## name(type** p) { if (p != NULL) { FDKfree_L(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((num) * sizeof(type)); } + + /** See #H_ALLOC_MEM for description. */ + #define C_ALLOC_MEM2_L(name,type,n1,n2,s) \ + type * Get ## name (int n) { FDK_ASSERT((n) < (n2)); return (type*)FDKcalloc_L(n1, sizeof(type), s); } \ + void Free ## name(type** p) { if (p != NULL) { FDKfree_L(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); } + + /** See #H_ALLOC_MEM for description. */ + #define C_AALLOC_MEM_L(name,type,num,s) \ + type * Get ## name(int n) { FDK_ASSERT((n) == 0); return ((type*)FDKaalloc_L((num)*sizeof(type), ALIGNMENT_DEFAULT, s)); } \ + void Free ## name(type** p) { if (p != NULL) { FDKafree_L(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + sizeof(void *)); } + + /** See #H_ALLOC_MEM for description. */ + #define C_AALLOC_MEM2_L(name,type,n1,n2,s) \ + type * Get ## name (int n) { FDK_ASSERT((n) < (n2)); return ((type*)FDKaalloc_L((n1)*sizeof(type), ALIGNMENT_DEFAULT, s)); } \ + void Free ## name(type** p) { if (p != NULL) { FDKafree_L(*p); *p=NULL; } } \ + UINT GetRequiredMem ## name(void) { return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + sizeof(void *)) * (n2); } + +/** See #H_ALLOC_MEM_OVERLAY for description. */ + + + #define C_ALLOC_MEM_OVERLAY(name,type,num,sect,tag) C_AALLOC_MEM_L(name,type,num,sect) + + + #define C_AALLOC_SCRATCH_START(name,type,n) \ + type _ ## name[(n)+(ALIGNMENT_DEFAULT+sizeof(type)-1)]; \ + type * name = (type*)ALIGN_PTR(_ ## name); \ + + #define C_ALLOC_SCRATCH_START(name,type,n) \ + type name[n]; + + #define C_AALLOC_SCRATCH_END(name,type,n) + #define C_ALLOC_SCRATCH_END(name,type,n) + + +/*-------------------------------------------- + * Runtime support declarations + *---------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +/** printf() using stdout. If ::ARCH_WA_FLUSH_CONSOLE defined, a flush is done additionally after printf(). */ +void FDKprintf ( const char* szFmt, ...); + +/** printf() using stderr. If ::ARCH_WA_FLUSH_CONSOLE defined, a flush is done additionally after printf(). */ +void FDKprintfErr ( const char* szFmt, ...); + +/** Wrapper for 's getchar(). */ +int FDKgetchar(void); + +INT FDKfprintf(void *stream, const char *format, ...); +INT FDKsprintf(char *str, const char *format, ...); + + + +const char *FDKstrchr(const char *s, INT c); +const char *FDKstrstr(const char *haystack, const char *needle); +char *FDKstrcpy(char *dest, const char *src); +char *FDKstrncpy(char *dest, const char *src, const UINT n); + +#define FDK_MAX_OVERLAYS 8 /**< Maximum number of memory overlays. */ + + +void *FDKcalloc (const UINT n, const UINT size); +void *FDKmalloc (const UINT size); +void FDKfree (void *ptr); + +/** + * Allocate and clear an aligned memory area. Use FDKafree() instead of FDKfree() for these memory areas. + * + * \param size Size of requested memory in bytes. + * \param alignment Alignment of requested memory in bytes. + * \return Pointer to allocated memory. + */ +void *FDKaalloc (const UINT size, const UINT alignment); + +/** + * Free an aligned memory area. + * + * \param ptr Pointer to be freed. + * \return void + */ +void FDKafree (void *ptr); + + +/** + * Allocate memory in a specific memory section. + * Requests can be made for internal or external memory. If internal memory is + * requested, FDKcalloc_L() first tries to use L1 memory, which sizes are defined + * by ::DATA_L1_A_SIZE and ::DATA_L1_B_SIZE. If no L1 memory is available, then + * FDKcalloc_L() tries to use L2 memory. If that fails as well, the requested + * memory is allocated at an extern location using the fallback FDKcalloc(). + * + * \param n See MSDN documentation on calloc(). + * \param size See MSDN documentation on calloc(). + * \param s Memory section. + * \return See MSDN documentation on calloc(). + */ +void *FDKcalloc_L(const UINT n, const UINT size, MEMORY_SECTION s); + +/** + * Allocate aligned memory in a specific memory section. + * See FDKcalloc_L() description for details - same applies here. + */ +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s); + +/** + * Free memory that was allocated in a specific memory section. + */ +void FDKfree_L(void *ptr); + +/** + * Free aligned memory that was allocated in a specific memory section. + */ +void FDKafree_L(void *ptr); + + +/** + * Copy memory. Source and destination memory must not overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to use. + * The function arguments correspond to the standard memcpy(). Please see MSDN + * documentation for details on how to use it. + */ +void FDKmemcpy(void *dst, const void *src, const UINT size); + +/** + * Copy memory. Source and destination memory are allowed to overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to use. + * The function arguments correspond to the standard memmove(). Please see MSDN + * documentation for details on how to use it. +*/ +void FDKmemmove(void *dst, const void *src, const UINT size); + +/** + * Clear memory. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to use. + * The function arguments correspond to the standard memclear(). Please see MSDN + * documentation for details on how to use it. +*/ +void FDKmemclear(void *memPtr, const UINT size); + +/** + * Fill memory with values. + * The function arguments correspond to the standard memset(). Please see MSDN + * documentation for details on how to use it. + */ +void FDKmemset(void *memPtr, const INT value, const UINT size); + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size); +INT FDKstrcmp(const char *s1, const char *s2); +INT FDKstrncmp(const char *s1, const char *s2, const UINT size); + +UINT FDKstrlen(const char *s); + +#define FDKmax(a,b) ( (a) > (b) ? (a):(b)) +#define FDKmin(a,b) ( (a) < (b) ? (a):(b)) + +#define FDK_INT_MAX ((INT)0x7FFFFFFF) +#define FDK_INT_MIN ((INT)0x80000000) + +/* Math function wrappers. Only intended for compatibility, not to be highly optimized. */ +/* Used for debugging, dev code .. */ + +INT FDKabs(INT j); +double FDKfabs(double x); +double FDKpow(double x, double y); +double FDKsqrt(double x); +double FDKatan(double x); +double FDKlog(double x); +double FDKsin(double x); +double FDKcos(double x); +double FDKexp(double x); +#define FDKlog2(a) (FDKlog(a)*1.442695041) /* log(2.0) = 1.442695041 */ +#define FDKlog10(a) (FDKlog(a)*0.434294482) /* 1.0/log(10.0) = 0.434294482 */ +double FDKatan2(double y, double x); +double FDKacos(double x); +double FDKtan(double x); +double FDKfloor(double x); +double FDKceil(double x); +INT FDKatoi(const char *nptr); +long FDKatol(const char *nptr); +float FDKatof(const char *nptr); +/* LONG LONG FDKatoll(const char *nptr); */ +/* LONG LONG FDKatoq(const char *nptr); */ + + + +/* FILE I/O */ + +/*! + * Check platform for endianess. + * + * \return 1 if platform is little endian, non-1 if platform is big endian. + */ +#ifdef __cplusplus +inline +#else +static +#endif +int IS_LITTLE_ENDIAN(void) { + int __dummy = 1; + return ( *( (UCHAR*)(&(__dummy) ) ) ); +} + +/*! + * Convert input value to little endian format. + * + * \param val Value to be converted. It may be in both big or little endian. + * \return Value in little endian format. + */ +#define TO_LITTLE_ENDIAN(val) \ + ( (IS_LITTLE_ENDIAN()) ? \ + (val) \ + : ( (((val) & 0xff) << 24) || (((val) & 0xff00)<< 8) || (((val) & 0xff0000)>>8) || (((val) & 0xff000000) >> 24) ) ) + + +/*! + * \fn FDKFILE *FDKfopen(const char *filename, const char *mode); + * Standard fopen() wrapper. + * \fn INT FDKfclose(FDKFILE *FP); + * Standard fclose() wrapper. + * \fn INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); + * Standard fseek() wrapper. + * \fn INT FDKftell(FDKFILE *FP); + * Standard ftell() wrapper. + * \fn INT FDKfflush(FDKFILE *fp); + * Standard fflush() wrapper. + * \fn UINT FDKfwrite(void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + * Standard fwrite() wrapper. + * \fn UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); + * Standard fread() wrapper. + */ +typedef void FDKFILE; +extern const INT FDKSEEK_SET, FDKSEEK_CUR, FDKSEEK_END; + +FDKFILE *FDKfopen(const char *filename, const char *mode); +INT FDKfclose(FDKFILE *FP); +INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); +INT FDKftell(FDKFILE *FP); +INT FDKfflush(FDKFILE *fp); +UINT FDKfwrite(void *ptrf, INT size, UINT nmemb, FDKFILE *fp); +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); +char* FDKfgets(void *dst, INT size, FDKFILE *fp); +void FDKrewind(FDKFILE *fp); +INT FDKfeof(FDKFILE *fp); + +/** + * \brief Write each member in little endian order. Convert automatically to host endianess. + * \param ptrf Pointer to memory where to read data from. + * \param size Size of each item to be written. + * \param nmemb Number of items to be written. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfwrite_EL(void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + +/** + * \brief Read variable of size "size" as little endian. Convert automatically to host endianess. + * 4-byte alignment is enforced for 24 bit data, at 32 bit full scale. + * \param dst Pointer to memory where to store data into. + * \param size Size of each item to be read. + * \param nmemb Number of items to be read. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp); + + +/** + * \brief Print FDK software disclaimer. + */ +void FDKprintDisclaimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __GENERICSTDS_H__ */ diff --git a/libSYS/include/machine_type.h b/libSYS/include/machine_type.h new file mode 100644 index 00000000..2165d8e9 --- /dev/null +++ b/libSYS/include/machine_type.h @@ -0,0 +1,357 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + +******************************************************************************/ + +/** \file machine_type.h + * \brief Type defines for various processors and compiler tools. + */ + +#if !defined(__MACHINE_TYPE_H__) +#define __MACHINE_TYPE_H__ + + +/* Library calling convention spec. __cdecl and friends might be added here as required. */ + #define LINKSPEC_H + #define LINKSPEC_CPP + + +/** + * collate all corresponding compiler specific macros to detect a debug build, and set the DEBUG macro if that is the case. + */ +#if defined(_DEBUG) +#define DEBUG +#endif + + +/* for doxygen the following docu parts must be separated */ +/** \var SCHAR + * Data type representing at least 1 byte signed integer on all supported platforms. + */ +/** \var UCHAR + * Data type representing at least 1 byte unsigned integer on all supported platforms. + */ +/** \var INT + * Data type representing at least 4 byte signed integer on all supported platforms. + */ +/** \var UINT + * Data type representing at least 4 byte unsigned integer on all supported platforms. + */ +/** \var LONG + * Data type representing 4 byte signed integer on all supported platforms. + */ +/** \var ULONG + * Data type representing 4 byte unsigned integer on all supported platforms. + */ +/** \var SHORT + * Data type representing 2 byte signed integer on all supported platforms. + */ +/** \var USHORT + * Data type representing 2 byte unsigned integer on all supported platforms. + */ +/** \var INT64 + * Data type representing 8 byte signed integer on all supported platforms. + */ +/** \var UINT64 + * Data type representing 8 byte unsigned integer on all supported platforms. + */ +/** \def SHORT_BITS + * Number of bits the data type short represents. sizeof() is not suited to get this info, + * because a byte is not always defined as 8 bits. + */ +/** \def CHAR_BITS + * Number of bits the data type char represents. sizeof() is not suited to get this info, + * because a byte is not always defined as 8 bits. + */ +/** \var INT_PCM + * Data type representing the width of input and output PCM samples. + */ + + + typedef signed int INT; + typedef unsigned int UINT; +#ifdef __LP64__ + /* force FDK long-datatypes to 4 byte */ + /* jdr: Use defines to avoid type alias problems on 64 bit machines. */ + #define LONG INT + #define ULONG UINT +#else /* __LP64__ */ + typedef signed long LONG; + typedef unsigned long ULONG; +#endif /* __LP64__ */ + typedef signed short SHORT; + typedef unsigned short USHORT; + typedef signed char SCHAR; + typedef unsigned char UCHAR; + + #define SHORT_BITS 16 + #define CHAR_BITS 8 + + +/* Define 64 bit base integer type. */ +#ifdef _MSC_VER + typedef __int64 INT64; + typedef unsigned __int64 UINT64; +#else + typedef long long INT64; + typedef unsigned long long UINT64; +#endif + +#ifndef NULL + #ifdef __cplusplus + #define NULL 0 + #else + #define NULL ((void *)0) + #endif +#endif + +/* Assert is functional on x86 PC's and also when debugging is turned on. */ +#if defined(DEBUG) || defined(__i686__) || defined(__i586__) || defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(FDK_DEBUG) || defined(FDK_ASSERT_ENABLE) + #include + #define FDK_ASSERT(x) assert(x) +#else + #define FDK_ASSERT(ignore) +#endif + + typedef SHORT INT_PCM; + #define WAV_BITS 16 + #define SAMPLE_BITS 16 + #define SAMPLE_MAX (((LONG)1<<(SAMPLE_BITS-1))-1) + #define SAMPLE_MIN (~SAMPLE_MAX) + +/*! +* \def RAM_ALIGN +* Used to align memory as prefix before memory declaration. For example: + \code + RAM_ALIGN + int myArray[16]; + \endcode + + Note, that not all platforms support this mechanism. For example with TI compilers + a preprocessor pragma is used, but to do something like + + \code + #define RAM_ALIGN #pragma DATA_ALIGN(x) + \encode + + would require the preprocessor to process this line twice to fully resolve it. Hence, + a fully platform-independant way to use alignment is not supported. + +* \def ALIGNMENT_DEFAULT +* Default alignment in bytes. +*/ +#if defined(__GNUC__) /* cppp replaced: elif */ + #define ALIGNMENT_DEFAULT 8 + #define RAM_ALIGN __attribute__((aligned(ALIGNMENT_DEFAULT))) +#else + #define ALIGNMENT_DEFAULT 8 + #define RAM_ALIGN +#endif + + +/*! +* \def RESTRICT +* The restrict keyword is supported by some platforms and RESTRICT maps to +* either the corresponding keyword on each platform or to void if the +* compiler does not provide such feature. +* +* \def WORD_ALIGNED(x) +* Tells the compiler that pointer x is WORD aligned. +* At the moment only supported by TI compilers. +* +* \def DWORD_ALIGNED(x) +* Tells the compiler that pointer x is DWORD aligned. +* At the moment only supported by TI compilers. +*/ + #define RESTRICT + #define WORD_ALIGNED(x) + #define DWORD_ALIGNED(x) + + +/*----------------------------------------------------------------------------------- + * ALIGN_SIZE + *-----------------------------------------------------------------------------------*/ +/*! + * \brief This macro aligns a given value depending on ::ALIGNMENT_DEFAULT. + * + * For example if #ALIGNMENT_DEFAULT equals 8, then: + * - ALIGN_SIZE(3) returns 8 + * - ALIGN_SIZE(8) returns 8 + * - ALIGN_SIZE(9) returns 16 + */ +#define ALIGN_SIZE(a) ((a)+ (((INT)ALIGNMENT_DEFAULT - ((INT)(a) & (ALIGNMENT_DEFAULT-1)) ) & (ALIGNMENT_DEFAULT-1))) + +/*----------------------------------------------------------------------------------- + * ALIGN_PTR + * cast (a) to width of pointer + *-----------------------------------------------------------------------------------*/ +/*! + * \brief This macro aligns a given address depending on ::ALIGNMENT_DEFAULT. + */ +#define ALIGN_PTR(a) ( (unsigned char*)(a) + (((INT)ALIGNMENT_DEFAULT - ((INT)(UINT64)(a) & (ALIGNMENT_DEFAULT-1)) ) & (ALIGNMENT_DEFAULT-1)) ) + + /* Alignment macro for libSYS heap implementation */ +#define ALIGNMENT_EXTRES ( ALIGNMENT_DEFAULT ) +#define ALGN_SIZE_EXTRES(a) ((a)+ (((INT)ALIGNMENT_EXTRES - ((INT)(a) & (ALIGNMENT_EXTRES-1)) ) & (ALIGNMENT_EXTRES-1))) + + +/*! + * \def FORCEINLINE + * Sometimes compiler do not do what they are told to do, and in case of inlining some + * additional command might be necessary depending on the platform. + * + * \def FDK_INLINE + * Defines how the compiler is told to inline stuff. + */ +#ifdef DEBUG +#undef FORCEINLINE +#define FORCEINLINE +#else +#ifndef FORCEINLINE + #if defined(__GNUC__) /* cppp replaced: elif */ + #define FORCEINLINE inline __attribute((always_inline)) + #else + #define FORCEINLINE + #endif +#endif +#endif + + /* for all other platforms */ + #define FDK_INLINE inline + + +/*! + * \def LNK_SECTION_DATA_L1 + * The LNK_SECTION_* defines allow memory to be drawn from specific memory + * sections. Used as prefix before variable declaration. + * + * \def LNK_SECTION_DATA_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_A + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_B + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_INITCODE + * See ::LNK_SECTION_DATA_L1 + */ +/************************************************** + * Code Section macros + **************************************************/ + #define LNK_SECTION_CODE_L1 + #define LNK_SECTION_CODE_L2 + #define LNK_SECTION_INITCODE + +/* Memory section macros. */ + + /* default fall back */ + #define LNK_SECTION_DATA_L1 + #define LNK_SECTION_DATA_L2 + #define LNK_SECTION_CONSTDATA + #define LNK_SECTION_CONSTDATA_L1 + + #define LNK_SECTION_L1_DATA_A + #define LNK_SECTION_L1_DATA_B + + +#ifdef _MSC_VER + /* + * Sometimes certain features are excluded from compilation and therefore the warning 4065 may occur: + * "switch statement contains 'default' but no 'case' labels" + * We consider this warning irrelevant and disable it. + */ + #pragma warning( disable : 4065 ) +#endif + +#endif /* __MACHINE_TYPE_H__ */ diff --git a/libSYS/include/wav_file.h b/libSYS/include/wav_file.h new file mode 100644 index 00000000..2bc43b2e --- /dev/null +++ b/libSYS/include/wav_file.h @@ -0,0 +1,233 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Eric Allamanche + +******************************************************************************/ + +/** \file wav_file.h + * \brief Rudimentary WAVE file read/write support. + * + * The WAVE file reader/writer is intented to be used in the codec's example + * framework for easily getting started with encoding/decoding. Therefore + * it serves mainly for helping quickly understand how a codec's API actually + * works. + * Being a WAVE file reader/writer with very basic functionality, it may not be + * able to read WAVE files that come with unusual configurations. + * Details on how to use the interface functions can be found in every + * (encoder/decoder) example framework. + */ + +#ifndef __WAV_FILE_H__ +#define __WAV_FILE_H__ + + + +#include "genericStds.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPEAKER_FRONT_LEFT 0x1 +#define SPEAKER_FRONT_RIGHT 0x2 +#define SPEAKER_FRONT_CENTER 0x4 +#define SPEAKER_LOW_FREQUENCY 0x8 +#define SPEAKER_BACK_LEFT 0x10 +#define SPEAKER_BACK_RIGHT 0x20 +#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 +#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 +#define SPEAKER_BACK_CENTER 0x100 +#define SPEAKER_SIDE_LEFT 0x200 +#define SPEAKER_SIDE_RIGHT 0x400 +#define SPEAKER_TOP_CENTER 0x800 +#define SPEAKER_TOP_FRONT_LEFT 0x1000 +#define SPEAKER_TOP_FRONT_CENTER 0x2000 +#define SPEAKER_TOP_FRONT_RIGHT 0x4000 +#define SPEAKER_TOP_BACK_LEFT 0x8000 +#define SPEAKER_TOP_BACK_CENTER 0x10000 +#define SPEAKER_TOP_BACK_RIGHT 0x20000 +#define SPEAKER_RESERVED 0x80000000 + +/*! + * RIFF WAVE file struct. + * For details see WAVE file format documentation (for example at http://www.wotsit.org). + */ +typedef struct WAV_HEADER +{ + char riffType[4]; + UINT riffSize; + char waveType[4]; + char formatType[4]; + UINT formatSize; + USHORT compressionCode; + USHORT numChannels; + UINT sampleRate; + UINT bytesPerSecond; + USHORT blockAlign; + USHORT bitsPerSample; + char dataType[4]; + UINT dataSize; +} WAV_HEADER; + +struct WAV +{ + WAV_HEADER header; + FDKFILE *fp; + UINT channelMask; +}; + +typedef struct WAV *HANDLE_WAV; + +/** + * \brief Open a WAV file handle for reading. + * + * \param pWav Pointer to a memory location, where a WAV handle is returned. + * \param filename File name to be opened. + * + * \return 0 on success and non-zero on failure. + */ +INT WAV_InputOpen (HANDLE_WAV *pWav, const char *filename); + +/** + * \brief Read samples from a WAVE file. The samples are automatically re-ordered to the + * native host endianess and scaled to full scale of the INT_PCM type, from + * whatever BPS the WAVE file had specified in its header data. + * + * \param wav Handle of WAV file. + * \param sampleBuffer Pointer to store audio data. + * \param numSamples Desired number of samples to read. + * \param nBufBits Size in bit of each audio sample of sampleBuffer. + * + * \return Number of samples actually read. + */ +INT WAV_InputRead (HANDLE_WAV wav, void *sampleBuffer, UINT numSamples, int nBufBits); + +/** + * \brief Close a WAV file reading handle. + * \param pWav Pointer to a WAV file reading handle. + * \return void + */ +void WAV_InputClose(HANDLE_WAV *pWav); + +/** + * \brief Open WAV output/writer handle. + * + * \param pWav Pointer to WAV handle to be returned. + * \param outputFilename File name of the file to be written to. + * \param sampleRate Desired samplerate of the resulting WAV file. + * \param numChannels Desired number of audio channels of the resulting WAV file. + * \param bitsPerSample Desired number of bits per audio sample of the resulting WAV file. + * + * \return 0: ok; -1: error + */ +INT WAV_OutputOpen(HANDLE_WAV *pWav, const char *outputFilename, INT sampleRate, INT numChannels, INT bitsPerSample); + +/** + * \brief Write data to WAV file asociated to WAV handle. + * + * \param wav Handle of WAV file + * \param sampleBuffer Pointer to audio samples, right justified integer values. + * \param numberOfSamples The number of individual audio sample valuesto be written. + * \param nBufBits Size in bits of each audio sample in sampleBuffer. + * \param nSigBits Amount of significant bits of each nBufBits in sampleBuffer. + * + * \return 0: ok; -1: error + */ +INT WAV_OutputWrite(HANDLE_WAV wav, void *sampleBuffer, UINT numberOfSamples, int nBufBits, int nSigBits); + +/** + * \brief Close WAV output handle. + * \param pWav Pointer to WAV handle. *pWav is set to NULL. + * \return void + */ +void WAV_OutputClose(HANDLE_WAV *pWav); + +#ifdef __cplusplus +} +#endif + + +#endif /* __WAV_FILE_H__ */ diff --git a/libSYS/src/cmdl_parser.cpp b/libSYS/src/cmdl_parser.cpp new file mode 100644 index 00000000..24ec0d5d --- /dev/null +++ b/libSYS/src/cmdl_parser.cpp @@ -0,0 +1,581 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + Description: command line parser + +******************************************************************************/ + + + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +#include "cmdl_parser.h" +#include "genericStds.h" + + + +/************************ interface ************************/ + +static INT GetArgFromString(INT argc, TEXTCHAR* argv[], TEXTCHAR* search_string, TEXTCHAR type, TEXTCHAR* found_string , INT* switches_used); +static void RemoveWhiteSpace(const TEXTCHAR* pReqArgs, TEXTCHAR* Removed); +static INT CheckArg(TEXTCHAR* arg, TEXTCHAR* str, UINT numArgs, TEXTCHAR type, TEXTCHAR* current_str); +static INT CheckForUnusedSwitches(INT argc, /*TEXTCHAR* argv[],*/ INT* switches_used); +static INT ParseString(TEXTCHAR* str, INT*, TEXTCHAR*, TEXTCHAR*); +static void GetNumberOfArgs(TEXTCHAR* str, INT* nArgs); + +static +void removeQuotes(char *str) +{ + if (str[0] == '"') { + FDKstrcpy(str, str+1); + str[FDKstrlen(str)-1] = 0; + } +} + + +/********************** implementation *********************/ + +INT IIS_ScanCmdl(INT argc, TEXTCHAR* argv[], const TEXTCHAR* str, ...) +{ + INT i = 0; + INT found_and_set = 0; + INT nArgs = 0; + INT* switches_used = 0; + INT* b_str_opt = 0; + TEXTCHAR* s_str = 0; + TEXTCHAR* c_str_type = 0; + TEXTCHAR* str_clean = 0; + + va_list ap; + + if (argc == 0 || argc == 1) + { + FDKprintf("No command line arguments\n"); + goto bail; + } + + str_clean = (TEXTCHAR*) FDKcalloc((unsigned int)_tcslen(str), sizeof(TEXTCHAR)); + if (str_clean == NULL) { + FDKprintf("Error allocating memory line %d, file %s\n", __LINE__, __FILE__); + return 0; + } + + RemoveWhiteSpace(str, str_clean ); + GetNumberOfArgs(str_clean, &nArgs); + + b_str_opt = (INT*) FDKcalloc(nArgs, sizeof(INT)); + s_str = (TEXTCHAR*) FDKcalloc(nArgs*CMDL_MAX_ARGC, sizeof(TEXTCHAR) ); + c_str_type = (TEXTCHAR*) FDKcalloc(nArgs, sizeof(TEXTCHAR)); + switches_used = (INT*) FDKcalloc(argc, sizeof(INT)); + + if (b_str_opt == NULL || s_str == NULL || c_str_type == NULL || switches_used == NULL) { + FDKprintf("Error allocating memory line %d, file %s\n", __LINE__, __FILE__); + goto bail; + } + + if ( ParseString( str_clean, b_str_opt, s_str, c_str_type )) { + goto bail; + } + + va_start(ap, str); + + for ( i = 0; i < nArgs; i++ ) + { + TEXTCHAR arg[CMDL_MAX_STRLEN] = {L'\0'}; + TEXTCHAR* p_arg = arg; + TEXTCHAR* current_str = &(s_str[i*CMDL_MAX_ARGC]); + + if (GetArgFromString(argc, argv, current_str, c_str_type[i], arg, switches_used ) + && !b_str_opt[i] ) + { +#ifdef _UNICODE + _ftprintf(stderr, _TEXT("\n\nError: Parsing argument for required switch '%ls'.\n" ), current_str); +#else + _ftprintf(stderr, _TEXT("\n\nError: Parsing argument for required switch '%s'.\n" ), current_str); +#endif + found_and_set = 0; + goto bail; + } + if (CheckArg(p_arg, s_str, nArgs, c_str_type[i], current_str)) + { + goto bail; + } + + switch (c_str_type[i] ) + { + case 's': + { + TEXTCHAR* tmp; + tmp = va_arg(ap, TEXTCHAR*); + + if ( arg[0] == '\0' ) + break; + + _tcsncpy( tmp, arg, CMDL_MAX_STRLEN ); + /* Remove quotes. Windows Mobile Workaround. */ + removeQuotes(tmp); + found_and_set++; + break; + } + case 'd': + { + INT* tmp = va_arg(ap, INT*); + + if ( arg[0] == '\0' ) + break; + + *tmp = _tcstol(arg, NULL, 0); + found_and_set++; + break; + } + case 'c': + { + char* tmp = va_arg(ap, char*); + + if ( arg[0] == '\0' ) + break; + + *tmp = *arg; + found_and_set++; + break; + } + case 'u': + { + UCHAR* tmp = va_arg(ap, UCHAR*); + + if ( arg[0] == '\0' ) + break; + + *tmp = _tstoi(arg); + found_and_set++; + break; + } + case 'f': + { + float* tmp = (float*) va_arg( ap,double*); + + if ( arg[0] == '\0' ) + break; + + *tmp = (float) _tstof(arg); + found_and_set++; + break; + } + case 'y': // support 'data type double' + { + double* tmp = (double*) va_arg( ap,double*); + // use sscanf instead _tstof because of gcc + //_tstof(arg,"%lf",tmp); // '%lf' reads as double + *tmp = _tstof(arg); // '%lf' reads as double + found_and_set++; + break; + } + case '1': + { + + INT* tmp = va_arg( ap, INT*); + + if ( arg[0] == '\0' ) + break; + + *tmp = 1; + found_and_set++; + break; + } + + default: + FDKprintfErr("Bug: unsupported data identifier \"%c\"\n", c_str_type[i]); + break; + + } + + } + + va_end(ap); + + CheckForUnusedSwitches(argc, /*argv,*/ switches_used); + +bail: + if (b_str_opt) FDKfree(b_str_opt); + if (s_str) FDKfree(s_str); + if (c_str_type) FDKfree(c_str_type); + if (str_clean) FDKfree(str_clean); + if (switches_used) FDKfree(switches_used); + + return found_and_set; +} + + +void GetNumberOfArgs(TEXTCHAR* str, INT* nArgs) +{ + UINT i = 0; + for ( i = 0; i < _tcslen(str); ++i ) + { + if ( str[i] == '%') + *nArgs+= 1; + } + +} + +INT ParseString(TEXTCHAR* str, INT* b_str_opt, TEXTCHAR* s_str, TEXTCHAR* c_str_type ) +{ + UINT i = 0; + INT argCounter = 0; + + TEXTCHAR* str_start = 0; + TEXTCHAR* str_stop = 0; + + + str_start = str; + str_stop = str_start; + + for ( i = 0; i < _tcslen(str) - 1; ++i ) + { + if ( str[i] == '%' ) /* We have an Argument */ + { + if ( argCounter ) + { + if ( b_str_opt[argCounter-1] ) + str_start = str_stop + 3; + + else + str_start = str_stop + 2; + } + + /* Save Argument type */ + c_str_type[argCounter] = str[i+1]; + + if ( *str_start == '(' ) /* Optional Argument */ + { + b_str_opt[argCounter] = 1; + str_start++; + } + + /* Save Argument */ + str[i] = '\0'; + + _tcsncpy(&(s_str[argCounter*CMDL_MAX_ARGC]), str_start, CMDL_MAX_ARGC ); + + str[i] = '%'; + + str_stop = &(str[i]); + + if ( b_str_opt[argCounter] ) + { + if ( i+2 > ( _tcslen(str) -1 )) + { + _ftprintf(stderr,_TEXT("\n\nInternal Parser Error: Strlen Problem\n") ); + return 1; + } + if ( str[i+2] != ')' ) + { + _ftprintf(stderr,_TEXT("\n\nInternal Parser Error: Missing bracket ')'\n") ); + return 1; + } + + } + + + argCounter++; + } + + + } + + return 0; + } + + + + +void RemoveWhiteSpace(const TEXTCHAR* pReqArgs, TEXTCHAR* pRemoved) +{ + UINT i = 0; + INT k = 0; + UINT len = (UINT)_tcslen(pReqArgs); + + + for ( i = 0; i < len; ++i ) + { + + if ( pReqArgs[i] != ' ' ) + { + pRemoved[k] = pReqArgs[i]; + k++; + } + } +} + + +INT GetArgFromString(INT argc, TEXTCHAR* argv[], TEXTCHAR* search_string, TEXTCHAR type, TEXTCHAR* found_string, INT* sw_used ) +{ + INT i = 0; + + for (i = 1; i < argc; ++i ) { + if ( !_tcscmp(search_string, argv[i]) ) /* Strings are equal */ + { + if ( type == '1' ) /* Switch without argument */ + { + _tcsncpy( found_string, _TEXT("1"), 1); + sw_used[i] = 1; + return 0; + + } + + if ( i == (argc - 1)) /* We have %s or %d but are finished*/ + return 1; + + if ( _tcslen(argv[i+1]) > CMDL_MAX_STRLEN ) + { +#ifdef _UNICODE + _ftprintf (stderr,_TEXT("Warning: Ignoring argument for switch '%ls'. "), search_string ); +#else + _ftprintf (stderr,_TEXT("Warning: Ignoring argument for switch '%s'. "), search_string ); +#endif + _ftprintf (stderr,_TEXT("Argument is too LONG.\n") ); + return 1; + } + else + { + _tcsncpy( found_string, argv[i+1], CMDL_MAX_STRLEN); + sw_used[i] = 1; + sw_used[i+1] = 1; + return 0; + } + } + } + return 1; +} + + + +INT CheckArg(TEXTCHAR* arg, TEXTCHAR* str, UINT numArgs, TEXTCHAR type, TEXTCHAR* cur_str) +{ + UINT i = 0; + + /* No argument given-> return */ + if (arg[0] == '\0') + return 0; + + + /* Check if arg is switch */ + for ( i = 0; i < numArgs; ++i ) + { + if (!_tcscmp(arg, &(str[i*CMDL_MAX_ARGC]))) + { +#ifdef _UNICODE + _ftprintf(stderr, _TEXT("\n\nError: Argument '%ls' for switch '%ls' is not valid \n" ), arg, cur_str ); +#else + _ftprintf(stderr, _TEXT("\n\nError: Argument '%s' for switch '%s' is not valid \n" ), arg, cur_str ); +#endif + return 1; + } + + } + /* Check if type is %d but a string is given */ + + for ( i = 0; i < _tcslen(arg); ++i ) + { + if ( (type == 'd') && !_istdigit(arg[i]) && arg[i] != 'x' && arg[i] != '-') + { +#ifdef _UNICODE + _ftprintf(stderr, _TEXT("\n\nError: Argument '%ls' for switch '%ls' is not a valid number.\n" ), arg, cur_str); +#else + _ftprintf(stderr, _TEXT("\n\nError: Argument '%s' for switch '%s' is not a valid number.\n" ), arg, cur_str); +#endif + return 1; + } + } + + + return 0; +} + + +INT CheckForUnusedSwitches(INT argc, /*TEXTCHAR* argv[],*/ INT* switches_used) +{ + INT i = 0; + + for( i = 1; i < argc; ++i ) + { + if ( !switches_used[i] ) + { + ++i; + } + } + + return 0; +} + + + +static char line[CMDL_MAX_STRLEN*CMDL_MAX_ARGC]; +static char *argv_ptr[CMDL_MAX_ARGC]; +#ifdef CMDFILE_PREFIX +static char tmp[256]; /* this array is used to store the prefix and the filepath/name */ +#endif + +int IIS_ProcessCmdlList(const char* param_filename, int (*pFunction)(int, TEXTCHAR**)) +{ + /* static to reduce required stack size */ + + FDKFILE *config_fp; + int argc; + char *line_ptr; + +#ifdef CMDFILE_PREFIX + FDKstrcpy(tmp, CMDFILE_PREFIX); + FDKstrcpy(tmp+FDKstrlen(CMDFILE_PREFIX), param_filename); + /* Open the file with command lines */ + config_fp = FDKfopen(tmp, "r"); +#else + /* Open the file with command lines */ + config_fp = FDKfopen(param_filename, "r"); +#endif + + if(config_fp == NULL) + { +#ifdef CMDFILE_PREFIX + FDKprintf("\ncould not open config file %s", tmp); +#else + FDKprintf("\ncould not open config file %s", param_filename); +#endif + return 1; + } + + /* Obtain a command line from config file */ + while (FDKfgets(line, CMDL_MAX_STRLEN*CMDL_MAX_ARGC, config_fp) != NULL) + { + argc = 1; + + /* Eat \n */ + line_ptr = (char*)FDKstrchr(line, '\n'); + if (line_ptr != NULL) + *line_ptr = ' '; + + line_ptr = line; + + /* Scan the line and put the command line params into argv */ + do { + /* Skip consecutive blanks. */ + while (*line_ptr == ' ' && line_ptr < line+CMDL_MAX_STRLEN) + line_ptr++; + /* Assign argument. */ + argv_ptr[argc] = line_ptr; + /* Get pointer to next blank. */ + line_ptr = (char*)FDKstrchr(line_ptr, ' '); + /* */ + if (line_ptr != NULL) { + /* Null terminate */ + *line_ptr = 0; + /* Skip former blank (now null character) */ + line_ptr++; + /* Advance argument counter */ + } + argc++; + } while ( line_ptr != NULL && argc < CMDL_MAX_ARGC); + + /* call "would be main()" */ + if (argc > 2 && *argv_ptr[1] != '#' && FDKstrlen(argv_ptr[1])>1) + { + int retval; + + retval = (*pFunction)(argc, argv_ptr); + + FDKprintf("main returned %d\n", retval); + } + } + + FDKfclose(config_fp); + return 0; +} + diff --git a/libSYS/src/conv_string.cpp b/libSYS/src/conv_string.cpp new file mode 100644 index 00000000..28cbc834 --- /dev/null +++ b/libSYS/src/conv_string.cpp @@ -0,0 +1,179 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + Description: string conversion functions + +******************************************************************************/ + + + +#include "genericStds.h" +#include "conv_string.h" + +INT charBuf2HexString(char *string, UCHAR *charBuf, INT charBufLength) +{ + INT i; + UCHAR c1, c2; + + /* sanity checks */ + /* check array length */ + if (charBufLength == 0) { + return -1; + } + + /* define hex string Table */ + UCHAR hexSymb[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + + /* calculate corresponding hex string from charBuffer */ + for (i=0;i>4)&0x0f; /* upper nibble */ + c2 = (charBuf[i])&0x0f; /* lower nibble */ + + string[i*2] = hexSymb[c1]; /* convert to string */ + string[i*2+1] = hexSymb[c2]; /* convert to string */ + } + + /* terminate string */ + string[charBufLength<<1]='\0'; + + return 0; + +} + +INT hexString2CharBuf(const char *string, UCHAR *charBuf, UINT charBufLength) +{ + UINT i, k = 0; + UCHAR hNibble, lNibble; + + /* sanity checks */ + if (string[0] == '\0') { + return -1; /* invalid string size */ + } + + if (charBufLength<=0){ + return -2; /* invalid buffer size */ + } + + /* convert to hex characters to corresponding 8bit value */ + for (i=0;(string[i]!='\0')&&((i>>1)>1; + hNibble = hexChar2Dec(string[i]); + lNibble = hexChar2Dec(string[i+1]); + if ((hNibble == 16) || (lNibble == 16)) { + return -3; /* invalid character */ + } + charBuf[k] = ((hNibble<<4)&0xf0) + lNibble; + } + + /* check if last character was string terminator */ + if ((string[i-2]!=0) && (string[i]!=0)) { + return -1; /* invalid string size */ + } + + /* fill charBuffer with zeros */ + for (i=k+1;i= '0') && (c <= '9')) + r = c-'0'; + else if ((c >= 'a') && (c <= 'f')) + r = c-'a'+10; + else if ((c >= 'A') && (c <= 'F')) + r = c-'A'+10; + else + r = 16; /* invalid hex character */ + + return (UCHAR)r; +} + diff --git a/libSYS/src/genericStds.cpp b/libSYS/src/genericStds.cpp new file mode 100644 index 00000000..89c422cd --- /dev/null +++ b/libSYS/src/genericStds.cpp @@ -0,0 +1,496 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): + Description: - Generic memory, stdio, string, etc. function wrappers or + builtins. + - OS dependant function wrappers. + +******************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS + +#include + +#include "genericStds.h" + +/* library info */ +#define SYS_LIB_VL0 1 +#define SYS_LIB_VL1 3 +#define SYS_LIB_VL2 8 +#define SYS_LIB_TITLE "System Integration Library" +#ifdef __ANDROID__ +#define SYS_LIB_BUILD_DATE "" +#define SYS_LIB_BUILD_TIME "" +#else +#define SYS_LIB_BUILD_DATE __DATE__ +#define SYS_LIB_BUILD_TIME __TIME__ +#endif + + #include + #include + #include + #include + + +/*************************************************************** + * memory allocation monitoring variables + ***************************************************************/ + + +/* Include OS/System specific implementations. */ +#if defined(__linux__) && !defined(__ANDROID__) /* cppp replaced: elif */ + #include "linux/genericStds_linux.cpp" +#endif + + +#if !(defined(USE_BUILTIN_STRING_FUNCTIONS) || defined(__SYMBIAN32__)) +#include +#include +#include + +#ifndef FUNCTION_FDKprintf +void FDKprintf( const char* szFmt, ...) { + va_list ap; + va_start(ap, szFmt); + vprintf(szFmt, ap); + va_end(ap); +#ifdef ARCH_WA_FLUSH_CONSOLE + fflush(stdout); +#endif +} +#endif + +#ifndef FUNCTION_FDKprintfErr +void FDKprintfErr( const char* szFmt, ...) { + va_list ap; + va_start(ap, szFmt); +#if defined(ARCH_WA_SLOWCON) + vprintf(szFmt, ap); +#else + vfprintf(stderr, szFmt, ap); +#endif + va_end(ap); +#ifdef ARCH_WA_FLUSH_CONSOLE + fflush(stderr); +#endif +} +#endif + +int FDKgetchar(void) { return getchar(); } + +INT FDKfprintf(FDKFILE *stream, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vfprintf((FILE*)stream, format, ap); + va_end(ap); + return chars; +} + +#ifndef FUNCTION_FDKsprintf +INT FDKsprintf(char *str, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vsprintf(str, format, ap); + va_end(ap); + return chars; +} +#endif + +#else + +void FDKprintf( const char* szFmt, ...) { /* stub! */; } +void FDKprintfErr( const char* szFmt, ...) { /* stub! */; } +INT FDKfprintf(FILE *stream, const char *format, ...) { /*stub ! */; } +INT FDKsprintf(char *str, const char *format, ...) { /* stub! */; } + +#endif + +/************************************************************************************************/ + + +const char *FDKstrchr(const char *s, INT c) { return strchr(s, c); } +const char *FDKstrstr(const char *haystack, const char *needle) { return strstr(haystack, needle); } +#ifndef FUNCTION_FDKstrcpy +char *FDKstrcpy(char *dest, const char *src) { return strcpy(dest, src); } +#endif +char *FDKstrncpy(char *dest, const char *src, UINT n) { return strncpy(dest, src, n); } + +/************************************************************************* + * DYNAMIC MEMORY management (heap) + *************************************************************************/ + +#ifndef FUNCTION_FDKcalloc +void *FDKcalloc (const UINT n, const UINT size) +{ + void* ptr; + + ptr = calloc(n, size); + + return ptr; +} +#endif + +#ifndef FUNCTION_FDKmalloc +void *FDKmalloc (const UINT size) +{ + void* ptr; + + ptr = malloc(size); + + return ptr; +} +#endif + +#ifndef FUNCTION_FDKfree +void FDKfree (void *ptr) +{ + /* FDKprintf("f, heapSize: %d\n", heapSizeCurr); */ + free((INT*)ptr); +} +#endif + +#ifndef FUNCTION_FDKaalloc +void *FDKaalloc(const UINT size, const UINT alignment) +{ + void *addr, *result=NULL; + addr = FDKcalloc(1, size + alignment + sizeof(void*)); /* Malloc and clear memory. */ + + if (addr!=NULL) + { + result = ALIGN_PTR((unsigned char*)addr + sizeof(void*)); /* Get aligned memory base address. */ + *(((void**)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + } + + return result; /* Return aligned address. */ +} +#endif + +#ifndef FUNCTION_FDKafree +void FDKafree (void *ptr) +{ + void *addr; + addr = *(((void**)ptr)-1); /* Get pointer to malloc'ed memory. */ + FDKfree(addr); /* Free malloc'ed memory area. */ +} +#endif + + +#ifndef FUNCTION_FDKcalloc_L + +/*--------------------------------------------------------------------------* + * DATA MEMORY L1/L2 (fallback) + *--------------------------------------------------------------------------*/ + + + +/*--------------------------------------------------------------------------* + * FDKcalloc_L + *--------------------------------------------------------------------------*/ +void *FDKcalloc_L(const UINT dim, const UINT size, MEMORY_SECTION s) +{ + int a_size; + + if (s == SECT_DATA_EXTERN) + goto fallback; + + a_size = ((dim*size+3)&0xfffffffc); /* force 4 byte alignment (1111 .... 1111 1100) */ + + + + + + //printf("Warning, out of internal memory\n"); + +fallback: + return FDKcalloc(dim, size); +} +#endif /* FUNCTION_FDKcalloc_L */ + +#ifndef FUNCTION_FDKfree_L +void FDKfree_L (void *p) +{ + + FDKfree(p); +} +#endif /* FUNCTION_FDKfree_L */ + +#ifndef FUNCTION_FDKaalloc_L +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s) +{ + void *addr, *result=NULL; + addr = FDKcalloc_L(1, size + alignment + sizeof(void*), s); /* Malloc and clear memory. */ + + if (addr!=NULL) + { + result = ALIGN_PTR((unsigned char *)addr + sizeof(void*)); /* Get aligned memory base address. */ + *(((void**)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + } + + return result; /* Return aligned address. */ +} +#endif + +#ifndef FUNCTION_FDKafree_L +void FDKafree_L (void *ptr) +{ + void *addr; + + addr = *(((void**)ptr)-1); /* Get pointer to malloc'ed memory. */ + FDKfree_L(addr); /* Free malloc'ed memory area. */ +} +#endif + + + +/*--------------------------------------------------------------------------------------- + * FUNCTION: FDKmemcpy + * DESCRIPTION: - copies memory from "src" to "dst" with length "size" bytes + * - compiled with FDK_DEBUG will give you warnings + *---------------------------------------------------------------------------------------*/ +void FDKmemcpy(void *dst, const void *src, const UINT size) +{ + + /* do the copy */ + memcpy(dst, src, size); +} + +void FDKmemmove(void *dst, const void *src, const UINT size) { memmove(dst, src, size); } +void FDKmemset(void *memPtr, const INT value, const UINT size) { memset(memPtr, value, size); } +void FDKmemclear(void *memPtr, const UINT size) { FDKmemset(memPtr,0,size); } +UINT FDKstrlen(const char *s) { return (UINT)strlen(s); } + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size) { return memcmp(s1, s2, size); } +INT FDKstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); } +INT FDKstrncmp(const char *s1, const char *s2, const UINT size) { return strncmp(s1, s2, size); } + + +/* Math function wrappers. Only intended for compatibility, not to be highly optimized. */ + +INT FDKabs(INT j) { return abs(j); } +double FDKfabs(double x) { return fabs(x); } +double FDKpow(double x, double y) { return pow(x,y); } +double FDKsqrt(double x) { return sqrt(x); } +double FDKatan(double x) { return atan(x); } +double FDKlog(double x) { return log(x); } +double FDKsin(double x) { return sin(x); } +double FDKcos(double x) { return cos(x); } +double FDKexp(double x) { return exp(x); } +double FDKatan2(double y, double x) { return atan2(y, x); } +double FDKacos(double x) { return acos(x); } +double FDKtan(double x) { return tan(x); } +double FDKfloor(double x) { return floor(x); } +double FDKceil(double x) { return ceil(x); } + +INT FDKatoi(const char *nptr) { return atoi(nptr); } +long FDKatol(const char *nptr) { return atol(nptr); } +float FDKatof(const char *nptr) { return (float)atof(nptr); } + + +/* ==================== FILE I/O ====================== */ + +#if !defined(FUNCTION_FDKfopen) +FDKFILE *FDKfopen(const char *filename, const char *mode) { return fopen(filename, mode); } +#endif +#if !defined(FUNCTION_FDKfclose) +INT FDKfclose(FDKFILE *fp) { return fclose((FILE*)fp);} +#endif +#if !defined(FUNCTION_FDKfseek) +INT FDKfseek(FDKFILE *fp, LONG OFFSET, int WHENCE) { return fseek((FILE*)fp, OFFSET, WHENCE);} +#endif +#if !defined(FUNCTION_FDKftell) +INT FDKftell(FDKFILE *fp) { return ftell((FILE*)fp); } +#endif +#if !defined(FUNCTION_FDKfflush) +INT FDKfflush(FDKFILE *fp) { return fflush((FILE*)fp); } +#endif +const INT FDKSEEK_SET = SEEK_SET; +const INT FDKSEEK_CUR = SEEK_CUR; +const INT FDKSEEK_END = SEEK_END; + +#if !defined(FUNCTION_FDKfwrite) +UINT FDKfwrite(void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { return fwrite(ptrf, size, nmemb, (FILE*)fp); } +#endif +#if !defined(FUNCTION_FDKfread) +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp) { return fread(dst, size, nmemb, (FILE*)fp); } +#endif +#if !defined(FUNCTION_FDKfgets) +char* FDKfgets(void *dst, INT size, FDKFILE *fp) { return fgets((char *)dst, size, (FILE*)fp); } +#endif +#if !defined(FUNCTION_FDKrewind) +void FDKrewind(FDKFILE *fp) { FDKfseek((FILE*)fp,0,FDKSEEK_SET); } +#endif + + +UINT FDKfwrite_EL(void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { + + if (IS_LITTLE_ENDIAN()) { + FDKfwrite(ptrf, size, nmemb, fp); + } else { + UINT n; + INT s; + + UCHAR *ptr = (UCHAR*) ptrf; + + for (n=0; n=0; s--) { + //FDKprintf("char = %c\n", (char)*(ptr+s)); + FDKfwrite(ptr + s, 1, 1, fp); + } + ptr = ptr + size; + } + } + return nmemb; +} + + +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp) { + UINT n, s0, s1, err; + UCHAR tmp, *ptr; + UCHAR tmp24[3]; + + /* Enforce alignment of 24 bit data. */ + if (size == 3) { + ptr = (UCHAR*)dst; + err = 0; + for (n=0; n 1) { + ptr = (UCHAR*)dst; + for (n=0; n +#endif + + + + +void FDKprintDisclaimer(void) +{ + FDKprintf( + "This program is protected by copyright law and international treaties.\n" \ + "Any reproduction or distribution of this program, or any portion\n" \ + "of it, may result in severe civil and criminal penalties, and will be\n" \ + "prosecuted to the maximum extent possible under law.\n\n"); +} + diff --git a/libSYS/src/linux/FDK_stackload_linux.cpp b/libSYS/src/linux/FDK_stackload_linux.cpp new file mode 100644 index 00000000..82fa9ab8 --- /dev/null +++ b/libSYS/src/linux/FDK_stackload_linux.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Manuel Jander + Description: Stack consumption information gathering. + +******************************************************************************/ + diff --git a/libSYS/src/linux/audio_linux.cpp b/libSYS/src/linux/audio_linux.cpp new file mode 100644 index 00000000..835b27b3 --- /dev/null +++ b/libSYS/src/linux/audio_linux.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author: Manuel Jander + Description: Audio support + +******************************************************************************/ + diff --git a/libSYS/src/linux/coresup_linux.cpp b/libSYS/src/linux/coresup_linux.cpp new file mode 100644 index 00000000..9e6fa855 --- /dev/null +++ b/libSYS/src/linux/coresup_linux.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Manuel Jander + Description: System support routines + +******************************************************************************/ + diff --git a/libSYS/src/linux/genericStds_linux.cpp b/libSYS/src/linux/genericStds_linux.cpp new file mode 100644 index 00000000..da375c0b --- /dev/null +++ b/libSYS/src/linux/genericStds_linux.cpp @@ -0,0 +1,294 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Manuel Jander + Description: Linux genericStds (mostly kernel SRAM driver bindings) + +******************************************************************************/ + + +/* + * NOTE: it makes only sense to enable this if you also have the corresponding + * GNU/Linux kernel driver to access fast SRAM. + */ +#if defined(__arm__) /* || defined(__mips__) */ + +/** + * EABI static linking problem workaround + * + * These function are normally present in libc.a but + * apparently can be linked only statically. + * While using C++ (iisisoff) that is a problem, + * because it wont work (static global constructors + * cause problems with static linked programs). + * So the workaround is to include those functions here, + * because libSYS.a is linked statically, and libc can be + * linked dynamically as usual. + * + * Add more EABI functions here if you get unresolved + * symbols of EABI functions. + */ +#include + +#ifdef __cplusplus +extern "C" { +#endif +void __aeabi_memcpy(void *dest, void *src, int size) +{ + memcpy(dest, src, size); +} +void __aeabi_memcpy4(void *dest, void *src, int size) +{ + memcpy(dest, src, size); +} +void __aeabi_memmove4(void *dest, void *src, int size) +{ + memmove(dest, src, size); +} +void __aeabi_memclr(void *ptr, int size) +{ + memset(ptr, 0, size); +} +void __aeabi_memclr4(void *ptr, int size) +{ + memset(ptr, 0, size); +} +#ifdef __cplusplus +} +#endif + +/* Include Linux kernel config, or set ARCH and processor macros directly */ +/* +#define CONFIG_ARCH_MXC +#define CONFIG_ARCH_MX25 +*/ + +#if defined(CONFIG_ARCH_OMAP3) +#define KERNEL_SRAM_SIZE 65536 +#elif defined(CONFIG_ARCH_MX31) +#define KERNEL_SRAM_SIZE 16384 +#elif defined(CONFIG_ARCH_MX25) +#define KERNEL_SRAM_SIZE 131072 +#elif defined(CONFIG_ARCH_MX35) +#define KERNEL_SRAM_SIZE 131072 +#else +#define KERNEL_SRAM_SIZE 0 +#endif + +#if (KERNEL_SRAM_SIZE > 0) +#define KERNEL_SCRATCH_SIZE (4096) +#define FDK_SCRATCHBUF_SIZE (KERNEL_SCRATCH_SIZE/sizeof(INT)) +#define DATA_L1_A_SIZE (KERNEL_SRAM_SIZE-KERNEL_SCRATCH_SIZE) + +#define RESOURCE_scratchBuffer +#define FUNCTION_FDKprolog +#define FUNCTION_FDKepilog + +static unsigned char *L1_DATA_A=NULL; +static unsigned char *_a=NULL; + + +#ifdef RESOURCE_scratchBuffer +static INT *__scratchBuffer; +static unsigned char *__pScratchBuffer = NULL; +#endif + + +#ifdef __linux__ + +#include +#include +#include +#include +#include +#include + +static int fd; +static inline void * getSram(void) +{ + unsigned long *ptr = NULL; + + /* Open driver */ + fd = open("/dev/sram", 0); + if (fd < 0) + { + printf("Unable to open /dev/sram. Fallback to malloc\n"); + /* Signal "no sram driver at use". */ + fd = -1; + /* Return malloced pointer (fallback) */ + return FDKaalloc(KERNEL_SRAM_SIZE, 8); + } + + /* Get memory mapped into CPU (virtual) address space */ + ptr = (unsigned long *)mmap(NULL, KERNEL_SRAM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if(ptr == MAP_FAILED) + { + printf("Unable to mmap(). Fallback to malloc\n"); + /* Give up on the sram driver */ + close(fd); + /* Signal "no sram driver at use". */ + fd = -1; + /* Return malloced pointer (fallback) */ + ptr = (unsigned long *)FDKaalloc(KERNEL_SRAM_SIZE, 8); + } + + + /* Return pointer to sram */ + return (void*)ptr; +} + +static inline void freeSram(void* ptr) +{ + /* Check if sram driver is being used. */ + if (fd == -1) + { + FDKafree(ptr); + return; + } + + /* Unmap memory */ + munmap(ptr, KERNEL_SRAM_SIZE); + /* Close driver */ + close(fd); + + return; +} + +#else + +static inline void * getSram(void) +{ + return FDKaalloc(KERNEL_SRAM_SIZE, 8); +} +static inline void * freeSram(void* ptr) +{ + FDKafree(ptr); +} + +#endif + + +#ifdef FUNCTION_FDKprolog +void FDKprolog(void) +{ + unsigned char *addr = (unsigned char*)getSram(); + + + if (addr == NULL) + { + printf("SRAM allocation failed ! This is fatal.\n"); + exit(-1); + } + +#ifdef RESOURCE_scratchBuffer + __scratchBuffer = (INT*) ( addr + (KERNEL_SRAM_SIZE-KERNEL_SCRATCH_SIZE) ); + __pScratchBuffer = addr + (KERNEL_SRAM_SIZE); +#endif + + printf("SRAM @ 0x%08x\n", (unsigned int) addr); + atexit(FDKepilog); + + FDKprolog_generic(); +} +#endif + +#ifdef FUNCTION_FDKepilog +void FDKepilog(void) +{ + /* Because of atexit(), make sure to call this only once */ + if (L1_DATA_A != NULL) + { + freeSram(L1_DATA_A); + L1_DATA_A = NULL; + + FDKepilog_generic(); + } +} +#endif + +#endif /* KERNEL_SRAM > 0 */ + +#endif /* ifdef __arm__ */ + diff --git a/libSYS/src/linux/uart_linux.cpp b/libSYS/src/linux/uart_linux.cpp new file mode 100644 index 00000000..dee5694a --- /dev/null +++ b/libSYS/src/linux/uart_linux.cpp @@ -0,0 +1,90 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author: Manuel Jander + Description: UART support + +******************************************************************************/ + diff --git a/libSYS/src/mips/genericStds_mips.cpp b/libSYS/src/mips/genericStds_mips.cpp new file mode 100644 index 00000000..e08ec481 --- /dev/null +++ b/libSYS/src/mips/genericStds_mips.cpp @@ -0,0 +1,292 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Manuel Jander + Description: + +******************************************************************************/ + +#define RESOURCE_scratchBuffer +#define FUNCTION_FDKprolog +#define FUNCTION_FDKepilog + +#define MIPS_VIRTUAL_START (0x80000000) +/* value below is defined in simulator config (MipsMemIntf-{24KE,4KE}.cfg) */ +#define MIPS_SDE_SCRATCHPAD (0x00058000) + +//#define MIPS_SRAM_SIZE (32768) +#define MIPS_SRAM_SIZE (4096) + +#define MIPS_SCRATCH_SIZE (4096) +#define DATA_L1_A_SIZE (MIPS_SRAM_SIZE-MIPS_SCRATCH_SIZE) + + + + +#ifdef RESOURCE_scratchBuffer +#define FDK_SCRATCHBUF_SIZE 1024 +static LONG *___scratchBuffer = NULL; +static LONG *__scratchBuffer = NULL; +static unsigned char *__pScratchBuffer = NULL; +#endif + + +#ifdef __linux__ + +#include +#include +#include +#include +#include +#include + +static int fd; +static inline void * getSram(void) +{ + unsigned long *ptr = NULL; + + /* Open driver */ + fd = open("/dev/sram", 0); + if (fd < 0) + { + printf("Unable to access sram. Fallback to malloc\n"); + /* Signal "no sram driver at use". */ + fd = -1; + /* Return malloced pointer (fallback) */ + return malloc(MIPS_SRAM_SIZE); + } + + /* Get memory mapped into CPU (virtual) address space */ + ptr = (unsigned long *)mmap(NULL, MIPS_SRAM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if(ptr == MAP_FAILED) + { + printf("Unable to access sram. Fallback to malloc\n"); + /* Give up on the sram driver */ + close(fd); + /* Signal "no sram driver at use". */ + fd = -1; + /* Return malloced pointer (fallback) */ + ptr = (unsigned long *)malloc(MIPS_SRAM_SIZE); + } + + + /* Return pointer to sram */ + return (void*)ptr; +} + +static inline void freeSram(void* ptr) +{ + /* Check if sram driver is being used. */ + if (fd == -1) + { + free(ptr); + return; + } + + /* Unmap memory */ + munmap(ptr, MIPS_SRAM_SIZE); + /* Close driver */ + close(fd); + + return; +} + +#elif defined(__SDE_MIPS__) + +#include +#include + +static int hasISPRAM, hasDSPRAM; + +static inline void * getSram(void) +{ + void *addr; + unsigned int Config; + + Config = mips_getconfig(); + hasISPRAM = (Config >> 24) & 1; + hasDSPRAM = (Config >> 23) & 1; + + FDKprintf("Config ISP/DSP: %d/%d\n", hasISPRAM, hasDSPRAM); + + if (hasDSPRAM) { + long paddr, laddr; + + FDKprintf("wrong\n"); + paddr = MIPS_SDE_SCRATCHPAD; + /* Fixed mapping of kseg0: 0x80000000-0x9fffffff virtual => 0x00000000-0x1fffffff physical */ + laddr = MIPS_VIRTUAL_START + MIPS_SDE_SCRATCHPAD; + addr = (void*)(laddr); + } else { + FDKprintf("ok\n"); + addr = malloc(MIPS_SRAM_SIZE); + FDKprintf("addr %d\n", (int)addr); + } + return addr; +} +static inline void freeSram(void* ptr) +{ + if (!hasDSPRAM) { + free(ptr); + } +} + +#else + +static inline void * getSram(void) +{ + return malloc(MIPS_SRAM_SIZE); +} +static inline void freeSram(void* ptr) +{ + free(ptr); +} + +#endif + + +#ifdef FUNCTION_FDKprolog +void FDKprolog(void) +{ + unsigned char *addr; + +#ifdef _MIPS_ARCH_MIPS32R2 + unsigned status; + asm volatile("mfc0 %0, $12, 0;\n" : "=r" (status)); + status |= (1 << 24); + asm volatile("mtc0 %0, $12, 0;\n" :: "r" (status)); +#endif + + addr = (unsigned char*)getSram(); + if (addr == NULL) { + FDKprintfErr("SRAM allocation failed ! This is fatal.\n"); + exit(-1); + } else { + FDKprintf("SRAM @ 0x%08x, size = 0x%x\n", (unsigned int) addr, MIPS_SRAM_SIZE); + } + + +#ifdef RESOURCE_scratchBuffer + ___scratchBuffer = (LONG*)(addr + MIPS_SRAM_SIZE - MIPS_SCRATCH_SIZE); +#endif + + atexit(FDKepilog); + + FDKprolog_generic(); +} +#endif + +#ifdef FUNCTION_FDKepilog +void FDKepilog(void) +{ + +#ifdef _MIPS_ARCH_MIPS32R2 + unsigned status; + asm volatile("mfc0 %0, $12, 0;\n" : "=r" (status)); + status &= ~(1 << 24); + asm volatile("mtc0 %0, $12, 0;\n" :: "r" (status)); +#endif + + FDKepilog_generic(); +} +#endif + + +#if !defined(__linux__) + +#define FUNCTION_FDKclock + +#ifndef MIPS_CPU_CLK +#define MIPS_CPU_CLK 100000000 +#endif + +INT FDKclock(void) { + INT clk; + + asm volatile ("mfc0 %0,$9 " : "=r" (clk)); + return clk; +} + +#endif /* !defined(__linux__) */ diff --git a/libSYS/src/wav_file.cpp b/libSYS/src/wav_file.cpp new file mode 100644 index 00000000..58bcfaad --- /dev/null +++ b/libSYS/src/wav_file.cpp @@ -0,0 +1,560 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/************************** Fraunhofer IIS FDK SysLib ********************** + + Author(s): Eric Allamanche + Description: a rudimentary wav file interface + +******************************************************************************/ + + + +#include "wav_file.h" +#include "genericStds.h" + + +static INT_PCM ulaw2pcm (UCHAR ulawbyte); + +/*! + * + * \brief Read header from a WAVEfile. Host endianess is handled accordingly. + * \wav->fp filepointer of type FILE*. + * \wavinfo SWavInfo struct where the decoded header info is stored into. + * \return 0 on success and non-zero on failure. + * + */ +INT WAV_InputOpen (HANDLE_WAV *pWav, const char *filename) +{ + HANDLE_WAV wav = (HANDLE_WAV)FDKcalloc(1, sizeof(struct WAV)); + INT offset; + + if (wav == NULL) { + FDKprintfErr("WAV_InputOpen(): Unable to allocate WAV struct.\n"); + goto error; + } + + wav->fp = FDKfopen(filename, "rb"); + if (wav->fp == NULL) { + FDKprintfErr("WAV_InputOpen(): Unable to open wav file. %s\n", filename); + goto error; + } + + /* read RIFF-chunk */ + if (FDKfread(&(wav->header.riffType), 1, 4, wav->fp) != 4) { + FDKprintfErr("WAV_InputOpen(): couldn't read RIFF_ID\n"); + goto error; /* bad error "couldn't read RIFF_ID" */ + } + if (FDKstrncmp("RIFF", wav->header.riffType, 4)) { + FDKprintfErr("WAV_InputOpen(): RIFF descriptor not found.\n") ; + goto error; + } + + /* Read RIFF size. Ignored. */ + FDKfread_EL(&(wav->header.riffSize), 4, 1, wav->fp); + + /* read WAVE-chunk */ + if (FDKfread(&wav->header.waveType, 1, 4, wav->fp) !=4) { + FDKprintfErr("WAV_InputOpen(): couldn't read format\n"); + goto error; /* bad error "couldn't read format" */ + } + if (FDKstrncmp("WAVE", wav->header.waveType, 4)) { + FDKprintfErr("WAV_InputOpen(): WAVE chunk ID not found.\n") ; + goto error; + } + + /* read format-chunk */ + if (FDKfread(&(wav->header.formatType), 1, 4, wav->fp) != 4) { + FDKprintfErr("WAV_InputOpen(): couldn't read format_ID\n"); + goto error; /* bad error "couldn't read format_ID" */ + } + if (FDKstrncmp("fmt", wav->header.formatType, 3)) { + FDKprintfErr("WAV_InputOpen(): fmt chunk format not found.\n") ; + goto error; + } + + + FDKfread_EL(&wav->header.formatSize, 4, 1, wav->fp); /* should be 16 for PCM-format (uncompressed) */ + + + /* read info */ + FDKfread_EL(&(wav->header.compressionCode), 2, 1, wav->fp); + FDKfread_EL(&(wav->header.numChannels), 2, 1, wav->fp); + FDKfread_EL(&(wav->header.sampleRate), 4, 1, wav->fp); + FDKfread_EL(&(wav->header.bytesPerSecond), 4, 1, wav->fp); + FDKfread_EL(&(wav->header.blockAlign), 2, 1, wav->fp); + FDKfread_EL(&(wav->header.bitsPerSample), 2, 1, wav->fp); + + offset = wav->header.formatSize - 16; + + /* Wave format extensible */ + if (wav->header.compressionCode == 0xFFFE) { + static const UCHAR guidPCM[16] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 + }; + USHORT extraFormatBytes, validBitsPerSample; + UCHAR guid[16]; + INT i; + + /* read extra bytes */ + FDKfread_EL(&(extraFormatBytes), 2, 1, wav->fp); + offset -= 2; + + if (extraFormatBytes >= 22) { + FDKfread_EL(&(validBitsPerSample), 2, 1, wav->fp); + FDKfread_EL(&(wav->channelMask), 4, 1, wav->fp); + FDKfread_EL(&(guid), 16, 1, wav->fp); + + /* check for PCM GUID */ + for (i = 0; i < 16; i++) if (guid[i] != guidPCM[i]) break; + if (i == 16) wav->header.compressionCode = 0x01; + + offset -= 22; + } + } + + /* Skip rest of fmt header if any. */ + for (;offset > 0; offset--) { + FDKfread(&wav->header.formatSize, 1, 1, wav->fp); + } + + do { + /* Read data chunk ID */ + if (FDKfread(wav->header.dataType, 1, 4, wav->fp) != 4) { + FDKprintfErr("WAV_InputOpen(): Unable to read data chunk ID.\n"); + FDKfree(wav); + goto error; + } + + /* Read chunk length. */ + FDKfread_EL(&offset, 4, 1, wav->fp); + + /* Check for data chunk signature. */ + if (FDKstrncmp("data", wav->header.dataType, 4) == 0) { + wav->header.dataSize = offset; + break; + } + /* Jump over non data chunk. */ + for (;offset > 0; offset--) { + FDKfread(&(wav->header.dataSize), 1, 1, wav->fp); + } + } while (!FDKfeof(wav->fp)); + + /* return success */ + *pWav = wav; + return 0; + + /* Error path */ +error: + + if (wav) { + if (wav->fp) { + FDKfclose(wav->fp); + wav->fp = NULL; + } + FDKfree(wav); + } + + *pWav = NULL; + + return -1; +} + +/*! + * + * \brief Read samples from a WAVEfile. The samples are automatically reorder to the native + * host endianess and scaled to full scale of the INT_PCM type, from whatever bps the WAVEfile + * had specified in its haader data. + * + * \wav HANDLE_WAV of the wav file. + * \buffer Pointer to store read data. + * \numSamples Desired number of samples to read. + * \nBits sample size in bits to be used for the buffer + * + * \return Number of samples actually read. + * + */ + +INT WAV_InputRead (HANDLE_WAV wav, void *buffer, UINT numSamples, int nBits) +{ + UINT result = 0 ; + UINT i; + SCHAR *bptr = (SCHAR*)buffer; + LONG *lptr = (LONG*)buffer; + SHORT *sptr = (SHORT*)buffer; + + switch (wav->header.compressionCode) + { + case 0x01: /* PCM uncompressed */ + if (nBits == wav->header.bitsPerSample) { + result = FDKfread_EL(buffer, wav->header.bitsPerSample >> 3, numSamples, wav->fp) ; + } else { + result = 0; + for (i=0; iheader.bitsPerSample >> 3, 1, wav->fp) ; + + /* Move read bits to lower bits of LONG. */ + if ( !IS_LITTLE_ENDIAN() && wav->header.bitsPerSample != 24 && wav->header.bitsPerSample < 32) { + tmp >>= (32-wav->header.bitsPerSample); + } + + /* Full scale */ + if (wav->header.bitsPerSample > nBits) + tmp >>= (wav->header.bitsPerSample-nBits); + else + tmp <<= (nBits-wav->header.bitsPerSample); + + if (nBits == 8) + *bptr++ = (SCHAR) tmp; + if (nBits == 16) + *sptr++ = (SHORT) tmp; + if (nBits == 32) + *lptr++ = (LONG) tmp; + } + } + break; + + case 0x07: /* u-Law compression */ + for (i=0; ifp) ; + sptr[i] = ulaw2pcm(bptr[i<<1]) ; + } + break ; + + default: + FDKprintf("WAV_InputRead(): unsupported data-compression!!") ; + break ; + } + return result ; +} + +void WAV_InputClose(HANDLE_WAV *pWav) +{ + HANDLE_WAV wav = *pWav; + + if (wav != NULL) { + if (wav->fp != NULL) { + FDKfclose(wav->fp); + wav->fp = NULL; + } + if (wav) { + FDKfree(wav); + } + } + *pWav = NULL; +} + +/* conversion of u-law to linear coding */ +static INT_PCM ulaw2pcm (UCHAR ulawbyte) +{ + static const INT exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 } ; + INT sign, exponent, mantissa, sample ; + + ulawbyte = (UCHAR)~ulawbyte ; + sign = (ulawbyte & 0x80) ; + exponent = (ulawbyte >> 4) & 0x07 ; + mantissa = ulawbyte & 0x0F ; + + sample = exp_lut[exponent] + (mantissa << (exponent + 3)) ; + if (sign != 0) + sample = -sample ; + + return (INT_PCM)sample ; +} + +/************** Writer ***********************/ + +static UINT LittleEndian32(UINT v) +{ + if (IS_LITTLE_ENDIAN()) + return v ; + else + return (v & 0x000000FF) << 24 | (v & 0x0000FF00) << 8 | (v & 0x00FF0000) >> 8 | (v & 0xFF000000) >> 24; +} + +static SHORT LittleEndian16(SHORT v) +{ + if (IS_LITTLE_ENDIAN()) + return v; + else + return (SHORT)(((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF)); +} + +static USHORT Unpack(USHORT v) +{ + if (IS_LITTLE_ENDIAN()) + return v; + else + return (SHORT)(((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF)); +} + +/** + * WAV_OutputOpen + * \brief Open WAV output/writer handle + * \param pWav pointer to WAV handle to be returned + * \param sampleRate desired samplerate of the resulting WAV file + * \param numChannels desired number of audio channels of the resulting WAV file + * \param bitsPerSample desired number of bits per audio sample of the resulting WAV file + * + * \return value: 0: ok + * -1: error + */ +INT WAV_OutputOpen(HANDLE_WAV *pWav, const char *outputFilename, INT sampleRate, INT numChannels, INT bitsPerSample) +{ + HANDLE_WAV wav = (HANDLE_WAV)FDKcalloc(1, sizeof(struct WAV)); + UINT size = 0; + + if (wav == NULL) { + FDKprintfErr("WAV_OutputOpen(): Unable to allocate WAV struct.\n"); + goto bail; + } + + if (bitsPerSample != 16 && bitsPerSample != 24 && bitsPerSample != 32) + { + FDKprintfErr("WAV_OutputOpen(): Invalid argument (bitsPerSample).\n"); + goto bail; + } + + wav->fp = FDKfopen(outputFilename, "wb"); + if (wav->fp == NULL) + { + FDKprintfErr("WAV_OutputOpen(): unable to create file %s\n", outputFilename); + goto bail; + } + + FDKstrcpy(wav->header.riffType, "RIFF"); + wav->header.riffSize = LittleEndian32(0x7fffffff); /* in case fseek() doesn't work later in WAV_OutputClose() */ + FDKstrcpy(wav->header.waveType, "WAVE"); + + FDKstrcpy(wav->header.formatType, "fmt "); + wav->header.formatSize = LittleEndian32(16); + + wav->header.compressionCode = LittleEndian16(0x01); + wav->header.bitsPerSample = LittleEndian16((SHORT)bitsPerSample); + wav->header.numChannels = LittleEndian16((SHORT)numChannels); + wav->header.blockAlign = LittleEndian16((SHORT)(numChannels * (bitsPerSample >> 3))); + wav->header.sampleRate = LittleEndian32(sampleRate); + wav->header.bytesPerSecond = LittleEndian32(sampleRate * wav->header.blockAlign); + FDKstrcpy(wav->header.dataType, "data"); + wav->header.dataSize = LittleEndian32(0x7fffffff - 36); + + + size = sizeof(WAV_HEADER); + if (FDKfwrite(&wav->header, 1, size, wav->fp) != size) + { + FDKprintfErr("WAV_OutputOpen(): error writing to output file %s\n", outputFilename); + goto bail; + } + + + wav->header.dataSize = wav->header.riffSize = 0; + + *pWav = wav; + + return 0; + +bail: + if (wav) { + if (wav->fp) { + FDKfclose(wav->fp); + } + FDKfree(wav); + } + + pWav = NULL; + + return -1; +} + + +/** + * WAV_OutputWrite + * \brief Write data to WAV file asociated to WAV handle + * + * \param wav handle of wave file + * \param sampleBuffer pointer to audio samples, right justified integer values + * \param nBufBits size in bits of each audio sample in sampleBuffer + * \param nSigBits amount of significant bits of each nBufBits in sampleBuffer + * + * \return value: 0: ok + * -1: error + */ +INT WAV_OutputWrite(HANDLE_WAV wav, void *sampleBuffer, UINT numberOfSamples, int nBufBits, int nSigBits) +{ + SCHAR *bptr = (SCHAR*)sampleBuffer; + SHORT *sptr = (SHORT*)sampleBuffer; + LONG *lptr = (LONG*)sampleBuffer; + LONG tmp; + + int bps = Unpack(wav->header.bitsPerSample); + UINT i; + + /* Pack samples if required */ + if (bps == nBufBits && bps == nSigBits) { + if (FDKfwrite_EL(sampleBuffer, (bps>>3), numberOfSamples, wav->fp) != numberOfSamples) + { + FDKprintfErr("WAV_OutputWrite(): error: unable to write to file %d\n", wav->fp); + return -1; + } + } else { + for (i=0; i>= -shift; + else + tmp <<= shift; + + /* Write sample */ + result=FDKfwrite_EL(&tmp, bps>>3, 1, wav->fp); + if (result <= 0) { + FDKprintfErr("WAV_OutputWrite(): error: unable to write to file %d\n", wav->fp); + return -1; + } + } + } + + wav->header.dataSize += (numberOfSamples * (bps>>3)); + return 0; +} + + +/** + * WAV_OutputClose + * \brief Close WAV Output handle + * \param pWav pointer to WAV handle. *pWav is set to NULL. + */ +void WAV_OutputClose(HANDLE_WAV *pWav) +{ + HANDLE_WAV wav = *pWav; + UINT size = 0; + + if ( wav == NULL ) { + return; + } + + wav->header.dataSize = LittleEndian32(wav->header.dataSize); + wav->header.riffSize = LittleEndian32(wav->header.dataSize + 36); + + if (wav->fp != NULL) + { + if (FDKfseek(wav->fp, 0, FDKSEEK_SET)) { + FDKprintf("WAV_OutputClose(): fseek() failed.\n"); + } + + size = sizeof(WAV_HEADER); + if (FDKfwrite(&wav->header.riffType, 1, size, wav->fp) != size) + { + FDKprintfErr("WAV_OutputClose(): unable to write header\n"); + } + + if (FDKfclose(wav->fp)) + { + FDKprintfErr("WAV_OutputClose(): unable to close wav file\n"); + } + wav->fp = NULL; + } + + FDKfree(wav); + *pWav = NULL; +} + diff --git a/m4/.gitkeep b/m4/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/wavreader.c b/wavreader.c new file mode 100644 index 00000000..898eb9cf --- /dev/null +++ b/wavreader.c @@ -0,0 +1,193 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include "wavreader.h" +#include +#include +#include +#include + +#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +struct wav_reader { + FILE *wav; + uint32_t data_length; + + int format; + int sample_rate; + int bits_per_sample; + int channels; + int byte_rate; + int block_align; + + int streamed; +}; + +static uint32_t read_tag(struct wav_reader* wr) { + uint32_t tag = 0; + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + return tag; +} + +static uint32_t read_int32(struct wav_reader* wr) { + uint32_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + value |= fgetc(wr->wav) << 16; + value |= fgetc(wr->wav) << 24; + return value; +} + +static uint16_t read_int16(struct wav_reader* wr) { + uint16_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + return value; +} + +static void skip(FILE *f, int n) { + int i; + for (i = 0; i < n; i++) + fgetc(f); +} + +void* wav_read_open(const char *filename) { + struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr)); + long data_pos = 0; + memset(wr, 0, sizeof(*wr)); + + if (!strcmp(filename, "-")) + wr->wav = stdin; + else + wr->wav = fopen(filename, "rb"); + if (wr->wav == NULL) { + free(wr); + return NULL; + } + + while (1) { + uint32_t tag, tag2, length; + tag = read_tag(wr); + if (feof(wr->wav)) + break; + length = read_int32(wr); + if (!length || length >= 0x7fff0000) { + wr->streamed = 1; + length = ~0; + } + if (tag != TAG('R', 'I', 'F', 'F') || length < 4) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + tag2 = read_tag(wr); + length -= 4; + if (tag2 != TAG('W', 'A', 'V', 'E')) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + // RIFF chunk found, iterate through it + while (length >= 8) { + uint32_t subtag, sublength; + subtag = read_tag(wr); + if (feof(wr->wav)) + break; + sublength = read_int32(wr); + length -= 8; + if (length < sublength) + break; + if (subtag == TAG('f', 'm', 't', ' ')) { + if (sublength < 16) { + // Insufficient data for 'fmt ' + break; + } + wr->format = read_int16(wr); + wr->channels = read_int16(wr); + wr->sample_rate = read_int32(wr); + wr->byte_rate = read_int32(wr); + wr->block_align = read_int16(wr); + wr->bits_per_sample = read_int16(wr); + if (wr->format == 0xfffe) { + if (sublength < 28) { + // Insufficient data for waveformatex + break; + } + skip(wr->wav, 8); + wr->format = read_int32(wr); + skip(wr->wav, sublength - 28); + } else { + skip(wr->wav, sublength - 16); + } + } else if (subtag == TAG('d', 'a', 't', 'a')) { + data_pos = ftell(wr->wav); + wr->data_length = sublength; + if (!wr->data_length || wr->streamed) { + wr->streamed = 1; + return wr; + } + fseek(wr->wav, sublength, SEEK_CUR); + } else { + skip(wr->wav, sublength); + } + length -= sublength; + } + if (length > 0) { + // Bad chunk? + fseek(wr->wav, length, SEEK_CUR); + } + } + fseek(wr->wav, data_pos, SEEK_SET); + return wr; +} + +void wav_read_close(void* obj) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (wr->wav != stdin) + fclose(wr->wav); + free(wr); +} + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (format) + *format = wr->format; + if (channels) + *channels = wr->channels; + if (sample_rate) + *sample_rate = wr->sample_rate; + if (bits_per_sample) + *bits_per_sample = wr->bits_per_sample; + if (data_length) + *data_length = wr->data_length; + return wr->format && wr->sample_rate; +} + +int wav_read_data(void* obj, unsigned char* data, unsigned int length) { + struct wav_reader* wr = (struct wav_reader*) obj; + int n; + if (wr->wav == NULL) + return -1; + if (length > wr->data_length && !wr->streamed) + length = wr->data_length; + n = fread(data, 1, length, wr->wav); + wr->data_length -= length; + return n; +} + diff --git a/wavreader.h b/wavreader.h new file mode 100644 index 00000000..57a13ffb --- /dev/null +++ b/wavreader.h @@ -0,0 +1,37 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef WAVREADER_H +#define WAVREADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +void* wav_read_open(const char *filename); +void wav_read_close(void* obj); + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length); +int wav_read_data(void* obj, unsigned char* data, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/win32/getopt.h b/win32/getopt.h new file mode 100644 index 00000000..7402521e --- /dev/null +++ b/win32/getopt.h @@ -0,0 +1,904 @@ +#ifndef __GETOPT_H__ +/** + * DISCLAIMER + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * + * The mingw-w64 runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Implementation of the `getopt', `getopt_long' and `getopt_long_only' + * APIs, for inclusion in the MinGW runtime library. + * + * This file is part of the MinGW32 package set. + * + * Written by Keith Marshall + * Copyright (C) 2008, 2009, 2011, 2012, MinGW.org Project. + * + * --------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice, this permission notice, and the following + * disclaimer shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * --------------------------------------------------------------------------- + * + */ + +#define __GETOPT_H__ + +/* All the headers include this file. */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int optind; /* index of first non-option in argv */ +extern int optopt; /* single option character, as parsed */ +extern int opterr; /* flag to enable built-in diagnostics... */ + /* (user may set to zero, to suppress) */ + +extern char *optarg; /* pointer to argument of current option */ + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +extern int getopt(int nargc, char * const *nargv, const char *options); + +#ifdef _BSD_SOURCE +/* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset +extern int optreset; +#endif +#ifdef __cplusplus +} +#endif +/* + * POSIX requires the `getopt' API to be specified in `unistd.h'; + * thus, `unistd.h' includes this header. However, we do not want + * to expose the `getopt_long' or `getopt_long_only' APIs, when + * included in this manner. Thus, close the standard __GETOPT_H__ + * declarations block, and open an additional __GETOPT_LONG_H__ + * specific block, only when *not* __UNISTD_H_SOURCED__, in which + * to declare the extended API. + */ +#endif /* !defined(__GETOPT_H__) */ + +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) +#define __GETOPT_LONG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct option /* specification for a long form option... */ +{ + const char *name; /* option name, without leading hyphens */ + int has_arg; /* does it take an argument? */ + int *flag; /* where to save its status, or NULL */ + int val; /* its associated status value */ +}; + +enum /* permitted values for its `has_arg' field... */ +{ + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ +}; + +extern int getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +extern int getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +/* + * Previous MinGW implementation had... + */ +#ifndef HAVE_DECL_GETOPT +/* + * ...for the long form API only; keep this for compatibility. + */ +# define HAVE_DECL_GETOPT 1 +#endif + + + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +/* Initialise the public variables. */ + +int optind = 1; /* index for first non-option arg */ +int opterr = 1; /* enable built-in error messages */ + +char *optarg = NULL; /* pointer to current option argument */ + +#define CHAR char /* argument type selector */ + +#define getopt_switchar '-' /* option prefix character in argv */ +#define getopt_pluschar '+' /* prefix for POSIX mode in optstring */ +#define getopt_takes_argument ':' /* marker for optarg in optstring */ +#define getopt_arg_assign '=' /* longopt argument field separator */ +#define getopt_unknown '?' /* return code for unmatched option */ +#define getopt_ordered 1 /* return code for ordered non-option */ + +#define getopt_all_done -1 /* return code to indicate completion */ + +enum +{ /* All `getopt' API functions are implemented via calls to the + * common static function `getopt_parse()'; these `mode' selectors + * determine the behaviour of `getopt_parse()', to deliver the + * appropriate result in each case. + */ + getopt_mode_standard = 0, /* getopt() */ + getopt_mode_long, /* getopt_long() */ + getopt_mode_long_only /* getopt_long_only() */ +}; + +enum +{ /* When attempting to match a command line argument to a long form option, + * these indicate the status of the match. + */ + getopt_no_match = 0, /* no successful match */ + getopt_abbreviated_match, /* argument is an abbreviation for an option */ + getopt_exact_match /* argument matches the full option name */ +}; + +int optopt = getopt_unknown; /* return value for option being evaluated */ + +/* Some BSD applications expect to be able to reinitialise `getopt' parsing + * by setting a global variable called `optreset'. We provide an obfuscated + * API, which allows applications to emulate this brain damage; however, any + * use of this is non-portable, and is strongly discouraged. + */ +#define optreset __mingw_optreset +int optreset = 0; + +static +int getopt_missing_arg( const CHAR *optstring ) +{ + /* Helper function to determine the appropriate return value, + * for the case where a required option argument is missing. + */ + if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) ) + ++optstring; + return (*optstring == getopt_takes_argument) + ? getopt_takes_argument + : getopt_unknown; +} + +/* `complain' macro facilitates the generation of simple built-in + * error messages, displayed on various fault conditions, provided + * `opterr' is non-zero. + */ +#define complain( MSG, ARG ) if( opterr ) \ + fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG ) + +static +int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval ) +{ + /* Helper function, to generate more complex built-in error + * messages, for invalid arguments to long form options ... + */ + if( opterr ) + { + /* ... but, displayed only if `opterr' is non-zero. + */ + char flag[] = "--"; + if( mode != getopt_mode_long ) + /* + * only display one hyphen, for implicit long form options, + * improperly resolved by `getopt_long_only()'. + */ + flag[1] = 0; + /* + * always preface the program name ... + */ + fprintf( stderr, "%s: ", prog ); + /* + * to the appropriate, option specific message. + */ + fprintf( stderr, fmt, flag, opt->name ); + } + /* Whether displaying the message, or not, always set `optopt' + * to identify the faulty option ... + */ + optopt = opt->val; + /* + * and return the `invalid option' indicator. + */ + return retval; +} + +/* `getopt_conventions' establish behavioural options, to control + * the operation of `getopt_parse()', e.g. to select between POSIX + * and GNU style argument parsing behaviour. + */ +#define getopt_set_conventions 0x1000 +#define getopt_posixly_correct 0x0010 + +static +int getopt_conventions( int flags ) +{ + static int conventions = 0; + + if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) ) + { + /* default conventions have not yet been established; + * initialise them now! + */ + conventions = getopt_set_conventions; + if( flags == getopt_pluschar ) + conventions |= getopt_posixly_correct; + } + + else if( flags & getopt_set_conventions ) + /* + * default conventions may have already been established, + * but this is a specific request to augment them. + */ + conventions |= flags; + + /* in any event, return the currently established conventions. + */ + return conventions; +} + +static +int is_switchar( CHAR flag ) +{ + /* A simple helper function, used to identify the switch character + * introducing an optional command line argument. + */ + return flag == getopt_switchar; +} + +static +const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string ) +{ + /* Helper function, used to identify short form options. + */ + if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) ) + ++opt_string; + if( *opt_string == getopt_takes_argument ) + ++opt_string; + do if( lookup == *opt_string ) return opt_string; + while( *++opt_string ); + return NULL; +} + +static +int getopt_match_long( const CHAR *nextchar, const CHAR *optname ) +{ + /* Helper function, used to identify potential matches for + * long form options. + */ + CHAR matchchar; + while( (matchchar = *nextchar++) && (matchchar == *optname) ) + /* + * skip over initial substring which DOES match. + */ + ++optname; + + if( matchchar ) + { + /* did NOT match the entire argument to an initial substring + * of a defined option name ... + */ + if( matchchar != getopt_arg_assign ) + /* + * ... and didn't stop at an `=' internal field separator, + * so this is NOT a possible match. + */ + return getopt_no_match; + + /* DID stop at an `=' internal field separator, + * so this IS a possible match, and what follows is an + * argument to the possibly matched option. + */ + optarg = (char *)(nextchar); + } + return *optname + /* + * if we DIDN'T match the ENTIRE text of the option name, + * then it's a possible abbreviated match ... + */ + ? getopt_abbreviated_match + /* + * but if we DID match the entire option name, + * then it's a DEFINITE EXACT match. + */ + : getopt_exact_match; +} + +static +int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind, +struct option *opt, int index, int *retindex, const CHAR *optstring ) +{ + /* Helper function to establish appropriate return conditions, + * on resolution of a long form option. + */ + if( retindex != NULL ) + *retindex = index; + + /* On return, `optind' should normally refer to the argument, if any, + * which follows the current one; it is convenient to set this, before + * checking for the presence of any `optarg'. + */ + optind = *argind + 1; + + if( optarg && (opt[index].has_arg == no_argument) ) + /* + * it is an error for the user to specify an option specific argument + * with an option which doesn't expect one! + */ + return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n", + PROGNAME, opt + index, getopt_unknown ); + + else if( (optarg == NULL) && (opt[index].has_arg == required_argument) ) + { + /* similarly, it is an error if no argument is specified + * with an option which requires one ... + */ + if( optind < argc ) + /* + * ... except that the requirement may be satisfied from + * the following command line argument, if any ... + */ + optarg = argv[*argind = optind++]; + + else + /* so fail this case, only if no such argument exists! + */ + return getopt_argerror( mode, "option `%s%s' requires an argument\n", + PROGNAME, opt + index, getopt_missing_arg( optstring ) ); + } + + /* when the caller has provided a return buffer ... + */ + if( opt[index].flag != NULL ) + { + /* ... then we place the proper return value there, + * and return a status code of zero ... + */ + *(opt[index].flag) = opt[index].val; + return 0; + } + /* ... otherwise, the return value becomes the status code. + */ + return opt[index].val; +} + +static +int getopt_verify( const CHAR *nextchar, const CHAR *optstring ) +{ + /* Helper function, called by getopt_parse() when invoked + * by getopt_long_only(), to verify when an unmatched or an + * ambiguously matched long form option string is valid as + * a short form option specification. + */ + if( ! (nextchar && *nextchar && optstring && *optstring) ) + /* + * There are no characters to be matched, or there are no + * valid short form option characters to which they can be + * matched, so this can never be valid. + */ + return 0; + + while( *nextchar ) + { + /* For each command line character in turn ... + */ + const CHAR *test; + if( (test = getopt_match( *nextchar++, optstring )) == NULL ) + /* + * ... there is no short form option to match the current + * candidate, so the entire argument fails. + */ + return 0; + + if( test[1] == getopt_takes_argument ) + /* + * The current candidate is valid, and it matches an option + * which takes an argument, so this command line argument is + * a valid short form option specification; accept it. + */ + return 1; + } + /* If we get to here, then every character in the command line + * argument was valid as a short form option; accept it. + */ + return 1; +} + +static +#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring +int getopt_parse( int mode, getopt_std_args, ... ) +{ + /* Common core implementation for ALL `getopt' functions. + */ + static int argind = 0; + static int optbase = 0; + static const CHAR *nextchar = NULL; + static int optmark = 0; + + if( (optreset |= (optind < 1)) || (optind < optbase) ) + { + /* POSIX does not prescribe any definitive mechanism for restarting + * a `getopt' scan, but some applications may require such capability. + * We will support it, by allowing the caller to adjust the value of + * `optind' downwards, (nominally setting it to zero). Since POSIX + * wants `optind' to have an initial value of one, but we want all + * of our internal place holders to be initialised to zero, when we + * are called for the first time, we will handle such a reset by + * adjusting all of the internal place holders to one less than + * the adjusted `optind' value, (but never to less than zero). + */ + if( optreset ) + { + /* User has explicitly requested reinitialisation... + * We need to reset `optind' to it's normal initial value of 1, + * to avoid a potential infinitely recursive loop; by doing this + * up front, we also ensure that the remaining place holders + * will be correctly reinitialised to no less than zero. + */ + optind = 1; + + /* We also need to clear the `optreset' request... + */ + optreset = 0; + } + + /* Now, we may safely reinitialise the internal place holders, to + * one less than `optind', without fear of making them negative. + */ + optmark = optbase = argind = optind - 1; + nextchar = NULL; + } + + /* From a POSIX perspective, the following is `undefined behaviour'; + * we implement it thus, for compatibility with GNU and BSD getopt. + */ + else if( optind > (argind + 1) ) + { + /* Some applications expect to be able to manipulate `optind', + * causing `getopt' to skip over one or more elements of `argv'; + * POSIX doesn't require us to support this brain-damaged concept; + * (indeed, POSIX defines no particular behaviour, in the event of + * such usage, so it must be considered a bug for an application + * to rely on any particular outcome); nonetheless, Mac-OS-X and + * BSD actually provide *documented* support for this capability, + * so we ensure that our internal place holders keep track of + * external `optind' increments; (`argind' must lag by one). + */ + argind = optind - 1; + + /* When `optind' is misused, in this fashion, we also abandon any + * residual text in the argument we had been parsing; this is done + * without any further processing of such abandoned text, assuming + * that the caller is equipped to handle it appropriately. + */ + nextchar = NULL; + } + + if( nextchar && *nextchar ) + { + /* we are parsing a standard, or short format, option argument ... + */ + const CHAR *optchar; + if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL ) + { + /* we have identified it as valid ... + */ + if( optchar[1] == getopt_takes_argument ) + { + /* and determined that it requires an associated argument ... + */ + if( ! *(optarg = (char *)(nextchar)) ) + { + /* the argument is NOT attached ... + */ + if( optchar[2] == getopt_takes_argument ) + /* + * but this GNU extension marks it as optional, + * so we don't provide one on this occasion. + */ + optarg = NULL; + + /* otherwise this option takes a mandatory argument, + * so, provided there is one available ... + */ + else if( (argc - argind) > 1 ) + /* + * we take the following command line argument, + * as the appropriate option argument. + */ + optarg = argv[++argind]; + + /* but if no further argument is available, + * then there is nothing we can do, except for + * issuing the requisite diagnostic message. + */ + else + { + complain( "option requires an argument -- %c", optopt ); + return getopt_missing_arg( optstring ); + } + } + optind = argind + 1; + nextchar = NULL; + } + else + optarg = NULL; + optind = (nextchar && *nextchar) ? argind : argind + 1; + return optopt; + } + /* if we didn't find a valid match for the specified option character, + * then we fall through to here, so take appropriate diagnostic action. + */ + if( mode == getopt_mode_long_only ) + { + complain( "unrecognised option `-%s'", --nextchar ); + nextchar = NULL; + optopt = 0; + } + else + complain( "invalid option -- %c", optopt ); + optind = (nextchar && *nextchar) ? argind : argind + 1; + return getopt_unknown; + } + + if( optmark > optbase ) + { + /* This can happen, in GNU parsing mode ONLY, when we have + * skipped over non-option arguments, and found a subsequent + * option argument; in this case we permute the arguments. + */ + int index; + /* + * `optspan' specifies the number of contiguous arguments + * which are spanned by the current option, and so must be + * moved together during permutation. + */ + const int optspan = argind - optmark + 1; + /* + * we use `this_arg' to store these temporarily. + */ + CHAR **this_arg = malloc(sizeof(CHAR*) * optspan); + /* + * we cannot manipulate `argv' directly, since the `getopt' + * API prototypes it as `read-only'; this cast to `arglist' + * allows us to work around that restriction. + */ + CHAR **arglist = (char **)(argv); + + /* save temporary copies of the arguments which are associated + * with the current option ... + */ + for( index = 0; index < optspan; ++index ) + this_arg[index] = arglist[optmark + index]; + + /* move all preceding non-option arguments to the right, + * overwriting these saved arguments, while making space + * to replace them in their permuted location. + */ + for( --optmark; optmark >= optbase; --optmark ) + arglist[optmark + optspan] = arglist[optmark]; + + /* restore the temporarily saved option arguments to + * their permuted location. + */ + for( index = 0; index < optspan; ++index ) + arglist[optbase + index] = this_arg[index]; + + /* adjust `optbase', to account for the relocated option. + */ + optbase += optspan; + + free(this_arg); + } + + else + /* no permutation occurred ... + * simply adjust `optbase' for all options parsed so far. + */ + optbase = argind + 1; + + /* enter main parsing loop ... + */ + while( argc > ++argind ) + { + /* inspect each argument in turn, identifying possible options ... + */ + if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar ) + { + /* we've found a candidate option argument ... */ + + if( is_switchar( *nextchar ) ) + { + /* it's a double hyphen argument ... */ + + const CHAR *refchar = nextchar; + if( *++refchar ) + { + /* and it looks like a long format option ... + * `getopt_long' mode must be active to accept it as such, + * `getopt_long_only' also qualifies, but we must downgrade + * it to force explicit handling as a long format option. + */ + if( mode >= getopt_mode_long ) + { + nextchar = refchar; + mode = getopt_mode_long; + } + } + else + { + /* this is an explicit `--' end of options marker, so wrap up now! + */ + if( optmark > optbase ) + { + /* permuting the argument list as necessary ... + * (note use of `this_arg' and `arglist', as above). + */ + CHAR *this_arg = argv[optmark]; + CHAR **arglist = (CHAR **)(argv); + + /* move all preceding non-option arguments to the right ... + */ + do arglist[optmark] = arglist[optmark - 1]; + while( optmark-- > optbase ); + + /* reinstate the `--' marker, in its permuted location. + */ + arglist[optbase] = this_arg; + } + /* ... before finally bumping `optbase' past the `--' marker, + * and returning the `all done' completion indicator. + */ + optind = ++optbase; + return getopt_all_done; + } + } + else if( mode < getopt_mode_long_only ) + { + /* it's not an explicit long option, and `getopt_long_only' isn't active, + * so we must explicitly try to match it as a short option. + */ + mode = getopt_mode_standard; + } + + if( mode >= getopt_mode_long ) + { + /* the current argument is a long form option, (either explicitly, + * introduced by a double hyphen, or implicitly because we were called + * by `getopt_long_only'); this is where we parse it. + */ + int lookup; + int matched = -1; + + /* we need to fetch the `extra' function arguments, which are + * specified for the `getopt_long' APIs. + */ + va_list refptr; + struct option *longopts; + int *optindex; + va_start( refptr, optstring ); + longopts = va_arg( refptr, struct option * ); + optindex = va_arg( refptr, int * ); + va_end( refptr ); + + /* ensuring that `optarg' does not inherit any junk, from parsing + * preceding arguments ... + */ + optarg = NULL; + for( lookup = 0; longopts && longopts[lookup].name; ++lookup ) + { + /* scan the list of defined long form options ... + */ + switch( getopt_match_long( nextchar, longopts[lookup].name ) ) + { + /* looking for possible matches for the current argument. + */ + case getopt_exact_match: + /* + * when an exact match is found, + * return it immediately, setting `nextchar' to NULL, + * to ensure we don't mistakenly try to match any + * subsequent characters as short form options. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, lookup, optindex, optstring ); + + case getopt_abbreviated_match: + /* + * but, for a partial (initial substring) match ... + */ + if( matched >= 0 ) + { + /* if this is not the first, then we have an ambiguity ... + */ + if( (mode == getopt_mode_long_only) + /* + * However, in the case of getopt_long_only(), if + * the entire ambiguously matched string represents + * a valid short option specification, then we may + * proceed to interpret it as such. + */ + && getopt_verify( nextchar, optstring ) ) + return getopt_parse( mode, argc, argv, optstring ); + + /* If we get to here, then the ambiguously matched + * partial long option isn't valid for short option + * evaluation; reset parser context to resume with + * the following command line argument, diagnose + * ambiguity, and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "option `%s' is ambiguous", argv[argind] ); + return getopt_unknown; + } + /* otherwise just note that we've found a possible match ... + */ + matched = lookup; + } + } + if( matched >= 0 ) + { + /* if we get to here, then we found exactly one partial match, + * so return it, as for an exact match. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, matched, optindex, optstring ); + } + /* if here, then we had what SHOULD have been a long form option, + * but it is unmatched ... + */ + if( (mode < getopt_mode_long_only) + /* + * ... although paradoxically, `mode == getopt_mode_long_only' + * allows us to still try to match it as a short form option. + */ + || (getopt_verify( nextchar, optstring ) == 0) ) + { + /* When it cannot be matched, reset the parsing context to + * resume from the next argument, diagnose the failed match, + * and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "unrecognised option `%s'", argv[argind] ); + return getopt_unknown; + } + } + /* fall through to handle standard short form options... + * when the option argument format is neither explictly identified + * as long, nor implicitly matched as such, and the argument isn't + * just a bare hyphen, (which isn't an option), then we make one + * recursive call to explicitly interpret it as short format. + */ + if( *nextchar ) + return getopt_parse( mode, argc, argv, optstring ); + } + /* if we get to here, then we've parsed a non-option argument ... + * in GNU compatibility mode, we step over it, so we can permute + * any subsequent option arguments, but ... + */ + if( *optstring == getopt_switchar ) + { + /* if `optstring' begins with a `-' character, this special + * GNU specific behaviour requires us to return the non-option + * arguments in strict order, as pseudo-arguments to a special + * option, with return value defined as `getopt_ordered'. + */ + nextchar = NULL; + optind = argind + 1; + optarg = argv[argind]; + return getopt_ordered; + } + if( getopt_conventions( *optstring ) & getopt_posixly_correct ) + /* + * otherwise ... + * for POSIXLY_CORRECT behaviour, or if `optstring' begins with + * a `+' character, then we break out of the parsing loop, so that + * the scan ends at the current argument, with no permutation. + */ + break; + } + /* fall through when all arguments have been evaluated, + */ + optind = optbase; + return getopt_all_done; +} + +/* All three public API entry points are trivially defined, + * in terms of the internal `getopt_parse' function. + */ +int getopt( getopt_std_args ) +{ + return getopt_parse( getopt_mode_standard, argc, argv, optstring ); +} + +int getopt_long( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index ); +} + +int getopt_long_only( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index ); +} + +#ifdef __weak_alias +/* + * These Microsnot style uglified aliases are provided for compatibility + * with the previous MinGW implementation of the getopt API. + */ +__weak_alias( getopt, _getopt ) +__weak_alias( getopt_long, _getopt_long ) +__weak_alias( getopt_long_only, _getopt_long_only ) +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ From 065978d1d0ca8b891325068b3b3ee6c3d4b53d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 12:57:29 +0200 Subject: [PATCH 017/135] added renaming to bootstrap --- fdk-aac-dab/bootstrap | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fdk-aac-dab/bootstrap b/fdk-aac-dab/bootstrap index a3394ab2..f55e0c40 100755 --- a/fdk-aac-dab/bootstrap +++ b/fdk-aac-dab/bootstrap @@ -1,4 +1,20 @@ -#! /bin/sh +#!/bin/sh + +#stupid, but works: first "unpatch", in case we've patched already +echo "scanning for files..." +files=$(git ls-files|grep -v bootstrap |grep -vi changelog) +echo "replacing occurrences of patched string" +sed -i 's/\(fdk[^ ]aac\)[^ ]dab/\1/g' $files +sed -i 's/\(FDK[^ ]AAC\)[^ ]DAB/\1/g' $files + +#then patch: append "dab" to lower and uppercase fdk?aacdab, and use the same "?" +#delimiter to connect the two +echo "patching" +sed -i 's/\(fdk\([^ ]\)aac\)/\1\2dab/g' $files +sed -i 's/\(FDK\([^ ]\)AAC\)/\1\2DAB/g' $files + +mv fdk-aac.pc.in fdk-aac-dab.pc.in +mv fdk-aac.sym fdk-aac-dab.sym autoreconf --install && \ echo "You can call ./configure now" From 0e26c873bf95debee11a8ac2534c3b4956dd5afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 13:35:13 +0200 Subject: [PATCH 018/135] Included fdk_aac_dab --- CMakeLists.txt | 10 ++++---- cmake/Modules/FindFdk-aac-dab.cmake | 38 +++++++++++++++++++++++++++ cmake/Modules/FindFdk-aac.cmake | 40 ----------------------------- lib/CMakeLists.txt | 4 +-- lib/mp4_encode_sb_impl.cc | 2 +- lib/mp4_encode_sb_impl.h | 4 +-- 6 files changed, 48 insertions(+), 50 deletions(-) create mode 100644 cmake/Modules/FindFdk-aac-dab.cmake delete mode 100644 cmake/Modules/FindFdk-aac.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index feb5eaaf..3f80632a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,13 +53,13 @@ else() endif () ######################################################################## -# Find FDK-AAC +# Find FDK-AAC-DAB ######################################################################## -find_package(Fdk-aac REQUIRED) -if (NOT FDK-AAC_FOUND ) - message(FATAL_ERROR "please install fdk-aac") +find_package(Fdk-aac-dab REQUIRED) +if (NOT FDK-AAC-DAB_FOUND ) + message(FATAL_ERROR "please install fdk-aac-dab") else() - message(STATUS "FDK-AAC found") + message(STATUS "FDK-AAC-DAB found") endif () ######################################################################## diff --git a/cmake/Modules/FindFdk-aac-dab.cmake b/cmake/Modules/FindFdk-aac-dab.cmake new file mode 100644 index 00000000..f987ad27 --- /dev/null +++ b/cmake/Modules/FindFdk-aac-dab.cmake @@ -0,0 +1,38 @@ +# Try to find fdk-aac-dab library and include path. +# Once done this will define +# +# FDK-AAC-DAB_INCLUDE_DIRS - where to find fdk-aac-dab.h, etc. +# FDK-AAC-DAB_LIBRARIES - List of libraries when using libfdk-aac-dab. +# FDK-AAC-DAB_FOUND - True if libfdk-aac-dab found. + +find_path(FDK-AAC-DAB_INCLUDE_DIR fdk-aac-dab/aacenc_lib.h + /opt/local/include + /usr/local/include + /usr/include +) +find_library(FDK-AAC-DAB_LIBRARY NAMES fdk-aac-dab DOC "The libfdk-aac-dab library") + +if(FDK-AAC-DAB_INCLUDE_DIR AND FDK-AAC-DAB_LIBRARY) + set(FDK-AAC-DAB_FOUND 1) + set(FDK-AAC-DAB_LIBRARIES ${FDK-AAC-DAB_LIBRARY}) + set(FDK-AAC-DAB_INCLUDE_DIRS ${FDK-AAC-DAB_INCLUDE_DIR}) +else(FDK-AAC-DAB_INCLUDE_DIR AND FDK-AAC-DAB_LIBRARY) + set(FDK-AAC-DAB_FOUND 0) + set(FDK-AAC-DAB_LIBRARIES) + set(FDK-AAC-DAB_INCLUDE_DIRS) +endif(FDK-AAC-DAB_INCLUDE_DIR AND FDK-AAC-DAB_LIBRARY) + +mark_as_advanced(FDK-AAC-DAB_INCLUDE_DIR) +mark_as_advanced(FDK-AAC-DAB_LIBRARY) +mark_as_advanced(FDK-AAC-DAB_FOUND) + +if(NOT FDK-AAC-DAB_FOUND) + set(FDK-AAC-DAB_DIR_MESSAGE "libfdk-aac-dab was not found. Make sure FDK-AAC-DAB_LIBRARY and FDK-AAC-DAB_INCLUDE_DIR are set.") + if(NOT FDK-AAC-DAB_FIND_QUIETLY) + message(STATUS "${FDK-AAC-DAB_DIR_MESSAGE}") + else(NOT FDK-AAC-DAB_FIND_QUIETLY) + if(FDK-AAC-DAB_FIND_REQUIRED) + message(FATAL_ERROR "${FDK-AAC-DAB_DIR_MESSAGE}") + endif(FDK-AAC-DAB_FIND_REQUIRED) + endif(NOT FDK-AAC-DAB_FIND_QUIETLY) +endif(NOT FDK-AAC-DAB_FOUND) diff --git a/cmake/Modules/FindFdk-aac.cmake b/cmake/Modules/FindFdk-aac.cmake deleted file mode 100644 index 6cd8dba4..00000000 --- a/cmake/Modules/FindFdk-aac.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# Try to find fdk-aac library and include path. -# Once done this will define -# -# FDK-AAC_INCLUDE_DIRS - where to find fdk-aac.h, etc. -# FDK-AAC_LIBRARIES - List of libraries when using libfdk-aac. -# FDK-AAC_FOUND - True if libfdk-aac found. - -find_path(FDK-AAC_INCLUDE_DIR aacenc_lib.h - /opt/local/include - /usr/local/include - /usr/local/include/fdk-aac - /usr/include - /usr/include/fdk-aac -) -find_library(FDK-AAC_LIBRARY NAMES fdk-aac DOC "The libfdk-aac library") - -if(FDK-AAC_INCLUDE_DIR AND FDK-AAC_LIBRARY) - set(FDK-AAC_FOUND 1) - set(FDK-AAC_LIBRARIES ${FDK-AAC_LIBRARY}) - set(FDK-AAC_INCLUDE_DIRS ${FDK-AAC_INCLUDE_DIR}) -else(FDK-AAC_INCLUDE_DIR AND FDK-AAC_LIBRARY) - set(FDK-AAC_FOUND 0) - set(FDK-AAC_LIBRARIES) - set(FDK-AAC_INCLUDE_DIRS) -endif(FDK-AAC_INCLUDE_DIR AND FDK-AAC_LIBRARY) - -mark_as_advanced(FDK-AAC_INCLUDE_DIR) -mark_as_advanced(FDK-AAC_LIBRARY) -mark_as_advanced(FDK-AAC_FOUND) - -if(NOT FDK-AAC_FOUND) - set(FDK-AAC_DIR_MESSAGE "libfdk-aac was not found. Make sure FDK-AAC_LIBRARY and FDK-AAC_INCLUDE_DIR are set.") - if(NOT FDK-AAC_FIND_QUIETLY) - message(STATUS "${FDK-AAC_DIR_MESSAGE}") - else(NOT FDK-AAC_FIND_QUIETLY) - if(FDK-AAC_FIND_REQUIRED) - message(FATAL_ERROR "${FDK-AAC_DIR_MESSAGE}") - endif(FDK-AAC_FIND_REQUIRED) - endif(NOT FDK-AAC_FIND_QUIETLY) -endif(NOT FDK-AAC_FOUND) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 432363cc..baa30bbd 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -22,7 +22,7 @@ ######################################################################## include(GrPlatform) #define LIB_SUFFIX -include_directories(${Boost_INCLUDE_DIR} ${FDK-AAC_INCLUDE_DIRS} ${LIBTOOLAME-DAB_INCLUDE_DIR}) +include_directories(${Boost_INCLUDE_DIR} ${FDK-AAC-DAB_INCLUDE_DIRS} ${LIBTOOLAME-DAB_INCLUDE_DIR}) link_directories(${Boost_LIBRARY_DIRS}) list(APPEND dab_sources moving_sum_ff_impl.cc @@ -103,7 +103,7 @@ if(NOT dab_sources) endif(NOT dab_sources) add_library(gnuradio-dab SHARED ${dab_sources}) -target_link_libraries(gnuradio-dab ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${FAAD_LIBRARIES} ${FDK-AAC_LIBRARIES}) +target_link_libraries(gnuradio-dab ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES} ${FAAD_LIBRARIES} ${FDK-AAC-DAB_LIBRARIES}) set_target_properties(gnuradio-dab PROPERTIES DEFINE_SYMBOL "gnuradio_dab_EXPORTS") if(APPLE) diff --git a/lib/mp4_encode_sb_impl.cc b/lib/mp4_encode_sb_impl.cc index 927eba15..a46028e6 100644 --- a/lib/mp4_encode_sb_impl.cc +++ b/lib/mp4_encode_sb_impl.cc @@ -33,7 +33,7 @@ #include #include #include -#include "aacenc_lib.h" +#include "fdk-aac-dab/aacenc_lib.h" using namespace boost; diff --git a/lib/mp4_encode_sb_impl.h b/lib/mp4_encode_sb_impl.h index fe7a581e..037d5a5b 100644 --- a/lib/mp4_encode_sb_impl.h +++ b/lib/mp4_encode_sb_impl.h @@ -27,8 +27,8 @@ #define INCLUDED_DAB_MP4_ENCODE_SB_IMPL_H #include -#include "./FDK_audio.h" -#include "aacenc_lib.h" +#include "fdk-aac-dab/FDK_audio.h" +#include "fdk-aac-dab/aacenc_lib.h" namespace gr { namespace dab { From 6cc35df0169ad5b39857566327fc35ab57861eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 14:30:19 +0200 Subject: [PATCH 019/135] renamed fdk-aac to fdk-aac-dab --- fdk-aac-dab/.gitignore | 2 +- fdk-aac-dab/Makefile.am | 22 +++++++++---------- fdk-aac-dab/Makefile.vc | 18 +++++++-------- fdk-aac-dab/README.md | 4 ++-- fdk-aac-dab/configure.ac | 8 +++---- .../{fdk-aac.pc.in => fdk-aac-dab.pc.in} | 2 +- fdk-aac-dab/{fdk-aac.sym => fdk-aac-dab.sym} | 0 fdk-aac-dab/libAACdec/src/aacdecoder_lib.cpp | 2 +- fdk-aac-dab/libAACenc/src/aacenc_lib.cpp | 2 +- fdk-aac-dab/libSYS/include/FDK_audio.h | 6 ++--- 10 files changed, 33 insertions(+), 33 deletions(-) rename fdk-aac-dab/{fdk-aac.pc.in => fdk-aac-dab.pc.in} (83%) rename fdk-aac-dab/{fdk-aac.sym => fdk-aac-dab.sym} (100%) diff --git a/fdk-aac-dab/.gitignore b/fdk-aac-dab/.gitignore index 263e5aa2..5bc071a8 100644 --- a/fdk-aac-dab/.gitignore +++ b/fdk-aac-dab/.gitignore @@ -9,7 +9,7 @@ Makefile.in aclocal.m4 autom4te.cache configure -fdk-aac.pc +fdk-aac-dab.pc config.guess config.log config.status diff --git a/fdk-aac-dab/Makefile.am b/fdk-aac-dab/Makefile.am index 11fbef1f..835e17c5 100644 --- a/fdk-aac-dab/Makefile.am +++ b/fdk-aac-dab/Makefile.am @@ -13,12 +13,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/libPCMutils/include AM_CXXFLAGS = -fno-exceptions -fno-rtti -libfdk_aac_la_LINK = $(LINK) $(libfdk_aac_la_LDFLAGS) +libfdk_aac_dab_la_LINK = $(LINK) $(libfdk_aac_dab_la_LDFLAGS) # Mention a dummy pure C file to trigger generation of the $(LINK) variable -nodist_EXTRA_libfdk_aac_la_SOURCES = dummy.c +nodist_EXTRA_libfdk_aac_dab_la_SOURCES = dummy.c -fdk_aacincludedir = $(includedir)/fdk-aac -fdk_aacinclude_HEADERS = \ +fdk_aac_dabincludedir = $(includedir)/fdk-aac-dab +fdk_aac_dabinclude_HEADERS = \ $(top_srcdir)/libSYS/include/machine_type.h \ $(top_srcdir)/libSYS/include/genericStds.h \ $(top_srcdir)/libSYS/include/FDK_audio.h \ @@ -26,17 +26,17 @@ fdk_aacinclude_HEADERS = \ $(top_srcdir)/libAACdec/include/aacdecoder_lib.h pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = fdk-aac.pc +pkgconfig_DATA = fdk-aac-dab.pc -lib_LTLIBRARIES = libfdk-aac.la +lib_LTLIBRARIES = libfdk-aac-dab.la -libfdk_aac_la_LDFLAGS = -version-info @FDK_AAC_VERSION@ -no-undefined \ - -export-symbols $(top_srcdir)/fdk-aac.sym +libfdk_aac_dab_la_LDFLAGS = -version-info @FDK_AAC_DAB_VERSION@ -no-undefined \ + -export-symbols $(top_srcdir)/fdk-aac-dab.sym if EXAMPLE bin_PROGRAMS = aac-enc$(EXEEXT) -aac_enc_LDADD = libfdk-aac.la +aac_enc_LDADD = libfdk-aac-dab.la aac_enc_SOURCES = aac-enc.c wavreader.c noinst_HEADERS = wavreader.h @@ -179,7 +179,7 @@ SYS_SRC = \ libSYS/src/genericStds.cpp \ libSYS/src/wav_file.cpp -libfdk_aac_la_SOURCES = \ +libfdk_aac_dab_la_SOURCES = \ $(AACDEC_SRC) $(AACENC_SRC) \ $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ $(SBRDEC_SRC) $(SBRENC_SRC) \ @@ -190,7 +190,7 @@ EXTRA_DIST = \ $(top_srcdir)/MODULE_LICENSE_FRAUNHOFER \ $(top_srcdir)/NOTICE \ $(top_srcdir)/Android.mk \ - $(top_srcdir)/fdk-aac.sym \ + $(top_srcdir)/fdk-aac-dab.sym \ $(top_srcdir)/Makefile.vc \ $(top_srcdir)/documentation/*.pdf \ $(top_srcdir)/libAACdec/src/*.h \ diff --git a/fdk-aac-dab/Makefile.vc b/fdk-aac-dab/Makefile.vc index 6fccb9ca..cb7fea37 100644 --- a/fdk-aac-dab/Makefile.vc +++ b/fdk-aac-dab/Makefile.vc @@ -165,7 +165,7 @@ SYS_SRC = \ libSYS/src/genericStds.cpp \ libSYS/src/wav_file.cpp -libfdk_aac_SOURCES = \ +libfdk_aac_dab_SOURCES = \ $(AACDEC_SRC) $(AACENC_SRC) \ $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ $(SBRDEC_SRC) $(SBRENC_SRC) \ @@ -183,19 +183,19 @@ CPPFLAGS = $(CFLAGS) LDFLAGS = -nologo $(XLDFLAGS) ARFLAGS = -nologo -incdir = $(prefix_win)\include\fdk-aac +incdir = $(prefix_win)\include\fdk-aac-dab bindir = $(prefix_win)\bin libdir = $(prefix_win)\lib INST_DIRS = $(bindir) $(incdir) $(libdir) -LIB_DEF = fdk-aac.def -STATIC_LIB = fdk-aac.lib -SHARED_LIB = fdk-aac-1.dll -IMP_LIB = fdk-aac.dll.lib +LIB_DEF = fdk-aac-dab.def +STATIC_LIB = fdk-aac-dab.lib +SHARED_LIB = fdk-aac-dab-1.dll +IMP_LIB = fdk-aac-dab.dll.lib AAC_ENC_OBJS = $(aac_enc_SOURCES:.c=.obj) -FDK_OBJS = $(libfdk_aac_SOURCES:.cpp=.obj) +FDK_OBJS = $(libfdk_aac_dab_SOURCES:.cpp=.obj) PROGS = aac-enc.exe @@ -204,7 +204,7 @@ PROGS = aac-enc.exe all: $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) clean: - del /f $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) libfdk-aac.pc 2>NUL + del /f $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) libfdk-aac-dab.pc 2>NUL del /f *.obj *.exp 2>NUL del /f libAACdec\src\*.obj 2>NUL del /f libAACenc\src\*.obj 2>NUL @@ -247,4 +247,4 @@ $(PROGS): $(AAC_ENC_OBJS) $(LIB_DEF): @echo EXPORTS > $(LIB_DEF) - @type fdk-aac.sym >> $(LIB_DEF) + @type fdk-aac-dab.sym >> $(LIB_DEF) diff --git a/fdk-aac-dab/README.md b/fdk-aac-dab/README.md index 308f2923..ea42cd7e 100644 --- a/fdk-aac-dab/README.md +++ b/fdk-aac-dab/README.md @@ -1,7 +1,7 @@ -A patched version of fdk-aac with DAB+ support +A patched version of fdk-aac-dab with DAB+ support ============================================== -This is a modified version of fdk-aac that supports the AOTs +This is a modified version of fdk-aac-dab that supports the AOTs required for DAB+ encoding. This library is a dependency for ODR-AudioEnc. diff --git a/fdk-aac-dab/configure.ac b/fdk-aac-dab/configure.ac index 1485ff72..8ac38905 100644 --- a/fdk-aac-dab/configure.ac +++ b/fdk-aac-dab/configure.ac @@ -1,7 +1,7 @@ dnl -*- Autoconf -*- dnl Process this file with autoconf to produce a configure script. -AC_INIT([fdk-aac], [0.1.5], [http://sourceforge.net/projects/opencore-amr/]) +AC_INIT([fdk-aac-dab], [0.1.5], [http://sourceforge.net/projects/opencore-amr/]) AC_CONFIG_AUX_DIR(.) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([tar-ustar foreign]) @@ -26,13 +26,13 @@ AC_SEARCH_LIBS([sin], [m]) dnl soname version to use dnl goes by ‘current[:revision[:age]]’ with the soname ending up as dnl current.age.revision -FDK_AAC_VERSION=1:0:0 +FDK_AAC_DAB_VERSION=1:0:0 AS_IF([test x$enable_shared = xyes], [LIBS_PRIVATE=$LIBS], [LIBS_PUBLIC=$LIBS]) -AC_SUBST(FDK_AAC_VERSION) +AC_SUBST(FDK_AAC_DAB_VERSION) AC_SUBST(LIBS_PUBLIC) AC_SUBST(LIBS_PRIVATE) AC_CONFIG_FILES([Makefile - fdk-aac.pc]) + fdk-aac-dab.pc]) AC_OUTPUT diff --git a/fdk-aac-dab/fdk-aac.pc.in b/fdk-aac-dab/fdk-aac-dab.pc.in similarity index 83% rename from fdk-aac-dab/fdk-aac.pc.in rename to fdk-aac-dab/fdk-aac-dab.pc.in index 2edac451..66fc7b8d 100644 --- a/fdk-aac-dab/fdk-aac.pc.in +++ b/fdk-aac-dab/fdk-aac-dab.pc.in @@ -6,6 +6,6 @@ includedir=@includedir@ Name: Fraunhofer FDK AAC Codec Library Description: AAC codec library Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lfdk-aac @LIBS_PUBLIC@ +Libs: -L${libdir} -lfdk-aac-dab @LIBS_PUBLIC@ Libs.private: @LIBS_PRIVATE@ Cflags: -I${includedir} diff --git a/fdk-aac-dab/fdk-aac.sym b/fdk-aac-dab/fdk-aac-dab.sym similarity index 100% rename from fdk-aac-dab/fdk-aac.sym rename to fdk-aac-dab/fdk-aac-dab.sym diff --git a/fdk-aac-dab/libAACdec/src/aacdecoder_lib.cpp b/fdk-aac-dab/libAACdec/src/aacdecoder_lib.cpp index 50efb0fd..c971ad4b 100644 --- a/fdk-aac-dab/libAACdec/src/aacdecoder_lib.cpp +++ b/fdk-aac-dab/libAACdec/src/aacdecoder_lib.cpp @@ -1123,7 +1123,7 @@ LINKSPEC_CPP INT aacDecoder_GetLibInfo ( LIB_INFO *info ) } info += i; - info->module_id = FDK_AACDEC; + info->module_id = FDK_AAC_DABDEC; /* build own library info */ info->version = LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2); LIB_VERSION_STRING(info); diff --git a/fdk-aac-dab/libAACenc/src/aacenc_lib.cpp b/fdk-aac-dab/libAACenc/src/aacenc_lib.cpp index 1ea9a5c2..5a239c39 100644 --- a/fdk-aac-dab/libAACenc/src/aacenc_lib.cpp +++ b/fdk-aac-dab/libAACenc/src/aacenc_lib.cpp @@ -1803,7 +1803,7 @@ AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) return AACENC_INIT_ERROR; } - info[i].module_id = FDK_AACENC; + info[i].module_id = FDK_AAC_DABENC; info[i].build_date = (char*)AACENCODER_LIB_BUILD_DATE; info[i].build_time = (char*)AACENCODER_LIB_BUILD_TIME; info[i].title = (char*)AACENCODER_LIB_TITLE; diff --git a/fdk-aac-dab/libSYS/include/FDK_audio.h b/fdk-aac-dab/libSYS/include/FDK_audio.h index 9a787fb8..aafdbd54 100644 --- a/fdk-aac-dab/libSYS/include/FDK_audio.h +++ b/fdk-aac-dab/libSYS/include/FDK_audio.h @@ -427,8 +427,8 @@ typedef enum { FDK_NONE = 0, FDK_TOOLS = 1, FDK_SYSLIB = 2, - FDK_AACDEC = 3, - FDK_AACENC = 4, + FDK_AAC_DABDEC = 3, + FDK_AAC_DABENC = 4, FDK_SBRDEC = 5, FDK_SBRENC = 6, FDK_TPDEC = 7, @@ -441,7 +441,7 @@ typedef enum { FDK_DABPARSE = 14, FDK_DRMDEC = 15, FDK_DRMPARSE = 16, - FDK_AACLDENC = 17, + FDK_AAC_DABLDENC = 17, FDK_MP2ENC = 18, FDK_MP3ENC = 19, FDK_MP3DEC = 20, From 86954264c48e630d7bfae93eaa8e4034be1085c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 14:38:42 +0200 Subject: [PATCH 020/135] Documentation on installing fdk-aac-dab: Readme and useful CMake output --- CMakeLists.txt | 11 ++++++++++- README.md | 12 ++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f80632a..e7aa9d45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,16 @@ endif () ######################################################################## find_package(Fdk-aac-dab REQUIRED) if (NOT FDK-AAC-DAB_FOUND ) - message(FATAL_ERROR "please install fdk-aac-dab") + message(FATAL_ERROR "please install fdk-aac-dab: +You'll find it in the eponymous subdirectory; build it using: + + $ cd fdk-aac-dab + $ ./bootstrap + $ ./configure [--prefix ...] [--other options] + $ make + $ make install + +") else() message(STATUS "FDK-AAC-DAB found") endif () diff --git a/README.md b/README.md index d7d6c62d..e2b00a83 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,14 @@ This package requires that GNU Radio is already installed. It also depends on some GNU Radio prerequisites, such as Boost and cppunit. -It also depends on fdk-aac. If you're on a Debianoid (Debian, Mint, *buntu…), -you might want to `apt-get install fdk-aac-dev`. If you're on a Redhatoid -(Redhat, Fedora, Centos…), `dnf install fdk-aac-devel` is the analogous method -of installing this dependency. +It also depends on fdk-aac with DAB patches (fdk-aac-dab). You'll find it in +the eponymous subdirectory; build it using: + + $ cd fdk-aac-dab + $ ./bootstrap + $ ./configure [--prefix ...] [--other options] + $ make + $ make install There is a dependency on the modified MPEG encoder libtoolame from the ODR project. It's fetched by ´git submodule update --init´ automatically. From 5f37af8c2606ac527caee7a0f84889fe050cd152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 17:16:46 +0200 Subject: [PATCH 021/135] imported dab_swig as dab in tests --- python/qa_conv_encoder_bb.py | 3 ++- python/qa_crc16_bb.py | 2 +- python/qa_dab_transmission_frame_mux_bb.py | 2 +- python/qa_dabplus_audio_decoder_ff.py | 2 +- python/qa_energy_disp.py | 2 +- python/qa_fib_sink_vb.py | 2 +- python/qa_fib_source_b.py | 2 +- python/qa_fic_encode.py | 13 ++++++++----- python/qa_mapper_bc.py | 2 +- python/qa_mp2_decode_bs.py | 2 +- python/qa_mp2_encode_sb.py | 2 +- python/qa_mp4_decode_bs.py | 2 +- python/qa_mp4_encode_sb.py | 2 +- python/qa_msc_decode.py | 2 +- python/qa_msc_encode.py | 2 +- python/qa_prune.py | 2 +- python/qa_puncture_bb.py | 2 +- python/qa_reed_solomon_decode_bb.py | 2 +- python/qa_reed_solomon_encode_bb.py | 2 +- python/qa_repartition_vectors.py | 2 +- python/qa_select_subch_vfvf.py | 2 +- python/qa_select_vectors.py | 2 +- python/qa_time_deinterleave_ff.py | 2 +- python/qa_time_interleave_bb.py | 2 +- python/qa_unpuncture_ff.py | 2 +- 25 files changed, 33 insertions(+), 29 deletions(-) diff --git a/python/qa_conv_encoder_bb.py b/python/qa_conv_encoder_bb.py index 73d8f703..6c8c439d 100755 --- a/python/qa_conv_encoder_bb.py +++ b/python/qa_conv_encoder_bb.py @@ -21,7 +21,8 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +#import dab_swig as dab +import dab_swig as dab class qa_conv_encoder_bb (gr_unittest.TestCase): diff --git a/python/qa_crc16_bb.py b/python/qa_crc16_bb.py index 05b1489a..c7b807b3 100755 --- a/python/qa_crc16_bb.py +++ b/python/qa_crc16_bb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_crc16_bb(gr_unittest.TestCase): diff --git a/python/qa_dab_transmission_frame_mux_bb.py b/python/qa_dab_transmission_frame_mux_bb.py index e8de99b4..0f357fca 100755 --- a/python/qa_dab_transmission_frame_mux_bb.py +++ b/python/qa_dab_transmission_frame_mux_bb.py @@ -23,7 +23,7 @@ from gnuradio import blocks from gnuradio import audio from gnuradio import fft -import dab +import dab_swig as dab import os class qa_dab_transmission_frame_mux_bb (gr_unittest.TestCase): diff --git a/python/qa_dabplus_audio_decoder_ff.py b/python/qa_dabplus_audio_decoder_ff.py index 5f957a04..ce68ccdf 100755 --- a/python/qa_dabplus_audio_decoder_ff.py +++ b/python/qa_dabplus_audio_decoder_ff.py @@ -23,7 +23,7 @@ from gnuradio import blocks from gnuradio import audio import os -import dab +import dab_swig as dab from gnuradio import audio class qa_dabplus_audio_decoder_ff (gr_unittest.TestCase): diff --git a/python/qa_energy_disp.py b/python/qa_energy_disp.py index 6f9dd330..4c719211 100644 --- a/python/qa_energy_disp.py +++ b/python/qa_energy_disp.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_energy_disp (gr_unittest.TestCase): diff --git a/python/qa_fib_sink_vb.py b/python/qa_fib_sink_vb.py index aee74319..7af5c45c 100644 --- a/python/qa_fib_sink_vb.py +++ b/python/qa_fib_sink_vb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_fib_sink_vb (gr_unittest.TestCase): diff --git a/python/qa_fib_source_b.py b/python/qa_fib_source_b.py index dbcaed88..4124314d 100755 --- a/python/qa_fib_source_b.py +++ b/python/qa_fib_source_b.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_fib_source_b (gr_unittest.TestCase): diff --git a/python/qa_fic_encode.py b/python/qa_fic_encode.py index ad563c40..959653dd 100755 --- a/python/qa_fic_encode.py +++ b/python/qa_fic_encode.py @@ -22,7 +22,10 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks from gnuradio import fec -import dab +import dab_swig as dab +from parameters import dab_parameters +from fic_encode import fic_encode +from fic import fic_decode class qa_fic_encode (gr_unittest.TestCase): @@ -36,14 +39,14 @@ def tearDown (self): # manual check, if fibs are correctly processed through the coding and mapping blocks def test_001_t (self): self.symbol_length = 32*4 - self.dab_params = dab.parameters.dab_parameters(1, 208.064e6, True) + self.dab_params = dab_parameters(1, 208.064e6, True) # source - self.dp = dab.parameters.dab_parameters(1, 208.064e6, True) + self.dp = dab_parameters(1, 208.064e6, True) self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1", "musicmix", 4, [2], [15]) # encoder - self.fib_enc = dab.fic_encode(self.dab_params) + self.fib_enc = fic_encode(self.dab_params) self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) # mapper @@ -54,7 +57,7 @@ def test_001_t (self): self.soft_interleaver = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers) # decode - self.fic_decoder = dab.fic_decode(self.dab_params) + self.fic_decoder = fic_decode(self.dab_params) # control stream self.trigger_src = blocks.vector_source_b([1] + [0]*74, True) diff --git a/python/qa_mapper_bc.py b/python/qa_mapper_bc.py index 21046975..434b4f25 100755 --- a/python/qa_mapper_bc.py +++ b/python/qa_mapper_bc.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab from math import sqrt class qa_mapper_bc (gr_unittest.TestCase): diff --git a/python/qa_mp2_decode_bs.py b/python/qa_mp2_decode_bs.py index fdd40fb8..3248b1d6 100755 --- a/python/qa_mp2_decode_bs.py +++ b/python/qa_mp2_decode_bs.py @@ -22,7 +22,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks import os -import dab +import dab_swig as dab class qa_mp2_decode_bs (gr_unittest.TestCase): diff --git a/python/qa_mp2_encode_sb.py b/python/qa_mp2_encode_sb.py index d97f668e..2bef0f30 100755 --- a/python/qa_mp2_encode_sb.py +++ b/python/qa_mp2_encode_sb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab import os class qa_mp2_encode_sb (gr_unittest.TestCase): diff --git a/python/qa_mp4_decode_bs.py b/python/qa_mp4_decode_bs.py index 57dc32f8..3819815e 100755 --- a/python/qa_mp4_decode_bs.py +++ b/python/qa_mp4_decode_bs.py @@ -23,7 +23,7 @@ from gnuradio import blocks from gnuradio import audio import os -import dab +import dab_swig as dab class qa_mp4_decode_bs (gr_unittest.TestCase): diff --git a/python/qa_mp4_encode_sb.py b/python/qa_mp4_encode_sb.py index 68ae2f2b..469a2a08 100755 --- a/python/qa_mp4_encode_sb.py +++ b/python/qa_mp4_encode_sb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab from gnuradio import audio import os diff --git a/python/qa_msc_decode.py b/python/qa_msc_decode.py index 17593595..a6ed5379 100755 --- a/python/qa_msc_decode.py +++ b/python/qa_msc_decode.py @@ -22,7 +22,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks import os -import dab +import dab_swig as dab class qa_msc_decode (gr_unittest.TestCase): diff --git a/python/qa_msc_encode.py b/python/qa_msc_encode.py index 1a8f1e23..29907bc2 100755 --- a/python/qa_msc_encode.py +++ b/python/qa_msc_encode.py @@ -23,7 +23,7 @@ from gnuradio import blocks from gnuradio import audio import os -import dab +import dab_swig as dab class qa_msc_encode(gr_unittest.TestCase): diff --git a/python/qa_prune.py b/python/qa_prune.py index 5aa5f0bd..b2032bf4 100755 --- a/python/qa_prune.py +++ b/python/qa_prune.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_prune (gr_unittest.TestCase): diff --git a/python/qa_puncture_bb.py b/python/qa_puncture_bb.py index 755da6b4..3902320e 100755 --- a/python/qa_puncture_bb.py +++ b/python/qa_puncture_bb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_puncture_bb (gr_unittest.TestCase): diff --git a/python/qa_reed_solomon_decode_bb.py b/python/qa_reed_solomon_decode_bb.py index 8743ce11..15945071 100755 --- a/python/qa_reed_solomon_decode_bb.py +++ b/python/qa_reed_solomon_decode_bb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab import os class qa_reed_solomon_decode_bb (gr_unittest.TestCase): diff --git a/python/qa_reed_solomon_encode_bb.py b/python/qa_reed_solomon_encode_bb.py index 625fe3a8..af2c16d2 100755 --- a/python/qa_reed_solomon_encode_bb.py +++ b/python/qa_reed_solomon_encode_bb.py @@ -22,7 +22,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks import random -import dab +import dab_swig as dab class qa_reed_solomon_encode_bb(gr_unittest.TestCase): diff --git a/python/qa_repartition_vectors.py b/python/qa_repartition_vectors.py index cb6c371b..429a6b0f 100755 --- a/python/qa_repartition_vectors.py +++ b/python/qa_repartition_vectors.py @@ -20,7 +20,7 @@ # from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab class qa_repartition_vectors(gr_unittest.TestCase): diff --git a/python/qa_select_subch_vfvf.py b/python/qa_select_subch_vfvf.py index ef12acab..d591af35 100755 --- a/python/qa_select_subch_vfvf.py +++ b/python/qa_select_subch_vfvf.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_select_subch_vfvf (gr_unittest.TestCase): diff --git a/python/qa_select_vectors.py b/python/qa_select_vectors.py index c135ad57..4da6e1a3 100755 --- a/python/qa_select_vectors.py +++ b/python/qa_select_vectors.py @@ -20,7 +20,7 @@ # from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab class qa_select_vectors(gr_unittest.TestCase): diff --git a/python/qa_time_deinterleave_ff.py b/python/qa_time_deinterleave_ff.py index ebe194af..cc76e00d 100755 --- a/python/qa_time_deinterleave_ff.py +++ b/python/qa_time_deinterleave_ff.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_time_deinterleave_ff (gr_unittest.TestCase): diff --git a/python/qa_time_interleave_bb.py b/python/qa_time_interleave_bb.py index 472fea91..c0a8aa2f 100755 --- a/python/qa_time_interleave_bb.py +++ b/python/qa_time_interleave_bb.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_time_interleave_bb (gr_unittest.TestCase): diff --git a/python/qa_unpuncture_ff.py b/python/qa_unpuncture_ff.py index b27f6a0f..bcf2bf51 100755 --- a/python/qa_unpuncture_ff.py +++ b/python/qa_unpuncture_ff.py @@ -21,7 +21,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab class qa_unpuncture_ff (gr_unittest.TestCase): From 2bbe53673f67d2a3418e2d0165af41deb442c455 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 21 Aug 2017 18:00:49 +0200 Subject: [PATCH 022/135] GUI: prevent overflow of labels and set border for maximum of services --- lib/fib_source_b_impl.cc | 2 +- python/GUI/main.py | 32 +++-- python/GUI/user_frontend.py | 209 +++++++++++++++++----------- python/GUI/user_frontend.ui | 264 ++++++++++++++++++++++++++---------- 4 files changed, 347 insertions(+), 160 deletions(-) diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index 27e135ab..8d017827 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -206,7 +206,7 @@ namespace gr { if ((d_nFIBs_written % 3 == 0 && d_transmission_mode != 3) || (d_nFIBs_written % 4 == 0 && d_transmission_mode == 3)) { //////////////////////////////////////////////// -/// add first FIB with only MCI (max numSubCh = 5) +/// add first FIB with only MCI (max services = 4) //////////////////////////////////////////////// //ensemble info std::memcpy(out + d_offset, d_ensemble_info, d_size_ensemble_info); diff --git a/python/GUI/main.py b/python/GUI/main.py index 3660d6b6..e57c8cd1 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -126,31 +126,31 @@ def __init__(self, parent=None): # create dict for service components self.components = [ {"label": self.t_label_comp1, "data_rate_label": self.t_label_rate1, "data_rate": self.t_spin_rate1, - "protection_label": self.t_label_prot1, "protection": self.t_spin_prot1, "enabled": True, + "protection_label": self.t_label_prot1, "protection": self.t_combo_prot1, "enabled": True, "src_label": self.t_label_comp_src1, "src_path_disp": self.t_label_path_src1, "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1}, {"label": self.t_label_comp2, "data_rate_label": self.t_label_rate2, "data_rate": self.t_spin_rate2, - "protection_label": self.t_label_prot2, "protection": self.t_spin_prot2, "enabled": False, + "protection_label": self.t_label_prot2, "protection": self.t_combo_prot2, "enabled": False, "src_label": self.t_label_comp_src2, "src_path_disp": self.t_label_path_src2, "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2}, {"label": self.t_label_comp3, "data_rate_label": self.t_label_rate3, "data_rate": self.t_spin_rate3, - "protection_label": self.t_label_prot3, "protection": self.t_spin_prot3, "enabled": False, + "protection_label": self.t_label_prot3, "protection": self.t_combo_prot3, "enabled": False, "src_label": self.t_label_comp_src3, "src_path_disp": self.t_label_path_src3, "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3}, {"label": self.t_label_comp4, "data_rate_label": self.t_label_rate4, "data_rate": self.t_spin_rate4, - "protection_label": self.t_label_prot4, "protection": self.t_spin_prot4, "enabled": False, + "protection_label": self.t_label_prot4, "protection": self.t_combo_prot4, "enabled": False, "src_label": self.t_label_comp_src4, "src_path_disp": self.t_label_path_src4, "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4}, {"label": self.t_label_comp5, "data_rate_label": self.t_label_rate5, "data_rate": self.t_spin_rate5, - "protection_label": self.t_label_prot5, "protection": self.t_spin_prot5, "enabled": False, + "protection_label": self.t_label_prot5, "protection": self.t_combo_prot5, "enabled": False, "src_label": self.t_label_comp_src5, "src_path_disp": self.t_label_path_src5, "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5}, {"label": self.t_label_comp6, "data_rate_label": self.t_label_rate6, "data_rate": self.t_spin_rate6, - "protection_label": self.t_label_prot6, "protection": self.t_spin_prot6, "enabled": False, + "protection_label": self.t_label_prot6, "protection": self.t_combo_prot6, "enabled": False, "src_label": self.t_label_comp_src6, "src_path_disp": self.t_label_path_src6, "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6}, {"label": self.t_label_comp7, "data_rate_label": self.t_label_rate7, "data_rate": self.t_spin_rate7, - "protection_label": self.t_label_prot7, "protection": self.t_spin_prot7, "enabled": False, + "protection_label": self.t_label_prot7, "protection": self.t_combo_prot7, "enabled": False, "src_label": self.t_label_comp_src7, "src_path_disp": self.t_label_path_src7, "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7}] # update service components initially to hide the service components 2-7 @@ -237,6 +237,7 @@ def init_receiver(self): if (not self.src_is_USRP) and (self.file_path == "None"): self.label_path.setStyleSheet('color: red') else: + self.label_path.setStyleSheet('color: black') # set up and start flowgraph self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, self.src_is_USRP, self.file_path, self.recorder) @@ -671,7 +672,7 @@ def t_init_transmitter(self): record_states = [False] * self.t_spin_num_subch.value() for i in range(0, self.t_spin_num_subch.value()): # write array with protection modes - protection_array[i] = self.components[i]["protection"].value() + protection_array[i] = self.components[i]["protection"].currentIndex() # write array with data rates data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 # check audio paths @@ -680,14 +681,25 @@ def t_init_transmitter(self): self.components[i]["src_path_disp"].setStyleSheet('color: red') arguments_incomplete = True self.statusBar.showMessage("path " + str(i+1) + " not selected") + # check if length of label is <= 16 chars + elif len(str(self.components[i]["edit_label"].text())) > 16: + self.components[i]["edit_label"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("Warning: Label is longer than 16 characters!") else: audio_paths[i] = self.components[i]["src_path"] - # write service labels + # write service labels appended in one string merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) + self.components[i]["edit_label"].setStyleSheet('color: black') # write dabplus types dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) - print merged_service_string + # check if length of ensemble label is <= 16 chars + if len(str(self.t_edit_ensemble_label.text())) > 16: + self.t_edit_ensemble_label.setStyleSheet('color: red') + arguments_incomplete = True + else: + self.t_edit_ensemble_label.setStyleSheet('color: black') # check if File path for sink is chosen if option enabled if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): self.t_label_sink.setStyleSheet('color: red') diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index a1318ba1..b96968ef 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(992, 739) + MainWindow.resize(1146, 739) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -209,6 +209,8 @@ def setupUi(self, MainWindow): self.line_11.setFrameShadow(QtGui.QFrame.Sunken) self.line_11.setObjectName(_fromUtf8("line_11")) self.verticalLayout_7.addWidget(self.line_11) + spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem3) self.horizontalLayout_23 = QtGui.QHBoxLayout() self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) self.bar_snr = QtGui.QProgressBar(self.tab_reception) @@ -253,15 +255,15 @@ def setupUi(self, MainWindow): self.horizontalLayout_29.addWidget(self.label_firecode) self.verticalLayout_13 = QtGui.QVBoxLayout() self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) - spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem3) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem4) self.led_msc = KLed(self.tab_reception) self.led_msc.setLook(KLed.Sunken) self.led_msc.setDarkFactor(300) self.led_msc.setObjectName(_fromUtf8("led_msc")) self.verticalLayout_13.addWidget(self.led_msc) - spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem4) + spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_13.addItem(spacerItem5) self.horizontalLayout_29.addLayout(self.verticalLayout_13) self.label_label_msc = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() @@ -271,8 +273,8 @@ def setupUi(self, MainWindow): self.label_label_msc.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.label_label_msc.setObjectName(_fromUtf8("label_label_msc")) self.horizontalLayout_29.addWidget(self.label_label_msc) - spacerItem5 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_29.addItem(spacerItem5) + spacerItem6 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_29.addItem(spacerItem6) self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_29) self.horizontalLayout_32 = QtGui.QHBoxLayout() self.horizontalLayout_32.setObjectName(_fromUtf8("horizontalLayout_32")) @@ -287,14 +289,14 @@ def setupUi(self, MainWindow): self.horizontalLayout_32.addWidget(self.label_fic) self.verticalLayout_14 = QtGui.QVBoxLayout() self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) - spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem6) + spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem7) self.led_fic = KLed(self.tab_reception) self.led_fic.setLook(KLed.Sunken) self.led_fic.setObjectName(_fromUtf8("led_fic")) self.verticalLayout_14.addWidget(self.led_fic) - spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem7) + spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_14.addItem(spacerItem8) self.horizontalLayout_32.addLayout(self.verticalLayout_14) self.label_label_fic = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() @@ -304,12 +306,12 @@ def setupUi(self, MainWindow): self.label_label_fic.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.label_label_fic.setObjectName(_fromUtf8("label_label_fic")) self.horizontalLayout_32.addWidget(self.label_label_fic) - spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_32.addItem(spacerItem8) + spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_32.addItem(spacerItem9) self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_32) self.verticalLayout_7.addLayout(self.vertical_layout_dev_mode_right_vertical) - spacerItem9 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem9) + spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem10) self.line_6 = QtGui.QFrame(self.tab_reception) self.line_6.setFrameShape(QtGui.QFrame.HLine) self.line_6.setFrameShadow(QtGui.QFrame.Sunken) @@ -375,8 +377,8 @@ def setupUi(self, MainWindow): self.line_9.setFrameShadow(QtGui.QFrame.Sunken) self.line_9.setObjectName(_fromUtf8("line_9")) self.verticalLayout_7.addWidget(self.line_9) - spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem10) + spacerItem11 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem11) self.label_2 = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() font.setBold(True) @@ -437,7 +439,7 @@ def setupUi(self, MainWindow): self.dev_scroll_area.setWidgetResizable(True) self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) self.dev_scroll_area_content = QtGui.QWidget() - self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 87, 602)) + self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 241, 602)) self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) @@ -463,8 +465,8 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem11) + spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem12) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) @@ -510,8 +512,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_10) self.horizontalLayout_31 = QtGui.QHBoxLayout() self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem12) + spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem13) self.label_8 = QtGui.QLabel(self.tab_transmission) self.label_8.setObjectName(_fromUtf8("label_8")) self.horizontalLayout_31.addWidget(self.label_8) @@ -530,7 +532,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 448, 1269)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 525, 1269)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -571,11 +573,6 @@ def setupUi(self, MainWindow): self.t_label_prot1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot1.setObjectName(_fromUtf8("t_label_prot1")) self.formLayout_3.setWidget(5, QtGui.QFormLayout.LabelRole, self.t_label_prot1) - self.t_spin_prot1 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot1.setMaximum(3) - self.t_spin_prot1.setProperty("value", 2) - self.t_spin_prot1.setObjectName(_fromUtf8("t_spin_prot1")) - self.formLayout_3.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_spin_prot1) self.t_label_comp_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src1.setObjectName(_fromUtf8("t_label_comp_src1")) self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) @@ -636,10 +633,6 @@ def setupUi(self, MainWindow): self.t_label_prot2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot2.setObjectName(_fromUtf8("t_label_prot2")) self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_prot2) - self.t_spin_prot2 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot2.setProperty("value", 2) - self.t_spin_prot2.setObjectName(_fromUtf8("t_spin_prot2")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_spin_prot2) self.t_label_comp_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src2.setObjectName(_fromUtf8("t_label_comp_src2")) self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) @@ -687,10 +680,6 @@ def setupUi(self, MainWindow): self.t_label_prot3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot3.setObjectName(_fromUtf8("t_label_prot3")) self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_prot3) - self.t_spin_prot3 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot3.setProperty("value", 2) - self.t_spin_prot3.setObjectName(_fromUtf8("t_spin_prot3")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_spin_prot3) self.t_label_comp_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src3.setObjectName(_fromUtf8("t_label_comp_src3")) self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) @@ -737,10 +726,6 @@ def setupUi(self, MainWindow): self.t_label_prot4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot4.setObjectName(_fromUtf8("t_label_prot4")) self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_prot4) - self.t_spin_prot4 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot4.setProperty("value", 2) - self.t_spin_prot4.setObjectName(_fromUtf8("t_spin_prot4")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.FieldRole, self.t_spin_prot4) self.t_label_comp_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src4.setObjectName(_fromUtf8("t_label_comp_src4")) self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) @@ -787,10 +772,6 @@ def setupUi(self, MainWindow): self.t_label_prot5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot5.setObjectName(_fromUtf8("t_label_prot5")) self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_prot5) - self.t_spin_prot5 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot5.setProperty("value", 2) - self.t_spin_prot5.setObjectName(_fromUtf8("t_spin_prot5")) - self.formLayout_3.setWidget(25, QtGui.QFormLayout.FieldRole, self.t_spin_prot5) self.t_label_comp_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src5.setObjectName(_fromUtf8("t_label_comp_src5")) self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) @@ -837,10 +818,6 @@ def setupUi(self, MainWindow): self.t_label_prot6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot6.setObjectName(_fromUtf8("t_label_prot6")) self.formLayout_3.setWidget(30, QtGui.QFormLayout.LabelRole, self.t_label_prot6) - self.t_spin_prot6 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot6.setProperty("value", 2) - self.t_spin_prot6.setObjectName(_fromUtf8("t_spin_prot6")) - self.formLayout_3.setWidget(30, QtGui.QFormLayout.FieldRole, self.t_spin_prot6) self.t_label_comp_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src6.setObjectName(_fromUtf8("t_label_comp_src6")) self.formLayout_3.setWidget(31, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) @@ -887,11 +864,6 @@ def setupUi(self, MainWindow): self.t_label_prot7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot7.setObjectName(_fromUtf8("t_label_prot7")) self.formLayout_3.setWidget(35, QtGui.QFormLayout.LabelRole, self.t_label_prot7) - self.t_spin_prot7 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_prot7.setEnabled(True) - self.t_spin_prot7.setProperty("value", 2) - self.t_spin_prot7.setObjectName(_fromUtf8("t_spin_prot7")) - self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_spin_prot7) self.t_label_comp_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src7.setObjectName(_fromUtf8("t_label_comp_src7")) self.formLayout_3.setWidget(36, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) @@ -963,8 +935,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) - spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus1.addItem(spacerItem13) + spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus1.addItem(spacerItem14) self.t_combo_dabplus1 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus1.setObjectName(_fromUtf8("t_combo_dabplus1")) self.t_combo_dabplus1.addItem(_fromUtf8("")) @@ -973,8 +945,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(2, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus1) self.t_layout_combo_dabplus2 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus2.setObjectName(_fromUtf8("t_layout_combo_dabplus2")) - spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus2.addItem(spacerItem14) + spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus2.addItem(spacerItem15) self.t_combo_dabplus2 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus2.setObjectName(_fromUtf8("t_combo_dabplus2")) self.t_combo_dabplus2.addItem(_fromUtf8("")) @@ -983,8 +955,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) - spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus3.addItem(spacerItem15) + spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus3.addItem(spacerItem16) self.t_combo_dabplus3 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus3.setObjectName(_fromUtf8("t_combo_dabplus3")) self.t_combo_dabplus3.addItem(_fromUtf8("")) @@ -993,8 +965,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) - spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus4.addItem(spacerItem16) + spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus4.addItem(spacerItem17) self.t_combo_dabplus4 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus4.setObjectName(_fromUtf8("t_combo_dabplus4")) self.t_combo_dabplus4.addItem(_fromUtf8("")) @@ -1003,8 +975,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(17, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) - spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus5.addItem(spacerItem17) + spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus5.addItem(spacerItem18) self.t_combo_dabplus5 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus5.setObjectName(_fromUtf8("t_combo_dabplus5")) self.t_combo_dabplus5.addItem(_fromUtf8("")) @@ -1013,8 +985,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(22, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) - spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus6.addItem(spacerItem18) + spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus6.addItem(spacerItem19) self.t_combo_dabplus6 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus6.setObjectName(_fromUtf8("t_combo_dabplus6")) self.t_combo_dabplus6.addItem(_fromUtf8("")) @@ -1023,14 +995,63 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(27, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) - spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus7.addItem(spacerItem19) + spacerItem20 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus7.addItem(spacerItem20) self.t_combo_dabplus7 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus7.setObjectName(_fromUtf8("t_combo_dabplus7")) self.t_combo_dabplus7.addItem(_fromUtf8("")) self.t_combo_dabplus7.addItem(_fromUtf8("")) self.t_layout_combo_dabplus7.addWidget(self.t_combo_dabplus7) self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus7) + self.t_combo_prot1 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot1.setObjectName(_fromUtf8("t_combo_prot1")) + self.t_combo_prot1.addItem(_fromUtf8("")) + self.t_combo_prot1.addItem(_fromUtf8("")) + self.t_combo_prot1.addItem(_fromUtf8("")) + self.t_combo_prot1.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_combo_prot1) + self.t_combo_prot2 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot2.setObjectName(_fromUtf8("t_combo_prot2")) + self.t_combo_prot2.addItem(_fromUtf8("")) + self.t_combo_prot2.addItem(_fromUtf8("")) + self.t_combo_prot2.addItem(_fromUtf8("")) + self.t_combo_prot2.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_combo_prot2) + self.t_combo_prot3 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot3.setObjectName(_fromUtf8("t_combo_prot3")) + self.t_combo_prot3.addItem(_fromUtf8("")) + self.t_combo_prot3.addItem(_fromUtf8("")) + self.t_combo_prot3.addItem(_fromUtf8("")) + self.t_combo_prot3.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_combo_prot3) + self.t_combo_prot4 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot4.setObjectName(_fromUtf8("t_combo_prot4")) + self.t_combo_prot4.addItem(_fromUtf8("")) + self.t_combo_prot4.addItem(_fromUtf8("")) + self.t_combo_prot4.addItem(_fromUtf8("")) + self.t_combo_prot4.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(20, QtGui.QFormLayout.FieldRole, self.t_combo_prot4) + self.t_combo_prot5 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot5.setObjectName(_fromUtf8("t_combo_prot5")) + self.t_combo_prot5.addItem(_fromUtf8("")) + self.t_combo_prot5.addItem(_fromUtf8("")) + self.t_combo_prot5.addItem(_fromUtf8("")) + self.t_combo_prot5.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(25, QtGui.QFormLayout.FieldRole, self.t_combo_prot5) + self.t_combo_prot6 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot6.setObjectName(_fromUtf8("t_combo_prot6")) + self.t_combo_prot6.addItem(_fromUtf8("")) + self.t_combo_prot6.addItem(_fromUtf8("")) + self.t_combo_prot6.addItem(_fromUtf8("")) + self.t_combo_prot6.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(30, QtGui.QFormLayout.FieldRole, self.t_combo_prot6) + self.t_combo_prot7 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_prot7.setObjectName(_fromUtf8("t_combo_prot7")) + self.t_combo_prot7.addItem(_fromUtf8("")) + self.t_combo_prot7.addItem(_fromUtf8("")) + self.t_combo_prot7.addItem(_fromUtf8("")) + self.t_combo_prot7.addItem(_fromUtf8("")) + self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_combo_prot7) self.verticalLayout_4.addLayout(self.formLayout_3) self.line_15 = QtGui.QFrame(self.scrollAreaWidgetContents) self.line_15.setFrameShape(QtGui.QFrame.HLine) @@ -1081,6 +1102,14 @@ def setupUi(self, MainWindow): self.label_14 = QtGui.QLabel(self.tab_transmission) self.label_14.setObjectName(_fromUtf8("label_14")) self.formLayout_2.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_14) + self.t_combo_country = QtGui.QComboBox(self.tab_transmission) + self.t_combo_country.setObjectName(_fromUtf8("t_combo_country")) + self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.t_combo_country) + self.line = QtGui.QFrame(self.tab_transmission) + self.line.setFrameShape(QtGui.QFrame.HLine) + self.line.setFrameShadow(QtGui.QFrame.Sunken) + self.line.setObjectName(_fromUtf8("line")) + self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) self.label_15 = QtGui.QLabel(self.tab_transmission) font = QtGui.QFont() font.setPointSize(13) @@ -1109,16 +1138,8 @@ def setupUi(self, MainWindow): self.t_combo_language = QtGui.QComboBox(self.tab_transmission) self.t_combo_language.setObjectName(_fromUtf8("t_combo_language")) self.formLayout_2.setWidget(7, QtGui.QFormLayout.FieldRole, self.t_combo_language) - self.t_combo_country = QtGui.QComboBox(self.tab_transmission) - self.t_combo_country.setObjectName(_fromUtf8("t_combo_country")) - self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.t_combo_country) - self.line = QtGui.QFrame(self.tab_transmission) - self.line.setFrameShape(QtGui.QFrame.HLine) - self.line.setFrameShadow(QtGui.QFrame.Sunken) - self.line.setObjectName(_fromUtf8("line")) - self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - spacerItem20 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem20) + spacerItem21 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem21) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -1133,8 +1154,8 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem21 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem21) + spacerItem22 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem22) self.verticalLayout_8.addLayout(self.horizontalLayout_22) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) @@ -1200,7 +1221,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) + self.mode_tabs.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1319,6 +1340,34 @@ def retranslateUi(self, MainWindow): self.t_combo_dabplus6.setItemText(1, _translate("MainWindow", "DAB", None)) self.t_combo_dabplus7.setItemText(0, _translate("MainWindow", "DAB+", None)) self.t_combo_dabplus7.setItemText(1, _translate("MainWindow", "DAB", None)) + self.t_combo_prot1.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot1.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot1.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot1.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot2.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot2.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot2.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot2.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot3.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot3.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot3.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot3.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot4.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot4.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot4.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot4.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot5.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot5.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot5.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot5.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot6.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot6.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot6.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot6.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_combo_prot7.setItemText(0, _translate("MainWindow", "A1", None)) + self.t_combo_prot7.setItemText(1, _translate("MainWindow", "A2", None)) + self.t_combo_prot7.setItemText(2, _translate("MainWindow", "A3", None)) + self.t_combo_prot7.setItemText(3, _translate("MainWindow", "A4", None)) self.t_label_increase_num_subch_info.setText(_translate("MainWindow", "increase \"Number of channels\" for more components", None)) self.label_12.setText(_translate("MainWindow", "Ensemble info", None)) self.label_13.setText(_translate("MainWindow", "Label", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 12b31c4f..7830a0ba 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,7 +6,7 @@ 0 0 - 992 + 1146 739 @@ -85,7 +85,7 @@ true - 0 + 1 @@ -383,6 +383,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -941,7 +954,7 @@ 0 0 - 87 + 241 602 @@ -1139,7 +1152,7 @@ 0 0 - 448 + 525 1269 @@ -1210,16 +1223,6 @@ - - - - 3 - - - 2 - - - @@ -1349,13 +1352,6 @@ - - - - 2 - - - @@ -1458,13 +1454,6 @@ - - - - 2 - - - @@ -1564,13 +1553,6 @@ - - - - 2 - - - @@ -1670,13 +1652,6 @@ - - - - 2 - - - @@ -1776,13 +1751,6 @@ - - - - 2 - - - @@ -1882,16 +1850,6 @@ - - - - true - - - 2 - - - @@ -2240,6 +2198,174 @@ + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + + + + + + A1 + + + + + A2 + + + + + A3 + + + + + A4 + + + + @@ -2329,6 +2455,16 @@ + + + + + + + Qt::Horizontal + + + @@ -2384,16 +2520,6 @@ - - - - - - - Qt::Horizontal - - - From 328c1b0774fe3dcafa9824f0e8f07dc3e90d39a7 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 21 Aug 2017 20:04:32 +0200 Subject: [PATCH 023/135] receiver: fix fatal bug in mp2 decoding --- lib/mp2_decode_bs_impl.cc | 7 ++++--- python/GUI/usrp_dabplus_rx.py | 5 +++-- python/GUI/usrp_dabplus_tx.py | 12 +++++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/mp2_decode_bs_impl.cc b/lib/mp2_decode_bs_impl.cc index d259fbdd..cda9adda 100644 --- a/lib/mp2_decode_bs_impl.cc +++ b/lib/mp2_decode_bs_impl.cc @@ -263,6 +263,7 @@ namespace gr { d_output_size = KJMP2_SAMPLES_PER_FRAME; set_output_multiple(d_output_size); + GR_LOG_DEBUG(d_logger, "mp2 decoder initialized"); } /* @@ -640,10 +641,10 @@ namespace gr { out_right[d_nproduced + n] = sample_buf[n*2+1]; } d_nproduced += KJMP2_SAMPLES_PER_FRAME; + GR_LOG_DEBUG(d_logger, "mp2 decoding succeeded"); } else { GR_LOG_DEBUG(d_logger, "mp2 decoding failed"); } - d_mp2_header_OK = 0; d_mp2_header_count = 0; d_mp2_bit_count = 0; @@ -657,8 +658,9 @@ namespace gr { add_bit_to_mp2(d_mp2_frame, 1, d_mp2_bit_count++); d_mp2_header_OK = 1; } - } else + }else { d_mp2_header_count = 0; + } } else if (d_mp2_header_OK == 1) { add_bit_to_mp2(d_mp2_frame, in[logical_frame_count * d_mp2_framesize + i], d_mp2_bit_count++); if (d_mp2_bit_count == 24) { @@ -669,7 +671,6 @@ namespace gr { } } - // Tell runtime system how many input items we consumed on // each input stream. consume_each(noutput_items / d_output_size * d_mp2_framesize); diff --git a/python/GUI/usrp_dabplus_rx.py b/python/GUI/usrp_dabplus_rx.py index 86a8fa22..c6229444 100644 --- a/python/GUI/usrp_dabplus_rx.py +++ b/python/GUI/usrp_dabplus_rx.py @@ -102,7 +102,8 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) else: self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) - self.mp2_dec = dab.mp2_decode_bs_make(bit_rate) + self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) + self.mp2_dec = dab.mp2_decode_bs_make(bit_rate / 8) self.s2f_left = blocks.short_to_float_make(1, 32767) self.s2f_right = blocks.short_to_float_make(1, 32767) self.gain_left = blocks.multiply_const_ff(1, 1) @@ -120,7 +121,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect((self.demod, 0), (self.dabplus, 0)) self.connect((self.demod, 1), (self.dabplus, 1)) else: - self.connect((self.demod, 0), (self.msc_dec, 0), self.mp2_dec) + self.connect((self.demod, 0), (self.msc_dec, 0), self.unpack, self.mp2_dec) self.connect((self.demod, 1), (self.msc_dec, 1)) self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py index cb465c3c..8c7fa6fd 100644 --- a/python/GUI/usrp_dabplus_tx.py +++ b/python/GUI/usrp_dabplus_tx.py @@ -44,13 +44,16 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.language = language self.protections = protections self.data_rates_n = data_rates_n - self.subch_sizes = np.multiply(self.data_rates_n, 6) self.src_paths = src_paths self.use_usrp = use_usrp self.dabplus_types = dabplus_types self.sink_path = sink_path self.selected_audio = selected_audio self.volume = 80 + sizes = {0: 12, 1: 8, 2: 6, 3: 4} + self.subch_sizes = [None] * len(self.data_rates_n) + for i in range(0, len(self.data_rates_n)): + self.subch_sizes[i] = self.data_rates_n[i] * sizes[protections[i]] ######################## # FIC @@ -74,7 +77,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label for i in range(0, self.num_subch): if not self.src_paths[i] is "mic": # source - self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) + self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], False) # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) @@ -92,7 +95,6 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label # MUX ######################## self.mux = dab.dab_transmission_frame_mux_bb_make(self.dab_mode, self.num_subch, self.subch_sizes) - #self.mux = dab.dab_transmission_frame_mux_bb_make(1, 1, [84, 84]) self.trigsrc = blocks.vector_source_b([1] + [0] * (self.dp.symbols_per_frame-2), True) ######################## @@ -137,8 +139,8 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) - self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) - self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) + #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) + #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) def transmit(self): tx = usrp_dabplus_tx() From 507bcf695353facfbc772967cb63cadc485e925d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Mon, 21 Aug 2017 20:26:34 +0200 Subject: [PATCH 024/135] removed header that becomes redundant through fdk-aac-dab --- lib/FDK_audio.h | 645 ------------------------------------------------ 1 file changed, 645 deletions(-) delete mode 100644 lib/FDK_audio.h diff --git a/lib/FDK_audio.h b/lib/FDK_audio.h deleted file mode 100644 index 9a787fb8..00000000 --- a/lib/FDK_audio.h +++ /dev/null @@ -1,645 +0,0 @@ - -/* ----------------------------------------------------------------------------------------------------------- -Software License for The Fraunhofer FDK AAC Codec Library for Android - -© Copyright 1995 - 2015 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. - All rights reserved. - - 1. INTRODUCTION -The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements -the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. -This FDK AAC Codec software is intended to be used on a wide variety of Android devices. - -AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual -audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by -independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part -of the MPEG specifications. - -Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) -may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners -individually for the purpose of encoding or decoding bit streams in products that are compliant with -the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license -these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec -software may already be covered under those patent licenses when it is used for those licensed purposes only. - -Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, -are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional -applications information and documentation. - -2. COPYRIGHT LICENSE - -Redistribution and use in source and binary forms, with or without modification, are permitted without -payment of copyright license fees provided that you satisfy the following conditions: - -You must retain the complete text of this software license in redistributions of the FDK AAC Codec or -your modifications thereto in source code form. - -You must retain the complete text of this software license in the documentation and/or other materials -provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. -You must make available free of charge copies of the complete source code of the FDK AAC Codec and your -modifications thereto to recipients of copies in binary form. - -The name of Fraunhofer may not be used to endorse or promote products derived from this library without -prior written permission. - -You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec -software or your modifications thereto. - -Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software -and the date of any change. For modified versions of the FDK AAC Codec, the term -"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term -"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." - -3. NO PATENT LICENSE - -NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, -ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with -respect to this software. - -You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized -by appropriate patent licenses. - -4. DISCLAIMER - -This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors -"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties -of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, -including but not limited to procurement of substitute goods or services; loss of use, data, or profits, -or business interruption, however caused and on any theory of liability, whether in contract, strict -liability, or tort (including negligence), arising in any way out of the use of this software, even if -advised of the possibility of such damage. - -5. CONTACT INFORMATION - -Fraunhofer Institute for Integrated Circuits IIS -Attention: Audio and Multimedia Departments - FDK AAC LL -Am Wolfsmantel 33 -91058 Erlangen, Germany - -www.iis.fraunhofer.de/amm -amm-info@iis.fraunhofer.de ------------------------------------------------------------------------------------------------------------ */ - -/************************** Fraunhofer IIS FDK SysLib ********************** - - Author(s): Manuel Jander - -******************************************************************************/ - -/** \file FDK_audio.h - * \brief Global audio struct and constant definitions. - */ - -#ifndef FDK_AUDIO_H -#define FDK_AUDIO_H - -#include "machine_type.h" -#include "genericStds.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * File format identifiers. - */ -typedef enum -{ - FF_UNKNOWN = -1, /**< Unknown format. */ - FF_RAW = 0, /**< No container, bit stream data conveyed "as is". */ - - FF_MP4_3GPP = 3, /**< 3GPP file format. */ - FF_MP4_MP4F = 4, /**< MPEG-4 File format. */ - - FF_RAWPACKETS = 5, /**< Proprietary raw packet file. */ - - FF_DRMCT = 12 /**< Digital Radio Mondial (DRM30/DRM+) CT proprietary file format. */ - -} FILE_FORMAT; - -/** - * Transport type identifiers. - */ -typedef enum -{ - TT_UNKNOWN = -1, /**< Unknown format. */ - TT_MP4_RAW = 0, /**< "as is" access units (packet based since there is obviously no sync layer) */ - TT_MP4_ADIF = 1, /**< ADIF bitstream format. */ - TT_MP4_ADTS = 2, /**< ADTS bitstream format. */ - - TT_MP4_LATM_MCP1 = 6, /**< Audio Mux Elements with muxConfigPresent = 1 */ - TT_MP4_LATM_MCP0 = 7, /**< Audio Mux Elements with muxConfigPresent = 0, out of band StreamMuxConfig */ - - TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ - - TT_DRM = 12, /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ - TT_DABPLUS = 13, /**< Digital Audio Broadcastong (DAB+) superframes bitstream format. */ - - TT_MP1_L1 = 16, /**< MPEG 1 Audio Layer 1 audio bitstream. */ - TT_MP1_L2 = 17, /**< MPEG 1 Audio Layer 2 audio bitstream. */ - TT_MP1_L3 = 18, /**< MPEG 1 Audio Layer 3 audio bitstream. */ - - TT_RSVD50 = 50 /**< */ - -} TRANSPORT_TYPE; - -#define TT_IS_PACKET(x) \ - ( ((x) == TT_MP4_RAW) \ - || ((x) == TT_DRM) \ - || ((x) == TT_MP4_LATM_MCP0) \ - || ((x) == TT_MP4_LATM_MCP1) ) - -/** - * Audio Object Type definitions. - */ -typedef enum -{ - AOT_NONE = -1, - AOT_NULL_OBJECT = 0, - AOT_AAC_MAIN = 1, /**< Main profile */ - AOT_AAC_LC = 2, /**< Low Complexity object */ - AOT_AAC_SSR = 3, - AOT_AAC_LTP = 4, - AOT_SBR = 5, - AOT_AAC_SCAL = 6, - AOT_TWIN_VQ = 7, - AOT_CELP = 8, - AOT_HVXC = 9, - AOT_RSVD_10 = 10, /**< (reserved) */ - AOT_RSVD_11 = 11, /**< (reserved) */ - AOT_TTSI = 12, /**< TTSI Object */ - AOT_MAIN_SYNTH = 13, /**< Main Synthetic object */ - AOT_WAV_TAB_SYNTH = 14, /**< Wavetable Synthesis object */ - AOT_GEN_MIDI = 15, /**< General MIDI object */ - AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */ - AOT_ER_AAC_LC = 17, /**< Error Resilient(ER) AAC Low Complexity */ - AOT_RSVD_18 = 18, /**< (reserved) */ - AOT_ER_AAC_LTP = 19, /**< Error Resilient(ER) AAC LTP object */ - AOT_ER_AAC_SCAL = 20, /**< Error Resilient(ER) AAC Scalable object */ - AOT_ER_TWIN_VQ = 21, /**< Error Resilient(ER) TwinVQ object */ - AOT_ER_BSAC = 22, /**< Error Resilient(ER) BSAC object */ - AOT_ER_AAC_LD = 23, /**< Error Resilient(ER) AAC LowDelay object */ - AOT_ER_CELP = 24, /**< Error Resilient(ER) CELP object */ - AOT_ER_HVXC = 25, /**< Error Resilient(ER) HVXC object */ - AOT_ER_HILN = 26, /**< Error Resilient(ER) HILN object */ - AOT_ER_PARA = 27, /**< Error Resilient(ER) Parametric object */ - AOT_RSVD_28 = 28, /**< might become SSC */ - AOT_PS = 29, /**< PS, Parametric Stereo (includes SBR) */ - AOT_MPEGS = 30, /**< MPEG Surround */ - - AOT_ESCAPE = 31, /**< Signal AOT uses more than 5 bits */ - - AOT_MP3ONMP4_L1 = 32, /**< MPEG-Layer1 in mp4 */ - AOT_MP3ONMP4_L2 = 33, /**< MPEG-Layer2 in mp4 */ - AOT_MP3ONMP4_L3 = 34, /**< MPEG-Layer3 in mp4 */ - AOT_RSVD_35 = 35, /**< might become DST */ - AOT_RSVD_36 = 36, /**< might become ALS */ - AOT_AAC_SLS = 37, /**< AAC + SLS */ - AOT_SLS = 38, /**< SLS */ - AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */ - - AOT_USAC = 42, /**< USAC */ - AOT_SAOC = 43, /**< SAOC */ - AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ - - AOT_DABPLUS_AAC_LC = 135, /**< Virtual AOT for DAB plus AAC-LC */ - AOT_DABPLUS_SBR = 136, /**< Virtual AOT for DAB plus HE-AAC */ - AOT_DABPLUS_PS = 137, /**< Virtual AOT for DAB plus HE-AAC v2 */ - - - /* Pseudo AOTs */ - AOT_DRM_AAC = 143, /**< Virtual AOT for DRM (ER-AAC-SCAL without SBR) */ - AOT_DRM_SBR = 144, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR) */ - AOT_DRM_MPEG_PS = 145 /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ - -} AUDIO_OBJECT_TYPE; - -#define CAN_DO_PS(aot) \ - ((aot) == AOT_AAC_LC \ -|| (aot) == AOT_SBR \ -|| (aot) == AOT_PS \ -|| (aot) == AOT_ER_BSAC \ -|| (aot) == AOT_DRM_AAC) - -#define IS_USAC(aot) \ - ((aot) == AOT_USAC) - -#define IS_LOWDELAY(aot) \ - ((aot) == AOT_ER_AAC_LD \ -|| (aot) == AOT_ER_AAC_ELD) - -/** Channel Mode ( 1-7 equals MPEG channel configurations, others are arbitrary). */ -typedef enum { - MODE_INVALID = -1, - MODE_UNKNOWN = 0, - MODE_1 = 1, /**< C */ - MODE_2 = 2, /**< L+R */ - MODE_1_2 = 3, /**< C, L+R */ - MODE_1_2_1 = 4, /**< C, L+R, Rear */ - MODE_1_2_2 = 5, /**< C, L+R, LS+RS */ - MODE_1_2_2_1 = 6, /**< C, L+R, LS+RS, LFE */ - MODE_1_2_2_2_1 = 7, /**< C, LC+RC, L+R, LS+RS, LFE */ - - - MODE_1_1 = 16, /**< 2 SCEs (dual mono) */ - MODE_1_1_1_1 = 17, /**< 4 SCEs */ - MODE_1_1_1_1_1_1 = 18, /**< 6 SCEs */ - MODE_1_1_1_1_1_1_1_1 = 19, /**< 8 SCEs */ - MODE_1_1_1_1_1_1_1_1_1_1_1_1 = 20, /**< 12 SCEs */ - - MODE_2_2 = 21, /**< 2 CPEs */ - MODE_2_2_2 = 22, /**< 3 CPEs */ - MODE_2_2_2_2 = 23, /**< 4 CPEs */ - MODE_2_2_2_2_2_2 = 24, /**< 6 CPEs */ - - MODE_2_1 = 30, /**< CPE,SCE (ARIB standard B32) */ - - MODE_7_1_REAR_SURROUND = 33, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ - MODE_7_1_FRONT_CENTER = 34 /**< C, LC+RC, L+R, LS+RS, LFE */ - -} CHANNEL_MODE; - -/** - * Speaker description tags. - * Do not change the enumeration values unless it keeps the following segmentation: - * - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe) - * - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom) - */ -typedef enum { - ACT_NONE = 0x00, - ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */ - ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */ - ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */ - ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */ - - ACT_TOP = 0x10, /*!< Top speaker area (for combination with speaker positions) */ - ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */ - ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */ - ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */ - - ACT_BOTTOM = 0x20, /*!< Bottom speaker area (for combination with speaker positions) */ - ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */ - ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */ - ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */ - -} AUDIO_CHANNEL_TYPE; - -typedef enum -{ - SIG_UNKNOWN = -1, - SIG_IMPLICIT = 0, - SIG_EXPLICIT_BW_COMPATIBLE = 1, - SIG_EXPLICIT_HIERARCHICAL = 2 - -} SBR_PS_SIGNALING; - -/** - * Audio Codec flags. - */ -#define AC_ER_VCB11 0x000001 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use virtual codebooks */ -#define AC_ER_RVLC 0x000002 /*!< aacSpectralDataResilienceFlag flag (from ASC): 1 means use huffman codeword reordering */ -#define AC_ER_HCR 0x000004 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use virtual codebooks */ -#define AC_SCALABLE 0x000008 /*!< AAC Scalable*/ -#define AC_ELD 0x000010 /*!< AAC-ELD */ -#define AC_LD 0x000020 /*!< AAC-LD */ -#define AC_ER 0x000040 /*!< ER syntax */ -#define AC_BSAC 0x000080 /*!< BSAC */ -#define AC_USAC 0x000100 /*!< USAC */ -#define AC_USAC_TW 0x000200 /*!< USAC time warped filter bank is active */ -#define AC_USAC_NOISE 0x000400 /*!< USAC noise filling is active */ -#define AC_USAC_HBE 0x000800 /*!< USAC harmonic bandwidth extension is active */ -#define AC_RSVD50 0x001000 /*!< Rsvd50 */ -#define AC_SBR_PRESENT 0x002000 /*!< SBR present flag (from ASC) */ -#define AC_SBRCRC 0x004000 /*!< SBR CRC present flag. Only relevant for AAC-ELD for now. */ -#define AC_PS_PRESENT 0x008000 /*!< PS present flag (from ASC or implicit) */ -#define AC_MPS_PRESENT 0x010000 /*!< MPS present flag (from ASC or implicit) */ -#define AC_DRM 0x020000 /*!< DRM bit stream syntax */ -#define AC_INDEP 0x040000 /*!< Independency flag */ -#define AC_MPS_RES 0x080000 /*!< MPS residual individual channel data. */ -#define AC_DAB 0x800000 /*!< DAB bit stream syntax */ -#define AC_LD_MPS 0x01000000 /*!< Low Delay MPS. */ - - -/* CODER_CONFIG::flags */ -#define CC_MPEG_ID 0x00100000 -#define CC_IS_BASELAYER 0x00200000 -#define CC_PROTECTION 0x00400000 -#define CC_SBR 0x00800000 -#define CC_SBRCRC 0x00010000 -#define CC_RVLC 0x01000000 -#define CC_VCB11 0x02000000 -#define CC_HCR 0x04000000 -#define CC_PSEUDO_SURROUND 0x08000000 -#define CC_USAC_NOISE 0x10000000 -#define CC_USAC_TW 0x20000000 -#define CC_USAC_HBE 0x40000000 - -/** Generic audio coder configuration structure. */ -typedef struct { - AUDIO_OBJECT_TYPE aot; /**< Audio Object Type (AOT). */ - AUDIO_OBJECT_TYPE extAOT; /**< Extension Audio Object Type (SBR). */ - CHANNEL_MODE channelMode; /**< Channel mode. */ - INT samplingRate; /**< Sampling rate. */ - INT extSamplingRate; /**< Extended samplerate (SBR). */ - INT bitRate; /**< Average bitrate. */ - int samplesPerFrame; /**< Number of PCM samples per codec frame and audio channel. */ - int noChannels; /**< Number of audio channels. */ - int bitsFrame; - int nSubFrames; /**< Amount of encoder subframes. 1 means no subframing. */ - int BSACnumOfSubFrame; /**< The number of the sub-frames which are grouped and transmitted in a super-frame (BSAC). */ - int BSAClayerLength; /**< The average length of the large-step layers in bytes (BSAC). */ - UINT flags; /**< flags */ - UCHAR matrixMixdownA; /**< Matrix mixdown index to put into PCE. Default value 0 means no mixdown coefficient, - valid values are 1-4 which correspond to matrix_mixdown_idx 0-3. */ - UCHAR headerPeriod; /**< Frame period for sending in band configuration buffers in the transport layer. */ - - UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */ - UCHAR sbrMode; /**< USAC SBR mode */ - SBR_PS_SIGNALING sbrSignaling;/**< 0: implicit signaling, 1: backwards compatible explicit signaling, 2: hierarcical explicit signaling */ - - UCHAR sbrPresent; - UCHAR psPresent; -} CODER_CONFIG; - -/** MP4 Element IDs. */ -typedef enum -{ - ID_NONE = -1, /**< Invalid Element helper ID. */ - ID_SCE = 0, /**< Single Channel Element. */ - ID_CPE = 1, /**< Channel Pair Element. */ - ID_CCE = 2, /**< Coupling Channel Element. */ - ID_LFE = 3, /**< LFE Channel Element. */ - ID_DSE = 4, /**< Currently one Data Stream Element for ancillary data is supported. */ - ID_PCE = 5, /**< Program Config Element. */ - ID_FIL = 6, /**< Fill Element. */ - ID_END = 7, /**< Arnie (End Element = Terminator). */ - ID_EXT = 8, /**< Extension Payload (ER only). */ - ID_SCAL = 9, /**< AAC scalable element (ER only). */ - ID_LAST -} MP4_ELEMENT_ID; - -#define IS_CHANNEL_ELEMENT(elementId) \ - ((elementId) == ID_SCE \ -|| (elementId) == ID_CPE \ -|| (elementId) == ID_LFE) - -#define EXT_ID_BITS 4 /**< Size in bits of extension payload type tags. */ - -/** Extension payload types. */ -typedef enum { - EXT_FIL = 0x00, - EXT_FILL_DATA = 0x01, - EXT_DATA_ELEMENT = 0x02, - EXT_DATA_LENGTH = 0x03, - EXT_LDSAC_DATA = 0x09, - EXT_SAOC_DATA = 0x0a, - EXT_DYNAMIC_RANGE = 0x0b, - EXT_SAC_DATA = 0x0c, - EXT_SBR_DATA = 0x0d, - EXT_SBR_DATA_CRC = 0x0e -} EXT_PAYLOAD_TYPE; - - -/** - * Proprietary raw packet file configuration data type identifier. - */ -typedef enum -{ - TC_NOTHING = 0, /* No configuration available -> in-band configuration. */ - TC_RAW_ASC, /* Configuration data field is a raw AudioSpecificConfig. */ - TC_RAW_SMC, /* Configuration data field is a raw StreamMuxConfig. */ - TC_RAW_SDC /* Configuration data field is a raw Drm SDC. */ - -} TP_CONFIG_TYPE; - -/* - * ############################################################################################## - * Library identification and error handling - * ############################################################################################## - */ -/* \cond */ -#define MODULE_ID_MASK (0x000000ff) -#define MODULE_ID_SHIFT (24) - -typedef enum { - FDK_NONE = 0, - FDK_TOOLS = 1, - FDK_SYSLIB = 2, - FDK_AACDEC = 3, - FDK_AACENC = 4, - FDK_SBRDEC = 5, - FDK_SBRENC = 6, - FDK_TPDEC = 7, - FDK_TPENC = 8, - FDK_MPSDEC = 9, - FDK_MPEGFILEREAD = 10, - FDK_MPEGFILEWRITE = 11, - FDK_MP2DEC = 12, - FDK_DABDEC = 13, - FDK_DABPARSE = 14, - FDK_DRMDEC = 15, - FDK_DRMPARSE = 16, - FDK_AACLDENC = 17, - FDK_MP2ENC = 18, - FDK_MP3ENC = 19, - FDK_MP3DEC = 20, - FDK_MP3HEADPHONE = 21, - FDK_MP3SDEC = 22, - FDK_MP3SENC = 23, - FDK_EAEC = 24, - FDK_DABENC = 25, - FDK_DMBDEC = 26, - FDK_FDREVERB = 27, - FDK_DRMENC = 28, - FDK_METADATATRANSCODER = 29, - FDK_AC3DEC = 30, - FDK_PCMDMX = 31, - - FDK_MODULE_LAST - -} FDK_MODULE_ID; - -/* AAC capability flags */ -#define CAPF_AAC_LC 0x00000001 /**< Support flag for AAC Low Complexity. */ -#define CAPF_ER_AAC_LD 0x00000002 /**< Support flag for AAC Low Delay with Error Resilience tools. */ -#define CAPF_ER_AAC_SCAL 0x00000004 /**< Support flag for AAC Scalable. */ -#define CAPF_ER_AAC_LC 0x00000008 /**< Support flag for AAC Low Complexity with Error Resilience tools. */ -#define CAPF_AAC_480 0x00000010 /**< Support flag for AAC with 480 framelength. */ -#define CAPF_AAC_512 0x00000020 /**< Support flag for AAC with 512 framelength. */ -#define CAPF_AAC_960 0x00000040 /**< Support flag for AAC with 960 framelength. */ -#define CAPF_AAC_1024 0x00000080 /**< Support flag for AAC with 1024 framelength. */ -#define CAPF_AAC_HCR 0x00000100 /**< Support flag for AAC with Huffman Codeword Reordering. */ -#define CAPF_AAC_VCB11 0x00000200 /**< Support flag for AAC Virtual Codebook 11. */ -#define CAPF_AAC_RVLC 0x00000400 /**< Support flag for AAC Reversible Variable Length Coding. */ -#define CAPF_AAC_MPEG4 0x00000800 /**< Support flag for MPEG file format. */ -#define CAPF_AAC_DRC 0x00001000 /**< Support flag for AAC Dynamic Range Control. */ -#define CAPF_AAC_CONCEALMENT 0x00002000 /**< Support flag for AAC concealment. */ -#define CAPF_AAC_DRM_BSFORMAT 0x00004000 /**< Support flag for AAC DRM bistream format. */ -#define CAPF_ER_AAC_ELD 0x00008000 /**< Support flag for AAC Enhanced Low Delay with Error Resilience tools. */ -#define CAPF_ER_AAC_BSAC 0x00010000 /**< Support flag for AAC BSAC. */ -#define CAPF_AAC_SUPERFRAMING 0x00020000 /**< Support flag for AAC Superframing. */ - -/* Transport capability flags */ -#define CAPF_ADTS 0x00000001 /**< Support flag for ADTS transport format. */ -#define CAPF_ADIF 0x00000002 /**< Support flag for ADIF transport format. */ -#define CAPF_LATM 0x00000004 /**< Support flag for LATM transport format. */ -#define CAPF_LOAS 0x00000008 /**< Support flag for LOAS transport format. */ -#define CAPF_RAWPACKETS 0x00000010 /**< Support flag for RAW PACKETS transport format. */ -#define CAPF_DRM 0x00000020 /**< Support flag for DRM/DRM+ transport format. */ -#define CAPF_RSVD50 0x00000040 /**< Support flag for RSVD50 transport format */ - -/* SBR capability flags */ -#define CAPF_SBR_LP 0x00000001 /**< Support flag for SBR Low Power mode. */ -#define CAPF_SBR_HQ 0x00000002 /**< Support flag for SBR High Quality mode. */ -#define CAPF_SBR_DRM_BS 0x00000004 /**< Support flag for */ -#define CAPF_SBR_CONCEALMENT 0x00000008 /**< Support flag for SBR concealment. */ -#define CAPF_SBR_DRC 0x00000010 /**< Support flag for SBR Dynamic Range Control. */ -#define CAPF_SBR_PS_MPEG 0x00000020 /**< Support flag for MPEG Parametric Stereo. */ -#define CAPF_SBR_PS_DRM 0x00000040 /**< Support flag for DRM Parametric Stereo. */ - -/* MP2 encoder capability flags */ -#define CAPF_MP2ENC_SS 0x00000001 /**< Support flag for Seamless Switching. */ -#define CAPF_MP2ENC_DAB 0x00000002 /**< Support flag for Layer2 DAB. */ - -/* DAB capability flags */ -#define CAPF_DAB_MP2 0x00000001 /**< Support flag for Layer2 DAB. */ -#define CAPF_DAB_AAC 0x00000002 /**< Support flag for DAB+ (HE-AAC v2). */ -#define CAPF_DAB_PAD 0x00000004 /**< Support flag for PAD extraction. */ -#define CAPF_DAB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ -#define CAPF_DAB_SURROUND 0x00000010 /**< Support flag for DAB Surround (MPS). */ - -/* DMB capability flags */ -#define CAPF_DMB_BSAC 0x00000001 /**< Support flag for ER AAC BSAC. */ -#define CAPF_DMB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ -#define CAPF_DMB_SURROUND 0x00000010 /**< Support flag for DMB Surround (MPS). */ - -/* PCM up/downmmix capability flags */ -#define CAPF_DMX_BLIND 0x00000001 /**< Support flag for blind downmixing. */ -#define CAPF_DMX_PCE 0x00000002 /**< Support flag for guided downmix with data from MPEG-2/4 Program Config Elements (PCE). */ -#define CAPF_DMX_ARIB 0x00000004 /**< Support flag for PCE guided downmix with slightly different equations and levels to fulfill ARIB standard. */ -#define CAPF_DMX_DVB 0x00000008 /**< Support flag for guided downmix with data from DVB ancillary data fields. */ -#define CAPF_DMX_CH_EXP 0x00000010 /**< Support flag for simple upmixing by dublicating channels or adding zero channels. */ -/* \endcond */ - - -/* - * ############################################################################################## - * Library versioning - * ############################################################################################## - */ - -/** - * Convert each member of version numbers to one single numeric version representation. - * \param lev0 1st level of version number. - * \param lev1 2nd level of version number. - * \param lev2 3rd level of version number. - */ -#define LIB_VERSION(lev0, lev1, lev2) ((lev0<<24 & 0xff000000) | \ - (lev1<<16 & 0x00ff0000) | \ - (lev2<<8 & 0x0000ff00)) - -/** - * Build text string of version. - */ -#define LIB_VERSION_STRING(info) FDKsprintf((info)->versionStr, "%d.%d.%d", (((info)->version >> 24) & 0xff), (((info)->version >> 16) & 0xff), (((info)->version >> 8 ) & 0xff)) - -/** - * Library information. - */ -typedef struct LIB_INFO -{ - const char* title; - const char* build_date; - const char* build_time; - FDK_MODULE_ID module_id; - INT version; - UINT flags; - char versionStr[32]; -} LIB_INFO; - -/** Initialize library info. */ -static inline void FDKinitLibInfo( LIB_INFO* info ) -{ - int i; - - for (i = 0; i < FDK_MODULE_LAST; i++) { - info[i].module_id = FDK_NONE; - } -} - -/** Aquire supported features of library. */ -static inline UINT FDKlibInfo_getCapabilities( const LIB_INFO* info, FDK_MODULE_ID module_id ) -{ - int i; - - for (i=0; i Date: Tue, 22 Aug 2017 10:31:51 +0200 Subject: [PATCH 025/135] GUI: merge DAB and DAB+ transmitter/receiver flowgraph in one class respectively --- python/GUI/main.py | 14 +-- python/GUI/usrp_dab_rx.py | 67 +++++++---- python/GUI/usrp_dab_tx.py | 57 +++++++--- python/GUI/usrp_dabplus_rx.py | 206 ---------------------------------- python/GUI/usrp_dabplus_tx.py | 152 ------------------------- 5 files changed, 94 insertions(+), 402 deletions(-) delete mode 100644 python/GUI/usrp_dabplus_rx.py delete mode 100644 python/GUI/usrp_dabplus_tx.py diff --git a/python/GUI/main.py b/python/GUI/main.py index e57c8cd1..a10395e4 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -5,9 +5,7 @@ import sys import time import user_frontend -import usrp_dabplus_rx import usrp_dab_rx -import usrp_dabplus_tx import usrp_dab_tx import math import json @@ -230,7 +228,7 @@ def set_file_path(self): def init_receiver(self): self.statusBar.showMessage("initializing receiver ...") - # stop any processes that access to an instance of usrp_dabplus_rx + # stop any processes that access to an instance of usrp_dab_rx self.snr_timer.stop() self.firecode_timer.stop() # check if file path is selected in case that file is the selected source @@ -239,7 +237,7 @@ def init_receiver(self): else: self.label_path.setStyleSheet('color: black') # set up and start flowgraph - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, self.src_is_USRP, self.file_path, self.recorder) self.my_receiver.start() # status bar @@ -336,7 +334,7 @@ def selected_subch(self): def snr_update(self): print "update snr" - # display snr in progress bar if an instance of usrp_dabplus_rx is existing + # display snr in progress bar if an instance of usrp_dab_rx is existing if hasattr(self, 'my_receiver'): SNR = self.my_receiver.get_snr() if SNR > 10: @@ -375,7 +373,7 @@ def play_audio(self): self.snr_timer.stop() self.firecode_timer.stop() self.my_receiver.stop() - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, @@ -426,7 +424,7 @@ def record_audio(self): self.btn_stop.setEnabled(True) self.recorder = True # start flowgraph - self.my_receiver = usrp_dabplus_rx.usrp_dabplus_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, self.src_is_USRP, self.file_path, self.recorder) @@ -707,7 +705,7 @@ def t_init_transmitter(self): if arguments_incomplete is False: # init transmitter - self.my_transmitter = usrp_dabplus_tx.usrp_dabplus_tx(self.t_spin_dab_mode.value(), + self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), self.t_spinbox_frequency.value(), self.t_spin_num_subch.value(), str(self.t_edit_ensemble_label.text()), diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index d98a35ef..c900fed3 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -20,7 +20,7 @@ # """ -receive DAB with USRP (for DAB+ reception see usrp_dabplus_rx.py) +receive DAB+ with USRP """ from gnuradio import gr, uhd, blocks @@ -32,16 +32,18 @@ class usrp_dab_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use_usrp, src_path, record_audio = False, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, record_audio = False, sink_path = "None"): gr.top_block.__init__(self) self.dab_mode = dab_mode self.verbose = False self.sample_rate = 2e6 + self.dabplus = dabplus self.use_usrp = use_usrp self.src_path = src_path self.record_audio = record_audio self.sink_path = sink_path + gr.log.set_level("warn") ######################## # source @@ -52,7 +54,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use self.src.set_antenna("TX/RX") else: print "using file source" - self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, True) + self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, False) # set paramters to default mode self.softbits = True @@ -96,32 +98,46 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, use ######################## # MSC decoder and audio sink ######################## - self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) - self.mp2 = dab.mp2_decode_bs_make(bit_rate / 8) - self.s2f_left = blocks.short_to_float_make(1, 32767) - self.s2f_right = blocks.short_to_float_make(1, 32767) - self.gain_left = blocks.multiply_const_ff(1, 1) - self.gain_right = blocks.multiply_const_ff(1, 1) - self.audio = audio.sink_make(32000) + if self.dabplus: + self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) + else: + self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) + self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) + self.mp2_dec = dab.mp2_decode_bs_make(bit_rate / 8) + self.s2f_left = blocks.short_to_float_make(1, 32767) + self.s2f_right = blocks.short_to_float_make(1, 32767) + self.gain_left = blocks.multiply_const_ff(1, 1) + self.gain_right = blocks.multiply_const_ff(1, 1) + self.audio = audio.sink_make(audio_bit_rate) ######################## # Connections ######################## self.connect(self.src, self.fft_plot) self.connect(self.src, self.waterfall_plot) - #self.connect(self.src, self.time_plot) self.connect(self.src, self.demod, (self.fic_dec, 0)) self.connect((self.demod, 1), (self.fic_dec, 1)) - self.connect((self.demod, 0), (self.msc_dec, 0)) - self.connect((self.demod, 1), (self.msc_dec, 1)) - self.connect(self.msc_dec, (self.mp2, 0), self.s2f_left, self.gain_left, (self.audio, 0)) - self.connect((self.mp2, 1), self.s2f_right, self.gain_right, (self.audio, 1)) + if self.dabplus: + self.connect((self.demod, 0), (self.dabplus, 0)) + self.connect((self.demod, 1), (self.dabplus, 1)) + else: + self.connect((self.demod, 0), (self.msc_dec, 0), self.unpack, self.mp2_dec) + self.connect((self.demod, 1), (self.msc_dec, 1)) + self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) + self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) + # connect audio to sound card + if self.dabplus: + self.connect((self.dabplus, 0), (self.audio, 0)) + self.connect((self.dabplus, 1), (self.audio, 1)) + else: + self.connect(self.gain_left, (self.audio, 0)) + self.connect(self.gain_right, (self.audio, 1)) # connect file sink if recording is selected if self.record_audio: self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) - self.connect(self.gain_left, (self.sink, 0)) - self.connect(self.gain_right, (self.sink, 1)) + self.connect((self.dabplus, 0), (self.sink, 0)) + self.connect((self.dabplus, 1), (self.sink, 1)) # tune USRP frequency if self.use_usrp: @@ -151,16 +167,29 @@ def get_programme_type(self): return self.fic_dec.get_programme_type() def get_sample_rate(self): - return self.mp2.get_sample_rate() + return self.dabplus.get_sample_rate() def get_snr(self): return self.snr_measurement.snr() + def get_firecode_passed(self): + return self.dabplus.get_firecode_passed() + + def get_corrected_errors(self): + return self.dabplus.get_corrected_errors() + + def get_crc_passed(self): + return self.fic_dec.get_crc_passed() + ######################## # setter methods ######################## def set_volume(self, volume): - self.dabplus.set_volume(volume) + if self.dabplus: + self.dabplus.set_volume(volume) + else: + self.gain_left.set_k(volume) + self.gain_right.set_k(volume) def set_freq(self, freq): if self.src.set_center_freq(freq): diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 38a7f89b..1bf39c23 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -20,7 +20,7 @@ # """ -receive DAB with USRP (for DAB+ transmission see usrp_dabplus_tx.py) +transmit DAB+ with USRP """ from gnuradio import gr, uhd, blocks @@ -29,8 +29,8 @@ import numpy as np -class usrp_dabplus_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, audio_sample_rate, src_paths, selected_audio, use_usrp, sink_path = "dab_iq_generated.dat"): +class usrp_dab_tx(gr.top_block): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -44,37 +44,50 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.language = language self.protections = protections self.data_rates_n = data_rates_n - self.subch_sizes = np.multiply(self.data_rates_n, 6) self.src_paths = src_paths self.use_usrp = use_usrp + self.dabplus_types = dabplus_types self.sink_path = sink_path self.selected_audio = selected_audio self.volume = 80 + sizes = {0: 12, 1: 8, 2: 6, 3: 4} + self.subch_sizes = [None] * len(self.data_rates_n) + for i in range(0, len(self.data_rates_n)): + self.subch_sizes[i] = self.data_rates_n[i] * sizes[protections[i]] ######################## # FIC ######################## # source - self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n) + self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n, self.dabplus_types) # encoder self.fic_enc = dab.fic_encode(self.dp) ######################## # MSC ######################## + self.recorder = audio.source_make(32000) self.msc_sources = [None] * self.num_subch self.f2s_left_converters = [None] * self.num_subch self.f2s_right_converters = [None] * self.num_subch + self.mp4_encoders = [None] * self.num_subch self.mp2_encoders = [None] * self.num_subch + self.rs_encoders = [None] * self.num_subch self.msc_encoders = [None] * self.num_subch for i in range(0, self.num_subch): - # source - self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) + if not self.src_paths[i] is "mic": + # source + self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], False) # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) - # mp2 encoder - self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n, 2, audio_sample_rate) + if self.dabplus_types[i] is 1: + # mp4 encoder and Reed-Solomon encoder + self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) + self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) + else: + # mp2 encoder + self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n[i], 2, 48000) # encoder self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) @@ -82,7 +95,6 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label # MUX ######################## self.mux = dab.dab_transmission_frame_mux_bb_make(self.dab_mode, self.num_subch, self.subch_sizes) - #self.mux = dab.dab_transmission_frame_mux_bb_make(1, 1, [84, 84]) self.trigsrc = blocks.vector_source_b([1] + [0] * (self.dp.symbols_per_frame-2), True) ######################## @@ -102,25 +114,36 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label else: self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) # audio sink - self.audio = audio.sink_make(audio_sample_rate) + self.audio = audio.sink_make(32000) + self.gain_left = blocks.multiply_const_ff_make(1, 1) self.gain_right = blocks.multiply_const_ff_make(1, 1) + self.s2f_left = blocks.short_to_float_make(1, 32767) + self.s2f_right = blocks.short_to_float_make(1, 32767) ######################## # Connections ######################## self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) for i in range(0, self.num_subch): - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) + if self.dabplus_types[i] is 1: + if self.src_paths[i] is "mic": + self.connect((self.recorder, 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i + 1)) + self.connect((self.recorder, 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i + 1)) + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) - self.connect(self.mod, self.sink) - self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) - self.connect((self.msc_sources[self.selected_audio - 1], 1), self.gain_right, (self.audio, 1)) + self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) + #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) + #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) def transmit(self): - tx = usrp_dabplus_tx() + tx = usrp_dab_tx() tx.run() def set_volume(self, volume): diff --git a/python/GUI/usrp_dabplus_rx.py b/python/GUI/usrp_dabplus_rx.py deleted file mode 100644 index c6229444..00000000 --- a/python/GUI/usrp_dabplus_rx.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -receive DAB+ with USRP -""" - -from gnuradio import gr, uhd, blocks -from gnuradio import audio, digital -from gnuradio import qtgui -from gnuradio import fft -import dab -import time, math - - -class usrp_dabplus_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, record_audio = False, sink_path = "None"): - gr.top_block.__init__(self) - - self.dab_mode = dab_mode - self.verbose = False - self.sample_rate = 2e6 - self.dabplus = dabplus - self.use_usrp = use_usrp - self.src_path = src_path - self.record_audio = record_audio - self.sink_path = sink_path - gr.log.set_level("warn") - - ######################## - # source - ######################## - if self.use_usrp: - self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) - self.src.set_samp_rate(self.sample_rate) - self.src.set_antenna("TX/RX") - else: - print "using file source" - self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, False) - - # set paramters to default mode - self.softbits = True - self.filter_input = True - self.autocorrect_sample_rate = False - self.resample_fixed = 1 - self.correct_ffe = True - self.equalize_magnitude = True - self.frequency = frequency - self.dab_params = dab.parameters.dab_parameters(self.dab_mode, self.sample_rate, self.verbose) - self.rx_params = dab.parameters.receiver_parameters(self.dab_mode, self.softbits, - self.filter_input, - self.autocorrect_sample_rate, - self.resample_fixed, - self.verbose, self.correct_ffe, - self.equalize_magnitude) - ######################## - # FFT and waterfall plot - ######################## - self.fft_plot = qtgui.freq_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "FFT") - self.waterfall_plot = qtgui.waterfall_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "Waterfall") - #self.time_plot = qtgui.time_sink_c_make(1024, 2e6, "Time") - - ######################## - # OFDM demod - ######################## - self.demod = dab.ofdm_demod(self.dab_params, self.rx_params, self.verbose) - - ######################## - # SNR measurement - ######################## - self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dab_params.num_carriers) - self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) - self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) - - ######################## - # FIC decoder - ######################## - self.fic_dec = dab.fic_decode(self.dab_params) - - ######################## - # MSC decoder and audio sink - ######################## - if self.dabplus: - self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) - else: - self.msc_dec = dab.msc_decode(self.dab_params, address, size, protection) - self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) - self.mp2_dec = dab.mp2_decode_bs_make(bit_rate / 8) - self.s2f_left = blocks.short_to_float_make(1, 32767) - self.s2f_right = blocks.short_to_float_make(1, 32767) - self.gain_left = blocks.multiply_const_ff(1, 1) - self.gain_right = blocks.multiply_const_ff(1, 1) - self.audio = audio.sink_make(audio_bit_rate) - - ######################## - # Connections - ######################## - self.connect(self.src, self.fft_plot) - self.connect(self.src, self.waterfall_plot) - self.connect(self.src, self.demod, (self.fic_dec, 0)) - self.connect((self.demod, 1), (self.fic_dec, 1)) - if self.dabplus: - self.connect((self.demod, 0), (self.dabplus, 0)) - self.connect((self.demod, 1), (self.dabplus, 1)) - else: - self.connect((self.demod, 0), (self.msc_dec, 0), self.unpack, self.mp2_dec) - self.connect((self.demod, 1), (self.msc_dec, 1)) - self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) - self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) - self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) - # connect audio to sound card - if self.dabplus: - self.connect((self.dabplus, 0), (self.audio, 0)) - self.connect((self.dabplus, 1), (self.audio, 1)) - else: - self.connect(self.gain_left, (self.audio, 0)) - self.connect(self.gain_right, (self.audio, 1)) - # connect file sink if recording is selected - if self.record_audio: - self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) - self.connect((self.dabplus, 0), (self.sink, 0)) - self.connect((self.dabplus, 1), (self.sink, 1)) - - # tune USRP frequency - if self.use_usrp: - self.set_freq(self.frequency) - # set gain - # if no gain was specified, use the mid-point in dB - g = self.src.get_gain_range() - self.rx_gain = float(g.start() + g.stop()) / 2 - self.src.set_gain(self.rx_gain) - -######################## -# getter methods -######################## - def get_ensemble_info(self): - return self.fic_dec.get_ensemble_info() - - def get_service_info(self): - return self.fic_dec.get_service_info() - - def get_service_labels(self): - return self.fic_dec.get_service_labels() - - def get_subch_info(self): - return self.fic_dec.get_subch_info() - - def get_programme_type(self): - return self.fic_dec.get_programme_type() - - def get_sample_rate(self): - return self.dabplus.get_sample_rate() - - def get_snr(self): - return self.snr_measurement.snr() - - def get_firecode_passed(self): - return self.dabplus.get_firecode_passed() - - def get_corrected_errors(self): - return self.dabplus.get_corrected_errors() - - def get_crc_passed(self): - return self.fic_dec.get_crc_passed() - -######################## -# setter methods -######################## - def set_volume(self, volume): - if self.dabplus: - self.dabplus.set_volume(volume) - else: - self.gain_left.set_k(volume) - self.gain_right.set_k(volume) - - def set_freq(self, freq): - if self.src.set_center_freq(freq): - if self.verbose: - print "--> retuned to " + str(freq) + " Hz" - return True - else: - print "-> error - cannot tune to " + str(freq) + " Hz" - return False - - def receive(self): - rx = usrp_dabplus_rx() - rx.run() - diff --git a/python/GUI/usrp_dabplus_tx.py b/python/GUI/usrp_dabplus_tx.py deleted file mode 100644 index 8c7fa6fd..00000000 --- a/python/GUI/usrp_dabplus_tx.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -""" -transmit DAB+ with USRP -""" - -from gnuradio import gr, uhd, blocks -from gnuradio import audio -import dab -import numpy as np - - -class usrp_dabplus_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): - gr.top_block.__init__(self) - - self.dab_mode = dab_mode - self.frequency = frequency - interp = 64 - self.sample_rate = 128e6 / interp - self.dp = dab.parameters.dab_parameters(self.dab_mode, 2000000, False) - self.num_subch = num_subch - self.ensemble_label = ensemble_label - self.service_label = service_label - self.language = language - self.protections = protections - self.data_rates_n = data_rates_n - self.src_paths = src_paths - self.use_usrp = use_usrp - self.dabplus_types = dabplus_types - self.sink_path = sink_path - self.selected_audio = selected_audio - self.volume = 80 - sizes = {0: 12, 1: 8, 2: 6, 3: 4} - self.subch_sizes = [None] * len(self.data_rates_n) - for i in range(0, len(self.data_rates_n)): - self.subch_sizes[i] = self.data_rates_n[i] * sizes[protections[i]] - - ######################## - # FIC - ######################## - # source - self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n, self.dabplus_types) - # encoder - self.fic_enc = dab.fic_encode(self.dp) - - ######################## - # MSC - ######################## - self.recorder = audio.source_make(32000) - self.msc_sources = [None] * self.num_subch - self.f2s_left_converters = [None] * self.num_subch - self.f2s_right_converters = [None] * self.num_subch - self.mp4_encoders = [None] * self.num_subch - self.mp2_encoders = [None] * self.num_subch - self.rs_encoders = [None] * self.num_subch - self.msc_encoders = [None] * self.num_subch - for i in range(0, self.num_subch): - if not self.src_paths[i] is "mic": - # source - self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], False) - # float to short - self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) - self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) - if self.dabplus_types[i] is 1: - # mp4 encoder and Reed-Solomon encoder - self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) - self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) - else: - # mp2 encoder - self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n[i], 2, 48000) - # encoder - self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) - - ######################## - # MUX - ######################## - self.mux = dab.dab_transmission_frame_mux_bb_make(self.dab_mode, self.num_subch, self.subch_sizes) - self.trigsrc = blocks.vector_source_b([1] + [0] * (self.dp.symbols_per_frame-2), True) - - ######################## - # Modulator - ######################## - self.s2v_mod = blocks.stream_to_vector(gr.sizeof_char, self.dp.num_carriers/4) - self.mod = dab.ofdm_mod(self.dp) - - ######################## - # Sink - ######################## - if self.use_usrp: - self.sink = uhd.usrp_sink("", uhd.io_type.COMPLEX_FLOAT32, 1) - self.sink.set_samp_rate(self.sample_rate) - self.sink.set_antenna("TX/RX") - self.sink.set_center_freq(self.frequency) - else: - self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) - # audio sink - self.audio = audio.sink_make(32000) - - self.gain_left = blocks.multiply_const_ff_make(1, 1) - self.gain_right = blocks.multiply_const_ff_make(1, 1) - self.s2f_left = blocks.short_to_float_make(1, 32767) - self.s2f_right = blocks.short_to_float_make(1, 32767) - - ######################## - # Connections - ######################## - self.connect(self.fic_src, self.fic_enc, (self.mux, 0)) - for i in range(0, self.num_subch): - if self.dabplus_types[i] is 1: - if self.src_paths[i] is "mic": - self.connect((self.recorder, 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i + 1)) - self.connect((self.recorder, 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) - else: - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) - else: - self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i + 1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) - self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) - self.connect(self.trigsrc, (self.mod, 1)) - self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) - #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) - #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) - - def transmit(self): - tx = usrp_dabplus_tx() - tx.run() - - def set_volume(self, volume): - self.gain_left.set_k(volume) - self.gain_right.set_k(volume) - From 353d02f4262882bf24e43529ad095a657cf1027a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 22 Aug 2017 22:54:12 +0200 Subject: [PATCH 026/135] GUI: replace KDE LED with bitmap fixes #22 --- python/GUI/led_green.png | Bin 0 -> 572 bytes python/GUI/led_orange.png | Bin 0 -> 572 bytes python/GUI/led_red.png | Bin 0 -> 565 bytes python/GUI/main.py | 23 ++++++++++++++--------- python/GUI/user_frontend.py | 14 ++++++-------- python/GUI/user_frontend.ui | 26 ++++++++------------------ python/GUI/usrp_dab_rx.py | 2 +- 7 files changed, 29 insertions(+), 36 deletions(-) create mode 100644 python/GUI/led_green.png create mode 100644 python/GUI/led_orange.png create mode 100644 python/GUI/led_red.png diff --git a/python/GUI/led_green.png b/python/GUI/led_green.png new file mode 100644 index 0000000000000000000000000000000000000000..baa12e62e574e420c5fd552eb145d0877627d404 GIT binary patch literal 572 zcmV-C0>k}@P)cCL36o|w^i&Bu1K!mXa_O-8lI|Q}T z8GmOw$4KsD0Lbfn_&EG6f8D7VXp3h(@AbeRc&4`i#)6LI=rB1f>#{V;Wd?KNlZiH_vxAU?=N{&V?c-gtOT)l7B(azG27(Ncmy8N+nY}wX2>wWs0YyttnocXDJdi>(} z-T3WUc4m%>kuue!F|n~jLKjyeCDO$W32p3gIH}C)O8ya2%goO)(CCb8#_WO%V8$#X z(`aqz%+K>eiognd%U7s^V#?IVPe_26c*?Y(P$=K>0xJ;9_OewAh04e#Oe(5~2uMk9 zxy{IwR0Uw(HeiLJ|}I zOF|OV!EV0W5MkHu7|DG+*YmNS=2pJv?;VLFjRs82Ew%ME`{GpYOJk*BG@gdd$rCg6 zEFX(&aSe1;mx{c~nswyi{r>=<(aKV`a9rC1WSN($5S1`67T_-*m-(!qI+-N^0000< KMNUMnLSTYU{152> literal 0 HcmV?d00001 diff --git a/python/GUI/led_orange.png b/python/GUI/led_orange.png new file mode 100644 index 0000000000000000000000000000000000000000..0cedcd7c78be1f9568ce2555bd766d4dd2ea5458 GIT binary patch literal 572 zcmV-C0>k}@P)q0RR8#(T`!!d1K47o%lPd2j`70P2haV%hLfKBJ$?7uRr8y_ zKFIbJZtZYw1dxoG9Oy-MwE5UZo!-+IvKSv)qx(nuQo5|&W@C#x_W^L=aIMOvNn0i%=Oro-#`?6}1sT=mst6cL!EV8behuo6^)|9RM|Feo9r? z#@NBgi?2$rH#ATVw}Rtu07m1U0MrIupcdu&wuo0{e<);cU4-pocdzk7mKn>GMam*& znX=3pzomBf+$i>XLnoW1R^>KLT%*GGujKcSU;z;3?nCwDW$gw|cg+dgm&c-&DCQ!F zTnBmn2QaJawWTSGChFjY{~G|XR#@XnUj`vyN~KNJI1$`n9ip+%ucbs(y-L;Y+&`*i>b>2CL& z>0T>+OaP!!D!;fae*LVH1aMYX-1U#)rw!rz&w%xema|!Ma$>4VRF#{iK-uj!QVQ4Y z?(De3;R{;MW`B>5rBeOrw6%P)+HJsO*|HriCKK)Zz1>}RIJA=Z&%@D?on>p^zROOB z$%N4e;O2(uv`W+8+uNqoe!I6P^NUMURsA1l(zaP&XFO(e6Cey(E}ir9{@Gdl<@3MG z3sK(Agx0M%#&L)uJddKFDDXU@2*-)ySk!ejyOm8*1i7*RW5{zB3$CvL77OwmV=Q9= zrOKj^b{L8vKx@j9`J5miO#zaG`JA#uYvKEL7)rPQ&Pa*Y zj7CoHjda!q+M*bby{jvLs^b10c#)r;ij57?>&dl&kb_kbw(_t0jqj7DB*|;ivfoUEJnO@ItJQiL7Nta*i6F2+-rWIu zb+v{j&znvg-+%o8fH9)hj&!B(16rv{myIp4tmpneCY<=L+!7wd00000NkvXXu0mjf Dr5OmO literal 0 HcmV?d00001 diff --git a/python/GUI/main.py b/python/GUI/main.py index a10395e4..b72fcb16 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -311,11 +311,14 @@ def selected_subch(self): self.protection = int(subch_data['protection']) conv_table = [12, 8, 6, 5] self.bit_rate = self.size * 8/conv_table[self.protection] - if self.bit_rate < 100: - self.audio_bit_rate = 48000 - else: - self.audio_bit_rate = 32000 self.dabplus = service_data['DAB+'] + if dabplus: + if self.bit_rate < 100: + self.audio_bit_rate = 48000 + else: + self.audio_bit_rate = 32000 + else: + self.audio_bit_rate = 48000 # display info to selected sub-channel # service info @@ -532,10 +535,12 @@ def dev_mode_open(self): self.waterfall_plot.show() self.constellation.show() self.label_firecode.show() + self.led_msc.setText("") self.led_msc.show() self.label_label_msc.show() self.label_firecode.setText("") self.label_fic.show() + self.led_fic.setText("") self.led_fic.show() self.label_label_fic.show() self.label_fic.setText("") @@ -570,22 +575,22 @@ def update_firecode(self): # write msc status if not self.my_receiver.get_firecode_passed(): self.label_firecode.setText(self.label_firecode.text() + "X ") - self.led_msc.setColor(QtGui.QColor(255, 0, 0)) + self.led_msc.setText("") else: errors = self.my_receiver.get_corrected_errors() if errors < 10: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + " < /font>") - self.led_msc.setColor(QtGui.QColor(0, 255, 0)) + self.led_msc.setText("") else: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + "") - self.led_msc.setColor(QtGui.QColor(0, 255, 128)) + self.led_msc.setText("") # write fic status if self.my_receiver.get_crc_passed(): self.label_fic.setText(self.label_fic.text() + "0 ") - self.led_fic.setColor(QtGui.QColor(0, 255, 0)) + self.led_fic.setText("") else: self.label_fic.setText(self.label_fic.text() + "X ") - self.led_fic.setColor(QtGui.QColor(255, 0, 0)) + self.led_fic.setText("") self.label_fic.setWordWrap(True) self.label_firecode.setWordWrap(True) self.content_count += 1 diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index b96968ef..e87b4147 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -257,9 +257,7 @@ def setupUi(self, MainWindow): self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout_13.addItem(spacerItem4) - self.led_msc = KLed(self.tab_reception) - self.led_msc.setLook(KLed.Sunken) - self.led_msc.setDarkFactor(300) + self.led_msc = QtGui.QLabel(self.tab_reception) self.led_msc.setObjectName(_fromUtf8("led_msc")) self.verticalLayout_13.addWidget(self.led_msc) spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) @@ -291,8 +289,7 @@ def setupUi(self, MainWindow): self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) self.verticalLayout_14.addItem(spacerItem7) - self.led_fic = KLed(self.tab_reception) - self.led_fic.setLook(KLed.Sunken) + self.led_fic = QtGui.QLabel(self.tab_reception) self.led_fic.setObjectName(_fromUtf8("led_fic")) self.verticalLayout_14.addWidget(self.led_fic) spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) @@ -439,7 +436,7 @@ def setupUi(self, MainWindow): self.dev_scroll_area.setWidgetResizable(True) self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) self.dev_scroll_area_content = QtGui.QWidget() - self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 241, 602)) + self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 239, 602)) self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) @@ -1221,7 +1218,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(1) + self.mode_tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1251,8 +1248,10 @@ def retranslateUi(self, MainWindow): self.label_snr.setText(_translate("MainWindow", "reception: ", None)) self.label_7.setText(_translate("MainWindow", "dB", None)) self.label_firecode.setText(_translate("MainWindow", "

Superframes:

", None)) + self.led_msc.setText(_translate("MainWindow", "led", None)) self.label_label_msc.setText(_translate("MainWindow", "MSC", None)) self.label_fic.setText(_translate("MainWindow", "

FIC:

", None)) + self.led_fic.setText(_translate("MainWindow", "led", None)) self.label_label_fic.setText(_translate("MainWindow", "FIC", None)) self.label_service.setText(_translate("MainWindow", "SERVICE", None)) self.label_programme_type.setText(_translate("MainWindow", "programme type\n" @@ -1388,4 +1387,3 @@ def retranslateUi(self, MainWindow): self.label_19.setText(_translate("MainWindow", "Volume", None)) self.mode_tabs.setTabText(self.mode_tabs.indexOf(self.tab_transmission), _translate("MainWindow", "Transmitter", None)) -from PyKDE4.kdeui import KLed diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 7830a0ba..30a8001c 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true
- 1 + 0 @@ -506,12 +506,9 @@
- - - KLed::Sunken - - - 300 + + + led @@ -610,9 +607,9 @@
- - - KLed::Sunken + + + led @@ -954,7 +951,7 @@ 0 0 - 241 + 239 602 @@ -2702,13 +2699,6 @@ - - - KLed - QWidget -
kled.h
-
-
diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index c900fed3..3ac3e25b 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -135,7 +135,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect(self.gain_right, (self.audio, 1)) # connect file sink if recording is selected if self.record_audio: - self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, 32000) + self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, audio_bit_rate) self.connect((self.dabplus, 0), (self.sink, 0)) self.connect((self.dabplus, 1), (self.sink, 1)) From 5ce9d99b69b411873eadedc10f164b057f1b049f Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 23 Aug 2017 15:06:32 +0200 Subject: [PATCH 027/135] fib_source: fix qa test --- python/qa_fib_source_b.py | 4 ++-- python/qa_fic_encode.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/qa_fib_source_b.py b/python/qa_fib_source_b.py index 4124314d..22ac34a2 100755 --- a/python/qa_fib_source_b.py +++ b/python/qa_fib_source_b.py @@ -34,7 +34,7 @@ def tearDown (self): # manual check if transmitted data is interpreted properly # trivial fib_source with only one sub-channel def test_001_t(self): - src = dab.fib_source_b_make(1,1,'Galaxy_News', 'Wasteland_Radio', 'Country_Mix', 0x09, [0], [8]) + src = dab.fib_source_b_make(1,1,'Galaxy_News', 'Wasteland_Radio', 'Country_Mix', 0x09, [0], [8], [1]) fib_unpacked_to_packed = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) s2v = blocks.stream_to_vector(gr.sizeof_char, 32) crc16 = dab.crc16_bb(32, 0x1021, 0xffff) @@ -45,7 +45,7 @@ def test_001_t(self): # multiple sub-channels def test_001_t(self): - src = dab.fib_source_b_make(1,7,'Galaxy_News', 'Wasteland_Radio', 'Country_Mix', 0x09, [0, 1, 2, 3, 3, 2, 1], [8, 2, 8, 8, 2, 1, 4]) + src = dab.fib_source_b_make(1,7,'Galaxy_News', 'Wasteland_Radio1Wasteland_Radio2Wasteland_Radio3Wasteland_Radio4Wasteland_Radio5Wasteland_Radio6Wasteland_Radio7', 'Country_Mix', 0x09, [0, 1, 2, 3, 3, 2, 1], [8, 2, 8, 8, 2, 1, 4], [1, 1, 0, 1, 1, 0, 1]) fib_unpacked_to_packed = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) s2v = blocks.stream_to_vector(gr.sizeof_char, 32) crc16 = dab.crc16_bb(32, 0x1021, 0xffff) diff --git a/python/qa_fic_encode.py b/python/qa_fic_encode.py index 959653dd..67486f48 100755 --- a/python/qa_fic_encode.py +++ b/python/qa_fic_encode.py @@ -43,7 +43,7 @@ def test_001_t (self): # source self.dp = dab_parameters(1, 208.064e6, True) - self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1", "musicmix", 4, [2], [15]) + self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1", "musicmix", 4, [2], [15], [1]) # encoder self.fib_enc = fic_encode(self.dab_params) From abd5d22b1d928e2a96d6cbfd01a33f6397305ddc Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 23 Aug 2017 15:08:38 +0200 Subject: [PATCH 028/135] GUI: add a posteriori audio sample rate correction --- python/GUI/main.py | 125 ++++++++++- python/GUI/user_frontend.py | 295 ++++++++++++++++++------- python/GUI/user_frontend.ui | 427 +++++++++++++++++++++++++++++------- python/GUI/usrp_dab_tx.py | 8 +- 4 files changed, 677 insertions(+), 178 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index b72fcb16..26756c1c 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -44,7 +44,7 @@ def __init__(self, parent=None): self.address = 0 self.size = 6 self.protection = 2 - self.audio_bit_rate = 32000 + self.audio_bit_rate = 16000 self.volume = 80 self.subch = -1 self.dabplus = True @@ -79,6 +79,9 @@ def __init__(self, parent=None): self.table_mci.cellClicked.connect(self.selected_subch) # a click on the play button compiles receiver with new subch info and plays the audio self.btn_play.clicked.connect(self.play_audio) + # adjust audio sampling rate + self.timer_audio_sampling_rate = QTimer() + self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) # stop button click stops audio reception self.btn_stop.clicked.connect(self.stop_reception) # volume slider moved @@ -126,31 +129,31 @@ def __init__(self, parent=None): {"label": self.t_label_comp1, "data_rate_label": self.t_label_rate1, "data_rate": self.t_spin_rate1, "protection_label": self.t_label_prot1, "protection": self.t_combo_prot1, "enabled": True, "src_label": self.t_label_comp_src1, "src_path_disp": self.t_label_path_src1, - "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1}, + "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1, "audio_rate_label": self.t_label_audio_rate1, "combo_audio_rate": self.t_combo_audio_rate1, "combo_audio_rate_dab": self.t_combo_audio_rate_dab1}, {"label": self.t_label_comp2, "data_rate_label": self.t_label_rate2, "data_rate": self.t_spin_rate2, "protection_label": self.t_label_prot2, "protection": self.t_combo_prot2, "enabled": False, "src_label": self.t_label_comp_src2, "src_path_disp": self.t_label_path_src2, - "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2}, + "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2, "audio_rate_label": self.t_label_audio_rate2, "combo_audio_rate": self.t_combo_audio_rate2, "combo_audio_rate_dab": self.t_combo_audio_rate_dab2}, {"label": self.t_label_comp3, "data_rate_label": self.t_label_rate3, "data_rate": self.t_spin_rate3, "protection_label": self.t_label_prot3, "protection": self.t_combo_prot3, "enabled": False, "src_label": self.t_label_comp_src3, "src_path_disp": self.t_label_path_src3, - "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3}, + "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3, "audio_rate_label": self.t_label_audio_rate3, "combo_audio_rate": self.t_combo_audio_rate3, "combo_audio_rate_dab": self.t_combo_audio_rate_dab3}, {"label": self.t_label_comp4, "data_rate_label": self.t_label_rate4, "data_rate": self.t_spin_rate4, "protection_label": self.t_label_prot4, "protection": self.t_combo_prot4, "enabled": False, "src_label": self.t_label_comp_src4, "src_path_disp": self.t_label_path_src4, - "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4}, + "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4, "audio_rate_label": self.t_label_audio_rate4, "combo_audio_rate": self.t_combo_audio_rate4, "combo_audio_rate_dab": self.t_combo_audio_rate_dab4}, {"label": self.t_label_comp5, "data_rate_label": self.t_label_rate5, "data_rate": self.t_spin_rate5, "protection_label": self.t_label_prot5, "protection": self.t_combo_prot5, "enabled": False, "src_label": self.t_label_comp_src5, "src_path_disp": self.t_label_path_src5, - "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5}, + "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5, "audio_rate_label": self.t_label_audio_rate5, "combo_audio_rate": self.t_combo_audio_rate5, "combo_audio_rate_dab": self.t_combo_audio_rate_dab5}, {"label": self.t_label_comp6, "data_rate_label": self.t_label_rate6, "data_rate": self.t_spin_rate6, "protection_label": self.t_label_prot6, "protection": self.t_combo_prot6, "enabled": False, "src_label": self.t_label_comp_src6, "src_path_disp": self.t_label_path_src6, - "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6}, + "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6, "audio_rate_label": self.t_label_audio_rate6, "combo_audio_rate": self.t_combo_audio_rate6, "combo_audio_rate_dab": self.t_combo_audio_rate_dab6}, {"label": self.t_label_comp7, "data_rate_label": self.t_label_rate7, "data_rate": self.t_spin_rate7, "protection_label": self.t_label_prot7, "protection": self.t_combo_prot7, "enabled": False, "src_label": self.t_label_comp_src7, "src_path_disp": self.t_label_path_src7, - "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7}] + "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7, "audio_rate_label": self.t_label_audio_rate7, "combo_audio_rate": self.t_combo_audio_rate7, "combo_audio_rate_dab": self.t_combo_audio_rate_dab7}] # update service components initially to hide the service components 2-7 self.t_update_service_components() # provide suggestions for language combo box @@ -184,6 +187,13 @@ def __init__(self, parent=None): self.t_btn_record5.pressed.connect(self.t_toggle_record5) self.t_btn_record6.pressed.connect(self.t_toggle_record6) self.t_btn_record7.pressed.connect(self.t_toggle_record7) + self.t_combo_dabplus1.currentIndexChanged.connect(self.change_audio_bit_rates1) + self.t_combo_dabplus2.currentIndexChanged.connect(self.change_audio_bit_rates2) + self.t_combo_dabplus3.currentIndexChanged.connect(self.change_audio_bit_rates3) + self.t_combo_dabplus4.currentIndexChanged.connect(self.change_audio_bit_rates4) + self.t_combo_dabplus5.currentIndexChanged.connect(self.change_audio_bit_rates5) + self.t_combo_dabplus6.currentIndexChanged.connect(self.change_audio_bit_rates6) + self.t_combo_dabplus7.currentIndexChanged.connect(self.change_audio_bit_rates7) # set volume if volume slider is changed self.t_slider_volume.valueChanged.connect(self.t_set_volume) @@ -312,7 +322,7 @@ def selected_subch(self): conv_table = [12, 8, 6, 5] self.bit_rate = self.size * 8/conv_table[self.protection] self.dabplus = service_data['DAB+'] - if dabplus: + if self.dabplus: if self.bit_rate < 100: self.audio_bit_rate = 48000 else: @@ -398,7 +408,26 @@ def play_audio(self): # start timer for snr update again self.snr_timer.start(1000) self.firecode_timer.start(120) - # update dev mode + # start audio sampling rate timer + self.timer_audio_sampling_rate.start(500) + + def adjust_audio_sampling_rate(self): + self.timer_audio_sampling_rate.stop() + new_sampling_rate = self.my_receiver.get_sample_rate() + print "key adjust" + if new_sampling_rate != self.audio_bit_rate and new_sampling_rate != -1: + self.audio_bit_rate = new_sampling_rate + self.statusBar.showMessage("Adjusting audio sampling rate to " + str(new_sampling_rate)) + self.my_receiver.stop() + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + + self.my_receiver.start() + elif new_sampling_rate == -1: + self.timer_audio_sampling_rate.start(200) def stop_reception(self): # close dev mode @@ -633,7 +662,7 @@ def t_change_num_subch(self): self.t_spin_listen_to_component.setMaximum(num_subch) def t_update_service_components(self): - # display/hide components after the info in components (dict) + # display/hide components referring to the info in components (dict) for component in self.components: if component["enabled"] is False: component["label"].hide() @@ -648,6 +677,9 @@ def t_update_service_components(self): component["edit_label"].hide() component["combo_dabplus"].hide() component["btn_record"].hide() + component["audio_rate_label"].hide() + component["combo_audio_rate"].hide() + component["combo_audio_rate_dab"].hide() else: component["label"].show() component["data_rate_label"].show() @@ -661,6 +693,13 @@ def t_update_service_components(self): component["edit_label"].show() component["combo_dabplus"].show() component["btn_record"].show() + component["audio_rate_label"].show() + if component["combo_dabplus"].currentIndex() is 0: + component["combo_audio_rate"].show() + component["combo_audio_rate_dab"].hide() + else: + component["combo_audio_rate_dab"].show() + component["combo_audio_rate"].hide() def t_init_transmitter(self): self.statusBar.showMessage("initializing transmitter...") @@ -669,6 +708,7 @@ def t_init_transmitter(self): # produce array for protection and data_rate and src_paths protection_array = [None] * self.t_spin_num_subch.value() data_rate_n_array = [None] * self.t_spin_num_subch.value() + audio_sampling_rate_array = [None] * self.t_spin_num_subch.value() audio_paths = ["None"] * self.t_spin_num_subch.value() merged_service_string = "" dabplus_types = [True] * self.t_spin_num_subch.value() @@ -678,6 +718,11 @@ def t_init_transmitter(self): protection_array[i] = self.components[i]["protection"].currentIndex() # write array with data rates data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # write audio sampling rates in array + if self.components[i]["combo_dabplus"].currentIndex() is 0: + audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 + else: + audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 # check audio paths if self.components[i]["src_path"] is "None": # highlight the path which is not selected @@ -716,7 +761,7 @@ def t_init_transmitter(self): str(self.t_edit_ensemble_label.text()), merged_service_string, self.t_combo_language.currentIndex(), - protection_array, data_rate_n_array, + protection_array, data_rate_n_array, audio_sampling_rate_array, audio_paths, self.t_spin_listen_to_component.value(), self.t_rbtn_USRP.isChecked(), @@ -846,6 +891,62 @@ def t_toggle_record7(self): self.t_label_path_src7.setText("microphone") self.components[6]["src_path"] = "mic" + def change_audio_bit_rates1(self): + if self.t_combo_dabplus1.currentIndex() is 0: + self.t_combo_audio_rate1.show() + self.t_combo_audio_rate_dab1.hide() + else: + self.t_combo_audio_rate_dab1.show() + self.t_combo_audio_rate1.hide() + + def change_audio_bit_rates2(self): + if self.t_combo_dabplus2.currentIndex() is 0: + self.t_combo_audio_rate2.show() + self.t_combo_audio_rate_dab2.hide() + else: + self.t_combo_audio_rate_dab2.show() + self.t_combo_audio_rate2.hide() + + def change_audio_bit_rates3(self): + if self.t_combo_dabplus3.currentIndex() is 0: + self.t_combo_audio_rate3.show() + self.t_combo_audio_rate_dab3.hide() + else: + self.t_combo_audio_rate_dab3.show() + self.t_combo_audio_rate3.hide() + + def change_audio_bit_rates4(self): + if self.t_combo_dabplus4.currentIndex() is 0: + self.t_combo_audio_rate4.show() + self.t_combo_audio_rate_dab4.hide() + else: + self.t_combo_audio_rate_dab4.show() + self.t_combo_audio_rate4.hide() + + def change_audio_bit_rates5(self): + if self.t_combo_dabplus5.currentIndex() is 0: + self.t_combo_audio_rate5.show() + self.t_combo_audio_rate_dab5.hide() + else: + self.t_combo_audio_rate_dab5.show() + self.t_combo_audio_rate5.hide() + + def change_audio_bit_rates6(self): + if self.t_combo_dabplus6.currentIndex() is 0: + self.t_combo_audio_rate6.show() + self.t_combo_audio_rate_dab6.hide() + else: + self.t_combo_audio_rate_dab6.show() + self.t_combo_audio_rate6.hide() + + def change_audio_bit_rates7(self): + if self.t_combo_dabplus7.currentIndex() is 0: + self.t_combo_audio_rate7.show() + self.t_combo_audio_rate_dab7.hide() + else: + self.t_combo_audio_rate_dab7.show() + self.t_combo_audio_rate7.hide() + class lookup_tables: languages = [ diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index e87b4147..7ab47eb7 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -529,7 +529,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 525, 1269)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -1028, 525, 1514)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -572,7 +572,7 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(5, QtGui.QFormLayout.LabelRole, self.t_label_prot1) self.t_label_comp_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src1.setObjectName(_fromUtf8("t_label_comp_src1")) - self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) + self.formLayout_3.setWidget(7, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) self.horizontalLayout_13 = QtGui.QHBoxLayout() self.horizontalLayout_13.setObjectName(_fromUtf8("horizontalLayout_13")) self.t_btn_record1 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -609,7 +609,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src1 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src1.setObjectName(_fromUtf8("t_btn_path_src1")) self.horizontalLayout_13.addWidget(self.t_btn_path_src1) - self.formLayout_3.setLayout(6, QtGui.QFormLayout.FieldRole, self.horizontalLayout_13) + self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.horizontalLayout_13) self.t_label_comp2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp2.setEnabled(True) font = QtGui.QFont() @@ -618,21 +618,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp2.setFont(font) self.t_label_comp2.setObjectName(_fromUtf8("t_label_comp2")) - self.formLayout_3.setWidget(7, QtGui.QFormLayout.LabelRole, self.t_label_comp2) + self.formLayout_3.setWidget(8, QtGui.QFormLayout.LabelRole, self.t_label_comp2) self.t_label_rate2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate2.setObjectName(_fromUtf8("t_label_rate2")) - self.formLayout_3.setWidget(9, QtGui.QFormLayout.LabelRole, self.t_label_rate2) + self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_rate2) self.t_spin_rate2 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate2.setMaximum(999) self.t_spin_rate2.setProperty("value", 112) self.t_spin_rate2.setObjectName(_fromUtf8("t_spin_rate2")) - self.formLayout_3.setWidget(9, QtGui.QFormLayout.FieldRole, self.t_spin_rate2) + self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_spin_rate2) self.t_label_prot2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot2.setObjectName(_fromUtf8("t_label_prot2")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_prot2) + self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_prot2) self.t_label_comp_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src2.setObjectName(_fromUtf8("t_label_comp_src2")) - self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) + self.formLayout_3.setWidget(13, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) self.horizontalLayout_14 = QtGui.QHBoxLayout() self.horizontalLayout_14.setObjectName(_fromUtf8("horizontalLayout_14")) self.t_btn_record2 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -656,7 +656,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src2 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src2.setObjectName(_fromUtf8("t_btn_path_src2")) self.horizontalLayout_14.addWidget(self.t_btn_path_src2) - self.formLayout_3.setLayout(11, QtGui.QFormLayout.FieldRole, self.horizontalLayout_14) + self.formLayout_3.setLayout(13, QtGui.QFormLayout.FieldRole, self.horizontalLayout_14) self.t_label_comp3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp3.setEnabled(True) font = QtGui.QFont() @@ -665,21 +665,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp3.setFont(font) self.t_label_comp3.setObjectName(_fromUtf8("t_label_comp3")) - self.formLayout_3.setWidget(12, QtGui.QFormLayout.LabelRole, self.t_label_comp3) + self.formLayout_3.setWidget(14, QtGui.QFormLayout.LabelRole, self.t_label_comp3) self.t_label_rate3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate3.setObjectName(_fromUtf8("t_label_rate3")) - self.formLayout_3.setWidget(14, QtGui.QFormLayout.LabelRole, self.t_label_rate3) + self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_rate3) self.t_spin_rate3 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate3.setMaximum(999) self.t_spin_rate3.setProperty("value", 112) self.t_spin_rate3.setObjectName(_fromUtf8("t_spin_rate3")) - self.formLayout_3.setWidget(14, QtGui.QFormLayout.FieldRole, self.t_spin_rate3) + self.formLayout_3.setWidget(16, QtGui.QFormLayout.FieldRole, self.t_spin_rate3) self.t_label_prot3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot3.setObjectName(_fromUtf8("t_label_prot3")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_prot3) + self.formLayout_3.setWidget(17, QtGui.QFormLayout.LabelRole, self.t_label_prot3) self.t_label_comp_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src3.setObjectName(_fromUtf8("t_label_comp_src3")) - self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) + self.formLayout_3.setWidget(19, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) self.horizontalLayout_15 = QtGui.QHBoxLayout() self.horizontalLayout_15.setObjectName(_fromUtf8("horizontalLayout_15")) self.t_btn_record3 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -703,7 +703,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src3 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src3.setObjectName(_fromUtf8("t_btn_path_src3")) self.horizontalLayout_15.addWidget(self.t_btn_path_src3) - self.formLayout_3.setLayout(16, QtGui.QFormLayout.FieldRole, self.horizontalLayout_15) + self.formLayout_3.setLayout(19, QtGui.QFormLayout.FieldRole, self.horizontalLayout_15) self.t_label_comp4 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -711,21 +711,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp4.setFont(font) self.t_label_comp4.setObjectName(_fromUtf8("t_label_comp4")) - self.formLayout_3.setWidget(17, QtGui.QFormLayout.LabelRole, self.t_label_comp4) + self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_comp4) self.t_label_rate4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate4.setObjectName(_fromUtf8("t_label_rate4")) - self.formLayout_3.setWidget(19, QtGui.QFormLayout.LabelRole, self.t_label_rate4) + self.formLayout_3.setWidget(22, QtGui.QFormLayout.LabelRole, self.t_label_rate4) self.t_spin_rate4 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate4.setMaximum(999) self.t_spin_rate4.setProperty("value", 112) self.t_spin_rate4.setObjectName(_fromUtf8("t_spin_rate4")) - self.formLayout_3.setWidget(19, QtGui.QFormLayout.FieldRole, self.t_spin_rate4) + self.formLayout_3.setWidget(22, QtGui.QFormLayout.FieldRole, self.t_spin_rate4) self.t_label_prot4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot4.setObjectName(_fromUtf8("t_label_prot4")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_prot4) + self.formLayout_3.setWidget(23, QtGui.QFormLayout.LabelRole, self.t_label_prot4) self.t_label_comp_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src4.setObjectName(_fromUtf8("t_label_comp_src4")) - self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) + self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) self.horizontalLayout_16 = QtGui.QHBoxLayout() self.horizontalLayout_16.setObjectName(_fromUtf8("horizontalLayout_16")) self.t_btn_record4 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -749,7 +749,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src4 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src4.setObjectName(_fromUtf8("t_btn_path_src4")) self.horizontalLayout_16.addWidget(self.t_btn_path_src4) - self.formLayout_3.setLayout(21, QtGui.QFormLayout.FieldRole, self.horizontalLayout_16) + self.formLayout_3.setLayout(25, QtGui.QFormLayout.FieldRole, self.horizontalLayout_16) self.t_label_comp5 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -757,21 +757,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp5.setFont(font) self.t_label_comp5.setObjectName(_fromUtf8("t_label_comp5")) - self.formLayout_3.setWidget(22, QtGui.QFormLayout.LabelRole, self.t_label_comp5) + self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp5) self.t_label_rate5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate5.setObjectName(_fromUtf8("t_label_rate5")) - self.formLayout_3.setWidget(24, QtGui.QFormLayout.LabelRole, self.t_label_rate5) + self.formLayout_3.setWidget(28, QtGui.QFormLayout.LabelRole, self.t_label_rate5) self.t_spin_rate5 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate5.setMaximum(999) self.t_spin_rate5.setProperty("value", 112) self.t_spin_rate5.setObjectName(_fromUtf8("t_spin_rate5")) - self.formLayout_3.setWidget(24, QtGui.QFormLayout.FieldRole, self.t_spin_rate5) + self.formLayout_3.setWidget(28, QtGui.QFormLayout.FieldRole, self.t_spin_rate5) self.t_label_prot5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot5.setObjectName(_fromUtf8("t_label_prot5")) - self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_prot5) + self.formLayout_3.setWidget(29, QtGui.QFormLayout.LabelRole, self.t_label_prot5) self.t_label_comp_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src5.setObjectName(_fromUtf8("t_label_comp_src5")) - self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) + self.formLayout_3.setWidget(31, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) self.horizontalLayout_17 = QtGui.QHBoxLayout() self.horizontalLayout_17.setObjectName(_fromUtf8("horizontalLayout_17")) self.t_btn_record5 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -795,7 +795,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src5 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src5.setObjectName(_fromUtf8("t_btn_path_src5")) self.horizontalLayout_17.addWidget(self.t_btn_path_src5) - self.formLayout_3.setLayout(26, QtGui.QFormLayout.FieldRole, self.horizontalLayout_17) + self.formLayout_3.setLayout(31, QtGui.QFormLayout.FieldRole, self.horizontalLayout_17) self.t_label_comp6 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -803,21 +803,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp6.setFont(font) self.t_label_comp6.setObjectName(_fromUtf8("t_label_comp6")) - self.formLayout_3.setWidget(27, QtGui.QFormLayout.LabelRole, self.t_label_comp6) + self.formLayout_3.setWidget(32, QtGui.QFormLayout.LabelRole, self.t_label_comp6) self.t_label_rate6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate6.setObjectName(_fromUtf8("t_label_rate6")) - self.formLayout_3.setWidget(29, QtGui.QFormLayout.LabelRole, self.t_label_rate6) + self.formLayout_3.setWidget(34, QtGui.QFormLayout.LabelRole, self.t_label_rate6) self.t_spin_rate6 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate6.setMaximum(999) self.t_spin_rate6.setProperty("value", 112) self.t_spin_rate6.setObjectName(_fromUtf8("t_spin_rate6")) - self.formLayout_3.setWidget(29, QtGui.QFormLayout.FieldRole, self.t_spin_rate6) + self.formLayout_3.setWidget(34, QtGui.QFormLayout.FieldRole, self.t_spin_rate6) self.t_label_prot6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot6.setObjectName(_fromUtf8("t_label_prot6")) - self.formLayout_3.setWidget(30, QtGui.QFormLayout.LabelRole, self.t_label_prot6) + self.formLayout_3.setWidget(35, QtGui.QFormLayout.LabelRole, self.t_label_prot6) self.t_label_comp_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src6.setObjectName(_fromUtf8("t_label_comp_src6")) - self.formLayout_3.setWidget(31, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) + self.formLayout_3.setWidget(37, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) self.horizontalLayout_18 = QtGui.QHBoxLayout() self.horizontalLayout_18.setObjectName(_fromUtf8("horizontalLayout_18")) self.t_btn_record6 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -841,7 +841,7 @@ def setupUi(self, MainWindow): self.t_btn_path_src6 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src6.setObjectName(_fromUtf8("t_btn_path_src6")) self.horizontalLayout_18.addWidget(self.t_btn_path_src6) - self.formLayout_3.setLayout(31, QtGui.QFormLayout.FieldRole, self.horizontalLayout_18) + self.formLayout_3.setLayout(37, QtGui.QFormLayout.FieldRole, self.horizontalLayout_18) self.t_label_comp7 = QtGui.QLabel(self.scrollAreaWidgetContents) font = QtGui.QFont() font.setPointSize(13) @@ -849,21 +849,21 @@ def setupUi(self, MainWindow): font.setWeight(75) self.t_label_comp7.setFont(font) self.t_label_comp7.setObjectName(_fromUtf8("t_label_comp7")) - self.formLayout_3.setWidget(32, QtGui.QFormLayout.LabelRole, self.t_label_comp7) + self.formLayout_3.setWidget(38, QtGui.QFormLayout.LabelRole, self.t_label_comp7) self.t_label_rate7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_rate7.setObjectName(_fromUtf8("t_label_rate7")) - self.formLayout_3.setWidget(34, QtGui.QFormLayout.LabelRole, self.t_label_rate7) + self.formLayout_3.setWidget(40, QtGui.QFormLayout.LabelRole, self.t_label_rate7) self.t_spin_rate7 = QtGui.QSpinBox(self.scrollAreaWidgetContents) self.t_spin_rate7.setMaximum(999) self.t_spin_rate7.setProperty("value", 112) self.t_spin_rate7.setObjectName(_fromUtf8("t_spin_rate7")) - self.formLayout_3.setWidget(34, QtGui.QFormLayout.FieldRole, self.t_spin_rate7) + self.formLayout_3.setWidget(40, QtGui.QFormLayout.FieldRole, self.t_spin_rate7) self.t_label_prot7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_prot7.setObjectName(_fromUtf8("t_label_prot7")) - self.formLayout_3.setWidget(35, QtGui.QFormLayout.LabelRole, self.t_label_prot7) + self.formLayout_3.setWidget(41, QtGui.QFormLayout.LabelRole, self.t_label_prot7) self.t_label_comp_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_comp_src7.setObjectName(_fromUtf8("t_label_comp_src7")) - self.formLayout_3.setWidget(36, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) + self.formLayout_3.setWidget(43, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) self.horizontalLayout_19 = QtGui.QHBoxLayout() self.horizontalLayout_19.setObjectName(_fromUtf8("horizontalLayout_19")) self.t_btn_record7 = QtGui.QPushButton(self.scrollAreaWidgetContents) @@ -887,49 +887,49 @@ def setupUi(self, MainWindow): self.t_btn_path_src7 = QtGui.QToolButton(self.scrollAreaWidgetContents) self.t_btn_path_src7.setObjectName(_fromUtf8("t_btn_path_src7")) self.horizontalLayout_19.addWidget(self.t_btn_path_src7) - self.formLayout_3.setLayout(36, QtGui.QFormLayout.FieldRole, self.horizontalLayout_19) + self.formLayout_3.setLayout(43, QtGui.QFormLayout.FieldRole, self.horizontalLayout_19) self.t_label_label1 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label1.setObjectName(_fromUtf8("t_label_label1")) self.formLayout_3.setWidget(3, QtGui.QFormLayout.LabelRole, self.t_label_label1) self.t_label_label2 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label2.setObjectName(_fromUtf8("t_label_label2")) - self.formLayout_3.setWidget(8, QtGui.QFormLayout.LabelRole, self.t_label_label2) + self.formLayout_3.setWidget(9, QtGui.QFormLayout.LabelRole, self.t_label_label2) self.t_label_label3 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label3.setObjectName(_fromUtf8("t_label_label3")) - self.formLayout_3.setWidget(13, QtGui.QFormLayout.LabelRole, self.t_label_label3) + self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_label3) self.t_label_label4 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label4.setObjectName(_fromUtf8("t_label_label4")) - self.formLayout_3.setWidget(18, QtGui.QFormLayout.LabelRole, self.t_label_label4) + self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_label4) self.t_label_label5 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label5.setObjectName(_fromUtf8("t_label_label5")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.LabelRole, self.t_label_label5) + self.formLayout_3.setWidget(27, QtGui.QFormLayout.LabelRole, self.t_label_label5) self.t_label_label6 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label6.setObjectName(_fromUtf8("t_label_label6")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.LabelRole, self.t_label_label6) + self.formLayout_3.setWidget(33, QtGui.QFormLayout.LabelRole, self.t_label_label6) self.t_label_label7 = QtGui.QLabel(self.scrollAreaWidgetContents) self.t_label_label7.setObjectName(_fromUtf8("t_label_label7")) - self.formLayout_3.setWidget(33, QtGui.QFormLayout.LabelRole, self.t_label_label7) + self.formLayout_3.setWidget(39, QtGui.QFormLayout.LabelRole, self.t_label_label7) self.t_edit_service_label1 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label1.setObjectName(_fromUtf8("t_edit_service_label1")) self.formLayout_3.setWidget(3, QtGui.QFormLayout.FieldRole, self.t_edit_service_label1) self.t_edit_service_label2 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label2.setObjectName(_fromUtf8("t_edit_service_label2")) - self.formLayout_3.setWidget(8, QtGui.QFormLayout.FieldRole, self.t_edit_service_label2) + self.formLayout_3.setWidget(9, QtGui.QFormLayout.FieldRole, self.t_edit_service_label2) self.t_edit_service_label3 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label3.setObjectName(_fromUtf8("t_edit_service_label3")) - self.formLayout_3.setWidget(13, QtGui.QFormLayout.FieldRole, self.t_edit_service_label3) + self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_edit_service_label3) self.t_edit_service_label4 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label4.setObjectName(_fromUtf8("t_edit_service_label4")) - self.formLayout_3.setWidget(18, QtGui.QFormLayout.FieldRole, self.t_edit_service_label4) + self.formLayout_3.setWidget(21, QtGui.QFormLayout.FieldRole, self.t_edit_service_label4) self.t_edit_service_label5 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label5.setObjectName(_fromUtf8("t_edit_service_label5")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.FieldRole, self.t_edit_service_label5) + self.formLayout_3.setWidget(27, QtGui.QFormLayout.FieldRole, self.t_edit_service_label5) self.t_edit_service_label6 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label6.setObjectName(_fromUtf8("t_edit_service_label6")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.FieldRole, self.t_edit_service_label6) + self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label6) self.t_edit_service_label7 = QtGui.QLineEdit(self.scrollAreaWidgetContents) self.t_edit_service_label7.setObjectName(_fromUtf8("t_edit_service_label7")) - self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) + self.formLayout_3.setWidget(39, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -949,7 +949,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus2.addItem(_fromUtf8("")) self.t_combo_dabplus2.addItem(_fromUtf8("")) self.t_layout_combo_dabplus2.addWidget(self.t_combo_dabplus2) - self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) + self.formLayout_3.setLayout(8, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -959,7 +959,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus3.addItem(_fromUtf8("")) self.t_combo_dabplus3.addItem(_fromUtf8("")) self.t_layout_combo_dabplus3.addWidget(self.t_combo_dabplus3) - self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) + self.formLayout_3.setLayout(14, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -969,7 +969,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus4.addItem(_fromUtf8("")) self.t_combo_dabplus4.addItem(_fromUtf8("")) self.t_layout_combo_dabplus4.addWidget(self.t_combo_dabplus4) - self.formLayout_3.setLayout(17, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) + self.formLayout_3.setLayout(20, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -979,7 +979,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus5.addItem(_fromUtf8("")) self.t_combo_dabplus5.addItem(_fromUtf8("")) self.t_layout_combo_dabplus5.addWidget(self.t_combo_dabplus5) - self.formLayout_3.setLayout(22, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) + self.formLayout_3.setLayout(26, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -989,7 +989,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus6.addItem(_fromUtf8("")) self.t_combo_dabplus6.addItem(_fromUtf8("")) self.t_layout_combo_dabplus6.addWidget(self.t_combo_dabplus6) - self.formLayout_3.setLayout(27, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) + self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) spacerItem20 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) @@ -999,7 +999,7 @@ def setupUi(self, MainWindow): self.t_combo_dabplus7.addItem(_fromUtf8("")) self.t_combo_dabplus7.addItem(_fromUtf8("")) self.t_layout_combo_dabplus7.addWidget(self.t_combo_dabplus7) - self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus7) + self.formLayout_3.setLayout(38, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus7) self.t_combo_prot1 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot1.setObjectName(_fromUtf8("t_combo_prot1")) self.t_combo_prot1.addItem(_fromUtf8("")) @@ -1013,42 +1013,154 @@ def setupUi(self, MainWindow): self.t_combo_prot2.addItem(_fromUtf8("")) self.t_combo_prot2.addItem(_fromUtf8("")) self.t_combo_prot2.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_combo_prot2) + self.formLayout_3.setWidget(11, QtGui.QFormLayout.FieldRole, self.t_combo_prot2) self.t_combo_prot3 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot3.setObjectName(_fromUtf8("t_combo_prot3")) self.t_combo_prot3.addItem(_fromUtf8("")) self.t_combo_prot3.addItem(_fromUtf8("")) self.t_combo_prot3.addItem(_fromUtf8("")) self.t_combo_prot3.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_combo_prot3) + self.formLayout_3.setWidget(17, QtGui.QFormLayout.FieldRole, self.t_combo_prot3) self.t_combo_prot4 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot4.setObjectName(_fromUtf8("t_combo_prot4")) self.t_combo_prot4.addItem(_fromUtf8("")) self.t_combo_prot4.addItem(_fromUtf8("")) self.t_combo_prot4.addItem(_fromUtf8("")) self.t_combo_prot4.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.FieldRole, self.t_combo_prot4) + self.formLayout_3.setWidget(23, QtGui.QFormLayout.FieldRole, self.t_combo_prot4) self.t_combo_prot5 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot5.setObjectName(_fromUtf8("t_combo_prot5")) self.t_combo_prot5.addItem(_fromUtf8("")) self.t_combo_prot5.addItem(_fromUtf8("")) self.t_combo_prot5.addItem(_fromUtf8("")) self.t_combo_prot5.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(25, QtGui.QFormLayout.FieldRole, self.t_combo_prot5) + self.formLayout_3.setWidget(29, QtGui.QFormLayout.FieldRole, self.t_combo_prot5) self.t_combo_prot6 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot6.setObjectName(_fromUtf8("t_combo_prot6")) self.t_combo_prot6.addItem(_fromUtf8("")) self.t_combo_prot6.addItem(_fromUtf8("")) self.t_combo_prot6.addItem(_fromUtf8("")) self.t_combo_prot6.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(30, QtGui.QFormLayout.FieldRole, self.t_combo_prot6) + self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_combo_prot6) self.t_combo_prot7 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_prot7.setObjectName(_fromUtf8("t_combo_prot7")) self.t_combo_prot7.addItem(_fromUtf8("")) self.t_combo_prot7.addItem(_fromUtf8("")) self.t_combo_prot7.addItem(_fromUtf8("")) self.t_combo_prot7.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_combo_prot7) + self.formLayout_3.setWidget(41, QtGui.QFormLayout.FieldRole, self.t_combo_prot7) + self.t_label_audio_rate1 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate1.setObjectName(_fromUtf8("t_label_audio_rate1")) + self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate1) + self.t_label_audio_rate2 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate2.setObjectName(_fromUtf8("t_label_audio_rate2")) + self.formLayout_3.setWidget(12, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate2) + self.t_label_audio_rate3 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate3.setObjectName(_fromUtf8("t_label_audio_rate3")) + self.formLayout_3.setWidget(18, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate3) + self.t_label_audio_rate4 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate4.setObjectName(_fromUtf8("t_label_audio_rate4")) + self.formLayout_3.setWidget(24, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate4) + self.t_label_audio_rate5 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate5.setObjectName(_fromUtf8("t_label_audio_rate5")) + self.formLayout_3.setWidget(30, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate5) + self.t_label_audio_rate6 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate6.setObjectName(_fromUtf8("t_label_audio_rate6")) + self.formLayout_3.setWidget(36, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate6) + self.t_label_audio_rate7 = QtGui.QLabel(self.scrollAreaWidgetContents) + self.t_label_audio_rate7.setObjectName(_fromUtf8("t_label_audio_rate7")) + self.formLayout_3.setWidget(42, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate7) + self.horizontalLayout_2 = QtGui.QHBoxLayout() + self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) + self.t_combo_audio_rate1 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate1.setObjectName(_fromUtf8("t_combo_audio_rate1")) + self.t_combo_audio_rate1.addItem(_fromUtf8("")) + self.t_combo_audio_rate1.addItem(_fromUtf8("")) + self.horizontalLayout_2.addWidget(self.t_combo_audio_rate1) + self.t_combo_audio_rate_dab1 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab1.setObjectName(_fromUtf8("t_combo_audio_rate_dab1")) + self.t_combo_audio_rate_dab1.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab1.addItem(_fromUtf8("")) + self.horizontalLayout_2.addWidget(self.t_combo_audio_rate_dab1) + self.formLayout_3.setLayout(6, QtGui.QFormLayout.FieldRole, self.horizontalLayout_2) + self.horizontalLayout_33 = QtGui.QHBoxLayout() + self.horizontalLayout_33.setObjectName(_fromUtf8("horizontalLayout_33")) + self.t_combo_audio_rate2 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate2.setObjectName(_fromUtf8("t_combo_audio_rate2")) + self.t_combo_audio_rate2.addItem(_fromUtf8("")) + self.t_combo_audio_rate2.addItem(_fromUtf8("")) + self.horizontalLayout_33.addWidget(self.t_combo_audio_rate2) + self.t_combo_audio_rate_dab2 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab2.setObjectName(_fromUtf8("t_combo_audio_rate_dab2")) + self.t_combo_audio_rate_dab2.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab2.addItem(_fromUtf8("")) + self.horizontalLayout_33.addWidget(self.t_combo_audio_rate_dab2) + self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.horizontalLayout_33) + self.horizontalLayout_34 = QtGui.QHBoxLayout() + self.horizontalLayout_34.setObjectName(_fromUtf8("horizontalLayout_34")) + self.t_combo_audio_rate3 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate3.setObjectName(_fromUtf8("t_combo_audio_rate3")) + self.t_combo_audio_rate3.addItem(_fromUtf8("")) + self.t_combo_audio_rate3.addItem(_fromUtf8("")) + self.horizontalLayout_34.addWidget(self.t_combo_audio_rate3) + self.t_combo_audio_rate_dab3 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab3.setObjectName(_fromUtf8("t_combo_audio_rate_dab3")) + self.t_combo_audio_rate_dab3.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab3.addItem(_fromUtf8("")) + self.horizontalLayout_34.addWidget(self.t_combo_audio_rate_dab3) + self.formLayout_3.setLayout(18, QtGui.QFormLayout.FieldRole, self.horizontalLayout_34) + self.horizontalLayout_35 = QtGui.QHBoxLayout() + self.horizontalLayout_35.setObjectName(_fromUtf8("horizontalLayout_35")) + self.t_combo_audio_rate4 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate4.setObjectName(_fromUtf8("t_combo_audio_rate4")) + self.t_combo_audio_rate4.addItem(_fromUtf8("")) + self.t_combo_audio_rate4.addItem(_fromUtf8("")) + self.horizontalLayout_35.addWidget(self.t_combo_audio_rate4) + self.t_combo_audio_rate_dab4 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab4.setObjectName(_fromUtf8("t_combo_audio_rate_dab4")) + self.t_combo_audio_rate_dab4.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab4.addItem(_fromUtf8("")) + self.horizontalLayout_35.addWidget(self.t_combo_audio_rate_dab4) + self.formLayout_3.setLayout(24, QtGui.QFormLayout.FieldRole, self.horizontalLayout_35) + self.horizontalLayout_36 = QtGui.QHBoxLayout() + self.horizontalLayout_36.setObjectName(_fromUtf8("horizontalLayout_36")) + self.t_combo_audio_rate5 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate5.setObjectName(_fromUtf8("t_combo_audio_rate5")) + self.t_combo_audio_rate5.addItem(_fromUtf8("")) + self.t_combo_audio_rate5.addItem(_fromUtf8("")) + self.horizontalLayout_36.addWidget(self.t_combo_audio_rate5) + self.t_combo_audio_rate_dab5 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab5.setObjectName(_fromUtf8("t_combo_audio_rate_dab5")) + self.t_combo_audio_rate_dab5.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab5.addItem(_fromUtf8("")) + self.horizontalLayout_36.addWidget(self.t_combo_audio_rate_dab5) + self.formLayout_3.setLayout(30, QtGui.QFormLayout.FieldRole, self.horizontalLayout_36) + self.horizontalLayout_37 = QtGui.QHBoxLayout() + self.horizontalLayout_37.setObjectName(_fromUtf8("horizontalLayout_37")) + self.t_combo_audio_rate6 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate6.setObjectName(_fromUtf8("t_combo_audio_rate6")) + self.t_combo_audio_rate6.addItem(_fromUtf8("")) + self.t_combo_audio_rate6.addItem(_fromUtf8("")) + self.horizontalLayout_37.addWidget(self.t_combo_audio_rate6) + self.t_combo_audio_rate_dab6 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab6.setObjectName(_fromUtf8("t_combo_audio_rate_dab6")) + self.t_combo_audio_rate_dab6.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab6.addItem(_fromUtf8("")) + self.horizontalLayout_37.addWidget(self.t_combo_audio_rate_dab6) + self.formLayout_3.setLayout(36, QtGui.QFormLayout.FieldRole, self.horizontalLayout_37) + self.horizontalLayout_38 = QtGui.QHBoxLayout() + self.horizontalLayout_38.setObjectName(_fromUtf8("horizontalLayout_38")) + self.t_combo_audio_rate7 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate7.setObjectName(_fromUtf8("t_combo_audio_rate7")) + self.t_combo_audio_rate7.addItem(_fromUtf8("")) + self.t_combo_audio_rate7.addItem(_fromUtf8("")) + self.horizontalLayout_38.addWidget(self.t_combo_audio_rate7) + self.t_combo_audio_rate_dab7 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_audio_rate_dab7.setObjectName(_fromUtf8("t_combo_audio_rate_dab7")) + self.t_combo_audio_rate_dab7.addItem(_fromUtf8("")) + self.t_combo_audio_rate_dab7.addItem(_fromUtf8("")) + self.horizontalLayout_38.addWidget(self.t_combo_audio_rate_dab7) + self.formLayout_3.setLayout(42, QtGui.QFormLayout.FieldRole, self.horizontalLayout_38) self.verticalLayout_4.addLayout(self.formLayout_3) self.line_15 = QtGui.QFrame(self.scrollAreaWidgetContents) self.line_15.setFrameShape(QtGui.QFrame.HLine) @@ -1115,28 +1227,22 @@ def setupUi(self, MainWindow): self.label_15.setFont(font) self.label_15.setObjectName(_fromUtf8("label_15")) self.formLayout_2.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_15) - self.label_16 = QtGui.QLabel(self.tab_transmission) - self.label_16.setObjectName(_fromUtf8("label_16")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_16) - self.t_edit_service_label = QtGui.QLineEdit(self.tab_transmission) - self.t_edit_service_label.setObjectName(_fromUtf8("t_edit_service_label")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_edit_service_label) self.label_17 = QtGui.QLabel(self.tab_transmission) self.label_17.setObjectName(_fromUtf8("label_17")) - self.formLayout_2.setWidget(6, QtGui.QFormLayout.LabelRole, self.label_17) + self.formLayout_2.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_17) self.t_spin_num_subch = QtGui.QSpinBox(self.tab_transmission) - self.t_spin_num_subch.setMaximum(7) + self.t_spin_num_subch.setMaximum(4) self.t_spin_num_subch.setProperty("value", 1) self.t_spin_num_subch.setObjectName(_fromUtf8("t_spin_num_subch")) - self.formLayout_2.setWidget(6, QtGui.QFormLayout.FieldRole, self.t_spin_num_subch) + self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_spin_num_subch) self.label_23 = QtGui.QLabel(self.tab_transmission) self.label_23.setObjectName(_fromUtf8("label_23")) - self.formLayout_2.setWidget(7, QtGui.QFormLayout.LabelRole, self.label_23) + self.formLayout_2.setWidget(6, QtGui.QFormLayout.LabelRole, self.label_23) self.t_combo_language = QtGui.QComboBox(self.tab_transmission) self.t_combo_language.setObjectName(_fromUtf8("t_combo_language")) - self.formLayout_2.setWidget(7, QtGui.QFormLayout.FieldRole, self.t_combo_language) + self.formLayout_2.setWidget(6, QtGui.QFormLayout.FieldRole, self.t_combo_language) spacerItem21 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(8, QtGui.QFormLayout.FieldRole, spacerItem21) + self.formLayout_2.setItem(7, QtGui.QFormLayout.FieldRole, spacerItem21) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -1218,7 +1324,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) + self.mode_tabs.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1367,14 +1473,47 @@ def retranslateUi(self, MainWindow): self.t_combo_prot7.setItemText(1, _translate("MainWindow", "A2", None)) self.t_combo_prot7.setItemText(2, _translate("MainWindow", "A3", None)) self.t_combo_prot7.setItemText(3, _translate("MainWindow", "A4", None)) + self.t_label_audio_rate1.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_label_audio_rate2.setText(_translate("MainWindow", "Audio Sampling rate", None)) + self.t_label_audio_rate3.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_label_audio_rate4.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_label_audio_rate5.setText(_translate("MainWindow", "audio sampling rate", None)) + self.t_label_audio_rate6.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_label_audio_rate7.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_combo_audio_rate1.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate1.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab1.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab1.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate2.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate2.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab2.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab2.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate3.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate3.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab3.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab3.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate4.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate4.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab4.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab4.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate5.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate5.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab5.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab5.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate6.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate6.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab6.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab6.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_audio_rate7.setItemText(0, _translate("MainWindow", "32 kHz", None)) + self.t_combo_audio_rate7.setItemText(1, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab7.setItemText(0, _translate("MainWindow", "48 kHz", None)) + self.t_combo_audio_rate_dab7.setItemText(1, _translate("MainWindow", "24 kHz", None)) self.t_label_increase_num_subch_info.setText(_translate("MainWindow", "increase \"Number of channels\" for more components", None)) self.label_12.setText(_translate("MainWindow", "Ensemble info", None)) self.label_13.setText(_translate("MainWindow", "Label", None)) self.t_edit_ensemble_label.setText(_translate("MainWindow", "Galaxy News", None)) self.label_14.setText(_translate("MainWindow", "Country", None)) self.label_15.setText(_translate("MainWindow", "Service", None)) - self.label_16.setText(_translate("MainWindow", "Label", None)) - self.t_edit_service_label.setText(_translate("MainWindow", "Wasteland Radio", None)) self.label_17.setText(_translate("MainWindow", "Number of channels", None)) self.label_23.setText(_translate("MainWindow", "Language", None)) self.t_btn_init.setText(_translate("MainWindow", "start transmitter", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 30a8001c..a5c9bc01 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true - 0 + 1 @@ -1148,9 +1148,9 @@ 0 - 0 + -1028 525 - 1269 + 1514 @@ -1220,14 +1220,14 @@ - + Audio Source - + @@ -1308,7 +1308,7 @@ - + true @@ -1325,14 +1325,14 @@ - + Data rate [kbit/s] - + 999 @@ -1342,21 +1342,21 @@ - + Protection Mode - + Audio Source - + @@ -1410,7 +1410,7 @@ - + true @@ -1427,14 +1427,14 @@ - + Data rate [kbit/s] - + 999 @@ -1444,21 +1444,21 @@ - + Protection Mode - + Audio Source - + @@ -1512,7 +1512,7 @@ - + @@ -1526,14 +1526,14 @@ - + Data rate [kbit/s] - + 999 @@ -1543,21 +1543,21 @@ - + Protection Mode - + Audio Source - + @@ -1611,7 +1611,7 @@ - + @@ -1625,14 +1625,14 @@ - + Data rate [kbit/s] - + 999 @@ -1642,21 +1642,21 @@ - + Protection Mode - + Audio Source - + @@ -1710,7 +1710,7 @@ - + @@ -1724,14 +1724,14 @@ - + Data rate [kbit/s] - + 999 @@ -1741,21 +1741,21 @@ - + Protection Mode - + Audio Source - + @@ -1809,7 +1809,7 @@ - + @@ -1823,14 +1823,14 @@ - + Data rate [kbit/s] - + 999 @@ -1840,21 +1840,21 @@ - + Protection Mode - + Audio Source - + @@ -1915,42 +1915,42 @@ - + Name - + Name - + Name - + Name - + Name - + Name @@ -1960,22 +1960,22 @@ - + - + - + - + - + - + @@ -2009,7 +2009,7 @@ - + @@ -2040,7 +2040,7 @@ - + @@ -2071,7 +2071,7 @@ - + @@ -2102,7 +2102,7 @@ - + @@ -2133,7 +2133,7 @@ - + @@ -2164,7 +2164,7 @@ - + @@ -2219,7 +2219,7 @@ - + @@ -2243,7 +2243,7 @@ - + @@ -2267,7 +2267,7 @@ - + @@ -2291,7 +2291,7 @@ - + @@ -2315,7 +2315,7 @@ - + @@ -2339,7 +2339,7 @@ - + @@ -2363,6 +2363,279 @@ + + + + Audio sampling rate + + + + + + + Audio Sampling rate + + + + + + + Audio sampling rate + + + + + + + Audio sampling rate + + + + + + + audio sampling rate + + + + + + + Audio sampling rate + + + + + + + Audio sampling rate + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + + + + + + + + 32 kHz + + + + + 48 kHz + + + + + + + + + 48 kHz + + + + + 24 kHz + + + + + + @@ -2477,47 +2750,33 @@ - - - Label - - - - - - - Wasteland Radio - - - - Number of channels - + - 7 + 4 1 - + Language - + - + Qt::Vertical diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 1bf39c23..9066f3f0 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -30,7 +30,7 @@ class usrp_dab_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, audio_sampling_rates, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -77,17 +77,17 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label for i in range(0, self.num_subch): if not self.src_paths[i] is "mic": # source - self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], False) + self.msc_sources[i] = blocks.wavfile_source_make(self.src_paths[i], True) # float to short self.f2s_left_converters[i] = blocks.float_to_short_make(1, 32767) self.f2s_right_converters[i] = blocks.float_to_short_make(1, 32767) if self.dabplus_types[i] is 1: # mp4 encoder and Reed-Solomon encoder - self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, 32000, 1) + self.mp4_encoders[i] = dab.mp4_encode_sb_make(self.data_rates_n[i], 2, audio_sampling_rates[i], 1) self.rs_encoders[i] = dab.reed_solomon_encode_bb_make(self.data_rates_n[i]) else: # mp2 encoder - self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n[i], 2, 48000) + self.mp2_encoders[i] = dab.mp2_encode_sb_make(self.data_rates_n[i], 2, audio_sampling_rates[i]) # encoder self.msc_encoders[i] = dab.msc_encode(self.dp, self.data_rates_n[i], self.protections[i]) From abfdd1794a20d512398f26569efaa4310cdc6ba4 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 09:17:24 +0200 Subject: [PATCH 029/135] fix qa test qa_fic_encode --- python/qa_fic_encode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/qa_fic_encode.py b/python/qa_fic_encode.py index 67486f48..2894bf8e 100755 --- a/python/qa_fic_encode.py +++ b/python/qa_fic_encode.py @@ -43,7 +43,7 @@ def test_001_t (self): # source self.dp = dab_parameters(1, 208.064e6, True) - self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1", "musicmix", 4, [2], [15], [1]) + self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1 ", "musicmix", 4, [2], [15], [1]) # encoder self.fib_enc = fic_encode(self.dab_params) From 9940b0025ed61726b9c7b2902f69a79d5b40c96b Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 09:36:02 +0200 Subject: [PATCH 030/135] GUI: add reception stop button fixes #24 --- python/GUI/main.py | 55 +++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 26756c1c..d6fa9c33 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -52,6 +52,7 @@ def __init__(self, parent=None): self.recorder = False self.file_path = "None" self.src_is_USRP = True + self.receiver_running = False # table preparations header = self.table_mci.horizontalHeader() @@ -237,30 +238,38 @@ def set_file_path(self): self.label_path.setText(path) def init_receiver(self): - self.statusBar.showMessage("initializing receiver ...") - # stop any processes that access to an instance of usrp_dab_rx - self.snr_timer.stop() - self.firecode_timer.stop() - # check if file path is selected in case that file is the selected source - if (not self.src_is_USRP) and (self.file_path == "None"): - self.label_path.setStyleSheet('color: red') + if not self.receiver_running: + self.statusBar.showMessage("initializing receiver ...") + # stop any processes that access to an instance of usrp_dab_rx + self.snr_timer.stop() + self.firecode_timer.stop() + # check if file path is selected in case that file is the selected source + if (not self.src_is_USRP) and (self.file_path == "None"): + self.label_path.setStyleSheet('color: red') + else: + self.label_path.setStyleSheet('color: black') + # set up and start flowgraph + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver.start() + # status bar + self.statusBar.showMessage("Reception is running.") + # init dev mode + self.dev_mode_init() + # once scan ensemble automatically (after per clicking btn) + time.sleep(1) + self.update_service_info() + self.btn_update_info.setEnabled(True) + self.snr_update() + self.snr_timer.start(1000) + self.firecode_timer.start(120) + self.receiver_running = True + self.btn_init.setText("stop receiver") else: - self.label_path.setStyleSheet('color: black') - # set up and start flowgraph - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) - self.my_receiver.start() - # status bar - self.statusBar.showMessage("Reception is running.") - # init dev mode - self.dev_mode_init() - # once scan ensemble automatically (after per clicking btn) - time.sleep(1) - self.update_service_info() - self.btn_update_info.setEnabled(True) - self.snr_update() - self.snr_timer.start(1000) - self.firecode_timer.start(120) + self.my_receiver.stop() + self.receiver_running = False + self.btn_init.setText("start receiver") + self.statusBar.showMessage("Receiver stopped.") def update_service_info(self): # set status bar message From f73707b5e49239755d407986ba799b6dc902db2d Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 10:20:17 +0200 Subject: [PATCH 031/135] transmitter: enable mono audio sources fixes #25 --- python/GUI/main.py | 38 +++++++----- python/GUI/user_frontend.py | 64 +++++++++++++++++--- python/GUI/user_frontend.ui | 115 +++++++++++++++++++++++++++++++++--- python/GUI/usrp_dab_tx.py | 22 +++++-- 4 files changed, 204 insertions(+), 35 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index d6fa9c33..cc03b413 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -130,31 +130,31 @@ def __init__(self, parent=None): {"label": self.t_label_comp1, "data_rate_label": self.t_label_rate1, "data_rate": self.t_spin_rate1, "protection_label": self.t_label_prot1, "protection": self.t_combo_prot1, "enabled": True, "src_label": self.t_label_comp_src1, "src_path_disp": self.t_label_path_src1, - "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1, "audio_rate_label": self.t_label_audio_rate1, "combo_audio_rate": self.t_combo_audio_rate1, "combo_audio_rate_dab": self.t_combo_audio_rate_dab1}, + "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1, "audio_rate_label": self.t_label_audio_rate1, "combo_audio_rate": self.t_combo_audio_rate1, "combo_audio_rate_dab": self.t_combo_audio_rate_dab1, "combo_stereo": self.t_combo_stereo1}, {"label": self.t_label_comp2, "data_rate_label": self.t_label_rate2, "data_rate": self.t_spin_rate2, "protection_label": self.t_label_prot2, "protection": self.t_combo_prot2, "enabled": False, "src_label": self.t_label_comp_src2, "src_path_disp": self.t_label_path_src2, - "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2, "audio_rate_label": self.t_label_audio_rate2, "combo_audio_rate": self.t_combo_audio_rate2, "combo_audio_rate_dab": self.t_combo_audio_rate_dab2}, + "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2, "audio_rate_label": self.t_label_audio_rate2, "combo_audio_rate": self.t_combo_audio_rate2, "combo_audio_rate_dab": self.t_combo_audio_rate_dab2, "combo_stereo": self.t_combo_stereo2}, {"label": self.t_label_comp3, "data_rate_label": self.t_label_rate3, "data_rate": self.t_spin_rate3, "protection_label": self.t_label_prot3, "protection": self.t_combo_prot3, "enabled": False, "src_label": self.t_label_comp_src3, "src_path_disp": self.t_label_path_src3, - "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3, "audio_rate_label": self.t_label_audio_rate3, "combo_audio_rate": self.t_combo_audio_rate3, "combo_audio_rate_dab": self.t_combo_audio_rate_dab3}, + "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3, "audio_rate_label": self.t_label_audio_rate3, "combo_audio_rate": self.t_combo_audio_rate3, "combo_audio_rate_dab": self.t_combo_audio_rate_dab3, "combo_stereo": self.t_combo_stereo3}, {"label": self.t_label_comp4, "data_rate_label": self.t_label_rate4, "data_rate": self.t_spin_rate4, "protection_label": self.t_label_prot4, "protection": self.t_combo_prot4, "enabled": False, "src_label": self.t_label_comp_src4, "src_path_disp": self.t_label_path_src4, - "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4, "audio_rate_label": self.t_label_audio_rate4, "combo_audio_rate": self.t_combo_audio_rate4, "combo_audio_rate_dab": self.t_combo_audio_rate_dab4}, + "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4, "audio_rate_label": self.t_label_audio_rate4, "combo_audio_rate": self.t_combo_audio_rate4, "combo_audio_rate_dab": self.t_combo_audio_rate_dab4, "combo_stereo": self.t_combo_stereo4}, {"label": self.t_label_comp5, "data_rate_label": self.t_label_rate5, "data_rate": self.t_spin_rate5, "protection_label": self.t_label_prot5, "protection": self.t_combo_prot5, "enabled": False, "src_label": self.t_label_comp_src5, "src_path_disp": self.t_label_path_src5, - "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5, "audio_rate_label": self.t_label_audio_rate5, "combo_audio_rate": self.t_combo_audio_rate5, "combo_audio_rate_dab": self.t_combo_audio_rate_dab5}, + "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5, "audio_rate_label": self.t_label_audio_rate5, "combo_audio_rate": self.t_combo_audio_rate5, "combo_audio_rate_dab": self.t_combo_audio_rate_dab5, "combo_stereo": self.t_combo_stereo5}, {"label": self.t_label_comp6, "data_rate_label": self.t_label_rate6, "data_rate": self.t_spin_rate6, "protection_label": self.t_label_prot6, "protection": self.t_combo_prot6, "enabled": False, "src_label": self.t_label_comp_src6, "src_path_disp": self.t_label_path_src6, - "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6, "audio_rate_label": self.t_label_audio_rate6, "combo_audio_rate": self.t_combo_audio_rate6, "combo_audio_rate_dab": self.t_combo_audio_rate_dab6}, + "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6, "audio_rate_label": self.t_label_audio_rate6, "combo_audio_rate": self.t_combo_audio_rate6, "combo_audio_rate_dab": self.t_combo_audio_rate_dab6, "combo_stereo": self.t_combo_stereo6}, {"label": self.t_label_comp7, "data_rate_label": self.t_label_rate7, "data_rate": self.t_spin_rate7, "protection_label": self.t_label_prot7, "protection": self.t_combo_prot7, "enabled": False, "src_label": self.t_label_comp_src7, "src_path_disp": self.t_label_path_src7, - "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7, "audio_rate_label": self.t_label_audio_rate7, "combo_audio_rate": self.t_combo_audio_rate7, "combo_audio_rate_dab": self.t_combo_audio_rate_dab7}] + "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7, "audio_rate_label": self.t_label_audio_rate7, "combo_audio_rate": self.t_combo_audio_rate7, "combo_audio_rate_dab": self.t_combo_audio_rate_dab7, "combo_stereo": self.t_combo_stereo7}] # update service components initially to hide the service components 2-7 self.t_update_service_components() # provide suggestions for language combo box @@ -689,6 +689,7 @@ def t_update_service_components(self): component["audio_rate_label"].hide() component["combo_audio_rate"].hide() component["combo_audio_rate_dab"].hide() + component["combo_stereo"].hide() else: component["label"].show() component["data_rate_label"].show() @@ -703,6 +704,7 @@ def t_update_service_components(self): component["combo_dabplus"].show() component["btn_record"].show() component["audio_rate_label"].show() + component["combo_stereo"].show() if component["combo_dabplus"].currentIndex() is 0: component["combo_audio_rate"].show() component["combo_audio_rate_dab"].hide() @@ -714,19 +716,23 @@ def t_init_transmitter(self): self.statusBar.showMessage("initializing transmitter...") # boolean is set to True if info is missing to init the transmitter arguments_incomplete = False - # produce array for protection and data_rate and src_paths - protection_array = [None] * self.t_spin_num_subch.value() - data_rate_n_array = [None] * self.t_spin_num_subch.value() - audio_sampling_rate_array = [None] * self.t_spin_num_subch.value() - audio_paths = ["None"] * self.t_spin_num_subch.value() + # produce array for protection and data_rate and src_paths and stereo flags + num_subch = self.t_spin_num_subch.value() + protection_array = [None] * num_subch + data_rate_n_array = [None] * num_subch + audio_sampling_rate_array = [None] * num_subch + audio_paths = [None] * num_subch + stereo_flags = [None] * num_subch merged_service_string = "" - dabplus_types = [True] * self.t_spin_num_subch.value() - record_states = [False] * self.t_spin_num_subch.value() - for i in range(0, self.t_spin_num_subch.value()): + dabplus_types = [True] * num_subch + record_states = [False] * num_subch + for i in range(0, num_subch): # write array with protection modes protection_array[i] = self.components[i]["protection"].currentIndex() # write array with data rates data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # write stereo flags + stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() # write audio sampling rates in array if self.components[i]["combo_dabplus"].currentIndex() is 0: audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 @@ -770,7 +776,7 @@ def t_init_transmitter(self): str(self.t_edit_ensemble_label.text()), merged_service_string, self.t_combo_language.currentIndex(), - protection_array, data_rate_n_array, audio_sampling_rate_array, + protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, audio_paths, self.t_spin_listen_to_component.value(), self.t_rbtn_USRP.isChecked(), diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 7ab47eb7..bd7cb321 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -360,6 +360,7 @@ def setupUi(self, MainWindow): icon = QtGui.QIcon.fromTheme(_fromUtf8("network-receive")) self.btn_init.setIcon(icon) self.btn_init.setCheckable(False) + self.btn_init.setFlat(False) self.btn_init.setObjectName(_fromUtf8("btn_init")) self.horizontalLayout_26.addWidget(self.btn_init) self.btn_update_info = QtGui.QPushButton(self.tab_reception) @@ -1072,6 +1073,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(42, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate7) self.horizontalLayout_2 = QtGui.QHBoxLayout() self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) + self.t_combo_stereo1 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo1.setObjectName(_fromUtf8("t_combo_stereo1")) + self.t_combo_stereo1.addItem(_fromUtf8("")) + self.t_combo_stereo1.addItem(_fromUtf8("")) + self.horizontalLayout_2.addWidget(self.t_combo_stereo1) self.t_combo_audio_rate1 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate1.setObjectName(_fromUtf8("t_combo_audio_rate1")) self.t_combo_audio_rate1.addItem(_fromUtf8("")) @@ -1085,6 +1091,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(6, QtGui.QFormLayout.FieldRole, self.horizontalLayout_2) self.horizontalLayout_33 = QtGui.QHBoxLayout() self.horizontalLayout_33.setObjectName(_fromUtf8("horizontalLayout_33")) + self.t_combo_stereo2 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo2.setObjectName(_fromUtf8("t_combo_stereo2")) + self.t_combo_stereo2.addItem(_fromUtf8("")) + self.t_combo_stereo2.addItem(_fromUtf8("")) + self.horizontalLayout_33.addWidget(self.t_combo_stereo2) self.t_combo_audio_rate2 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate2.setObjectName(_fromUtf8("t_combo_audio_rate2")) self.t_combo_audio_rate2.addItem(_fromUtf8("")) @@ -1098,6 +1109,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.horizontalLayout_33) self.horizontalLayout_34 = QtGui.QHBoxLayout() self.horizontalLayout_34.setObjectName(_fromUtf8("horizontalLayout_34")) + self.t_combo_stereo3 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo3.setObjectName(_fromUtf8("t_combo_stereo3")) + self.t_combo_stereo3.addItem(_fromUtf8("")) + self.t_combo_stereo3.addItem(_fromUtf8("")) + self.horizontalLayout_34.addWidget(self.t_combo_stereo3) self.t_combo_audio_rate3 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate3.setObjectName(_fromUtf8("t_combo_audio_rate3")) self.t_combo_audio_rate3.addItem(_fromUtf8("")) @@ -1111,6 +1127,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(18, QtGui.QFormLayout.FieldRole, self.horizontalLayout_34) self.horizontalLayout_35 = QtGui.QHBoxLayout() self.horizontalLayout_35.setObjectName(_fromUtf8("horizontalLayout_35")) + self.t_combo_stereo4 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo4.setObjectName(_fromUtf8("t_combo_stereo4")) + self.t_combo_stereo4.addItem(_fromUtf8("")) + self.t_combo_stereo4.addItem(_fromUtf8("")) + self.horizontalLayout_35.addWidget(self.t_combo_stereo4) self.t_combo_audio_rate4 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate4.setObjectName(_fromUtf8("t_combo_audio_rate4")) self.t_combo_audio_rate4.addItem(_fromUtf8("")) @@ -1124,6 +1145,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(24, QtGui.QFormLayout.FieldRole, self.horizontalLayout_35) self.horizontalLayout_36 = QtGui.QHBoxLayout() self.horizontalLayout_36.setObjectName(_fromUtf8("horizontalLayout_36")) + self.t_combo_stereo5 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo5.setObjectName(_fromUtf8("t_combo_stereo5")) + self.t_combo_stereo5.addItem(_fromUtf8("")) + self.t_combo_stereo5.addItem(_fromUtf8("")) + self.horizontalLayout_36.addWidget(self.t_combo_stereo5) self.t_combo_audio_rate5 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate5.setObjectName(_fromUtf8("t_combo_audio_rate5")) self.t_combo_audio_rate5.addItem(_fromUtf8("")) @@ -1137,6 +1163,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(30, QtGui.QFormLayout.FieldRole, self.horizontalLayout_36) self.horizontalLayout_37 = QtGui.QHBoxLayout() self.horizontalLayout_37.setObjectName(_fromUtf8("horizontalLayout_37")) + self.t_combo_stereo6 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo6.setObjectName(_fromUtf8("t_combo_stereo6")) + self.t_combo_stereo6.addItem(_fromUtf8("")) + self.t_combo_stereo6.addItem(_fromUtf8("")) + self.horizontalLayout_37.addWidget(self.t_combo_stereo6) self.t_combo_audio_rate6 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate6.setObjectName(_fromUtf8("t_combo_audio_rate6")) self.t_combo_audio_rate6.addItem(_fromUtf8("")) @@ -1150,6 +1181,11 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(36, QtGui.QFormLayout.FieldRole, self.horizontalLayout_37) self.horizontalLayout_38 = QtGui.QHBoxLayout() self.horizontalLayout_38.setObjectName(_fromUtf8("horizontalLayout_38")) + self.t_combo_stereo7 = QtGui.QComboBox(self.scrollAreaWidgetContents) + self.t_combo_stereo7.setObjectName(_fromUtf8("t_combo_stereo7")) + self.t_combo_stereo7.addItem(_fromUtf8("")) + self.t_combo_stereo7.addItem(_fromUtf8("")) + self.horizontalLayout_38.addWidget(self.t_combo_stereo7) self.t_combo_audio_rate7 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_audio_rate7.setObjectName(_fromUtf8("t_combo_audio_rate7")) self.t_combo_audio_rate7.addItem(_fromUtf8("")) @@ -1473,37 +1509,51 @@ def retranslateUi(self, MainWindow): self.t_combo_prot7.setItemText(1, _translate("MainWindow", "A2", None)) self.t_combo_prot7.setItemText(2, _translate("MainWindow", "A3", None)) self.t_combo_prot7.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_label_audio_rate1.setText(_translate("MainWindow", "Audio sampling rate", None)) - self.t_label_audio_rate2.setText(_translate("MainWindow", "Audio Sampling rate", None)) - self.t_label_audio_rate3.setText(_translate("MainWindow", "Audio sampling rate", None)) - self.t_label_audio_rate4.setText(_translate("MainWindow", "Audio sampling rate", None)) - self.t_label_audio_rate5.setText(_translate("MainWindow", "audio sampling rate", None)) - self.t_label_audio_rate6.setText(_translate("MainWindow", "Audio sampling rate", None)) - self.t_label_audio_rate7.setText(_translate("MainWindow", "Audio sampling rate", None)) + self.t_label_audio_rate1.setText(_translate("MainWindow", "Audio settings", None)) + self.t_label_audio_rate2.setText(_translate("MainWindow", "Audio settings", None)) + self.t_label_audio_rate3.setText(_translate("MainWindow", "Audio sampling", None)) + self.t_label_audio_rate4.setText(_translate("MainWindow", "Audio sampling", None)) + self.t_label_audio_rate5.setText(_translate("MainWindow", "audio sampling", None)) + self.t_label_audio_rate6.setText(_translate("MainWindow", "Audio sampling", None)) + self.t_label_audio_rate7.setText(_translate("MainWindow", "Audio sampling", None)) + self.t_combo_stereo1.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo1.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate1.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate1.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab1.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab1.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo2.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo2.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate2.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate2.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab2.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab2.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo3.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo3.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate3.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate3.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab3.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab3.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo4.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo4.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate4.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate4.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab4.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab4.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo5.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo5.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate5.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate5.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab5.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab5.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo6.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo6.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate6.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate6.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab6.setItemText(0, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab6.setItemText(1, _translate("MainWindow", "24 kHz", None)) + self.t_combo_stereo7.setItemText(0, _translate("MainWindow", "stereo", None)) + self.t_combo_stereo7.setItemText(1, _translate("MainWindow", "mono", None)) self.t_combo_audio_rate7.setItemText(0, _translate("MainWindow", "32 kHz", None)) self.t_combo_audio_rate7.setItemText(1, _translate("MainWindow", "48 kHz", None)) self.t_combo_audio_rate_dab7.setItemText(0, _translate("MainWindow", "48 kHz", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index a5c9bc01..d1387a4a 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -777,6 +777,9 @@ false + + false + @@ -2366,54 +2369,68 @@ - Audio sampling rate + Audio settings - Audio Sampling rate + Audio settings - Audio sampling rate + Audio sampling - Audio sampling rate + Audio sampling - audio sampling rate + audio sampling - Audio sampling rate + Audio sampling - Audio sampling rate + Audio sampling + + + + + stereo + + + + + mono + + + + @@ -2446,6 +2463,20 @@ + + + + + stereo + + + + + mono + + + + @@ -2478,6 +2509,20 @@ + + + + + stereo + + + + + mono + + + + @@ -2510,6 +2555,20 @@ + + + + + stereo + + + + + mono + + + + @@ -2542,6 +2601,20 @@ + + + + + stereo + + + + + mono + + + + @@ -2574,6 +2647,20 @@ + + + + + stereo + + + + + mono + + + + @@ -2606,6 +2693,20 @@ + + + + + stereo + + + + + mono + + + + diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 9066f3f0..f87b82dd 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -30,7 +30,7 @@ class usrp_dab_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, audio_sampling_rates, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, stereo_flags, audio_sampling_rates, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -129,16 +129,28 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label if self.dabplus_types[i] is 1: if self.src_paths[i] is "mic": self.connect((self.recorder, 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i + 1)) - self.connect((self.recorder, 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + if stereo_flags[i] == 0: + self.connect((self.recorder, 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect(self.f2s_left_converters[i], (self.mp4_encoders[i], 1)) else: self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp4_encoders[i], 0), self.rs_encoders[i], self.msc_encoders[i], (self.mux, i+1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + if stereo_flags[i] == 0: + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp4_encoders[i], 1)) + else: + self.connect(self.f2s_left_converters[i], (self.mp4_encoders[i], 1)) else: self.connect((self.msc_sources[i], 0), self.f2s_left_converters[i], (self.mp2_encoders[i], 0), self.msc_encoders[i], (self.mux, i + 1)) - self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) + if stereo_flags[i] == 0: + self.connect((self.msc_sources[i], 1), self.f2s_right_converters[i], (self.mp2_encoders[i], 1)) + else: + self.connect(self.f2s_left_converters[i], (self.mp2_encoders[i], 1)) self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) - self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) + if use_usrp: + self.connect(self.mod, self.sink) + else: + self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) #self.connect((self.msc_sources[self.selected_audio-1], 1), self.gain_right, (self.audio, 1)) From 6b073d6ce1acd00f4b69c604fe11769f7fa9dd8e Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 10:29:15 +0200 Subject: [PATCH 032/135] GUI: prevent GUI from resizing when playing another service --- python/GUI/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index cc03b413..323bdace 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -391,7 +391,7 @@ def play_audio(self): dev_mode_opened = False if self.dev_mode_active: dev_mode_opened = True - self.dev_mode_close() + self.dev_mode_close() self.snr_timer.stop() self.firecode_timer.stop() self.my_receiver.stop() From 99504f3e28c2fff6f4e392157f199da7551a7e21 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 12:06:20 +0200 Subject: [PATCH 033/135] GUI: fix path for bitmaps (logo and LEDs) by using realpath --- python/GUI/main.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index 323bdace..2cfa5c91 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -25,8 +25,7 @@ def __init__(self, parent=None): self.screen_width = resolution_width self.screen_height = resolution_height # show logo if it exists - if os.path.exists("DAB_logo.png"): - self.label_logo.setText("") + self.label_logo.setText("") # tab definitions self.modes = {"rec": 0, "trans": 1, "dev": 2} From e08cee7f83e26d948ff76010bc4aa16ef8b6c72f Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 24 Aug 2017 15:45:51 +0200 Subject: [PATCH 034/135] transmitter: fix country ID encoding in fib_source closes #26 --- grc/dab_fib_source_b.xml | 5 +++++ include/dab/fib_source_b.h | 2 +- lib/fib_source_b_impl.cc | 16 +++++++++------- lib/fib_source_b_impl.h | 5 ++--- python/GUI/main.py | 2 +- python/GUI/user_frontend.py | 19 +++++-------------- python/GUI/user_frontend.ui | 22 ++++------------------ python/GUI/usrp_dab_tx.py | 4 ++-- python/qa_fib_source_b.py | 4 ++-- python/qa_fic_encode.py | 2 +- 10 files changed, 32 insertions(+), 49 deletions(-) diff --git a/grc/dab_fib_source_b.xml b/grc/dab_fib_source_b.xml index fe0efe38..4a25fef6 100644 --- a/grc/dab_fib_source_b.xml +++ b/grc/dab_fib_source_b.xml @@ -26,6 +26,11 @@ 4 + + Country ID + country_ID + int + Number sub-channels num_subch diff --git a/include/dab/fib_source_b.h b/include/dab/fib_source_b.h index 653c3c16..021b3b90 100644 --- a/include/dab/fib_source_b.h +++ b/include/dab/fib_source_b.h @@ -43,7 +43,7 @@ namespace gr { * class. dab::fib_source_b::make is the public interface for * creating new instances. */ - static sptr make(int transmission_mode, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); + static sptr make(int transmission_mode, int coutry_ID, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); }; } // namespace dab diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index 8d017827..d94278e3 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -67,7 +67,7 @@ namespace gr { /// SI-FIGs, ready to transmit ///////////////////////////////////////////// //Ensemble label - char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, @@ -77,7 +77,7 @@ namespace gr { 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}; - //"001 10101 0000 0 000 0100 000000000000 01011111 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01001110 01100101 01110111 01110011 01011111 01011111 01011111 0011100011111000"; // Ensemble label: "__Galaxy_News___" + //"001 10101 0000 0 000 0000 000000000000 01011111 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01001110 01100101 01110111 01110011 01011111 01011111 01011111 0011100011111000"; // Ensemble label: "__Galaxy_News___" //Programme Service label char fib_source_b_impl::d_programme_service_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, @@ -99,12 +99,12 @@ namespace gr { //001 10101 0000 0 001 0100000000000000 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01010010 01100001 01100100 01101001 01101111 00110001 01011111 01011111 0111000111100100 fib_source_b::sptr - fib_source_b::make(int transmission_mode, int num_subch, std::string ensemble_label, + fib_source_b::make(int transmission_mode, int country_ID, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus) { return gnuradio::get_initial_sptr - (new fib_source_b_impl(transmission_mode, num_subch, ensemble_label, + (new fib_source_b_impl(transmission_mode, country_ID, num_subch, ensemble_label, programme_service_labels, service_comp_label, service_comp_lang, protection_mode, data_rate_n, dabplus)); } @@ -112,7 +112,7 @@ namespace gr { /* * The private constructor */ - fib_source_b_impl::fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, + fib_source_b_impl::fib_source_b_impl(int transmission_mode, int country_ID, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus) @@ -120,7 +120,7 @@ namespace gr { gr::io_signature::make(0, 0, 0), gr::io_signature::make(1, 1, sizeof(char))), d_transmission_mode(transmission_mode), d_num_subch(num_subch), d_nFIBs_written(0), - d_protection_mode(protection_mode), d_data_rate_n(data_rate_n), d_dabplus(dabplus) + d_protection_mode(protection_mode), d_data_rate_n(data_rate_n), d_dabplus(dabplus), d_country_ID(country_ID) { if (d_transmission_mode != 3) set_output_multiple((8 * FIB_LENGTH) * 3); else set_output_multiple((8 * FIB_LENGTH) * 4); @@ -291,7 +291,7 @@ namespace gr { d_subch_size = 4 * d_data_rate_n[subch_count]; break; default: - //fehler + //error break; } //write subchannel size @@ -323,6 +323,8 @@ namespace gr { // write ensemble label std::memcpy(out + d_offset, d_ensemble_label, d_size_label); d_offset += d_size_label; + // change country ID + bit_adaption(out + d_offset-(d_size_label-20), d_country_ID, 4); ++d_label_counter; } else{ diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index edbe727e..6cdb4af4 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -43,6 +43,7 @@ namespace gr { class fib_source_b_impl : public fib_source_b { private: int d_transmission_mode; //transmission mode + int d_country_ID; std::vector d_dabplus; int d_offset; uint16_t d_nFIBs_written; //counts totally written FIBs @@ -70,15 +71,13 @@ namespace gr { int d_label_counter; const static int d_size_label = 176; static char d_ensemble_label[176]; //21*8+8, ensemble label (FIG 1/0) - const static int d_size_ensemble_label = 176; static char d_programme_service_label[176]; //21*8+8, service label (FIG 1/0) - const static int d_size_service_label = 176; std::string d_service_labels; int write_label(char *out_ptr, std::string label, int num_chars = 16);//default for 16 characters (16 byte) public: - fib_source_b_impl(int transmission_mode, int num_subch, std::string ensemble_label, + fib_source_b_impl(int transmission_mode, int coutry_ID, int num_subch, std::string ensemble_label, std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); diff --git a/python/GUI/main.py b/python/GUI/main.py index 2cfa5c91..737ca384 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -774,7 +774,7 @@ def t_init_transmitter(self): self.t_spin_num_subch.value(), str(self.t_edit_ensemble_label.text()), merged_service_string, - self.t_combo_language.currentIndex(), + self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, audio_paths, self.t_spin_listen_to_component.value(), diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index bd7cb321..3487c4ff 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -1255,30 +1255,22 @@ def setupUi(self, MainWindow): self.line.setFrameShadow(QtGui.QFrame.Sunken) self.line.setObjectName(_fromUtf8("line")) self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - self.label_15 = QtGui.QLabel(self.tab_transmission) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.label_15.setFont(font) - self.label_15.setObjectName(_fromUtf8("label_15")) - self.formLayout_2.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_15) self.label_17 = QtGui.QLabel(self.tab_transmission) self.label_17.setObjectName(_fromUtf8("label_17")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_17) + self.formLayout_2.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_17) self.t_spin_num_subch = QtGui.QSpinBox(self.tab_transmission) self.t_spin_num_subch.setMaximum(4) self.t_spin_num_subch.setProperty("value", 1) self.t_spin_num_subch.setObjectName(_fromUtf8("t_spin_num_subch")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_spin_num_subch) + self.formLayout_2.setWidget(4, QtGui.QFormLayout.FieldRole, self.t_spin_num_subch) self.label_23 = QtGui.QLabel(self.tab_transmission) self.label_23.setObjectName(_fromUtf8("label_23")) - self.formLayout_2.setWidget(6, QtGui.QFormLayout.LabelRole, self.label_23) + self.formLayout_2.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_23) self.t_combo_language = QtGui.QComboBox(self.tab_transmission) self.t_combo_language.setObjectName(_fromUtf8("t_combo_language")) - self.formLayout_2.setWidget(6, QtGui.QFormLayout.FieldRole, self.t_combo_language) + self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_combo_language) spacerItem21 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(7, QtGui.QFormLayout.FieldRole, spacerItem21) + self.formLayout_2.setItem(6, QtGui.QFormLayout.FieldRole, spacerItem21) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -1563,7 +1555,6 @@ def retranslateUi(self, MainWindow): self.label_13.setText(_translate("MainWindow", "Label", None)) self.t_edit_ensemble_label.setText(_translate("MainWindow", "Galaxy News", None)) self.label_14.setText(_translate("MainWindow", "Country", None)) - self.label_15.setText(_translate("MainWindow", "Service", None)) self.label_17.setText(_translate("MainWindow", "Number of channels", None)) self.label_23.setText(_translate("MainWindow", "Language", None)) self.t_btn_init.setText(_translate("MainWindow", "start transmitter", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index d1387a4a..e09d4487 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -2837,27 +2837,13 @@ - - - - 13 - 75 - true - - - - Service - - - - Number of channels - + 4 @@ -2867,17 +2853,17 @@ - + Language - + - + Qt::Vertical diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index f87b82dd..d3dcdc93 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -30,7 +30,7 @@ class usrp_dab_tx(gr.top_block): - def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, protections, data_rates_n, stereo_flags, audio_sampling_rates, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): + def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label, language, country_ID, protections, data_rates_n, stereo_flags, audio_sampling_rates, src_paths, selected_audio, use_usrp, dabplus_types, sink_path = "dab_iq_generated.dat"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -59,7 +59,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label # FIC ######################## # source - self.fic_src = dab.fib_source_b_make(self.dab_mode, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n, self.dabplus_types) + self.fic_src = dab.fib_source_b_make(self.dab_mode, country_ID, self.num_subch, self.ensemble_label, self.service_label, "", self.language, self.protections, self.data_rates_n, self.dabplus_types) # encoder self.fic_enc = dab.fic_encode(self.dp) diff --git a/python/qa_fib_source_b.py b/python/qa_fib_source_b.py index 22ac34a2..2843ab6c 100755 --- a/python/qa_fib_source_b.py +++ b/python/qa_fib_source_b.py @@ -34,7 +34,7 @@ def tearDown (self): # manual check if transmitted data is interpreted properly # trivial fib_source with only one sub-channel def test_001_t(self): - src = dab.fib_source_b_make(1,1,'Galaxy_News', 'Wasteland_Radio', 'Country_Mix', 0x09, [0], [8], [1]) + src = dab.fib_source_b_make(1,1,1,'Galaxy_News', 'Wasteland_Radio', 'Country_Mix', 0x09, [0], [8], [1]) fib_unpacked_to_packed = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) s2v = blocks.stream_to_vector(gr.sizeof_char, 32) crc16 = dab.crc16_bb(32, 0x1021, 0xffff) @@ -45,7 +45,7 @@ def test_001_t(self): # multiple sub-channels def test_001_t(self): - src = dab.fib_source_b_make(1,7,'Galaxy_News', 'Wasteland_Radio1Wasteland_Radio2Wasteland_Radio3Wasteland_Radio4Wasteland_Radio5Wasteland_Radio6Wasteland_Radio7', 'Country_Mix', 0x09, [0, 1, 2, 3, 3, 2, 1], [8, 2, 8, 8, 2, 1, 4], [1, 1, 0, 1, 1, 0, 1]) + src = dab.fib_source_b_make(1,1,7,'Galaxy_News', 'Wasteland_Radio1Wasteland_Radio2Wasteland_Radio3Wasteland_Radio4Wasteland_Radio5Wasteland_Radio6Wasteland_Radio7', 'Country_Mix', 0x09, [0, 1, 2, 3, 3, 2, 1], [8, 2, 8, 8, 2, 1, 4], [1, 1, 0, 1, 1, 0, 1]) fib_unpacked_to_packed = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) s2v = blocks.stream_to_vector(gr.sizeof_char, 32) crc16 = dab.crc16_bb(32, 0x1021, 0xffff) diff --git a/python/qa_fic_encode.py b/python/qa_fic_encode.py index 2894bf8e..adb43e42 100755 --- a/python/qa_fic_encode.py +++ b/python/qa_fic_encode.py @@ -43,7 +43,7 @@ def test_001_t (self): # source self.dp = dab_parameters(1, 208.064e6, True) - self.fib_src = dab.fib_source_b_make(1, 1, "ensemble1", "service1 ", "musicmix", 4, [2], [15], [1]) + self.fib_src = dab.fib_source_b_make(1, 1, 1, "ensemble1", "service1 ", "musicmix", 4, [2], [15], [1]) # encoder self.fib_enc = fic_encode(self.dab_params) From c791166221d0f5cea0a43953328319b9047dab14 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 25 Aug 2017 17:50:26 +0200 Subject: [PATCH 035/135] app: add executable application DABstep --- CMakeLists.txt | 1 + apps/CMakeLists.txt | 1 + apps/DABstep | 1090 +++++++++++++++++++++++++++++++++++++ apps/usrp_dab_rx.py | 147 ----- apps/usrp_dab_tx.py | 91 ---- python/GUI/CMakeLists.txt | 37 ++ 6 files changed, 1129 insertions(+), 238 deletions(-) create mode 100755 apps/DABstep delete mode 100755 apps/usrp_dab_rx.py delete mode 100755 apps/usrp_dab_tx.py create mode 100644 python/GUI/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index e7aa9d45..f0266b8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,7 @@ add_subdirectory(include/dab) add_subdirectory(lib) add_subdirectory(swig) add_subdirectory(python) +add_subdirectory(python/GUI) add_subdirectory(grc) add_subdirectory(apps) add_subdirectory(docs) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index c837d77f..3c68d9a0 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -21,5 +21,6 @@ include(GrPython) GR_PYTHON_INSTALL( PROGRAMS + DABstep DESTINATION bin ) diff --git a/apps/DABstep b/apps/DABstep new file mode 100755 index 00000000..6818e100 --- /dev/null +++ b/apps/DABstep @@ -0,0 +1,1090 @@ +#!/usr/bin/env python + +from PyQt4 import QtGui +from PyQt4.QtCore import QTimer +import sys +import time +import dab.user_frontend as user_frontend +import dab.usrp_dab_rx as usrp_dab_rx +import dab.usrp_dab_tx as usrp_dab_tx +import math +import json +import sip +import os + +resolution_width = 0 +resolution_height = 0 + +class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): + def __init__(self, parent=None): + super(DABstep, self).__init__(parent) + self.setupUi(self) + self.resize(800, 600) + # window title + self.setWindowTitle("DABstep - A DAB/DAB+ transceiver app") + self.screen_width = resolution_width + self.screen_height = resolution_height + # show logo if it exists + post_path = os.path.join('share', 'gr-dab') + if os.environ.get('PYBOMBS_PREFIX'): + path = os.path.join(os.environ.get('PYBOMBS_PREFIX'), post_path) + else: + path = os.path.join('/usr', 'local', post_path) + self.path = path + self.label_logo.setText("") + + # tab definitions + self.modes = {"rec": 0, "trans": 1, "dev": 2} + self.mode = self.modes["rec"] + self.mode_tabs.currentChanged.connect(self.change_tab) + + # lookup table + self.table = lookup_tables() + + ###################################################################### + # TAB RECEPTION (defining variables, signals and slots) + ###################################################################### + # receiver variables + self.bit_rate = 8 + self.address = 0 + self.size = 6 + self.protection = 2 + self.audio_bit_rate = 16000 + self.volume = 80 + self.subch = -1 + self.dabplus = True + self.need_new_init = True + self.recorder = False + self.file_path = "None" + self.src_is_USRP = True + self.receiver_running = False + + # table preparations + header = self.table_mci.horizontalHeader() + header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents) + header.setResizeMode(1, QtGui.QHeaderView.Stretch) + header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents) + header.setResizeMode(3, QtGui.QHeaderView.ResizeToContents) + header.setStretchLastSection(False) + self.table_mci.verticalHeader().hide() + self.table_mci.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) + + # timer for update of SNR + self.snr_timer = QTimer() + self.snr_timer.timeout.connect(self.snr_update) + # change of source by radio buttons + self.rbtn_USRP.clicked.connect(self.src2USRP) + self.rbtn_File.clicked.connect(self.src2File) + # set file path + self.btn_file_path.clicked.connect(self.set_file_path) + # init button initializes receiver with center frequency + self.btn_init.clicked.connect(self.init_receiver) + # update button updates services in table + self.btn_update_info.clicked.connect(self.update_service_info) + # a click on a cell of the service table let the text box show more info to the selected service + self.table_mci.cellClicked.connect(self.selected_subch) + # a click on the play button compiles receiver with new subch info and plays the audio + self.btn_play.clicked.connect(self.play_audio) + # adjust audio sampling rate + self.timer_audio_sampling_rate = QTimer() + self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) + # stop button click stops audio reception + self.btn_stop.clicked.connect(self.stop_reception) + # volume slider moved + self.slider_volume.valueChanged.connect(self.set_volume) + # record button + self.btn_record.clicked.connect(self.record_audio) + + ###################################################################### + # DEVELOPER MODE + ###################################################################### + self.dev_mode_active = False + # hide scroll area + self.dev_scroll_area.hide() + # hide close button and just show open button + self.btn_dev_mode_close.hide() + # dev mode open button pressed + self.btn_dev_mode_open.clicked.connect(self.dev_mode_open) + # dev mode close button pressed + self.btn_dev_mode_close.clicked.connect(self.dev_mode_close) + # firecode display + self.firecode_timer = QTimer() + self.firecode_timer.timeout.connect(self.update_firecode) + self.label_firecode.setText("") + self.label_fic.setText("") + font = QtGui.QFont() + font.setFamily("CourierNew") + self.label_firecode.setFont(font) + self.label_firecode.hide() + self.led_msc.hide() + self.label_label_msc.hide() + self.label_fic.setFont(font) + self.label_fic.hide() + self.led_fic.hide() + self.label_label_fic.hide() + self.content_count = 0 + + ###################################################################### + # TAB TRANSMISSION (defining variables, signals and slots) + ###################################################################### + # change of sink by radio buttons + self.t_rbtn_USRP.clicked.connect(self.t_set_sink_USRP) + self.t_rbtn_File.clicked.connect(self.t_set_sink_File) + # create dict for service components + self.components = [ + {"label": self.t_label_comp1, "data_rate_label": self.t_label_rate1, "data_rate": self.t_spin_rate1, + "protection_label": self.t_label_prot1, "protection": self.t_combo_prot1, "enabled": True, + "src_label": self.t_label_comp_src1, "src_path_disp": self.t_label_path_src1, + "src_btn": self.t_btn_path_src1, "src_path": "None", "label_label": self.t_label_label1, "edit_label": self.t_edit_service_label1, "combo_dabplus": self.t_combo_dabplus1, "btn_record": self.t_btn_record1, "audio_rate_label": self.t_label_audio_rate1, "combo_audio_rate": self.t_combo_audio_rate1, "combo_audio_rate_dab": self.t_combo_audio_rate_dab1, "combo_stereo": self.t_combo_stereo1}, + {"label": self.t_label_comp2, "data_rate_label": self.t_label_rate2, "data_rate": self.t_spin_rate2, + "protection_label": self.t_label_prot2, "protection": self.t_combo_prot2, "enabled": False, + "src_label": self.t_label_comp_src2, "src_path_disp": self.t_label_path_src2, + "src_btn": self.t_btn_path_src2, "src_path": "None", "label_label": self.t_label_label2, "edit_label": self.t_edit_service_label2, "combo_dabplus": self.t_combo_dabplus2, "btn_record": self.t_btn_record2, "audio_rate_label": self.t_label_audio_rate2, "combo_audio_rate": self.t_combo_audio_rate2, "combo_audio_rate_dab": self.t_combo_audio_rate_dab2, "combo_stereo": self.t_combo_stereo2}, + {"label": self.t_label_comp3, "data_rate_label": self.t_label_rate3, "data_rate": self.t_spin_rate3, + "protection_label": self.t_label_prot3, "protection": self.t_combo_prot3, "enabled": False, + "src_label": self.t_label_comp_src3, "src_path_disp": self.t_label_path_src3, + "src_btn": self.t_btn_path_src3, "src_path": "None", "label_label": self.t_label_label3, "edit_label": self.t_edit_service_label3, "combo_dabplus": self.t_combo_dabplus3, "btn_record": self.t_btn_record3, "audio_rate_label": self.t_label_audio_rate3, "combo_audio_rate": self.t_combo_audio_rate3, "combo_audio_rate_dab": self.t_combo_audio_rate_dab3, "combo_stereo": self.t_combo_stereo3}, + {"label": self.t_label_comp4, "data_rate_label": self.t_label_rate4, "data_rate": self.t_spin_rate4, + "protection_label": self.t_label_prot4, "protection": self.t_combo_prot4, "enabled": False, + "src_label": self.t_label_comp_src4, "src_path_disp": self.t_label_path_src4, + "src_btn": self.t_btn_path_src4, "src_path": "None", "label_label": self.t_label_label4, "edit_label": self.t_edit_service_label4, "combo_dabplus": self.t_combo_dabplus4, "btn_record": self.t_btn_record4, "audio_rate_label": self.t_label_audio_rate4, "combo_audio_rate": self.t_combo_audio_rate4, "combo_audio_rate_dab": self.t_combo_audio_rate_dab4, "combo_stereo": self.t_combo_stereo4}, + {"label": self.t_label_comp5, "data_rate_label": self.t_label_rate5, "data_rate": self.t_spin_rate5, + "protection_label": self.t_label_prot5, "protection": self.t_combo_prot5, "enabled": False, + "src_label": self.t_label_comp_src5, "src_path_disp": self.t_label_path_src5, + "src_btn": self.t_btn_path_src5, "src_path": "None", "label_label": self.t_label_label5, "edit_label": self.t_edit_service_label5, "combo_dabplus": self.t_combo_dabplus5, "btn_record": self.t_btn_record5, "audio_rate_label": self.t_label_audio_rate5, "combo_audio_rate": self.t_combo_audio_rate5, "combo_audio_rate_dab": self.t_combo_audio_rate_dab5, "combo_stereo": self.t_combo_stereo5}, + {"label": self.t_label_comp6, "data_rate_label": self.t_label_rate6, "data_rate": self.t_spin_rate6, + "protection_label": self.t_label_prot6, "protection": self.t_combo_prot6, "enabled": False, + "src_label": self.t_label_comp_src6, "src_path_disp": self.t_label_path_src6, + "src_btn": self.t_btn_path_src6, "src_path": "None", "label_label": self.t_label_label6, "edit_label": self.t_edit_service_label6, "combo_dabplus": self.t_combo_dabplus6, "btn_record": self.t_btn_record6, "audio_rate_label": self.t_label_audio_rate6, "combo_audio_rate": self.t_combo_audio_rate6, "combo_audio_rate_dab": self.t_combo_audio_rate_dab6, "combo_stereo": self.t_combo_stereo6}, + {"label": self.t_label_comp7, "data_rate_label": self.t_label_rate7, "data_rate": self.t_spin_rate7, + "protection_label": self.t_label_prot7, "protection": self.t_combo_prot7, "enabled": False, + "src_label": self.t_label_comp_src7, "src_path_disp": self.t_label_path_src7, + "src_btn": self.t_btn_path_src7, "src_path": "None", "label_label": self.t_label_label7, "edit_label": self.t_edit_service_label7, "combo_dabplus": self.t_combo_dabplus7, "btn_record": self.t_btn_record7, "audio_rate_label": self.t_label_audio_rate7, "combo_audio_rate": self.t_combo_audio_rate7, "combo_audio_rate_dab": self.t_combo_audio_rate_dab7, "combo_stereo": self.t_combo_stereo7}] + # update service components initially to hide the service components 2-7 + self.t_update_service_components() + # provide suggestions for language combo box + for i in range(0,len(self.table.languages)): + self.t_combo_language.addItem(self.table.languages[i]) + # provide suggestions for country combo box + for i in range(0,len(self.table.country_ID_ECC_E0)): + self.t_combo_country.addItem(self.table.country_ID_ECC_E0[i]) + # update dict "components" and display of service components if spinbox "number of channels" is changed + self.t_spin_num_subch.valueChanged.connect(self.t_change_num_subch) + # write ensemble/service info when init is pressed + self.t_btn_init.pressed.connect(self.t_init_transmitter) + # start flowgraph when play btn pressed + self.t_btn_play.pressed.connect(self.t_run_transmitter) + # stop button pressed + self.t_btn_stop.pressed.connect(self.t_stop_transmitter) + # path for File sink path + self.t_btn_file_path.pressed.connect(self.t_set_file_path) + # path selection for all 7 (possible) sub channels + self.t_btn_path_src1.pressed.connect(self.t_set_subch_path1) + self.t_btn_path_src2.pressed.connect(self.t_set_subch_path2) + self.t_btn_path_src3.pressed.connect(self.t_set_subch_path3) + self.t_btn_path_src4.pressed.connect(self.t_set_subch_path4) + self.t_btn_path_src5.pressed.connect(self.t_set_subch_path5) + self.t_btn_path_src6.pressed.connect(self.t_set_subch_path6) + self.t_btn_path_src7.pressed.connect(self.t_set_subch_path7) + self.t_btn_record1.pressed.connect(self.t_toggle_record1) + self.t_btn_record2.pressed.connect(self.t_toggle_record2) + self.t_btn_record3.pressed.connect(self.t_toggle_record3) + self.t_btn_record4.pressed.connect(self.t_toggle_record4) + self.t_btn_record5.pressed.connect(self.t_toggle_record5) + self.t_btn_record6.pressed.connect(self.t_toggle_record6) + self.t_btn_record7.pressed.connect(self.t_toggle_record7) + self.t_combo_dabplus1.currentIndexChanged.connect(self.change_audio_bit_rates1) + self.t_combo_dabplus2.currentIndexChanged.connect(self.change_audio_bit_rates2) + self.t_combo_dabplus3.currentIndexChanged.connect(self.change_audio_bit_rates3) + self.t_combo_dabplus4.currentIndexChanged.connect(self.change_audio_bit_rates4) + self.t_combo_dabplus5.currentIndexChanged.connect(self.change_audio_bit_rates5) + self.t_combo_dabplus6.currentIndexChanged.connect(self.change_audio_bit_rates6) + self.t_combo_dabplus7.currentIndexChanged.connect(self.change_audio_bit_rates7) + # set volume if volume slider is changed + self.t_slider_volume.valueChanged.connect(self.t_set_volume) + + ################################ + # general functions + ################################ + def change_tab(self): + if self.mode_tabs.currentWidget() is self.tab_transmission: + print "changed to transmission mode" + self.t_update_service_components() + + elif self.mode_tabs.currentWidget() is self.tab_reception: + print "changed to reception mode" + else: + print "changed to unknown tab" + + ################################ + # Receiver functions + ################################ + + def src2USRP(self): + # enable/disable buttons + self.btn_file_path.setEnabled(False) + self.label_path.setEnabled(False) + self.spinbox_frequency.setEnabled(True) + self.label_frequency.setEnabled(True) + self.src_is_USRP = True + + def src2File(self): + # enable/disable buttons + self.btn_file_path.setEnabled(True) + self.label_path.setEnabled(True) + self.spinbox_frequency.setEnabled(False) + self.label_frequency.setEnabled(False) + self.src_is_USRP = False + + def set_file_path(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a file with recorded IQ samples") + if path: # if user didn't pick a directory don't continue + self.file_path = str(path) + self.label_path.setText(path) + + def init_receiver(self): + if not self.receiver_running: + self.statusBar.showMessage("initializing receiver ...") + # stop any processes that access to an instance of usrp_dab_rx + self.snr_timer.stop() + self.firecode_timer.stop() + # check if file path is selected in case that file is the selected source + if (not self.src_is_USRP) and (self.file_path == "None"): + self.label_path.setStyleSheet('color: red') + else: + self.label_path.setStyleSheet('color: black') + # set up and start flowgraph + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + self.my_receiver.start() + # status bar + self.statusBar.showMessage("Reception is running.") + # init dev mode + self.dev_mode_init() + # once scan ensemble automatically (after per clicking btn) + time.sleep(1) + self.update_service_info() + self.btn_update_info.setEnabled(True) + self.snr_update() + self.snr_timer.start(1000) + self.firecode_timer.start(120) + self.receiver_running = True + self.btn_init.setText("stop receiver") + else: + self.my_receiver.stop() + self.receiver_running = False + self.btn_init.setText("start receiver") + self.statusBar.showMessage("Receiver stopped.") + + def update_service_info(self): + # set status bar message + self.statusBar.showMessage("Scanning ensemble...") + # remove all old data from table at first + while (self.table_mci.rowCount() > 0): + self.table_mci.removeRow(0) + + # get new data from fic_sink + service_data = self.get_service_info() + service_labels = self.get_service_labels() + + # write new data to table + for n, key in enumerate(sorted(service_data, key=lambda service_data: service_data['ID'])): + # add a new row + self.table_mci.insertRow(n) + # print ID in first collumn + self.table_mci.setItem(n, 0, QtGui.QTableWidgetItem(str(key['ID']))) + # print reference (later label) + self.table_mci.setItem(n, 1, QtGui.QTableWidgetItem(next((item for item in service_labels if item["reference"] == key['reference']), {'label':"not found"})['label'])) + # print type + self.table_mci.setItem(n, 3, QtGui.QTableWidgetItem("primary" if key['primary'] == True else "secondary")) + # print DAB Mode + self.table_mci.setItem(n, 2, QtGui.QTableWidgetItem(("DAB+" if key['DAB+'] == True else "DAB "))) + + # set number of sub channels + self.num_subch = self.table_mci.rowCount() + + # display ensemble info + ensemble_data = self.get_ensemble_info() + self.label_ensemble.setText(ensemble_data.keys()[0].strip()) + self.label_country.setText(str(self.table.country_ID_ECC_E0[int(ensemble_data.values()[0]['country_ID'])])) + self.lcd_number_num_subch.display(self.num_subch) + # status bar + self.statusBar.showMessage("Select a Service Component.") + + def selected_subch(self): + # enable/disable buttons + self.btn_play.setEnabled(True) + self.btn_record.setEnabled(True) + # new subch was selected + self.btn_play.setText("Play") + self.slider_volume.setEnabled(False) + + # get selected sub-channel by its ID + ID = self.table_mci.item(self.table_mci.currentRow(), 0).text() + # find related service reference to ID + reference = next((item for item in self.get_service_info() if item['ID'] == int(ID)), {'reference':-1})['reference'] + # get dicts to specific service and sub-channel + service_data = next((item for item in self.get_service_info() if item['ID'] == int(ID)), {"reference":-1, "ID": -1, "primary": True}) + service_label = next((item for item in self.get_service_labels() if item['reference'] == int(reference)), {"reference": -1, "label":"not found"}) + subch_data = next((item for item in self.get_subch_info() if item['ID'] == int(ID)), {"ID":-1, "address":0, "protection":0,"size":0}) + programme_type = next((item for item in self.get_programme_type() if item["reference"] == reference), {"programme_type":0}) + + # update sub-channel info for receiver + self.address = int(subch_data['address']) + self.size = int(subch_data['size']) + self.protection = int(subch_data['protection']) + conv_table = [12, 8, 6, 5] + self.bit_rate = self.size * 8/conv_table[self.protection] + self.dabplus = service_data['DAB+'] + if self.dabplus: + if self.bit_rate < 100: + self.audio_bit_rate = 48000 + else: + self.audio_bit_rate = 32000 + else: + self.audio_bit_rate = 48000 + + # display info to selected sub-channel + # service info + self.label_service.setText(service_label['label'].strip()) + self.label_bit_rate.setText(str(subch_data['size']*8/6) + " kbps") + # service component (=sub-channel) info + self.label_primary.setText(("primary" if service_data['primary'] == True else "secondary")) + self.label_dabplus.setText(("DAB+" if service_data['DAB+'] == True else "DAB")) + # programme type + if programme_type["programme_type"] is 0: + self.label_programme_type.setText("\n") + else: + self.label_programme_type.setText(self.table.programme_types[programme_type["programme_type"]] + "\n") + # status Bar + self.statusBar.showMessage("Play/Record the selected service component.") + + def snr_update(self): + print "update snr" + # display snr in progress bar if an instance of usrp_dab_rx is existing + if hasattr(self, 'my_receiver'): + SNR = self.my_receiver.get_snr() + if SNR > 10: + self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") + if SNR > 20: + SNR = 20 + elif 5 < SNR <= 10: + self.setStyleSheet("""QProgressBar::chunk { background: "yellow"; }""") + else: + self.setStyleSheet("""QProgressBar::chunk { background: "red"; }""") + if SNR < -20 or math.isnan(SNR): + SNR = -20 + self.bar_snr.setValue(SNR) + self.lcd_snr.display(SNR) + else: + self.bar_snr.setValue(-20) + self.label_snr.setText("SNR: no reception") + self.snr_timer.start(1000) + + def play_audio(self): + if not self.slider_volume.isEnabled(): + # play button pressed + self.btn_play.setText("Mute") + self.btn_stop.setEnabled(True) + self.slider_volume.setEnabled(True) + self.btn_update_info.setEnabled(True) + self.slider_volume.setValue(self.volume) + self.set_volume() + # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver + if self.subch is not self.table_mci.currentRow(): + self.subch = self.table_mci.currentRow() + dev_mode_opened = False + if self.dev_mode_active: + dev_mode_opened = True + self.dev_mode_close() + self.snr_timer.stop() + self.firecode_timer.stop() + self.my_receiver.stop() + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + + self.my_receiver.start() + self.statusBar.showMessage("Audio playing.") + self.dev_mode_init() + if dev_mode_opened: + self.dev_mode_open() + else: + # mute button pressed + self.btn_play.setText("Play") + self.volume = self.slider_volume.value() + self.slider_volume.setValue(0) + self.slider_volume.setEnabled(False) + self.set_volume() + self.need_new_init = False + # start timer for snr update again + self.snr_timer.start(1000) + self.firecode_timer.start(120) + # start audio sampling rate timer + self.timer_audio_sampling_rate.start(500) + + def adjust_audio_sampling_rate(self): + self.timer_audio_sampling_rate.stop() + new_sampling_rate = self.my_receiver.get_sample_rate() + print "key adjust" + if new_sampling_rate != self.audio_bit_rate and new_sampling_rate != -1: + self.audio_bit_rate = new_sampling_rate + self.statusBar.showMessage("Adjusting audio sampling rate to " + str(new_sampling_rate)) + self.my_receiver.stop() + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + + self.my_receiver.start() + elif new_sampling_rate == -1: + self.timer_audio_sampling_rate.start(200) + + def stop_reception(self): + # close dev mode + self.btn_dev_mode_close.hide() + self.btn_dev_mode_open.show() + self.btn_dev_mode_open.setEnabled(False) + # stop flowgraph + self.my_receiver.stop() + # enable/disable buttons + self.btn_stop.setEnabled(False) + self.btn_play.setText("Play") + self.btn_play.setEnabled(True) + self.slider_volume.setEnabled(False) + self.btn_update_info.setEnabled(False) + self.btn_record.setEnabled(True) + self.recorder = False + # stop snr updates because no flowgraph is running to measure snr + self.snr_timer.stop() + self.firecode_timer.stop() + self.statusBar.showMessage("Reception stopped.") + + def record_audio(self): + # enable/disable buttons + self.btn_record.setEnabled(False) + self.btn_play.setEnabled(False) + self.btn_stop.setEnabled(True) + self.recorder = True + # start flowgraph + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path, self.recorder) + + self.my_receiver.start() + self.statusBar.showMessage("Recording audio ...") + + def set_volume(self): + # map volume from [0:100] to [0:1] + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + + def get_ensemble_info(self): + self.json = self.my_receiver.get_ensemble_info() + if self.json is "": + return {"unknown":{"country_ID":0}} + else: + # load string (json) with ensemble info and convert it to dictionary + # string structure example: "{\"SWR_BW_N\":{\"country_ID\":1}}" + self.ensemble_info = json.loads(self.json) + json.dumps(self.ensemble_info) + return self.ensemble_info + + def get_service_info(self): + self.json = self.my_receiver.get_service_info() + if self.json is "": + return [] + else: + # load string (json) with MCI and convert it to array of dictionaries + self.service_info = json.loads(self.json) + # string structure example: "[{\"reference\":736,\"ID\":2,\"primary\":true},{\"reference\":736,\"ID\":3,\"primary\":false},{\"reference\":234,\"ID\":5,\"primary\":true}]" + json.dumps(self.service_info) + return self.service_info + + def get_service_labels(self): + self.json = self.my_receiver.get_service_labels() + if self.json is "": + return [] + else: + # load string (json) with service labels and convert it to array of dictionaries + self.service_labels = json.loads(self.json) + # string structure example: "[{\"label\":\"SWR1_BW \",\"reference\":736},{\"label\":\"SWR2 \",\"reference\":234}]" + json.dumps(self.service_labels) + return self.service_labels + + def get_subch_info(self): + self.json = self.my_receiver.get_subch_info() + if self.json is "": + return [] + else: + # load string (json) with sub-channel info and convert it to array of dictionaries + self.subch_info = json.loads(self.json) + # string structure example: "[{\"ID\":2, \"address\":54, \"protect\":2,\"size\":84},{\"ID\":3, \"address\":54, \"protect\":2,\"size\":84}]" + json.dumps(self.subch_info) + return self.subch_info + + def get_programme_type(self): + self.json = self.my_receiver.get_programme_type() + # load string (json) with service information (programme type) and convert it to array of dictionaries + if self.json == "": + return [] + else: + self.programme_type = json.loads(self.json) + # string structure example: "[{\"reference\":736, \"programme_type\":13},{\"reference\":234, \"programme_type\":0}]" + json.dumps(self.programme_type) + return self.programme_type + + def get_sample_rate(self): + # TODO: set rational resampler in flowgraoph with sample rate + return self.my_receiver.get_sample_rate() + + ################################ + # Developer Mode + ################################ + + def dev_mode_init(self): + available_height = self.screen_height-200 + # constellation plot + self.constellation = sip.wrapinstance(self.my_receiver.constellation_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.constellation) + self.constellation.setMaximumHeight(available_height/3) + self.constellation.setMaximumWidth(available_height/3*2) + self.constellation.hide() + # FFT plot + self.fft_plot = sip.wrapinstance(self.my_receiver.fft_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.fft_plot) + self.fft_plot.setMaximumHeight(available_height/3) + self.fft_plot.setMaximumWidth(available_height/3*2) + self.fft_plot.hide() + # Waterfall plot + self.waterfall_plot = sip.wrapinstance(self.my_receiver.waterfall_plot.pyqwidget(), QtGui.QWidget) + self.vertical_layout_dev_mode_right.addWidget(self.waterfall_plot) + self.waterfall_plot.setMaximumHeight(available_height/3) + self.waterfall_plot.setMaximumWidth(available_height/3*2) + self.waterfall_plot.hide() + # if dev mode is initialized, we can enable the dev mode open button + self.btn_dev_mode_open.setEnabled(True) + + def dev_mode_open(self): + self.dev_mode_active = True + self.dev_scroll_area.show() + # hide open button and show close button + self.btn_dev_mode_open.hide() + self.btn_dev_mode_close.show() + # show widgets + self.fft_plot.show() + self.waterfall_plot.show() + self.constellation.show() + self.label_firecode.show() + self.led_msc.setText("") + self.led_msc.show() + self.label_label_msc.show() + self.label_firecode.setText("") + self.label_fic.show() + self.led_fic.setText("") + self.led_fic.show() + self.label_label_fic.show() + self.label_fic.setText("") + self.content_count = 0 + # resize window width + self.showMaximized() + + def dev_mode_close(self): + self.dev_mode_active = False + self.dev_scroll_area.hide() + # hide close button and show open button + self.btn_dev_mode_close.hide() + self.btn_dev_mode_open.show() + # hide widgets + self.fft_plot.hide() + self.waterfall_plot.hide() + self.constellation.hide() + self.label_firecode.hide() + self.led_msc.hide() + self.label_label_msc.hide() + self.label_fic.hide() + self.led_fic.hide() + self.label_label_fic.hide() + self.resize(800, 600) + + def update_firecode(self): + if self.dev_mode_active: + if self.content_count >=80: + self.label_firecode.setText("") + self.label_fic.setText("") + self.content_count = 0 + # write msc status + if not self.my_receiver.get_firecode_passed(): + self.label_firecode.setText(self.label_firecode.text() + "X ") + self.led_msc.setText("") + else: + errors = self.my_receiver.get_corrected_errors() + if errors < 10: + self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + " < /font>") + self.led_msc.setText("") + else: + self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + "") + self.led_msc.setText("") + # write fic status + if self.my_receiver.get_crc_passed(): + self.label_fic.setText(self.label_fic.text() + "0 ") + self.led_fic.setText("") + else: + self.label_fic.setText(self.label_fic.text() + "X ") + self.led_fic.setText("") + self.label_fic.setWordWrap(True) + self.label_firecode.setWordWrap(True) + self.content_count += 1 + + ################################ + # Transmitter functions + ################################ + + def t_set_sink_USRP(self): + # enable/disable buttons + self.t_btn_file_path.setEnabled(False) + self.t_label_sink.setEnabled(False) + self.t_spinbox_frequency.setEnabled(True) + self.t_label_frequency.setEnabled(True) + + def t_set_sink_File(self): + # enable/disable buttons + self.t_btn_file_path.setEnabled(True) + self.t_label_sink.setEnabled(True) + self.t_spinbox_frequency.setEnabled(False) + self.t_label_frequency.setEnabled(False) + + def t_change_num_subch(self): + # get number of sub-channels from spin box + num_subch = self.t_spin_num_subch.value() + # update info text under the component fill in forms + if num_subch is 7: + self.t_label_increase_num_subch_info.setText("7 is the maximum number of components") + else: + self.t_label_increase_num_subch_info.setText("increase \"Number of channels\" for more components") + # enable num_subch fill in forms for sub-channels + if 0 <= num_subch <= 7: + for n in range(0, 7): + if n < num_subch: + self.components[n]["enabled"] = True + else: + self.components[n]["enabled"] = False + # display changes + self.t_update_service_components() + self.t_spin_listen_to_component.setMaximum(num_subch) + + def t_update_service_components(self): + # display/hide components referring to the info in components (dict) + for component in self.components: + if component["enabled"] is False: + component["label"].hide() + component["data_rate_label"].hide() + component["data_rate"].hide() + component["protection_label"].hide() + component["protection"].hide() + component["src_label"].hide() + component["src_path_disp"].hide() + component["src_btn"].hide() + component["label_label"].hide() + component["edit_label"].hide() + component["combo_dabplus"].hide() + component["btn_record"].hide() + component["audio_rate_label"].hide() + component["combo_audio_rate"].hide() + component["combo_audio_rate_dab"].hide() + component["combo_stereo"].hide() + else: + component["label"].show() + component["data_rate_label"].show() + component["data_rate"].show() + component["protection_label"].show() + component["protection"].show() + component["src_label"].show() + component["src_path_disp"].show() + component["src_btn"].show() + component["label_label"].show() + component["edit_label"].show() + component["combo_dabplus"].show() + component["btn_record"].show() + component["audio_rate_label"].show() + component["combo_stereo"].show() + if component["combo_dabplus"].currentIndex() is 0: + component["combo_audio_rate"].show() + component["combo_audio_rate_dab"].hide() + else: + component["combo_audio_rate_dab"].show() + component["combo_audio_rate"].hide() + + def t_init_transmitter(self): + self.statusBar.showMessage("initializing transmitter...") + # boolean is set to True if info is missing to init the transmitter + arguments_incomplete = False + # produce array for protection and data_rate and src_paths and stereo flags + num_subch = self.t_spin_num_subch.value() + protection_array = [None] * num_subch + data_rate_n_array = [None] * num_subch + audio_sampling_rate_array = [None] * num_subch + audio_paths = [None] * num_subch + stereo_flags = [None] * num_subch + merged_service_string = "" + dabplus_types = [True] * num_subch + record_states = [False] * num_subch + for i in range(0, num_subch): + # write array with protection modes + protection_array[i] = self.components[i]["protection"].currentIndex() + # write array with data rates + data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # write stereo flags + stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() + # write audio sampling rates in array + if self.components[i]["combo_dabplus"].currentIndex() is 0: + audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 + else: + audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 + # check audio paths + if self.components[i]["src_path"] is "None": + # highlight the path which is not selected + self.components[i]["src_path_disp"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("path " + str(i+1) + " not selected") + # check if length of label is <= 16 chars + elif len(str(self.components[i]["edit_label"].text())) > 16: + self.components[i]["edit_label"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("Warning: Label is longer than 16 characters!") + else: + audio_paths[i] = self.components[i]["src_path"] + # write service labels appended in one string + merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) + self.components[i]["edit_label"].setStyleSheet('color: black') + # write dabplus types + dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) + + # check if length of ensemble label is <= 16 chars + if len(str(self.t_edit_ensemble_label.text())) > 16: + self.t_edit_ensemble_label.setStyleSheet('color: red') + arguments_incomplete = True + else: + self.t_edit_ensemble_label.setStyleSheet('color: black') + # check if File path for sink is chosen if option enabled + if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): + self.t_label_sink.setStyleSheet('color: red') + arguments_incomplete = True + + if arguments_incomplete is False: + # init transmitter + self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), + self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + merged_service_string, + self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), + protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + dabplus_types, + str(self.t_label_sink.text()) + "/" + str( + self.t_edit_file_name.text())) + + # enable play button + self.t_btn_play.setEnabled(True) + self.t_label_status.setText("ready to transmit") + self.statusBar.showMessage("ready to transmit") + + def t_run_transmitter(self): + self.t_btn_stop.setEnabled(True) + self.t_slider_volume.setEnabled(True) + self.t_label_status.setText("transmitting...") + self.statusBar.showMessage("transmitting...") + self.my_transmitter.start() + + def t_set_volume(self): + self.my_transmitter.set_volume(float(self.t_slider_volume.value())/100) + + def t_stop_transmitter(self): + # stop flowgraph + self.my_transmitter.stop() + self.t_btn_stop.setEnabled(False) + self.t_slider_volume.setEnabled(False) + self.t_label_status.setText("not running") + self.statusBar.showMessage("Transmission stopped.") + + def t_set_file_path(self): + path = QtGui.QFileDialog.getExistingDirectory(self, "Pick a folder for your file sink") + if path: # if user didn't pick a directory don't continue + # display path in path label + self.t_label_sink.setText(path) + self.t_label_sink.setStyleSheet('color: black') + + def t_set_subch_path1(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[0]["src_path"] = str(path) + # display path in path label + self.components[0]["src_path_disp"].setText(path) + self.components[0]["src_path_disp"].setStyleSheet('color: black') + self.t_btn_record1.setFlat(False) + + def t_set_subch_path2(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[1]["src_path"] = str(path) + # display path in path label + self.components[1]["src_path_disp"].setText(path) + self.components[1]["src_path_disp"].setStyleSheet('color: black') + + def t_set_subch_path3(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[2]["src_path"] = str(path) + # display path in path label + self.components[2]["src_path_disp"].setText(path) + self.components[2]["src_path_disp"].setStyleSheet('color: black') + + def t_set_subch_path4(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[3]["src_path"] = str(path) + # display path in path label + self.components[3]["src_path_disp"].setText(path) + self.components[3]["src_path_disp"].setStyleSheet('color: black') + + def t_set_subch_path5(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[4]["src_path"] = str(path) + # display path in path label + self.components[4]["src_path_disp"].setText(path) + self.components[4]["src_path_disp"].setStyleSheet('color: black') + + def t_set_subch_path6(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[5]["src_path"] = str(path) + # display path in path label + self.components[5]["src_path_disp"].setText(path) + self.components[5]["src_path_disp"].setStyleSheet('color: black') + + def t_set_subch_path7(self): + path = QtGui.QFileDialog.getOpenFileName(self, "Pick a .wav file as audio source") + if path: # if user didn't pick a directory don't continue + # set new path in dict components + self.components[6]["src_path"] = str(path) + # display path in path label + self.components[6]["src_path_disp"].setText(path) + self.components[7]["src_path_disp"].setStyleSheet('color: black') + + def t_toggle_record1(self): + self.t_label_path_src1.setText("microphone") + self.components[0]["src_path"] = "mic" + + def t_toggle_record2(self): + self.t_label_path_src2.setText("microphone") + self.components[1]["src_path"] = "mic" + + def t_toggle_record3(self): + self.t_label_path_src3.setText("microphone") + self.components[2]["src_path"] = "mic" + + def t_toggle_record4(self): + self.t_label_path_src4.setText("microphone") + self.components[3]["src_path"] = "mic" + + def t_toggle_record5(self): + self.t_label_path_src5.setText("microphone") + self.components[4]["src_path"] = "mic" + + def t_toggle_record6(self): + self.t_label_path_src6.setText("microphone") + self.components[5]["src_path"] = "mic" + + def t_toggle_record7(self): + self.t_label_path_src7.setText("microphone") + self.components[6]["src_path"] = "mic" + + def change_audio_bit_rates1(self): + if self.t_combo_dabplus1.currentIndex() is 0: + self.t_combo_audio_rate1.show() + self.t_combo_audio_rate_dab1.hide() + else: + self.t_combo_audio_rate_dab1.show() + self.t_combo_audio_rate1.hide() + + def change_audio_bit_rates2(self): + if self.t_combo_dabplus2.currentIndex() is 0: + self.t_combo_audio_rate2.show() + self.t_combo_audio_rate_dab2.hide() + else: + self.t_combo_audio_rate_dab2.show() + self.t_combo_audio_rate2.hide() + + def change_audio_bit_rates3(self): + if self.t_combo_dabplus3.currentIndex() is 0: + self.t_combo_audio_rate3.show() + self.t_combo_audio_rate_dab3.hide() + else: + self.t_combo_audio_rate_dab3.show() + self.t_combo_audio_rate3.hide() + + def change_audio_bit_rates4(self): + if self.t_combo_dabplus4.currentIndex() is 0: + self.t_combo_audio_rate4.show() + self.t_combo_audio_rate_dab4.hide() + else: + self.t_combo_audio_rate_dab4.show() + self.t_combo_audio_rate4.hide() + + def change_audio_bit_rates5(self): + if self.t_combo_dabplus5.currentIndex() is 0: + self.t_combo_audio_rate5.show() + self.t_combo_audio_rate_dab5.hide() + else: + self.t_combo_audio_rate_dab5.show() + self.t_combo_audio_rate5.hide() + + def change_audio_bit_rates6(self): + if self.t_combo_dabplus6.currentIndex() is 0: + self.t_combo_audio_rate6.show() + self.t_combo_audio_rate_dab6.hide() + else: + self.t_combo_audio_rate_dab6.show() + self.t_combo_audio_rate6.hide() + + def change_audio_bit_rates7(self): + if self.t_combo_dabplus7.currentIndex() is 0: + self.t_combo_audio_rate7.show() + self.t_combo_audio_rate_dab7.hide() + else: + self.t_combo_audio_rate_dab7.show() + self.t_combo_audio_rate7.hide() + + +class lookup_tables: + languages = [ + "unknown language", + "Albanian", + "Breton", + "Catalan", + "Croatian", + "Welsh", + "Czech", + "Danish", + "German", + "English", + "Spanish", + "Esperanto", + "Estonian", + "Basque", + "Faroese", + "French", + "Frisian", + "Irish", + "Gaelic", + "Galician", + "Icelandic", + "Italian", + "Lappish", + "Latin", + "Latvian", + "Luxembourgian", + "Lithuanian", + "Hungarian", + "Maltese", + "Dutch", + "Norwegian", + "Occitan", + "Polish", + "Postuguese", + "Romanian", + "Romansh", + "Serbian", + "Slovak", + "Slovene", + "Finnish", + "Swedish", + "Tuskish", + "Flemish", + "Walloon" + ] + programme_types = [ + "No programme type", + "News", + "Current Affairs", + "Information", + "Sport", + "Education", + "Drama", + "Culture", + "Science", + "Varied", + "Pop Music", + "Rock Music", + "Easy Listening Music", + "Light Classical", + "Serious Classical", + "Other Music", + "Weather/meteorology", + "Finance/Business", + "Children's programmes", + "Social Affairs", + "Religion", + "Phone In", + "Travel", + "Leisure", + "Jazz Music", + "Country Music", + "National Music", + "Oldies Music", + "Folk Music", + "Documentary", + "None", + "None" + ] + country_ID_ECC_E0 = [ + "None", + "Germany", + "Algeria", + "Andorra", + "Israel", + "Italy", + "Belgium", + "Russian Federation", + "Azores (Portugal)", + "Albania", + "Austria", + "Hungary", + "Malta", + "Germany", + "Canaries (Spain)", + "Egypt" + ] + protection_EEP_set_A = [ + "1-A", + "2-A", + "3-A", + "4-A" + ] + +def main(): + app = QtGui.QApplication(sys.argv) + global resolution_width + resolution_width = app.desktop().screenGeometry().width() + global resolution_height + resolution_height = app.desktop().screenGeometry().height() + + form = DABstep() + form.show() + app.exec_() + + +if __name__ == '__main__': + main() diff --git a/apps/usrp_dab_rx.py b/apps/usrp_dab_rx.py deleted file mode 100755 index 04168e84..00000000 --- a/apps/usrp_dab_rx.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf8 -*- - -# Andreas Müller, 2008 -# andrmuel@ee.ethz.ch -# -# this code may be freely used under GNU GPL conditions - -""" -receive DAB with USRP -""" - -from gnuradio import gr, uhd, blocks -import dab -from gnuradio.eng_option import eng_option -from optparse import OptionParser -import sys, time, threading, math - -class usrp_dab_rx(gr.top_block): - def __init__(self): - gr.top_block.__init__(self) - - - parser = OptionParser(option_class=eng_option, usage="%prog: [options] output-filename") - parser.add_option("-m", "--dab-mode", type="int", default=1, - help="DAB mode [default=%default]") - parser.add_option("-F", "--filter-input", action="store_true", default=False, - help="Enable FFT filter at input") - parser.add_option('-c', '--correct-ffe', action="store_true", default=False, - help="do fine frequency correction") - parser.add_option('-u', '--correct-ffe-usrp', action="store_true", default=False, - help="do fine frequency correction by retuning the USRP instead of in software") - parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False, - help="do magnitude equalization") - parser.add_option("-s", "--resample-fixed", type="eng_float", default=1, - help="resample by a fixed factor (fractional interpolation)") - parser.add_option("-S", "--autocorrect-sample-rate", action="store_true", default=False, - help="Estimate sample rate offset and resample (dynamic fractional interpolation)") - parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), - help="select USRP Rx side A or B [default=A]") - parser.add_option("-f", "--freq", type="eng_float", default=227.36e6, - help="set frequency to FREQ [default=%default]") - parser.add_option("-d", "--decim", type="intx", default=32, - help="set decimation rate to DECIM [default=%default]") - parser.add_option("-g", "--rx-gain", type="eng_float", default=None, - help="set receive gain in dB (default is midpoint)") - parser.add_option('-v', '--verbose', action="store_true", default=False, - help="verbose output") - parser.add_option('-a', '--antenna', type="string", default="TX/RX", - help="select antenna") - (options, args) = parser.parse_args () - - # if len(args)!=1: - # parser.print_help() - # sys.exit(1) - # else: - # self.filename = args[0] - - # if gr.enable_realtime_scheduling() != gr.RT_OK: - # print "-> failed to enable realtime scheduling" - - self.verbose = options.verbose - - self.src = uhd.usrp_source("",uhd.io_type.COMPLEX_FLOAT32,1) - #self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) - #self.subdev = uhd.selected_subdev(self.src, options.rx_subdev_spec) - #print "--> using RX dboard " + self.subdev.side_and_name() - - self.sample_rate = 2e6#self.src.adc_rate()/options.decim - self.src.set_samp_rate(self.sample_rate) - self.src.set_antenna(options.antenna) - self.dab_params = dab.parameters.dab_parameters(mode=options.dab_mode, sample_rate=self.sample_rate, verbose=options.verbose) - self.rx_params = dab.parameters.receiver_parameters(mode=options.dab_mode, softbits=True, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, verbose=options.verbose, correct_ffe=options.correct_ffe, equalize_magnitude=options.equalize_magnitude) - - self.demod = dab.ofdm_demod(self.dab_params, self.rx_params, verbose=options.verbose) - - # self.sink = gr.file_sink(gr.sizeof_char*384, self.filename) - # self.trigsink = gr.null_sink(gr.sizeof_char) - # self.connect(self.src, self.demod, self.sink) - # self.connect((self.demod,1), self.trigsink) - - self.fic_dec = dab.fic_decode(self.dab_params) - self.connect(self.src, self.demod, (self.fic_dec,0)) - self.connect((self.demod,1), (self.fic_dec,1)) - - # tune frequency - self.frequency = options.freq - self.set_freq(options.freq) - - # set gain - if options.rx_gain is None: - # if no gain was specified, use the mid-point in dB - g = self.src.get_gain_range() - options.rx_gain = float(g.start()+g.stop())/2 - self.src.set_gain(options.rx_gain) - #self.subdev.set_gain(options.rx_gain) - - self.update_ui = options.verbose - if self.update_ui: - self.run_ui_update_thread = True - self.ui_updater = threading.Timer(0.1,self.update_ui_function) - self.ui_updater.setDaemon(True) - self.ui_updater.start() - - self.correct_ffe_usrp = options.correct_ffe_usrp - if self.correct_ffe_usrp: - print "--> correcting FFE on USRP" - self.run_correct_ffe_thread = True - self.ffe_updater = threading.Timer(0.1, self.correct_ffe) - self.ffe_updater.setDaemon(True) - self.ffe_updater.start() - - def update_ui_function(self): - while self.run_ui_update_thread: - var = self.demod.probe_phase_var.level() - q = int(50*(math.sqrt(var)/(math.pi/4))) - print "--> Phase variance: " + str(var) +"\n" - print "--> Signal quality: " + '='*(50-q) + '>' + '-'*q + "\n" - time.sleep(0.3) - - def correct_ffe(self): - while self.run_correct_ffe_thread: - diff = self.demod.sync.ffs_sample_and_average_arg.ffe_estimate() - if abs(diff) > self.rx_params.usrp_ffc_min_deviation: - self.frequency -= diff*self.rx_params.usrp_ffc_adapt_factor - print "--> updating fine frequency correction: " + str(self.frequency) - self.set_freq(self.frequency) - time.sleep(1./self.rx_params.usrp_ffc_retune_frequency) - - def set_freq(self, freq): - if self.src.set_center_freq(freq): #src.tune(0, self.subdev, freq): - if self.verbose: - print "--> retuned to " + str(freq) + " Hz" - return True - else: - print "-> error - cannot tune to " + str(freq) + " Hz" - return False - -if __name__=='__main__': - try: - rx = usrp_dab_rx() - rx.run() - except KeyboardInterrupt: - pass - - - diff --git a/apps/usrp_dab_tx.py b/apps/usrp_dab_tx.py deleted file mode 100755 index 3c7da91c..00000000 --- a/apps/usrp_dab_tx.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf8 -*- - -# Andreas Müller, 2008 -# andrmuel@ee.ethz.ch -# -# this code may be freely used under GNU GPL conditions - -""" -send DAB with USRP -""" - -from gnuradio import gr, uhd, blocks -from gnuradio.eng_option import eng_option -import dab -from optparse import OptionParser -import sys - -class usrp_dab_tx(gr.top_block): - def __init__(self): - gr.top_block.__init__(self) - - - parser = OptionParser(option_class=eng_option, usage="%prog: [options] input-filename") - parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=(0, 0), - help="select USRP Tx side A or B [default=A]") - parser.add_option("-f", "--freq", type="eng_float", default=227.36e6, - help="set frequency to FREQ [default=%default]") - parser.add_option("-g", "--tx-gain", type="eng_float", default=None, - help="set transmit gain in dB (default is midpoint)") - parser.add_option('-v', '--verbose', action="store_true", default=False, - help="verbose output") - parser.add_option('-a', '--antenna', type="string", default="TX/RX", - help="select antenna") - - (options, args) = parser.parse_args () - if len(args)!=1: - parser.print_help() - sys.exit(1) - else: - self.filename = args[0] - - # if gr.enable_realtime_scheduling() != gr.RT_OK: - # print "-> failed to enable realtime scheduling" - - interp = 64 - self.sample_rate = 128e6/interp - self.dab_params = dab.parameters.dab_parameters(mode=1, sample_rate=2000000, verbose=options.verbose) - - self.src = blocks.file_source(gr.sizeof_char, "debug/generated_transmission_frame.dat") - self.trigsrc = blocks.vector_source_b([1]+[0]*(self.dab_params.symbols_per_frame-1),True) - - self.s2v = blocks.stream_to_vector(gr.sizeof_char, 384) - - self.mod = dab.ofdm_mod(self.dab_params, verbose=options.verbose) - - #self.sink = usrp.sink_c(interp_rate = interp) - self.sink = uhd.usrp_sink("",uhd.io_type.COMPLEX_FLOAT32,1) - self.sink.set_samp_rate(self.sample_rate) - #self.sink.set_mux(usrp.determine_tx_mux_value(self.sink, options.tx_subdev_spec)) - #self.subdev = usrp.selected_subdev(self.sink, options.tx_subdev_spec) - self.sink.set_antenna(options.antenna) - self.file_sink = blocks.file_sink_make(gr.sizeof_gr_complex, "debug/generated_iq_data.dat") - - print "--> using sample rate: " + str(self.sample_rate) - - - self.connect(self.src, self.s2v, self.mod, self.sink) - self.connect(self.trigsrc, (self.mod,1)) - self.connect(self.mod, self.file_sink) - self.connect(self.mod, self.sink) - - # tune frequency - self.sink.set_center_freq(options.freq) - - # set gain - if options.tx_gain is None: - # if no gain was specified, use the mid-point in dB - g = self.sink.get_gain_range() - options.tx_gain = float(g.start()+g.stop())/2 - self.sink.set_gain(options.tx_gain) - - -if __name__=='__main__': - try: - usrp_dab_tx().run() - except KeyboardInterrupt: - pass - - - diff --git a/python/GUI/CMakeLists.txt b/python/GUI/CMakeLists.txt new file mode 100644 index 00000000..e243f8bb --- /dev/null +++ b/python/GUI/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +include(GrPython) + +GR_PYTHON_INSTALL( + FILES + usrp_dab_rx.py + usrp_dab_tx.py + user_frontend.py + DESTINATION ${GR_PYTHON_DIR}/dab + COMPONENT "dab_python" +) +set(GR_PKG_DAB_DATA_DIR ${GR_PKG_DATA_DIR}) +install(FILES + DAB_logo.png + led_red.png + led_orange.png + led_green.png + DESTINATION ${GR_PKG_DAB_DATA_DIR} +) From f764a8fb66f4b42b3eddb0350feefdd0670f3346 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 25 Aug 2017 18:15:08 +0200 Subject: [PATCH 036/135] receiver: add valve_ff block to make the audio player control independent of the receiver control --- grc/CMakeLists.txt | 2 +- grc/dab_valve_ff.xml | 26 +++++++++++ include/dab/CMakeLists.txt | 2 +- include/dab/valve_ff.h | 58 ++++++++++++++++++++++++ lib/CMakeLists.txt | 2 +- lib/valve_ff_impl.cc | 93 ++++++++++++++++++++++++++++++++++++++ lib/valve_ff_impl.h | 58 ++++++++++++++++++++++++ python/CMakeLists.txt | 1 + python/qa_valve_ff.py | 58 ++++++++++++++++++++++++ swig/dab_swig.i | 3 ++ 10 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 grc/dab_valve_ff.xml create mode 100644 include/dab/valve_ff.h create mode 100644 lib/valve_ff_impl.cc create mode 100644 lib/valve_ff_impl.h create mode 100755 python/qa_valve_ff.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index de22f3b4..0c108ee8 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -70,5 +70,5 @@ install(FILES dab_reed_solomon_encode_bb.xml dab_mp4_encode_sb.xml dab_mp2_encode_sb.xml - DESTINATION share/gnuradio/grc/blocks + dab_valve_ff.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_valve_ff.xml b/grc/dab_valve_ff.xml new file mode 100644 index 00000000..69330dc8 --- /dev/null +++ b/grc/dab_valve_ff.xml @@ -0,0 +1,26 @@ + + Valve + dab_valve_ff + [DAB] + import dab + dab.valve_ff($closed, $feed_with_zeros) + + Closed + closed + raw + + + Feed with zeros + feed_with_zeros + false + raw + + + in + float + + + out + float + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 89ba4b26..6b315b70 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -64,5 +64,5 @@ install(FILES reed_solomon_encode_bb.h mp4_encode_sb.h mp2_encode_sb.h - DESTINATION include/dab + valve_ff.h DESTINATION include/dab ) diff --git a/include/dab/valve_ff.h b/include/dab/valve_ff.h new file mode 100644 index 00000000..debb71b6 --- /dev/null +++ b/include/dab/valve_ff.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_VALVE_FF_H +#define INCLUDED_DAB_VALVE_FF_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief lets samples pass or not depending on the state of closed + * \ingroup dab + * + */ + class DAB_API valve_ff : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::valve_ff. + * + * To avoid accidental use of raw pointers, dab::valve_ff's + * constructor is in a private implementation + * class. dab::valve_ff::make is the public interface for + * creating new instances. + */ + static sptr make(bool closed, bool feed_with_zeros = false); + virtual void set_closed(bool closed) = 0; + virtual void set_feed_with_zeros(bool feed_with_zeros) = 0; + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_VALVE_FF_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3d9fac3f..1566e671 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -93,7 +93,7 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/psycho_n1.c ${LIBTOOLAME-DAB_SOURCE_DIR}/encode_new.c ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c - ) + valve_ff_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/valve_ff_impl.cc b/lib/valve_ff_impl.cc new file mode 100644 index 00000000..8e43c40b --- /dev/null +++ b/lib/valve_ff_impl.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "valve_ff_impl.h" + +namespace gr { + namespace dab { + + valve_ff::sptr + valve_ff::make(bool closed, bool feed_with_zeros) + { + return gnuradio::get_initial_sptr + (new valve_ff_impl(closed, feed_with_zeros)); + } + + /* + * The private constructor + */ + valve_ff_impl::valve_ff_impl(bool closed, bool feed_with_zeros) + : gr::block("valve_ff", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(1, 1, sizeof(float))), + d_feed_with_zeros(feed_with_zeros), d_closed(closed) + {} + + /* + * Our virtual destructor. + */ + valve_ff_impl::~valve_ff_impl() + { + } + + void + valve_ff_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + valve_ff_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + if (d_closed){ + if (d_feed_with_zeros){ + // send zeros instead of the incoming floats as idle state + memset(out, 0, noutput_items * sizeof(float)); + consume_each (noutput_items); + return noutput_items; + } + else{ + // dump incoming frames and send nothing + consume_each (noutput_items); + return 0; + } + } + else{ + // valve opened, simply pass through the floats + memcpy(out, in, noutput_items * sizeof(float)); + consume_each (noutput_items); + return noutput_items; + } + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/valve_ff_impl.h b/lib/valve_ff_impl.h new file mode 100644 index 00000000..8294cbe8 --- /dev/null +++ b/lib/valve_ff_impl.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_VALVE_FF_IMPL_H +#define INCLUDED_DAB_VALVE_FF_IMPL_H + +#include + +namespace gr { + namespace dab { +/*! \brief lets samples pass or not depending on the state of closed + * @param feed_with_zeros if valve is closed feed_with_zeros decides if zeros are sent or nothing + * @param closed decides if valve is closed or opened + */ + class valve_ff_impl : public valve_ff + { + private: + bool d_feed_with_zeros; + bool d_closed; + + public: + valve_ff_impl(bool closed, bool feed_with_zeros); + ~valve_ff_impl(); + + // Where all the action really happens + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + void set_closed(bool closed) { d_closed = closed; } + void set_feed_with_zeros(bool feed_with_zeros) { d_feed_with_zeros = feed_with_zeros; } + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_VALVE_FF_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index d6466d8e..dfa68618 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -72,3 +72,4 @@ GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURC GR_ADD_TEST(qa_reed_solomon_encode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_reed_solomon_encode_bb.py) GR_ADD_TEST(qa_mp4_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp4_encode_sb.py) GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) +GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) diff --git a/python/qa_valve_ff.py b/python/qa_valve_ff.py new file mode 100755 index 00000000..f6da153c --- /dev/null +++ b/python/qa_valve_ff.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 <+YOU OR YOUR COMPANY+>. +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + +class qa_valve_ff (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + src_data = (1, 2, 3, 4) + expected_result = (1, 2, 3, 4) + src = blocks.vector_source_f(src_data) + valve = dab.valve_ff(False) + dst = blocks.vector_sink_f() + self.tb.connect(src, valve, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002_t (self): + src_data = (1, 2, 3, 4) + expected_result = (0, 0, 0, 0) + src = blocks.vector_source_f(src_data) + valve = dab.valve_ff(True, True) + dst = blocks.vector_sink_f() + self.tb.connect(src, valve, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.run(qa_valve_ff, "qa_valve_ff.xml") diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 2a579272..24c0950c 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -50,6 +50,7 @@ #include "dab/reed_solomon_encode_bb.h" #include "dab/mp4_encode_sb.h" #include "dab/mp2_encode_sb.h" +#include "dab/valve_ff.h" %} @@ -140,3 +141,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, mp4_encode_sb); %include "dab/mp2_encode_sb.h" GR_SWIG_BLOCK_MAGIC2(dab, mp2_encode_sb); +%include "dab/valve_ff.h" +GR_SWIG_BLOCK_MAGIC2(dab, valve_ff); From 94db7bf53bf80da0970c8514ff7137b336f2d019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Fri, 25 Aug 2017 19:03:51 +0200 Subject: [PATCH 037/135] externalized path to icons --- apps/DABstep | 18 +++++++----------- python/CMakeLists.txt | 15 ++++++++++++++- python/__init__.py | 1 + python/constants.py.in | 1 + 4 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 python/constants.py.in diff --git a/apps/DABstep b/apps/DABstep index 6818e100..6a8010b6 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -7,6 +7,7 @@ import time import dab.user_frontend as user_frontend import dab.usrp_dab_rx as usrp_dab_rx import dab.usrp_dab_tx as usrp_dab_tx +import dab.constants as constants import math import json import sip @@ -25,12 +26,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.screen_width = resolution_width self.screen_height = resolution_height # show logo if it exists - post_path = os.path.join('share', 'gr-dab') - if os.environ.get('PYBOMBS_PREFIX'): - path = os.path.join(os.environ.get('PYBOMBS_PREFIX'), post_path) - else: - path = os.path.join('/usr', 'local', post_path) - self.path = path + self.path = constants.icon_path self.label_logo.setText("") # tab definitions @@ -618,22 +614,22 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): # write msc status if not self.my_receiver.get_firecode_passed(): self.label_firecode.setText(self.label_firecode.text() + "X ") - self.led_msc.setText("") + self.led_msc.setText("") else: errors = self.my_receiver.get_corrected_errors() if errors < 10: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + " < /font>") - self.led_msc.setText("") + self.led_msc.setText("") else: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + "") - self.led_msc.setText("") + self.led_msc.setText("") # write fic status if self.my_receiver.get_crc_passed(): self.label_fic.setText(self.label_fic.text() + "0 ") - self.led_fic.setText("") + self.led_fic.setText("") else: self.label_fic.setText(self.label_fic.text() + "X ") - self.led_fic.setText("") + self.led_fic.setText("") self.label_fic.setWordWrap(True) self.label_firecode.setWordWrap(True) self.content_count += 1 diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index dfa68618..afe75f60 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -23,7 +23,19 @@ include(GrPython) if(NOT PYTHONINTERP_FOUND) return() -endif() + endif() + + +######################################################################## +# Insert ICON PATH macro Insert ICON PATH macro into constants.py +######################################################################## +set(GR_PKG_DAB_DATA_DIR ${GR_PKG_DATA_DIR}) +set(GR_DAB_ICON_PATH ${CMAKE_INSTALL_PREFIX}/${GR_PKG_DATA_DIR}) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/constants.py.in + ${CMAKE_CURRENT_BINARY_DIR}/constants.py + ESCAPE_QUOTES + @ONLY) ######################################################################## # Install python sources @@ -41,6 +53,7 @@ GR_PYTHON_INSTALL( fic_encode.py msc_encode.py transmitter_c.py + ${CMAKE_CURRENT_BINARY_DIR}/constants.py dabplus_audio_decoder_ff.py DESTINATION ${GR_PYTHON_DIR}/dab ) diff --git a/python/__init__.py b/python/__init__.py index ba997465..dfaae6f9 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -44,4 +44,5 @@ from msc_encode import msc_encode from transmitter_c import transmitter_c from dabplus_audio_decoder_ff import dabplus_audio_decoder_ff +import constants # diff --git a/python/constants.py.in b/python/constants.py.in new file mode 100644 index 00000000..f2506995 --- /dev/null +++ b/python/constants.py.in @@ -0,0 +1 @@ +image_path = "@GR_DAB_ICON_PATH@" From ac15d367f0c31884dc9f15a3959a0b8e0c7ae807 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 25 Aug 2017 19:25:50 +0200 Subject: [PATCH 038/135] fix typo in constants.py.in --- python/constants.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/constants.py.in b/python/constants.py.in index f2506995..2213fb80 100644 --- a/python/constants.py.in +++ b/python/constants.py.in @@ -1 +1 @@ -image_path = "@GR_DAB_ICON_PATH@" +icon_path = "@GR_DAB_ICON_PATH@" From 6228a4ba6a06fb66549e4560b783fae080232d17 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sun, 27 Aug 2017 21:34:07 +0200 Subject: [PATCH 039/135] GUI: make audio player independed of reception using volume= 0 for STOP and valve block for RECORD --- apps/DABstep | 148 +++++++++++++++----------------- python/GUI/main.py | 166 +++++++++++++++++------------------- python/GUI/user_frontend.py | 4 +- python/GUI/user_frontend.ui | 4 +- python/GUI/usrp_dab_rx.py | 27 ++++-- 5 files changed, 170 insertions(+), 179 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index 6a8010b6..35dd3a1c 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -11,7 +11,6 @@ import dab.constants as constants import math import json import sip -import os resolution_width = 0 resolution_height = 0 @@ -50,10 +49,11 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.subch = -1 self.dabplus = True self.need_new_init = True - self.recorder = False self.file_path = "None" self.src_is_USRP = True self.receiver_running = False + self.audio_playing = False + self.recording = False # table preparations header = self.table_mci.horizontalHeader() @@ -85,11 +85,13 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.timer_audio_sampling_rate = QTimer() self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) # stop button click stops audio reception - self.btn_stop.clicked.connect(self.stop_reception) + self.btn_stop.hide() + self.btn_stop.clicked.connect(self.stop_audio) # volume slider moved self.slider_volume.valueChanged.connect(self.set_volume) # record button self.btn_record.clicked.connect(self.record_audio) + self.btn_record.setCheckable(True) ###################################################################### # DEVELOPER MODE @@ -251,7 +253,8 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.label_path.setStyleSheet('color: black') # set up and start flowgraph self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) + self.src_is_USRP, self.file_path) + self.my_receiver.set_volume(0) self.my_receiver.start() # status bar self.statusBar.showMessage("Reception is running.") @@ -262,6 +265,11 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.update_service_info() self.btn_update_info.setEnabled(True) self.snr_update() + self.slider_volume.setEnabled(True) + self.btn_play.setEnabled(True) + self.btn_stop.setEnabled(True) + self.btn_update_info.setEnabled(True) + self.btn_record.setEnabled(True) self.snr_timer.start(1000) self.firecode_timer.start(120) self.receiver_running = True @@ -270,6 +278,14 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.my_receiver.stop() self.receiver_running = False self.btn_init.setText("start receiver") + self.slider_volume.setEnabled(False) + self.btn_play.setEnabled(False) + self.btn_stop.setEnabled(False) + self.btn_update_info.setEnabled(False) + self.btn_record.setEnabled(False) + self.btn_play.show() + self.btn_stop.hide() + self.audio_playing = False self.statusBar.showMessage("Receiver stopped.") def update_service_info(self): @@ -311,9 +327,9 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): # enable/disable buttons self.btn_play.setEnabled(True) self.btn_record.setEnabled(True) - # new subch was selected - self.btn_play.setText("Play") - self.slider_volume.setEnabled(False) + if self.audio_playing: + self.btn_stop.show() + self.btn_play.show() # get selected sub-channel by its ID ID = self.table_mci.item(self.table_mci.currentRow(), 0).text() @@ -378,48 +394,44 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.snr_timer.start(1000) def play_audio(self): - if not self.slider_volume.isEnabled(): - # play button pressed - self.btn_play.setText("Mute") - self.btn_stop.setEnabled(True) - self.slider_volume.setEnabled(True) - self.btn_update_info.setEnabled(True) - self.slider_volume.setValue(self.volume) - self.set_volume() - # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver - if self.subch is not self.table_mci.currentRow(): - self.subch = self.table_mci.currentRow() - dev_mode_opened = False - if self.dev_mode_active: - dev_mode_opened = True - self.dev_mode_close() - self.snr_timer.stop() - self.firecode_timer.stop() - self.my_receiver.stop() - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), - self.spinbox_frequency.value(), self.bit_rate, - self.address, self.size, - self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) - - self.my_receiver.start() - self.statusBar.showMessage("Audio playing.") - self.dev_mode_init() - if dev_mode_opened: - self.dev_mode_open() - else: - # mute button pressed - self.btn_play.setText("Play") - self.volume = self.slider_volume.value() - self.slider_volume.setValue(0) - self.slider_volume.setEnabled(False) - self.set_volume() - self.need_new_init = False + # play button pressed + # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver + if self.subch is not self.table_mci.currentRow(): + self.subch = self.table_mci.currentRow() + dev_mode_opened = False + if self.dev_mode_active: + dev_mode_opened = True + self.dev_mode_close() + self.snr_timer.stop() + self.firecode_timer.stop() + self.my_receiver.stop() + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path) + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + self.my_receiver.start() + self.statusBar.showMessage("Audio playing.") + self.dev_mode_init() + if dev_mode_opened: + self.dev_mode_open() + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + self.audio_playing = True # start timer for snr update again self.snr_timer.start(1000) self.firecode_timer.start(120) # start audio sampling rate timer self.timer_audio_sampling_rate.start(500) + # toggle start/stop button + self.btn_play.hide() + self.btn_stop.show() + + def stop_audio(self): + self.my_receiver.set_volume(0) + self.audio_playing = False + self.btn_play.show() + self.btn_stop.hide() def adjust_audio_sampling_rate(self): self.timer_audio_sampling_rate.stop() @@ -433,49 +445,27 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) + self.src_is_USRP, self.file_path) self.my_receiver.start() elif new_sampling_rate == -1: self.timer_audio_sampling_rate.start(200) - def stop_reception(self): - # close dev mode - self.btn_dev_mode_close.hide() - self.btn_dev_mode_open.show() - self.btn_dev_mode_open.setEnabled(False) - # stop flowgraph - self.my_receiver.stop() - # enable/disable buttons - self.btn_stop.setEnabled(False) - self.btn_play.setText("Play") - self.btn_play.setEnabled(True) - self.slider_volume.setEnabled(False) - self.btn_update_info.setEnabled(False) - self.btn_record.setEnabled(True) - self.recorder = False - # stop snr updates because no flowgraph is running to measure snr - self.snr_timer.stop() - self.firecode_timer.stop() - self.statusBar.showMessage("Reception stopped.") - def record_audio(self): - # enable/disable buttons - self.btn_record.setEnabled(False) - self.btn_play.setEnabled(False) - self.btn_stop.setEnabled(True) - self.recorder = True - # start flowgraph - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, - self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) - - self.my_receiver.start() - self.statusBar.showMessage("Recording audio ...") + if self.recording: + self.my_receiver.set_valve_closed(True) + self.recording = False + self.btn_record.setChecked(False) + + else: + self.my_receiver.set_valve_closed(False) + self.recording = True + self.btn_record.setChecked(True) def set_volume(self): - # map volume from [0:100] to [0:1] - self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + if self.audio_playing: + # map volume from [0:100] to [0:1] + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) def get_ensemble_info(self): self.json = self.my_receiver.get_ensemble_info() diff --git a/python/GUI/main.py b/python/GUI/main.py index 737ca384..dfe21939 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -7,10 +7,10 @@ import user_frontend import usrp_dab_rx import usrp_dab_tx +import dab.constants as constants import math import json import sip -import os resolution_width = 0 resolution_height = 0 @@ -25,7 +25,8 @@ def __init__(self, parent=None): self.screen_width = resolution_width self.screen_height = resolution_height # show logo if it exists - self.label_logo.setText("") + self.path = constants.icon_path + self.label_logo.setText("") # tab definitions self.modes = {"rec": 0, "trans": 1, "dev": 2} @@ -48,10 +49,11 @@ def __init__(self, parent=None): self.subch = -1 self.dabplus = True self.need_new_init = True - self.recorder = False self.file_path = "None" self.src_is_USRP = True self.receiver_running = False + self.audio_playing = False + self.recording = False # table preparations header = self.table_mci.horizontalHeader() @@ -83,11 +85,13 @@ def __init__(self, parent=None): self.timer_audio_sampling_rate = QTimer() self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) # stop button click stops audio reception - self.btn_stop.clicked.connect(self.stop_reception) + self.btn_stop.hide() + self.btn_stop.clicked.connect(self.stop_audio) # volume slider moved self.slider_volume.valueChanged.connect(self.set_volume) # record button self.btn_record.clicked.connect(self.record_audio) + self.btn_record.setCheckable(True) ###################################################################### # DEVELOPER MODE @@ -249,7 +253,8 @@ def init_receiver(self): self.label_path.setStyleSheet('color: black') # set up and start flowgraph self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) + self.src_is_USRP, self.file_path) + self.my_receiver.set_volume(0) self.my_receiver.start() # status bar self.statusBar.showMessage("Reception is running.") @@ -260,6 +265,11 @@ def init_receiver(self): self.update_service_info() self.btn_update_info.setEnabled(True) self.snr_update() + self.slider_volume.setEnabled(True) + self.btn_play.setEnabled(True) + self.btn_stop.setEnabled(True) + self.btn_update_info.setEnabled(True) + self.btn_record.setEnabled(True) self.snr_timer.start(1000) self.firecode_timer.start(120) self.receiver_running = True @@ -268,6 +278,14 @@ def init_receiver(self): self.my_receiver.stop() self.receiver_running = False self.btn_init.setText("start receiver") + self.slider_volume.setEnabled(False) + self.btn_play.setEnabled(False) + self.btn_stop.setEnabled(False) + self.btn_update_info.setEnabled(False) + self.btn_record.setEnabled(False) + self.btn_play.show() + self.btn_stop.hide() + self.audio_playing = False self.statusBar.showMessage("Receiver stopped.") def update_service_info(self): @@ -309,9 +327,9 @@ def selected_subch(self): # enable/disable buttons self.btn_play.setEnabled(True) self.btn_record.setEnabled(True) - # new subch was selected - self.btn_play.setText("Play") - self.slider_volume.setEnabled(False) + if self.audio_playing: + self.btn_stop.show() + self.btn_play.show() # get selected sub-channel by its ID ID = self.table_mci.item(self.table_mci.currentRow(), 0).text() @@ -376,48 +394,44 @@ def snr_update(self): self.snr_timer.start(1000) def play_audio(self): - if not self.slider_volume.isEnabled(): - # play button pressed - self.btn_play.setText("Mute") - self.btn_stop.setEnabled(True) - self.slider_volume.setEnabled(True) - self.btn_update_info.setEnabled(True) - self.slider_volume.setValue(self.volume) - self.set_volume() - # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver - if self.subch is not self.table_mci.currentRow(): - self.subch = self.table_mci.currentRow() - dev_mode_opened = False - if self.dev_mode_active: - dev_mode_opened = True - self.dev_mode_close() - self.snr_timer.stop() - self.firecode_timer.stop() - self.my_receiver.stop() - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), - self.spinbox_frequency.value(), self.bit_rate, - self.address, self.size, - self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) - - self.my_receiver.start() - self.statusBar.showMessage("Audio playing.") - self.dev_mode_init() - if dev_mode_opened: - self.dev_mode_open() - else: - # mute button pressed - self.btn_play.setText("Play") - self.volume = self.slider_volume.value() - self.slider_volume.setValue(0) - self.slider_volume.setEnabled(False) - self.set_volume() - self.need_new_init = False + # play button pressed + # if selected sub-channel is not the current sub-channel we have to reconfigure the receiver + if self.subch is not self.table_mci.currentRow(): + self.subch = self.table_mci.currentRow() + dev_mode_opened = False + if self.dev_mode_active: + dev_mode_opened = True + self.dev_mode_close() + self.snr_timer.stop() + self.firecode_timer.stop() + self.my_receiver.stop() + self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), + self.spinbox_frequency.value(), self.bit_rate, + self.address, self.size, + self.protection, self.audio_bit_rate, self.dabplus, + self.src_is_USRP, self.file_path) + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + self.my_receiver.start() + self.statusBar.showMessage("Audio playing.") + self.dev_mode_init() + if dev_mode_opened: + self.dev_mode_open() + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + self.audio_playing = True # start timer for snr update again self.snr_timer.start(1000) self.firecode_timer.start(120) # start audio sampling rate timer self.timer_audio_sampling_rate.start(500) + # toggle start/stop button + self.btn_play.hide() + self.btn_stop.show() + + def stop_audio(self): + self.my_receiver.set_volume(0) + self.audio_playing = False + self.btn_play.show() + self.btn_stop.hide() def adjust_audio_sampling_rate(self): self.timer_audio_sampling_rate.stop() @@ -431,49 +445,27 @@ def adjust_audio_sampling_rate(self): self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) + self.src_is_USRP, self.file_path) self.my_receiver.start() elif new_sampling_rate == -1: self.timer_audio_sampling_rate.start(200) - def stop_reception(self): - # close dev mode - self.btn_dev_mode_close.hide() - self.btn_dev_mode_open.show() - self.btn_dev_mode_open.setEnabled(False) - # stop flowgraph - self.my_receiver.stop() - # enable/disable buttons - self.btn_stop.setEnabled(False) - self.btn_play.setText("Play") - self.btn_play.setEnabled(True) - self.slider_volume.setEnabled(False) - self.btn_update_info.setEnabled(False) - self.btn_record.setEnabled(True) - self.recorder = False - # stop snr updates because no flowgraph is running to measure snr - self.snr_timer.stop() - self.firecode_timer.stop() - self.statusBar.showMessage("Reception stopped.") - def record_audio(self): - # enable/disable buttons - self.btn_record.setEnabled(False) - self.btn_play.setEnabled(False) - self.btn_stop.setEnabled(True) - self.recorder = True - # start flowgraph - self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, - self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path, self.recorder) - - self.my_receiver.start() - self.statusBar.showMessage("Recording audio ...") + if self.recording: + self.my_receiver.set_valve_closed(True) + self.recording = False + self.btn_record.setChecked(False) + + else: + self.my_receiver.set_valve_closed(False) + self.recording = True + self.btn_record.setChecked(True) def set_volume(self): - # map volume from [0:100] to [0:1] - self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) + if self.audio_playing: + # map volume from [0:100] to [0:1] + self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) def get_ensemble_info(self): self.json = self.my_receiver.get_ensemble_info() @@ -572,12 +564,12 @@ def dev_mode_open(self): self.waterfall_plot.show() self.constellation.show() self.label_firecode.show() - self.led_msc.setText("") + self.led_msc.setText("") self.led_msc.show() self.label_label_msc.show() self.label_firecode.setText("") self.label_fic.show() - self.led_fic.setText("") + self.led_fic.setText("") self.led_fic.show() self.label_label_fic.show() self.label_fic.setText("") @@ -612,22 +604,22 @@ def update_firecode(self): # write msc status if not self.my_receiver.get_firecode_passed(): self.label_firecode.setText(self.label_firecode.text() + "X ") - self.led_msc.setText("") + self.led_msc.setText("") else: errors = self.my_receiver.get_corrected_errors() if errors < 10: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + " < /font>") - self.led_msc.setText("") + self.led_msc.setText("") else: self.label_firecode.setText(self.label_firecode.text() + "" + str(errors) + "") - self.led_msc.setText("") + self.led_msc.setText("") # write fic status if self.my_receiver.get_crc_passed(): self.label_fic.setText(self.label_fic.text() + "0 ") - self.led_fic.setText("") + self.led_fic.setText("") else: self.label_fic.setText(self.label_fic.text() + "X ") - self.led_fic.setText("") + self.led_fic.setText("") self.label_fic.setWordWrap(True) self.label_firecode.setWordWrap(True) self.content_count += 1 diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 3487c4ff..17557942 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -394,7 +394,7 @@ def setupUi(self, MainWindow): self.btn_play.setObjectName(_fromUtf8("btn_play")) self.horizontalLayout_5.addWidget(self.btn_play) self.btn_stop = QtGui.QPushButton(self.tab_reception) - self.btn_stop.setEnabled(False) + self.btn_stop.setEnabled(True) icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-stop")) self.btn_stop.setIcon(icon) self.btn_stop.setObjectName(_fromUtf8("btn_stop")) @@ -1352,7 +1352,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(1) + self.mode_tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index e09d4487..3e40ff03 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true - 1 + 0 @@ -858,7 +858,7 @@ - false + true Stop diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 3ac3e25b..0f8986f3 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -32,7 +32,7 @@ class usrp_dab_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, record_audio = False, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, sink_path = "None"): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -41,7 +41,6 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.dabplus = dabplus self.use_usrp = use_usrp self.src_path = src_path - self.record_audio = record_audio self.sink_path = sink_path gr.log.set_level("warn") @@ -96,7 +95,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.fic_dec = dab.fic_decode(self.dab_params) ######################## - # MSC decoder and audio sink + # MSC decoder ######################## if self.dabplus: self.dabplus = dab.dabplus_audio_decoder_ff(self.dab_params, bit_rate, address, size, protection, True) @@ -108,7 +107,14 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.s2f_right = blocks.short_to_float_make(1, 32767) self.gain_left = blocks.multiply_const_ff(1, 1) self.gain_right = blocks.multiply_const_ff(1, 1) + + ######################## + # audio sink + ######################## + self.valve_left = dab.valve_ff_make(True) + self.valve_right= dab.valve_ff_make(True) self.audio = audio.sink_make(audio_bit_rate) + self.wav_sink = blocks.wavfile_sink_make("dab_audio.wav", 2, audio_bit_rate) ######################## # Connections @@ -126,18 +132,17 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) - # connect audio to sound card + # connect audio to sound card and file sink if self.dabplus: self.connect((self.dabplus, 0), (self.audio, 0)) self.connect((self.dabplus, 1), (self.audio, 1)) + self.connect((self.dabplus, 0), self.valve_left, (self.wav_sink, 0)) + self.connect((self.dabplus, 1), self.valve_right, (self.wav_sink, 1)) else: self.connect(self.gain_left, (self.audio, 0)) self.connect(self.gain_right, (self.audio, 1)) - # connect file sink if recording is selected - if self.record_audio: - self.sink = blocks.wavfile_sink_make("dab_audio.wav", 2, audio_bit_rate) - self.connect((self.dabplus, 0), (self.sink, 0)) - self.connect((self.dabplus, 1), (self.sink, 1)) + self.connect(self.gain_left, self.valve_left, (self.wav_sink, 0)) + self.connect(self.gain_right, self.valve_right, (self.wav_sink, 1)) # tune USRP frequency if self.use_usrp: @@ -191,6 +196,10 @@ def set_volume(self, volume): self.gain_left.set_k(volume) self.gain_right.set_k(volume) + def set_valve_closed(self, closed): + self.valve_left.set_closed(closed) + self.valve_right.set_closed(closed) + def set_freq(self, freq): if self.src.set_center_freq(freq): if self.verbose: From a2c413e5ac59c9498ff9c6ac189c37f19bcf2f48 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 28 Aug 2017 10:20:17 +0200 Subject: [PATCH 040/135] receiver: add peak_detector from gnuradio 3.7.10 --- grc/CMakeLists.txt | 3 +- grc/dab_peak_detector_fb.xml | 40 +++++++++++ include/dab/CMakeLists.txt | 3 +- include/dab/peak_detector_fb.h | 115 +++++++++++++++++++++++++++++++ lib/CMakeLists.txt | 3 +- lib/peak_detector_fb_impl.cc | 121 +++++++++++++++++++++++++++++++++ lib/peak_detector_fb_impl.h | 65 ++++++++++++++++++ python/CMakeLists.txt | 1 + python/detect_null.py | 4 +- python/qa_peak_detector_fb.py | 101 +++++++++++++++++++++++++++ swig/dab_swig.i | 3 + 11 files changed, 455 insertions(+), 4 deletions(-) create mode 100644 grc/dab_peak_detector_fb.xml create mode 100644 include/dab/peak_detector_fb.h create mode 100644 lib/peak_detector_fb_impl.cc create mode 100644 lib/peak_detector_fb_impl.h create mode 100755 python/qa_peak_detector_fb.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 0c108ee8..cd79e04b 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -70,5 +70,6 @@ install(FILES dab_reed_solomon_encode_bb.xml dab_mp4_encode_sb.xml dab_mp2_encode_sb.xml - dab_valve_ff.xml DESTINATION share/gnuradio/grc/blocks + dab_valve_ff.xml + dab_peak_detector_fb.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_peak_detector_fb.xml b/grc/dab_peak_detector_fb.xml new file mode 100644 index 00000000..545eb18b --- /dev/null +++ b/grc/dab_peak_detector_fb.xml @@ -0,0 +1,40 @@ + + + peak_detector_fb + dab_peak_detector_fb + dab + import dab + dab.peak_detector_fb($threshold_factor_rise, $threshold_factor_fall, $look_ahead, $alpha) + + TH Factor Rise + threshold_factor_rise + 0.25 + real + + + TH Factor Fall + threshold_factor_fall + 0.40 + real + + + Look Ahead + look_ahead + 10 + int + + + Alpha + alpha + 0.001 + real + + + in + float + + + out + byte + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 6b315b70..50993e5f 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -64,5 +64,6 @@ install(FILES reed_solomon_encode_bb.h mp4_encode_sb.h mp2_encode_sb.h - valve_ff.h DESTINATION include/dab + valve_ff.h + peak_detector_fb.h DESTINATION include/dab ) diff --git a/include/dab/peak_detector_fb.h b/include/dab/peak_detector_fb.h new file mode 100644 index 00000000..8d9e76b8 --- /dev/null +++ b/include/dab/peak_detector_fb.h @@ -0,0 +1,115 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_PEAK_DETECTOR_FB_H +#define INCLUDED_DAB_PEAK_DETECTOR_FB_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief Detect the peak of a signal + * \ingroup peak_detectors_blk + * + * \details + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. + */ + class DAB_API peak_detector_fb : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * Make a peak detector block. + * + * \param threshold_factor_rise The threshold factor determins + * when a peak has started. An average of the signal is + * calculated and when the value of the signal goes over + * threshold_factor_rise*average, we start looking for a + * peak. + * \param threshold_factor_fall The threshold factor determins + * when a peak has ended. An average of the signal is + * calculated and when the value of the signal goes + * below threshold_factor_fall*average, we stop looking + * for a peak. + * \param look_ahead The look-ahead value is used when the + * threshold is found to look if there another peak + * within this step range. If there is a larger value, + * we set that as the peak and look ahead again. This is + * continued until the highest point is found with This + * look-ahead range. + * \param alpha The gain value of a moving average filter + */ + static sptr make(float threshold_factor_rise = 0.25, + float threshold_factor_fall = 0.40, + int look_ahead = 10, + float alpha = 0.001); + + /*! \brief Set the threshold factor value for the rise time + * \param thr new threshold factor + */ + virtual void set_threshold_factor_rise(float thr) = 0; + + /*! \brief Set the threshold factor value for the fall time + * \param thr new threshold factor + */ + virtual void set_threshold_factor_fall(float thr) = 0; + + /*! \brief Set the look-ahead factor + * \param look new look-ahead factor + */ + virtual void set_look_ahead(int look) = 0; + + /*! \brief Set the running average alpha + * \param alpha new alpha for running average + */ + virtual void set_alpha(float alpha) = 0; + + /*! \brief Get the threshold factor value for the rise time + * \return threshold factor + */ + virtual float threshold_factor_rise() = 0; + + /*! \brief Get the threshold factor value for the fall time + * \return threshold factor + */ + virtual float threshold_factor_fall() = 0; + + /*! \brief Get the look-ahead factor value + * \return look-ahead factor + */ + virtual int look_ahead() = 0; + + /*! \brief Get the alpha value of the running average + * \return alpha + */ + virtual float alpha() = 0; + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_PEAK_DETECTOR_FB_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 1566e671..3992c30e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -93,7 +93,8 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/psycho_n1.c ${LIBTOOLAME-DAB_SOURCE_DIR}/encode_new.c ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c - valve_ff_impl.cc ) + valve_ff_impl.cc + peak_detector_fb_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/peak_detector_fb_impl.cc b/lib/peak_detector_fb_impl.cc new file mode 100644 index 00000000..87455460 --- /dev/null +++ b/lib/peak_detector_fb_impl.cc @@ -0,0 +1,121 @@ +/* -*- c++ -*- */ +/* This is a version of the GNU Radio peak_detector_fb block before commit 9d9ea63c45b5f314eb344a69340ef49e8edafdfa. + * + * Copyright 2007,2010,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "peak_detector_fb_impl.h" +#include + +namespace gr { + namespace dab { + + peak_detector_fb::sptr + peak_detector_fb::make(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha) + { + return gnuradio::get_initial_sptr + (new peak_detector_fb_impl(threshold_factor_rise, threshold_factor_fall, look_ahead, alpha)); + } + + /* + * The private constructor + */ + peak_detector_fb_impl::peak_detector_fb_impl(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha) + : gr::sync_block("peak_detector_fb", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(1, 1, sizeof(char))), + d_threshold_factor_rise(threshold_factor_rise), + d_threshold_factor_fall(threshold_factor_fall), + d_look_ahead(look_ahead), d_avg_alpha(alpha), d_avg(0), d_found(0) + {} + + /* + * Our virtual destructor. + */ + peak_detector_fb_impl::~peak_detector_fb_impl() + { + } + + int + peak_detector_fb_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + float *iptr = (float*)input_items[0]; + char *optr = (char*)output_items[0]; + + memset(optr, 0, noutput_items*sizeof(char)); + + float peak_val = -(float)INFINITY; + int peak_ind = 0; + unsigned char state = 0; + int i = 0; + + //printf("noutput_items %d\n",noutput_items); + while(i < noutput_items) { + if(state == 0) { // below threshold + if(iptr[i] > d_avg*d_threshold_factor_rise) { + state = 1; + } + else { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + } + else if(state == 1) { // above threshold, have not found peak + //printf("Entered State 1: %f i: %d noutput_items: %d\n", iptr[i], i, noutput_items); + if(iptr[i] > peak_val) { + peak_val = iptr[i]; + peak_ind = i; + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else if(iptr[i] > d_avg*d_threshold_factor_fall) { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else { + optr[peak_ind] = 1; + state = 0; + peak_val = -(float)INFINITY; + //printf("Leaving State 1: Peak: %f Peak Ind: %d i: %d noutput_items: %d\n", + //peak_val, peak_ind, i, noutput_items); + } + } + } + + if(state == 0) { + //printf("Leave in State 0, produced %d\n",noutput_items); + return noutput_items; + } + else { // only return up to passing the threshold + //printf("Leave in State 1, only produced %d of %d\n",peak_ind,noutput_items); + return peak_ind+1; + } + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/peak_detector_fb_impl.h b/lib/peak_detector_fb_impl.h new file mode 100644 index 00000000..f0429d96 --- /dev/null +++ b/lib/peak_detector_fb_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* This is a version of the GNU Radio peak_detector_fb block before commit 9d9ea63c45b5f314eb344a69340ef49e8edafdfa. + * + * Copyright 2007,2010,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_PEAK_DETECTOR_FB_IMPL_H +#define INCLUDED_DAB_PEAK_DETECTOR_FB_IMPL_H + +#include + +namespace gr { + namespace dab { + + class peak_detector_fb_impl : public peak_detector_fb + { + private: + float d_threshold_factor_rise; + float d_threshold_factor_fall; + int d_look_ahead; + float d_avg_alpha; + float d_avg; + unsigned char d_found; + + public: + peak_detector_fb_impl(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha); + ~peak_detector_fb_impl(); + + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + void set_threshold_factor_fall(float thr) { d_threshold_factor_fall = thr; } + void set_look_ahead(int look) { d_look_ahead = look; } + void set_alpha(float alpha) { d_avg_alpha = alpha; } + float threshold_factor_rise() { return d_threshold_factor_rise; } + float threshold_factor_fall() { return d_threshold_factor_fall; } + int look_ahead() { return d_look_ahead; } + float alpha() { return d_avg_alpha; } + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_PEAK_DETECTOR_FB_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index afe75f60..193482b1 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -86,3 +86,4 @@ GR_ADD_TEST(qa_reed_solomon_encode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURC GR_ADD_TEST(qa_mp4_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp4_encode_sb.py) GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) +GR_ADD_TEST(qa_peak_detector_fb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_peak_detector_fb.py) diff --git a/python/detect_null.py b/python/detect_null.py index 2f2ee27c..7772f31a 100644 --- a/python/detect_null.py +++ b/python/detect_null.py @@ -20,6 +20,8 @@ # Andreas Mueller, 2008 # andrmuel@ee.ethz.ch +# Moritz Luca Schmid, 2017 +# luca.m.schmid@gmail.com from gnuradio import gr, blocks from dab import dab_swig @@ -56,7 +58,7 @@ def __init__(self, length, debug=False): self.ns_invert = blocks.multiply_const_ff(-1) # peak detector on the inverted, summed up signal -> we get the nulls (i.e. the position of the start of a frame) - self.ns_peak_detect = blocks.peak_detector_fb(0.6,0.7,10,0.0001) # mostly found by try and error -> remember that the values are negative! + self.ns_peak_detect = dab_swig.peak_detector_fb(0.6,0.7,10,0.0001) # mostly found by try and error -> remember that the values are negative! # connect it all self.connect(self, self.ns_c2magsquared, self.ns_moving_sum, self.ns_invert, self.ns_peak_detect, self) diff --git a/python/qa_peak_detector_fb.py b/python/qa_peak_detector_fb.py new file mode 100755 index 00000000..71e77bf8 --- /dev/null +++ b/python/qa_peak_detector_fb.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2007,2010,2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + +class qa_peak_detector_fb (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_01(self): + tb = self.tb + + data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + + expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + + src = blocks.vector_source_f(data, False) + regen = blocks.peak_detector_fb() + dst = blocks.vector_sink_b() + + tb.connect(src, regen) + tb.connect(regen, dst) + tb.run() + + dst_data = dst.data() + + self.assertEqual(expected_result, dst_data) + + def test_02(self): + tb = self.tb + + data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + + expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + + src = blocks.vector_source_i(data, False) + regen = blocks.peak_detector_ib() + dst = blocks.vector_sink_b() + + tb.connect(src, regen) + tb.connect(regen, dst) + tb.run() + + dst_data = dst.data() + + self.assertEqual(expected_result, dst_data) + + def test_03(self): + tb = self.tb + + data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] + + expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + + src = blocks.vector_source_s(data, False) + regen = blocks.peak_detector_sb() + dst = blocks.vector_sink_b() + + tb.connect(src, regen) + tb.connect(regen, dst) + tb.run() + + dst_data = dst.data() + + self.assertEqual(expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.run(qa_peak_detector_fb, "qa_peak_detector_fb.xml") diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 24c0950c..16a9edc4 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -51,6 +51,7 @@ #include "dab/mp4_encode_sb.h" #include "dab/mp2_encode_sb.h" #include "dab/valve_ff.h" +#include "dab/peak_detector_fb.h" %} @@ -143,3 +144,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, mp2_encode_sb); %include "dab/valve_ff.h" GR_SWIG_BLOCK_MAGIC2(dab, valve_ff); +%include "dab/peak_detector_fb.h" +GR_SWIG_BLOCK_MAGIC2(dab, peak_detector_fb); From 89e608af8b51176b4ebbbb8eff2100639ce90bd0 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 28 Aug 2017 11:08:11 +0200 Subject: [PATCH 041/135] resolve #28 fic_encode test --- python/fic.py | 2 +- python/fic_encode.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/fic.py b/python/fic.py index 6a9524c6..0c2e0e3d 100644 --- a/python/fic.py +++ b/python/fic.py @@ -24,7 +24,7 @@ # andrmuel@ee.ethz.ch from gnuradio import gr, trellis, blocks -import dab +import dab_swig as dab from math import sqrt """ diff --git a/python/fic_encode.py b/python/fic_encode.py index bcca43fb..029d0f1d 100644 --- a/python/fic_encode.py +++ b/python/fic_encode.py @@ -21,7 +21,7 @@ from gnuradio import gr, blocks from gnuradio import fec -import dab +import dab_swig as dab class fic_encode(gr.hier_block2): """ From 6e38790a11a33da57d0f8157536f119dce6e88cc Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 28 Aug 2017 12:18:57 +0200 Subject: [PATCH 042/135] README: add GSoC section and add FAAD2 dependency --- README.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e2b00a83..83288110 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,17 @@ Contents 0: License -1: Installation +1: Google Summer of Code 2017 -2: Usage +2: Installation -3: Features +3: Usage -4: (Current) Constraints +4: Features -5: Known Bugs +5: (Current) Constraints + +6: Known Bugs License ------- @@ -35,6 +37,22 @@ 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 . +Google Summer of Code 2017 +------------ + +This repository is the result of the 2017 Google Summer of Code project "A DAB/DAB+ transceiver app" by Moritz Luca Schmid. It is a fork of the [gr-dab] (https://github.com/andrmuel/gr-dab) repository of Andreas Mueller which already contains the implementation of the DAB physical layer including OFDM. The following expanding work on gr-dab was done during GSoC 2017 by Moritz Luca Schmid: + +* FIC source and expand FIC sink (GNU Radio blocks) +* FIC encoder, including CRC, energy dispersal, convolutional encoding with puncturing (GNU Radio blocks) +* MSC encoder and decoder, including CRC, energy dispersal/descramble, convolutional encoding/decoding with puncturing, time interleaving/deinterleaving (GNU Radio blocks) +* DAB transmission frame multiplexer (GNU Radio blocks) +* MPEG Audio Layer II encoder/decoder for DAB tranmitter/receiver (GNU Radio blocks) +* HE-AAC v2 (mp4) encoder/decoder for DAB+ transmitter/receiver (GNU Radio blocks) +* Graphical user interface for DAB/DAB+ transmission/reception (pyQt4) +* "DABstep" as an executable application for DAB/DAB+ transmission/reception + +For more detailed information about the work which was done, containing changes in code and new code, check out the [commit history] (https://github.com/kit-cel/gr-dab/commits/master) of this repository. + Installation ------------ @@ -46,6 +64,8 @@ This package requires that GNU Radio is already installed. It also depends on some GNU Radio prerequisites, such as Boost and cppunit. +A dependency is the FAAD2 library. (ubuntu: sudo apt-get install libfaad-dev, fedora: sudo dnf install faad2-devel) + It also depends on fdk-aac with DAB patches (fdk-aac-dab). You'll find it in the eponymous subdirectory; build it using: From a96eb8f631af8cca006212140c46e904aa5e5efe Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 28 Aug 2017 16:54:31 +0200 Subject: [PATCH 043/135] README: embed links to GSoC blog and commit history --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83288110..0464adf7 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ along with this program. If not, see . Google Summer of Code 2017 ------------ -This repository is the result of the 2017 Google Summer of Code project "A DAB/DAB+ transceiver app" by Moritz Luca Schmid. It is a fork of the [gr-dab] (https://github.com/andrmuel/gr-dab) repository of Andreas Mueller which already contains the implementation of the DAB physical layer including OFDM. The following expanding work on gr-dab was done during GSoC 2017 by Moritz Luca Schmid: +This repository is the result of the 2017 Google Summer of Code project "A DAB/DAB+ transceiver app" by Moritz Luca Schmid. It is a fork of the [gr-dab](https://github.com/andrmuel/gr-dab) repository of Andreas Mueller which already contains the implementation of the DAB physical layer including OFDM. The following expanding work on gr-dab was done during GSoC 2017 by Moritz Luca Schmid: * FIC source and expand FIC sink (GNU Radio blocks) * FIC encoder, including CRC, energy dispersal, convolutional encoding with puncturing (GNU Radio blocks) @@ -51,7 +51,7 @@ This repository is the result of the 2017 Google Summer of Code project "A DAB/D * Graphical user interface for DAB/DAB+ transmission/reception (pyQt4) * "DABstep" as an executable application for DAB/DAB+ transmission/reception -For more detailed information about the work which was done, containing changes in code and new code, check out the [commit history] (https://github.com/kit-cel/gr-dab/commits/master) of this repository. +For more detailed information about the done work, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). Installation From 5ee89d39edf80d6138aff60da96ceb6a0b061a9a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 29 Aug 2017 11:50:03 +0200 Subject: [PATCH 044/135] README: add Ideas and Current Constraints --- README.md | 36 +++++++++++++++++++++++------------- examples/README | 2 ++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0464adf7..aece3240 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,11 @@ Contents 4: Features -5: (Current) Constraints +5: Current Constraints -6: Known Bugs +6: Ideas + +7: Known Bugs License ------- @@ -45,13 +47,15 @@ This repository is the result of the 2017 Google Summer of Code project "A DAB/D * FIC source and expand FIC sink (GNU Radio blocks) * FIC encoder, including CRC, energy dispersal, convolutional encoding with puncturing (GNU Radio blocks) * MSC encoder and decoder, including CRC, energy dispersal/descramble, convolutional encoding/decoding with puncturing, time interleaving/deinterleaving (GNU Radio blocks) -* DAB transmission frame multiplexer (GNU Radio blocks) +* DAB transmission frame multiplexer (GNU Radio block) * MPEG Audio Layer II encoder/decoder for DAB tranmitter/receiver (GNU Radio blocks) * HE-AAC v2 (mp4) encoder/decoder for DAB+ transmitter/receiver (GNU Radio blocks) * Graphical user interface for DAB/DAB+ transmission/reception (pyQt4) * "DABstep" as an executable application for DAB/DAB+ transmission/reception -For more detailed information about the done work, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). +For more detailed information about the work done during GSoC, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). + +Summarizing, all set [milestones](https://dabtransceiver.wordpress.com/milestones/) for GSoC were fulfilled. But of course, there are many ideas of expanding and improving gr-dab in the future (see [Ideas](https://github.com/kit-cel/gr-dab#Ideas) and [Constraints](https://github.com/kit-cel/gr-dab#Constraints)). Installation @@ -93,13 +97,9 @@ To build this module, run these commands: Usage ----- -Receiving DAB+ broadcasts -######################### - - -Transmitting DAB+ -################# - +* Receiving and Transmitting DAB/DAB+ broadcasts with the application "DABstep" +* Receiving or Transmitting DAB/DAB+ with prepaired GNU Radio Companion flowgraph under examples +* Receiving or Transmitting DAB/DAB+ by building your own GNU Radio flowgraph with provided gr-dab blocks Features -------- @@ -107,11 +107,21 @@ Features * Transmits DAB+ Audio transmissions, metadata * Receives DAB+ -(Current) Constraints +Current Constraints --------------------- -TODO +* only audio channels supported so far, no data channels +* PAD interpretation and generation not supported so far +* only EEP with protection profile set A supported so far, no set B and no UEP + +Ideas +---------- + +* FM simulation, calculating the audio noise out of the SNR and adding it to the audio +* parallel FM receiver that fills in the audio in case a superframe is broken Known Bugs ---------- +* OFDM demodulator gets out of sync sometimes causing burst errors + diff --git a/examples/README b/examples/README index 7c87b768..84af406e 100644 --- a/examples/README +++ b/examples/README @@ -2,3 +2,5 @@ simple_top.grc - all-in-one receiving block usage sample. dab_mer.grc - Hierarchical block, which counts MER. dab_measurement_graph_rtlsdr.grc - Top block to make measurements of DAB signal. Reception by RTL-SDR Stick. +dab_receiver.grc - Reception of FIC and MSC of a DAB/DAB+ broadcast. Reception by USRP source. +dab_transmitter.grc - Transmission of FIC and MSC of a DAB/DAB+ broadcast. Transmission over USRP sink. From e8aa0f2b8d16f01643b797666bba1630c74ca4c6 Mon Sep 17 00:00:00 2001 From: Moritz Luca Schmid Date: Tue, 29 Aug 2017 11:54:16 +0200 Subject: [PATCH 045/135] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aece3240..2da46fc3 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ This repository is the result of the 2017 Google Summer of Code project "A DAB/D For more detailed information about the work done during GSoC, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). -Summarizing, all set [milestones](https://dabtransceiver.wordpress.com/milestones/) for GSoC were fulfilled. But of course, there are many ideas of expanding and improving gr-dab in the future (see [Ideas](https://github.com/kit-cel/gr-dab#Ideas) and [Constraints](https://github.com/kit-cel/gr-dab#Constraints)). +Summarizing, all set [milestones](https://dabtransceiver.wordpress.com/milestones/) for GSoC were fulfilled. But of course, there are many ideas of expanding and improving gr-dab in the future (see Ideas and Constraints below). Installation From 67d5b6b4e8d0b715982bc02f4e613ef9a0a4fc68 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 29 Aug 2017 11:50:03 +0200 Subject: [PATCH 046/135] README: add Ideas and Current Constraints --- README.md | 36 +++++++++++++++++++++++------------- examples/README | 2 ++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0464adf7..2da46fc3 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,11 @@ Contents 4: Features -5: (Current) Constraints +5: Current Constraints -6: Known Bugs +6: Ideas + +7: Known Bugs License ------- @@ -45,13 +47,15 @@ This repository is the result of the 2017 Google Summer of Code project "A DAB/D * FIC source and expand FIC sink (GNU Radio blocks) * FIC encoder, including CRC, energy dispersal, convolutional encoding with puncturing (GNU Radio blocks) * MSC encoder and decoder, including CRC, energy dispersal/descramble, convolutional encoding/decoding with puncturing, time interleaving/deinterleaving (GNU Radio blocks) -* DAB transmission frame multiplexer (GNU Radio blocks) +* DAB transmission frame multiplexer (GNU Radio block) * MPEG Audio Layer II encoder/decoder for DAB tranmitter/receiver (GNU Radio blocks) * HE-AAC v2 (mp4) encoder/decoder for DAB+ transmitter/receiver (GNU Radio blocks) * Graphical user interface for DAB/DAB+ transmission/reception (pyQt4) * "DABstep" as an executable application for DAB/DAB+ transmission/reception -For more detailed information about the done work, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). +For more detailed information about the work done during GSoC, containing changes in code and new code, check out the [commit history](https://github.com/kit-cel/gr-dab/commits/master) of this repository. Weekly reports containing updates about the working progress, additional information, highlights and challenging pieces during GSoC can be found on my [GSoC blog](https://dabtransceiver.wordpress.com/). + +Summarizing, all set [milestones](https://dabtransceiver.wordpress.com/milestones/) for GSoC were fulfilled. But of course, there are many ideas of expanding and improving gr-dab in the future (see Ideas and Constraints below). Installation @@ -93,13 +97,9 @@ To build this module, run these commands: Usage ----- -Receiving DAB+ broadcasts -######################### - - -Transmitting DAB+ -################# - +* Receiving and Transmitting DAB/DAB+ broadcasts with the application "DABstep" +* Receiving or Transmitting DAB/DAB+ with prepaired GNU Radio Companion flowgraph under examples +* Receiving or Transmitting DAB/DAB+ by building your own GNU Radio flowgraph with provided gr-dab blocks Features -------- @@ -107,11 +107,21 @@ Features * Transmits DAB+ Audio transmissions, metadata * Receives DAB+ -(Current) Constraints +Current Constraints --------------------- -TODO +* only audio channels supported so far, no data channels +* PAD interpretation and generation not supported so far +* only EEP with protection profile set A supported so far, no set B and no UEP + +Ideas +---------- + +* FM simulation, calculating the audio noise out of the SNR and adding it to the audio +* parallel FM receiver that fills in the audio in case a superframe is broken Known Bugs ---------- +* OFDM demodulator gets out of sync sometimes causing burst errors + diff --git a/examples/README b/examples/README index 7c87b768..84af406e 100644 --- a/examples/README +++ b/examples/README @@ -2,3 +2,5 @@ simple_top.grc - all-in-one receiving block usage sample. dab_mer.grc - Hierarchical block, which counts MER. dab_measurement_graph_rtlsdr.grc - Top block to make measurements of DAB signal. Reception by RTL-SDR Stick. +dab_receiver.grc - Reception of FIC and MSC of a DAB/DAB+ broadcast. Reception by USRP source. +dab_transmitter.grc - Transmission of FIC and MSC of a DAB/DAB+ broadcast. Transmission over USRP sink. From 6202a87363c48f75343787e1f45241103b8e191c Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 7 Sep 2017 16:44:59 +0200 Subject: [PATCH 047/135] Sync: Add delayed correlation block --- grc/CMakeLists.txt | 3 +- grc/dab_mp2_encode_sb.xml | 6 +- grc/dab_synchronization_ff.xml | 25 +++++++ include/dab/CMakeLists.txt | 3 +- include/dab/synchronization_ff.h | 56 ++++++++++++++ lib/CMakeLists.txt | 3 +- lib/synchronization_ff_impl.cc | 124 +++++++++++++++++++++++++++++++ lib/synchronization_ff_impl.h | 53 +++++++++++++ python/CMakeLists.txt | 2 +- python/qa_synchronization_ff.py | 41 ++++++++++ swig/dab_swig.i | 4 + 11 files changed, 313 insertions(+), 7 deletions(-) create mode 100644 grc/dab_synchronization_ff.xml create mode 100644 include/dab/synchronization_ff.h create mode 100644 lib/synchronization_ff_impl.cc create mode 100644 lib/synchronization_ff_impl.h create mode 100755 python/qa_synchronization_ff.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index cd79e04b..a4d50e9c 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -71,5 +71,6 @@ install(FILES dab_mp4_encode_sb.xml dab_mp2_encode_sb.xml dab_valve_ff.xml - dab_peak_detector_fb.xml DESTINATION share/gnuradio/grc/blocks + dab_peak_detector_fb.xml + dab_synchronization_ff.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_mp2_encode_sb.xml b/grc/dab_mp2_encode_sb.xml index 66c1ff46..c50cba2c 100644 --- a/grc/dab_mp2_encode_sb.xml +++ b/grc/dab_mp2_encode_sb.xml @@ -5,7 +5,7 @@ import dab dab.mp2_encode_sb($bit_rate_n, $channels, $sample_rate) - Bitrate / 8kbit/s + Bitrate / 8 kbit/s bit_rate_n int @@ -37,8 +37,8 @@ in - raw - channels + short + $channels out diff --git a/grc/dab_synchronization_ff.xml b/grc/dab_synchronization_ff.xml new file mode 100644 index 00000000..a4c84fc9 --- /dev/null +++ b/grc/dab_synchronization_ff.xml @@ -0,0 +1,25 @@ + + Synchronization ff + dab_synchronization_ff + DAB + import dab + dab.synchronization_ff($symbol_length, $cyclic_prefix_length) + + Symbol_length + symbol_length + int + + + Cyclic_prefix_length + cyclic_prefix_length + int + + + in + complex + + + out + complex + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 50993e5f..a22f19b8 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -65,5 +65,6 @@ install(FILES mp4_encode_sb.h mp2_encode_sb.h valve_ff.h - peak_detector_fb.h DESTINATION include/dab + peak_detector_fb.h + synchronization_ff.h DESTINATION include/dab ) diff --git a/include/dab/synchronization_ff.h b/include/dab/synchronization_ff.h new file mode 100644 index 00000000..697cdea2 --- /dev/null +++ b/include/dab/synchronization_ff.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_SYNCHRONIZATION_FF_H +#define INCLUDED_DAB_SYNCHRONIZATION_FF_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API synchronization_ff : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::synchronization_ff. + * + * To avoid accidental use of raw pointers, dab::synchronization_ff's + * constructor is in a private implementation + * class. dab::synchronization_ff::make is the public interface for + * creating new instances. + */ + static sptr make(int symbol_length, int cyclic_prefix_length); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_SYNCHRONIZATION_FF_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3992c30e..c460a64d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -94,7 +94,8 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/encode_new.c ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c valve_ff_impl.cc - peak_detector_fb_impl.cc ) + peak_detector_fb_impl.cc + synchronization_ff_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc new file mode 100644 index 00000000..589f94ee --- /dev/null +++ b/lib/synchronization_ff_impl.cc @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "synchronization_ff_impl.h" + +namespace gr { + namespace dab { + + synchronization_ff::sptr + synchronization_ff::make(int symbol_length, int cyclic_prefix_length) + { + return gnuradio::get_initial_sptr + (new synchronization_ff_impl(symbol_length, cyclic_prefix_length)); + } + + /* + * The private constructor + */ + synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length) + : gr::sync_block("synchronization_ff", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_symbol_length(symbol_length), + d_cyclic_prefix_length(cyclic_prefix_length) + { + //set_history(cyclic_prefix_length); + set_min_noutput_items(symbol_length+cyclic_prefix_length); + d_correlation = 0; + d_energy_prefix = 1; + d_energy_repetition = 1; + d_recalculate = 0; + } + + /* + * Our virtual destructor. + */ + synchronization_ff_impl::~synchronization_ff_impl() + { + } + + int + synchronization_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + + for (int i = 0; i < noutput_items-d_symbol_length-d_cyclic_prefix_length; i++) { + if(d_recalculate > 100000){ + d_correlation = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_correlation += in[i+j] * conj(in[d_symbol_length+i+j]); + } + + d_energy_prefix = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_prefix += std::real(in[i+j] * conj(in[i+j])); + } + + d_energy_repetition = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_repetition += std::real(in[i+j+d_symbol_length] * conj(in[i+j+d_symbol_length])); + } + + d_recalculate = 0; + } + else { + d_correlation += in[i + d_cyclic_prefix_length - 1] * conj(in[d_symbol_length+i + d_cyclic_prefix_length - 1]); + d_energy_prefix += std::real(in[i + d_cyclic_prefix_length - 1] * conj(in[i + d_cyclic_prefix_length - 1])); + d_energy_repetition += std::real(in[d_symbol_length + i + d_cyclic_prefix_length - 1]*conj(in[d_symbol_length+i + d_cyclic_prefix_length - 1])); + out[i] = d_energy_repetition; + d_correlation -= in[i] * conj(in[d_symbol_length+i]); + d_energy_prefix -= std::real(in[i] * conj(in[i])); + d_energy_repetition -= std::real(in[d_symbol_length+i]*conj(in[d_symbol_length+i])); + } + + out[i] = d_correlation/std::sqrt(d_energy_prefix*d_energy_repetition); + + d_recalculate ++; + } + + //d_delay_correlation = d_delay_correlation - in[i]*conj(in[i+d_symbol_length]) + in[i+d_cyclic_prefix_length]*conj(in[i+d_cyclic_prefix_length+d_symbol_length]); + //d_energy_prefix = d_energy_prefix - std::real(in[i]*conj(in[i])) + std::real(in[i+d_cyclic_prefix_length]*conj(in[i+d_cyclic_prefix_length])); + //d_energy_repetition = d_energy_repetition - in[i+d_symbol_length]*conj(in[i+d_symbol_length]) + in[i+d_cyclic_prefix_length+d_symbol_length]*conj(in[i+d_cyclic_prefix_length+d_symbol_length]); + //out[i] = d_energy_prefix.real(); + + /*for (int j = 0; j < d_cyclic_prefix_length; ++j) { + //d_delay_correlation += in[i+j] * conj(in[i+j+d_symbol_length]); + d_energy_prefix += std::real(in[i+j] * conj(in[i+j])); + //d_energy_repetition += std::real(in[i+j+d_symbol_length] * conj(in[i+j+d_symbol_length])); + } + out[i] = d_energy_prefix;*/ + + // Tell runtime system how many output items we produced. + return noutput_items-d_symbol_length-d_cyclic_prefix_length; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h new file mode 100644 index 00000000..396780f3 --- /dev/null +++ b/lib/synchronization_ff_impl.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H +#define INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H + +#include + +namespace gr { + namespace dab { + + class synchronization_ff_impl : public synchronization_ff + { + private: + int d_symbol_length; + int d_cyclic_prefix_length; + int d_recalculate; + gr_complex d_correlation; + float d_energy_prefix; + float d_energy_repetition; + + public: + synchronization_ff_impl(int symbol_length, int cyclic_prefix_length); + ~synchronization_ff_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 193482b1..7644fb41 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -25,7 +25,6 @@ if(NOT PYTHONINTERP_FOUND) return() endif() - ######################################################################## # Insert ICON PATH macro Insert ICON PATH macro into constants.py ######################################################################## @@ -87,3 +86,4 @@ GR_ADD_TEST(qa_mp4_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) GR_ADD_TEST(qa_peak_detector_fb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_peak_detector_fb.py) +GR_ADD_TEST(qa_synchronization_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_synchronization_ff.py) diff --git a/python/qa_synchronization_ff.py b/python/qa_synchronization_ff.py new file mode 100755 index 00000000..10f579db --- /dev/null +++ b/python/qa_synchronization_ff.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 <+YOU OR YOUR COMPANY+>. +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + +class qa_synchronization_ff (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + # set up fg + self.tb.run () + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_synchronization_ff, "qa_synchronization_ff.xml") diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 16a9edc4..d03afaef 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -52,6 +52,7 @@ #include "dab/mp2_encode_sb.h" #include "dab/valve_ff.h" #include "dab/peak_detector_fb.h" +#include "dab/synchronization_ff.h" %} @@ -146,3 +147,6 @@ GR_SWIG_BLOCK_MAGIC2(dab, mp2_encode_sb); GR_SWIG_BLOCK_MAGIC2(dab, valve_ff); %include "dab/peak_detector_fb.h" GR_SWIG_BLOCK_MAGIC2(dab, peak_detector_fb); + +%include "dab/synchronization_ff.h" +GR_SWIG_BLOCK_MAGIC2(dab, synchronization_ff); From c5133b9ac61d060063873a9443b2b350cf5db068 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 27 Sep 2017 13:21:36 +0200 Subject: [PATCH 048/135] synch: working time sync --- grc/dab_synchronization_ff.xml | 7 +- include/dab/synchronization_ff.h | 2 +- lib/synchronization_ff_impl.cc | 257 +++++++++++++++++++++++++------ lib/synchronization_ff_impl.h | 21 ++- 4 files changed, 232 insertions(+), 55 deletions(-) diff --git a/grc/dab_synchronization_ff.xml b/grc/dab_synchronization_ff.xml index a4c84fc9..53670c19 100644 --- a/grc/dab_synchronization_ff.xml +++ b/grc/dab_synchronization_ff.xml @@ -3,7 +3,7 @@ dab_synchronization_ff DAB import dab - dab.synchronization_ff($symbol_length, $cyclic_prefix_length) + dab.synchronization_ff($symbol_length, $cyclic_prefix_length, $num_ofdm_symbols) Symbol_length symbol_length @@ -14,6 +14,11 @@ cyclic_prefix_length int + + Num_ofdm_symbols + num_ofdm_symbols + int + in complex diff --git a/include/dab/synchronization_ff.h b/include/dab/synchronization_ff.h index 697cdea2..c3d2e313 100644 --- a/include/dab/synchronization_ff.h +++ b/include/dab/synchronization_ff.h @@ -46,7 +46,7 @@ namespace gr { * class. dab::synchronization_ff::make is the public interface for * creating new instances. */ - static sptr make(int symbol_length, int cyclic_prefix_length); + static sptr make(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols); }; } // namespace dab diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index 589f94ee..559acc25 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -22,35 +22,50 @@ #include "config.h" #endif +#include +#include +#include +#include #include #include "synchronization_ff_impl.h" +using namespace boost; + namespace gr { namespace dab { synchronization_ff::sptr - synchronization_ff::make(int symbol_length, int cyclic_prefix_length) + synchronization_ff::make(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) { return gnuradio::get_initial_sptr - (new synchronization_ff_impl(symbol_length, cyclic_prefix_length)); + (new synchronization_ff_impl(symbol_length, cyclic_prefix_length, num_ofdm_symbols)); } /* * The private constructor */ - synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length) - : gr::sync_block("synchronization_ff", - gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(gr_complex))), - d_symbol_length(symbol_length), - d_cyclic_prefix_length(cyclic_prefix_length) + synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) + : gr::sync_block("synchronization_ff", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_symbol_length(symbol_length), + d_cyclic_prefix_length(cyclic_prefix_length), + d_num_ofdm_symbols(num_ofdm_symbols) { //set_history(cyclic_prefix_length); - set_min_noutput_items(symbol_length+cyclic_prefix_length); + set_min_noutput_items(symbol_length + cyclic_prefix_length); d_correlation = 0; d_energy_prefix = 1; d_energy_repetition = 1; - d_recalculate = 0; + d_NULL_symbol_energy = 1; + d_NULL_detected = false; + d_moving_average_counter = 0; + d_frame_count = 1; + d_frame_length_count = 0; + d_wait_for_NULL = true; + d_on_peak = false; + d_acquisition = false; + d_energy_threshold = 2; } /* @@ -60,63 +75,203 @@ namespace gr { { } + void + synchronization_ff_impl::delayed_correlation(const gr_complex *sample, bool new_calculation) + { + if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || new_calculation) { + if (d_moving_average_counter == 0 && (!new_calculation)) { + // first value is calculated completely, next values are calculated with moving average + d_moving_average_counter++; + } else { + // reset counter + d_moving_average_counter = 0; + } + // calculate delayed correlation for this sample completely + d_correlation = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_correlation += sample[j] * conj(sample[d_symbol_length + j]); + } + // calculate energy of cyclic prefix for this sample completely + d_energy_prefix = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_prefix += std::real(sample[j] * conj(sample[j])); + } + // calculate energy of its repetition for this sample completely + d_energy_repetition = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_repetition += std::real(sample[j + d_symbol_length] * conj(sample[j + d_symbol_length])); + } + } else { + // calculate next step for moving average + d_correlation += + sample[d_cyclic_prefix_length - 1] * conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); + d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * conj(sample[d_cyclic_prefix_length - 1])); + d_energy_repetition += std::real(sample[d_symbol_length + d_cyclic_prefix_length - 1] * + conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); + d_correlation -= sample[0] * conj(sample[d_symbol_length]); + d_energy_prefix -= std::real(sample[0] * conj(sample[0])); + d_energy_repetition -= std::real(sample[d_symbol_length] * conj(sample[d_symbol_length])); + d_moving_average_counter++; + } + // normalize + d_correlation_normalized = d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); + // calculate magnitude + d_correlation_normalized_magnitude = d_correlation_normalized.real() * d_correlation_normalized.real() + + d_correlation_normalized.imag() * d_correlation_normalized.imag(); + } + + bool + synchronization_ff_impl::detect_peak() + { + if (!d_on_peak && d_correlation_normalized_magnitude > 0.85) { + d_on_peak = true; + return false; + } else if (d_on_peak && d_correlation_normalized_magnitude < 0.8) { + // peak found + d_on_peak = false; + return true; + } else { + return false; + } + } + int synchronization_ff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - - for (int i = 0; i < noutput_items-d_symbol_length-d_cyclic_prefix_length; i++) { - if(d_recalculate > 100000){ - d_correlation = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_correlation += in[i+j] * conj(in[d_symbol_length+i+j]); + for (int i = 0; i < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++i) { + if (d_wait_for_NULL) { + // search for next correlation peak + delayed_correlation(&in[i], false); + if (detect_peak()) { + if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * d_energy_threshold)) { + // set tag at beginning of new frame (first symbol after null symbol) + add_item_tag(0, nitems_written(0) + i, pmt::mp("start"), + pmt::from_float(d_correlation_normalized_magnitude)); + GR_LOG_DEBUG(d_logger, format(" Found start of frame (i=%d)") % i); + // reset NULL detector + d_NULL_detected = false; + // switch to tracking mode + d_wait_for_NULL = false; + } else { + //peak but not after NULL symbol + } + } else { + if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < + 0.1))) { // ||((d_energy_prefix/d_energy_repetition < 0.2)&&(d_energy_prefix < d_NULL_symbol_energy)&&(d_NULL_detected)) + // schreibe NULL energy wenn 1.) energy threshhold unterschritten und noch kein NULL davor detected, oder wenn 2.) schon davor NULL detected aber jetzt noch weniger energy und wieder unter threshold + d_NULL_symbol_energy = d_energy_prefix; + d_NULL_detected = true; + add_item_tag(0, nitems_written(0) + i, pmt::mp("NULL"), pmt::from_float(d_energy_prefix)); + GR_LOG_DEBUG(d_logger, format(" NULL detected")); + } } - - d_energy_prefix = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_prefix += std::real(in[i+j] * conj(in[i+j])); - } - - d_energy_repetition = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_repetition += std::real(in[i+j+d_symbol_length] * conj(in[i+j+d_symbol_length])); - } - - d_recalculate = 0; } - else { - d_correlation += in[i + d_cyclic_prefix_length - 1] * conj(in[d_symbol_length+i + d_cyclic_prefix_length - 1]); - d_energy_prefix += std::real(in[i + d_cyclic_prefix_length - 1] * conj(in[i + d_cyclic_prefix_length - 1])); - d_energy_repetition += std::real(in[d_symbol_length + i + d_cyclic_prefix_length - 1]*conj(in[d_symbol_length+i + d_cyclic_prefix_length - 1])); - out[i] = d_energy_repetition; - d_correlation -= in[i] * conj(in[d_symbol_length+i]); - d_energy_prefix -= std::real(in[i] * conj(in[i])); - d_energy_repetition -= std::real(in[d_symbol_length+i]*conj(in[d_symbol_length+i])); + else if (++d_frame_length_count >= (d_symbol_length + d_cyclic_prefix_length)) { + //we are where the next peak is expected + d_frame_length_count = 0; + // correlation has to be calculated completely new, because of skipping samples + delayed_correlation(&in[i], true); + GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); + // check if there is really a peak + if (d_correlation_normalized_magnitude > 0.5) { + d_frame_count++; + GR_LOG_DEBUG(d_logger, format(" Peak as expected %d") % d_frame_count); + // did we arrive at the last symbol? + if (d_frame_count >= d_num_ofdm_symbols) { + d_frame_count = 1; + GR_LOG_DEBUG(d_logger, format(" End of Frame -> switch to acquisition mode")); + //TODO: skip forward more + // switch to acquisition mode again to get the start of the next frame exactly + d_wait_for_NULL = true; + add_item_tag(0, nitems_written(0) + i, pmt::mp("end of frame"), pmt::from_float(d_energy_prefix)); + } + } else { + // no peak found -> out of track; search for next NULL symbol + d_wait_for_NULL = true; + GR_LOG_DEBUG(d_logger, format("Lost track")); + add_item_tag(0, nitems_written(0) + i, pmt::mp("lost track"), + pmt::from_float(d_correlation_normalized_magnitude)); + d_frame_count = 1; + } } - out[i] = d_correlation/std::sqrt(d_energy_prefix*d_energy_repetition); + } - d_recalculate ++; + d_moving_average_counter = 0; + for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { + delayed_correlation(&in[j], false); + out[j] = d_correlation_normalized; } - //d_delay_correlation = d_delay_correlation - in[i]*conj(in[i+d_symbol_length]) + in[i+d_cyclic_prefix_length]*conj(in[i+d_cyclic_prefix_length+d_symbol_length]); - //d_energy_prefix = d_energy_prefix - std::real(in[i]*conj(in[i])) + std::real(in[i+d_cyclic_prefix_length]*conj(in[i+d_cyclic_prefix_length])); - //d_energy_repetition = d_energy_repetition - in[i+d_symbol_length]*conj(in[i+d_symbol_length]) + in[i+d_cyclic_prefix_length+d_symbol_length]*conj(in[i+d_cyclic_prefix_length+d_symbol_length]); - //out[i] = d_energy_prefix.real(); + return noutput_items - d_cyclic_prefix_length - d_symbol_length; - /*for (int j = 0; j < d_cyclic_prefix_length; ++j) { - //d_delay_correlation += in[i+j] * conj(in[i+j+d_symbol_length]); - d_energy_prefix += std::real(in[i+j] * conj(in[i+j])); - //d_energy_repetition += std::real(in[i+j+d_symbol_length] * conj(in[i+j+d_symbol_length])); + /* + memset(out, 0, (noutput_items-d_symbol_length-d_cyclic_prefix_length)* sizeof(float)); + + int i = 0; + while(i < noutput_items-d_symbol_length-d_cyclic_prefix_length){ + if(d_wait_for_NULL){ + // search for next correlation peak + delayed_correlation(&in[i], false); + if(detect_peak()){ + if(d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy*d_energy_threshold)){ + // set tag at beginning of new frame (first symbol after null symbol) + add_item_tag(0, nitems_written(0) + i, pmt::mp("start"), pmt::from_float(d_correlation_normalized_magnitude)); + GR_LOG_DEBUG(d_logger, format(" Found start of frame (i=%d)")%i); + // reset NULL detector + d_NULL_detected = false; + // switch to tracking mode + d_wait_for_NULL = false; + } + else{ + } + } + else { + if(((!d_NULL_detected) && (d_energy_prefix/d_energy_repetition < 0.2))||((d_energy_prefix/d_energy_repetition < 0.2)&&(d_energy_prefix < d_NULL_symbol_energy)&&(d_NULL_detected))) { + // schreibe NULL energy wenn 1.) energy threshhold unterschritten und noch kein NULL davor detected, oder wenn 2.) schon davor NULL detected aber jetzt noch weniger energy und wieder unter threshold + d_NULL_symbol_energy = d_energy_prefix; + d_NULL_detected = true; + GR_LOG_DEBUG(d_logger, format(" NULL detected")); + } + } + out[i] = d_correlation_normalized_magnitude; } - out[i] = d_energy_prefix;*/ + else{ + // skip samples of 1 symbol length + memset(&out[i], 1, (d_symbol_length+d_cyclic_prefix_length-1)* sizeof(float)); + i += (d_symbol_length + d_cyclic_prefix_length-1); + // correlation has to be calculated completely new, because of skipping samples + delayed_correlation(&in[i], true); + GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)")%d_correlation_normalized_magnitude %i); + out[i] = d_correlation_normalized_magnitude; + if(d_correlation_normalized_magnitude > 0.5){ + d_frame_count++; + GR_LOG_DEBUG(d_logger, format(" Peak as expected %d") %d_frame_count); + if(d_frame_count >= d_num_ofdm_symbols){ + d_frame_count = 1; + GR_LOG_DEBUG(d_logger, format(" End of Frame -> switch to acquisition mode")); + //TODO: skip forward more + d_wait_for_NULL = true; + add_item_tag(0, nitems_written(0) + i, pmt::mp("end of frame"), pmt::from_float(d_energy_prefix)); + } + } + else{ + // no peak found -> out of track; search for next NULL symbol + d_wait_for_NULL = true; + GR_LOG_DEBUG(d_logger, format("Lost track")); + add_item_tag(0, nitems_written(0) + i, pmt::mp("lost track"), pmt::from_float(d_correlation_normalized_magnitude)); + d_frame_count = 1; + } + } + i++; + } - // Tell runtime system how many output items we produced. - return noutput_items-d_symbol_length-d_cyclic_prefix_length; + return noutput_items;*/ } } /* namespace dab */ diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h index 396780f3..42078171 100644 --- a/lib/synchronization_ff_impl.h +++ b/lib/synchronization_ff_impl.h @@ -31,15 +31,32 @@ namespace gr { private: int d_symbol_length; int d_cyclic_prefix_length; - int d_recalculate; + int d_moving_average_counter; gr_complex d_correlation; + gr_complex d_correlation_normalized; + float d_correlation_normalized_magnitude; + float d_correlation_normalized_phase; float d_energy_prefix; float d_energy_repetition; + float d_NULL_symbol_energy; + bool d_NULL_detected; + + int d_energy_threshold; + + int d_num_ofdm_symbols; + int d_frame_count; + int d_frame_length_count; + bool d_wait_for_NULL; + bool d_on_peak; + bool d_acquisition; public: - synchronization_ff_impl(int symbol_length, int cyclic_prefix_length); + synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols); ~synchronization_ff_impl(); + void delayed_correlation(const gr_complex *sample, bool new_calculation); + bool detect_peak(); + // Where all the action really happens int work(int noutput_items, gr_vector_const_void_star &input_items, From 46549634dfe6622069de534b11468450f7caef6e Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 27 Sep 2017 15:16:53 +0200 Subject: [PATCH 049/135] sync: estimate frequency offset --- lib/synchronization_ff_impl.cc | 119 ++++++--------------------------- lib/synchronization_ff_impl.h | 21 +++--- 2 files changed, 33 insertions(+), 107 deletions(-) diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index 559acc25..01362ef2 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -1,17 +1,17 @@ /* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -52,8 +52,7 @@ namespace gr { d_cyclic_prefix_length(cyclic_prefix_length), d_num_ofdm_symbols(num_ofdm_symbols) { - //set_history(cyclic_prefix_length); - set_min_noutput_items(symbol_length + cyclic_prefix_length); + set_min_noutput_items(symbol_length + cyclic_prefix_length+1); d_correlation = 0; d_energy_prefix = 1; d_energy_repetition = 1; @@ -65,7 +64,6 @@ namespace gr { d_wait_for_NULL = true; d_on_peak = false; d_acquisition = false; - d_energy_threshold = 2; } /* @@ -145,14 +143,13 @@ namespace gr { for (int i = 0; i < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++i) { if (d_wait_for_NULL) { - // search for next correlation peak + // acquisition mode: search for next correlation peak after a NULL symbol delayed_correlation(&in[i], false); if (detect_peak()) { - if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * d_energy_threshold)) { + if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { // set tag at beginning of new frame (first symbol after null symbol) - add_item_tag(0, nitems_written(0) + i, pmt::mp("start"), - pmt::from_float(d_correlation_normalized_magnitude)); - GR_LOG_DEBUG(d_logger, format(" Found start of frame (i=%d)") % i); + add_item_tag(0, nitems_written(0) + i, pmt::mp("Start"), + pmt::from_float(std::arg(d_correlation))); // reset NULL detector d_NULL_detected = false; // switch to tracking mode @@ -161,117 +158,43 @@ namespace gr { //peak but not after NULL symbol } } else { - if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < - 0.1))) { // ||((d_energy_prefix/d_energy_repetition < 0.2)&&(d_energy_prefix < d_NULL_symbol_energy)&&(d_NULL_detected)) - // schreibe NULL energy wenn 1.) energy threshhold unterschritten und noch kein NULL davor detected, oder wenn 2.) schon davor NULL detected aber jetzt noch weniger energy und wieder unter threshold + if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.1))) { + // NULL symbol detection, if energy is < 0.1 * energy a symbol time later d_NULL_symbol_energy = d_energy_prefix; d_NULL_detected = true; - add_item_tag(0, nitems_written(0) + i, pmt::mp("NULL"), pmt::from_float(d_energy_prefix)); - GR_LOG_DEBUG(d_logger, format(" NULL detected")); } } } else if (++d_frame_length_count >= (d_symbol_length + d_cyclic_prefix_length)) { - //we are where the next peak is expected + // &in[i] points now to the sample where the next symbol start (=peak) is expected d_frame_length_count = 0; - // correlation has to be calculated completely new, because of skipping samples + // correlation has to be calculated completely new, because of skipping samples before delayed_correlation(&in[i], true); - GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); + //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.5) { + if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge and not before peak d_frame_count++; - GR_LOG_DEBUG(d_logger, format(" Peak as expected %d") % d_frame_count); - // did we arrive at the last symbol? + // check if we arrived at the last symbol if (d_frame_count >= d_num_ofdm_symbols) { d_frame_count = 1; GR_LOG_DEBUG(d_logger, format(" End of Frame -> switch to acquisition mode")); - //TODO: skip forward more + //TODO: skip forward more to safe computing many computing steps // switch to acquisition mode again to get the start of the next frame exactly d_wait_for_NULL = true; - add_item_tag(0, nitems_written(0) + i, pmt::mp("end of frame"), pmt::from_float(d_energy_prefix)); } } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track")); - add_item_tag(0, nitems_written(0) + i, pmt::mp("lost track"), - pmt::from_float(d_correlation_normalized_magnitude)); + GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode")); d_frame_count = 1; } } - } - d_moving_average_counter = 0; - for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { - delayed_correlation(&in[j], false); - out[j] = d_correlation_normalized; - } + // pass iq samples through with set tags + memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); return noutput_items - d_cyclic_prefix_length - d_symbol_length; - - /* - memset(out, 0, (noutput_items-d_symbol_length-d_cyclic_prefix_length)* sizeof(float)); - - int i = 0; - while(i < noutput_items-d_symbol_length-d_cyclic_prefix_length){ - if(d_wait_for_NULL){ - // search for next correlation peak - delayed_correlation(&in[i], false); - if(detect_peak()){ - if(d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy*d_energy_threshold)){ - // set tag at beginning of new frame (first symbol after null symbol) - add_item_tag(0, nitems_written(0) + i, pmt::mp("start"), pmt::from_float(d_correlation_normalized_magnitude)); - GR_LOG_DEBUG(d_logger, format(" Found start of frame (i=%d)")%i); - // reset NULL detector - d_NULL_detected = false; - // switch to tracking mode - d_wait_for_NULL = false; - } - else{ - } - } - else { - if(((!d_NULL_detected) && (d_energy_prefix/d_energy_repetition < 0.2))||((d_energy_prefix/d_energy_repetition < 0.2)&&(d_energy_prefix < d_NULL_symbol_energy)&&(d_NULL_detected))) { - // schreibe NULL energy wenn 1.) energy threshhold unterschritten und noch kein NULL davor detected, oder wenn 2.) schon davor NULL detected aber jetzt noch weniger energy und wieder unter threshold - d_NULL_symbol_energy = d_energy_prefix; - d_NULL_detected = true; - GR_LOG_DEBUG(d_logger, format(" NULL detected")); - } - } - out[i] = d_correlation_normalized_magnitude; - } - else{ - // skip samples of 1 symbol length - memset(&out[i], 1, (d_symbol_length+d_cyclic_prefix_length-1)* sizeof(float)); - i += (d_symbol_length + d_cyclic_prefix_length-1); - // correlation has to be calculated completely new, because of skipping samples - delayed_correlation(&in[i], true); - GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)")%d_correlation_normalized_magnitude %i); - out[i] = d_correlation_normalized_magnitude; - if(d_correlation_normalized_magnitude > 0.5){ - d_frame_count++; - GR_LOG_DEBUG(d_logger, format(" Peak as expected %d") %d_frame_count); - if(d_frame_count >= d_num_ofdm_symbols){ - d_frame_count = 1; - GR_LOG_DEBUG(d_logger, format(" End of Frame -> switch to acquisition mode")); - //TODO: skip forward more - d_wait_for_NULL = true; - add_item_tag(0, nitems_written(0) + i, pmt::mp("end of frame"), pmt::from_float(d_energy_prefix)); - } - } - else{ - // no peak found -> out of track; search for next NULL symbol - d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track")); - add_item_tag(0, nitems_written(0) + i, pmt::mp("lost track"), pmt::from_float(d_correlation_normalized_magnitude)); - d_frame_count = 1; - } - } - i++; - } - - return noutput_items;*/ } } /* namespace dab */ diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h index 42078171..77340130 100644 --- a/lib/synchronization_ff_impl.h +++ b/lib/synchronization_ff_impl.h @@ -1,17 +1,17 @@ /* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -25,7 +25,13 @@ namespace gr { namespace dab { - +/*! \brief sets tag at the beginning of each OFDM frame + * + * \param symbol_length length of each OFDM symbol without guard intervall + * \param cyclic_prefix_length length of the cyclic prefix (= length of the guard intervall) + * \param num_ofdm_symbols number of OFDM symbols without the NULL symbol + * + */ class synchronization_ff_impl : public synchronization_ff { private: @@ -40,9 +46,6 @@ namespace gr { float d_energy_repetition; float d_NULL_symbol_energy; bool d_NULL_detected; - - int d_energy_threshold; - int d_num_ofdm_symbols; int d_frame_count; int d_frame_length_count; From 2802050606b0d0471b5c7fb74f0f6a2f1d225fb5 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 28 Sep 2017 16:11:50 +0200 Subject: [PATCH 050/135] sync: correct frequency offset --- lib/synchronization_ff_impl.cc | 16 ++++++++++++++-- lib/synchronization_ff_impl.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index 01362ef2..a2a1632d 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -28,6 +28,7 @@ #include #include #include "synchronization_ff_impl.h" +#include using namespace boost; @@ -57,6 +58,7 @@ namespace gr { d_energy_prefix = 1; d_energy_repetition = 1; d_NULL_symbol_energy = 1; + d_frequency_offset = 0; d_NULL_detected = false; d_moving_average_counter = 0; d_frame_count = 1; @@ -150,6 +152,9 @@ namespace gr { // set tag at beginning of new frame (first symbol after null symbol) add_item_tag(0, nitems_written(0) + i, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); + // calculate new frequency offset + d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s + GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%std::arg(d_correlation)); // reset NULL detector d_NULL_detected = false; // switch to tracking mode @@ -177,7 +182,6 @@ namespace gr { // check if we arrived at the last symbol if (d_frame_count >= d_num_ofdm_symbols) { d_frame_count = 1; - GR_LOG_DEBUG(d_logger, format(" End of Frame -> switch to acquisition mode")); //TODO: skip forward more to safe computing many computing steps // switch to acquisition mode again to get the start of the next frame exactly d_wait_for_NULL = true; @@ -189,11 +193,19 @@ namespace gr { d_frame_count = 1; } } + // copy sample correcting the frequency offset + out[i] = in[i] * gr_expj(-d_frequency_offset); } // pass iq samples through with set tags - memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); + // memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); + // debug output to check the delayed correlation + /*d_moving_average_counter = 0; + for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { + delayed_correlation(&in[j], false); + out[j] = d_correlation_normalized; + }*/ return noutput_items - d_cyclic_prefix_length - d_symbol_length; } diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h index 77340130..4d418102 100644 --- a/lib/synchronization_ff_impl.h +++ b/lib/synchronization_ff_impl.h @@ -45,6 +45,7 @@ namespace gr { float d_energy_prefix; float d_energy_repetition; float d_NULL_symbol_energy; + float d_frequency_offset; bool d_NULL_detected; int d_num_ofdm_symbols; int d_frame_count; From 6ede829170e3306382fd0b18f1674d65e1441f80 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 29 Sep 2017 13:51:21 +0200 Subject: [PATCH 051/135] sync: implementation as sync block --- grc/dab_synchronization_ff.xml | 2 +- lib/synchronization_ff_impl.cc | 76 +++++++++++++++++++++++++++------- lib/synchronization_ff_impl.h | 3 +- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/grc/dab_synchronization_ff.xml b/grc/dab_synchronization_ff.xml index 53670c19..db7512be 100644 --- a/grc/dab_synchronization_ff.xml +++ b/grc/dab_synchronization_ff.xml @@ -25,6 +25,6 @@ out - complex + float diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index a2a1632d..f878b13b 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -48,7 +48,8 @@ namespace gr { synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) : gr::sync_block("synchronization_ff", gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(gr_complex))), + //gr::io_signature::make(1, 1, sizeof(gr_complex))), + gr::io_signature::make(1, 1, sizeof(float))), d_symbol_length(symbol_length), d_cyclic_prefix_length(cyclic_prefix_length), d_num_ofdm_symbols(num_ofdm_symbols) @@ -64,7 +65,7 @@ namespace gr { d_frame_count = 1; d_frame_length_count = 0; d_wait_for_NULL = true; - d_on_peak = false; + d_on_triangle = false; d_acquisition = false; } @@ -120,20 +121,52 @@ namespace gr { d_correlation_normalized.imag() * d_correlation_normalized.imag(); } + /*! \brief returns true at a point with a little space before the peak of a correlation triangular + * + */ + bool + synchronization_ff_impl::detect_start_of_symbol() + { + if(d_on_triangle){ + if(d_correlation_normalized_magnitude < 0.5){ + // we left the triangle + d_on_triangle = false; + return false; + } + else{ + // we are still on the triangle but we already picked our pre-peak value + return false; + } + } + else{ + // not on a correlation triangle yet + if(d_correlation_normalized_magnitude > 0.85){ + // no we are on the triangle + d_on_triangle = true; + return true; + } + else{ + // no triangle here + return false; + } + } + } +/* bool - synchronization_ff_impl::detect_peak() + synchronization_ff_impl::detect_peak() // on triangle used for detect_start_of_symbol() { - if (!d_on_peak && d_correlation_normalized_magnitude > 0.85) { - d_on_peak = true; + if (!d_on_triangle && d_correlation_normalized_magnitude > 0.85) { + // over threshold, peak is coming soon + d_on_triangle = true; return false; - } else if (d_on_peak && d_correlation_normalized_magnitude < 0.8) { + } else if (d_on_triangle && d_correlation_normalized_magnitude < 0.8) { // peak found - d_on_peak = false; + d_on_triangle = false; return true; } else { return false; } - } + }*/ int synchronization_ff_impl::work(int noutput_items, @@ -141,20 +174,24 @@ namespace gr { gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; + //gr_complex *out = (gr_complex *) output_items[0]; + float *out = (float *) output_items[0]; for (int i = 0; i < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++i) { + out[i] = 10; + // just for measurement reasons if (d_wait_for_NULL) { // acquisition mode: search for next correlation peak after a NULL symbol delayed_correlation(&in[i], false); - if (detect_peak()) { + if (detect_start_of_symbol()) { if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { + // calculate new frequency offset + d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s // set tag at beginning of new frame (first symbol after null symbol) add_item_tag(0, nitems_written(0) + i, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); - // calculate new frequency offset - d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s - GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%std::arg(d_correlation)); + GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%d_frequency_offset); + out[i] = d_frequency_offset; // reset NULL detector d_NULL_detected = false; // switch to tracking mode @@ -177,10 +214,15 @@ namespace gr { delayed_correlation(&in[i], true); //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge and not before peak + if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge + d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s + out[i] = d_frequency_offset; // in rad/s + //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset)); + GR_LOG_DEBUG(d_logger, format("in track %d")%d_frequency_offset); d_frame_count++; // check if we arrived at the last symbol if (d_frame_count >= d_num_ofdm_symbols) { + //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); d_frame_count = 1; //TODO: skip forward more to safe computing many computing steps // switch to acquisition mode again to get the start of the next frame exactly @@ -189,12 +231,14 @@ namespace gr { } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode")); + //GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)")%d_correlation_normalized_magnitude); + add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), + pmt::from_float(d_correlation_normalized_magnitude)); d_frame_count = 1; } } // copy sample correcting the frequency offset - out[i] = in[i] * gr_expj(-d_frequency_offset); + //out[i] = d_correlation_normalized_magnitude;; } // pass iq samples through with set tags diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h index 4d418102..b4888877 100644 --- a/lib/synchronization_ff_impl.h +++ b/lib/synchronization_ff_impl.h @@ -51,7 +51,7 @@ namespace gr { int d_frame_count; int d_frame_length_count; bool d_wait_for_NULL; - bool d_on_peak; + bool d_on_triangle; bool d_acquisition; public: @@ -60,6 +60,7 @@ namespace gr { void delayed_correlation(const gr_complex *sample, bool new_calculation); bool detect_peak(); + bool detect_start_of_symbol(); // Where all the action really happens int work(int noutput_items, From 2d43e9d0f3378cc13cc841b6c90dcf96dff3a2be Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 29 Sep 2017 15:25:25 +0200 Subject: [PATCH 052/135] sync: add freq_offset_variance_measurement --- include/dab/synchronization_ff.h | 2 +- lib/synchronization_ff_impl.cc | 22 +++++++--- lib/synchronization_ff_impl.h | 6 ++- python/frequency_offset_variance.py | 68 +++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 python/frequency_offset_variance.py diff --git a/include/dab/synchronization_ff.h b/include/dab/synchronization_ff.h index c3d2e313..d3e1171c 100644 --- a/include/dab/synchronization_ff.h +++ b/include/dab/synchronization_ff.h @@ -33,7 +33,7 @@ namespace gr { * \ingroup dab * */ - class DAB_API synchronization_ff : virtual public gr::sync_block + class DAB_API synchronization_ff : virtual public gr::block { public: typedef boost::shared_ptr sptr; diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index f878b13b..1b2a1452 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -46,7 +46,7 @@ namespace gr { * The private constructor */ synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) - : gr::sync_block("synchronization_ff", + : gr::block("synchronization_ff", gr::io_signature::make(1, 1, sizeof(gr_complex)), //gr::io_signature::make(1, 1, sizeof(gr_complex))), gr::io_signature::make(1, 1, sizeof(float))), @@ -54,7 +54,7 @@ namespace gr { d_cyclic_prefix_length(cyclic_prefix_length), d_num_ofdm_symbols(num_ofdm_symbols) { - set_min_noutput_items(symbol_length + cyclic_prefix_length+1); + //set_min_noutput_items(symbol_length + cyclic_prefix_length+1); d_correlation = 0; d_energy_prefix = 1; d_energy_repetition = 1; @@ -76,6 +76,12 @@ namespace gr { { } + void + synchronization_ff_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + void synchronization_ff_impl::delayed_correlation(const gr_complex *sample, bool new_calculation) { @@ -169,16 +175,17 @@ namespace gr { }*/ int - synchronization_ff_impl::work(int noutput_items, + synchronization_ff_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; //gr_complex *out = (gr_complex *) output_items[0]; float *out = (float *) output_items[0]; + d_nwritten = 0; for (int i = 0; i < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++i) { - out[i] = 10; // just for measurement reasons if (d_wait_for_NULL) { // acquisition mode: search for next correlation peak after a NULL symbol @@ -191,7 +198,7 @@ namespace gr { add_item_tag(0, nitems_written(0) + i, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%d_frequency_offset); - out[i] = d_frequency_offset; + out[d_nwritten++] = d_frequency_offset; // reset NULL detector d_NULL_detected = false; // switch to tracking mode @@ -216,7 +223,7 @@ namespace gr { // check if there is really a peak if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s - out[i] = d_frequency_offset; // in rad/s + out[d_nwritten++] = d_frequency_offset; // in rad/s //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset)); GR_LOG_DEBUG(d_logger, format("in track %d")%d_frequency_offset); d_frame_count++; @@ -250,7 +257,8 @@ namespace gr { delayed_correlation(&in[j], false); out[j] = d_correlation_normalized; }*/ - return noutput_items - d_cyclic_prefix_length - d_symbol_length; + consume_each(noutput_items - d_cyclic_prefix_length - d_symbol_length); + return d_nwritten; } } /* namespace dab */ diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h index b4888877..b3dbfcec 100644 --- a/lib/synchronization_ff_impl.h +++ b/lib/synchronization_ff_impl.h @@ -54,6 +54,8 @@ namespace gr { bool d_on_triangle; bool d_acquisition; + int d_nwritten; + public: synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols); ~synchronization_ff_impl(); @@ -62,8 +64,10 @@ namespace gr { bool detect_peak(); bool detect_start_of_symbol(); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + // Where all the action really happens - int work(int noutput_items, + int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); }; diff --git a/python/frequency_offset_variance.py b/python/frequency_offset_variance.py new file mode 100644 index 00000000..4cb9bdce --- /dev/null +++ b/python/frequency_offset_variance.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import numpy as np +from gnuradio import gr +from gnuradio import blocks +from gnuradio import filter +import dab + +''' +Messung der Varianz des Frequenzoffsets bei verschiedenen SNR Szenarien +''' + +class measure_freq_offset(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + #data_source = blocks.vector_source_c_make(signal) + data_source = blocks.file_source_make(gr.sizeof_gr_complex, "data/gen_iq_dab_normalized_resampled.dat") + measure = dab.synchronization_ff_make(2048, 504, 76) + head = blocks.head_make(gr.sizeof_float, 2) + sink = blocks.vector_sink_f_make() + self.connect(data_source, measure, head, sink) + self.run() + self.sink_data = sink.data() + #self.data = np.asarray(self.sink_data) + print self.sink_data + +flowgraph = measure_freq_offset() +# input original iq data +#iq_gen = np.fromfile('data/gen_iq_dab_normalized_resampled.dat', dtype=complex) +#len = len(iq_gen) +# SNR vector +# noise_range = np.asarray((-10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0)) +# # calculate frequency offset for each SNR +# for SNR in noise_range: +# print "Calculating freq offset for SNR: " + str(SNR) +# # generate noise signal +# #n = (np.sqrt(np.power(10.0, -SNR/10.0)/2.0) * (np.random.normal(0, 1, len) + 1j * np.random.normal(0, 1, len))) +# # add noise to signal +# #rx = np.add(iq_gen, n) +# # feed noisy signal in flowgraph +# flowgraph = measure_freq_offset() +# #f_offset = flowgraph.data +# # convert to Hz +# #f_offset = np.multiply(f_offset, 1.0/(2.0*np.pi)) +# #print f_offset +# # calculate variance +# # var = np.var(f_offset) +# # print var \ No newline at end of file From 6ebd1306a77d3771b940d670064693eceaba2df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Fri, 29 Sep 2017 15:38:40 +0200 Subject: [PATCH 053/135] made frequency_offset_variance.py executable --- python/frequency_offset_variance.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 python/frequency_offset_variance.py diff --git a/python/frequency_offset_variance.py b/python/frequency_offset_variance.py old mode 100644 new mode 100755 From 9b628deb280abe4b042a5c1760cc13a03f65842c Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 2 Oct 2017 10:55:04 +0200 Subject: [PATCH 054/135] sync: add coarse freq correction --- grc/CMakeLists.txt | 4 +- ..._ofdm_coarse_frequency_correction_vcvc.xml | 32 ++ grc/dab_ofdm_synchronization_cvf.xml | 35 +++ include/dab/CMakeLists.txt | 4 +- .../ofdm_coarse_frequency_correction_vcvc.h | 56 ++++ include/dab/ofdm_synchronization_cvf.h | 56 ++++ lib/CMakeLists.txt | 4 +- lib/ofdm_coarse_frequency_correct_impl.cc | 2 +- ...m_coarse_frequency_correction_vcvc_impl.cc | 129 ++++++++ ...dm_coarse_frequency_correction_vcvc_impl.h | 53 ++++ lib/ofdm_synchronization_cvf_impl.cc | 275 ++++++++++++++++++ lib/ofdm_synchronization_cvf_impl.h | 80 +++++ lib/synchronization_ff_impl.cc | 2 +- python/CMakeLists.txt | 1 + python/qa_ofdm_synchronization_cvf.py | 41 +++ swig/dab_swig.i | 6 + 16 files changed, 775 insertions(+), 5 deletions(-) create mode 100644 grc/dab_ofdm_coarse_frequency_correction_vcvc.xml create mode 100644 grc/dab_ofdm_synchronization_cvf.xml create mode 100644 include/dab/ofdm_coarse_frequency_correction_vcvc.h create mode 100644 include/dab/ofdm_synchronization_cvf.h create mode 100644 lib/ofdm_coarse_frequency_correction_vcvc_impl.cc create mode 100644 lib/ofdm_coarse_frequency_correction_vcvc_impl.h create mode 100644 lib/ofdm_synchronization_cvf_impl.cc create mode 100644 lib/ofdm_synchronization_cvf_impl.h create mode 100755 python/qa_ofdm_synchronization_cvf.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index a4d50e9c..363beb7b 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -72,5 +72,7 @@ install(FILES dab_mp2_encode_sb.xml dab_valve_ff.xml dab_peak_detector_fb.xml - dab_synchronization_ff.xml DESTINATION share/gnuradio/grc/blocks + dab_synchronization_ff.xml + dab_ofdm_synchronization_cvf.xml + dab_ofdm_coarse_frequency_correction_vcvc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml b/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml new file mode 100644 index 00000000..4932123c --- /dev/null +++ b/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml @@ -0,0 +1,32 @@ + + Ofdm coarse frequency correction vcvc + dab_ofdm_coarse_frequency_correction_vcvc + DAB + import dab + dab.ofdm_coarse_frequency_correction_vcvc($fft_length, $num_carriers, $cyclic_prefix_length) + + Fft_length + fft_length + int + + + Num_carriers + num_carriers + int + + + Cyclic_prefix_length + cyclic_prefix_length + int + + + in + complex + $fft_length + + + out + complex + $num_carriers + + diff --git a/grc/dab_ofdm_synchronization_cvf.xml b/grc/dab_ofdm_synchronization_cvf.xml new file mode 100644 index 00000000..fbfe0faa --- /dev/null +++ b/grc/dab_ofdm_synchronization_cvf.xml @@ -0,0 +1,35 @@ + + Ofdm_synchronization cvf + dab_ofdm_synchronization_cvf + DAB + import dab + dab.ofdm_synchronization_cvf($symbol_length, $cyclic_prefix_length, $fft_length, $symbols_per_frame) + + Symbol_length + symbol_length + int + + + Cyclic_prefix_length + cyclic_prefix_length + int + + + Fft_length + fft_length + int + + + Symbols_per_frame + symbols_per_frame + int + + + in + complex + + + out + complex + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index a22f19b8..8375e2f6 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -66,5 +66,7 @@ install(FILES mp2_encode_sb.h valve_ff.h peak_detector_fb.h - synchronization_ff.h DESTINATION include/dab + synchronization_ff.h + ofdm_synchronization_cvf.h + ofdm_coarse_frequency_correction_vcvc.h DESTINATION include/dab ) diff --git a/include/dab/ofdm_coarse_frequency_correction_vcvc.h b/include/dab/ofdm_coarse_frequency_correction_vcvc.h new file mode 100644 index 00000000..e6f46e9c --- /dev/null +++ b/include/dab/ofdm_coarse_frequency_correction_vcvc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_H +#define INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API ofdm_coarse_frequency_correction_vcvc : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::ofdm_coarse_frequency_correction_vcvc. + * + * To avoid accidental use of raw pointers, dab::ofdm_coarse_frequency_correction_vcvc's + * constructor is in a private implementation + * class. dab::ofdm_coarse_frequency_correction_vcvc::make is the public interface for + * creating new instances. + */ + static sptr make(int fft_length, int num_carriers, int cyclic_prefix_length); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_H */ + diff --git a/include/dab/ofdm_synchronization_cvf.h b/include/dab/ofdm_synchronization_cvf.h new file mode 100644 index 00000000..9e4d0ab3 --- /dev/null +++ b/include/dab/ofdm_synchronization_cvf.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_H +#define INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API ofdm_synchronization_cvf : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::ofdm_synchronization_cvf. + * + * To avoid accidental use of raw pointers, dab::ofdm_synchronization_cvf's + * constructor is in a private implementation + * class. dab::ofdm_synchronization_cvf::make is the public interface for + * creating new instances. + */ + static sptr make(int symbol_length, int cyclic_prefix_lenght, int fft_length, int symbols_per_frame); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index c460a64d..7c8d13c2 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -95,7 +95,9 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c valve_ff_impl.cc peak_detector_fb_impl.cc - synchronization_ff_impl.cc ) + synchronization_ff_impl.cc + ofdm_synchronization_cvf_impl.cc + ofdm_coarse_frequency_correction_vcvc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/ofdm_coarse_frequency_correct_impl.cc b/lib/ofdm_coarse_frequency_correct_impl.cc index 940dac51..3afded21 100644 --- a/lib/ofdm_coarse_frequency_correct_impl.cc +++ b/lib/ofdm_coarse_frequency_correct_impl.cc @@ -127,7 +127,7 @@ ofdm_coarse_frequency_correct_impl::work(int noutput_items, frame_start_out[0] = 1; correlate_energy(iptr); d_delta_f = d_freq_offset+d_num_carriers/2-d_fft_length/2; - // fprintf(stderr, "cfs: coarse freq. offset (subcarriers): %d\n", d_delta_f); + fprintf(stderr, "cfs: coarse freq. offset (subcarriers): %d\n", d_freq_offset); d_symbol_num = 0; } else { frame_start_out[0] = 0; diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc new file mode 100644 index 00000000..f48b515a --- /dev/null +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -0,0 +1,129 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "ofdm_coarse_frequency_correction_vcvc_impl.h" + +namespace gr { + namespace dab { + + ofdm_coarse_frequency_correction_vcvc::sptr + ofdm_coarse_frequency_correction_vcvc::make(int fft_length, int num_carriers, int cyclic_prefix_length) + { + return gnuradio::get_initial_sptr + (new ofdm_coarse_frequency_correction_vcvc_impl(fft_length, num_carriers, cyclic_prefix_length)); + } + + /* + * The private constructor + */ + ofdm_coarse_frequency_correction_vcvc_impl::ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, int num_carriers, int cyclic_prefix_length) + : gr::sync_block("ofdm_coarse_frequency_correction_vcvc", + gr::io_signature::make(1, 1, fft_length*sizeof(gr_complex)), + gr::io_signature::make(1, 1, num_carriers*sizeof(gr_complex))), + d_fft_length(fft_length), + d_num_carriers(num_carriers), + d_cyclic_prefix_length(cyclic_prefix_length) + { + d_freq_offset = 0; + } + + /* + * Our virtual destructor. + */ + ofdm_coarse_frequency_correction_vcvc_impl::~ofdm_coarse_frequency_correction_vcvc_impl() + { + } + + /*! Energy measurement over the num_carriers sub_carriers + the central carrier. + * The energy gets a maximum when the calculation window and the occupied carriers are congruent. + * Fine frequency synchronization in the range of one sub-carrier spacing is already done. + */ + void + ofdm_coarse_frequency_correction_vcvc_impl::measure_energy(const gr_complex *symbol) + { + unsigned int i, index; + float energy = 0, max = 0; + // first energy measurement is processed completely + for (i=0; i max) { + max = energy; + index = i; + } + } + + d_freq_offset = index; + } + + int + ofdm_coarse_frequency_correction_vcvc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + std::vector tags; + unsigned int tag_count = 0; + // get tags for the beginning of a frame + get_tags_in_window(tags, 0, 0, noutput_items); + for (int i = 0; i < noutput_items; ++i) { + /* new calculation for each new frame, measured at the pilot symbol and frequency correction + * applied for all symbols of this frame + */ + if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0) { + measure_energy(&in[i * d_fft_length]); + fprintf(stderr, "New frame, first used sub-carrier: %d\n", d_freq_offset); + tag_count++; + } + // copy the first half (left of central sub-carrier) of the sub-carriers to the output + memcpy(out, &in[i*d_fft_length+d_freq_offset], d_num_carriers/2 * sizeof(gr_complex)); + // copy the second half (right of central sub-carrier) of the sub-carriers to the output + memcpy(out+d_num_carriers/2, &in[i*d_fft_length+d_freq_offset+d_num_carriers/2+1], d_num_carriers/2 * sizeof(gr_complex)); + out += d_num_carriers; + } + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h new file mode 100644 index 00000000..2bda1adc --- /dev/null +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_IMPL_H +#define INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_IMPL_H + +#include + +namespace gr { + namespace dab { + + class ofdm_coarse_frequency_correction_vcvc_impl : public ofdm_coarse_frequency_correction_vcvc + { + private: + int d_fft_length; + int d_num_carriers; + int d_cyclic_prefix_length; + unsigned int d_freq_offset; + + public: + ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, int num_carriers, int cyclic_prefix_length); + ~ofdm_coarse_frequency_correction_vcvc_impl(); + + void measure_energy(const gr_complex*); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_OFDM_COARSE_FREQUENCY_CORRECTION_VCVC_IMPL_H */ + diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc new file mode 100644 index 00000000..baab909d --- /dev/null +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -0,0 +1,275 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include "ofdm_synchronization_cvf_impl.h" +#include + +using namespace boost; + +namespace gr { + namespace dab { + + ofdm_synchronization_cvf::sptr + ofdm_synchronization_cvf::make(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame) + { + return gnuradio::get_initial_sptr + (new ofdm_synchronization_cvf_impl(symbol_length, cyclic_prefix_length, fft_length, symbols_per_frame)); + } + + /* + * The private constructor + */ + ofdm_synchronization_cvf_impl::ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame) + : gr::block("ofdm_synchronization_cvf", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + //gr::io_signature::make(1, 1, sizeof(gr_complex))), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_symbol_length(symbol_length), + d_cyclic_prefix_length(cyclic_prefix_length), + d_symbols_per_frame(symbols_per_frame), + d_fft_length(fft_length) + { + d_correlation = 0; + d_energy_prefix = 1; + d_energy_repetition = 1; + d_NULL_symbol_energy = 1; + d_frequency_offset = 0; + d_NULL_detected = false; + d_moving_average_counter = 0; + d_symbol_count = 0; + d_symbol_element_count = 0; + d_wait_for_NULL = true; + d_on_triangle = false; + d_control_counter = 0; + } + + /* + * Our virtual destructor. + */ + ofdm_synchronization_cvf_impl::~ofdm_synchronization_cvf_impl() + { + } + + void + ofdm_synchronization_cvf_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items + d_symbol_length + d_cyclic_prefix_length+1; + } + + void + ofdm_synchronization_cvf_impl::delayed_correlation(const gr_complex *sample, bool new_calculation) + { + if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || new_calculation) { + if (d_moving_average_counter == 0 && (!new_calculation)) { + // first value is calculated completely, next values are calculated with moving average + d_moving_average_counter++; + } else { + // reset counter + d_moving_average_counter = 0; + } + // calculate delayed correlation for this sample completely + d_correlation = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_correlation += sample[j] * conj(sample[d_symbol_length + j]); + } + // calculate energy of cyclic prefix for this sample completely + d_energy_prefix = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_prefix += std::real(sample[j] * conj(sample[j])); + } + // calculate energy of its repetition for this sample completely + d_energy_repetition = 0; + for (int j = 0; j < d_cyclic_prefix_length; j++) { + d_energy_repetition += std::real(sample[j + d_symbol_length] * conj(sample[j + d_symbol_length])); + } + } else { + // calculate next step for moving average + d_correlation += + sample[d_cyclic_prefix_length - 1] * conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); + d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * conj(sample[d_cyclic_prefix_length - 1])); + d_energy_repetition += std::real(sample[d_symbol_length + d_cyclic_prefix_length - 1] * + conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); + d_correlation -= sample[0] * conj(sample[d_symbol_length]); + d_energy_prefix -= std::real(sample[0] * conj(sample[0])); + d_energy_repetition -= std::real(sample[d_symbol_length] * conj(sample[d_symbol_length])); + d_moving_average_counter++; + } + // normalize + d_correlation_normalized = d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); + // calculate magnitude + d_correlation_normalized_magnitude = d_correlation_normalized.real() * d_correlation_normalized.real() + + d_correlation_normalized.imag() * d_correlation_normalized.imag(); + } + + /*! \brief returns true at a point with a little space before the peak of a correlation triangular + * + */ + bool + ofdm_synchronization_cvf_impl::detect_start_of_symbol() + { + if(d_on_triangle){ + if(d_correlation_normalized_magnitude < 0.5){ + // we left the triangle + d_on_triangle = false; + return false; + } + else{ + // we are still on the triangle but we already picked our pre-peak value + return false; + } + } + else{ + // not on a correlation triangle yet + if(d_correlation_normalized_magnitude > 0.85){ + // no we are on the triangle + d_on_triangle = true; + return true; + } + else{ + // no triangle here + return false; + } + } + } +/* + bool + ofdm_synchronization_cvf_impl::detect_peak() // on triangle used for detect_start_of_symbol() + { + if (!d_on_triangle && d_correlation_normalized_magnitude > 0.85) { + // over threshold, peak is coming soon + d_on_triangle = true; + return false; + } else if (d_on_triangle && d_correlation_normalized_magnitude < 0.8) { + // peak found + d_on_triangle = false; + return true; + } else { + return false; + } + }*/ + + int + ofdm_synchronization_cvf_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + d_nwritten = 0; + + for (int i = 0; i < noutput_items; ++i) { + // just for measurement reasons + if (d_wait_for_NULL) { + // acquisition mode: search for next correlation peak after a NULL symbol + delayed_correlation(&in[i], false); + if (detect_start_of_symbol()) { + if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { + // calculate new frequency offset + d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s + // set tag at beginning of new frame (first symbol after null symbol) + add_item_tag(0, nitems_written(0) + i+1, pmt::mp("Start"), + pmt::from_float(std::arg(d_correlation))); + GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%d_frequency_offset); + /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy + * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. + */ + //reset the symbol element counter + d_symbol_element_count = 0; + d_symbol_count = 0; + // reset NULL detector + d_NULL_detected = false; + // switch to tracking mode + d_wait_for_NULL = false; + } else { + //peak but not after NULL symbol + } + } else { + if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.1))) { + // NULL symbol detection, if energy is < 0.1 * energy a symbol time later + d_NULL_symbol_energy = d_energy_prefix; + d_NULL_detected = true; + } + } + } + else if (++d_symbol_element_count >= (d_symbol_length + d_cyclic_prefix_length)) { + d_symbol_count++; + // next symbol expecting + // reset symbol_element_count because we arrived at the start of the next symbol + d_symbol_element_count = 0; + // check if we arrived at the next NULL symbol + if (d_symbol_count >= d_symbols_per_frame) { + //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); + d_symbol_count = 0; + //TODO: skip forward more to safe computing many computing steps + // switch to acquisition mode again to get the start of the next frame exactly + d_wait_for_NULL = true; + } + else { + // correlation has to be calculated completely new, because of skipping samples before + delayed_correlation(&in[i], true); + //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); + // check if there is really a peak + if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge + d_frequency_offset = std::arg(d_correlation) / 0.001246; // in rad/s + //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset)); + //GR_LOG_DEBUG(d_logger, format("in track %d") % d_frequency_offset); + } else { + // no peak found -> out of track; search for next NULL symbol + d_wait_for_NULL = true; + GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)")%d_correlation_normalized_magnitude); + /*add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), + pmt::from_float(d_correlation_normalized_magnitude));*/ + } + } + } + else if(d_cyclic_prefix_length <= d_symbol_element_count){ + // now we start copying one symbol length to the output + out[d_nwritten++] = in[i] * gr_expj(-d_frequency_offset); + } + // copy sample correcting the frequency offset + //out[i] = d_correlation_normalized_magnitude;; + } + + // pass iq samples through with set tags + // memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); + + // debug output to check the delayed correlation + /*d_moving_average_counter = 0; + for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { + delayed_correlation(&in[j], false); + out[j] = d_correlation_normalized; + }*/ + consume_each(noutput_items); + return d_nwritten; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h new file mode 100644 index 00000000..98e11ef2 --- /dev/null +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_IMPL_H +#define INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_IMPL_H + +#include + +namespace gr { + namespace dab { +/*! \brief sets tag at the beginning of each OFDM frame + * + * \param symbol_length length of each OFDM symbol without guard intervall + * \param cyclic_prefix_length length of the cyclic prefix (= length of the guard intervall) + * \param num_ofdm_symbols number of OFDM symbols without the NULL symbol + * + */ + class ofdm_synchronization_cvf_impl : public ofdm_synchronization_cvf + { + private: + int d_symbol_length; + int d_cyclic_prefix_length; + int d_fft_length; + int d_moving_average_counter; + gr_complex d_correlation; + gr_complex d_correlation_normalized; + float d_correlation_normalized_magnitude; + float d_correlation_normalized_phase; + float d_energy_prefix; + float d_energy_repetition; + float d_NULL_symbol_energy; + float d_frequency_offset; + bool d_NULL_detected; + int d_symbols_per_frame; + int d_symbol_count; + int d_symbol_element_count; + bool d_wait_for_NULL; + bool d_on_triangle; + int d_control_counter; + + int d_nwritten; + + public: + ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame); + ~ofdm_synchronization_cvf_impl(); + + void delayed_correlation(const gr_complex *sample, bool new_calculation); + bool detect_peak(); + bool detect_start_of_symbol(); + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + // Where all the action really happens + int general_work(int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_IMPL_H */ + diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc index 1b2a1452..d98cbfab 100644 --- a/lib/synchronization_ff_impl.cc +++ b/lib/synchronization_ff_impl.cc @@ -54,7 +54,7 @@ namespace gr { d_cyclic_prefix_length(cyclic_prefix_length), d_num_ofdm_symbols(num_ofdm_symbols) { - //set_min_noutput_items(symbol_length + cyclic_prefix_length+1); + set_min_noutput_items(symbol_length + cyclic_prefix_length+1); d_correlation = 0; d_energy_prefix = 1; d_energy_repetition = 1; diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 7644fb41..2b9d9b9b 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -87,3 +87,4 @@ GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) GR_ADD_TEST(qa_peak_detector_fb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_peak_detector_fb.py) GR_ADD_TEST(qa_synchronization_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_synchronization_ff.py) +GR_ADD_TEST(qa_ofdm_synchronization_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronization_cvf.py) diff --git a/python/qa_ofdm_synchronization_cvf.py b/python/qa_ofdm_synchronization_cvf.py new file mode 100755 index 00000000..76a16265 --- /dev/null +++ b/python/qa_ofdm_synchronization_cvf.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 <+YOU OR YOUR COMPANY+>. +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + +class qa_ofdm_synchronization_cvf (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + # set up fg + self.tb.run () + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_ofdm_synchronization_cvf, "qa_ofdm_synchronization_cvf.xml") diff --git a/swig/dab_swig.i b/swig/dab_swig.i index d03afaef..8f30bf86 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -53,6 +53,8 @@ #include "dab/valve_ff.h" #include "dab/peak_detector_fb.h" #include "dab/synchronization_ff.h" +#include "dab/ofdm_synchronization_cvf.h" +#include "dab/ofdm_coarse_frequency_correction_vcvc.h" %} @@ -150,3 +152,7 @@ GR_SWIG_BLOCK_MAGIC2(dab, peak_detector_fb); %include "dab/synchronization_ff.h" GR_SWIG_BLOCK_MAGIC2(dab, synchronization_ff); +%include "dab/ofdm_synchronization_cvf.h" +GR_SWIG_BLOCK_MAGIC2(dab, ofdm_synchronization_cvf); +%include "dab/ofdm_coarse_frequency_correction_vcvc.h" +GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); From 3e84eb4ee2546e94cbf369d443ec94b98f59163b Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 2 Oct 2017 16:49:42 +0200 Subject: [PATCH 055/135] sync: correct fine frequency offset when cutting cyclic prefix out --- examples/dab_transmitter.grc | 12 ++++++-- grc/CMakeLists.txt | 3 +- grc/dab_ofdm_sync_dab2.xml | 7 ++++- include/dab/CMakeLists.txt | 3 +- lib/CMakeLists.txt | 3 +- lib/ofdm_ffe_all_in_one_impl.cc | 2 +- lib/ofdm_synchronization_cvf_impl.cc | 43 ++++++++++++++++------------ lib/ofdm_synchronization_cvf_impl.h | 3 +- swig/dab_swig.i | 1 + 9 files changed, 51 insertions(+), 26 deletions(-) diff --git a/examples/dab_transmitter.grc b/examples/dab_transmitter.grc index 07a7fad1..6fef72fb 100644 --- a/examples/dab_transmitter.grc +++ b/examples/dab_transmitter.grc @@ -428,10 +428,18 @@ affinity + + country_ID + 1 + dab_mode 1 + + dabplus + 1 + data_rate_n [14] @@ -481,8 +489,8 @@ 1 - programme_service_label - "jkdlsa" + programme_service_labels + "" diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 363beb7b..72a409f9 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -74,5 +74,6 @@ install(FILES dab_peak_detector_fb.xml dab_synchronization_ff.xml dab_ofdm_synchronization_cvf.xml - dab_ofdm_coarse_frequency_correction_vcvc.xml DESTINATION share/gnuradio/grc/blocks + dab_ofdm_coarse_frequency_correction_vcvc.xml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_ofdm_sync_dab2.xml b/grc/dab_ofdm_sync_dab2.xml index 320cbd73..3382da22 100644 --- a/grc/dab_ofdm_sync_dab2.xml +++ b/grc/dab_ofdm_sync_dab2.xml @@ -4,12 +4,17 @@ dab_ofdm_sync_dab2 [DAB] import dab - dab.ofdm_sync_dab2($dab_params, $rx_params, $debug) + dab.ofdm_sync_dab2(dab.parameters.dab_parameters(mode=$mode, sample_rate=$samp_rate, verbose=False), dab.parameters.receiver_parameters(mode=$mode), False) Mode mode int + + Samp_rate + samp_rate + int + in complex diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 8375e2f6..17932cd4 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -68,5 +68,6 @@ install(FILES peak_detector_fb.h synchronization_ff.h ofdm_synchronization_cvf.h - ofdm_coarse_frequency_correction_vcvc.h DESTINATION include/dab + ofdm_coarse_frequency_correction_vcvc.h + DESTINATION include/dab ) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7c8d13c2..044b6e4d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -97,7 +97,8 @@ list(APPEND dab_sources peak_detector_fb_impl.cc synchronization_ff_impl.cc ofdm_synchronization_cvf_impl.cc - ofdm_coarse_frequency_correction_vcvc_impl.cc ) + ofdm_coarse_frequency_correction_vcvc_impl.cc + ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/ofdm_ffe_all_in_one_impl.cc b/lib/ofdm_ffe_all_in_one_impl.cc index 07bfe88c..5b951c3f 100644 --- a/lib/ofdm_ffe_all_in_one_impl.cc +++ b/lib/ofdm_ffe_all_in_one_impl.cc @@ -136,7 +136,7 @@ ofdm_ffe_all_in_one_impl::work(int noutput_items, d_estimated_error = d_alpha*d_ffs_error_sum + (1-d_alpha)*d_estimated_error; /* slow adjustment */ d_estimated_error_per_sample = d_estimated_error / (float)d_fft_length; -// fprintf(stderr, "ofdm_ffe_all_in_one: d_estimated_error: %f (%3.2f Hz)\n", d_estimated_error, d_estimated_error_per_sample*d_sample_rate/(2*M_PI)); + fprintf(stderr, "ofdm_ffe_all_in_one: d_estimated_error: %f (%3.2f Hz)\n", d_estimated_error, d_estimated_error_per_sample*d_sample_rate/(2*M_PI)); } d_cur_symbol++; diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index baab909d..e43ffffc 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -29,6 +29,8 @@ #include #include "ofdm_synchronization_cvf_impl.h" #include +#include +#include using namespace boost; @@ -59,7 +61,7 @@ namespace gr { d_energy_prefix = 1; d_energy_repetition = 1; d_NULL_symbol_energy = 1; - d_frequency_offset = 0; + d_frequency_offset_per_sample = 0; d_NULL_detected = false; d_moving_average_counter = 0; d_symbol_count = 0; @@ -67,6 +69,7 @@ namespace gr { d_wait_for_NULL = true; d_on_triangle = false; d_control_counter = 0; + d_phase = 0; } /* @@ -192,11 +195,11 @@ namespace gr { if (detect_start_of_symbol()) { if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { // calculate new frequency offset - d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s + d_frequency_offset_per_sample = std::arg(d_correlation)/d_fft_length; // in rad/sample // set tag at beginning of new frame (first symbol after null symbol) add_item_tag(0, nitems_written(0) + i+1, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); - GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%d_frequency_offset); + GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%(d_frequency_offset_per_sample*2048000/(2*3.1415))); /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. */ @@ -237,9 +240,9 @@ namespace gr { //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); // check if there is really a peak if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge - d_frequency_offset = std::arg(d_correlation) / 0.001246; // in rad/s - //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset)); - //GR_LOG_DEBUG(d_logger, format("in track %d") % d_frequency_offset); + d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s + //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); + GR_LOG_DEBUG(d_logger, format("in track %d") % (d_frequency_offset_per_sample*2048000/(2*3.1415))); } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; @@ -250,22 +253,26 @@ namespace gr { } } else if(d_cyclic_prefix_length <= d_symbol_element_count){ + // calculate the complex frequency correction value + float oi, oq; + // fixed point sine and cosine + int32_t angle = gr::fxpt::float_to_fixed (d_phase); + gr::fxpt::sincos(angle, &oq, &oi); + gr_complex fine_frequency_correction = gr_complex(oi, oq); // now we start copying one symbol length to the output - out[d_nwritten++] = in[i] * gr_expj(-d_frequency_offset); + out[d_nwritten++] = in[i] * fine_frequency_correction; } - // copy sample correcting the frequency offset - //out[i] = d_correlation_normalized_magnitude;; + /* fine frequency correction: + * The frequency offset estimation is done above with the correlation. + * The modulated frequency runs parralel to the whole input stream, including the cyclic prefix, and is mixed + * to the output symbol samples. + */ + d_phase += d_frequency_offset_per_sample; + //place phase in [-pi, +pi[ + #define F_PI ((float)(M_PI)) + d_phase = std::fmod(d_phase + F_PI, 2.0f * F_PI) - F_PI; } - // pass iq samples through with set tags - // memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); - - // debug output to check the delayed correlation - /*d_moving_average_counter = 0; - for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { - delayed_correlation(&in[j], false); - out[j] = d_correlation_normalized; - }*/ consume_each(noutput_items); return d_nwritten; } diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index 98e11ef2..52e2cf04 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -46,7 +46,7 @@ namespace gr { float d_energy_prefix; float d_energy_repetition; float d_NULL_symbol_energy; - float d_frequency_offset; + float d_frequency_offset_per_sample; bool d_NULL_detected; int d_symbols_per_frame; int d_symbol_count; @@ -54,6 +54,7 @@ namespace gr { bool d_wait_for_NULL; bool d_on_triangle; int d_control_counter; + float d_phase; int d_nwritten; diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 8f30bf86..990f3bdd 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -156,3 +156,4 @@ GR_SWIG_BLOCK_MAGIC2(dab, synchronization_ff); GR_SWIG_BLOCK_MAGIC2(dab, ofdm_synchronization_cvf); %include "dab/ofdm_coarse_frequency_correction_vcvc.h" GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); + From b1b11464d063266299a26630c15ab87852ccbc2d Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 3 Oct 2017 19:32:17 +0200 Subject: [PATCH 056/135] sync: phase correction with phase reference symbol --- grc/CMakeLists.txt | 2 +- grc/dab_phase_correction_cc.xml | 20 +++ include/dab/CMakeLists.txt | 2 +- include/dab/phase_correction_cc.h | 56 +++++++ lib/CMakeLists.txt | 2 +- ...m_coarse_frequency_correction_vcvc_impl.cc | 2 +- lib/ofdm_synchronization_cvf_impl.cc | 5 +- lib/phase_correction_cc_impl.cc | 144 ++++++++++++++++++ lib/phase_correction_cc_impl.h | 57 +++++++ swig/dab_swig.i | 3 + 10 files changed, 286 insertions(+), 7 deletions(-) create mode 100644 grc/dab_phase_correction_cc.xml create mode 100644 include/dab/phase_correction_cc.h create mode 100644 lib/phase_correction_cc_impl.cc create mode 100644 lib/phase_correction_cc_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 72a409f9..28917c14 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -75,5 +75,5 @@ install(FILES dab_synchronization_ff.xml dab_ofdm_synchronization_cvf.xml dab_ofdm_coarse_frequency_correction_vcvc.xml - DESTINATION share/gnuradio/grc/blocks + dab_phase_correction_cc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_phase_correction_cc.xml b/grc/dab_phase_correction_cc.xml new file mode 100644 index 00000000..579afc4e --- /dev/null +++ b/grc/dab_phase_correction_cc.xml @@ -0,0 +1,20 @@ + + Phase correction cc + dab_phase_correction_cc + DAB + import dab + dab.phase_correction_cc($num_carriers) + + Num_carriers + num_carriers + int + + + in + complex + + + out + complex + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 17932cd4..ff2729c7 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -69,5 +69,5 @@ install(FILES synchronization_ff.h ofdm_synchronization_cvf.h ofdm_coarse_frequency_correction_vcvc.h - DESTINATION include/dab + phase_correction_cc.h DESTINATION include/dab ) diff --git a/include/dab/phase_correction_cc.h b/include/dab/phase_correction_cc.h new file mode 100644 index 00000000..64799b5b --- /dev/null +++ b/include/dab/phase_correction_cc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_PHASE_CORRECTION_CC_H +#define INCLUDED_DAB_PHASE_CORRECTION_CC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API phase_correction_cc : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::phase_correction_cc. + * + * To avoid accidental use of raw pointers, dab::phase_correction_cc's + * constructor is in a private implementation + * class. dab::phase_correction_cc::make is the public interface for + * creating new instances. + */ + static sptr make(int num_carriers); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_PHASE_CORRECTION_CC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 044b6e4d..9c32075f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -98,7 +98,7 @@ list(APPEND dab_sources synchronization_ff_impl.cc ofdm_synchronization_cvf_impl.cc ofdm_coarse_frequency_correction_vcvc_impl.cc - ) + phase_correction_cc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index f48b515a..b16d753f 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -110,7 +110,7 @@ namespace gr { */ if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0) { measure_energy(&in[i * d_fft_length]); - fprintf(stderr, "New frame, first used sub-carrier: %d\n", d_freq_offset); + //fprintf(stderr, "New frame, first used sub-carrier: %d\n", d_freq_offset); tag_count++; } // copy the first half (left of central sub-carrier) of the sub-carriers to the output diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index e43ffffc..3776fc6b 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -28,7 +28,6 @@ #include #include #include "ofdm_synchronization_cvf_impl.h" -#include #include #include @@ -199,7 +198,7 @@ namespace gr { // set tag at beginning of new frame (first symbol after null symbol) add_item_tag(0, nitems_written(0) + i+1, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); - GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%(d_frequency_offset_per_sample*2048000/(2*3.1415))); + //GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%(d_frequency_offset_per_sample*2048000/(2*3.1415))); /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. */ @@ -242,7 +241,7 @@ namespace gr { if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); - GR_LOG_DEBUG(d_logger, format("in track %d") % (d_frequency_offset_per_sample*2048000/(2*3.1415))); + //GR_LOG_DEBUG(d_logger, format("in track %d") % (d_frequency_offset_per_sample*2048000/(2*3.1415))); } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; diff --git a/lib/phase_correction_cc_impl.cc b/lib/phase_correction_cc_impl.cc new file mode 100644 index 00000000..e0e0c7bc --- /dev/null +++ b/lib/phase_correction_cc_impl.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "phase_correction_cc_impl.h" +#include +#include +#include + +namespace gr { + namespace dab { + + const uint8_t phase_correction_cc_impl::d_lookup_n[48] = {1,2,0,1,3,2,2,3,2,1,2,3,1,2,3,3,2,2,2,1,1,3,1,2,3,1,1,1,2,2,1,0,2,2,3,3,0,2,1,3,3,3,3,0,3,0,1,1}; + const uint8_t phase_correction_cc_impl::d_lookup_h[4][32] = {{0,2,0,0,0,0,1,1,2,0,0,0,2,2,1,1,0,2,0,0,0,0,1,1,2,0,0,0,2,2,1,1}, + {0,3,2,3,0,1,3,0,2,1,2,3,2,3,3,0,0,3,2,3,0,1,3,0,2,1,2,3,2,3,3,0}, + {0,0,0,2,0,2,1,3,2,2,0,2,2,0,1,3,0,0,0,2,0,2,1,3,2,2,0,2,2,0,1,3}, + {0,1,2,1,0,3,3,2,2,3,2,1,2,1,3,2,0,1,2,1,0,3,3,2,2,3,2,1,2,1,3,2}}; + + phase_correction_cc::sptr + phase_correction_cc::make(int num_carriers) + { + return gnuradio::get_initial_sptr + (new phase_correction_cc_impl(num_carriers)); + } + + /* + * The private constructor + */ + phase_correction_cc_impl::phase_correction_cc_impl(int num_carriers) + : gr::block("phase_correction_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_num_carriers(num_carriers) + {} + + /* + * Our virtual destructor. + */ + phase_correction_cc_impl::~phase_correction_cc_impl() + { + } + + void + phase_correction_cc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + float + phase_correction_cc_impl::calc_phase_diff(const gr_complex sample, int k){ + // calculate ideal phase of this phase reference sample + // k - k' + uint8_t block_position = k%32; + // i + uint8_t i = ((k-block_position)/32)%4; + // n over lookup table + uint8_t n = d_lookup_n[(k-block_position)/32]; + // h over lookup table + uint8_t h = d_lookup_h[i][block_position]; + // ideal phase over formula + #define F_PI ((float)(M_PI)) + float ideal_phase = (F_PI/2)*(h + n); + // phase of sample + float real_phase = std::arg(sample); + // phase difference + float diff = ideal_phase - real_phase; + return std::fmod(diff + F_PI, 2.0f * F_PI) - F_PI; + } + + int + phase_correction_cc_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + unsigned int offset = 0; + std::vector tags; + unsigned int tag_count = 0; + // get tags for the beginning of a frame + get_tags_in_window(tags, 0, 0, noutput_items); + + for (int i = 0; i < noutput_items; ++i) { + if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0) { + d_pilot_counter = 0; + d_phase_difference = 0; + tag_count++; + } + if(d_pilot_counter < d_num_carriers){ + // add phase difference of current sample to d_phase_difference + d_phase_difference += calc_phase_diff(in[i], d_pilot_counter++); + } + else { + if (d_pilot_counter == d_num_carriers) { + // phase reference symobl completely read, calculate average phase difference + d_phase_difference /= d_num_carriers; + //fprintf(stderr, "phase difference: %f\n", d_phase_difference); + d_pilot_counter++; + } + // calculate the complex frequency correction value + float oi, oq; + // fixed point sine and cosine + //int32_t angle = gr::fxpt::float_to_fixed (d_phase_difference); + //gr::fxpt::sincos(angle, &oq, &oi); + //gr_complex phase_correction = gr_complex(oi, oq); + gr_complex phase_correction = gr_expj(F_PI/4); + // copy samples from all non phase reference symbols to output + out[offset++] = in[i] * phase_correction; + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return offset; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/phase_correction_cc_impl.h b/lib/phase_correction_cc_impl.h new file mode 100644 index 00000000..22c6ca43 --- /dev/null +++ b/lib/phase_correction_cc_impl.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_PHASE_CORRECTION_CC_IMPL_H +#define INCLUDED_DAB_PHASE_CORRECTION_CC_IMPL_H + +#include + +namespace gr { + namespace dab { + + class phase_correction_cc_impl : public phase_correction_cc + { + private: + int d_num_carriers; + int d_pilot_counter; + float d_phase_difference; + const static uint8_t d_lookup_n[48]; + const static uint8_t d_lookup_h[4][32]; + + public: + phase_correction_cc_impl(int num_carriers); + ~phase_correction_cc_impl(); + + float calc_phase_diff(const gr_complex, int); + + // Where all the action really happens + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_PHASE_CORRECTION_CC_IMPL_H */ + diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 990f3bdd..7c9686af 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -55,6 +55,7 @@ #include "dab/synchronization_ff.h" #include "dab/ofdm_synchronization_cvf.h" #include "dab/ofdm_coarse_frequency_correction_vcvc.h" +#include "dab/phase_correction_cc.h" %} @@ -157,3 +158,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, ofdm_synchronization_cvf); %include "dab/ofdm_coarse_frequency_correction_vcvc.h" GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); +%include "dab/phase_correction_cc.h" +GR_SWIG_BLOCK_MAGIC2(dab, phase_correction_cc); From 433bb3e3b6ac58fca0a45f5bdb58454fd49e848d Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 4 Oct 2017 10:22:23 +0200 Subject: [PATCH 057/135] sync: add documentation to phase correction block --- lib/phase_correction_cc_impl.cc | 24 +++++++++++++++++------- lib/phase_correction_cc_impl.h | 7 +++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/phase_correction_cc_impl.cc b/lib/phase_correction_cc_impl.cc index e0e0c7bc..6cffa90d 100644 --- a/lib/phase_correction_cc_impl.cc +++ b/lib/phase_correction_cc_impl.cc @@ -31,6 +31,7 @@ namespace gr { namespace dab { + // lookup tabels for the generation of the pilot symbol samples const uint8_t phase_correction_cc_impl::d_lookup_n[48] = {1,2,0,1,3,2,2,3,2,1,2,3,1,2,3,3,2,2,2,1,1,3,1,2,3,1,1,1,2,2,1,0,2,2,3,3,0,2,1,3,3,3,3,0,3,0,1,1}; const uint8_t phase_correction_cc_impl::d_lookup_h[4][32] = {{0,2,0,0,0,0,1,1,2,0,0,0,2,2,1,1,0,2,0,0,0,0,1,1,2,0,0,0,2,2,1,1}, {0,3,2,3,0,1,3,0,2,1,2,3,2,3,3,0,0,3,2,3,0,1,3,0,2,1,2,3,2,3,3,0}, @@ -52,7 +53,9 @@ namespace gr { gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(gr_complex))), d_num_carriers(num_carriers) - {} + { + set_tag_propagation_policy(TPP_DONT); + } /* * Our virtual destructor. @@ -67,6 +70,15 @@ namespace gr { ninput_items_required[0] = noutput_items; } + /*! \brief Calculates phase difference of one specific sample. + * + * The phase difference of one sample of the phase reference symbol is calculated by generating the ideal phase + * of this sample and comparing it to the actual phase. + * + * @param sample incoming complex sample + * @param k index of the sample within the phase reference symbol + * @return phase difference in radians in range [-pi, +pi[ + */ float phase_correction_cc_impl::calc_phase_diff(const gr_complex sample, int k){ // calculate ideal phase of this phase reference sample @@ -118,14 +130,12 @@ namespace gr { d_phase_difference /= d_num_carriers; //fprintf(stderr, "phase difference: %f\n", d_phase_difference); d_pilot_counter++; + // this is the first sample of the first symbol after the phase reference symbol so the start of the FIC + add_item_tag(0, (nitems_written(0)+i), pmt::mp("start_of_frame"), + pmt::from_long(1)); } // calculate the complex frequency correction value - float oi, oq; - // fixed point sine and cosine - //int32_t angle = gr::fxpt::float_to_fixed (d_phase_difference); - //gr::fxpt::sincos(angle, &oq, &oi); - //gr_complex phase_correction = gr_complex(oi, oq); - gr_complex phase_correction = gr_expj(F_PI/4); + gr_complex phase_correction = gr_expj(d_phase_difference); // copy samples from all non phase reference symbols to output out[offset++] = in[i] * phase_correction; } diff --git a/lib/phase_correction_cc_impl.h b/lib/phase_correction_cc_impl.h index 22c6ca43..44f1c9a6 100644 --- a/lib/phase_correction_cc_impl.h +++ b/lib/phase_correction_cc_impl.h @@ -25,6 +25,13 @@ namespace gr { namespace dab { + /*! \brief phase correction with phase reference symbol + * The first symbol after each tag (=beginning of new frame) is the phase reference symbol. + * The phase of the samples of this symbol is known. The average phase difference from the incoming samples + * to the ideal phase is the value used for the phase correction. + * + * \param num_carriers number of used OFDM sub-carriers and therefore number of samples per symbol + */ class phase_correction_cc_impl : public phase_correction_cc { From 818386f85d9056ee104bfd9449fc06a9ef98de6a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 4 Oct 2017 11:11:50 +0200 Subject: [PATCH 058/135] sync: add frequency deinterleaver --- grc/CMakeLists.txt | 3 +- grc/dab_frequency_deinterleave_cc.xml | 20 ++++++ include/dab/CMakeLists.txt | 3 +- include/dab/frequency_deinterleave_cc.h | 56 +++++++++++++++++ lib/CMakeLists.txt | 3 +- lib/frequency_deinterleave_cc_impl.cc | 82 +++++++++++++++++++++++++ lib/frequency_deinterleave_cc_impl.h | 52 ++++++++++++++++ lib/phase_correction_cc_impl.cc | 10 +-- lib/phase_correction_cc_impl.h | 10 +-- swig/dab_swig.i | 3 + 10 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 grc/dab_frequency_deinterleave_cc.xml create mode 100644 include/dab/frequency_deinterleave_cc.h create mode 100644 lib/frequency_deinterleave_cc_impl.cc create mode 100644 lib/frequency_deinterleave_cc_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 28917c14..7654a886 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -75,5 +75,6 @@ install(FILES dab_synchronization_ff.xml dab_ofdm_synchronization_cvf.xml dab_ofdm_coarse_frequency_correction_vcvc.xml - dab_phase_correction_cc.xml DESTINATION share/gnuradio/grc/blocks + dab_phase_correction_cc.xml + dab_frequency_deinterleave_cc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_frequency_deinterleave_cc.xml b/grc/dab_frequency_deinterleave_cc.xml new file mode 100644 index 00000000..70a5979c --- /dev/null +++ b/grc/dab_frequency_deinterleave_cc.xml @@ -0,0 +1,20 @@ + + Frequency deinterleave cc + dab_frequency_deinterleave_cc + DAB + import dab + dab.frequency_deinterleave_cc($interleaving_sequence) + + Interleaving_sequence + interleaving_sequence + raw + + + in + complex + + + out + complex + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index ff2729c7..d43f9a45 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -69,5 +69,6 @@ install(FILES synchronization_ff.h ofdm_synchronization_cvf.h ofdm_coarse_frequency_correction_vcvc.h - phase_correction_cc.h DESTINATION include/dab + phase_correction_cc.h + frequency_deinterleave_cc.h DESTINATION include/dab ) diff --git a/include/dab/frequency_deinterleave_cc.h b/include/dab/frequency_deinterleave_cc.h new file mode 100644 index 00000000..12e3911e --- /dev/null +++ b/include/dab/frequency_deinterleave_cc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H +#define INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API frequency_deinterleave_cc : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::frequency_deinterleave_cc. + * + * To avoid accidental use of raw pointers, dab::frequency_deinterleave_cc's + * constructor is in a private implementation + * class. dab::frequency_deinterleave_cc::make is the public interface for + * creating new instances. + */ + static sptr make(const std::vector &interleaving_sequence); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9c32075f..399079b5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -98,7 +98,8 @@ list(APPEND dab_sources synchronization_ff_impl.cc ofdm_synchronization_cvf_impl.cc ofdm_coarse_frequency_correction_vcvc_impl.cc - phase_correction_cc_impl.cc ) + phase_correction_cc_impl.cc + frequency_deinterleave_cc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/frequency_deinterleave_cc_impl.cc b/lib/frequency_deinterleave_cc_impl.cc new file mode 100644 index 00000000..e0800552 --- /dev/null +++ b/lib/frequency_deinterleave_cc_impl.cc @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "frequency_deinterleave_cc_impl.h" + +namespace gr { + namespace dab { + + frequency_deinterleave_cc::sptr + frequency_deinterleave_cc::make(const std::vector &interleaving_sequence) + { + return gnuradio::get_initial_sptr + (new frequency_deinterleave_cc_impl(interleaving_sequence)); + } + + /* + * The private constructor + */ + frequency_deinterleave_cc_impl::frequency_deinterleave_cc_impl(const std::vector &interleaving_sequence) + : gr::sync_block("frequency_deinterleave_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_interleaving_sequence(interleaving_sequence), + d_length(interleaving_sequence.size()) + { + // check if interleaving sequency matches with its size + for (int i = 0; i < d_length; ++i) { + if (d_interleaving_sequence[i] >= d_length) { + throw std::invalid_argument((boost::format("size of interleaving element (%d) exceeds length of symbol (%d)") %(int)d_interleaving_sequence[i] %(int)d_length).str()); + } + } + set_output_multiple(d_length); + } + + /* + * Our virtual destructor. + */ + frequency_deinterleave_cc_impl::~frequency_deinterleave_cc_impl() + { + } + + int + frequency_deinterleave_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; ++i) { + out[d_interleaving_sequence[i]] = in[i]; + } + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/frequency_deinterleave_cc_impl.h b/lib/frequency_deinterleave_cc_impl.h new file mode 100644 index 00000000..f92a1632 --- /dev/null +++ b/lib/frequency_deinterleave_cc_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H +#define INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H + +#include + +namespace gr { + namespace dab { + /*! \brief DAB frequency deinterleaving + * \param interleaving_sequence vector with scrambling info + */ + + class frequency_deinterleave_cc_impl : public frequency_deinterleave_cc + { + private: + std::vector d_interleaving_sequence; + unsigned int d_length; + + public: + frequency_deinterleave_cc_impl(const std::vector &interleaving_sequence); + ~frequency_deinterleave_cc_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H */ + diff --git a/lib/phase_correction_cc_impl.cc b/lib/phase_correction_cc_impl.cc index 6cffa90d..8b94b829 100644 --- a/lib/phase_correction_cc_impl.cc +++ b/lib/phase_correction_cc_impl.cc @@ -1,17 +1,17 @@ /* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, diff --git a/lib/phase_correction_cc_impl.h b/lib/phase_correction_cc_impl.h index 44f1c9a6..83393c8b 100644 --- a/lib/phase_correction_cc_impl.h +++ b/lib/phase_correction_cc_impl.h @@ -1,17 +1,17 @@ /* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 7c9686af..50a3195e 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -56,6 +56,7 @@ #include "dab/ofdm_synchronization_cvf.h" #include "dab/ofdm_coarse_frequency_correction_vcvc.h" #include "dab/phase_correction_cc.h" +#include "dab/frequency_deinterleave_cc.h" %} @@ -160,3 +161,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); %include "dab/phase_correction_cc.h" GR_SWIG_BLOCK_MAGIC2(dab, phase_correction_cc); +%include "dab/frequency_deinterleave_cc.h" +GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); From 8d7ecc21e66dae8d104e50b7f53b93f809edff9a Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 4 Oct 2017 11:33:30 +0200 Subject: [PATCH 059/135] sync: add softbit interleaver --- grc/CMakeLists.txt | 3 +- grc/dab_complex_to_interleaved_float_cf.xml | 38 +++++++++ include/dab/CMakeLists.txt | 3 +- include/dab/complex_to_interleaved_float_cf.h | 56 +++++++++++++ lib/CMakeLists.txt | 3 +- lib/complex_to_interleaved_float_cf_impl.cc | 78 +++++++++++++++++++ lib/complex_to_interleaved_float_cf_impl.h | 55 +++++++++++++ swig/dab_swig.i | 3 + 8 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 grc/dab_complex_to_interleaved_float_cf.xml create mode 100644 include/dab/complex_to_interleaved_float_cf.h create mode 100644 lib/complex_to_interleaved_float_cf_impl.cc create mode 100644 lib/complex_to_interleaved_float_cf_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 7654a886..567bb943 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -76,5 +76,6 @@ install(FILES dab_ofdm_synchronization_cvf.xml dab_ofdm_coarse_frequency_correction_vcvc.xml dab_phase_correction_cc.xml - dab_frequency_deinterleave_cc.xml DESTINATION share/gnuradio/grc/blocks + dab_frequency_deinterleave_cc.xml + dab_complex_to_interleaved_float_cf.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_complex_to_interleaved_float_cf.xml b/grc/dab_complex_to_interleaved_float_cf.xml new file mode 100644 index 00000000..8340422b --- /dev/null +++ b/grc/dab_complex_to_interleaved_float_cf.xml @@ -0,0 +1,38 @@ + + + complex_to_interleaved_float_cf + dab_complex_to_interleaved_float_cf + dab + import dab + dab.complex_to_interleaved_float_cf($symbol_length) + + + ... + ... + ... + + + + + in + + + + + + out + + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index d43f9a45..2e3201ac 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -70,5 +70,6 @@ install(FILES ofdm_synchronization_cvf.h ofdm_coarse_frequency_correction_vcvc.h phase_correction_cc.h - frequency_deinterleave_cc.h DESTINATION include/dab + frequency_deinterleave_cc.h + complex_to_interleaved_float_cf.h DESTINATION include/dab ) diff --git a/include/dab/complex_to_interleaved_float_cf.h b/include/dab/complex_to_interleaved_float_cf.h new file mode 100644 index 00000000..2a975d07 --- /dev/null +++ b/include/dab/complex_to_interleaved_float_cf.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_H +#define INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API complex_to_interleaved_float_cf : virtual public gr::sync_interpolator + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::complex_to_interleaved_float_cf. + * + * To avoid accidental use of raw pointers, dab::complex_to_interleaved_float_cf's + * constructor is in a private implementation + * class. dab::complex_to_interleaved_float_cf::make is the public interface for + * creating new instances. + */ + static sptr make(unsigned int symbol_length); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 399079b5..477e14da 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -99,7 +99,8 @@ list(APPEND dab_sources ofdm_synchronization_cvf_impl.cc ofdm_coarse_frequency_correction_vcvc_impl.cc phase_correction_cc_impl.cc - frequency_deinterleave_cc_impl.cc ) + frequency_deinterleave_cc_impl.cc + complex_to_interleaved_float_cf_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/complex_to_interleaved_float_cf_impl.cc b/lib/complex_to_interleaved_float_cf_impl.cc new file mode 100644 index 00000000..6d813005 --- /dev/null +++ b/lib/complex_to_interleaved_float_cf_impl.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "complex_to_interleaved_float_cf_impl.h" + +namespace gr { + namespace dab { + + complex_to_interleaved_float_cf::sptr + complex_to_interleaved_float_cf::make(unsigned int symbol_length) + { + return gnuradio::get_initial_sptr + (new complex_to_interleaved_float_cf_impl(symbol_length)); + } + + /* + * The private constructor + */ + complex_to_interleaved_float_cf_impl::complex_to_interleaved_float_cf_impl(unsigned int symbol_length) + : gr::sync_interpolator("complex_to_interleaved_float_cf", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(float)), 2), + d_symbol_length(symbol_length) + { + set_output_multiple(2*symbol_length); + } + + /* + * Our virtual destructor. + */ + complex_to_interleaved_float_cf_impl::~complex_to_interleaved_float_cf_impl() + { + } + + int + complex_to_interleaved_float_cf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items/2; ++i) { + // write the real parts of the symbol first + out[i] = in[i].real(); + // write the imaginary parts of the symbol second + out[i+d_symbol_length] = in[i].imag(); + } + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/complex_to_interleaved_float_cf_impl.h b/lib/complex_to_interleaved_float_cf_impl.h new file mode 100644 index 00000000..20588478 --- /dev/null +++ b/lib/complex_to_interleaved_float_cf_impl.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_IMPL_H +#define INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_IMPL_H + +#include + +namespace gr { + namespace dab { + /*! \brief separates the real and imaginary parts of a symbol + * Separates the real and imaginary parts of a symbol by first writing all real parts as floats of the symbol + * and then consecutively the imaginary parts as floats. + * + * \param symbol_length Number of samples per symbol. (the output is symbol_length real parts followed by symbol_length imag parts) + * + */ + + class complex_to_interleaved_float_cf_impl : public complex_to_interleaved_float_cf + { + private: + unsigned int d_symbol_length; + + public: + complex_to_interleaved_float_cf_impl(unsigned int symbol_length); + ~complex_to_interleaved_float_cf_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_CF_IMPL_H */ + diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 50a3195e..350e02e0 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -57,6 +57,7 @@ #include "dab/ofdm_coarse_frequency_correction_vcvc.h" #include "dab/phase_correction_cc.h" #include "dab/frequency_deinterleave_cc.h" +#include "dab/complex_to_interleaved_float_cf.h" %} @@ -163,3 +164,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); GR_SWIG_BLOCK_MAGIC2(dab, phase_correction_cc); %include "dab/frequency_deinterleave_cc.h" GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); +%include "dab/complex_to_interleaved_float_cf.h" +GR_SWIG_BLOCK_MAGIC2(dab, complex_to_interleaved_float_cf); From f6ded4d415539fb6e142438c6821f1b496108e89 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 4 Oct 2017 15:15:24 +0200 Subject: [PATCH 060/135] sync: add demux, separating FIC and MSC after sync --- grc/CMakeLists.txt | 4 +- grc/dab_demux_cc.xml | 40 ++++++++++ include/dab/CMakeLists.txt | 3 +- include/dab/demux_cc.h | 56 ++++++++++++++ lib/CMakeLists.txt | 3 +- lib/demux_cc_impl.cc | 150 +++++++++++++++++++++++++++++++++++++ lib/demux_cc_impl.h | 64 ++++++++++++++++ swig/dab_swig.i | 3 + 8 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 grc/dab_demux_cc.xml create mode 100644 include/dab/demux_cc.h create mode 100644 lib/demux_cc_impl.cc create mode 100644 lib/demux_cc_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 567bb943..68f7b23e 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -77,5 +77,7 @@ install(FILES dab_ofdm_coarse_frequency_correction_vcvc.xml dab_phase_correction_cc.xml dab_frequency_deinterleave_cc.xml - dab_complex_to_interleaved_float_cf.xml DESTINATION share/gnuradio/grc/blocks + dab_complex_to_interleaved_float_cf.xml + dab_demux_cc.xml + dab_ofdm_demod_cc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_demux_cc.xml b/grc/dab_demux_cc.xml new file mode 100644 index 00000000..36d70ec1 --- /dev/null +++ b/grc/dab_demux_cc.xml @@ -0,0 +1,40 @@ + + + demux_cc + dab_demux_cc + dab + import dab + dab.demux_cc($symbol_length, $symbols_fic, $symbol_msc, $fillval) + + Symbol Length + symbol_length + int + + + Symbols FIC + symbols_fic + int + + + Symbol MSC + symbols_msc + int + + + Fillvalue + fillval + complex + + + in + complex + + + FIC + complex + + + MSC + complex + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 2e3201ac..e576797d 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -71,5 +71,6 @@ install(FILES ofdm_coarse_frequency_correction_vcvc.h phase_correction_cc.h frequency_deinterleave_cc.h - complex_to_interleaved_float_cf.h DESTINATION include/dab + complex_to_interleaved_float_cf.h + demux_cc.h DESTINATION include/dab ) diff --git a/include/dab/demux_cc.h b/include/dab/demux_cc.h new file mode 100644 index 00000000..68d43ae2 --- /dev/null +++ b/include/dab/demux_cc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_DEMUX_CC_H +#define INCLUDED_DAB_DEMUX_CC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API demux_cc : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::demux_cc. + * + * To avoid accidental use of raw pointers, dab::demux_cc's + * constructor is in a private implementation + * class. dab::demux_cc::make is the public interface for + * creating new instances. + */ + static sptr make(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval = gr_complex(0,0)); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_DEMUX_CC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 477e14da..8998d2ff 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -100,7 +100,8 @@ list(APPEND dab_sources ofdm_coarse_frequency_correction_vcvc_impl.cc phase_correction_cc_impl.cc frequency_deinterleave_cc_impl.cc - complex_to_interleaved_float_cf_impl.cc ) + complex_to_interleaved_float_cf_impl.cc + demux_cc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc new file mode 100644 index 00000000..9337ac44 --- /dev/null +++ b/lib/demux_cc_impl.cc @@ -0,0 +1,150 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "demux_cc_impl.h" +#include +#include +#include + +using namespace boost; + +namespace gr { + namespace dab { + + demux_cc::sptr + demux_cc::make(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) + { + return gnuradio::get_initial_sptr + (new demux_cc_impl(symbol_length, symbols_fic, symbol_msc, fillval)); + } + + /* + * The private constructor + */ + demux_cc_impl::demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) + : gr::block("demux_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_symbol_lenght(symbol_length), + d_symbols_fic(symbols_fic), + d_symbols_msc(symbol_msc), + d_fillval(fillval) + { + set_output_multiple(symbol_length); + d_symbol_count = 0; + d_fic_syms_written = 0; + d_msc_syms_written = 0; + d_on_fic = true; + } + + /* + * Our virtual destructor. + */ + demux_cc_impl::~demux_cc_impl() + { + } + + void + demux_cc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + demux_cc_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *fic_out = (gr_complex *) output_items[0]; + gr_complex *msc_out = (gr_complex *) output_items[1]; + + // get tags for the beginning of a frame + std::vector tags; + unsigned int tag_count = 0; + get_tags_in_window(tags, 0, 0, noutput_items); + // check if there are any tags between a symbol start (that must not be the case) + for (int j = 0; j < tags.size(); ++j) { + if((tags[j].offset-nitems_read(0))%d_symbol_lenght != 0){ + GR_LOG_WARN(d_logger, format("Tag detected on position (%d): not a multiple of %d!") %(int)(tags[j].offset-nitems_read(0)) %(int)d_symbol_lenght); + } + } + + for (int i = 0; i < noutput_items/d_symbol_lenght; ++i) { + if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i*d_symbol_lenght == 0) { + // a tag on this symbol: a new frame begins here + tag_count++; + // check if last written channel is full before starting new frame; when not, fill it with fillval + if(d_on_fic && d_symbol_count < d_symbols_fic){ + GR_LOG_ERROR(d_logger, format("Tag received while in FIC, fill last %d symbols with fillval") %(int)(d_symbols_fic-d_symbol_count)); + for (unsigned int j = 0; j < (d_symbols_fic-d_symbol_count)*d_symbol_lenght; ++j) { + fic_out[d_fic_syms_written*d_symbol_lenght + j] = d_fillval; + } + d_fic_syms_written += d_symbols_fic-d_symbol_count; + } + if(!d_on_fic && d_symbol_count < d_symbols_msc){ + GR_LOG_ERROR(d_logger, format("Tag received while in MSC, fill last %d symbols with fillval") %(int)(d_symbols_msc-d_symbol_count)); + for (unsigned int j = 0; j < (d_symbols_msc-d_symbol_count)*d_symbol_lenght; ++j) { + msc_out[d_msc_syms_written*d_symbol_lenght + j] = d_fillval; + } + d_msc_syms_written += d_symbols_msc-d_symbol_count; + } + d_symbol_count = 0; + // now we can start with the new frame, which always starts with fic symbols + d_on_fic = true; + } + if(d_on_fic){ + // copy next symbol to fic output + memcpy(&fic_out[d_fic_syms_written++], &in[i*d_symbol_lenght], d_symbol_lenght* sizeof(gr_complex)); + // check if all fic symbols for this frame have been sent + if(++d_symbol_count >= d_symbols_fic){ + d_on_fic = false; + d_symbol_count = 0; + } + } + else{ + // copy next symbol to msc output + memcpy(&msc_out[d_msc_syms_written++], &in[i*d_symbol_lenght], d_symbol_lenght* sizeof(gr_complex)); + // check if all msc symbols for this frame have been sent + if(++d_symbol_count >= d_symbols_msc){ + d_on_fic = true; + d_symbol_count = 0; + } + } + } + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced on each output stream separately. + produce(0, d_fic_syms_written*d_symbol_lenght); + produce(1, d_msc_syms_written*d_symbol_lenght); + return WORK_CALLED_PRODUCE; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/demux_cc_impl.h b/lib/demux_cc_impl.h new file mode 100644 index 00000000..2034f79d --- /dev/null +++ b/lib/demux_cc_impl.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_DEMUX_CC_IMPL_H +#define INCLUDED_DAB_DEMUX_CC_IMPL_H + +#include + +namespace gr { + namespace dab { + /*! \brief Separation of FIC and MSC symbols. + * \param symbol_length number of samples per symbol + * \param symbols_fic number of symbols in the fic per transmission frame + * \param symobls_mic number of symbols in the msc per transmission frame + * \param fillval complex value to fill in if sync has been lost during frame + */ + + class demux_cc_impl : public demux_cc + { + private: + unsigned int d_symbol_lenght; + unsigned int d_symbols_fic; + unsigned int d_fic_syms_written; + unsigned int d_symbols_msc; + unsigned int d_msc_syms_written; + unsigned int d_symbol_count; + bool d_on_fic; + gr_complex d_fillval; + + public: + demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval); + ~demux_cc_impl(); + + // Where all the action really happens + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_DEMUX_CC_IMPL_H */ + diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 350e02e0..0ca0fb23 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -58,6 +58,7 @@ #include "dab/phase_correction_cc.h" #include "dab/frequency_deinterleave_cc.h" #include "dab/complex_to_interleaved_float_cf.h" +#include "dab/demux_cc.h" %} @@ -166,3 +167,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, phase_correction_cc); GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); %include "dab/complex_to_interleaved_float_cf.h" GR_SWIG_BLOCK_MAGIC2(dab, complex_to_interleaved_float_cf); +%include "dab/demux_cc.h" +GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); From 97f4b4b286019c0dd524966414ecfc5bc11702a5 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sat, 7 Oct 2017 19:12:26 +0200 Subject: [PATCH 061/135] sync: fixing tag setter --- lib/ofdm_synchronization_cvf_impl.cc | 139 ++++++++++++--------------- 1 file changed, 64 insertions(+), 75 deletions(-) diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index 3776fc6b..9dff5636 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -46,7 +46,8 @@ namespace gr { /* * The private constructor */ - ofdm_synchronization_cvf_impl::ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame) + ofdm_synchronization_cvf_impl::ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, + int fft_length, int symbols_per_frame) : gr::block("ofdm_synchronization_cvf", gr::io_signature::make(1, 1, sizeof(gr_complex)), //gr::io_signature::make(1, 1, sizeof(gr_complex))), @@ -81,7 +82,7 @@ namespace gr { void ofdm_synchronization_cvf_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { - ninput_items_required[0] = noutput_items + d_symbol_length + d_cyclic_prefix_length+1; + ninput_items_required[0] = noutput_items + d_symbol_length + d_cyclic_prefix_length + 1; } void @@ -135,52 +136,33 @@ namespace gr { bool ofdm_synchronization_cvf_impl::detect_start_of_symbol() { - if(d_on_triangle){ - if(d_correlation_normalized_magnitude < 0.5){ + if (d_on_triangle) { + if (d_correlation_normalized_magnitude < 0.5) { // we left the triangle d_on_triangle = false; return false; - } - else{ + } else { // we are still on the triangle but we already picked our pre-peak value return false; } - } - else{ + } else { // not on a correlation triangle yet - if(d_correlation_normalized_magnitude > 0.85){ + if (d_correlation_normalized_magnitude > 0.85) { // no we are on the triangle d_on_triangle = true; return true; - } - else{ + } else { // no triangle here return false; } } } -/* - bool - ofdm_synchronization_cvf_impl::detect_peak() // on triangle used for detect_start_of_symbol() - { - if (!d_on_triangle && d_correlation_normalized_magnitude > 0.85) { - // over threshold, peak is coming soon - d_on_triangle = true; - return false; - } else if (d_on_triangle && d_correlation_normalized_magnitude < 0.8) { - // peak found - d_on_triangle = false; - return true; - } else { - return false; - } - }*/ int ofdm_synchronization_cvf_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; @@ -194,11 +176,8 @@ namespace gr { if (detect_start_of_symbol()) { if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { // calculate new frequency offset - d_frequency_offset_per_sample = std::arg(d_correlation)/d_fft_length; // in rad/sample - // set tag at beginning of new frame (first symbol after null symbol) - add_item_tag(0, nitems_written(0) + i+1, pmt::mp("Start"), - pmt::from_float(std::arg(d_correlation))); - //GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%(d_frequency_offset_per_sample*2048000/(2*3.1415))); + d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/sample + //GR_LOG_DEBUG(d_logger, format("Start of frame, abs offset %d")%(nitems_read(0)+i)); /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. */ @@ -217,49 +196,59 @@ namespace gr { // NULL symbol detection, if energy is < 0.1 * energy a symbol time later d_NULL_symbol_energy = d_energy_prefix; d_NULL_detected = true; + //GR_LOG_DEBUG(d_logger, format("NULL detected")); } } - } - else if (++d_symbol_element_count >= (d_symbol_length + d_cyclic_prefix_length)) { - d_symbol_count++; - // next symbol expecting - // reset symbol_element_count because we arrived at the start of the next symbol - d_symbol_element_count = 0; - // check if we arrived at the next NULL symbol - if (d_symbol_count >= d_symbols_per_frame) { - //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); - d_symbol_count = 0; - //TODO: skip forward more to safe computing many computing steps - // switch to acquisition mode again to get the start of the next frame exactly - d_wait_for_NULL = true; - } - else { - // correlation has to be calculated completely new, because of skipping samples before - delayed_correlation(&in[i], true); - //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); - // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge - d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s - //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); - //GR_LOG_DEBUG(d_logger, format("in track %d") % (d_frequency_offset_per_sample*2048000/(2*3.1415))); - } else { - // no peak found -> out of track; search for next NULL symbol + } else { // tracking mode + if (d_symbol_element_count >= (d_symbol_length + d_cyclic_prefix_length)) { + // we expect the start of a new symbol here or the a NULL symbol if we arrived at the end of the frame + d_symbol_count++; + // next symbol expecting + // reset symbol_element_count because we arrived at the start of the next symbol + d_symbol_element_count = 0; + // check if we arrived at the next NULL symbol + if (d_symbol_count >= d_symbols_per_frame) { + //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); + d_symbol_count = 0; + //TODO: skip forward more to safe computing many computing steps + // switch to acquisition mode again to get the start of the next frame exactly d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)")%d_correlation_normalized_magnitude); - /*add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), - pmt::from_float(d_correlation_normalized_magnitude));*/ + } else { + // we expect the start of a new symbol here + // correlation has to be calculated completely new, because of skipping samples before + delayed_correlation(&in[i], true); + //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); + // check if there is really a peak + if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge + d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s + //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); + //GR_LOG_DEBUG(d_logger, format("in track symbol %d") % (d_symbol_count)); + } else { + // no peak found -> out of track; search for next NULL symbol + d_wait_for_NULL = true; + GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)") % + d_correlation_normalized_magnitude); + /*add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), + pmt::from_float(d_correlation_normalized_magnitude));*/ + } } + } else if (d_cyclic_prefix_length <= d_symbol_element_count) { + // calculate the complex frequency correction value + float oi, oq; + // fixed point sine and cosine + int32_t angle = gr::fxpt::float_to_fixed(d_phase); + gr::fxpt::sincos(angle, &oq, &oi); + gr_complex fine_frequency_correction = gr_complex(oi, oq); + // set tag at next item if it is the first element of the first symbol + if (d_symbol_count == 0 && d_symbol_element_count == d_cyclic_prefix_length) { + //GR_LOG_DEBUG(d_logger, format("Set Tag %d")%(nitems_read(0)+i)); + add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), + pmt::from_float(std::arg(d_correlation))); + } + // now we start copying one symbol length to the output + out[d_nwritten++] = in[i] * fine_frequency_correction; } - } - else if(d_cyclic_prefix_length <= d_symbol_element_count){ - // calculate the complex frequency correction value - float oi, oq; - // fixed point sine and cosine - int32_t angle = gr::fxpt::float_to_fixed (d_phase); - gr::fxpt::sincos(angle, &oq, &oi); - gr_complex fine_frequency_correction = gr_complex(oi, oq); - // now we start copying one symbol length to the output - out[d_nwritten++] = in[i] * fine_frequency_correction; + d_symbol_element_count++; } /* fine frequency correction: * The frequency offset estimation is done above with the correlation. @@ -268,8 +257,8 @@ namespace gr { */ d_phase += d_frequency_offset_per_sample; //place phase in [-pi, +pi[ - #define F_PI ((float)(M_PI)) - d_phase = std::fmod(d_phase + F_PI, 2.0f * F_PI) - F_PI; +#define F_PI ((float)(M_PI)) + d_phase = std::fmod(d_phase + F_PI, 2.0f * F_PI) - F_PI; } consume_each(noutput_items); From 01c3357992586e465a3d6a0df6435b10da87a405 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sun, 8 Oct 2017 19:59:02 +0200 Subject: [PATCH 062/135] sync: new hier block ofdm_demod and fic_decode --- grc/CMakeLists.txt | 4 +- grc/dab_complex_to_interleaved_float_vcf.xml | 4 +- grc/dab_demux_cc.xml | 5 +- grc/dab_differential_phasor_vcvc.xml | 27 +++++ grc/dab_fic_decode_vc.xml | 41 +++++++ grc/dab_ofdm_demod.xml | 2 +- grc/dab_ofdm_demod_cc.xml | 69 +++++++++++ include/dab/CMakeLists.txt | 3 +- include/dab/differential_phasor_vcvc.h | 56 +++++++++ lib/CMakeLists.txt | 3 +- lib/demux_cc_impl.cc | 100 ++++++++-------- lib/demux_cc_impl.h | 4 +- lib/differential_phasor_vcvc_impl.cc | 118 +++++++++++++++++++ lib/differential_phasor_vcvc_impl.h | 52 ++++++++ lib/frequency_deinterleave_cc_impl.cc | 6 +- python/CMakeLists.txt | 4 +- python/__init__.py | 2 + python/fic.py | 3 +- python/fic_decode_vc.py | 116 ++++++++++++++++++ python/ofdm_demod_cc.py | 86 ++++++++++++++ swig/dab_swig.i | 3 + 21 files changed, 646 insertions(+), 62 deletions(-) create mode 100644 grc/dab_differential_phasor_vcvc.xml create mode 100644 grc/dab_fic_decode_vc.xml create mode 100644 grc/dab_ofdm_demod_cc.xml create mode 100644 include/dab/differential_phasor_vcvc.h create mode 100644 lib/differential_phasor_vcvc_impl.cc create mode 100644 lib/differential_phasor_vcvc_impl.h create mode 100644 python/fic_decode_vc.py create mode 100644 python/ofdm_demod_cc.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 68f7b23e..1c043802 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -79,5 +79,7 @@ install(FILES dab_frequency_deinterleave_cc.xml dab_complex_to_interleaved_float_cf.xml dab_demux_cc.xml - dab_ofdm_demod_cc.xml DESTINATION share/gnuradio/grc/blocks + dab_ofdm_demod_cc.xml + dab_differential_phasor_vcvc.xml + dab_fic_decode_vc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_complex_to_interleaved_float_vcf.xml b/grc/dab_complex_to_interleaved_float_vcf.xml index a4674f63..76cb6326 100644 --- a/grc/dab_complex_to_interleaved_float_vcf.xml +++ b/grc/dab_complex_to_interleaved_float_vcf.xml @@ -1,7 +1,7 @@ - Complex to interleaved float + Complex to interleaved float vcf dab_complex_to_interleaved_float_vcf - [DAB] + DAB import dab dab.complex_to_interleaved_float_vcf($length) diff --git a/grc/dab_demux_cc.xml b/grc/dab_demux_cc.xml index 36d70ec1..46adf7f3 100644 --- a/grc/dab_demux_cc.xml +++ b/grc/dab_demux_cc.xml @@ -4,7 +4,7 @@ dab_demux_cc dab import dab - dab.demux_cc($symbol_length, $symbols_fic, $symbol_msc, $fillval) + dab.demux_cc($symbol_length, $symbols_fic, $symbols_msc, $fillval) Symbol Length symbol_length @@ -28,13 +28,16 @@ in complex + $symbol_length FIC complex + $symbol_length MSC complex + $symbol_length diff --git a/grc/dab_differential_phasor_vcvc.xml b/grc/dab_differential_phasor_vcvc.xml new file mode 100644 index 00000000..bbd036af --- /dev/null +++ b/grc/dab_differential_phasor_vcvc.xml @@ -0,0 +1,27 @@ + + Differential phasor vcvc + dab_differential_phasor_vcvc + DAB + import dab + dab.differential_phasor_vcvc($length, $symbols_per_frame) + + Length + length + raw + + + Symbols_per_frame + symbols_per_frame + raw + + + in + complex + $length + + + out + complex + $length + + diff --git a/grc/dab_fic_decode_vc.xml b/grc/dab_fic_decode_vc.xml new file mode 100644 index 00000000..1deb2294 --- /dev/null +++ b/grc/dab_fic_decode_vc.xml @@ -0,0 +1,41 @@ + + + DAB: FIC decoder2 + dab_fic_decode_vc + [DAB] + import dab + dab.fic_decode_vc(dab.parameters.dab_parameters(mode=$dab_mode, sample_rate=$samp_rate, verbose=False)) + + DAB Mode + dab_mode + 1 + int + + + + + + + Sampling Rate + samp_rate + samp_rate + int + + + in + complex + 1536 + + diff --git a/grc/dab_ofdm_demod.xml b/grc/dab_ofdm_demod.xml index 0619753d..8038c7dd 100644 --- a/grc/dab_ofdm_demod.xml +++ b/grc/dab_ofdm_demod.xml @@ -1,6 +1,6 @@ - DAB: OFDM Demodulator + DAB: OFDM Demodulator old dab_ofdm_demod [DAB] import dab diff --git a/grc/dab_ofdm_demod_cc.xml b/grc/dab_ofdm_demod_cc.xml new file mode 100644 index 00000000..8bafa484 --- /dev/null +++ b/grc/dab_ofdm_demod_cc.xml @@ -0,0 +1,69 @@ + + + DAB: OFDM Demodulator + dab_ofdm_demod_cc + [DAB] + import dab + dab.ofdm_demod_cc( + dab.parameters.dab_parameters( + mode=$dab_mode, + sample_rate=$samp_rate, + verbose=False + ) + ) + + + DAB Mode + dab_mode + 1 + enum + + + + + + + Sampling Rate + samp_rate + samp_rate + int + + + in + complex + + + FIC + complex + 1536 + + + MSC + complex + 1536 + + + Demodulates a whole DAB signal. + Output vector size depends on selected mode: + Mode I: 1536 complex samples or 384 bytes + Mode II: 384 complex samples or 96 bytes + Mode III: 192 complex samples or 48 bytes + Mode IV: 768 complex samples or 192 bytes + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index e576797d..b2e9a193 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -72,5 +72,6 @@ install(FILES phase_correction_cc.h frequency_deinterleave_cc.h complex_to_interleaved_float_cf.h - demux_cc.h DESTINATION include/dab + demux_cc.h + differential_phasor_vcvc.h DESTINATION include/dab ) diff --git a/include/dab/differential_phasor_vcvc.h b/include/dab/differential_phasor_vcvc.h new file mode 100644 index 00000000..25477fb2 --- /dev/null +++ b/include/dab/differential_phasor_vcvc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_H +#define INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API differential_phasor_vcvc : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::differential_phasor_vcvc. + * + * To avoid accidental use of raw pointers, dab::differential_phasor_vcvc's + * constructor is in a private implementation + * class. dab::differential_phasor_vcvc::make is the public interface for + * creating new instances. + */ + static sptr make(unsigned int length, unsigned int symbols_per_frame); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8998d2ff..dd97ff9f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -101,7 +101,8 @@ list(APPEND dab_sources phase_correction_cc_impl.cc frequency_deinterleave_cc_impl.cc complex_to_interleaved_float_cf_impl.cc - demux_cc_impl.cc ) + demux_cc_impl.cc + differential_phasor_vcvc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc index 9337ac44..5e1a2f11 100644 --- a/lib/demux_cc_impl.cc +++ b/lib/demux_cc_impl.cc @@ -45,17 +45,17 @@ namespace gr { */ demux_cc_impl::demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) : gr::block("demux_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(gr_complex))), + gr::io_signature::make(1, 1, sizeof(gr_complex)*symbol_length), + gr::io_signature::make(2, 2, sizeof(gr_complex)*symbol_length)), d_symbol_lenght(symbol_length), d_symbols_fic(symbols_fic), d_symbols_msc(symbol_msc), d_fillval(fillval) { - set_output_multiple(symbol_length); + set_tag_propagation_policy(TPP_DONT); d_symbol_count = 0; - d_fic_syms_written = 0; - d_msc_syms_written = 0; + d_fic_counter = 0; + d_msc_counter = 0; d_on_fic = true; } @@ -81,67 +81,69 @@ namespace gr { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *fic_out = (gr_complex *) output_items[0]; gr_complex *msc_out = (gr_complex *) output_items[1]; + unsigned int nconsumed = 0; + unsigned int fic_syms_written = 0; + unsigned int msc_syms_written = 0; // get tags for the beginning of a frame std::vector tags; unsigned int tag_count = 0; get_tags_in_window(tags, 0, 0, noutput_items); - // check if there are any tags between a symbol start (that must not be the case) - for (int j = 0; j < tags.size(); ++j) { - if((tags[j].offset-nitems_read(0))%d_symbol_lenght != 0){ - GR_LOG_WARN(d_logger, format("Tag detected on position (%d): not a multiple of %d!") %(int)(tags[j].offset-nitems_read(0)) %(int)d_symbol_lenght); - } - } - for (int i = 0; i < noutput_items/d_symbol_lenght; ++i) { - if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i*d_symbol_lenght == 0) { - // a tag on this symbol: a new frame begins here - tag_count++; - // check if last written channel is full before starting new frame; when not, fill it with fillval - if(d_on_fic && d_symbol_count < d_symbols_fic){ - GR_LOG_ERROR(d_logger, format("Tag received while in FIC, fill last %d symbols with fillval") %(int)(d_symbols_fic-d_symbol_count)); - for (unsigned int j = 0; j < (d_symbols_fic-d_symbol_count)*d_symbol_lenght; ++j) { - fic_out[d_fic_syms_written*d_symbol_lenght + j] = d_fillval; - } - d_fic_syms_written += d_symbols_fic-d_symbol_count; + /*fprintf(stderr, "Work call ####################################\n"); + fprintf(stderr, "nitems_read %d\n", nitems_read(0)); + fprintf(stderr, "noutput_items %d\n", noutput_items); + fprintf(stderr, "Tags: %d\n", tags.size()); + if(tags.size()>0){ + fprintf(stderr, "Tag offset %d\n", tags[tag_count].offset); + }*/ + for (int i = 0; i < noutput_items; ++i) { + if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0) - nconsumed == 0) { + //fprintf(stderr, "Tag detected\n"); + // this input symbol is tagged: a new frame begins here + if(d_fic_counter%d_symbols_fic == 0 && d_msc_counter%d_symbols_msc == 0){ + //fprintf(stderr, "Tag is at beginning of frame\n"); + // we are at the beginning of a frame and also finished writing the last frame + // we can remove this first symbol of the frame (phase reference symbol) and copy the other symbols + tag_count++; + nconsumed++; + d_fic_counter = 0; + d_msc_counter = 0; } - if(!d_on_fic && d_symbol_count < d_symbols_msc){ - GR_LOG_ERROR(d_logger, format("Tag received while in MSC, fill last %d symbols with fillval") %(int)(d_symbols_msc-d_symbol_count)); - for (unsigned int j = 0; j < (d_symbols_msc-d_symbol_count)*d_symbol_lenght; ++j) { - msc_out[d_msc_syms_written*d_symbol_lenght + j] = d_fillval; + else{ + // we did not finish the last frame, maybe we lost track in sync + // lets fill the remaining symbols with fillval before continuing with the new input frame + if(d_fic_counter%d_symbols_fic != 0){ + memset(&fic_out[fic_syms_written++*d_symbol_lenght], 0, d_symbol_lenght * sizeof(gr_complex)); + d_fic_counter++; + } + else{ + memset(&msc_out[msc_syms_written++*d_symbol_lenght], 0, d_symbol_lenght * sizeof(gr_complex)); + d_msc_counter++; } - d_msc_syms_written += d_symbols_msc-d_symbol_count; } - d_symbol_count = 0; - // now we can start with the new frame, which always starts with fic symbols - d_on_fic = true; } - if(d_on_fic){ - // copy next symbol to fic output - memcpy(&fic_out[d_fic_syms_written++], &in[i*d_symbol_lenght], d_symbol_lenght* sizeof(gr_complex)); - // check if all fic symbols for this frame have been sent - if(++d_symbol_count >= d_symbols_fic){ - d_on_fic = false; - d_symbol_count = 0; - } + else if (d_fic_counter < d_symbols_fic){ + // copy this symbol to fic output + memcpy(&fic_out[fic_syms_written++*d_symbol_lenght], &in[nconsumed++*d_symbol_lenght], d_symbol_lenght * sizeof(gr_complex)); + d_fic_counter++; } - else{ - // copy next symbol to msc output - memcpy(&msc_out[d_msc_syms_written++], &in[i*d_symbol_lenght], d_symbol_lenght* sizeof(gr_complex)); - // check if all msc symbols for this frame have been sent - if(++d_symbol_count >= d_symbols_msc){ - d_on_fic = true; - d_symbol_count = 0; - } + else if (d_msc_counter < d_symbols_msc){ + // copy this output to msc output + memcpy(&msc_out[msc_syms_written++*d_symbol_lenght], &in[nconsumed++*d_symbol_lenght], d_symbol_lenght * sizeof(gr_complex)); + d_msc_counter++; } } // Tell runtime system how many input items we consumed on // each input stream. - consume_each (noutput_items); + consume_each (nconsumed); // Tell runtime system how many output items we produced on each output stream separately. - produce(0, d_fic_syms_written*d_symbol_lenght); - produce(1, d_msc_syms_written*d_symbol_lenght); + produce(0, fic_syms_written); + produce(1, msc_syms_written); + //fprintf(stderr, "fic_syms_written %d\n", fic_syms_written); + //fprintf(stderr, "msc_syms_written %d\n", msc_syms_written); + //fprintf(stderr, "nconsumed %d\n", nconsumed); return WORK_CALLED_PRODUCE; } diff --git a/lib/demux_cc_impl.h b/lib/demux_cc_impl.h index 2034f79d..249831b7 100644 --- a/lib/demux_cc_impl.h +++ b/lib/demux_cc_impl.h @@ -37,9 +37,9 @@ namespace gr { private: unsigned int d_symbol_lenght; unsigned int d_symbols_fic; - unsigned int d_fic_syms_written; + unsigned int d_fic_counter; unsigned int d_symbols_msc; - unsigned int d_msc_syms_written; + unsigned int d_msc_counter; unsigned int d_symbol_count; bool d_on_fic; gr_complex d_fillval; diff --git a/lib/differential_phasor_vcvc_impl.cc b/lib/differential_phasor_vcvc_impl.cc new file mode 100644 index 00000000..729c6aaf --- /dev/null +++ b/lib/differential_phasor_vcvc_impl.cc @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "differential_phasor_vcvc_impl.h" + +namespace gr { + namespace dab { + + differential_phasor_vcvc::sptr + differential_phasor_vcvc::make(unsigned int length, unsigned int symbols_per_frame) + { + return gnuradio::get_initial_sptr + (new differential_phasor_vcvc_impl(length, symbols_per_frame)); + } + + /* + * The private constructor + */ + differential_phasor_vcvc_impl::differential_phasor_vcvc_impl(unsigned int length, unsigned int symbols_per_frame) + : gr::block("differential_phasor_vcvc", + gr::io_signature::make(1, 1, sizeof(gr_complex)*length), + gr::io_signature::make(1, 1, sizeof(gr_complex)*length)), + d_length(length), + d_symbols_per_frame(symbols_per_frame) + { + set_min_noutput_items(3); + } + + /* + * Our virtual destructor. + */ + differential_phasor_vcvc_impl::~differential_phasor_vcvc_impl() + { + } + + void + differential_phasor_vcvc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + differential_phasor_vcvc_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + fprintf(stderr, "Work call ####################################\n"); + fprintf(stderr, "nitems_read %d\n", nitems_read(0)); + fprintf(stderr, "noutput_items %d\n", noutput_items); + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + unsigned int symbols_written = 0; + + // get tags for the beginning of a frame + std::vector tags; + unsigned int tag_count = 0; + //get_tags_in_window(tags, 0, , noutput_items); + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); + fprintf(stderr, "number of tags: %d\n", tags.size()); + if(tags[tag_count].offset-nitems_read(0) == 0){ + fprintf(stderr, "Tag at beginning, pos %d\n", tags[tag_count].offset); + tag_count++; + } + + for (int i = 1; i < noutput_items; ++i) { + // reset symbol counter if tag is coming in + if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0){ + fprintf(stderr, "Tag at pos %d\n", tags[tag_count].offset); + /* start of frame -> this symbol is a phase reference symbol + * we need it to calculate the phase diff of the next symbol, so we just consume it now + */ + tag_count++; + } + else{ + // this is any other symbol than the phase reference symbol, and we calculate the diff to its predecessor + for(unsigned int j = 0; j < d_length; j++){ + //out[symbols_written*d_length+j] = in[(i+1)*d_length+j] * conj(in[i*d_length+j]); + out[symbols_written*d_length+j] = in[i*d_length+j] * conj(in[(i-1)*d_length+j]); + } + ++symbols_written; + } + } + + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items-1); + fprintf(stderr, "consume each %d\n", noutput_items-1); + + // Tell runtime system how many output items we produced. + return symbols_written; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/differential_phasor_vcvc_impl.h b/lib/differential_phasor_vcvc_impl.h new file mode 100644 index 00000000..f03b1683 --- /dev/null +++ b/lib/differential_phasor_vcvc_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_IMPL_H +#define INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_IMPL_H + +#include + +namespace gr { + namespace dab { + + class differential_phasor_vcvc_impl : public differential_phasor_vcvc + { + private: + unsigned int d_length; + unsigned int d_symbols_per_frame; + + public: + differential_phasor_vcvc_impl(unsigned int length, unsigned int symbols_per_frame); + ~differential_phasor_vcvc_impl(); + + // Where all the action really happens + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_DIFFERENTIAL_PHASOR_VCVC_IMPL_H */ + diff --git a/lib/frequency_deinterleave_cc_impl.cc b/lib/frequency_deinterleave_cc_impl.cc index e0800552..a43f271a 100644 --- a/lib/frequency_deinterleave_cc_impl.cc +++ b/lib/frequency_deinterleave_cc_impl.cc @@ -69,8 +69,10 @@ namespace gr { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - for (int i = 0; i < noutput_items; ++i) { - out[d_interleaving_sequence[i]] = in[i]; + for (int i = 0; i < noutput_items/d_length; ++i) { + for (int j = 0; j < d_length; ++j) { + out[i*d_length + d_interleaving_sequence[j]] = in[i*d_length + j]; + } } // Tell runtime system how many output items we produced. diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 2b9d9b9b..098edf61 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -53,7 +53,9 @@ GR_PYTHON_INSTALL( msc_encode.py transmitter_c.py ${CMAKE_CURRENT_BINARY_DIR}/constants.py - dabplus_audio_decoder_ff.py DESTINATION ${GR_PYTHON_DIR}/dab + dabplus_audio_decoder_ff.py + ofdm_demod_cc.py + fic_decode_vc.py DESTINATION ${GR_PYTHON_DIR}/dab ) ######################################################################## diff --git a/python/__init__.py b/python/__init__.py index dfaae6f9..c581fc76 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -44,5 +44,7 @@ from msc_encode import msc_encode from transmitter_c import transmitter_c from dabplus_audio_decoder_ff import dabplus_audio_decoder_ff +from ofdm_demod_cc import ofdm_demod_cc +from fic_decode_vc import fic_decode_vc import constants # diff --git a/python/fic.py b/python/fic.py index 0c2e0e3d..7ec29fbd 100644 --- a/python/fic.py +++ b/python/fic.py @@ -48,7 +48,8 @@ def __init__(self, dab_params, verbose=False, debug=False): @param dab_params DAB parameter object (dab.parameters.dab_parameters) """ gr.hier_block2.__init__(self, "fic", - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + #gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + gr.io_signature2(1, 1, gr.sizeof_float * dab_params.num_carriers * 2), gr.io_signature(1, 1, gr.sizeof_char * 32)) self.dp = dab_params diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py new file mode 100644 index 00000000..378608e2 --- /dev/null +++ b/python/fic_decode_vc.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, trellis, blocks +import dab +from math import sqrt + +class fic_decode_vc(gr.hier_block2): + """ + @brief block to decode FIBs (fast information blocks) from the FIC (fast information channel) of a demodulated DAB signal + + - get demodulated FIC from transmission frame + - do convolutional decoding + - undo energy dispersal + - get FIC information + """ + def __init__(self, dab_params): + gr.hier_block2.__init__(self, + "fic_decode_vc", + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Input signature + gr.io_signature(0, 0, gr.sizeof_char)) # Output signature + + self.dp = dab_params + + # complex to intereaved float for convolutional decoding + self.c2f = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers) + + # FIB block partitioning + self.v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers * 2) + self.s2v = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.fic_punctured_codeword_length) + + # unpuncturing + self.unpuncture = dab.unpuncture_vff(self.dp.assembled_fic_puncturing_sequence, 0) + + # convolutional coding + # self.fsm = trellis.fsm(self.dp.conv_code_in_bits, self.dp.conv_code_out_bits, self.dp.conv_code_generator_polynomials) + self.fsm = trellis.fsm(1, 4, [0133, 0171, 0145, 0133]) # OK (dumped to text and verified partially) + self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.dp.fic_conv_codeword_length) + # self.conv_decode = trellis.viterbi_combined_fb(self.fsm, 20, 0, 0, 1, [1./sqrt(2),-1/sqrt(2)] , trellis.TRELLIS_EUCLIDEAN) + table = [ + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 1, 0, + 0, 0, 1, 1, + 0, 1, 0, 0, + 0, 1, 0, 1, + 0, 1, 1, 0, + 0, 1, 1, 1, + 1, 0, 0, 0, + 1, 0, 0, 1, + 1, 0, 1, 0, + 1, 0, 1, 1, + 1, 1, 0, 0, + 1, 1, 0, 1, + 1, 1, 1, 0, + 1, 1, 1, 1 + ] + assert (len(table) / 4 == self.fsm.O()) + table = [(1 - 2 * x) / sqrt(2) for x in table] + self.conv_decode = trellis.viterbi_combined_fb(self.fsm, 774, 0, 0, 4, table, trellis.TRELLIS_EUCLIDEAN) + # self.conv_s2v = blocks.stream_to_vector(gr.sizeof_char, 774) + self.conv_prune = dab.prune(gr.sizeof_char, self.dp.fic_conv_codeword_length / 4, 0, + self.dp.conv_code_add_bits_input) + + # energy dispersal + self.prbs_src = blocks.vector_source_b(self.dp.prbs(self.dp.energy_dispersal_fic_vector_length), True) + # self.energy_v2s = blocks.vector_to_stream(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length) + self.add_mod_2 = blocks.xor_bb() + self.energy_s2v = blocks.stream_to_vector(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length) + self.cut_into_fibs = dab.repartition_vectors(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length, + self.dp.fib_bits, 1, self.dp.energy_dispersal_fic_fibs_per_vector) + + # connect all + self.nullsink = blocks.null_sink(gr.sizeof_char) + self.pack = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) + self.fibout = blocks.stream_to_vector(1, 32) + # self.filesink = gr.file_sink(gr.sizeof_char, "debug/fic.dat") + self.fibsink = dab.fib_sink_vb() + + # self.connect((self,0), (self.select_fic_syms,0), (self.repartition_fic,0), self.unpuncture, self.conv_v2s, self.conv_decode, self.conv_s2v, self.conv_prune, self.energy_v2s, self.add_mod_2, self.energy_s2v, (self.cut_into_fibs,0), gr.vector_to_stream(1,256), gr.unpacked_to_packed_bb(1,gr.GR_MSB_FIRST), self.filesink) + self.connect((self, 0), + self.c2f, + self.v2s, + self.s2v, + self.unpuncture, + self.conv_v2s, + self.conv_decode, + # self.conv_s2v, + self.conv_prune, + # self.energy_v2s, + self.add_mod_2, + #self.energy_s2v, + #(self.cut_into_fibs, 0), + #blocks.vector_to_stream(1, 256), + self.pack, + self.fibout, + self.fibsink) + self.connect(self.prbs_src, (self.add_mod_2, 1)) diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py new file mode 100644 index 00000000..5d812cd7 --- /dev/null +++ b/python/ofdm_demod_cc.py @@ -0,0 +1,86 @@ +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, blocks +from gnuradio import fft +from gnuradio import digital +import dab + +class ofdm_demod_cc(gr.hier_block2): + """ + @brief block to demodulate the DAB OFDM + + - fine time and frequency synchronization + - FFT + - coarse frequency correction (sub-carrier assignment) + - differential phasor + - phase correction with phase reference symbol + - frequency deinterleaving + - demux into FIC and MSC + """ + def __init__(self, dab_params): + gr.hier_block2.__init__(self, + "ofdm_demod_cc", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(2, 2, gr.sizeof_gr_complex*1536)) # Output signature + + self.dp = dab_params + + # fine time and frequency synchronization + self.sync = dab.ofdm_synchronization_cvf_make(self.dp.fft_length, + self.dp.cp_length, + self.dp.fft_length, + self.dp.symbols_per_frame) + + # FFT + self.s2v_fft = blocks.stream_to_vector_make(gr.sizeof_gr_complex, self.dp.fft_length) + self.fft = fft.fft_vcc(self.dp.fft_length, True, [], True) + + # coarse frequency correction (sub-carrier assignment) + self.coarse_freq_corr = dab.ofdm_coarse_frequency_correction_vcvc_make(self.dp.fft_length, + self.dp.num_carriers, + self.dp.cp_length) + self.v2s_fft = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dp.num_carriers) + + # differential phasor + self.differential_phasor = dab.diff_phasor_vcc_make(1536) + + # phase correction with phase reference symbol + self.phase_correction = dab.phase_correction_cc_make(self.dp.num_carriers) + + # frequency deinterleaving + self.frequency_deinterleaver = dab.frequency_interleaver_vcc_make(self.dp.frequency_deinterleaving_sequence_array) + + # demux into FIC and MSC + self.demux = dab.demux_cc_make(self.dp.num_carriers, + 3, 72, 0+0j) + + self.connect( + self, + self.sync, + self.s2v_fft, + self.fft, + self.coarse_freq_corr, + #self.v2s_fft, + self.differential_phasor, + self.frequency_deinterleaver, + self.demux, + (self, 0) + ) + self.connect((self.demux, 1), (self, 1)) diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 0ca0fb23..04b83997 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -59,6 +59,7 @@ #include "dab/frequency_deinterleave_cc.h" #include "dab/complex_to_interleaved_float_cf.h" #include "dab/demux_cc.h" +#include "dab/differential_phasor_vcvc.h" %} @@ -169,3 +170,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); GR_SWIG_BLOCK_MAGIC2(dab, complex_to_interleaved_float_cf); %include "dab/demux_cc.h" GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); +%include "dab/differential_phasor_vcvc.h" +GR_SWIG_BLOCK_MAGIC2(dab, differential_phasor_vcvc); From d638cfc4286f963530f2438b24288c9bb73ad110 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 9 Oct 2017 18:27:15 +0200 Subject: [PATCH 063/135] msc_decode: adapt to new sync structure --- python/dabplus_audio_decoder_ff.py | 8 ++--- python/msc_decode.py | 47 ++++++++++++------------------ 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index b6da1ae8..fcc583cd 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -39,15 +39,14 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Output signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_float)) else: # output signed 16 bit integers (directly from decoder) gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, - gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Output signature gr.io_signature2(2, 2, gr.sizeof_short, gr.sizeof_short)) self.dp = dab_params @@ -75,8 +74,7 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output # mp4 decoder self.mp4 = dab.mp4_decode_bs_make(self.bit_rate_n) - self.connect((self, 0), (self.msc_decoder, 0), self.firecode, self.rs, self.mp4) - self.connect((self, 1), (self.msc_decoder, 1)) + self.connect((self, 0), self.msc_decoder, self.firecode, self.rs, self.mp4) if self.output_float: # map short samples to the range [-1,1] in floats diff --git a/python/msc_decode.py b/python/msc_decode.py index 712bbb49..99c4dde1 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -27,7 +27,7 @@ class msc_decode(gr.hier_block2): """ @brief block to extract and decode a sub-channel out of the MSC (Main Service Channel) of a demodulated transmission frame - - get MSC from byte stream + - get demodulated FIC OFDM symbols from transmission frame - repartition MSC to CIFs (Common Interleaved Frames) - select a subchannel and extraxt it (dump rest of CIF) - do time deinterleaving @@ -40,13 +40,16 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F gr.hier_block2.__init__(self, "msc_decode", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Output signature gr.io_signature(1, 1, gr.sizeof_char)) self.dp = dab_params self.address = address + print "address: " + str(self.address) self.size = size + print "size: " + str(self.size) self.protect = protection + print "protection: " + str(self.protect) self.verbose = verbose self.debug = debug @@ -77,24 +80,18 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F #sanity check assert(6*self.n == self.puncturing_L1[self.protect] + self.puncturing_L2[self.protect]) + # complex to interleaved float: now we really have softbits (each float represents a bit on its exact place) + self.c2f = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers) - # MSC selection and block partitioning - # select OFDM carriers with MSC - self.select_msc_syms = dab.select_vectors(gr.sizeof_float, self.dp.num_carriers * 2, self.dp.num_msc_syms, - self.dp.num_fic_syms) - # repartition MSC data in CIFs (left out due to heavy burden for scheduler and not really necessary) - #self.repartition_msc_to_CIFs = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers * 2, - # self.dp.cif_bits, self.dp.num_msc_syms, - # self.dp.num_cifs) - #repartition MSC to CUs - self.repartition_msc_to_cus = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers*2, self.dp.msc_cu_size, self.dp.num_msc_syms, self.dp.num_cus * self.dp.num_cifs) - - # select CUs of one subchannel of each CIF and form logical frame vector - self.select_subch = dab.select_subch_vfvf_make(self.dp.msc_cu_size, self.dp.msc_cu_size * self.size, self.address, self.dp.num_cus) + # rearrange softbit vectors to CUs (capacity units) + self.v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers*2) + self.s2v = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.msc_cu_size) + self.select_subch = dab.select_cus_vcvc_make(self.dp.msc_cu_size, self.dp.num_cus, self.address, self.size) # time deinterleaving - self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size * self.size) + self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size) self.time_deinterleaver = dab.time_deinterleave_ff_make(self.dp.msc_cu_size * self.size, self.dp.scrambling_vector) + # unpuncture self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.msc_punctured_codeword_length) self.unpuncture = dab.unpuncture_ff_make(self.assembled_msc_puncturing_sequence, 0) @@ -137,11 +134,10 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F # connect blocks self.connect((self, 0), - (self.select_msc_syms, 0), - #(self.repartition_msc_to_CIFs, 0), - (self.repartition_msc_to_cus, 0), - (self.select_subch, 0), - #(self.repartition_cus_to_logical_frame, 0), + self.c2f, + self.v2s, + self.s2v, + self.select_subch, self.time_v2s, self.time_deinterleaver, #self.conv_v2s, @@ -154,14 +150,7 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F self.pack_bits, #self.energy_s2v, #better output stream or vector?? (self)) - #connect trigger chain - self.connect((self, 1), - (self.select_msc_syms, 1), - #(self.repartition_msc_to_CIFs, 1), - (self.repartition_msc_to_cus, 1), - #(self.select_subch, 1), - #(self.repartition_CUs_to_logical_frame, 1); - blocks.null_sink(gr.sizeof_char)) + # connect prbs for energy descramble self.connect(self.prbs_src, (self.add_mod_2, 1)) From b79d2ec2e0f73726c767c8508bfbc225f60ac1d0 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 9 Oct 2017 23:25:00 +0200 Subject: [PATCH 064/135] sync: new sync still with trigger stream --- grc/dab_dabplus_audio_decoder_ff.xml | 6 ++-- grc/dab_msc_decode.xml | 36 +++++++++++++++++---- grc/dab_ofdm_demod_cc.xml | 11 +++---- python/dabplus_audio_decoder_ff.py | 8 +++-- python/fic_decode_vc.py | 2 +- python/msc_decode.py | 47 +++++++++++++++++----------- python/ofdm_demod_cc.py | 16 +++++++--- 7 files changed, 84 insertions(+), 42 deletions(-) diff --git a/grc/dab_dabplus_audio_decoder_ff.xml b/grc/dab_dabplus_audio_decoder_ff.xml index f87d34f9..f2325e67 100644 --- a/grc/dab_dabplus_audio_decoder_ff.xml +++ b/grc/dab_dabplus_audio_decoder_ff.xml @@ -76,11 +76,11 @@ dat - complex - 1536 + float + 1536*2 - sync + dat byte diff --git a/grc/dab_msc_decode.xml b/grc/dab_msc_decode.xml index ded89796..1c266ff4 100644 --- a/grc/dab_msc_decode.xml +++ b/grc/dab_msc_decode.xml @@ -4,14 +4,37 @@ dab_msc_decode [DAB] import dab - dab.msc_decode($dab_params, $address, $size, $protection, $verbose, $debug) + dab.msc_decode(dab.parameters.dab_parameters(mode=$dab_mode, sample_rate=$samp_rate, verbose=False), $address, $size, $protection, $verbose, $debug) - DAB parameter - dab_params - raw + DAB Mode + dab_mode + 1 + int + + + + - subchannel address + Sampling Rate + samp_rate + samp_rate + int + + + Subchannel address address int @@ -68,8 +91,9 @@ - data + MSC symbols float + 1536*2 trigger diff --git a/grc/dab_ofdm_demod_cc.xml b/grc/dab_ofdm_demod_cc.xml index 8bafa484..24b54014 100644 --- a/grc/dab_ofdm_demod_cc.xml +++ b/grc/dab_ofdm_demod_cc.xml @@ -49,14 +49,13 @@ complex - FIC - complex - 1536 + data + float + 1536*2 - MSC - complex - 1536 + trigger + byte Demodulates a whole DAB signal. diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index fcc583cd..b6da1ae8 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -39,14 +39,15 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), + gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), # Output signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_float)) else: # output signed 16 bit integers (directly from decoder) gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), + gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, + gr.sizeof_char), # Output signature gr.io_signature2(2, 2, gr.sizeof_short, gr.sizeof_short)) self.dp = dab_params @@ -74,7 +75,8 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output # mp4 decoder self.mp4 = dab.mp4_decode_bs_make(self.bit_rate_n) - self.connect((self, 0), self.msc_decoder, self.firecode, self.rs, self.mp4) + self.connect((self, 0), (self.msc_decoder, 0), self.firecode, self.rs, self.mp4) + self.connect((self, 1), (self.msc_decoder, 1)) if self.output_float: # map short samples to the range [-1,1] in floats diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py index 378608e2..ce13b775 100644 --- a/python/fic_decode_vc.py +++ b/python/fic_decode_vc.py @@ -27,7 +27,7 @@ class fic_decode_vc(gr.hier_block2): """ @brief block to decode FIBs (fast information blocks) from the FIC (fast information channel) of a demodulated DAB signal - - get demodulated FIC from transmission frame + - get demodulated FIC OFDM symbols from transmission frame - do convolutional decoding - undo energy dispersal - get FIC information diff --git a/python/msc_decode.py b/python/msc_decode.py index 99c4dde1..712bbb49 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -27,7 +27,7 @@ class msc_decode(gr.hier_block2): """ @brief block to extract and decode a sub-channel out of the MSC (Main Service Channel) of a demodulated transmission frame - - get demodulated FIC OFDM symbols from transmission frame + - get MSC from byte stream - repartition MSC to CIFs (Common Interleaved Frames) - select a subchannel and extraxt it (dump rest of CIF) - do time deinterleaving @@ -40,16 +40,13 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F gr.hier_block2.__init__(self, "msc_decode", # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), + gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), # Output signature gr.io_signature(1, 1, gr.sizeof_char)) self.dp = dab_params self.address = address - print "address: " + str(self.address) self.size = size - print "size: " + str(self.size) self.protect = protection - print "protection: " + str(self.protect) self.verbose = verbose self.debug = debug @@ -80,18 +77,24 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F #sanity check assert(6*self.n == self.puncturing_L1[self.protect] + self.puncturing_L2[self.protect]) - # complex to interleaved float: now we really have softbits (each float represents a bit on its exact place) - self.c2f = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers) - # rearrange softbit vectors to CUs (capacity units) - self.v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers*2) - self.s2v = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.msc_cu_size) - self.select_subch = dab.select_cus_vcvc_make(self.dp.msc_cu_size, self.dp.num_cus, self.address, self.size) + # MSC selection and block partitioning + # select OFDM carriers with MSC + self.select_msc_syms = dab.select_vectors(gr.sizeof_float, self.dp.num_carriers * 2, self.dp.num_msc_syms, + self.dp.num_fic_syms) + # repartition MSC data in CIFs (left out due to heavy burden for scheduler and not really necessary) + #self.repartition_msc_to_CIFs = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers * 2, + # self.dp.cif_bits, self.dp.num_msc_syms, + # self.dp.num_cifs) + #repartition MSC to CUs + self.repartition_msc_to_cus = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers*2, self.dp.msc_cu_size, self.dp.num_msc_syms, self.dp.num_cus * self.dp.num_cifs) + + # select CUs of one subchannel of each CIF and form logical frame vector + self.select_subch = dab.select_subch_vfvf_make(self.dp.msc_cu_size, self.dp.msc_cu_size * self.size, self.address, self.dp.num_cus) # time deinterleaving - self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size) + self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size * self.size) self.time_deinterleaver = dab.time_deinterleave_ff_make(self.dp.msc_cu_size * self.size, self.dp.scrambling_vector) - # unpuncture self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.msc_punctured_codeword_length) self.unpuncture = dab.unpuncture_ff_make(self.assembled_msc_puncturing_sequence, 0) @@ -134,10 +137,11 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F # connect blocks self.connect((self, 0), - self.c2f, - self.v2s, - self.s2v, - self.select_subch, + (self.select_msc_syms, 0), + #(self.repartition_msc_to_CIFs, 0), + (self.repartition_msc_to_cus, 0), + (self.select_subch, 0), + #(self.repartition_cus_to_logical_frame, 0), self.time_v2s, self.time_deinterleaver, #self.conv_v2s, @@ -150,7 +154,14 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F self.pack_bits, #self.energy_s2v, #better output stream or vector?? (self)) - # connect prbs for energy descramble + #connect trigger chain + self.connect((self, 1), + (self.select_msc_syms, 1), + #(self.repartition_msc_to_CIFs, 1), + (self.repartition_msc_to_cus, 1), + #(self.select_subch, 1), + #(self.repartition_CUs_to_logical_frame, 1); + blocks.null_sink(gr.sizeof_char)) self.connect(self.prbs_src, (self.add_mod_2, 1)) diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index 5d812cd7..259dab3b 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -38,7 +38,7 @@ def __init__(self, dab_params): gr.hier_block2.__init__(self, "ofdm_demod_cc", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(2, 2, gr.sizeof_gr_complex*1536)) # Output signature + gr.io_signature2(2, 2, gr.sizeof_float*2*1536, gr.sizeof_char)) # Output signature self.dp = dab_params @@ -68,8 +68,10 @@ def __init__(self, dab_params): self.frequency_deinterleaver = dab.frequency_interleaver_vcc_make(self.dp.frequency_deinterleaving_sequence_array) # demux into FIC and MSC - self.demux = dab.demux_cc_make(self.dp.num_carriers, - 3, 72, 0+0j) + self.demux = dab.demux_cc_make(self.dp.num_carriers, 75, 0) + self.rm_pilot = dab.ofdm_remove_first_symbol_vcc(self.dp.num_carriers) + self.trigger_src = blocks.vector_source_b_make([1] + 75*[0], True) + self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) self.connect( self, @@ -80,7 +82,11 @@ def __init__(self, dab_params): #self.v2s_fft, self.differential_phasor, self.frequency_deinterleaver, - self.demux, + (self.rm_pilot, 0), + self.softbit_interleaver, (self, 0) ) - self.connect((self.demux, 1), (self, 1)) + #self.connect((self.demux, 1), (self, 1)) + self.connect(self.trigger_src, (self.rm_pilot, 1), (self, 1)) + #self.v2s_debug = blocks.vector_to_stream_make(gr.sizeof_gr_complex, 1536) + #self.connect(self.frequency_deinterleaver, self.v2s_debug, blocks.file_sink_make(gr.sizeof_gr_complex, "alle_symobols.dat")) From 434ddf5645926c31801a46050fd5d7ac6de74d47 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 10 Oct 2017 12:02:40 +0200 Subject: [PATCH 065/135] sync: include new sync in GUI --- grc/CMakeLists.txt | 3 +- grc/dab_dabplus_audio_decoder_ff.xml | 10 +--- grc/dab_msc_decode.xml | 8 +-- grc/dab_ofdm_demod_cc.xml | 11 ++-- grc/dab_select_cus_vcvc.xml | 37 ++++++++++++ include/dab/CMakeLists.txt | 3 +- include/dab/select_cus_vcvc.h | 56 +++++++++++++++++ lib/CMakeLists.txt | 3 +- lib/select_cus_vcvc_impl.cc | 90 ++++++++++++++++++++++++++++ lib/select_cus_vcvc_impl.h | 54 +++++++++++++++++ python/GUI/usrp_dab_rx.py | 10 ++-- python/dabplus_audio_decoder_ff.py | 20 +++++-- python/fic_decode_vc.py | 22 +++++++ python/ofdm_demod_cc.py | 15 +++-- swig/dab_swig.i | 3 + 15 files changed, 307 insertions(+), 38 deletions(-) create mode 100644 grc/dab_select_cus_vcvc.xml create mode 100644 include/dab/select_cus_vcvc.h create mode 100644 lib/select_cus_vcvc_impl.cc create mode 100644 lib/select_cus_vcvc_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 1c043802..e8edd11b 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -81,5 +81,6 @@ install(FILES dab_demux_cc.xml dab_ofdm_demod_cc.xml dab_differential_phasor_vcvc.xml - dab_fic_decode_vc.xml DESTINATION share/gnuradio/grc/blocks + dab_fic_decode_vc.xml + dab_select_cus_vcvc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_dabplus_audio_decoder_ff.xml b/grc/dab_dabplus_audio_decoder_ff.xml index f2325e67..157d9f1b 100644 --- a/grc/dab_dabplus_audio_decoder_ff.xml +++ b/grc/dab_dabplus_audio_decoder_ff.xml @@ -75,13 +75,9 @@ - dat - float - 1536*2 - - - dat - byte + MSC + complex + 1536 audio_left diff --git a/grc/dab_msc_decode.xml b/grc/dab_msc_decode.xml index 1c266ff4..742d8133 100644 --- a/grc/dab_msc_decode.xml +++ b/grc/dab_msc_decode.xml @@ -92,12 +92,8 @@ MSC symbols - float - 1536*2 - - - trigger - byte + complex + 1536 out diff --git a/grc/dab_ofdm_demod_cc.xml b/grc/dab_ofdm_demod_cc.xml index 24b54014..8bafa484 100644 --- a/grc/dab_ofdm_demod_cc.xml +++ b/grc/dab_ofdm_demod_cc.xml @@ -49,13 +49,14 @@ complex - data - float - 1536*2 + FIC + complex + 1536 - trigger - byte + MSC + complex + 1536 Demodulates a whole DAB signal. diff --git a/grc/dab_select_cus_vcvc.xml b/grc/dab_select_cus_vcvc.xml new file mode 100644 index 00000000..7daf120b --- /dev/null +++ b/grc/dab_select_cus_vcvc.xml @@ -0,0 +1,37 @@ + + Select cus vcvc + dab_select_cus_vcvc + DAB + import dab + dab.select_cus_vcvc($vlen, $frame_len, $address, $size) + + Vlen + vlen + raw + + + Frame_len + frame_len + raw + + + Address + address + raw + + + Size + size + raw + + + in + float + $vlen + + + out + float + $vlen + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index b2e9a193..9c5076bf 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -73,5 +73,6 @@ install(FILES frequency_deinterleave_cc.h complex_to_interleaved_float_cf.h demux_cc.h - differential_phasor_vcvc.h DESTINATION include/dab + differential_phasor_vcvc.h + select_cus_vcvc.h DESTINATION include/dab ) diff --git a/include/dab/select_cus_vcvc.h b/include/dab/select_cus_vcvc.h new file mode 100644 index 00000000..228f7a75 --- /dev/null +++ b/include/dab/select_cus_vcvc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_SELECT_CUS_VCVC_H +#define INCLUDED_DAB_SELECT_CUS_VCVC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API select_cus_vcvc : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::select_cus_vcvc. + * + * To avoid accidental use of raw pointers, dab::select_cus_vcvc's + * constructor is in a private implementation + * class. dab::select_cus_vcvc::make is the public interface for + * creating new instances. + */ + static sptr make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_SELECT_CUS_VCVC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index dd97ff9f..f813a1fa 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -102,7 +102,8 @@ list(APPEND dab_sources frequency_deinterleave_cc_impl.cc complex_to_interleaved_float_cf_impl.cc demux_cc_impl.cc - differential_phasor_vcvc_impl.cc ) + differential_phasor_vcvc_impl.cc + select_cus_vcvc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/select_cus_vcvc_impl.cc b/lib/select_cus_vcvc_impl.cc new file mode 100644 index 00000000..a8015c43 --- /dev/null +++ b/lib/select_cus_vcvc_impl.cc @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "select_cus_vcvc_impl.h" + +namespace gr { + namespace dab { + + select_cus_vcvc::sptr + select_cus_vcvc::make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) + { + return gnuradio::get_initial_sptr + (new select_cus_vcvc_impl(vlen, frame_len, address, size)); + } + + /* + * The private constructor + */ + select_cus_vcvc_impl::select_cus_vcvc_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) + : gr::block("select_cus_vcvc", + gr::io_signature::make(1, 1, vlen * sizeof(float)), + gr::io_signature::make(1, 1, vlen * sizeof(float))), + d_vlen(vlen), + d_frame_len(frame_len), + d_address(address), + d_size(size) + {} + + /* + * Our virtual destructor. + */ + select_cus_vcvc_impl::~select_cus_vcvc_impl() + { + } + + void + select_cus_vcvc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + { + ninput_items_required[0] = noutput_items; + } + + int + select_cus_vcvc_impl::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + unsigned int nwritten = 0; + + for (int i = 0; i < noutput_items; ++i) { + if(d_address <= (nitems_read(0)+i)%d_frame_len && (nitems_read(0)+i)%d_frame_len < d_address + d_size){ + //this cu is one of the selected subchannel -> copy it to ouput buffer + memcpy(&out[nwritten++*d_vlen], &in[i*d_vlen], d_vlen); + } + } + // Tell runtime system how many input items we consumed on + // each input stream. + consume_each (noutput_items); + + // Tell runtime system how many output items we produced. + return nwritten; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/select_cus_vcvc_impl.h b/lib/select_cus_vcvc_impl.h new file mode 100644 index 00000000..2b548e08 --- /dev/null +++ b/lib/select_cus_vcvc_impl.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H +#define INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H + +#include + +namespace gr { + namespace dab { + + class select_cus_vcvc_impl : public select_cus_vcvc + { + private: + unsigned int d_vlen; + unsigned int d_frame_len; + unsigned int d_address; + unsigned int d_size; + + public: + select_cus_vcvc_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); + ~select_cus_vcvc_impl(); + + // Where all the action really happens + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H */ + diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 0f8986f3..a1a9ab80 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -80,7 +80,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## # OFDM demod ######################## - self.demod = dab.ofdm_demod(self.dab_params, self.rx_params, self.verbose) + self.demod = dab.ofdm_demod_cc(self.dab_params) ######################## # SNR measurement @@ -92,7 +92,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## # FIC decoder ######################## - self.fic_dec = dab.fic_decode(self.dab_params) + self.fic_dec = dab.fic_decode_vc(self.dab_params) ######################## # MSC decoder @@ -121,11 +121,9 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## self.connect(self.src, self.fft_plot) self.connect(self.src, self.waterfall_plot) - self.connect(self.src, self.demod, (self.fic_dec, 0)) - self.connect((self.demod, 1), (self.fic_dec, 1)) + self.connect(self.src, self.demod, self.fic_dec) if self.dabplus: - self.connect((self.demod, 0), (self.dabplus, 0)) - self.connect((self.demod, 1), (self.dabplus, 1)) + self.connect((self.demod, 1), self.dabplus) else: self.connect((self.demod, 0), (self.msc_dec, 0), self.unpack, self.mp2_dec) self.connect((self.demod, 1), (self.msc_dec, 1)) diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index b6da1ae8..771b3a62 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -39,15 +39,14 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Output signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_float)) else: # output signed 16 bit integers (directly from decoder) gr.hier_block2.__init__(self, "dabplus_audio_decoder_ff", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, - gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_float * dab_params.num_carriers), # Output signature gr.io_signature2(2, 2, gr.sizeof_short, gr.sizeof_short)) self.dp = dab_params @@ -75,8 +74,19 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output # mp4 decoder self.mp4 = dab.mp4_decode_bs_make(self.bit_rate_n) - self.connect((self, 0), (self.msc_decoder, 0), self.firecode, self.rs, self.mp4) - self.connect((self, 1), (self.msc_decoder, 1)) + # trigger hybrid solution + # complex to intereaved float for convolutional decoding + self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) + + # FIB block partitioning + self.v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers * 2) + self.s2v = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.fic_punctured_codeword_length) + self.rm_pilot = dab.ofdm_remove_first_symbol_vcc(self.dp.num_carriers) + self.trigsrc = blocks.vector_source_b([1] + 75 * [0], True) + self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) + + self.connect((self, 0), (self.rm_pilot, 0), self.softbit_interleaver, (self.msc_decoder, 0), self.firecode, self.rs, self.mp4) + self.connect(self.trigsrc, (self.rm_pilot, 1), (self.msc_decoder, 1)) if self.output_float: # map short samples to the range [-1,1] in floats diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py index ce13b775..4cd6595c 100644 --- a/python/fic_decode_vc.py +++ b/python/fic_decode_vc.py @@ -95,8 +95,11 @@ def __init__(self, dab_params): # self.filesink = gr.file_sink(gr.sizeof_char, "debug/fic.dat") self.fibsink = dab.fib_sink_vb() + self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) + # self.connect((self,0), (self.select_fic_syms,0), (self.repartition_fic,0), self.unpuncture, self.conv_v2s, self.conv_decode, self.conv_s2v, self.conv_prune, self.energy_v2s, self.add_mod_2, self.energy_s2v, (self.cut_into_fibs,0), gr.vector_to_stream(1,256), gr.unpacked_to_packed_bb(1,gr.GR_MSB_FIRST), self.filesink) self.connect((self, 0), + self.demux1, self.c2f, self.v2s, self.s2v, @@ -114,3 +117,22 @@ def __init__(self, dab_params): self.fibout, self.fibsink) self.connect(self.prbs_src, (self.add_mod_2, 1)) + self.connect((self.demux1, 1), blocks.null_sink_make(gr.sizeof_gr_complex*1536)) + + def get_ensemble_info(self): + return self.fibsink.get_ensemble_info() + + def get_service_info(self): + return self.fibsink.get_service_info() + + def get_service_labels(self): + return self.fibsink.get_service_labels() + + def get_subch_info(self): + return self.fibsink.get_subch_info() + + def get_programme_type(self): + return self.fibsink.get_programme_type() + + def get_crc_passed(self): + return self.fibsink.get_crc_passed() diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index 259dab3b..fa110818 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -38,7 +38,7 @@ def __init__(self, dab_params): gr.hier_block2.__init__(self, "ofdm_demod_cc", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature2(2, 2, gr.sizeof_float*2*1536, gr.sizeof_char)) # Output signature + gr.io_signature(2, 2, gr.sizeof_gr_complex*1536)) # Output signature self.dp = dab_params @@ -68,7 +68,8 @@ def __init__(self, dab_params): self.frequency_deinterleaver = dab.frequency_interleaver_vcc_make(self.dp.frequency_deinterleaving_sequence_array) # demux into FIC and MSC - self.demux = dab.demux_cc_make(self.dp.num_carriers, 75, 0) + self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) + self.null1 = blocks.null_sink_make(gr.sizeof_gr_complex*1536) self.rm_pilot = dab.ofdm_remove_first_symbol_vcc(self.dp.num_carriers) self.trigger_src = blocks.vector_source_b_make([1] + 75*[0], True) self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) @@ -82,11 +83,13 @@ def __init__(self, dab_params): #self.v2s_fft, self.differential_phasor, self.frequency_deinterleaver, - (self.rm_pilot, 0), - self.softbit_interleaver, + #self.demux1, + #(self.rm_pilot, 0), + #self.softbit_interleaver, (self, 0) ) - #self.connect((self.demux, 1), (self, 1)) - self.connect(self.trigger_src, (self.rm_pilot, 1), (self, 1)) + #self.connect((self.demux1, 1), self.null1) + self.connect(self.frequency_deinterleaver, (self, 1)) + #self.connect(self.trigger_src, (self.rm_pilot, 1), (self, 1)) #self.v2s_debug = blocks.vector_to_stream_make(gr.sizeof_gr_complex, 1536) #self.connect(self.frequency_deinterleaver, self.v2s_debug, blocks.file_sink_make(gr.sizeof_gr_complex, "alle_symobols.dat")) diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 04b83997..d43210de 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -60,6 +60,7 @@ #include "dab/complex_to_interleaved_float_cf.h" #include "dab/demux_cc.h" #include "dab/differential_phasor_vcvc.h" +#include "dab/select_cus_vcvc.h" %} @@ -172,3 +173,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, complex_to_interleaved_float_cf); GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); %include "dab/differential_phasor_vcvc.h" GR_SWIG_BLOCK_MAGIC2(dab, differential_phasor_vcvc); +%include "dab/select_cus_vcvc.h" +GR_SWIG_BLOCK_MAGIC2(dab, select_cus_vcvc); From 06db20e0561b2c3b2be8db52557e3020decd32e6 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 10 Oct 2017 15:35:57 +0200 Subject: [PATCH 066/135] sync: remove any trigger ports from receiver --- grc/dab_ofdm_demod_cc.xml | 2 +- lib/demux_cc_impl.cc | 14 +++++---- lib/select_cus_vcvc_impl.cc | 2 +- python/dabplus_audio_decoder_ff.py | 15 ++-------- python/fic_decode_vc.py | 9 ------ python/msc_decode.py | 48 +++++++++--------------------- python/ofdm_demod_cc.py | 18 +++-------- 7 files changed, 30 insertions(+), 78 deletions(-) diff --git a/grc/dab_ofdm_demod_cc.xml b/grc/dab_ofdm_demod_cc.xml index 8bafa484..9ded75b8 100644 --- a/grc/dab_ofdm_demod_cc.xml +++ b/grc/dab_ofdm_demod_cc.xml @@ -45,7 +45,7 @@ int - in + IQ samples complex diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc index 5e1a2f11..732052f8 100644 --- a/lib/demux_cc_impl.cc +++ b/lib/demux_cc_impl.cc @@ -87,15 +87,17 @@ namespace gr { // get tags for the beginning of a frame std::vector tags; + const std::string s = "Start"; + pmt::pmt_t d_key = pmt::string_to_symbol(s); unsigned int tag_count = 0; - get_tags_in_window(tags, 0, 0, noutput_items); + get_tags_in_window(tags, 0, 0, noutput_items, d_key); /*fprintf(stderr, "Work call ####################################\n"); fprintf(stderr, "nitems_read %d\n", nitems_read(0)); fprintf(stderr, "noutput_items %d\n", noutput_items); fprintf(stderr, "Tags: %d\n", tags.size()); - if(tags.size()>0){ - fprintf(stderr, "Tag offset %d\n", tags[tag_count].offset); + for(int i = 0; i < tags.size(); i++){ + fprintf(stderr, "Tag offset %d\n", tags[i].offset); }*/ for (int i = 0; i < noutput_items; ++i) { if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0) - nconsumed == 0) { @@ -141,9 +143,9 @@ namespace gr { // Tell runtime system how many output items we produced on each output stream separately. produce(0, fic_syms_written); produce(1, msc_syms_written); - //fprintf(stderr, "fic_syms_written %d\n", fic_syms_written); - //fprintf(stderr, "msc_syms_written %d\n", msc_syms_written); - //fprintf(stderr, "nconsumed %d\n", nconsumed); + /*fprintf(stderr, "fic_syms_written %d\n", fic_syms_written); + fprintf(stderr, "msc_syms_written %d\n", msc_syms_written); + fprintf(stderr, "nconsumed %d\n", nconsumed);*/ return WORK_CALLED_PRODUCE; } diff --git a/lib/select_cus_vcvc_impl.cc b/lib/select_cus_vcvc_impl.cc index a8015c43..e49c2515 100644 --- a/lib/select_cus_vcvc_impl.cc +++ b/lib/select_cus_vcvc_impl.cc @@ -74,7 +74,7 @@ namespace gr { for (int i = 0; i < noutput_items; ++i) { if(d_address <= (nitems_read(0)+i)%d_frame_len && (nitems_read(0)+i)%d_frame_len < d_address + d_size){ //this cu is one of the selected subchannel -> copy it to ouput buffer - memcpy(&out[nwritten++*d_vlen], &in[i*d_vlen], d_vlen); + memcpy(&out[nwritten++*d_vlen], &in[i*d_vlen], d_vlen * sizeof(float)); } } // Tell runtime system how many input items we consumed on diff --git a/python/dabplus_audio_decoder_ff.py b/python/dabplus_audio_decoder_ff.py index 771b3a62..c617e854 100644 --- a/python/dabplus_audio_decoder_ff.py +++ b/python/dabplus_audio_decoder_ff.py @@ -74,19 +74,8 @@ def __init__(self, dab_params, bit_rate, address, subch_size, protection, output # mp4 decoder self.mp4 = dab.mp4_decode_bs_make(self.bit_rate_n) - # trigger hybrid solution - # complex to intereaved float for convolutional decoding - self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) - - # FIB block partitioning - self.v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers * 2) - self.s2v = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.fic_punctured_codeword_length) - self.rm_pilot = dab.ofdm_remove_first_symbol_vcc(self.dp.num_carriers) - self.trigsrc = blocks.vector_source_b([1] + 75 * [0], True) - self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) - - self.connect((self, 0), (self.rm_pilot, 0), self.softbit_interleaver, (self.msc_decoder, 0), self.firecode, self.rs, self.mp4) - self.connect(self.trigsrc, (self.rm_pilot, 1), (self.msc_decoder, 1)) + # connections + self.connect(self, self.msc_decoder, self.firecode, self.rs, self.mp4) if self.output_float: # map short samples to the range [-1,1] in floats diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py index 4cd6595c..92525f7c 100644 --- a/python/fic_decode_vc.py +++ b/python/fic_decode_vc.py @@ -95,29 +95,20 @@ def __init__(self, dab_params): # self.filesink = gr.file_sink(gr.sizeof_char, "debug/fic.dat") self.fibsink = dab.fib_sink_vb() - self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) - # self.connect((self,0), (self.select_fic_syms,0), (self.repartition_fic,0), self.unpuncture, self.conv_v2s, self.conv_decode, self.conv_s2v, self.conv_prune, self.energy_v2s, self.add_mod_2, self.energy_s2v, (self.cut_into_fibs,0), gr.vector_to_stream(1,256), gr.unpacked_to_packed_bb(1,gr.GR_MSB_FIRST), self.filesink) self.connect((self, 0), - self.demux1, self.c2f, self.v2s, self.s2v, self.unpuncture, self.conv_v2s, self.conv_decode, - # self.conv_s2v, self.conv_prune, - # self.energy_v2s, self.add_mod_2, - #self.energy_s2v, - #(self.cut_into_fibs, 0), - #blocks.vector_to_stream(1, 256), self.pack, self.fibout, self.fibsink) self.connect(self.prbs_src, (self.add_mod_2, 1)) - self.connect((self.demux1, 1), blocks.null_sink_make(gr.sizeof_gr_complex*1536)) def get_ensemble_info(self): return self.fibsink.get_ensemble_info() diff --git a/python/msc_decode.py b/python/msc_decode.py index 712bbb49..2d057c62 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -40,7 +40,7 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F gr.hier_block2.__init__(self, "msc_decode", # Input signature - gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), + gr.io_signature(1, 1, gr.sizeof_gr_complex * dab_params.num_carriers), # Output signature gr.io_signature(1, 1, gr.sizeof_char)) self.dp = dab_params @@ -77,23 +77,16 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F #sanity check assert(6*self.n == self.puncturing_L1[self.protect] + self.puncturing_L2[self.protect]) + # complex to interleaved float (part of the qpsk demodulation) + self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) - # MSC selection and block partitioning - # select OFDM carriers with MSC - self.select_msc_syms = dab.select_vectors(gr.sizeof_float, self.dp.num_carriers * 2, self.dp.num_msc_syms, - self.dp.num_fic_syms) - # repartition MSC data in CIFs (left out due to heavy burden for scheduler and not really necessary) - #self.repartition_msc_to_CIFs = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers * 2, - # self.dp.cif_bits, self.dp.num_msc_syms, - # self.dp.num_cifs) - #repartition MSC to CUs - self.repartition_msc_to_cus = dab.repartition_vectors_make(gr.sizeof_float, self.dp.num_carriers*2, self.dp.msc_cu_size, self.dp.num_msc_syms, self.dp.num_cus * self.dp.num_cifs) - - # select CUs of one subchannel of each CIF and form logical frame vector - self.select_subch = dab.select_subch_vfvf_make(self.dp.msc_cu_size, self.dp.msc_cu_size * self.size, self.address, self.dp.num_cus) + # repartition vectors in capacity units (CUs) and select a sub-channel + self.v2s_repart_to_cus = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers*2) + self.s2v_repart_to_cus = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.msc_cu_size) + self.select_subch = dab.select_cus_vcvc_make(self.dp.msc_cu_size, self.dp.num_cus, self.address, self.size) # time deinterleaving - self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size * self.size) + self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size) self.time_deinterleaver = dab.time_deinterleave_ff_make(self.dp.msc_cu_size * self.size, self.dp.scrambling_vector) # unpuncture self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.msc_punctured_codeword_length) @@ -130,38 +123,25 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F self.prbs_src = blocks.vector_source_b(self.dp.prbs(self.msc_I), True) self.energy_v2s = blocks.vector_to_stream(gr.sizeof_char, self.msc_I) self.add_mod_2 = blocks.xor_bb() - #self.energy_s2v = blocks.stream_to_vector(gr.sizeof_char, self.msc_I) #pack bits self.pack_bits = blocks.unpacked_to_packed_bb_make(1, gr.GR_MSB_FIRST) # connect blocks - self.connect((self, 0), - (self.select_msc_syms, 0), - #(self.repartition_msc_to_CIFs, 0), - (self.repartition_msc_to_cus, 0), - (self.select_subch, 0), - #(self.repartition_cus_to_logical_frame, 0), + self.connect( + self, + self.softbit_interleaver, + self.v2s_repart_to_cus, + self.s2v_repart_to_cus, + self.select_subch, self.time_v2s, self.time_deinterleaver, - #self.conv_v2s, self.unpuncture, self.conv_decode, - #self.conv_s2v, self.conv_prune, - #self.energy_v2s, self.add_mod_2, self.pack_bits, - #self.energy_s2v, #better output stream or vector?? (self)) - #connect trigger chain - self.connect((self, 1), - (self.select_msc_syms, 1), - #(self.repartition_msc_to_CIFs, 1), - (self.repartition_msc_to_cus, 1), - #(self.select_subch, 1), - #(self.repartition_CUs_to_logical_frame, 1); - blocks.null_sink(gr.sizeof_char)) self.connect(self.prbs_src, (self.add_mod_2, 1)) diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index fa110818..bbc85817 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -33,6 +33,7 @@ class ofdm_demod_cc(gr.hier_block2): - phase correction with phase reference symbol - frequency deinterleaving - demux into FIC and MSC + - output of complex qpsk symbols, separated after FIC and MSC """ def __init__(self, dab_params): gr.hier_block2.__init__(self, @@ -68,11 +69,7 @@ def __init__(self, dab_params): self.frequency_deinterleaver = dab.frequency_interleaver_vcc_make(self.dp.frequency_deinterleaving_sequence_array) # demux into FIC and MSC - self.demux1 = dab.demux_cc_make(self.dp.num_carriers, 3, 72) - self.null1 = blocks.null_sink_make(gr.sizeof_gr_complex*1536) - self.rm_pilot = dab.ofdm_remove_first_symbol_vcc(self.dp.num_carriers) - self.trigger_src = blocks.vector_source_b_make([1] + 75*[0], True) - self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) + self.demux = dab.demux_cc_make(self.dp.num_carriers, self.dp.num_fic_syms, self.dp.num_msc_syms) self.connect( self, @@ -80,16 +77,9 @@ def __init__(self, dab_params): self.s2v_fft, self.fft, self.coarse_freq_corr, - #self.v2s_fft, self.differential_phasor, self.frequency_deinterleaver, - #self.demux1, - #(self.rm_pilot, 0), - #self.softbit_interleaver, + self.demux, (self, 0) ) - #self.connect((self.demux1, 1), self.null1) - self.connect(self.frequency_deinterleaver, (self, 1)) - #self.connect(self.trigger_src, (self.rm_pilot, 1), (self, 1)) - #self.v2s_debug = blocks.vector_to_stream_make(gr.sizeof_gr_complex, 1536) - #self.connect(self.frequency_deinterleaver, self.v2s_debug, blocks.file_sink_make(gr.sizeof_gr_complex, "alle_symobols.dat")) + self.connect((self.demux, 1), (self, 1)) From aa1e9f08d0974530785f1daaed4f194fa5afa862 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 10 Oct 2017 16:38:44 +0200 Subject: [PATCH 067/135] receiver: adjust sampling rate from 2M to 2048k --- python/GUI/usrp_dab_rx.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index a1a9ab80..ec7df493 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -37,7 +37,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.dab_mode = dab_mode self.verbose = False - self.sample_rate = 2e6 + self.sample_rate = 2048e3 self.dabplus = dabplus self.use_usrp = use_usrp self.src_path = src_path @@ -49,6 +49,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## if self.use_usrp: self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) + self.src.set_clock_rate(self.sample_rate*20) self.src.set_samp_rate(self.sample_rate) self.src.set_antenna("TX/RX") else: @@ -74,6 +75,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud # FFT and waterfall plot ######################## self.fft_plot = qtgui.freq_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "FFT") + self.waterfall_plot = qtgui.waterfall_sink_c_make(1024, fft.window.WIN_BLACKMAN_HARRIS, self.frequency, 2e6, "Waterfall") #self.time_plot = qtgui.time_sink_c_make(1024, 2e6, "Time") @@ -85,9 +87,10 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## # SNR measurement ######################## - self.v2s_snr = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dab_params.num_carriers) + self.v2s_snr = blocks.vector_to_stream(gr.sizeof_gr_complex*1, self.dab_params.num_carriers) self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) + self.constellation_plot.enable_grid(True) ######################## # FIC decoder @@ -129,7 +132,8 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect((self.demod, 1), (self.msc_dec, 1)) self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) - self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, self.constellation_plot) + self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, blocks.null_sink_make(gr.sizeof_gr_complex)) + self.connect(self.v2s_snr, self.constellation_plot) # connect audio to sound card and file sink if self.dabplus: self.connect((self.dabplus, 0), (self.audio, 0)) From bd019076001ca8507c4ed375fd5e097cfac9eecf Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 10 Oct 2017 16:43:12 +0200 Subject: [PATCH 068/135] receiver: update grc example --- examples/dab_receiver.grc | 239 +++----------------------------------- 1 file changed, 16 insertions(+), 223 deletions(-) diff --git a/examples/dab_receiver.grc b/examples/dab_receiver.grc index d84a587a..dd171d0d 100644 --- a/examples/dab_receiver.grc +++ b/examples/dab_receiver.grc @@ -168,7 +168,7 @@ value - 2000000 + 2048000 @@ -218,104 +218,6 @@ 32000 - - blocks_file_sink - - append - False - - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - file - /home/luca/Desktop/iq_dab_neu.dat - - - _coordinate - (616, 542) - - - _rotation - 0 - - - id - blocks_file_sink_0 - - - type - complex - - - unbuffered - False - - - vlen - 1 - - - - blocks_null_sink - - alias - - - - bus_conns - [[0,],] - - - comment - - - - affinity - - - - _enabled - 1 - - - _coordinate - (1016, 297) - - - _rotation - 0 - - - id - blocks_null_sink_0_1 - - - type - byte - - - num_inputs - 1 - - - vlen - 1 - - blocks_vector_to_stream @@ -367,57 +269,6 @@ 1 - - blocks_vector_to_stream - - alias - - - - comment - - - - affinity - - - - _enabled - 1 - - - _coordinate - (832, 292) - - - _rotation - 0 - - - id - blocks_vector_to_stream_0_1 - - - type - byte - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - num_items - 32 - - - vlen - 1 - - dab_dabplus_audio_decoder_ff @@ -486,7 +337,7 @@ - dab_fic_decode + dab_fic_decode_vc alias @@ -505,11 +356,11 @@ _enabled - 1 + True _coordinate - (640, 281) + (624, 269) _rotation @@ -517,15 +368,7 @@ id - dab_fic_decode_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 + dab_fic_decode_vc_0 samp_rate @@ -533,11 +376,7 @@ - dab_ofdm_demod - - autocorr_sr - True - + dab_ofdm_demod_cc alias @@ -556,19 +395,11 @@ _enabled - 1 - - - eq_mag - True - - - correct_ffe True _coordinate - (352, 264) + (336, 281) _rotation @@ -576,11 +407,7 @@ id - dab_ofdm_demod_0 - - - input_fft - True + dab_ofdm_demod_cc_0 maxoutbuf @@ -594,10 +421,6 @@ samp_rate samp_rate - - soft_bits - soft - digital_mpsk_snr_est_cc @@ -1931,7 +1754,7 @@ clock_rate - 0.0 + 20*samp_rate comment @@ -1955,7 +1778,7 @@ _coordinate - (104, 271) + (88, 264) _rotation @@ -2112,12 +1935,6 @@ 0 0 - - blocks_vector_to_stream_0_1 - blocks_null_sink_0_1 - 0 - 0 - dab_dabplus_audio_decoder_ff_0 audio_sink_0 @@ -2131,40 +1948,22 @@ 1 - dab_fic_decode_0 - blocks_vector_to_stream_0_1 - 0 - 0 - - - dab_ofdm_demod_0 + dab_ofdm_demod_cc_0 blocks_vector_to_stream_0 0 0 - dab_ofdm_demod_0 - dab_dabplus_audio_decoder_ff_0 - 0 - 0 - - - dab_ofdm_demod_0 - dab_fic_decode_0 + dab_ofdm_demod_cc_0 + dab_fic_decode_vc_0 0 0 - dab_ofdm_demod_0 + dab_ofdm_demod_cc_0 dab_dabplus_audio_decoder_ff_0 1 - 1 - - - dab_ofdm_demod_0 - dab_fic_decode_0 - 1 - 1 + 0 digital_mpsk_snr_est_cc_0 @@ -2174,13 +1973,7 @@ uhd_usrp_source_0 - blocks_file_sink_0 - 0 - 0 - - - uhd_usrp_source_0 - dab_ofdm_demod_0 + dab_ofdm_demod_cc_0 0 0 From 19956a53ce4842dcf88c8a86f0b9c428981488d7 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Wed, 18 Oct 2017 11:43:06 +0200 Subject: [PATCH 069/135] sync: improve grc files --- grc/dab_demux_cc.xml | 4 ++-- grc/dab_ofdm_coarse_frequency_correction_vcvc.xml | 4 ++-- grc/dab_ofdm_synchronization_cvf.xml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grc/dab_demux_cc.xml b/grc/dab_demux_cc.xml index 46adf7f3..3aefbaed 100644 --- a/grc/dab_demux_cc.xml +++ b/grc/dab_demux_cc.xml @@ -1,8 +1,8 @@ - demux_cc + DAB: Demux dab_demux_cc - dab + [DAB] import dab dab.demux_cc($symbol_length, $symbols_fic, $symbols_msc, $fillval) diff --git a/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml b/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml index 4932123c..b47ee58e 100644 --- a/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml +++ b/grc/dab_ofdm_coarse_frequency_correction_vcvc.xml @@ -1,7 +1,7 @@ - Ofdm coarse frequency correction vcvc + DAB: Coarse Frequency Correction dab_ofdm_coarse_frequency_correction_vcvc - DAB + [DAB] import dab dab.ofdm_coarse_frequency_correction_vcvc($fft_length, $num_carriers, $cyclic_prefix_length) diff --git a/grc/dab_ofdm_synchronization_cvf.xml b/grc/dab_ofdm_synchronization_cvf.xml index fbfe0faa..84a47156 100644 --- a/grc/dab_ofdm_synchronization_cvf.xml +++ b/grc/dab_ofdm_synchronization_cvf.xml @@ -1,7 +1,7 @@ - Ofdm_synchronization cvf + DAB: Synchronization dab_ofdm_synchronization_cvf - DAB + [DAB] import dab dab.ofdm_synchronization_cvf($symbol_length, $cyclic_prefix_length, $fft_length, $symbols_per_frame) From 4956c34c9d713e95d240ec1f564cfec371242fe8 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 20 Oct 2017 16:27:19 +0200 Subject: [PATCH 070/135] transmitter: implement better qpsk mapper --- examples/dab_receiver.grc | 863 ++++++++++++++++++++++++++++----- examples/dab_transmitter.grc | 217 +++++++-- grc/CMakeLists.txt | 3 +- grc/dab_qpsk_mapper_vbvc.xml | 22 + include/dab/CMakeLists.txt | 3 +- include/dab/qpsk_mapper_vbvc.h | 56 +++ lib/CMakeLists.txt | 3 +- lib/qpsk_mapper_vbvc_impl.cc | 84 ++++ lib/qpsk_mapper_vbvc_impl.h | 50 ++ python/GUI/usrp_dab_tx.py | 5 +- python/ofdm.py | 21 +- swig/dab_swig.i | 3 + 12 files changed, 1136 insertions(+), 194 deletions(-) create mode 100644 grc/dab_qpsk_mapper_vbvc.xml create mode 100644 include/dab/qpsk_mapper_vbvc.h create mode 100644 lib/qpsk_mapper_vbvc_impl.cc create mode 100644 lib/qpsk_mapper_vbvc_impl.h diff --git a/examples/dab_receiver.grc b/examples/dab_receiver.grc index dd171d0d..3cec09b0 100644 --- a/examples/dab_receiver.grc +++ b/examples/dab_receiver.grc @@ -81,6 +81,69 @@ + + variable_qtgui_range + + comment + + + + value + 20 + + + _enabled + True + + + _coordinate + (288, 536) + + + gui_hint + + + + _rotation + 0 + + + id + SNR + + + label + + + + min_len + 200 + + + orient + Qt.Horizontal + + + start + -20 + + + step + 1 + + + stop + 60 + + + rangeType + float + + + widget + counter_slider + + variable_qtgui_range @@ -171,6 +234,61 @@ 2048000 + + analog_noise_source_x + + amp + 10**((-34.0-SNR)/20.0) + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (104, 478) + + + _rotation + 0 + + + id + analog_noise_source_x_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + noise_type + analog.GR_GAUSSIAN + + + type + complex + + + seed + 0 + + audio_sink @@ -218,6 +336,112 @@ 32000 + + blocks_add_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (328, 409) + + + _rotation + 0 + + + id + blocks_add_xx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + + + blocks_file_source + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + file + /home/luca/Desktop/reinstes_dab.dat + + + _coordinate + (64, 397) + + + _rotation + 0 + + + id + blocks_file_source_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + complex + + + repeat + True + + + vlen + 1 + + blocks_vector_to_stream @@ -273,7 +497,7 @@ dab_dabplus_audio_decoder_ff address - 234 + 0 bit_rate @@ -328,187 +552,530 @@ 2 - samp_rate - samp_rate + samp_rate + samp_rate + + + subch_size + 84 + + + + dab_fic_decode_vc + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + _enabled + True + + + _coordinate + (624, 269) + + + _rotation + 0 + + + id + dab_fic_decode_vc_0 + + + samp_rate + samp_rate + + + + dab_ofdm_demod_cc + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + _enabled + True + + + _coordinate + (360, 281) + + + _rotation + 0 + + + id + dab_ofdm_demod_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + samp_rate + + + + digital_mpsk_snr_est_cc + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + alpha + 0.001 + + + _coordinate + (840, 174) + + + _rotation + 0 + + + id + digital_mpsk_snr_est_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + tag_nsamples + 10000 + + + type + 0 + + + + note + + alias + + + + comment + 1. Set frequency in USRP +2. Run flowgraph and read fib_sink info in the console to get the DAB+ Decoder info +3. Set the DAB+ Decoder info and restart flowgraph +4. Adjust sampling rate + + + _enabled + True + + + _coordinate + (304, 12) + + + _rotation + 0 + + + id + note_0 + + + note + Instructions: + + + + qtgui_const_sink_x + + autoscale + False + + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (1056, 181) + + + gui_hint + + + + _rotation + 0 + + + grid + False + + + id + qtgui_const_sink_x_1 + + + legend + True + + + alpha1 + 1.0 + + + color1 + "blue" + + + label1 + + + + marker1 + 0 + + + style1 + 0 + + + width1 + 1 + + + alpha10 + 1.0 + + + color10 + "red" + + + label10 + + + + marker10 + 0 + + + style10 + 0 + + + width10 + 1 + + + alpha2 + 1.0 + + + color2 + "red" + + + label2 + + + + marker2 + 0 + + + style2 + 0 + + + width2 + 1 + + + alpha3 + 1.0 + + + color3 + "red" + + + label3 + + + + marker3 + 0 + + + style3 + 0 + + + width3 + 1 + + + alpha4 + 1.0 + + + color4 + "red" + + + label4 + + + + marker4 + 0 + + + style4 + 0 + + + width4 + 1 + + + alpha5 + 1.0 - subch_size - 84 + color5 + "red" - - - dab_fic_decode_vc - alias + label5 - comment - + marker5 + 0 - affinity - + style5 + 0 - dab_mode + width5 1 - _enabled - True + alpha6 + 1.0 - _coordinate - (624, 269) + color6 + "red" - _rotation + label6 + + + + marker6 0 - id - dab_fic_decode_vc_0 + style6 + 0 - samp_rate - samp_rate + width6 + 1 - - - dab_ofdm_demod_cc - alias - + alpha7 + 1.0 - comment - + color7 + "red" - affinity + label7 - dab_mode - 1 + marker7 + 0 - _enabled - True + style7 + 0 - _coordinate - (336, 281) + width7 + 1 - _rotation - 0 + alpha8 + 1.0 - id - dab_ofdm_demod_cc_0 + color8 + "red" - maxoutbuf + label8 + + + + marker8 0 - minoutbuf + style8 0 - samp_rate - samp_rate + width8 + 1 - - - digital_mpsk_snr_est_cc - alias - + alpha9 + 1.0 - comment - + color9 + "red" - affinity + label9 - _enabled - True + marker9 + 0 - alpha - 0.001 + style9 + 0 - _coordinate - (840, 174) + width9 + 1 - _rotation - 0 + name + "" - id - digital_mpsk_snr_est_cc_0 + nconnections + 1 - maxoutbuf - 0 + size + 1024 - minoutbuf + tr_chan 0 - tag_nsamples - 10000 + tr_level + 0.0 - type - 0 + tr_mode + qtgui.TRIG_MODE_FREE - - - note - alias - + tr_slope + qtgui.TRIG_SLOPE_POS - comment - 1. Set frequency in USRP -2. Run flowgraph and read fib_sink info in the console to get the DAB+ Decoder info -3. Set the DAB+ Decoder info and restart flowgraph -4. Adjust sampling rate + tr_tag + "" - _enabled - True + type + complex - _coordinate - (304, 12) + update_time + 0.10 - _rotation - 0 + xmax + 2 - id - note_0 + xmin + -2 - note - Instructions: + ymax + 2 + + + ymin + -2 - qtgui_const_sink_x + qtgui_time_sink_x autoscale False @@ -521,17 +1088,25 @@ comment + + ctrlpanel + False + affinity + + entags + True + _enabled True _coordinate - (1056, 181) + (424, 406) gui_hint @@ -547,7 +1122,7 @@ id - qtgui_const_sink_x_1 + qtgui_time_sink_x_0 legend @@ -567,11 +1142,11 @@ marker1 - 0 + -1 style1 - 0 + 1 width1 @@ -583,7 +1158,7 @@ color10 - "red" + "blue" label10 @@ -591,11 +1166,11 @@ marker10 - 0 + -1 style10 - 0 + 1 width10 @@ -615,11 +1190,11 @@ marker2 - 0 + -1 style2 - 0 + 1 width2 @@ -631,7 +1206,7 @@ color3 - "red" + "green" label3 @@ -639,11 +1214,11 @@ marker3 - 0 + -1 style3 - 0 + 1 width3 @@ -655,7 +1230,7 @@ color4 - "red" + "black" label4 @@ -663,11 +1238,11 @@ marker4 - 0 + -1 style4 - 0 + 1 width4 @@ -679,7 +1254,7 @@ color5 - "red" + "cyan" label5 @@ -687,11 +1262,11 @@ marker5 - 0 + -1 style5 - 0 + 1 width5 @@ -703,7 +1278,7 @@ color6 - "red" + "magenta" label6 @@ -711,11 +1286,11 @@ marker6 - 0 + -1 style6 - 0 + 1 width6 @@ -727,7 +1302,7 @@ color7 - "red" + "yellow" label7 @@ -735,11 +1310,11 @@ marker7 - 0 + -1 style7 - 0 + 1 width7 @@ -751,7 +1326,7 @@ color8 - "red" + "dark red" label8 @@ -759,11 +1334,11 @@ marker8 - 0 + -1 style8 - 0 + 1 width8 @@ -775,7 +1350,7 @@ color9 - "red" + "dark green" label9 @@ -783,11 +1358,11 @@ marker9 - 0 + -1 style9 - 0 + 1 width9 @@ -805,10 +1380,18 @@ size 1024 + + srate + samp_rate + tr_chan 0 + + tr_delay + 0 + tr_level 0.0 @@ -834,20 +1417,20 @@ 0.10 - xmax - 2 + ylabel + Amplitude - xmin - -2 + yunit + "" ymax - 2 + 1 ymin - -2 + -1 @@ -1774,7 +2357,7 @@ _enabled - 1 + 0 _coordinate @@ -1929,6 +2512,30 @@ + + analog_noise_source_x_0 + blocks_add_xx_0 + 0 + 1 + + + blocks_add_xx_0 + dab_ofdm_demod_cc_0 + 0 + 0 + + + blocks_add_xx_0 + qtgui_time_sink_x_0 + 0 + 0 + + + blocks_file_source_0 + blocks_add_xx_0 + 0 + 0 + blocks_vector_to_stream_0 digital_mpsk_snr_est_cc_0 diff --git a/examples/dab_transmitter.grc b/examples/dab_transmitter.grc index 6fef72fb..73fe3064 100644 --- a/examples/dab_transmitter.grc +++ b/examples/dab_transmitter.grc @@ -105,7 +105,58 @@ value - 2000000 + 2048000 + + + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + /home/luca/Desktop/grc_trans_test.dat + + + _coordinate + (1120, 318) + + + _rotation + 0 + + + id + blocks_file_sink_0 + + + type + complex + + + unbuffered + False + + + vlen + 1 @@ -332,7 +383,7 @@ file - /home/luca/Desktop/SWR3.wav + /home/luca/Desktop/music.wav _coordinate @@ -454,7 +505,7 @@ _coordinate - (24, 163) + (24, 149) _rotation @@ -517,7 +568,7 @@ _coordinate - (224, 205) + (256, 205) _rotation @@ -732,35 +783,19 @@ - qtgui_freq_sink_x + qtgui_const_sink_x autoscale False - - average - 1.0 - - - bw - samp_rate - alias - - fc - 0 - comment - - ctrlpanel - False - affinity @@ -769,13 +804,9 @@ _enabled True - - fftsize - 1024 - _coordinate - (1104, 110) + (1136, 120) gui_hint @@ -791,7 +822,7 @@ id - qtgui_freq_sink_x_0 + qtgui_const_sink_x_0 legend @@ -809,6 +840,14 @@ label1 + + marker1 + 0 + + + style1 + 0 + width1 1 @@ -819,12 +858,20 @@ color10 - "dark blue" + "red" label10 + + marker10 + 0 + + + style10 + 0 + width10 1 @@ -841,6 +888,14 @@ label2 + + marker2 + 0 + + + style2 + 0 + width2 1 @@ -851,12 +906,20 @@ color3 - "green" + "red" label3 + + marker3 + 0 + + + style3 + 0 + width3 1 @@ -867,12 +930,20 @@ color4 - "black" + "red" label4 + + marker4 + 0 + + + style4 + 0 + width4 1 @@ -883,12 +954,20 @@ color5 - "cyan" + "red" label5 + + marker5 + 0 + + + style5 + 0 + width5 1 @@ -899,12 +978,20 @@ color6 - "magenta" + "red" label6 + + marker6 + 0 + + + style6 + 0 + width6 1 @@ -915,12 +1002,20 @@ color7 - "yellow" + "red" label7 + + marker7 + 0 + + + style7 + 0 + width7 1 @@ -931,12 +1026,20 @@ color8 - "dark red" + "red" label8 + + marker8 + 0 + + + style8 + 0 + width8 1 @@ -947,23 +1050,23 @@ color9 - "dark green" + "red" label9 - width9 - 1 + marker9 + 0 - maxoutbuf + style9 0 - minoutbuf - 0 + width9 + 1 name @@ -974,12 +1077,8 @@ 1 - showports - True - - - freqhalf - True + size + 1024 tr_chan @@ -993,6 +1092,10 @@ tr_mode qtgui.TRIG_MODE_FREE + + tr_slope + qtgui.TRIG_SLOPE_POS + tr_tag "" @@ -1006,16 +1109,20 @@ 0.10 - wintype - firdes.WIN_BLACKMAN_hARRIS + xmax + 2 + + + xmin + -2 ymax - 10 + 2 ymin - -140 + -2 @@ -1729,7 +1836,7 @@ _enabled - True + 0 _coordinate @@ -1948,7 +2055,13 @@ dab_ofdm_mod_0 - qtgui_freq_sink_x_0 + blocks_file_sink_0 + 0 + 0 + + + dab_ofdm_mod_0 + qtgui_const_sink_x_0 0 0 diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index e8edd11b..3fe4e946 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -82,5 +82,6 @@ install(FILES dab_ofdm_demod_cc.xml dab_differential_phasor_vcvc.xml dab_fic_decode_vc.xml - dab_select_cus_vcvc.xml DESTINATION share/gnuradio/grc/blocks + dab_select_cus_vcvc.xml + dab_qpsk_mapper_vbvc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_qpsk_mapper_vbvc.xml b/grc/dab_qpsk_mapper_vbvc.xml new file mode 100644 index 00000000..a6b4576c --- /dev/null +++ b/grc/dab_qpsk_mapper_vbvc.xml @@ -0,0 +1,22 @@ + + Qpsk mapper vbvc + dab_qpsk_mapper_vbvc + DAB + import dab + dab.qpsk_mapper_vbvc($symbol_length) + + Symbol_length + symbol_length + raw + + + in + byte + $symbol_length/4 + + + out + complex + $symbol_length + + diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 9c5076bf..4f884356 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -74,5 +74,6 @@ install(FILES complex_to_interleaved_float_cf.h demux_cc.h differential_phasor_vcvc.h - select_cus_vcvc.h DESTINATION include/dab + select_cus_vcvc.h + qpsk_mapper_vbvc.h DESTINATION include/dab ) diff --git a/include/dab/qpsk_mapper_vbvc.h b/include/dab/qpsk_mapper_vbvc.h new file mode 100644 index 00000000..3c6335c1 --- /dev/null +++ b/include/dab/qpsk_mapper_vbvc.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_DAB_QPSK_MAPPER_VBVC_H +#define INCLUDED_DAB_QPSK_MAPPER_VBVC_H + +#include +#include + +namespace gr { + namespace dab { + + /*! + * \brief <+description of block+> + * \ingroup dab + * + */ + class DAB_API qpsk_mapper_vbvc : virtual public gr::sync_block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of dab::qpsk_mapper_vbvc. + * + * To avoid accidental use of raw pointers, dab::qpsk_mapper_vbvc's + * constructor is in a private implementation + * class. dab::qpsk_mapper_vbvc::make is the public interface for + * creating new instances. + */ + static sptr make(unsigned int symbol_length); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_QPSK_MAPPER_VBVC_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f813a1fa..4484d932 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -103,7 +103,8 @@ list(APPEND dab_sources complex_to_interleaved_float_cf_impl.cc demux_cc_impl.cc differential_phasor_vcvc_impl.cc - select_cus_vcvc_impl.cc ) + select_cus_vcvc_impl.cc + qpsk_mapper_vbvc_impl.cc ) set(dab_sources "${dab_sources}" PARENT_SCOPE) diff --git a/lib/qpsk_mapper_vbvc_impl.cc b/lib/qpsk_mapper_vbvc_impl.cc new file mode 100644 index 00000000..f9fa5763 --- /dev/null +++ b/lib/qpsk_mapper_vbvc_impl.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "qpsk_mapper_vbvc_impl.h" + +namespace gr { + namespace dab { + + qpsk_mapper_vbvc::sptr + qpsk_mapper_vbvc::make(unsigned int symbol_length) + { + return gnuradio::get_initial_sptr + (new qpsk_mapper_vbvc_impl(symbol_length)); + } + + /* + * The private constructor + */ + qpsk_mapper_vbvc_impl::qpsk_mapper_vbvc_impl(unsigned int symbol_length) + : gr::sync_block("qpsk_mapper_vbvc", + gr::io_signature::make(1, 1, sizeof(char)*symbol_length/4), + gr::io_signature::make(1, 1, sizeof(gr_complex)*symbol_length)), + d_symbol_length(symbol_length) + {} + + /* + * Our virtual destructor. + */ + qpsk_mapper_vbvc_impl::~qpsk_mapper_vbvc_impl() + { + } + + int + qpsk_mapper_vbvc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const char *in = (const char *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; ++i) { + // iterate over each symbol vector + for (int j = 0; j < d_symbol_length/8; ++j) { + // iterate over the symbo vector, but each byte has 8 bit, which are accessed manually + out[i*d_symbol_length + j*8 + 0] = gr_complex((in[i*(d_symbol_length/4) + j]&128)>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&128)>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 1] = gr_complex((in[i*(d_symbol_length/4) + j]&64 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&64 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 2] = gr_complex((in[i*(d_symbol_length/4) + j]&32 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&32 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 3] = gr_complex((in[i*(d_symbol_length/4) + j]&16 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&16 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 4] = gr_complex((in[i*(d_symbol_length/4) + j]&8 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&8 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 5] = gr_complex((in[i*(d_symbol_length/4) + j]&4 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&4 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 6] = gr_complex((in[i*(d_symbol_length/4) + j]&2 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&2 )>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + 7] = gr_complex((in[i*(d_symbol_length/4) + j]&1 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&1 )>0?-I_SQRT2:I_SQRT2); + } + } + + // Tell runtime system how many output items we produced. + return noutput_items; + } + + } /* namespace dab */ +} /* namespace gr */ + diff --git a/lib/qpsk_mapper_vbvc_impl.h b/lib/qpsk_mapper_vbvc_impl.h new file mode 100644 index 00000000..091f4b27 --- /dev/null +++ b/lib/qpsk_mapper_vbvc_impl.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_DAB_QPSK_MAPPER_VBVC_IMPL_H +#define INCLUDED_DAB_QPSK_MAPPER_VBVC_IMPL_H + +#define I_SQRT2 0.707106781187 + +#include + +namespace gr { + namespace dab { + + class qpsk_mapper_vbvc_impl : public qpsk_mapper_vbvc + { + private: + unsigned int d_symbol_length; + + public: + qpsk_mapper_vbvc_impl(unsigned int symbol_length); + ~qpsk_mapper_vbvc_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab +} // namespace gr + +#endif /* INCLUDED_DAB_QPSK_MAPPER_VBVC_IMPL_H */ + diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index d3dcdc93..4a2fa1f4 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -35,9 +35,8 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.dab_mode = dab_mode self.frequency = frequency - interp = 64 - self.sample_rate = 128e6 / interp - self.dp = dab.parameters.dab_parameters(self.dab_mode, 2000000, False) + self.sample_rate = 2048000 + self.dp = dab.parameters.dab_parameters(self.dab_mode, 2048000, False) self.num_subch = num_subch self.ensemble_label = ensemble_label self.service_label = service_label diff --git a/python/ofdm.py b/python/ofdm.py index ccd90a56..adbd9097 100644 --- a/python/ofdm.py +++ b/python/ofdm.py @@ -61,10 +61,11 @@ def __init__(self, dab_params, verbose=False, debug=False): # symbol mapping - self.mapper_v2s = blocks.vector_to_stream_make(gr.sizeof_char, 384) - self.mapper_unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) - self.mapper = dab.mapper_bc_make(dp.num_carriers) - self.mapper_s2v = blocks.stream_to_vector_make(gr.sizeof_gr_complex, 1536) + #self.mapper_v2s = blocks.vector_to_stream_make(gr.sizeof_char, 384) + #self.mapper_unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) + #self.mapper = dab.mapper_bc_make(dp.num_carriers) + #self.mapper_s2v = blocks.stream_to_vector_make(gr.sizeof_gr_complex, 1536) + self.mapper = dab.qpsk_mapper_vbvc(dp.num_carriers) # add pilot symbol self.insert_pilot = dab.ofdm_insert_pilot_vcc(dp.prn) @@ -84,6 +85,9 @@ def __init__(self, dab_params, verbose=False, debug=False): # cyclic prefixer self.prefixer = digital.ofdm_cyclic_prefixer(dp.fft_length, dp.symbol_length) + # normalize to energy = 1 after IFFT + self.multiply_const = blocks.multiply_const_cc(1/2048.0) + # convert back to vectors self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, dp.symbol_length) @@ -95,15 +99,16 @@ def __init__(self, dab_params, verbose=False, debug=False): # # data - self.connect((self,0), self.mapper_v2s, self.mapper_unpack, self.mapper, self.mapper_s2v, (self.insert_pilot,0), (self.sum_phase,0), self.interleave, self.move_and_insert_carrier, self.ifft, self.prefixer, self.s2v, (self.insert_null,0)) + #self.connect((self,0), self.mapper_v2s, self.mapper_unpack, self.mapper, self.mapper_s2v, (self.insert_pilot,0), (self.sum_phase,0), self.interleave, self.move_and_insert_carrier, self.ifft, self.prefixer, self.s2v, (self.insert_null,0)) + self.connect((self,0), self.mapper, (self.insert_pilot,0), (self.sum_phase,0), self.interleave, self.move_and_insert_carrier, self.ifft, self.prefixer, self.multiply_const, self.s2v, (self.insert_null,0)) self.connect(self.insert_null, self) # control signal (frame start) self.connect((self,1), (self.insert_pilot,1), (self.sum_phase,1), (self.insert_null,1)) - if debug: - #self.connect(self.mapper, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_mapper.dat")) - self.connect(self.insert_pilot, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_insert_pilot.dat")) + if False: + self.connect(self.mapper, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_mapper.dat")) + self.connect(self.insert_pilot, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_pilot_inserted.dat")) self.connect(self.sum_phase, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_sum_phase.dat")) self.connect(self.interleave, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_interleave.dat")) self.connect(self.move_and_insert_carrier, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/generated_signal_move_and_insert_carrier.dat")) diff --git a/swig/dab_swig.i b/swig/dab_swig.i index d43210de..c0e08144 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -61,6 +61,7 @@ #include "dab/demux_cc.h" #include "dab/differential_phasor_vcvc.h" #include "dab/select_cus_vcvc.h" +#include "dab/qpsk_mapper_vbvc.h" %} @@ -175,3 +176,5 @@ GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); GR_SWIG_BLOCK_MAGIC2(dab, differential_phasor_vcvc); %include "dab/select_cus_vcvc.h" GR_SWIG_BLOCK_MAGIC2(dab, select_cus_vcvc); +%include "dab/qpsk_mapper_vbvc.h" +GR_SWIG_BLOCK_MAGIC2(dab, qpsk_mapper_vbvc); From adeb4a76455b7ee6fa30e1e4b808820f3e328db2 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sat, 28 Oct 2017 13:28:09 +0200 Subject: [PATCH 071/135] sync: improve correlation for lower SNR --- lib/firecode_check_bb_impl.cc | 4 +-- lib/mp4_decode_bs_impl.cc | 14 ++++----- lib/ofdm_synchronization_cvf_impl.cc | 46 +++++++++++++++++++--------- lib/ofdm_synchronization_cvf_impl.h | 3 +- lib/reed_solomon_decode_bb_impl.cc | 2 +- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/lib/firecode_check_bb_impl.cc b/lib/firecode_check_bb_impl.cc index 6a0b1f41..b39ceb3f 100644 --- a/lib/firecode_check_bb_impl.cc +++ b/lib/firecode_check_bb_impl.cc @@ -80,14 +80,14 @@ namespace gr { while (d_nconsumed < noutput_items / d_frame_size - 4) { if (fc.check(&in[d_nconsumed * d_frame_size])) { - GR_LOG_DEBUG(d_logger, format("fire code (%d %d) OK at frame %d") %(int)in[d_nconsumed*d_frame_size] %(int)in[d_nconsumed*d_frame_size+1] % (nitems_read(0) / d_frame_size)); + //GR_LOG_DEBUG(d_logger, format("fire code (%d %d) OK at frame %d") %(int)in[d_nconsumed*d_frame_size] %(int)in[d_nconsumed*d_frame_size+1] % (nitems_read(0) / d_frame_size)); // fire code OK, copy superframe to output memcpy(out + d_nproduced * d_frame_size, in + d_nconsumed * d_frame_size, d_frame_size * 5); d_nproduced += 5; d_nconsumed += 5; d_firecode_passed = true; } else { - GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); + //GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); // shift of one logical frame d_nconsumed++; d_firecode_passed = false; diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index 9a74dd08..ac96f8ca 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -214,11 +214,11 @@ namespace gr { baudRate = sample_rate; } d_sample_rate = sample_rate; - GR_LOG_DEBUG(d_logger, format("bytes consumed %d") % (int) (hInfo.bytesconsumed)); - GR_LOG_DEBUG(d_logger, + //GR_LOG_DEBUG(d_logger, format("bytes consumed %d") % (int) (hInfo.bytesconsumed)); + /*GR_LOG_DEBUG(d_logger, format("sample_rate = %d, samples = %d, channels = %d, error = %d, sbr = %d") % sample_rate % samples % - (int) (hInfo.channels) % (int) (hInfo.error) % (int) (hInfo.sbr)); + (int) (hInfo.channels) % (int) (hInfo.error) % (int) (hInfo.sbr));*/ channels = hInfo.channels; if (hInfo.error != 0) { fprintf(stderr, "Warning: %s\n", @@ -244,7 +244,7 @@ namespace gr { } else GR_LOG_ERROR(d_logger, "Cannot handle these channels -> dump samples"); - GR_LOG_DEBUG(d_logger, format("Produced %d PCM samples (for each channel)") % (samples / 2)); + //GR_LOG_DEBUG(d_logger, format("Produced %d PCM samples (for each channel)") % (samples / 2)); d_nsamples_produced += samples / 2; return samples / 2; } @@ -307,10 +307,10 @@ namespace gr { d_ps_flag = (in[n * d_superframe_size + 2] >> 3) & 01; // bit 20 d_mpeg_surround = (in[n * d_superframe_size + 2] & 07); // bits 21 .. 23 // log header information - GR_LOG_DEBUG(d_logger, + /*GR_LOG_DEBUG(d_logger, format("superframe header: dac_rate %d, sbr_flag %d, aac_mode %d, ps_flag %d, surround %d") % (int) d_dac_rate % (int) d_sbr_flag % (int) d_aac_channel_mode % (int) d_ps_flag % - (int) d_mpeg_surround); + (int) d_mpeg_surround);*/ switch (2 * d_dac_rate + d_sbr_flag) { default: // cannot happen @@ -369,7 +369,7 @@ namespace gr { // CRC check of each AU (the 2 byte (16 bit) CRC word is excluded in aac_frame_length) if (crc16(&in[n * d_superframe_size + d_au_start[i]], aac_frame_length)) { - GR_LOG_DEBUG(d_logger, format("CRC check of AU %d successful") % i); + //GR_LOG_DEBUG(d_logger, format("CRC check of AU %d successful") % i); // handle proper AU handle_aac_frame(&in[n * d_superframe_size + d_au_start[i]], aac_frame_length, diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index 9dff5636..99d30bdd 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -70,6 +70,8 @@ namespace gr { d_on_triangle = false; d_control_counter = 0; d_phase = 0; + d_correlation_maximum = 0; + d_peak_set = false; } /* @@ -136,22 +138,34 @@ namespace gr { bool ofdm_synchronization_cvf_impl::detect_start_of_symbol() { - if (d_on_triangle) { - if (d_correlation_normalized_magnitude < 0.5) { - // we left the triangle + if(d_on_triangle){ + if(d_correlation_normalized_magnitude > d_correlation_maximum){ + d_correlation_maximum = d_correlation_normalized_magnitude; + + } + if(d_correlation_normalized_magnitude < d_correlation_maximum-0.05 && !d_peak_set){ + // we are right behind the peak + d_peak_set = true; + return true; + } + if(d_correlation_normalized_magnitude < 0.25){ + d_peak_set = false; d_on_triangle = false; - return false; - } else { - // we are still on the triangle but we already picked our pre-peak value + d_correlation_maximum = 0; + } + else{ + // we are still on the triangle but have not reached the end return false; } - } else { + } + else{ // not on a correlation triangle yet - if (d_correlation_normalized_magnitude > 0.85) { + if(d_correlation_normalized_magnitude > 0.35){ // no we are on the triangle d_on_triangle = true; - return true; - } else { + return false; + } + else{ // no triangle here return false; } @@ -174,7 +188,7 @@ namespace gr { // acquisition mode: search for next correlation peak after a NULL symbol delayed_correlation(&in[i], false); if (detect_start_of_symbol()) { - if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { + if (d_NULL_detected /*&& (d_energy_prefix > d_NULL_symbol_energy * 2)*/) { // calculate new frequency offset d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/sample //GR_LOG_DEBUG(d_logger, format("Start of frame, abs offset %d")%(nitems_read(0)+i)); @@ -190,9 +204,10 @@ namespace gr { d_wait_for_NULL = false; } else { //peak but not after NULL symbol + d_NULL_detected = false; } } else { - if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.1))) { + if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.4))) { // NULL symbol detection, if energy is < 0.1 * energy a symbol time later d_NULL_symbol_energy = d_energy_prefix; d_NULL_detected = true; @@ -219,20 +234,20 @@ namespace gr { delayed_correlation(&in[i], true); //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge + if (d_correlation_normalized_magnitude > 0.3) { //TODO: check if we are on right edge d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); //GR_LOG_DEBUG(d_logger, format("in track symbol %d") % (d_symbol_count)); } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)") % + GR_LOG_DEBUG(d_logger, format("Lost track at %d, switching ot acquisition mode (%d)") %d_symbol_count % d_correlation_normalized_magnitude); /*add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), pmt::from_float(d_correlation_normalized_magnitude));*/ } } - } else if (d_cyclic_prefix_length <= d_symbol_element_count) { + } else if (d_cyclic_prefix_length*0.75 <= d_symbol_element_count && d_symbol_element_count < d_cyclic_prefix_length*0.75 + d_symbol_length) { // calculate the complex frequency correction value float oi, oq; // fixed point sine and cosine @@ -244,6 +259,7 @@ namespace gr { //GR_LOG_DEBUG(d_logger, format("Set Tag %d")%(nitems_read(0)+i)); add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); + } // now we start copying one symbol length to the output out[d_nwritten++] = in[i] * fine_frequency_correction; diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index 52e2cf04..93d5c09d 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -55,7 +55,8 @@ namespace gr { bool d_on_triangle; int d_control_counter; float d_phase; - + bool d_peak_set; + float d_correlation_maximum; int d_nwritten; public: diff --git a/lib/reed_solomon_decode_bb_impl.cc b/lib/reed_solomon_decode_bb_impl.cc index bb84ac34..2d547dea 100644 --- a/lib/reed_solomon_decode_bb_impl.cc +++ b/lib/reed_solomon_decode_bb_impl.cc @@ -109,7 +109,7 @@ namespace gr { sf[pos * subch_index + i] = rs_packet[pos]; } } - GR_LOG_DEBUG(d_logger, format("RS corrected %d errors in superframe") % total_corr_count); + //GR_LOG_DEBUG(d_logger, format("RS corrected %d errors in superframe") % total_corr_count); d_corrected_errors = total_corr_count; } From 9d55f0c622a82d586394bc51305c1e68cc40cdc6 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 31 Oct 2017 12:45:34 +0100 Subject: [PATCH 072/135] wrap up transceiver with new sync --- examples/dab_receiver.grc | 877 +++++------------------------ examples/dab_transmitter.grc | 403 +------------ grc/CMakeLists.txt | 2 +- grc/dab_fib_source_b.xml | 28 +- grc/dab_fic_decode.xml | 45 -- grc/dab_fic_decode_vc.xml | 2 +- grc/dab_reed_solomon_encode_bb.xml | 2 +- 7 files changed, 177 insertions(+), 1182 deletions(-) delete mode 100644 grc/dab_fic_decode.xml diff --git a/examples/dab_receiver.grc b/examples/dab_receiver.grc index 3cec09b0..86534891 100644 --- a/examples/dab_receiver.grc +++ b/examples/dab_receiver.grc @@ -81,69 +81,6 @@ - - variable_qtgui_range - - comment - - - - value - 20 - - - _enabled - True - - - _coordinate - (288, 536) - - - gui_hint - - - - _rotation - 0 - - - id - SNR - - - label - - - - min_len - 200 - - - orient - Qt.Horizontal - - - start - -20 - - - step - 1 - - - stop - 60 - - - rangeType - float - - - widget - counter_slider - - variable_qtgui_range @@ -234,61 +171,6 @@ 2048000 - - analog_noise_source_x - - amp - 10**((-34.0-SNR)/20.0) - - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (104, 478) - - - _rotation - 0 - - - id - analog_noise_source_x_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - noise_type - analog.GR_GAUSSIAN - - - type - complex - - - seed - 0 - - audio_sink @@ -336,57 +218,6 @@ 32000 - - blocks_add_xx - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (328, 409) - - - _rotation - 0 - - - id - blocks_add_xx_0 - - - type - complex - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - num_inputs - 2 - - - vlen - 1 - - blocks_file_source @@ -403,15 +234,15 @@ _enabled - 1 + 0 file - /home/luca/Desktop/reinstes_dab.dat + _coordinate - (64, 397) + (144, 389) _rotation @@ -496,586 +327,194 @@ dab_dabplus_audio_decoder_ff - address - 0 - - - bit_rate - 112 - - - alias - - - - comment - - - - affinity - - - - dab_mode - 1 - - - _enabled - True - - - _coordinate - (672, 370) - - - _rotation - 0 - - - id - dab_dabplus_audio_decoder_ff_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - output_float - True - - - protection - 2 - - - samp_rate - samp_rate - - - subch_size - 84 - - - - dab_fic_decode_vc - - alias - - - - comment - - - - affinity - - - - dab_mode - 1 - - - _enabled - True - - - _coordinate - (624, 269) - - - _rotation - 0 - - - id - dab_fic_decode_vc_0 - - - samp_rate - samp_rate - - - - dab_ofdm_demod_cc - - alias - - - - comment - - - - affinity - - - - dab_mode - 1 - - - _enabled - True - - - _coordinate - (360, 281) - - - _rotation - 0 - - - id - dab_ofdm_demod_cc_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - samp_rate - samp_rate - - - - digital_mpsk_snr_est_cc - - alias - - - - comment - - - - affinity - - - - _enabled - 1 - - - alpha - 0.001 - - - _coordinate - (840, 174) - - - _rotation - 0 - - - id - digital_mpsk_snr_est_cc_0 - - - maxoutbuf - 0 - - - minoutbuf - 0 - - - tag_nsamples - 10000 - - - type - 0 - - - - note - - alias - - - - comment - 1. Set frequency in USRP -2. Run flowgraph and read fib_sink info in the console to get the DAB+ Decoder info -3. Set the DAB+ Decoder info and restart flowgraph -4. Adjust sampling rate - - - _enabled - True - - - _coordinate - (304, 12) - - - _rotation - 0 - - - id - note_0 - - - note - Instructions: - - - - qtgui_const_sink_x - - autoscale - False - - - alias - - - - comment - - - - affinity - - - - _enabled - 1 - - - _coordinate - (1056, 181) - - - gui_hint - - - - _rotation - 0 - - - grid - False - - - id - qtgui_const_sink_x_1 - - - legend - True - - - alpha1 - 1.0 - - - color1 - "blue" - - - label1 - - - - marker1 - 0 - - - style1 - 0 - - - width1 - 1 - - - alpha10 - 1.0 - - - color10 - "red" - - - label10 - - - - marker10 - 0 - - - style10 - 0 - - - width10 - 1 - - - alpha2 - 1.0 - - - color2 - "red" - - - label2 - - - - marker2 - 0 - - - style2 - 0 - - - width2 - 1 - - - alpha3 - 1.0 - - - color3 - "red" - - - label3 - - - - marker3 - 0 - - - style3 - 0 - - - width3 - 1 - - - alpha4 - 1.0 - - - color4 - "red" - - - label4 - - - - marker4 - 0 - - - style4 - 0 - - - width4 - 1 - - - alpha5 - 1.0 + address + 0 - color5 - "red" + bit_rate + 112 - label5 + alias - marker5 - 0 + comment + - style5 - 0 + affinity + - width5 + dab_mode 1 - alpha6 - 1.0 + _enabled + True - color6 - "red" + _coordinate + (672, 370) - label6 - + _rotation + 0 - marker6 - 0 + id + dab_dabplus_audio_decoder_ff_0 - style6 + maxoutbuf 0 - width6 - 1 + minoutbuf + 0 - alpha7 - 1.0 + output_float + True - color7 - "red" + protection + 2 - label7 - + samp_rate + samp_rate - marker7 - 0 + subch_size + 84 + + + dab_fic_decode_vc - style7 - 0 + alias + - width7 - 1 + comment + - alpha8 - 1.0 + affinity + - color8 - "red" + dab_mode + 1 - label8 - + _enabled + True - marker8 - 0 + _coordinate + (656, 269) - style8 + _rotation 0 - width8 - 1 - - - alpha9 - 1.0 + id + dab_fic_decode_vc_0 - color9 - "red" + samp_rate + samp_rate + + + dab_ofdm_demod_cc - label9 + alias - marker9 - 0 + comment + - style9 - 0 + affinity + - width9 + dab_mode 1 - name - "" + _enabled + True - nconnections - 1 + _coordinate + (360, 281) - size - 1024 + _rotation + 0 - tr_chan - 0 + id + dab_ofdm_demod_cc_0 - tr_level - 0.0 + maxoutbuf + 0 - tr_mode - qtgui.TRIG_MODE_FREE + minoutbuf + 0 - tr_slope - qtgui.TRIG_SLOPE_POS + samp_rate + samp_rate + + + note - tr_tag - "" + alias + - type - complex + comment + 1. Set frequency in USRP or activate file source for recorded IQ data +2. Run flowgraph and adjust gain +3. Read fib_sink info in the console to get the DAB Decoder info +4. Set the DAB+ Decoder info and restart flowgraph + +5. Execute "DABstep" out of your terminal for a user-friendly graphical application - update_time - 0.10 + _enabled + True - xmax - 2 + _coordinate + (304, 12) - xmin - -2 + _rotation + 0 - ymax - 2 + id + note_0 - ymin - -2 + note + Instructions: - qtgui_time_sink_x + qtgui_const_sink_x autoscale False @@ -1088,25 +527,17 @@ comment - - ctrlpanel - False - affinity - - entags - True - _enabled - True + 1 _coordinate - (424, 406) + (880, 181) gui_hint @@ -1122,7 +553,7 @@ id - qtgui_time_sink_x_0 + qtgui_const_sink_x_1 legend @@ -1142,11 +573,11 @@ marker1 - -1 + 0 style1 - 1 + 0 width1 @@ -1158,7 +589,7 @@ color10 - "blue" + "red" label10 @@ -1166,11 +597,11 @@ marker10 - -1 + 0 style10 - 1 + 0 width10 @@ -1190,11 +621,11 @@ marker2 - -1 + 0 style2 - 1 + 0 width2 @@ -1206,7 +637,7 @@ color3 - "green" + "red" label3 @@ -1214,11 +645,11 @@ marker3 - -1 + 0 style3 - 1 + 0 width3 @@ -1230,7 +661,7 @@ color4 - "black" + "red" label4 @@ -1238,11 +669,11 @@ marker4 - -1 + 0 style4 - 1 + 0 width4 @@ -1254,7 +685,7 @@ color5 - "cyan" + "red" label5 @@ -1262,11 +693,11 @@ marker5 - -1 + 0 style5 - 1 + 0 width5 @@ -1278,7 +709,7 @@ color6 - "magenta" + "red" label6 @@ -1286,11 +717,11 @@ marker6 - -1 + 0 style6 - 1 + 0 width6 @@ -1302,7 +733,7 @@ color7 - "yellow" + "red" label7 @@ -1310,11 +741,11 @@ marker7 - -1 + 0 style7 - 1 + 0 width7 @@ -1326,7 +757,7 @@ color8 - "dark red" + "red" label8 @@ -1334,11 +765,11 @@ marker8 - -1 + 0 style8 - 1 + 0 width8 @@ -1350,7 +781,7 @@ color9 - "dark green" + "red" label9 @@ -1358,11 +789,11 @@ marker9 - -1 + 0 style9 - 1 + 0 width9 @@ -1380,18 +811,10 @@ size 1024 - - srate - samp_rate - tr_chan 0 - - tr_delay - 0 - tr_level 0.0 @@ -1417,20 +840,20 @@ 0.10 - ylabel - Amplitude + xmax + 2 - yunit - "" + xmin + -2 ymax - 1 + 2 ymin - -1 + -2 @@ -2357,7 +1780,7 @@ _enabled - 0 + 1 _coordinate @@ -2512,33 +1935,15 @@ - - analog_noise_source_x_0 - blocks_add_xx_0 - 0 - 1 - - - blocks_add_xx_0 - dab_ofdm_demod_cc_0 - 0 - 0 - - - blocks_add_xx_0 - qtgui_time_sink_x_0 - 0 - 0 - blocks_file_source_0 - blocks_add_xx_0 + dab_ofdm_demod_cc_0 0 0 blocks_vector_to_stream_0 - digital_mpsk_snr_est_cc_0 + qtgui_const_sink_x_1 0 0 @@ -2572,12 +1977,6 @@ 1 0 - - digital_mpsk_snr_est_cc_0 - qtgui_const_sink_x_1 - 0 - 0 - uhd_usrp_source_0 dab_ofdm_demod_cc_0 diff --git a/examples/dab_transmitter.grc b/examples/dab_transmitter.grc index 73fe3064..bc026c1f 100644 --- a/examples/dab_transmitter.grc +++ b/examples/dab_transmitter.grc @@ -128,7 +128,7 @@ _enabled - True + 0 file @@ -136,11 +136,11 @@ _coordinate - (1120, 318) + (1158, 328) _rotation - 0 + 270 id @@ -273,7 +273,7 @@ _coordinate - (704, 228) + (752, 236) _rotation @@ -324,7 +324,7 @@ _coordinate - (672, 294) + (632, 294) _rotation @@ -438,7 +438,7 @@ _coordinate - (448, 217) + (496, 225) _rotation @@ -480,16 +480,12 @@ - country_ID - 1 - - - dab_mode + coutry_ID 1 dabplus - 1 + [1] data_rate_n @@ -501,11 +497,11 @@ ensemble_label - "jfkldsa" + "GNU Radio Tune" _coordinate - (24, 149) + (16, 164) _rotation @@ -523,26 +519,26 @@ minoutbuf 0 + + transmission_mode + 1 + num_subch 1 - protection_mode - [2] + programme_service_labels + "DABstep " - service_comp_label - "fdsas" + protection_mode + [2] service_comp_lang 1 - - programme_service_labels - "" - dab_fic_encode @@ -568,7 +564,7 @@ _coordinate - (256, 205) + (304, 213) _rotation @@ -674,7 +670,7 @@ _coordinate - (912, 471) + (824, 471) _rotation @@ -725,7 +721,7 @@ _coordinate - (880, 233) + (920, 241) _rotation @@ -782,349 +778,6 @@ Instructions: - - qtgui_const_sink_x - - autoscale - False - - - alias - - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (1136, 120) - - - gui_hint - - - - _rotation - 0 - - - grid - False - - - id - qtgui_const_sink_x_0 - - - legend - True - - - alpha1 - 1.0 - - - color1 - "blue" - - - label1 - - - - marker1 - 0 - - - style1 - 0 - - - width1 - 1 - - - alpha10 - 1.0 - - - color10 - "red" - - - label10 - - - - marker10 - 0 - - - style10 - 0 - - - width10 - 1 - - - alpha2 - 1.0 - - - color2 - "red" - - - label2 - - - - marker2 - 0 - - - style2 - 0 - - - width2 - 1 - - - alpha3 - 1.0 - - - color3 - "red" - - - label3 - - - - marker3 - 0 - - - style3 - 0 - - - width3 - 1 - - - alpha4 - 1.0 - - - color4 - "red" - - - label4 - - - - marker4 - 0 - - - style4 - 0 - - - width4 - 1 - - - alpha5 - 1.0 - - - color5 - "red" - - - label5 - - - - marker5 - 0 - - - style5 - 0 - - - width5 - 1 - - - alpha6 - 1.0 - - - color6 - "red" - - - label6 - - - - marker6 - 0 - - - style6 - 0 - - - width6 - 1 - - - alpha7 - 1.0 - - - color7 - "red" - - - label7 - - - - marker7 - 0 - - - style7 - 0 - - - width7 - 1 - - - alpha8 - 1.0 - - - color8 - "red" - - - label8 - - - - marker8 - 0 - - - style8 - 0 - - - width8 - 1 - - - alpha9 - 1.0 - - - color9 - "red" - - - label9 - - - - marker9 - 0 - - - style9 - 0 - - - width9 - 1 - - - name - "" - - - nconnections - 1 - - - size - 1024 - - - tr_chan - 0 - - - tr_level - 0.0 - - - tr_mode - qtgui.TRIG_MODE_FREE - - - tr_slope - qtgui.TRIG_SLOPE_POS - - - tr_tag - "" - - - type - complex - - - update_time - 0.10 - - - xmax - 2 - - - xmin - -2 - - - ymax - 2 - - - ymin - -2 - - reed_solomon_encode_bb @@ -1145,7 +798,7 @@ _coordinate - (672, 492) + (648, 492) _rotation @@ -1836,15 +1489,15 @@ _enabled - 0 + 1 _coordinate - (1096, 200) + (1128, 48) _rotation - 0 + 90 id @@ -2059,12 +1712,6 @@ 0 0 - - dab_ofdm_mod_0 - qtgui_const_sink_x_0 - 0 - 0 - dab_ofdm_mod_0 uhd_usrp_sink_0 diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 3fe4e946..153f7d74 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -31,7 +31,7 @@ install(FILES dab_complex_to_interleaved_float_vcf.xml dab_modulo_ff.xml dab_measure_processing_rate.xml - dab_fic_decode.xml +# dab_fic_decode.xml dab_ofdm_demod.xml dab_ofdm_mod.xml dab_select_vectors.xml diff --git a/grc/dab_fib_source_b.xml b/grc/dab_fib_source_b.xml index 4a25fef6..89979f05 100644 --- a/grc/dab_fib_source_b.xml +++ b/grc/dab_fib_source_b.xml @@ -3,11 +3,10 @@ dab_fib_source_b [DAB] import dab - dab.fib_source_b($dab_mode, $num_subch, $ensemble_label, $programme_service_labels, $service_comp_label, $service_comp_lang, $protection_mode, $data_rate_n) - - DAB Mode - dab_mode - 1 + dab.fib_source_b($transmission_mode, $coutry_ID, $num_subch, $ensemble_label, $programme_service_labels, "", $service_comp_lang, $protection_mode, $data_rate_n, $dabplus) + + Mode + transmission_mode int + + dab_ofdm_demod_cc_0 + blocks_null_sink_0 + 0 + 0 + dab_ofdm_demod_cc_0 blocks_vector_to_stream_0 @@ -1971,16 +3837,34 @@ 0 0 + + dab_ofdm_demod_cc_0 + blocks_null_sink_0_0 + 1 + 0 + dab_ofdm_demod_cc_0 dab_dabplus_audio_decoder_ff_0 1 0 + + rtlsdr_source_0 + dab_ofdm_demod_cc_0 + 0 + 0 + uhd_usrp_source_0 dab_ofdm_demod_cc_0 0 0 + + uhd_usrp_source_0 + qtgui_time_sink_x_0 + 0 + 0 + diff --git a/include/dab/ofdm_coarse_frequency_correction_vcvc.h b/include/dab/ofdm_coarse_frequency_correction_vcvc.h index e6f46e9c..f074ee94 100644 --- a/include/dab/ofdm_coarse_frequency_correction_vcvc.h +++ b/include/dab/ofdm_coarse_frequency_correction_vcvc.h @@ -38,6 +38,8 @@ namespace gr { public: typedef boost::shared_ptr sptr; + virtual float get_snr() = 0; + /*! * \brief Return a shared_ptr to a new instance of dab::ofdm_coarse_frequency_correction_vcvc. * diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index b16d753f..4536cfad 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -24,6 +24,7 @@ #include #include "ofdm_coarse_frequency_correction_vcvc_impl.h" +#include namespace gr { namespace dab { @@ -47,6 +48,7 @@ namespace gr { d_cyclic_prefix_length(cyclic_prefix_length) { d_freq_offset = 0; + d_snr = 0; } /* @@ -93,6 +95,38 @@ namespace gr { d_freq_offset = index; } + /*! SNR measurement by comparing the energy of occupied sub-carriers with the ones of empty sub-carriers + * @return estimated SNR float value + */ + void + ofdm_coarse_frequency_correction_vcvc_impl::measure_snr(const gr_complex *symbol) + { + // measure normalized energy of occupied sub-carriers + float energy = 0; + for (int i=0; i noise){ + // now we can calculate the SNR in dB + d_snr = 10*log((energy-noise)/noise); + } + } + int ofdm_coarse_frequency_correction_vcvc_impl::work(int noutput_items, gr_vector_const_void_star &input_items, @@ -110,7 +144,7 @@ namespace gr { */ if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0) { measure_energy(&in[i * d_fft_length]); - //fprintf(stderr, "New frame, first used sub-carrier: %d\n", d_freq_offset); + measure_snr(&in[i * d_fft_length]); tag_count++; } // copy the first half (left of central sub-carrier) of the sub-carriers to the output diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h index 2bda1adc..93f1989a 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h @@ -33,12 +33,17 @@ namespace gr { int d_num_carriers; int d_cyclic_prefix_length; unsigned int d_freq_offset; + float d_snr; public: ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, int num_carriers, int cyclic_prefix_length); ~ofdm_coarse_frequency_correction_vcvc_impl(); void measure_energy(const gr_complex*); + void measure_snr(const gr_complex*); + + virtual float get_snr() + { return d_snr;} // Where all the action really happens int work(int noutput_items, diff --git a/python/GUI/dab_audio.wav b/python/GUI/dab_audio.wav new file mode 100644 index 0000000000000000000000000000000000000000..ee612c550f57f2281409de086a211b19047f3e80 GIT binary patch literal 44 tcmWIYbaP_>f^f$$*R 10: + if SNR > 20.0: self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") - if SNR > 20: - SNR = 20 - elif 5 < SNR <= 10: + if SNR > 60.0: + SNR = 60 + elif 10 < SNR <= 15: self.setStyleSheet("""QProgressBar::chunk { background: "yellow"; }""") else: self.setStyleSheet("""QProgressBar::chunk { background: "red"; }""") - if SNR < -20 or math.isnan(SNR): - SNR = -20 - self.bar_snr.setValue(SNR) + if SNR < 0 or math.isnan(SNR): + SNR = 0 + self.bar_snr.setValue(int(SNR)) self.lcd_snr.display(SNR) else: - self.bar_snr.setValue(-20) + self.bar_snr.setValue(0) self.label_snr.setText("SNR: no reception") self.snr_timer.start(1000) diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 17557942..6166f60e 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -215,8 +215,8 @@ def setupUi(self, MainWindow): self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) self.bar_snr = QtGui.QProgressBar(self.tab_reception) self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) - self.bar_snr.setMinimum(-20) - self.bar_snr.setMaximum(20) + self.bar_snr.setMinimum(0) + self.bar_snr.setMaximum(60) self.bar_snr.setProperty("value", 0) self.bar_snr.setFormat(_fromUtf8("")) self.bar_snr.setObjectName(_fromUtf8("bar_snr")) diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 1a6a8d62..48a9b8a2 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -87,7 +87,6 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud # SNR measurement ######################## self.v2s_snr = blocks.vector_to_stream(gr.sizeof_gr_complex*1, self.dab_params.num_carriers) - self.snr_measurement = digital.mpsk_snr_est_cc_make(digital.SNR_EST_SIMPLE, 10000) self.constellation_plot = qtgui.const_sink_c_make(1024, "", 1) self.constellation_plot.enable_grid(True) @@ -131,8 +130,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect((self.demod, 1), (self.msc_dec, 1)) self.connect((self.mp2_dec, 0), self.s2f_left, self.gain_left) self.connect((self.mp2_dec, 1), self.s2f_right, self.gain_right) - self.connect((self.demod, 0), self.v2s_snr, self.snr_measurement, blocks.null_sink_make(gr.sizeof_gr_complex)) - self.connect(self.v2s_snr, self.constellation_plot) + self.connect((self.demod, 0), self.v2s_snr, self.constellation_plot) # connect audio to sound card and file sink if self.dabplus: self.connect((self.dabplus, 0), (self.audio, 0)) @@ -176,7 +174,7 @@ def get_sample_rate(self): return self.dabplus.get_sample_rate() def get_snr(self): - return self.snr_measurement.snr() + return self.demod.get_snr() def get_firecode_passed(self): return self.dabplus.get_firecode_passed() diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index bbc85817..746771ff 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -62,9 +62,6 @@ def __init__(self, dab_params): # differential phasor self.differential_phasor = dab.diff_phasor_vcc_make(1536) - # phase correction with phase reference symbol - self.phase_correction = dab.phase_correction_cc_make(self.dp.num_carriers) - # frequency deinterleaving self.frequency_deinterleaver = dab.frequency_interleaver_vcc_make(self.dp.frequency_deinterleaving_sequence_array) @@ -83,3 +80,6 @@ def __init__(self, dab_params): (self, 0) ) self.connect((self.demux, 1), (self, 1)) + + def get_snr(self): + return self.coarse_freq_corr.get_snr() From 3c3f2aa834d5e19b2c3dba513feb0715a9ac16fb Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 13 Nov 2017 14:31:29 +0100 Subject: [PATCH 093/135] remove binary data file --- python/GUI/dab_audio.wav | Bin 44 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 python/GUI/dab_audio.wav diff --git a/python/GUI/dab_audio.wav b/python/GUI/dab_audio.wav deleted file mode 100644 index ee612c550f57f2281409de086a211b19047f3e80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44 tcmWIYbaP_>f^f$$*R Date: Tue, 14 Nov 2017 16:59:33 +0100 Subject: [PATCH 094/135] correct fft/ifft normalization for power 1 in QPSK and in transmission signal --- python/ofdm.py | 3 ++- python/ofdm_demod_cc.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/python/ofdm.py b/python/ofdm.py index adbd9097..c24de3b5 100644 --- a/python/ofdm.py +++ b/python/ofdm.py @@ -32,6 +32,7 @@ from threading import Timer from time import sleep from math import pi +from math import sqrt """ modulator and demodulator for the DAB physical layer @@ -86,7 +87,7 @@ def __init__(self, dab_params, verbose=False, debug=False): self.prefixer = digital.ofdm_cyclic_prefixer(dp.fft_length, dp.symbol_length) # normalize to energy = 1 after IFFT - self.multiply_const = blocks.multiply_const_cc(1/2048.0) + self.multiply_const = blocks.multiply_const_cc(1.0/sqrt(2048)) # convert back to vectors self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, dp.symbol_length) diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index 746771ff..5fc01509 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -20,6 +20,7 @@ from gnuradio import gr, blocks from gnuradio import fft from gnuradio import digital +from math import sqrt import dab class ofdm_demod_cc(gr.hier_block2): @@ -52,6 +53,7 @@ def __init__(self, dab_params): # FFT self.s2v_fft = blocks.stream_to_vector_make(gr.sizeof_gr_complex, self.dp.fft_length) self.fft = fft.fft_vcc(self.dp.fft_length, True, [], True) + self.multiply = blocks.multiply_const_vcc([1.0/sqrt(2048)]*self.dp.fft_length) # coarse frequency correction (sub-carrier assignment) self.coarse_freq_corr = dab.ofdm_coarse_frequency_correction_vcvc_make(self.dp.fft_length, @@ -73,6 +75,7 @@ def __init__(self, dab_params): self.sync, self.s2v_fft, self.fft, + self.multiply, self.coarse_freq_corr, self.differential_phasor, self.frequency_deinterleaver, From 3c50f9fbc416688f91ed73436c04600c08502b5b Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Thu, 30 Nov 2017 15:36:30 +0100 Subject: [PATCH 095/135] improve flowgraphs for loopback ability --- examples/dab_receiver.grc | 500 +++++++++---- examples/dab_transmitter.grc | 1271 ++++++++++++++++++++++++++++------ 2 files changed, 1420 insertions(+), 351 deletions(-) diff --git a/examples/dab_receiver.grc b/examples/dab_receiver.grc index 5e107935..743bc2f0 100644 --- a/examples/dab_receiver.grc +++ b/examples/dab_receiver.grc @@ -81,6 +81,45 @@ + + variable_qtgui_entry + + comment + + + + value + 201072000 + + + _enabled + True + + + _coordinate + (855, 12) + + + gui_hint + + + + _rotation + 0 + + + id + freq + + + label + Frequency + + + type + int + + variable_qtgui_range @@ -195,7 +234,7 @@ _coordinate - (928, 401) + (905, 417) _rotation @@ -238,11 +277,11 @@ file - /home/luca/Desktop/iq_dab/171011.dat + /home/luca/Desktop/loopback/171130_rec.dat _coordinate - (108, 436) + (133, 433) _rotation @@ -273,100 +312,6 @@ 1 - - blocks_null_sink - - alias - - - - bus_conns - [[0,],] - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (936, 276) - - - _rotation - 0 - - - id - blocks_null_sink_0 - - - type - complex - - - num_inputs - 1 - - - vlen - 1536 - - - - blocks_null_sink - - alias - - - - bus_conns - [[0,],] - - - comment - - - - affinity - - - - _enabled - True - - - _coordinate - (949, 330) - - - _rotation - 0 - - - id - blocks_null_sink_0_0 - - - type - complex - - - num_inputs - 1 - - - vlen - 1536 - - blocks_vector_to_stream @@ -387,7 +332,7 @@ _coordinate - (672, 188) + (675, 189) _rotation @@ -422,7 +367,7 @@ dab_dabplus_audio_decoder_ff address - 234 + 54 bit_rate @@ -450,7 +395,7 @@ _coordinate - (672, 370) + (687, 386) _rotation @@ -509,7 +454,7 @@ _coordinate - (656, 269) + (674, 274) _rotation @@ -548,7 +493,7 @@ _coordinate - (360, 281) + (415, 286) _rotation @@ -579,7 +524,7 @@ comment - 1. Set frequency in USRP or activate file source for recorded IQ data + 1. Enable the data source of your choice and set the center frequency for hardware devices 2. Run flowgraph and adjust gain 3. Read fib_sink info in the console to get the DAB Decoder info 4. Set the DAB+ Decoder info and restart flowgraph @@ -592,7 +537,7 @@ _coordinate - (304, 12) + (301, 8) _rotation @@ -631,7 +576,7 @@ _coordinate - (880, 181) + (869, 182) gui_hint @@ -950,6 +895,293 @@ -2 + + qtgui_freq_sink_x + + autoscale + False + + + average + 1.0 + + + bw + samp_rate + + + alias + + + + fc + 0 + + + comment + + + + ctrlpanel + False + + + affinity + + + + _enabled + True + + + fftsize + 1024 + + + _coordinate + (416, 191) + + + gui_hint + + + + _rotation + 0 + + + grid + False + + + id + qtgui_freq_sink_x_0 + + + legend + True + + + alpha1 + 1.0 + + + color1 + "blue" + + + label1 + + + + width1 + 1 + + + alpha10 + 1.0 + + + color10 + "dark blue" + + + label10 + + + + width10 + 1 + + + alpha2 + 1.0 + + + color2 + "red" + + + label2 + + + + width2 + 1 + + + alpha3 + 1.0 + + + color3 + "green" + + + label3 + + + + width3 + 1 + + + alpha4 + 1.0 + + + color4 + "black" + + + label4 + + + + width4 + 1 + + + alpha5 + 1.0 + + + color5 + "cyan" + + + label5 + + + + width5 + 1 + + + alpha6 + 1.0 + + + color6 + "magenta" + + + label6 + + + + width6 + 1 + + + alpha7 + 1.0 + + + color7 + "yellow" + + + label7 + + + + width7 + 1 + + + alpha8 + 1.0 + + + color8 + "dark red" + + + label8 + + + + width8 + 1 + + + alpha9 + 1.0 + + + color9 + "dark green" + + + label9 + + + + width9 + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + name + "" + + + nconnections + 1 + + + showports + True + + + freqhalf + True + + + tr_chan + 0 + + + tr_level + 0.0 + + + tr_mode + qtgui.TRIG_MODE_FREE + + + tr_tag + "" + + + type + complex + + + update_time + 0.10 + + + wintype + firdes.WIN_BLACKMAN_hARRIS + + + ymax + 10 + + + ymin + -140 + + qtgui_time_sink_x @@ -978,11 +1210,11 @@ _enabled - 0 + 1 _coordinate - (389, 392) + (418, 381) gui_hint @@ -1329,7 +1561,7 @@ dc_offset_mode0 - 0 + 2 corr0 @@ -1337,7 +1569,7 @@ freq0 - 208064000 + freq gain_mode0 @@ -1353,7 +1585,7 @@ gain0 - 10 + gain_slider ant10 @@ -2609,11 +2841,11 @@ _enabled - True + 0 _coordinate - (104, 151) + (101, 150) _rotation @@ -2732,7 +2964,7 @@ center_freq0 - 208064000 + freq dc_offs_enb0 @@ -3620,7 +3852,7 @@ clock_rate - 20*samp_rate + 8*samp_rate comment @@ -3640,11 +3872,11 @@ _enabled - 0 + 1 _coordinate - (93, 321) + (121, 315) _rotation @@ -3797,7 +4029,13 @@ blocks_file_source_0 - dab_ofdm_demod_cc_0 + qtgui_freq_sink_x_0 + 0 + 0 + + + blocks_file_source_0 + qtgui_time_sink_x_0 0 0 @@ -3819,12 +4057,6 @@ 1 1 - - dab_ofdm_demod_cc_0 - blocks_null_sink_0 - 0 - 0 - dab_ofdm_demod_cc_0 blocks_vector_to_stream_0 @@ -3839,19 +4071,25 @@ dab_ofdm_demod_cc_0 - blocks_null_sink_0_0 + dab_dabplus_audio_decoder_ff_0 1 0 - dab_ofdm_demod_cc_0 - dab_dabplus_audio_decoder_ff_0 - 1 + rtlsdr_source_0 + dab_ofdm_demod_cc_0 + 0 0 rtlsdr_source_0 - dab_ofdm_demod_cc_0 + qtgui_freq_sink_x_0 + 0 + 0 + + + rtlsdr_source_0 + qtgui_time_sink_x_0 0 0 @@ -3861,6 +4099,12 @@ 0 0 + + uhd_usrp_source_0 + qtgui_freq_sink_x_0 + 0 + 0 + uhd_usrp_source_0 qtgui_time_sink_x_0 diff --git a/examples/dab_transmitter.grc b/examples/dab_transmitter.grc index bc026c1f..4794ee70 100644 --- a/examples/dab_transmitter.grc +++ b/examples/dab_transmitter.grc @@ -10,7 +10,7 @@ window_size - + 4096,2048 category @@ -82,18 +82,26 @@ - variable + variable_qtgui_range comment + + value + 0.3 + _enabled True _coordinate - (8, 77) + (670, 12) + + + gui_hint + _rotation @@ -101,63 +109,169 @@ id - samp_rate + ampl - value - 2048000 + label + Amplitude + + + min_len + 200 + + + orient + Qt.Horizontal + + + start + 0 + + + step + 0.01 + + + stop + 1 + + + rangeType + float + + + widget + counter_slider - blocks_file_sink + variable_qtgui_entry - append - False + comment + - alias + value + 201072000 + + + _enabled + True + + + _coordinate + (934, 11) + + + gui_hint + + _rotation + 0 + + + id + freq + + + label + Frequency + + + type + int + + + + variable_qtgui_range comment - affinity - + value + 50 _enabled - 0 + True - file - /home/luca/Desktop/grc_trans_test.dat + _coordinate + (807, 11) - _coordinate - (1158, 328) + gui_hint + _rotation - 270 + 0 id - blocks_file_sink_0 + gain_range - type - complex + label + Gain - unbuffered - False + min_len + 200 - vlen + orient + Qt.Horizontal + + + start + 0 + + + step 1 + + stop + 100 + + + rangeType + float + + + widget + counter_slider + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (8, 77) + + + _rotation + 0 + + + id + samp_rate + + + value + 2048000 + blocks_float_to_short @@ -253,6 +367,57 @@ 1 + + blocks_multiply_const_vxx + + alias + + + + comment + + + + const + ampl + + + affinity + + + + _enabled + True + + + _coordinate + (1127, 252) + + + _rotation + 0 + + + id + blocks_multiply_const_vxx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + blocks_stream_to_vector @@ -324,7 +489,7 @@ _coordinate - (632, 294) + (716, 288) _rotation @@ -390,32 +555,689 @@ (24, 481) - _rotation - 0 + _rotation + 0 + + + id + blocks_wavfile_source_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + nchan + 2 + + + repeat + True + + + + dab_dab_transmission_frame_mux_bb + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + _enabled + True + + + _coordinate + (496, 225) + + + _rotation + 0 + + + id + dab_dab_transmission_frame_mux_bb_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_subch + 1 + + + subch_size + [84] + + + + dab_fib_source_b + + alias + + + + comment + + + + affinity + + + + coutry_ID + 1 + + + dabplus + [1] + + + data_rate_n + [14] + + + _enabled + True + + + ensemble_label + "GNU Radio Tune" + + + _coordinate + (16, 164) + + + _rotation + 0 + + + id + dab_fib_source_b_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + transmission_mode + 1 + + + num_subch + 1 + + + programme_service_labels + "DABstep " + + + protection_mode + [2] + + + service_comp_lang + 1 + + + + dab_fic_encode + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + _enabled + True + + + _coordinate + (304, 213) + + + _rotation + 0 + + + id + dab_fic_encode_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + samp_rate + + + + dab_mp4_encode_sb + + afterburner + 1 + + + samp_rate + 32000 + + + bit_rate_n + 14 + + + alias + + + + channels + 2 + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (448, 478) + + + _rotation + 0 + + + id + dab_mp4_encode_sb_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + dab_msc_encode + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + data_rate_n + 14 + + + _enabled + True + + + _coordinate + (824, 471) + + + _rotation + 0 + + + id + dab_msc_encode_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + protection + 2 + + + samp_rate + samp_rate + + + + dab_ofdm_mod + + alias + + + + comment + + + + affinity + + + + dab_mode + 1 + + + _enabled + True + + + _coordinate + (921, 241) + + + _rotation + 0 + + + id + dab_ofdm_mod_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + samp_rate + + + + note + + alias + + + + comment + 1. Set frequency and clock source (default is external clock for better performance of the transmitter) in USRP +2. Choose audio source (.wav file or audio source) +3. Add more sub channels (optional) +4. Write Service Info and Multiplex Info in FIB source + +5. Execute "DABstep" out of your terminal for a user-friendly graphical application + + + _enabled + True + + + _coordinate + (200, 12) + + + _rotation + 0 + + + id + note_0 + + + note + Instructions: + + + + qtgui_freq_sink_x + + autoscale + False + + + average + 1.0 + + + bw + samp_rate + + + alias + + + + fc + 0 + + + comment + + + + ctrlpanel + False + + + affinity + + + + _enabled + True + + + fftsize + 1024 + + + _coordinate + (1323, 347) + + + gui_hint + + + + _rotation + 0 + + + grid + False + + + id + qtgui_freq_sink_x_0 + + + legend + True + + + alpha1 + 1.0 + + + color1 + "blue" + + + label1 + + + + width1 + 1 + + + alpha10 + 1.0 + + + color10 + "dark blue" + + + label10 + + + + width10 + 1 + + + alpha2 + 1.0 + + + color2 + "red" + + + label2 + + + + width2 + 1 + + + alpha3 + 1.0 + + + color3 + "green" + + + label3 + + + + width3 + 1 + + + alpha4 + 1.0 + + + color4 + "black" + + + label4 + + + + width4 + 1 + + + alpha5 + 1.0 + + + color5 + "cyan" + + + label5 + + + + width5 + 1 + + + alpha6 + 1.0 + + + color6 + "magenta" + + + label6 + + + + width6 + 1 + + + alpha7 + 1.0 + + + color7 + "yellow" + + + label7 + + + + width7 + 1 + + + alpha8 + 1.0 + + + color8 + "dark red" + + + label8 + + + + width8 + 1 + + + alpha9 + 1.0 + + + color9 + "dark green" + + + label9 + + + + width9 + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + name + "" + + + nconnections + 1 + + + showports + True + + + freqhalf + True + + + tr_chan + 0 + + + tr_level + 0.0 + + + tr_mode + qtgui.TRIG_MODE_FREE + + + tr_tag + "" - id - blocks_wavfile_source_0 + type + complex - maxoutbuf - 0 + update_time + 0.10 - minoutbuf - 0 + wintype + firdes.WIN_BLACKMAN_hARRIS - nchan - 2 + ymax + 10 - repeat - True + ymin + -140 - dab_dab_transmission_frame_mux_bb + qtgui_time_sink_x + + autoscale + False + alias @@ -424,13 +1246,17 @@ comment + + ctrlpanel + False + affinity - dab_mode - 1 + entags + True _enabled @@ -438,344 +1264,331 @@ _coordinate - (496, 225) + (1324, 428) + + + gui_hint + _rotation 0 - id - dab_dab_transmission_frame_mux_bb_0 + grid + False - maxoutbuf - 0 + id + qtgui_time_sink_x_0 - minoutbuf - 0 + legend + True - num_subch - 1 + alpha1 + 1.0 - subch_size - [84] + color1 + "blue" - - - dab_fib_source_b - alias + label1 - comment - + marker1 + -1 - affinity - + style1 + 1 - coutry_ID + width1 1 - dabplus - [1] + alpha10 + 1.0 - data_rate_n - [14] + color10 + "blue" - _enabled - True + label10 + - ensemble_label - "GNU Radio Tune" + marker10 + -1 - _coordinate - (16, 164) + style10 + 1 - _rotation - 0 + width10 + 1 - id - dab_fib_source_b_0 + alpha2 + 1.0 - maxoutbuf - 0 + color2 + "red" - minoutbuf - 0 + label2 + - transmission_mode - 1 + marker2 + -1 - num_subch + style2 1 - programme_service_labels - "DABstep " - - - protection_mode - [2] - - - service_comp_lang + width2 1 - - - dab_fic_encode - alias - + alpha3 + 1.0 - comment - + color3 + "green" - affinity + label3 - dab_mode - 1 + marker3 + -1 - _enabled - True + style3 + 1 - _coordinate - (304, 213) + width3 + 1 - _rotation - 0 + alpha4 + 1.0 - id - dab_fic_encode_0 + color4 + "black" - maxoutbuf - 0 + label4 + - minoutbuf - 0 + marker4 + -1 - samp_rate - samp_rate + style4 + 1 - - - dab_mp4_encode_sb - afterburner + width4 1 - samp_rate - 32000 + alpha5 + 1.0 - bit_rate_n - 14 + color5 + "cyan" - alias + label5 - channels - 2 + marker5 + -1 - comment - + style5 + 1 - affinity - + width5 + 1 - _enabled - True + alpha6 + 1.0 - _coordinate - (448, 478) + color6 + "magenta" - _rotation - 0 + label6 + - id - dab_mp4_encode_sb_0 + marker6 + -1 - maxoutbuf - 0 + style6 + 1 - minoutbuf - 0 + width6 + 1 - - - dab_msc_encode - alias - + alpha7 + 1.0 - comment - + color7 + "yellow" - affinity + label7 - dab_mode + marker7 + -1 + + + style7 1 - data_rate_n - 14 + width7 + 1 - _enabled - True + alpha8 + 1.0 - _coordinate - (824, 471) + color8 + "dark red" - _rotation - 0 + label8 + - id - dab_msc_encode_0 + marker8 + -1 - maxoutbuf - 0 + style8 + 1 - minoutbuf - 0 + width8 + 1 - protection - 2 + alpha9 + 1.0 - samp_rate - samp_rate + color9 + "dark green" - - - dab_ofdm_mod - alias + label9 - comment - + marker9 + -1 - affinity - + style9 + 1 - dab_mode + width9 1 - _enabled - True + name + "" - _coordinate - (920, 241) + nconnections + 1 - _rotation - 0 + size + 1024 - id - dab_ofdm_mod_0 + srate + samp_rate - maxoutbuf + tr_chan 0 - minoutbuf + tr_delay 0 - samp_rate - samp_rate + tr_level + 0.0 - - - note - alias - + tr_mode + qtgui.TRIG_MODE_FREE - comment - 1. Set frequency in USRP -2. Choose audio source (.wav file or audio source) -3. Add more sub channels (optional) -4. Write Service Info and Multiplex Info in FIB source + tr_slope + qtgui.TRIG_SLOPE_POS - _enabled - True + tr_tag + "" - _coordinate - (200, 12) + type + complex - _rotation - 0 + update_time + 0.10 - id - note_0 + ylabel + Amplitude - note - Instructions: + yunit + "" + + + ymax + 1 + + + ymin + -1 @@ -837,7 +1650,7 @@ center_freq0 - 208064000 + uhd.tune_request(freq, 2*samp_rate) norm_gain0 @@ -845,7 +1658,7 @@ gain0 - 50 + gain_range ant10 @@ -1469,7 +2282,7 @@ clock_rate - 0.0 + 8*samp_rate comment @@ -1493,11 +2306,11 @@ _coordinate - (1128, 48) + (1316, 187) _rotation - 90 + 0 id @@ -1509,7 +2322,7 @@ clock_source0 - + external sd_spec0 @@ -1517,7 +2330,7 @@ time_source0 - + external clock_source1 @@ -1652,6 +2465,24 @@ 0 1 + + blocks_multiply_const_vxx_0 + qtgui_freq_sink_x_0 + 0 + 0 + + + blocks_multiply_const_vxx_0 + qtgui_time_sink_x_0 + 0 + 0 + + + blocks_multiply_const_vxx_0 + uhd_usrp_sink_0 + 0 + 0 + blocks_stream_to_vector_0 dab_ofdm_mod_0 @@ -1708,13 +2539,7 @@ dab_ofdm_mod_0 - blocks_file_sink_0 - 0 - 0 - - - dab_ofdm_mod_0 - uhd_usrp_sink_0 + blocks_multiply_const_vxx_0 0 0 From 936cf017959e2308dba99335a047ef545bc0b2d1 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 1 Dec 2017 12:21:26 +0100 Subject: [PATCH 096/135] include RTL-SDR source in DABstep --- python/GUI/main.py | 22 ++++++++++++++---- python/GUI/user_frontend.py | 12 ++++++---- python/GUI/user_frontend.ui | 11 +++++++-- python/GUI/usrp_dab_rx.py | 46 ++++++++++++++++++++++++++----------- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index f158d5e3..79e3551b 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -51,6 +51,7 @@ def __init__(self, parent=None): self.need_new_init = True self.file_path = "None" self.src_is_USRP = True + self.src_is_RTL = False self.receiver_running = False self.audio_playing = False self.recording = False @@ -70,6 +71,7 @@ def __init__(self, parent=None): self.snr_timer.timeout.connect(self.snr_update) # change of source by radio buttons self.rbtn_USRP.clicked.connect(self.src2USRP) + self.rbtn_RTL.clicked.connect(self.src2RTL) self.rbtn_File.clicked.connect(self.src2File) # set file path self.btn_file_path.clicked.connect(self.set_file_path) @@ -225,6 +227,16 @@ def src2USRP(self): self.spinbox_frequency.setEnabled(True) self.label_frequency.setEnabled(True) self.src_is_USRP = True + self.src_is_RTL = False + + def src2RTL(self): + # enable/disable buttons + self.btn_file_path.setEnabled(False) + self.label_path.setEnabled(False) + self.spinbox_frequency.setEnabled(True) + self.label_frequency.setEnabled(True) + self.src_is_RTL = True + self.src_is_USRP = False def src2File(self): # enable/disable buttons @@ -233,6 +245,7 @@ def src2File(self): self.spinbox_frequency.setEnabled(False) self.label_frequency.setEnabled(False) self.src_is_USRP = False + self.src_is_RTL = False def set_file_path(self): path = QtGui.QFileDialog.getOpenFileName(self, "Pick a file with recorded IQ samples") @@ -247,13 +260,13 @@ def init_receiver(self): self.snr_timer.stop() self.firecode_timer.stop() # check if file path is selected in case that file is the selected source - if (not self.src_is_USRP) and (self.file_path == "None"): + if (not self.src_is_USRP) and (not self.src_is_RTL) and (self.file_path == "None"): self.label_path.setStyleSheet('color: red') else: self.label_path.setStyleSheet('color: black') # set up and start flowgraph self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path) self.my_receiver.set_volume(0) self.my_receiver.start() # status bar @@ -404,11 +417,12 @@ def play_audio(self): self.snr_timer.stop() self.firecode_timer.stop() self.my_receiver.stop() + self.temp_src = self.my_receiver.src self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path, prev_src=self.temp_src) self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) self.my_receiver.start() self.statusBar.showMessage("Audio playing.") @@ -444,7 +458,7 @@ def adjust_audio_sampling_rate(self): self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path, prev_src=self.temp_src) self.my_receiver.start() elif new_sampling_rate == -1: diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 6166f60e..fa0e081a 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -75,6 +75,9 @@ def setupUi(self, MainWindow): self.rbtn_USRP.setAutoRepeat(False) self.rbtn_USRP.setObjectName(_fromUtf8("rbtn_USRP")) self.horizontalLayout.addWidget(self.rbtn_USRP) + self.rbtn_RTL = QtGui.QRadioButton(self.tab_reception) + self.rbtn_RTL.setObjectName(_fromUtf8("rbtn_RTL")) + self.horizontalLayout.addWidget(self.rbtn_RTL) spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.label_frequency = QtGui.QLabel(self.tab_reception) @@ -215,8 +218,8 @@ def setupUi(self, MainWindow): self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) self.bar_snr = QtGui.QProgressBar(self.tab_reception) self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) - self.bar_snr.setMinimum(0) - self.bar_snr.setMaximum(60) + self.bar_snr.setMinimum(-20) + self.bar_snr.setMaximum(20) self.bar_snr.setProperty("value", 0) self.bar_snr.setFormat(_fromUtf8("")) self.bar_snr.setObjectName(_fromUtf8("bar_snr")) @@ -437,7 +440,7 @@ def setupUi(self, MainWindow): self.dev_scroll_area.setWidgetResizable(True) self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) self.dev_scroll_area_content = QtGui.QWidget() - self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 239, 602)) + self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 143, 602)) self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) @@ -530,7 +533,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -1028, 525, 1514)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 525, 1514)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -1362,6 +1365,7 @@ def retranslateUi(self, MainWindow): self.btn_dev_mode_close.setText(_translate("MainWindow", "Developer Mode", None)) self.btn_dev_mode_open.setText(_translate("MainWindow", "Developer Mode", None)) self.rbtn_USRP.setText(_translate("MainWindow", "USRP", None)) + self.rbtn_RTL.setText(_translate("MainWindow", "RTL-SDR", None)) self.label_frequency.setText(_translate("MainWindow", "Frequency", None)) self.label_4.setText(_translate("MainWindow", "Hz ", None)) self.rbtn_File.setText(_translate("MainWindow", "File", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 3e40ff03..848f8e92 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -114,6 +114,13 @@ + + + + RTL-SDR + + + @@ -954,7 +961,7 @@ 0 0 - 239 + 143 602 @@ -1151,7 +1158,7 @@ 0 - -1028 + 0 525 1514 diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 48a9b8a2..460bae11 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -27,12 +27,13 @@ from gnuradio import audio, digital from gnuradio import qtgui from gnuradio import fft +import osmosdr import dab import time, math class usrp_dab_rx(gr.top_block): - def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, src_path, sink_path = "None"): + def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, audio_bit_rate, dabplus, use_usrp, use_rtl, src_path, sink_path = "None", prev_src=None): gr.top_block.__init__(self) self.dab_mode = dab_mode @@ -40,22 +41,11 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.sample_rate = 2048e3 self.dabplus = dabplus self.use_usrp = use_usrp + self.use_rtl = use_rtl self.src_path = src_path self.sink_path = sink_path gr.log.set_level("warn") - ######################## - # source - ######################## - if self.use_usrp: - self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) - self.src.set_clock_rate(self.sample_rate*20) - self.src.set_samp_rate(self.sample_rate) - self.src.set_antenna("TX/RX") - else: - print "using file source" - self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, False) - # set paramters to default mode self.softbits = True self.filter_input = True @@ -71,6 +61,36 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.resample_fixed, self.verbose, self.correct_ffe, self.equalize_magnitude) + + ######################## + # source + ######################## + if self.use_usrp: + self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) + self.src.set_clock_rate(self.sample_rate*8) + self.src.set_samp_rate(self.sample_rate) + self.src.set_antenna("TX/RX") + + elif self.use_rtl: + if(prev_src is None): + self.src = osmosdr.source() + else: + self.src = prev_src + self.src.set_sample_rate(self.sample_rate) + self.src.set_center_freq(self.frequency, 0) + self.src.set_freq_corr(0, 0) + self.src.set_dc_offset_mode(2, 0) + self.src.set_iq_balance_mode(0, 0) + self.src.set_gain_mode(False, 0) + self.src.set_gain(40, 0) + self.src.set_if_gain(20, 0) + self.src.set_bb_gain(20, 0) + self.src.set_antenna("", 0) + self.src.set_bandwidth(0, 0) + else: + print "using file source" + self.src = blocks.file_source_make(gr.sizeof_gr_complex, self.src_path, False) + ######################## # FFT and waterfall plot ######################## From 10102656c64aa7a8964cc3cf1abc453f3a44e9a6 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 1 Dec 2017 18:14:53 +0100 Subject: [PATCH 097/135] correct fault in snr measurement --- apps/DABstep | 45 ++++++++++++++++--- ...m_coarse_frequency_correction_vcvc_impl.cc | 3 +- python/GUI/main.py | 22 ++++++++- python/GUI/user_frontend.py | 4 +- python/GUI/user_frontend.ui | 4 +- 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index 0e5fbc06..b50d1d85 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -51,6 +51,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.need_new_init = True self.file_path = "None" self.src_is_USRP = True + self.src_is_RTL = False self.receiver_running = False self.audio_playing = False self.recording = False @@ -70,6 +71,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.snr_timer.timeout.connect(self.snr_update) # change of source by radio buttons self.rbtn_USRP.clicked.connect(self.src2USRP) + self.rbtn_RTL.clicked.connect(self.src2RTL) self.rbtn_File.clicked.connect(self.src2File) # set file path self.btn_file_path.clicked.connect(self.set_file_path) @@ -225,6 +227,16 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.spinbox_frequency.setEnabled(True) self.label_frequency.setEnabled(True) self.src_is_USRP = True + self.src_is_RTL = False + + def src2RTL(self): + # enable/disable buttons + self.btn_file_path.setEnabled(False) + self.label_path.setEnabled(False) + self.spinbox_frequency.setEnabled(True) + self.label_frequency.setEnabled(True) + self.src_is_RTL = True + self.src_is_USRP = False def src2File(self): # enable/disable buttons @@ -233,6 +245,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.spinbox_frequency.setEnabled(False) self.label_frequency.setEnabled(False) self.src_is_USRP = False + self.src_is_RTL = False def set_file_path(self): path = QtGui.QFileDialog.getOpenFileName(self, "Pick a file with recorded IQ samples") @@ -247,13 +260,13 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.snr_timer.stop() self.firecode_timer.stop() # check if file path is selected in case that file is the selected source - if (not self.src_is_USRP) and (self.file_path == "None"): + if (not self.src_is_USRP) and (not self.src_is_RTL) and (self.file_path == "None"): self.label_path.setStyleSheet('color: red') else: self.label_path.setStyleSheet('color: black') # set up and start flowgraph self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path) self.my_receiver.set_volume(0) self.my_receiver.start() # status bar @@ -275,6 +288,11 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.receiver_running = True self.btn_init.setText("stop receiver") else: + # stop receiver was pressed + self.dev_mode_close() + # remove service table + while (self.table_mci.rowCount() > 0): + self.table_mci.removeRow(0) self.my_receiver.stop() self.receiver_running = False self.btn_init.setText("start receiver") @@ -287,6 +305,21 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.btn_stop.hide() self.audio_playing = False self.statusBar.showMessage("Receiver stopped.") + self.bar_snr.setValue(0) + # reset variables + self.bit_rate = 8 + self.address = 0 + self.size = 6 + self.protection = 2 + self.audio_bit_rate = 16000 + self.volume = 80 + self.subch = -1 + self.dabplus = True + self.need_new_init = True + self.file_path = "None" + self.receiver_running = False + self.audio_playing = False + self.recording = False def update_service_info(self): # set status bar message @@ -373,7 +406,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def snr_update(self): # display snr in progress bar if an instance of usrp_dab_rx is existing - if hasattr(self, 'my_receiver'): + if hasattr(self, 'my_receiver') and self.receiver_running: SNR = self.my_receiver.get_snr() if SNR > 20.0: self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") @@ -404,11 +437,12 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.snr_timer.stop() self.firecode_timer.stop() self.my_receiver.stop() + self.temp_src = self.my_receiver.src self.my_receiver = usrp_dab_rx.usrp_dab_rx(self.spin_dab_mode.value(), self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path, prev_src=self.temp_src) self.my_receiver.set_volume(float(self.slider_volume.value()) / 100) self.my_receiver.start() self.statusBar.showMessage("Audio playing.") @@ -444,7 +478,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.spinbox_frequency.value(), self.bit_rate, self.address, self.size, self.protection, self.audio_bit_rate, self.dabplus, - self.src_is_USRP, self.file_path) + self.src_is_USRP, self.src_is_RTL, self.file_path, prev_src=self.temp_src) self.my_receiver.start() elif new_sampling_rate == -1: @@ -1073,3 +1107,4 @@ def main(): if __name__ == '__main__': main() + diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index 4536cfad..4234aa6d 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -107,7 +107,6 @@ namespace gr { if (i != d_num_carriers/2) energy+=std::real(symbol[i+d_freq_offset]*conj(symbol[i+d_freq_offset])); } - // measure normalized energy of empty sub-carriers float noise = 0; for (int i=0; i noise){ // now we can calculate the SNR in dB - d_snr = 10*log((energy-noise)/noise); + d_snr = 10*log10((energy-noise)/noise); } } diff --git a/python/GUI/main.py b/python/GUI/main.py index 79e3551b..ce84ba07 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -288,6 +288,11 @@ def init_receiver(self): self.receiver_running = True self.btn_init.setText("stop receiver") else: + # stop receiver was pressed + self.dev_mode_close() + # remove service table + while (self.table_mci.rowCount() > 0): + self.table_mci.removeRow(0) self.my_receiver.stop() self.receiver_running = False self.btn_init.setText("start receiver") @@ -300,6 +305,21 @@ def init_receiver(self): self.btn_stop.hide() self.audio_playing = False self.statusBar.showMessage("Receiver stopped.") + self.bar_snr.setValue(0) + # reset variables + self.bit_rate = 8 + self.address = 0 + self.size = 6 + self.protection = 2 + self.audio_bit_rate = 16000 + self.volume = 80 + self.subch = -1 + self.dabplus = True + self.need_new_init = True + self.file_path = "None" + self.receiver_running = False + self.audio_playing = False + self.recording = False def update_service_info(self): # set status bar message @@ -386,7 +406,7 @@ def selected_subch(self): def snr_update(self): # display snr in progress bar if an instance of usrp_dab_rx is existing - if hasattr(self, 'my_receiver'): + if hasattr(self, 'my_receiver') and self.receiver_running: SNR = self.my_receiver.get_snr() if SNR > 20.0: self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index fa0e081a..a58b9939 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -218,7 +218,7 @@ def setupUi(self, MainWindow): self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) self.bar_snr = QtGui.QProgressBar(self.tab_reception) self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) - self.bar_snr.setMinimum(-20) + self.bar_snr.setMinimum(0) self.bar_snr.setMaximum(20) self.bar_snr.setProperty("value", 0) self.bar_snr.setFormat(_fromUtf8("")) @@ -1383,7 +1383,7 @@ def retranslateUi(self, MainWindow): self.label_ensemble.setText(_translate("MainWindow", "ENSEMBLE", None)) self.label_26.setText(_translate("MainWindow", "services:", None)) self.label_country.setText(_translate("MainWindow", "Country", None)) - self.label_snr.setText(_translate("MainWindow", "reception: ", None)) + self.label_snr.setText(_translate("MainWindow", "SNR:", None)) self.label_7.setText(_translate("MainWindow", "dB", None)) self.label_firecode.setText(_translate("MainWindow", "

Superframes:

", None)) self.led_msc.setText(_translate("MainWindow", "led", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 848f8e92..66591614 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -411,7 +411,7 @@ tfadsf
- -20 + 0 20 @@ -427,7 +427,7 @@ - reception: + SNR: From 67d3fb3fa07012703c0f98620aa182aa10878c00 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 4 Dec 2017 15:30:23 +0100 Subject: [PATCH 098/135] add gain adjustment and fix receiver usrp tune --- apps/DABstep | 12 ++++++ python/GUI/main.py | 12 ++++++ python/GUI/user_frontend.py | 80 +++++++++++++++++++++++++------------ python/GUI/user_frontend.ui | 72 ++++++++++++++++++++++++++++++++- python/GUI/usrp_dab_rx.py | 14 +++---- python/GUI/usrp_dab_tx.py | 12 +++++- 6 files changed, 165 insertions(+), 37 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index b50d1d85..dd9f4b0a 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -86,6 +86,8 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): # adjust audio sampling rate self.timer_audio_sampling_rate = QTimer() self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) + # gain setter + self.gain_spin.valueChanged.connect(self.set_rx_gain) # stop button click stops audio reception self.btn_stop.hide() self.btn_stop.clicked.connect(self.stop_audio) @@ -178,6 +180,8 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.t_btn_stop.pressed.connect(self.t_stop_transmitter) # path for File sink path self.t_btn_file_path.pressed.connect(self.t_set_file_path) + # gain setter + self.tx_gain.valueChanged.connect(self.set_tx_gain) # path selection for all 7 (possible) sub channels self.t_btn_path_src1.pressed.connect(self.t_set_subch_path1) self.t_btn_path_src2.pressed.connect(self.t_set_subch_path2) @@ -986,6 +990,14 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.t_combo_audio_rate_dab7.show() self.t_combo_audio_rate7.hide() + def set_rx_gain(self): + if hasattr(self, 'my_receiver'): + self.my_receiver.set_gain(self.gain_spin.value()) + + def set_tx_gain(self): + if hasattr(self, 'my_transmitter'): + self.my_transmitter.set_gain(self.tx_gain.value()) + class lookup_tables: languages = [ diff --git a/python/GUI/main.py b/python/GUI/main.py index ce84ba07..0cd7b452 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -86,6 +86,8 @@ def __init__(self, parent=None): # adjust audio sampling rate self.timer_audio_sampling_rate = QTimer() self.timer_audio_sampling_rate.timeout.connect(self.adjust_audio_sampling_rate) + # gain setter + self.gain_spin.valueChanged.connect(self.set_rx_gain) # stop button click stops audio reception self.btn_stop.hide() self.btn_stop.clicked.connect(self.stop_audio) @@ -178,6 +180,8 @@ def __init__(self, parent=None): self.t_btn_stop.pressed.connect(self.t_stop_transmitter) # path for File sink path self.t_btn_file_path.pressed.connect(self.t_set_file_path) + # gain setter + self.tx_gain.valueChanged.connect(self.set_tx_gain) # path selection for all 7 (possible) sub channels self.t_btn_path_src1.pressed.connect(self.t_set_subch_path1) self.t_btn_path_src2.pressed.connect(self.t_set_subch_path2) @@ -986,6 +990,14 @@ def change_audio_bit_rates7(self): self.t_combo_audio_rate_dab7.show() self.t_combo_audio_rate7.hide() + def set_rx_gain(self): + if hasattr(self, 'my_receiver'): + self.my_receiver.set_gain(self.gain_spin.value()) + + def set_tx_gain(self): + if hasattr(self, 'my_transmitter'): + self.my_transmitter.set_gain(self.tx_gain.value()) + class lookup_tables: languages = [ diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index a58b9939..58340fd4 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -373,13 +373,26 @@ def setupUi(self, MainWindow): self.btn_update_info.setObjectName(_fromUtf8("btn_update_info")) self.horizontalLayout_26.addWidget(self.btn_update_info) self.verticalLayout_7.addLayout(self.horizontalLayout_26) + self.horizontalLayout_40 = QtGui.QHBoxLayout() + self.horizontalLayout_40.setObjectName(_fromUtf8("horizontalLayout_40")) + self.label_10 = QtGui.QLabel(self.tab_reception) + self.label_10.setObjectName(_fromUtf8("label_10")) + self.horizontalLayout_40.addWidget(self.label_10) + self.gain_spin = QtGui.QSpinBox(self.tab_reception) + self.gain_spin.setMaximum(100) + self.gain_spin.setProperty("value", 50) + self.gain_spin.setObjectName(_fromUtf8("gain_spin")) + self.horizontalLayout_40.addWidget(self.gain_spin) + spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_40.addItem(spacerItem11) + self.verticalLayout_7.addLayout(self.horizontalLayout_40) self.line_9 = QtGui.QFrame(self.tab_reception) self.line_9.setFrameShape(QtGui.QFrame.HLine) self.line_9.setFrameShadow(QtGui.QFrame.Sunken) self.line_9.setObjectName(_fromUtf8("line_9")) self.verticalLayout_7.addWidget(self.line_9) - spacerItem11 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem11) + spacerItem12 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.verticalLayout_7.addItem(spacerItem12) self.label_2 = QtGui.QLabel(self.tab_reception) font = QtGui.QFont() font.setBold(True) @@ -466,14 +479,14 @@ def setupUi(self, MainWindow): self.t_rbtn_USRP.setChecked(True) self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem12) + spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_9.addItem(spacerItem13) self.t_label_frequency = QtGui.QLabel(self.tab_transmission) self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) self.horizontalLayout_9.addWidget(self.t_label_frequency) self.t_spinbox_frequency = QtGui.QSpinBox(self.tab_transmission) self.t_spinbox_frequency.setMaximum(1000000000) - self.t_spinbox_frequency.setProperty("value", 208064000) + self.t_spinbox_frequency.setProperty("value", 201072000) self.t_spinbox_frequency.setObjectName(_fromUtf8("t_spinbox_frequency")) self.horizontalLayout_9.addWidget(self.t_spinbox_frequency) self.label = QtGui.QLabel(self.tab_transmission) @@ -513,8 +526,8 @@ def setupUi(self, MainWindow): self.verticalLayout_5.addLayout(self.horizontalLayout_10) self.horizontalLayout_31 = QtGui.QHBoxLayout() self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem13) + spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_31.addItem(spacerItem14) self.label_8 = QtGui.QLabel(self.tab_transmission) self.label_8.setObjectName(_fromUtf8("label_8")) self.horizontalLayout_31.addWidget(self.label_8) @@ -936,8 +949,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setWidget(39, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) - spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus1.addItem(spacerItem14) + spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus1.addItem(spacerItem15) self.t_combo_dabplus1 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus1.setObjectName(_fromUtf8("t_combo_dabplus1")) self.t_combo_dabplus1.addItem(_fromUtf8("")) @@ -946,8 +959,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(2, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus1) self.t_layout_combo_dabplus2 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus2.setObjectName(_fromUtf8("t_layout_combo_dabplus2")) - spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus2.addItem(spacerItem15) + spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus2.addItem(spacerItem16) self.t_combo_dabplus2 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus2.setObjectName(_fromUtf8("t_combo_dabplus2")) self.t_combo_dabplus2.addItem(_fromUtf8("")) @@ -956,8 +969,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(8, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) - spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus3.addItem(spacerItem16) + spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus3.addItem(spacerItem17) self.t_combo_dabplus3 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus3.setObjectName(_fromUtf8("t_combo_dabplus3")) self.t_combo_dabplus3.addItem(_fromUtf8("")) @@ -966,8 +979,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(14, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) - spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus4.addItem(spacerItem17) + spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus4.addItem(spacerItem18) self.t_combo_dabplus4 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus4.setObjectName(_fromUtf8("t_combo_dabplus4")) self.t_combo_dabplus4.addItem(_fromUtf8("")) @@ -976,8 +989,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(20, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) - spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus5.addItem(spacerItem18) + spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus5.addItem(spacerItem19) self.t_combo_dabplus5 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus5.setObjectName(_fromUtf8("t_combo_dabplus5")) self.t_combo_dabplus5.addItem(_fromUtf8("")) @@ -986,8 +999,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(26, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) - spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus6.addItem(spacerItem19) + spacerItem20 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus6.addItem(spacerItem20) self.t_combo_dabplus6 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus6.setObjectName(_fromUtf8("t_combo_dabplus6")) self.t_combo_dabplus6.addItem(_fromUtf8("")) @@ -996,8 +1009,8 @@ def setupUi(self, MainWindow): self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) - spacerItem20 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus7.addItem(spacerItem20) + spacerItem21 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.t_layout_combo_dabplus7.addItem(spacerItem21) self.t_combo_dabplus7 = QtGui.QComboBox(self.scrollAreaWidgetContents) self.t_combo_dabplus7.setObjectName(_fromUtf8("t_combo_dabplus7")) self.t_combo_dabplus7.addItem(_fromUtf8("")) @@ -1272,8 +1285,8 @@ def setupUi(self, MainWindow): self.t_combo_language = QtGui.QComboBox(self.tab_transmission) self.t_combo_language.setObjectName(_fromUtf8("t_combo_language")) self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_combo_language) - spacerItem21 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(6, QtGui.QFormLayout.FieldRole, spacerItem21) + spacerItem22 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.formLayout_2.setItem(6, QtGui.QFormLayout.FieldRole, spacerItem22) self.verticalLayout_8.addLayout(self.formLayout_2) self.horizontalLayout_22 = QtGui.QHBoxLayout() self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) @@ -1288,9 +1301,22 @@ def setupUi(self, MainWindow): self.t_label_status = QtGui.QLabel(self.tab_transmission) self.t_label_status.setObjectName(_fromUtf8("t_label_status")) self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem22 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem22) + spacerItem23 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_22.addItem(spacerItem23) self.verticalLayout_8.addLayout(self.horizontalLayout_22) + self.horizontalLayout_39 = QtGui.QHBoxLayout() + self.horizontalLayout_39.setObjectName(_fromUtf8("horizontalLayout_39")) + self.label_9 = QtGui.QLabel(self.tab_transmission) + self.label_9.setObjectName(_fromUtf8("label_9")) + self.horizontalLayout_39.addWidget(self.label_9) + self.tx_gain = QtGui.QSpinBox(self.tab_transmission) + self.tx_gain.setMaximum(80) + self.tx_gain.setProperty("value", 30) + self.tx_gain.setObjectName(_fromUtf8("tx_gain")) + self.horizontalLayout_39.addWidget(self.tx_gain) + spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_39.addItem(spacerItem24) + self.verticalLayout_8.addLayout(self.horizontalLayout_39) self.line_10 = QtGui.QFrame(self.tab_transmission) self.line_10.setFrameShape(QtGui.QFrame.HLine) self.line_10.setFrameShadow(QtGui.QFrame.Sunken) @@ -1355,7 +1381,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) + self.mode_tabs.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): @@ -1399,6 +1425,7 @@ def retranslateUi(self, MainWindow): self.label_dabplus.setText(_translate("MainWindow", "DAB", None)) self.btn_init.setText(_translate("MainWindow", "start receiver", None)) self.btn_update_info.setText(_translate("MainWindow", "scan ensemble", None)) + self.label_10.setText(_translate("MainWindow", "Gain", None)) self.label_2.setText(_translate("MainWindow", "Audio Player", None)) self.btn_play.setText(_translate("MainWindow", " Play", None)) self.btn_stop.setText(_translate("MainWindow", " Stop", None)) @@ -1564,6 +1591,7 @@ def retranslateUi(self, MainWindow): self.t_btn_init.setText(_translate("MainWindow", "start transmitter", None)) self.label_22.setText(_translate("MainWindow", "Status:", None)) self.t_label_status.setText(_translate("MainWindow", "not running", None)) + self.label_9.setText(_translate("MainWindow", "Gain", None)) self.label_20.setText(_translate("MainWindow", "Audio Player", None)) self.label_18.setText(_translate("MainWindow", "Listen to component", None)) self.t_btn_play.setText(_translate("MainWindow", " Play", None)) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index 66591614..e2ed137f 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -85,7 +85,7 @@ true - 0 + 1 @@ -806,6 +806,40 @@
+ + + + + + Gain + + + + + + + 100 + + + 50 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -1027,7 +1061,7 @@ 1000000000 - 208064000 + 201072000 @@ -2928,6 +2962,40 @@
+ + + + + + Gain + + + + + + + 80 + + + 30 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 460bae11..5a354565 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -77,12 +77,12 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud else: self.src = prev_src self.src.set_sample_rate(self.sample_rate) - self.src.set_center_freq(self.frequency, 0) + self.src.set_center_freq(uhd.tune_request(self.frequency, 2*self.sample_rate)) self.src.set_freq_corr(0, 0) self.src.set_dc_offset_mode(2, 0) self.src.set_iq_balance_mode(0, 0) self.src.set_gain_mode(False, 0) - self.src.set_gain(40, 0) + self.src.set_gain(50, 0) self.src.set_if_gain(20, 0) self.src.set_bb_gain(20, 0) self.src.set_antenna("", 0) @@ -166,11 +166,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud # tune USRP frequency if self.use_usrp: self.set_freq(self.frequency) - # set gain - # if no gain was specified, use the mid-point in dB - g = self.src.get_gain_range() - self.rx_gain = float(g.start() + g.stop()) / 2 - self.src.set_gain(self.rx_gain) + ######################## # getter methods @@ -228,6 +224,10 @@ def set_freq(self, freq): print "-> error - cannot tune to " + str(freq) + " Hz" return False + def set_gain(self, gain): + if hasattr(self, 'src'): + self.src.set_gain(gain, 0) + def receive(self): rx = usrp_dab_rx() rx.run() diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 4a2fa1f4..3a899048 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -107,9 +107,14 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label ######################## if self.use_usrp: self.sink = uhd.usrp_sink("", uhd.io_type.COMPLEX_FLOAT32, 1) + self.sink.set_clock_rate(self.sample_rate * 8) self.sink.set_samp_rate(self.sample_rate) + self.sink.set_clock_source("gpsdo", 0) + self.sink.set_time_source("gpsdo", 0) self.sink.set_antenna("TX/RX") - self.sink.set_center_freq(self.frequency) + self.sink.set_gain(30, 0) + self.sink.set_center_freq(uhd.tune_request(self.frequency, 2*self.sample_rate)) + self.multiply = blocks.multiply_const_cc_make(0.3) else: self.sink = blocks.file_sink_make(gr.sizeof_gr_complex, self.sink_path) # audio sink @@ -147,7 +152,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.connect((self.mux, 0), self.s2v_mod, (self.mod, 0)) self.connect(self.trigsrc, (self.mod, 1)) if use_usrp: - self.connect(self.mod, self.sink) + self.connect(self.mod, self.multiply, self.sink) else: self.connect(self.mod, blocks.throttle_make(gr.sizeof_gr_complex, 2e6), self.sink) #self.connect((self.msc_sources[self.selected_audio-1], 0), self.gain_left, (self.audio, 0)) @@ -161,3 +166,6 @@ def set_volume(self, volume): self.gain_left.set_k(volume) self.gain_right.set_k(volume) + def set_gain(self, gain): + if hasattr(self, 'sink'): + self.sink.set_gain(gain, 0) From e74444e955614e5884f1a2c3938edc35b9837cda Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 4 Dec 2017 15:48:15 +0100 Subject: [PATCH 099/135] improve GUI --- python/GUI/user_frontend.py | 8 ++++---- python/GUI/user_frontend.ui | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 58340fd4..32411749 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -25,7 +25,7 @@ def _translate(context, text, disambig): class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(1146, 739) + MainWindow.resize(1203, 739) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setEnabled(True) self.centralwidget.setObjectName(_fromUtf8("centralwidget")) @@ -453,7 +453,7 @@ def setupUi(self, MainWindow): self.dev_scroll_area.setWidgetResizable(True) self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) self.dev_scroll_area_content = QtGui.QWidget() - self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 143, 602)) + self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 200, 602)) self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) @@ -546,7 +546,7 @@ def setupUi(self, MainWindow): self.scrollArea.setWidgetResizable(True) self.scrollArea.setObjectName(_fromUtf8("scrollArea")) self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 525, 1514)) + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 553, 1514)) self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) @@ -1381,7 +1381,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(1) + self.mode_tabs.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index e2ed137f..d2e59c5e 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -6,7 +6,7 @@ 0 0 - 1146 + 1203 739 @@ -85,7 +85,7 @@ true - 1 + 0 @@ -995,7 +995,7 @@ 0 0 - 143 + 200 602 @@ -1193,7 +1193,7 @@ 0 0 - 525 + 553 1514 From 63205ec9b8bb33aee94c174151c9a3d9b3563c50 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 4 Dec 2017 16:26:30 +0100 Subject: [PATCH 100/135] improve snr display bar --- apps/DABstep | 17 +++++++++-------- python/GUI/main.py | 17 +++++++++-------- python/GUI/user_frontend.py | 2 +- python/GUI/user_frontend.ui | 2 +- python/GUI/usrp_dab_rx.py | 5 +++-- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index dd9f4b0a..3eb33704 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -412,18 +412,19 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): # display snr in progress bar if an instance of usrp_dab_rx is existing if hasattr(self, 'my_receiver') and self.receiver_running: SNR = self.my_receiver.get_snr() - if SNR > 20.0: + if SNR > 15.0: self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") - if SNR > 60.0: - SNR = 60 - elif 10 < SNR <= 15: + elif SNR > 10.0: self.setStyleSheet("""QProgressBar::chunk { background: "yellow"; }""") - else: + elif SNR <= 10.0: self.setStyleSheet("""QProgressBar::chunk { background: "red"; }""") - if SNR < 0 or math.isnan(SNR): - SNR = 0 - self.bar_snr.setValue(int(SNR)) self.lcd_snr.display(SNR) + if SNR > 40: + SNR = 20 + elif SNR < 0: + SNR = 0 + self.bar_snr.setValue(int(SNR)) + else: self.bar_snr.setValue(0) self.label_snr.setText("SNR: no reception") diff --git a/python/GUI/main.py b/python/GUI/main.py index 0cd7b452..3451d64c 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -412,18 +412,19 @@ def snr_update(self): # display snr in progress bar if an instance of usrp_dab_rx is existing if hasattr(self, 'my_receiver') and self.receiver_running: SNR = self.my_receiver.get_snr() - if SNR > 20.0: + if SNR > 15.0: self.setStyleSheet("""QProgressBar::chunk { background: "green"; }""") - if SNR > 60.0: - SNR = 60 - elif 10 < SNR <= 15: + elif SNR > 10.0: self.setStyleSheet("""QProgressBar::chunk { background: "yellow"; }""") - else: + elif SNR <= 10.0: self.setStyleSheet("""QProgressBar::chunk { background: "red"; }""") - if SNR < 0 or math.isnan(SNR): - SNR = 0 - self.bar_snr.setValue(int(SNR)) self.lcd_snr.display(SNR) + if SNR > 40: + SNR = 20 + elif SNR < 0: + SNR = 0 + self.bar_snr.setValue(int(SNR)) + else: self.bar_snr.setValue(0) self.label_snr.setText("SNR: no reception") diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py index 32411749..77050152 100644 --- a/python/GUI/user_frontend.py +++ b/python/GUI/user_frontend.py @@ -219,7 +219,7 @@ def setupUi(self, MainWindow): self.bar_snr = QtGui.QProgressBar(self.tab_reception) self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) self.bar_snr.setMinimum(0) - self.bar_snr.setMaximum(20) + self.bar_snr.setMaximum(40) self.bar_snr.setProperty("value", 0) self.bar_snr.setFormat(_fromUtf8("")) self.bar_snr.setObjectName(_fromUtf8("bar_snr")) diff --git a/python/GUI/user_frontend.ui b/python/GUI/user_frontend.ui index d2e59c5e..a0b78bac 100644 --- a/python/GUI/user_frontend.ui +++ b/python/GUI/user_frontend.ui @@ -414,7 +414,7 @@ 0 - 20 + 40 0 diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 5a354565..9494f53f 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -69,6 +69,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.src = uhd.usrp_source("", uhd.io_type.COMPLEX_FLOAT32, 1) self.src.set_clock_rate(self.sample_rate*8) self.src.set_samp_rate(self.sample_rate) + self.src.set_gain(50, 0) self.src.set_antenna("TX/RX") elif self.use_rtl: @@ -82,7 +83,7 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.src.set_dc_offset_mode(2, 0) self.src.set_iq_balance_mode(0, 0) self.src.set_gain_mode(False, 0) - self.src.set_gain(50, 0) + self.src.set_gain(20, 0) self.src.set_if_gain(20, 0) self.src.set_bb_gain(20, 0) self.src.set_antenna("", 0) @@ -225,7 +226,7 @@ def set_freq(self, freq): return False def set_gain(self, gain): - if hasattr(self, 'src'): + if hasattr(self, 'src') and self.use_usrp: self.src.set_gain(gain, 0) def receive(self): From ad93669d4834c6df4cfc038b38847c4f3444dece Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 4 Dec 2017 16:47:41 +0100 Subject: [PATCH 101/135] fix bug with transmitter button toggle --- apps/DABstep | 153 ++++++++++++++++++++++++--------------------- python/GUI/main.py | 153 ++++++++++++++++++++++++--------------------- 2 files changed, 160 insertions(+), 146 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index 3eb33704..3993d9a6 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -206,6 +206,7 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): self.t_combo_dabplus7.currentIndexChanged.connect(self.change_audio_bit_rates7) # set volume if volume slider is changed self.t_slider_volume.valueChanged.connect(self.t_set_volume) + self.transmitter_running = False ################################ # general functions @@ -742,81 +743,87 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): component["combo_audio_rate"].hide() def t_init_transmitter(self): - self.statusBar.showMessage("initializing transmitter...") - # boolean is set to True if info is missing to init the transmitter - arguments_incomplete = False - # produce array for protection and data_rate and src_paths and stereo flags - num_subch = self.t_spin_num_subch.value() - protection_array = [None] * num_subch - data_rate_n_array = [None] * num_subch - audio_sampling_rate_array = [None] * num_subch - audio_paths = [None] * num_subch - stereo_flags = [None] * num_subch - merged_service_string = "" - dabplus_types = [True] * num_subch - record_states = [False] * num_subch - for i in range(0, num_subch): - # write array with protection modes - protection_array[i] = self.components[i]["protection"].currentIndex() - # write array with data rates - data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 - # write stereo flags - stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() - # write audio sampling rates in array - if self.components[i]["combo_dabplus"].currentIndex() is 0: - audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 - else: - audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 - # check audio paths - if self.components[i]["src_path"] is "None": - # highlight the path which is not selected - self.components[i]["src_path_disp"].setStyleSheet('color: red') - arguments_incomplete = True - self.statusBar.showMessage("path " + str(i+1) + " not selected") - # check if length of label is <= 16 chars - elif len(str(self.components[i]["edit_label"].text())) > 16: - self.components[i]["edit_label"].setStyleSheet('color: red') + if self.transmitter_running: + self.transmitter_running = False + self.t_btn_init.setText("start transmitter") + else: + self.transmitter_running = True + self.t_btn_init.setText("stop transmitter") + self.statusBar.showMessage("initializing transmitter...") + # boolean is set to True if info is missing to init the transmitter + arguments_incomplete = False + # produce array for protection and data_rate and src_paths and stereo flags + num_subch = self.t_spin_num_subch.value() + protection_array = [None] * num_subch + data_rate_n_array = [None] * num_subch + audio_sampling_rate_array = [None] * num_subch + audio_paths = [None] * num_subch + stereo_flags = [None] * num_subch + merged_service_string = "" + dabplus_types = [True] * num_subch + record_states = [False] * num_subch + for i in range(0, num_subch): + # write array with protection modes + protection_array[i] = self.components[i]["protection"].currentIndex() + # write array with data rates + data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # write stereo flags + stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() + # write audio sampling rates in array + if self.components[i]["combo_dabplus"].currentIndex() is 0: + audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 + else: + audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 + # check audio paths + if self.components[i]["src_path"] is "None": + # highlight the path which is not selected + self.components[i]["src_path_disp"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("path " + str(i+1) + " not selected") + # check if length of label is <= 16 chars + elif len(str(self.components[i]["edit_label"].text())) > 16: + self.components[i]["edit_label"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("Warning: Label is longer than 16 characters!") + else: + audio_paths[i] = self.components[i]["src_path"] + # write service labels appended in one string + merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) + self.components[i]["edit_label"].setStyleSheet('color: black') + # write dabplus types + dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) + + # check if length of ensemble label is <= 16 chars + if len(str(self.t_edit_ensemble_label.text())) > 16: + self.t_edit_ensemble_label.setStyleSheet('color: red') arguments_incomplete = True - self.statusBar.showMessage("Warning: Label is longer than 16 characters!") else: - audio_paths[i] = self.components[i]["src_path"] - # write service labels appended in one string - merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) - self.components[i]["edit_label"].setStyleSheet('color: black') - # write dabplus types - dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) - - # check if length of ensemble label is <= 16 chars - if len(str(self.t_edit_ensemble_label.text())) > 16: - self.t_edit_ensemble_label.setStyleSheet('color: red') - arguments_incomplete = True - else: - self.t_edit_ensemble_label.setStyleSheet('color: black') - # check if File path for sink is chosen if option enabled - if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): - self.t_label_sink.setStyleSheet('color: red') - arguments_incomplete = True - - if arguments_incomplete is False: - # init transmitter - self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), - self.t_spinbox_frequency.value(), - self.t_spin_num_subch.value(), - str(self.t_edit_ensemble_label.text()), - merged_service_string, - self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), - protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, - audio_paths, - self.t_spin_listen_to_component.value(), - self.t_rbtn_USRP.isChecked(), - dabplus_types, - str(self.t_label_sink.text()) + "/" + str( - self.t_edit_file_name.text())) - - # enable play button - self.t_btn_play.setEnabled(True) - self.t_label_status.setText("ready to transmit") - self.statusBar.showMessage("ready to transmit") + self.t_edit_ensemble_label.setStyleSheet('color: black') + # check if File path for sink is chosen if option enabled + if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): + self.t_label_sink.setStyleSheet('color: red') + arguments_incomplete = True + + if arguments_incomplete is False: + # init transmitter + self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), + self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + merged_service_string, + self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), + protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + dabplus_types, + str(self.t_label_sink.text()) + "/" + str( + self.t_edit_file_name.text())) + + # enable play button + self.t_btn_play.setEnabled(True) + self.t_label_status.setText("ready to transmit") + self.statusBar.showMessage("ready to transmit") def t_run_transmitter(self): self.t_btn_stop.setEnabled(True) diff --git a/python/GUI/main.py b/python/GUI/main.py index 3451d64c..e250deff 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -206,6 +206,7 @@ def __init__(self, parent=None): self.t_combo_dabplus7.currentIndexChanged.connect(self.change_audio_bit_rates7) # set volume if volume slider is changed self.t_slider_volume.valueChanged.connect(self.t_set_volume) + self.transmitter_running = False ################################ # general functions @@ -742,81 +743,87 @@ def t_update_service_components(self): component["combo_audio_rate"].hide() def t_init_transmitter(self): - self.statusBar.showMessage("initializing transmitter...") - # boolean is set to True if info is missing to init the transmitter - arguments_incomplete = False - # produce array for protection and data_rate and src_paths and stereo flags - num_subch = self.t_spin_num_subch.value() - protection_array = [None] * num_subch - data_rate_n_array = [None] * num_subch - audio_sampling_rate_array = [None] * num_subch - audio_paths = [None] * num_subch - stereo_flags = [None] * num_subch - merged_service_string = "" - dabplus_types = [True] * num_subch - record_states = [False] * num_subch - for i in range(0, num_subch): - # write array with protection modes - protection_array[i] = self.components[i]["protection"].currentIndex() - # write array with data rates - data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 - # write stereo flags - stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() - # write audio sampling rates in array - if self.components[i]["combo_dabplus"].currentIndex() is 0: - audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 - else: - audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 - # check audio paths - if self.components[i]["src_path"] is "None": - # highlight the path which is not selected - self.components[i]["src_path_disp"].setStyleSheet('color: red') - arguments_incomplete = True - self.statusBar.showMessage("path " + str(i+1) + " not selected") - # check if length of label is <= 16 chars - elif len(str(self.components[i]["edit_label"].text())) > 16: - self.components[i]["edit_label"].setStyleSheet('color: red') + if self.transmitter_running: + self.transmitter_running = False + self.t_btn_init.setText("start transmitter") + else: + self.transmitter_running = True + self.t_btn_init.setText("stop transmitter") + self.statusBar.showMessage("initializing transmitter...") + # boolean is set to True if info is missing to init the transmitter + arguments_incomplete = False + # produce array for protection and data_rate and src_paths and stereo flags + num_subch = self.t_spin_num_subch.value() + protection_array = [None] * num_subch + data_rate_n_array = [None] * num_subch + audio_sampling_rate_array = [None] * num_subch + audio_paths = [None] * num_subch + stereo_flags = [None] * num_subch + merged_service_string = "" + dabplus_types = [True] * num_subch + record_states = [False] * num_subch + for i in range(0, num_subch): + # write array with protection modes + protection_array[i] = self.components[i]["protection"].currentIndex() + # write array with data rates + data_rate_n_array[i] = self.components[i]["data_rate"].value()/8 + # write stereo flags + stereo_flags[i] = self.components[i]["combo_stereo"].currentIndex() + # write audio sampling rates in array + if self.components[i]["combo_dabplus"].currentIndex() is 0: + audio_sampling_rate_array[i] = 32000 if (self.components[i]["combo_audio_rate"].currentIndex() is 0) else 48000 + else: + audio_sampling_rate_array[i] = 48000 if (self.components[i]["combo_audio_rate_dab"].currentIndex() is 0) else 24000 + # check audio paths + if self.components[i]["src_path"] is "None": + # highlight the path which is not selected + self.components[i]["src_path_disp"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("path " + str(i+1) + " not selected") + # check if length of label is <= 16 chars + elif len(str(self.components[i]["edit_label"].text())) > 16: + self.components[i]["edit_label"].setStyleSheet('color: red') + arguments_incomplete = True + self.statusBar.showMessage("Warning: Label is longer than 16 characters!") + else: + audio_paths[i] = self.components[i]["src_path"] + # write service labels appended in one string + merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) + self.components[i]["edit_label"].setStyleSheet('color: black') + # write dabplus types + dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) + + # check if length of ensemble label is <= 16 chars + if len(str(self.t_edit_ensemble_label.text())) > 16: + self.t_edit_ensemble_label.setStyleSheet('color: red') arguments_incomplete = True - self.statusBar.showMessage("Warning: Label is longer than 16 characters!") else: - audio_paths[i] = self.components[i]["src_path"] - # write service labels appended in one string - merged_service_string = merged_service_string + str(self.components[i]["edit_label"].text()).ljust(16) - self.components[i]["edit_label"].setStyleSheet('color: black') - # write dabplus types - dabplus_types[i] = (1 if self.components[i]["combo_dabplus"].currentIndex() is 0 else 0) - - # check if length of ensemble label is <= 16 chars - if len(str(self.t_edit_ensemble_label.text())) > 16: - self.t_edit_ensemble_label.setStyleSheet('color: red') - arguments_incomplete = True - else: - self.t_edit_ensemble_label.setStyleSheet('color: black') - # check if File path for sink is chosen if option enabled - if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): - self.t_label_sink.setStyleSheet('color: red') - arguments_incomplete = True - - if arguments_incomplete is False: - # init transmitter - self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), - self.t_spinbox_frequency.value(), - self.t_spin_num_subch.value(), - str(self.t_edit_ensemble_label.text()), - merged_service_string, - self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), - protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, - audio_paths, - self.t_spin_listen_to_component.value(), - self.t_rbtn_USRP.isChecked(), - dabplus_types, - str(self.t_label_sink.text()) + "/" + str( - self.t_edit_file_name.text())) - - # enable play button - self.t_btn_play.setEnabled(True) - self.t_label_status.setText("ready to transmit") - self.statusBar.showMessage("ready to transmit") + self.t_edit_ensemble_label.setStyleSheet('color: black') + # check if File path for sink is chosen if option enabled + if self.t_rbtn_File.isChecked() and (str(self.t_label_sink.text()) == "select path"): + self.t_label_sink.setStyleSheet('color: red') + arguments_incomplete = True + + if arguments_incomplete is False: + # init transmitter + self.my_transmitter = usrp_dab_tx.usrp_dab_tx(self.t_spin_dab_mode.value(), + self.t_spinbox_frequency.value(), + self.t_spin_num_subch.value(), + str(self.t_edit_ensemble_label.text()), + merged_service_string, + self.t_combo_language.currentIndex(), self.t_combo_country.currentIndex(), + protection_array, data_rate_n_array, stereo_flags, audio_sampling_rate_array, + audio_paths, + self.t_spin_listen_to_component.value(), + self.t_rbtn_USRP.isChecked(), + dabplus_types, + str(self.t_label_sink.text()) + "/" + str( + self.t_edit_file_name.text())) + + # enable play button + self.t_btn_play.setEnabled(True) + self.t_label_status.setText("ready to transmit") + self.statusBar.showMessage("ready to transmit") def t_run_transmitter(self): self.t_btn_stop.setEnabled(True) From 3be2915a87805934f828b85b795dd6088d2aeac3 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Mon, 4 Dec 2017 17:26:33 +0100 Subject: [PATCH 102/135] add gain adjustment to rtl-sdr source --- python/GUI/usrp_dab_rx.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 9494f53f..81b971e6 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -78,12 +78,12 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud else: self.src = prev_src self.src.set_sample_rate(self.sample_rate) - self.src.set_center_freq(uhd.tune_request(self.frequency, 2*self.sample_rate)) + self.src.set_center_freq(self.frequency) self.src.set_freq_corr(0, 0) self.src.set_dc_offset_mode(2, 0) self.src.set_iq_balance_mode(0, 0) self.src.set_gain_mode(False, 0) - self.src.set_gain(20, 0) + self.src.set_gain(50, 0) self.src.set_if_gain(20, 0) self.src.set_bb_gain(20, 0) self.src.set_antenna("", 0) @@ -226,7 +226,7 @@ def set_freq(self, freq): return False def set_gain(self, gain): - if hasattr(self, 'src') and self.use_usrp: + if hasattr(self, 'src'): self.src.set_gain(gain, 0) def receive(self): From 4aaa2686f5183664b6f4042ff96ab1480a2229b1 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 5 Dec 2017 12:02:34 +0100 Subject: [PATCH 103/135] avoid audio underruns by adding a delay block --- python/GUI/usrp_dab_rx.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/python/GUI/usrp_dab_rx.py b/python/GUI/usrp_dab_rx.py index 81b971e6..9f763d2f 100644 --- a/python/GUI/usrp_dab_rx.py +++ b/python/GUI/usrp_dab_rx.py @@ -135,6 +135,8 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud ######################## self.valve_left = dab.valve_ff_make(True) self.valve_right= dab.valve_ff_make(True) + self.delay_left = blocks.delay_make(gr.sizeof_float, int(audio_bit_rate)) + self.delay_right = blocks.delay_make(gr.sizeof_float, int(audio_bit_rate)) self.audio = audio.sink_make(audio_bit_rate) self.wav_sink = blocks.wavfile_sink_make("dab_audio.wav", 2, audio_bit_rate) @@ -154,13 +156,13 @@ def __init__(self, dab_mode, frequency, bit_rate, address, size, protection, aud self.connect((self.demod, 0), self.v2s_snr, self.constellation_plot) # connect audio to sound card and file sink if self.dabplus: - self.connect((self.dabplus, 0), (self.audio, 0)) - self.connect((self.dabplus, 1), (self.audio, 1)) + self.connect((self.dabplus, 0), self.delay_left, (self.audio, 0)) + self.connect((self.dabplus, 1), self.delay_right, (self.audio, 1)) self.connect((self.dabplus, 0), self.valve_left, (self.wav_sink, 0)) self.connect((self.dabplus, 1), self.valve_right, (self.wav_sink, 1)) else: - self.connect(self.gain_left, (self.audio, 0)) - self.connect(self.gain_right, (self.audio, 1)) + self.connect(self.gain_left, self.delay_left, (self.audio, 0)) + self.connect(self.gain_right, self.delay_right, (self.audio, 1)) self.connect(self.gain_left, self.valve_left, (self.wav_sink, 0)) self.connect(self.gain_right, self.valve_right, (self.wav_sink, 1)) From 400ea4f611006fd1d2052ef1e09036b02a1a8613 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Tue, 5 Dec 2017 12:12:19 +0100 Subject: [PATCH 104/135] add gain setter for transmitter --- python/GUI/usrp_dab_tx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/GUI/usrp_dab_tx.py b/python/GUI/usrp_dab_tx.py index 3a899048..dd37c3aa 100644 --- a/python/GUI/usrp_dab_tx.py +++ b/python/GUI/usrp_dab_tx.py @@ -112,7 +112,7 @@ def __init__(self, dab_mode, frequency, num_subch, ensemble_label, service_label self.sink.set_clock_source("gpsdo", 0) self.sink.set_time_source("gpsdo", 0) self.sink.set_antenna("TX/RX") - self.sink.set_gain(30, 0) + self.sink.set_gain(50, 0) self.sink.set_center_freq(uhd.tune_request(self.frequency, 2*self.sample_rate)) self.multiply = blocks.multiply_const_cc_make(0.3) else: From 58df92a746d2c57e9ac756ff1111ffbb6328c303 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 18 Dec 2017 15:36:37 +0100 Subject: [PATCH 105/135] improve labels --- python/GUI/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/GUI/main.py b/python/GUI/main.py index e250deff..1adcc8d6 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -428,7 +428,7 @@ def snr_update(self): else: self.bar_snr.setValue(0) - self.label_snr.setText("SNR: no reception") + #self.label_snr.setText("SNR: no reception") self.snr_timer.start(1000) def play_audio(self): From 945e275e4b46bf6eae127cfc9d0a2c21101c84e7 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 18 Dec 2017 15:48:33 +0100 Subject: [PATCH 106/135] improve example flowgraphs --- examples/dab_receiver.grc | 4 ++-- examples/dab_transmitter.grc | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/dab_receiver.grc b/examples/dab_receiver.grc index 743bc2f0..93cb2187 100644 --- a/examples/dab_receiver.grc +++ b/examples/dab_receiver.grc @@ -277,7 +277,7 @@ file - /home/luca/Desktop/loopback/171130_rec.dat + _coordinate @@ -529,7 +529,7 @@ 3. Read fib_sink info in the console to get the DAB Decoder info 4. Set the DAB+ Decoder info and restart flowgraph -5. Execute "DABstep" out of your terminal for a user-friendly graphical application +Execute "DABstep" out of your terminal for a more user-friendly graphical application _enabled diff --git a/examples/dab_transmitter.grc b/examples/dab_transmitter.grc index 4794ee70..192720a6 100644 --- a/examples/dab_transmitter.grc +++ b/examples/dab_transmitter.grc @@ -97,7 +97,7 @@ _coordinate - (670, 12) + (928, 17) gui_hint @@ -160,7 +160,7 @@ _coordinate - (934, 11) + (1184, 30) gui_hint @@ -199,7 +199,7 @@ _coordinate - (807, 11) + (1064, 17) gui_hint @@ -922,7 +922,7 @@ 3. Add more sub channels (optional) 4. Write Service Info and Multiplex Info in FIB source -5. Execute "DABstep" out of your terminal for a user-friendly graphical application +Execute "DABstep" out of your terminal for a more user-friendly graphical application _enabled From 1e157c5de3f76460a60d4be0f48ccb7918af6de7 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 18 Dec 2017 16:52:10 +0100 Subject: [PATCH 107/135] update README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7d04c67e..8c889396 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ Features * Receiving and Transmitting DAB/DAB+ broadcasts with the graphical application "DABstep" * Receiving or Transmitting DAB/DAB+ with prepaired GNU Radio Companion flowgraph in examples/ * Receiving or Transmitting DAB/DAB+ by building your own GNU Radio flowgraph with provided gr-dab blocks +* USRP and RTl-SDR for reception supported Usage ------- @@ -129,10 +130,12 @@ Ideas * FM simulation, calculating the audio noise out of the SNR and adding it to the audio * parallel FM receiver that fills in the audio in case a superframe is broken +* include reception and transmission of data channels with packed data, e.g. pictures Known Bugs ---------- +* Audio underruns disturb played audio signal without having actual errors. Additional buffer through delay block is a temporary fix that only works until reception errors occur. Documentation -------------- From 5399fbedf91697b8503c31e614546ac406cfc260 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 5 Jan 2018 15:47:49 +0100 Subject: [PATCH 108/135] wrap up qa tests --- README.md | 2 +- grc/CMakeLists.txt | 12 +- grc/dab_ofdm_sync_dab.xml | 38 ---- grc/dab_ofdm_sync_dab2.xml | 30 ---- grc/dab_qpsk_demapper_vcb.xml | 38 ---- grc/dab_select_vectors.xml | 38 ---- include/dab/CMakeLists.txt | 2 - include/dab/qpsk_demapper_vcb.h | 56 ------ include/dab/select_vectors.h | 56 ------ lib/CMakeLists.txt | 2 - lib/qpsk_demapper_vcb_impl.cc | 88 ---------- lib/qpsk_demapper_vcb_impl.h | 45 ----- lib/select_vectors_impl.cc | 113 ------------ lib/select_vectors_impl.h | 68 -------- python/CMakeLists.txt | 71 ++++---- python/__init__.py | 4 +- python/fic_decode_vc.py | 2 +- python/{ofdm.py => ofdm_mod_bc.py} | 0 python/ofdm_sync_dab.py | 117 ------------- python/ofdm_sync_dab2.py | 109 ------------ .../qa/qa_complex_to_interleaved_float_vcf.py | 57 +++--- python/qa/qa_concatenate_signals.py | 84 --------- python/{ => qa}/qa_conv_encoder_bb.py | 9 +- .../qa_correct_individual_phase_offset_vff.py | 53 ------ python/{ => qa}/qa_crc16_bb.py | 6 + .../qa_dab_transmission_frame_mux_bb.py | 0 .../{ => qa}/qa_dabplus_audio_decoder_ff.py | 0 python/qa/qa_diff_phasor_vcc.py | 86 ++++----- python/{ => qa}/qa_energy_disp.py | 0 python/{ => qa}/qa_fib_sink_vb.py | 9 +- python/{ => qa}/qa_fib_source_b.py | 0 python/{ => qa}/qa_fic_encode.py | 7 +- python/qa/qa_frequency_interleaver_vcc.py | 37 ++++ python/qa/qa_frequency_interleaving.py | 38 ---- python/qa/qa_insert_null_symbol.py | 65 +++---- python/{ => qa}/qa_mp2_decode_bs.py | 0 python/{ => qa}/qa_mp2_encode_sb.py | 0 python/{ => qa}/qa_mp4_decode_bs.py | 5 + python/{ => qa}/qa_mp4_encode_sb.py | 0 python/{ => qa}/qa_msc_decode.py | 0 python/{ => qa}/qa_msc_encode.py | 0 python/qa/qa_ofdm_coarse_frequency_correct.py | 53 ------ python/qa/qa_ofdm_ffe_all_in_one.py | 48 ----- python/qa/qa_ofdm_insert_pilot.py | 77 ++++---- python/qa/qa_ofdm_move_and_insert_zero.py | 67 +++---- .../{ => qa}/qa_ofdm_synchronization_cvf.py | 0 python/{ => qa}/qa_prune.py | 6 +- python/qa/qa_prune_vectors.py | 51 ------ python/{ => qa}/qa_puncture_bb.py | 5 + python/qa/qa_puncture_vbb.py | 37 ---- python/qa/qa_qpsk_demapper_vcb.py | 36 ---- python/qa/qa_qpsk_mapper_vbc.py | 38 ---- python/{ => qa}/qa_reed_solomon_decode_bb.py | 6 +- python/{ => qa}/qa_reed_solomon_encode_bb.py | 16 +- python/qa/qa_select_vectors.py | 71 -------- python/qa/qa_sum_phasor_trig_vcc.py | 112 ++++++------ python/{ => qa}/qa_synchronization_ff.py | 0 python/{ => qa}/qa_time_deinterleave_ff.py | 5 + python/qa/qa_unpuncture_vff.py | 85 ++++----- python/{ => qa}/qa_valve_ff.py | 0 python/qa_mapper_bc.py | 51 ------ python/qa_select_subch_vfvf.py | 91 ---------- python/qa_select_vectors.py | 165 ------------------ python/qa_time_interleave_bb.py | 91 ---------- python/qa_unpuncture_ff.py | 60 ------- python/test_ofdm_sync_dab.py | 70 -------- swig/dab_swig.i | 8 +- 67 files changed, 422 insertions(+), 2174 deletions(-) delete mode 100644 grc/dab_ofdm_sync_dab.xml delete mode 100644 grc/dab_ofdm_sync_dab2.xml delete mode 100644 grc/dab_qpsk_demapper_vcb.xml delete mode 100644 grc/dab_select_vectors.xml delete mode 100644 include/dab/qpsk_demapper_vcb.h delete mode 100644 include/dab/select_vectors.h delete mode 100644 lib/qpsk_demapper_vcb_impl.cc delete mode 100644 lib/qpsk_demapper_vcb_impl.h delete mode 100644 lib/select_vectors_impl.cc delete mode 100644 lib/select_vectors_impl.h rename python/{ofdm.py => ofdm_mod_bc.py} (100%) delete mode 100644 python/ofdm_sync_dab.py delete mode 100644 python/ofdm_sync_dab2.py delete mode 100755 python/qa/qa_concatenate_signals.py rename python/{ => qa}/qa_conv_encoder_bb.py (87%) delete mode 100755 python/qa/qa_correct_individual_phase_offset_vff.py rename python/{ => qa}/qa_crc16_bb.py (95%) rename python/{ => qa}/qa_dab_transmission_frame_mux_bb.py (100%) rename python/{ => qa}/qa_dabplus_audio_decoder_ff.py (100%) rename python/{ => qa}/qa_energy_disp.py (100%) rename python/{ => qa}/qa_fib_sink_vb.py (88%) rename python/{ => qa}/qa_fib_source_b.py (100%) rename python/{ => qa}/qa_fic_encode.py (92%) create mode 100755 python/qa/qa_frequency_interleaver_vcc.py delete mode 100755 python/qa/qa_frequency_interleaving.py rename python/{ => qa}/qa_mp2_decode_bs.py (100%) rename python/{ => qa}/qa_mp2_encode_sb.py (100%) rename python/{ => qa}/qa_mp4_decode_bs.py (94%) rename python/{ => qa}/qa_mp4_encode_sb.py (100%) rename python/{ => qa}/qa_msc_decode.py (100%) rename python/{ => qa}/qa_msc_encode.py (100%) delete mode 100755 python/qa/qa_ofdm_coarse_frequency_correct.py delete mode 100755 python/qa/qa_ofdm_ffe_all_in_one.py rename python/{ => qa}/qa_ofdm_synchronization_cvf.py (100%) rename python/{ => qa}/qa_prune.py (92%) delete mode 100755 python/qa/qa_prune_vectors.py rename python/{ => qa}/qa_puncture_bb.py (94%) delete mode 100755 python/qa/qa_puncture_vbb.py delete mode 100755 python/qa/qa_qpsk_demapper_vcb.py delete mode 100755 python/qa/qa_qpsk_mapper_vbc.py rename python/{ => qa}/qa_reed_solomon_decode_bb.py (95%) rename python/{ => qa}/qa_reed_solomon_encode_bb.py (92%) delete mode 100755 python/qa/qa_select_vectors.py rename python/{ => qa}/qa_synchronization_ff.py (100%) rename python/{ => qa}/qa_time_deinterleave_ff.py (96%) rename python/{ => qa}/qa_valve_ff.py (100%) delete mode 100755 python/qa_mapper_bc.py delete mode 100755 python/qa_select_subch_vfvf.py delete mode 100755 python/qa_select_vectors.py delete mode 100755 python/qa_time_interleave_bb.py delete mode 100755 python/qa_unpuncture_ff.py delete mode 100755 python/test_ofdm_sync_dab.py diff --git a/README.md b/README.md index 8c889396..b899cc14 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Features * Receiving and Transmitting DAB/DAB+ broadcasts with the graphical application "DABstep" * Receiving or Transmitting DAB/DAB+ with prepaired GNU Radio Companion flowgraph in examples/ * Receiving or Transmitting DAB/DAB+ by building your own GNU Radio flowgraph with provided gr-dab blocks -* USRP and RTl-SDR for reception supported +* USRP and RTL-SDR for reception supported Usage ------- diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index cb47a758..87a309e3 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -17,20 +17,16 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. install(FILES - dab_ofdm_sync_dab.xml - dab_ofdm_sync_dab2.xml dab_detect_null.xml dab_diff_phasor_vcc.xml - # dab_frequency_interleaver_vcc.xml - dab_qpsk_demapper_vcb.xml + dab_frequency_interleaver_vcc.xml dab_complex_to_interleaved_float_vcf.xml - # dab_fic_decode.xml + dab_fic_decode.xml dab_ofdm_demod.xml dab_ofdm_mod.xml - dab_select_vectors.xml - # dab_unpuncture_vff.xml + dab_unpuncture_vff.xml dab_fib_sink_vb.xml - # dab_ofdm_insert_pilot_vcc.xml + dab_ofdm_insert_pilot_vcc.xml dab_sum_phasor_trig_vcc.xml dab_ofdm_move_and_insert_zero.xml dab_insert_null_symbol.xml diff --git a/grc/dab_ofdm_sync_dab.xml b/grc/dab_ofdm_sync_dab.xml deleted file mode 100644 index 6ca4bcc3..00000000 --- a/grc/dab_ofdm_sync_dab.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - ofdm_sync_dab - dab_ofdm_sync_dab - dab - import dab - dab.ofdm_sync_dab($dab_params, $rx_params, $debug) - - - ... - ... - ... - - - - - in - - - - - - out - - - diff --git a/grc/dab_ofdm_sync_dab2.xml b/grc/dab_ofdm_sync_dab2.xml deleted file mode 100644 index 3382da22..00000000 --- a/grc/dab_ofdm_sync_dab2.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - OFDM sync v2 - dab_ofdm_sync_dab2 - [DAB] - import dab - dab.ofdm_sync_dab2(dab.parameters.dab_parameters(mode=$mode, sample_rate=$samp_rate, verbose=False), dab.parameters.receiver_parameters(mode=$mode), False) - - Mode - mode - int - - - Samp_rate - samp_rate - int - - - in - complex - - - out - complex - - - trigger - byte - - diff --git a/grc/dab_qpsk_demapper_vcb.xml b/grc/dab_qpsk_demapper_vcb.xml deleted file mode 100644 index 10bf011a..00000000 --- a/grc/dab_qpsk_demapper_vcb.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - qpsk_demapper_vcb - dab_qpsk_demapper_vcb - dab - import dab - dab.qpsk_demapper_vcb($symbol_length) - - - ... - ... - ... - - - - - in - - - - - - out - - - diff --git a/grc/dab_select_vectors.xml b/grc/dab_select_vectors.xml deleted file mode 100644 index aaf06f0e..00000000 --- a/grc/dab_select_vectors.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - select_vectors - dab_select_vectors - dab - import dab - dab.select_vectors($itemsize, $length, $num_select, $num_skip) - - - ... - ... - ... - - - - - in - - - - - - out - - - diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index e8381d5d..459846bb 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -24,9 +24,7 @@ install(FILES api.h diff_phasor_vcc.h frequency_interleaver_vcc.h - qpsk_demapper_vcb.h complex_to_interleaved_float_vcf.h - select_vectors.h unpuncture_vff.h fib_sink_vb.h ofdm_insert_pilot_vcc.h diff --git a/include/dab/qpsk_demapper_vcb.h b/include/dab/qpsk_demapper_vcb.h deleted file mode 100644 index 371112fc..00000000 --- a/include/dab/qpsk_demapper_vcb.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2015 <+YOU OR YOUR COMPANY+>. - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_QPSK_DEMAPPER_VCB_H -#define INCLUDED_DAB_QPSK_DEMAPPER_VCB_H - -#include -#include - -namespace gr { - namespace dab { - - /*! - * \brief <+description of block+> - * \ingroup dab - * - */ - class DAB_API qpsk_demapper_vcb : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::qpsk_demapper_vcb. - * - * To avoid accidental use of raw pointers, dab::qpsk_demapper_vcb's - * constructor is in a private implementation - * class. dab::qpsk_demapper_vcb::make is the public interface for - * creating new instances. - */ - static sptr make(int symbol_length); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_QPSK_DEMAPPER_VCB_H */ - diff --git a/include/dab/select_vectors.h b/include/dab/select_vectors.h deleted file mode 100644 index bf91e90b..00000000 --- a/include/dab/select_vectors.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2015 <+YOU OR YOUR COMPANY+>. - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_SELECT_VECTORS_H -#define INCLUDED_DAB_SELECT_VECTORS_H - -#include -#include - -namespace gr { - namespace dab { - - /*! - * \brief <+description of block+> - * \ingroup dab - * - */ - class DAB_API select_vectors : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::select_vectors. - * - * To avoid accidental use of raw pointers, dab::select_vectors's - * constructor is in a private implementation - * class. dab::select_vectors::make is the public interface for - * creating new instances. - */ - static sptr make(size_t itemsize, unsigned int length, unsigned int num_select, unsigned int num_skip); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_SELECT_VECTORS_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0fef755b..11033789 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -27,9 +27,7 @@ link_directories(${Boost_LIBRARY_DIRS}) list(APPEND dab_sources diff_phasor_vcc_impl.cc frequency_interleaver_vcc_impl.cc - qpsk_demapper_vcb_impl.cc complex_to_interleaved_float_vcf_impl.cc - select_vectors_impl.cc unpuncture_vff_impl.cc fib_sink_vb_impl.cc crc16.cc diff --git a/lib/qpsk_demapper_vcb_impl.cc b/lib/qpsk_demapper_vcb_impl.cc deleted file mode 100644 index 545f5ffc..00000000 --- a/lib/qpsk_demapper_vcb_impl.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "qpsk_demapper_vcb_impl.h" - -namespace gr { - namespace dab { - -qpsk_demapper_vcb::sptr -qpsk_demapper_vcb::make(int symbol_length) -{ - return gnuradio::get_initial_sptr - (new qpsk_demapper_vcb_impl(symbol_length)); -} - -qpsk_demapper_vcb_impl::qpsk_demapper_vcb_impl(int symbol_length) - : gr::sync_block("qpsk_demapper_vcb", - gr::io_signature::make (1, 1, sizeof(gr_complex)*symbol_length), - gr::io_signature::make (1, 1, sizeof(char)*symbol_length/4)), - d_symbol_length(symbol_length) -{ - assert(symbol_length>0); - assert(symbol_length%4==0); -} - - -int -qpsk_demapper_vcb_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - char *out = (char *) output_items[0]; - - char byte = 0; - - for (int i=0; i - -namespace gr { - namespace dab { - -class qpsk_demapper_vcb_impl : public qpsk_demapper_vcb -{ - private: - - int d_symbol_length; - - public: - qpsk_demapper_vcb_impl(int symbol_length); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; -} -} - -#endif /* INCLUDED_DAB_QPSK_DEMAPPER_VCB_H */ diff --git a/lib/select_vectors_impl.cc b/lib/select_vectors_impl.cc deleted file mode 100644 index 6eb79672..00000000 --- a/lib/select_vectors_impl.cc +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "select_vectors_impl.h" - -namespace gr { - namespace dab { - -select_vectors::sptr -select_vectors::make(size_t itemsize, unsigned int length, unsigned int num_select, unsigned int num_skip) -{ - return gnuradio::get_initial_sptr - (new select_vectors_impl(itemsize, length, num_select, num_skip)); -} - -select_vectors_impl::select_vectors_impl(size_t itemsize, unsigned int length, unsigned int num_select, unsigned int num_skip) - : gr::block("select_vectors", - gr::io_signature::make2 (2, 2, itemsize*length, sizeof(char)), - gr::io_signature::make2 (2, 2, itemsize*length, sizeof(char))), - d_itemsize(itemsize), d_length(length), d_num_select(num_select), d_num_skip(num_skip), d_index(num_select+num_skip) /* <- dont output anything before 1st trigger */ -{ - assert(d_num_select!=0); - assert(d_length!=0); -} - -void -select_vectors_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - int in_req = noutput_items * (d_num_skip+d_num_select)/d_num_select; /* very coarse .. */ - - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = in_req; -} - -int -select_vectors_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const char *iptr = (const char *) input_items[0]; - const char *trigger = (const char *) input_items[1]; - - char *optr = (char *) output_items[0]; - char *triggerout = (char *) output_items[1]; - - int n_consumed = 0; - int n_produced = 0; - - - while (n_consumed < ninput_items[0] && n_consumed < ninput_items[1] && n_produced < noutput_items) { - - /* start of frame? */ - if (*trigger++ == 1) - d_index=0; - - /* select this vector? */ - if (d_index >= d_num_skip && d_index < d_num_select + d_num_skip) { - /* trigger signal */ - if (d_index == d_num_skip) - *triggerout++ = 1; - else - *triggerout++ = 0; - /* data */ - memcpy(optr, iptr, d_length*d_itemsize); - iptr += d_length*d_itemsize; - optr += d_length*d_itemsize; - n_produced++; - } else { - iptr += d_length*d_itemsize; - } - - d_index++; - n_consumed++; - } - - consume_each(n_consumed); - return n_produced; -} - -} -} - diff --git a/lib/select_vectors_impl.h b/lib/select_vectors_impl.h deleted file mode 100644 index f5e662db..00000000 --- a/lib/select_vectors_impl.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_DAB_SELECT_VECTORS_IMPL_H -#define INCLUDED_DAB_SELECT_VECTORS_IMPL_H - -#include - -namespace gr { - namespace dab { - -/*! \brief select a row of vectors - * - * input1: vector of size length*itemsize - * input2: char stream with triggers for start of transmission frame - * - * output1: vector of size length*itemsize - * output2: same as input2 - * - * selects a row of vectors of the transmission frame; start of a transmission frame is triggerd by input2 - * - * @param itemsize sizeof input and outputstream of port 0 - * @param length vector length - * @param num_select number of vectors to select - * @param num_skip number of vectors to skip before selection of num_select vectors - * - */ - class select_vectors_impl : public select_vectors { - private: - size_t d_itemsize; - unsigned int d_length; - unsigned int d_num_select; - unsigned int d_num_skip; - unsigned int d_index; - - public: - select_vectors_impl(size_t itemsize, unsigned int length, unsigned int num_select, unsigned int num_skip); - - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } -} - -#endif /* INCLUDED_DAB_SELECT_VECTORS_H */ diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e4fb403f..4ac6b5da 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -42,20 +42,17 @@ configure_file( GR_PYTHON_INSTALL( FILES __init__.py - ofdm_sync_dab.py - ofdm_sync_dab2.py - detect_null.py - ofdm.py + ofdm_mod_bc.py + ofdm_demod_cc.py parameters.py - fic.py - msc_decode.py fic_encode.py msc_encode.py + fic_decode_vc.py + msc_decode.py transmitter_c.py ${CMAKE_CURRENT_BINARY_DIR}/constants.py dabplus_audio_decoder_ff.py - ofdm_demod_cc.py - fic_decode_vc.py DESTINATION ${GR_PYTHON_DIR}/dab + DESTINATION ${GR_PYTHON_DIR}/dab ) ######################################################################## @@ -65,27 +62,37 @@ include(GrTest) set(GR_TEST_TARGET_DEPS gnuradio-dab) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) -GR_ADD_TEST(qa_time_interleave_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_time_interleave_bb.py) -GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_time_deinterleave_ff.py) -GR_ADD_TEST(qa_fib_sink_vb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_fib_sink_vb.py) -GR_ADD_TEST(qa_crc16_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_crc16_bb.py) -GR_ADD_TEST(qa_fib_source_b ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_fib_source_b.py) -GR_ADD_TEST(qa_select_subch_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_select_subch_vfvf.py) -GR_ADD_TEST(qa_unpuncture_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_unpuncture_ff.py) -GR_ADD_TEST(qa_prune ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_prune.py) -GR_ADD_TEST(qa_fic_encode ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_fic_encode.py) -GR_ADD_TEST(qa_puncture_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_puncture_bb.py) -GR_ADD_TEST(qa_msc_encode ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_msc_encode.py) -GR_ADD_TEST(qa_dab_transmission_frame_mux_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dab_transmission_frame_mux_bb.py) -GR_ADD_TEST(qa_conv_encoder_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_conv_encoder_bb.py) -GR_ADD_TEST(qa_mapper_bc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mapper_bc.py) -GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) -GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp4_decode_bs.py) -GR_ADD_TEST(qa_dabplus_audio_decoder_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dabplus_audio_decoder_ff.py) -GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_reed_solomon_decode_bb.py) -GR_ADD_TEST(qa_reed_solomon_encode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_reed_solomon_encode_bb.py) -GR_ADD_TEST(qa_mp4_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp4_encode_sb.py) -GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) -GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) -GR_ADD_TEST(qa_synchronization_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_synchronization_ff.py) -GR_ADD_TEST(qa_ofdm_synchronization_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronization_cvf.py) + +GR_ADD_TEST(qa_ofdm_insert_pilot.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_ofdm_insert_pilot.py) +GR_ADD_TEST(qa_sum_phasor_trig_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_sum_phasor_trig_vcc.py) +GR_ADD_TEST(qa_frequency_interleaver_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_frequency_interleaver_vcc.py) +GR_ADD_TEST(qa_ofdm_move_and_insert_zero.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_ofdm_move_and_insert_zero.py) +GR_ADD_TEST(qa_insert_null_symbol.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_insert_null_symbol.py) +GR_ADD_TEST(qa_fib_source_b.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_fib_source_b.py) +GR_ADD_TEST(qa_fic_encode.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_fic_encode.py) +GR_ADD_TEST(qa_crc16_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_crc16_bb.py) +GR_ADD_TEST(qa_conv_encoder_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_conv_encoder_bb.py) +GR_ADD_TEST(qa_puncture_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_puncture_bb.py) +GR_ADD_TEST(qa_mp4_encode_sb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_encode_sb.py) +GR_ADD_TEST(qa_reed_solomon_encode_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_encode_bb.py) +GR_ADD_TEST(qa_msc_encode.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_msc_encode.py) +GR_ADD_TEST(qa_dab_transmission_frame_mux_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_dab_transmission_frame_mux_bb.py) + +GR_ADD_TEST(qa_diff_phasor_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_diff_phasor_vcc.py) +GR_ADD_TEST(qa_complex_to_interleaved_float_vcf.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_complex_to_interleaved_float_vcf.py) +GR_ADD_TEST(qa_unpuncture_vff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_unpuncture_vff.py) +GR_ADD_TEST(qa_prune.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_prune.py) +GR_ADD_TEST(qa_fib_sink_vb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_fib_sink_vb.py) +GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_time_deinterleave_ff.py) +GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_decode_bb.py) +GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_decode_bs.py) + +#GR_ADD_TEST(qa_time_interleave_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_time_interleave_bb.py) +#GR_ADD_TEST(qa_select_subch_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_select_subch_vfvf.py) +#GR_ADD_TEST(qa_prune ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_prune.py) +#GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) +#GR_ADD_TEST(qa_dabplus_audio_decoder_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dabplus_audio_decoder_ff.py) +#GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) +#GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) +#GR_ADD_TEST(qa_synchronization_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_synchronization_ff.py) +#GR_ADD_TEST(qa_ofdm_synchronization_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronization_cvf.py) diff --git a/python/__init__.py b/python/__init__.py index c581fc76..db68a90a 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -31,8 +31,8 @@ pass # import any pure python here -from ofdm_sync_dab import ofdm_sync_dab -from ofdm_sync_dab2 import ofdm_sync_dab2 + + from detect_null import detect_null from parameters import dab_parameters from parameters import receiver_parameters diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py index 85c7344c..e7e79e6b 100644 --- a/python/fic_decode_vc.py +++ b/python/fic_decode_vc.py @@ -20,7 +20,7 @@ # from gnuradio import gr, trellis, blocks -import dab +import dab_swig as dab from math import sqrt class fic_decode_vc(gr.hier_block2): diff --git a/python/ofdm.py b/python/ofdm_mod_bc.py similarity index 100% rename from python/ofdm.py rename to python/ofdm_mod_bc.py diff --git a/python/ofdm_sync_dab.py b/python/ofdm_sync_dab.py deleted file mode 100644 index d83727c4..00000000 --- a/python/ofdm_sync_dab.py +++ /dev/null @@ -1,117 +0,0 @@ -# _*_ coding: utf8 _*_ - -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -from gnuradio import gr -from gnuradio import blocks, analog -import dab -import sys -from math import pi - -class ofdm_sync_dab(gr.hier_block2): - """ - @brief OFDM Energy based time synchronisation and coarse frequency synchronisation for DAB signals - - This block implements synchronisation. Time synchronisation is done by using the NULL symbols. - Fine frequency synchronisation is done by correlating the cyclic prefix with the last part of the symbol. - - In contrast to the first version, this block averages over multiple symbols to get better fine frequency error estimates. - """ - def __init__(self, dab_params, rx_params, debug=False): - """ - OFDM time and coarse frequency synchronisation for DAB - - @param mode DAB mode (1-4) - @param debug if True: write data streams out to files - """ - - dp = dab_params - rp = rx_params - - gr.hier_block2.__init__(self,"ofdm_sync_dab", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature - gr.io_signature2(2, 2, gr.sizeof_gr_complex, gr.sizeof_char)) # output signature - - # workaround for a problem that prevents connecting more than one block directly (see trac ticket #161) - self.input = gr.kludge_copy(gr.sizeof_gr_complex) - self.connect(self, self.input) - - # - # null-symbol detection - # - # (outsourced to detect_zero.py) - - self.ns_detect = detect_null.detect_null(dp.ns_length, debug) - self.connect(self.input, self.ns_detect) - - # - # fine frequency synchronisation - # - - # the code for fine frequency synchronisation is adapted from - # ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine - # frequency error, as suggested in "ML Estimation of Timing and - # Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek, - # Magnus Sandell, Per Ola Börjesson, see - # http://www.sm.luth.se/csee/sp/research/report/bsb96r.html - - self.ffs_delay = blocks.delay(gr.sizeof_gr_complex, dp.fft_length) - self.ffs_conj = blocks.conjugate_cc() - self.ffs_mult = blocks.multiply_cc() - self.ffs_moving_sum = dab_swig.moving_sum_cc(dp.cp_length) - self.ffs_arg = blocks.complex_to_arg() - self.ffs_sample_and_average = dab_swig.ofdm_ffs_sample(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, dp.sample_rate) - if rp.correct_ffe: - self.ffs_delay_input_for_correction = blocks.delay(gr.sizeof_gr_complex, dp.symbol_length*rp.symbols_for_ffs_estimation) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself - self.ffs_delay_frame_start = blocks.delay(gr.sizeof_char, dp.symbol_length*rp.symbols_for_ffs_estimation) # sample the value at the end of the symbol .. - self.ffs_nco = analog.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample - self.ffs_mixer = blocks.multiply_cc() - - # calculate fine frequency error - self.connect(self.input, self.ffs_conj, self.ffs_mult) - self.connect(self.input, self.ffs_delay, (self.ffs_mult, 1)) - self.connect(self.ffs_mult, self.ffs_moving_sum, self.ffs_arg, (self.ffs_sample_and_average, 0)) - self.connect(self.ns_detect, (self.ffs_sample_and_average, 1)) - - if rp.correct_ffe: - # do the correction - self.connect(self.ffs_sample_and_average, self.ffs_nco, (self.ffs_mixer, 0)) - self.connect(self.input, self.ffs_delay_input_for_correction, (self.ffs_mixer, 1)) - # output - corrected signal and start of DAB frames - self.connect(self.ffs_mixer, (self, 0)) - self.connect(self.ns_detect, self.ffs_delay_frame_start, (self, 1)) - else: - # just patch the signal through - self.connect(self.ffs_sample_and_average, blocks.null_sink(gr.sizeof_float)) - self.connect(self.input, (self,0)) - # frame start still needed .. - self.connect(self.ns_detect, (self,1)) - - if debug: - self.connect(self.ffs_sample_and_average, blocks.multiply_const_ff(1./(dp.T*2*pi)), gr.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat")) - self.connect(self.ffs_mixer, blocks.file_sink(gr.sizeof_gr_complex, "debug/ofdm_sync_dab_fine_freq_corrected_c.dat")) - - def clear_state(self): - self.ffs_moving_sum.reset() - self.ns_detect.clear_state() diff --git a/python/ofdm_sync_dab2.py b/python/ofdm_sync_dab2.py deleted file mode 100644 index fa8ed574..00000000 --- a/python/ofdm_sync_dab2.py +++ /dev/null @@ -1,109 +0,0 @@ -# _*_ coding: utf8 _*_ - -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -from gnuradio import gr, blocks, analog -import dab -import sys -from math import pi - -class ofdm_sync_dab2(gr.hier_block2): - """ - @brief OFDM Energy based time synchronisation and coarse frequency synchronisation for DAB signals - - This block implements synchronisation. Time synchronisation is done by using the NULL symbols. - Fine frequency synchronisation is done by correlating the cyclic prefix with the last part of the symbol. - - In contrast to the first version, this block averages over multiple symbols to get better fine frequency error estimates. - """ - def __init__(self, dab_params, rx_params, debug=False): - """ - OFDM time and coarse frequency synchronisation for DAB - - @param mode DAB mode (1-4) - @param debug if True: write data streams out to files - """ - - dp = dab_params - rp = rx_params - - gr.hier_block2.__init__(self,"ofdm_sync_dab", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature - gr.io_signature2(2, 2, gr.sizeof_gr_complex, gr.sizeof_char)) # output signature - - # workaround for a problem that prevents connecting more than one block directly (see trac ticket #161) - #self.input = gr.kludge_copy(gr.sizeof_gr_complex) - self.input = blocks.multiply_const_cc(1) # FIXME - self.connect(self, self.input) - - # - # null-symbol detection - # - # (outsourced to detect_zero.py) - - self.ns_detect = dab.detect_null(dp.ns_length, debug) - self.connect(self.input, self.ns_detect) - - # - # fine frequency synchronisation - # - - # the code for fine frequency synchronisation is adapted from - # ofdm_sync_ml.py; it abuses the cyclic prefix to find the fine - # frequency error, as suggested in "ML Estimation of Timing and - # Frequency Offset in OFDM Systems", by Jan-Jaap van de Beek, - # Magnus Sandell, Per Ola Börjesson, see - # http://www.sm.luth.se/csee/sp/research/report/bsb96r.html - - self.ffe = dab.ofdm_ffe_all_in_one(dp.symbol_length, dp.fft_length, rp.symbols_for_ffs_estimation, rp.ffs_alpha, int(dp.sample_rate)) - if rp.correct_ffe: - self.ffs_delay_input_for_correction = blocks.delay(gr.sizeof_gr_complex, dp.symbol_length*rp.symbols_for_ffs_estimation) # by delaying the input, we can use the ff offset estimation from the first symbol to correct the first symbol itself - self.ffs_delay_frame_start = blocks.delay(gr.sizeof_char, dp.symbol_length*rp.symbols_for_ffs_estimation) # sample the value at the end of the symbol .. - self.ffs_nco = analog.frequency_modulator_fc(1) # ffs_sample_and_hold directly outputs phase error per sample - self.ffs_mixer = blocks.multiply_cc() - - # calculate fine frequency error - self.connect(self.input, (self.ffe, 0)) - self.connect(self.ns_detect, (self.ffe, 1)) - - if rp.correct_ffe: - # do the correction - self.connect(self.ffe, self.ffs_nco, (self.ffs_mixer, 0)) - self.connect(self.input, self.ffs_delay_input_for_correction, (self.ffs_mixer, 1)) - # output - corrected signal and start of DAB frames - self.connect(self.ffs_mixer, (self, 0)) - self.connect(self.ns_detect, self.ffs_delay_frame_start, (self, 1)) - else: - # just patch the signal through - self.connect(self.ffe, blocks.null_sink(gr.sizeof_float)) - self.connect(self.input, (self,0)) - # frame start still needed .. - self.connect(self.ns_detect, (self,1)) - - if debug: - self.connect(self.ffe, blocks.multiply_const_ff(1./(dp.T*2*pi)), blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_fine_freq_err_f.dat")) - #self.connect(self.ffs_mixer, blocks.file_sink(gr.sizeof_gr_complex, "debug/ofdm_sync_dab_fine_freq_corrected_c.dat")) - - def clear_state(self): - self.ns_detect.clear_state() diff --git a/python/qa/qa_complex_to_interleaved_float_vcf.py b/python/qa/qa_complex_to_interleaved_float_vcf.py index bf08ade4..a05f30c7 100755 --- a/python/qa/qa_complex_to_interleaved_float_vcf.py +++ b/python/qa/qa_complex_to_interleaved_float_vcf.py @@ -2,35 +2,36 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab + class qa_complex_to_interleaved_float_vcf(gr_unittest.TestCase): - """ - @brief QA for the complex to interleaved float block - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_complex_to_interleaved_float_vcf(self): - src_data = (1+2j,3+4j,5+6j,7+8j) - expected_result = (1,3,2,4,5,7,6,8) - src = blocks.vector_source_c(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 2) - complex_to_interleaved_float_vcf = dab.complex_to_interleaved_float_vcf(2) - v2s = blocks.vector_to_stream(gr.sizeof_float, 4) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, complex_to_interleaved_float_vcf, v2s, dst) - self.tb.run() - result_data = dst.data() - # print result_data - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) + """ + @brief QA for the complex to interleaved float block -if __name__ == '__main__': - gr_unittest.main() + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + def test_001_complex_to_interleaved_float_vcf(self): + src_data = (1 + 2j, 3 + 4j, 5 + 6j, 7 + 8j) + expected_result = (1, 3, 2, 4, 5, 7, 6, 8) + src = blocks.vector_source_c(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 2) + complex_to_interleaved_float_vcf = dab.complex_to_interleaved_float_vcf(2) + v2s = blocks.vector_to_stream(gr.sizeof_float, 4) + dst = blocks.vector_sink_f() + self.tb.connect(src, s2v, complex_to_interleaved_float_vcf, v2s, dst) + self.tb.run() + result_data = dst.data() + # print result_data + self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) + + +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa/qa_concatenate_signals.py b/python/qa/qa_concatenate_signals.py deleted file mode 100755 index 208f93a8..00000000 --- a/python/qa/qa_concatenate_signals.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python - -import os -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab - -class qa_concatenate_signals(gr_unittest.TestCase): - """ - @brief QA for signal concatenation block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - os.environ['GR_SCHEDULER'] = "STS" # need single threaded scheduler for use with concatenate_signals - - def tearDown(self): - self.tb = None - - def test_001_concatenate_signals(self): - src_data0 = [1j,2j,3j,4j,5j] - src_data1 = [6j,7j,8j] - src_data2 = [9j,10j,11j,12j,13j,14j] - expected_result = src_data0 + src_data1 + src_data2 - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_c(src_data1) - src2 = blocks.vector_source_c(src_data2) - concatenate_signals = dab.concatenate_signals(gr.sizeof_gr_complex) - dst = blocks.vector_sink_c() - self.tb.connect(src0, (concatenate_signals,0)) - self.tb.connect(src1, (concatenate_signals,1)) - self.tb.connect(src2, (concatenate_signals,2)) - self.tb.connect(concatenate_signals, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) - - def test_002_concatenate_signals(self): - src_data0 = [6j] - src_data1 = [1j,2j,3j,4j,5j]*3000 - src_data2 = [7j] - src_data3 = [8j,9j,10j,11j]*3000 - expected_result = src_data0 + src_data1 + src_data2 + src_data3 - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_c(src_data1) - src2 = blocks.vector_source_c(src_data2) - src3 = blocks.vector_source_c(src_data3) - concatenate_signals = dab.concatenate_signals(gr.sizeof_gr_complex) - dst = blocks.vector_sink_c() - self.tb.connect(src0, (concatenate_signals,0)) - self.tb.connect(src1, (concatenate_signals,1)) - self.tb.connect(src2, (concatenate_signals,2)) - self.tb.connect(src3, (concatenate_signals,3)) - self.tb.connect(concatenate_signals, dst) - self.tb.run() - result_data = dst.data() - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) - - def test_003_concatenate_signals(self): - src_data0 = [6] - src_data1 = [1,2,3,4,5] - src_data2 = [7] - src_data3 = [8,9,10,11] - expected_result = src_data0 + src_data1 + src_data2 + src_data3 - src0 = blocks.vector_source_b(src_data0) - src1 = blocks.vector_source_b(src_data1) - src2 = blocks.vector_source_b(src_data2) - src3 = blocks.vector_source_b(src_data3) - concatenate_signals = dab.concatenate_signals(gr.sizeof_char) - dst = blocks.vector_sink_b() - self.tb.connect(src0, (concatenate_signals,0)) - self.tb.connect(src1, (concatenate_signals,1)) - self.tb.connect(src2, (concatenate_signals,2)) - self.tb.connect(src3, (concatenate_signals,3)) - self.tb.connect(concatenate_signals, dst) - self.tb.run() - result_data = list(dst.data()) - self.assertEqual(expected_result, result_data) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa_conv_encoder_bb.py b/python/qa/qa_conv_encoder_bb.py similarity index 87% rename from python/qa_conv_encoder_bb.py rename to python/qa/qa_conv_encoder_bb.py index 6c8c439d..460a85ad 100755 --- a/python/qa_conv_encoder_bb.py +++ b/python/qa/qa_conv_encoder_bb.py @@ -25,6 +25,11 @@ import dab_swig as dab class qa_conv_encoder_bb (gr_unittest.TestCase): + """ + @brief QA for the convolutional encoder block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () @@ -32,8 +37,10 @@ def setUp (self): def tearDown (self): self.tb = None -# test of a 2 byte frame with reference data (calculated by hand) def test_001_t(self): + """ + test of a 2 byte frame with reference data (calculated by hand) + """ data = (0x05, 0x00) expected_result = (0x00, 0x00, 0x0f, 0x62, 0xBF, 0x4D, 0x9F, 0x00, 0x00, 0x00, 0x00) src = blocks.vector_source_b(data) diff --git a/python/qa/qa_correct_individual_phase_offset_vff.py b/python/qa/qa_correct_individual_phase_offset_vff.py deleted file mode 100755 index 68afc261..00000000 --- a/python/qa/qa_correct_individual_phase_offset_vff.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -from math import pi -import dab - -class qa_correct_individual_phase_offset_vff(gr_unittest.TestCase): - """ - @brief QA for the individual carrier phase equalisation block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_correct_individual_phase_offset_vff(self): - expected_result = [x*pi/2+pi/4 for x in [1,-2,-1,0,1,-2]] - src_data = map(lambda x,y: x+y, expected_result,[0.1,0.3,-0.2,0.2,0.4,0.1]) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, 3) - mut = dab.correct_individual_phase_offset_vff(3, 1) - v2s = blocks.vector_to_stream(gr.sizeof_float, 3) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, mut, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 5) - - def test_002_correct_individual_phase_offset_vff(self): - data = [x*pi/2+pi/4 for x in [1,-2,-1,0,1,-2]] - src_data = map(lambda x,y: x+y, data, [0.1,0.3,-0.4,0.2,0.4,0.1]) - expected_result = map(lambda x,y: x+y, data, [0.05,0.15,-0.2,0.075,0.125,0.15]) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, 3) - mut = dab.correct_individual_phase_offset_vff(3, 0.5) - v2s = blocks.vector_to_stream(gr.sizeof_float, 3) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, mut, v2s, dst) - self.tb.run() - result_data = dst.data() - # print src_data - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 5) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa_crc16_bb.py b/python/qa/qa_crc16_bb.py similarity index 95% rename from python/qa_crc16_bb.py rename to python/qa/qa_crc16_bb.py index c7b807b3..be764eea 100755 --- a/python/qa_crc16_bb.py +++ b/python/qa/qa_crc16_bb.py @@ -25,6 +25,12 @@ class qa_crc16_bb(gr_unittest.TestCase): + """ + @brief QA for the crc16 block + + This class implements a test bench to verify the corresponding C++ class. + """ + def setUp(self): self.tb = gr.top_block() diff --git a/python/qa_dab_transmission_frame_mux_bb.py b/python/qa/qa_dab_transmission_frame_mux_bb.py similarity index 100% rename from python/qa_dab_transmission_frame_mux_bb.py rename to python/qa/qa_dab_transmission_frame_mux_bb.py diff --git a/python/qa_dabplus_audio_decoder_ff.py b/python/qa/qa_dabplus_audio_decoder_ff.py similarity index 100% rename from python/qa_dabplus_audio_decoder_ff.py rename to python/qa/qa_dabplus_audio_decoder_ff.py diff --git a/python/qa/qa_diff_phasor_vcc.py b/python/qa/qa_diff_phasor_vcc.py index 36cfbc42..6c53a33e 100755 --- a/python/qa/qa_diff_phasor_vcc.py +++ b/python/qa/qa_diff_phasor_vcc.py @@ -2,50 +2,50 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab + class qa_diff_phasor_vcc(gr_unittest.TestCase): - """ - @brief QA for the phase differentiation block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_diff_phasor_vcc(self): - a = [1+2j,2+3.5j,3.5+4j,4+5j,5+6j] - b = [1j,1j,1j,1j,1j] - c = [-1j+3,1j,-7+0j,2.5j+0.333,3.2j] - d = [(0.35979271051026462+0.89414454782483865j), - (0.19421665709046287+0.024219594550527801j), - (0.12445564785882557+0.40766238899138718j), - (0.041869638845043688+0.97860437393366329j), - (0.068927762235083234+0.16649764877365247j)] - e = [(0.16207552830286298+0.435385030608331j), - (0.47195779613669675+0.37824764113272558j), - (0.13911998015446148+0.6585095669811617j), - (0.093510743358783954+0.98446560079828938j), - (0.86036393297704694+0.72043005342024602j)] - multconj = lambda x,y: x.conjugate()*y - src_data = a+b+c+d+e - expected_result = [0j,0j,0j,0j,0j]+map(multconj,a,b)+map(multconj,b,c)+map(multconj,c,d)+map(multconj,d,e) - src = blocks.vector_source_c(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) - diff_phasor_vcc = dab.diff_phasor_vcc(5) - v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) - dst = blocks.vector_sink_c() - self.tb.connect(src, s2v, diff_phasor_vcc, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) + """ + @brief QA for the phase differentiation block. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_diff_phasor_vcc(self): + a = [1 + 2j, 2 + 3.5j, 3.5 + 4j, 4 + 5j, 5 + 6j] + b = [1j, 1j, 1j, 1j, 1j] + c = [-1j + 3, 1j, -7 + 0j, 2.5j + 0.333, 3.2j] + d = [(0.35979271051026462 + 0.89414454782483865j), + (0.19421665709046287 + 0.024219594550527801j), + (0.12445564785882557 + 0.40766238899138718j), + (0.041869638845043688 + 0.97860437393366329j), + (0.068927762235083234 + 0.16649764877365247j)] + e = [(0.16207552830286298 + 0.435385030608331j), + (0.47195779613669675 + 0.37824764113272558j), + (0.13911998015446148 + 0.6585095669811617j), + (0.093510743358783954 + 0.98446560079828938j), + (0.86036393297704694 + 0.72043005342024602j)] + multconj = lambda x, y: x.conjugate() * y + src_data = a + b + c + d + e + expected_result = [0j, 0j, 0j, 0j, 0j] + map(multconj, a, b) \ + + map(multconj, b, c) + map(multconj, c, d) + map(multconj, d, e) + src = blocks.vector_source_c(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) + diff_phasor_vcc = dab.diff_phasor_vcc(5) + v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) + dst = blocks.vector_sink_c() + self.tb.connect(src, s2v, diff_phasor_vcc, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa_energy_disp.py b/python/qa/qa_energy_disp.py similarity index 100% rename from python/qa_energy_disp.py rename to python/qa/qa_energy_disp.py diff --git a/python/qa_fib_sink_vb.py b/python/qa/qa_fib_sink_vb.py similarity index 88% rename from python/qa_fib_sink_vb.py rename to python/qa/qa_fib_sink_vb.py index 7af5c45c..1af8d69f 100644 --- a/python/qa_fib_sink_vb.py +++ b/python/qa/qa_fib_sink_vb.py @@ -24,6 +24,11 @@ import dab_swig as dab class qa_fib_sink_vb (gr_unittest.TestCase): + """ + @brief QA for the fib sink block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () @@ -31,8 +36,10 @@ def setUp (self): def tearDown (self): self.tb = None -#manual check of print outs with reference data of debug file (SWR radio station) def test_001_t (self): + """ + manual check of print outs with reference data of debug file + """ data = ( 0x05, 0x00, 0x10, 0xEA, 0x04, 0x24, 0x06, 0x02, 0xD3, 0xA6, 0x01, 0x3F, 0x06, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x89) diff --git a/python/qa_fib_source_b.py b/python/qa/qa_fib_source_b.py similarity index 100% rename from python/qa_fib_source_b.py rename to python/qa/qa_fib_source_b.py diff --git a/python/qa_fic_encode.py b/python/qa/qa_fic_encode.py similarity index 92% rename from python/qa_fic_encode.py rename to python/qa/qa_fic_encode.py index adb43e42..12e7e58b 100755 --- a/python/qa_fic_encode.py +++ b/python/qa/qa_fic_encode.py @@ -21,11 +21,10 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -from gnuradio import fec import dab_swig as dab from parameters import dab_parameters from fic_encode import fic_encode -from fic import fic_decode +from fic_decode_vc import fic_decode_vc as fic_decode class qa_fic_encode (gr_unittest.TestCase): @@ -59,9 +58,6 @@ def test_001_t (self): # decode self.fic_decoder = fic_decode(self.dab_params) - # control stream - self.trigger_src = blocks.vector_source_b([1] + [0]*74, True) - self.tb.connect(self.fib_src, blocks.head_make(gr.sizeof_char, 100000), self.fib_enc, @@ -71,7 +67,6 @@ def test_001_t (self): self.soft_interleaver, self.fic_decoder ) - self.tb.connect(self.trigger_src, (self.fic_decoder, 1)) self.tb.run () diff --git a/python/qa/qa_frequency_interleaver_vcc.py b/python/qa/qa_frequency_interleaver_vcc.py new file mode 100755 index 00000000..c21c62e4 --- /dev/null +++ b/python/qa/qa_frequency_interleaver_vcc.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + + +class qa_frequency_interleaver_vcc(gr_unittest.TestCase): + """ + @brief QA for frequency interleaving. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_frequency_interleaver_vcc(self): + src_data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + 1j] + expected_result = [2, 1, 4, 0, 3, 7, 6, 9 + 1j, 5, 8] + expected_result = [complex(x) for x in expected_result] + src = blocks.vector_source_c(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) + frequency_interleaver_vcc = dab.frequency_interleaver_vcc([3, 1, 0, 4, 2]) + v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) + dst = blocks.vector_sink_c() + self.tb.connect(src, s2v, frequency_interleaver_vcc, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) + + +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa/qa_frequency_interleaving.py b/python/qa/qa_frequency_interleaving.py deleted file mode 100755 index 63f47c5c..00000000 --- a/python/qa/qa_frequency_interleaving.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab - -class qa_frequency_interleaver_vcc(gr_unittest.TestCase): - """ - @brief QA for frequency interleaving. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_frequency_interleaver_vcc(self): - src_data = [0,1,2,3,4,5,6,7,8,9+1j] - expected_result = [2,1,4,0,3,7,6,9+1j,5,8] - expected_result = [complex(x) for x in expected_result] - src = blocks.vector_source_c(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 5) - frequency_interleaver_vcc = dab.frequency_interleaver_vcc([3,1,0,4,2]) - v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 5) - dst = blocks.vector_sink_c() - self.tb.connect(src, s2v, frequency_interleaver_vcc, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_insert_null_symbol.py b/python/qa/qa_insert_null_symbol.py index 7ae8e01e..1d396b60 100755 --- a/python/qa/qa_insert_null_symbol.py +++ b/python/qa/qa_insert_null_symbol.py @@ -2,39 +2,40 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import dab +import dab_swig as dab + class qa_insert_null_symbol(gr_unittest.TestCase): - """ - @brief QA for Null symbol insertion. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_insert_null_symbol(self): - src_data0 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] - src_data1 = [0,1,0,1,0] - expected_result = [1,2,3,0,0,0,0,0,4,5,6,7,8,9,0,0,0,0,0,10,11,12,13,14,15] - expected_result = [complex(x) for x in expected_result] - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 3) - insert_null_symbol = dab.insert_null_symbol(5,3) - dst = blocks.vector_sink_c() - self.tb.connect(src0, s2v, insert_null_symbol, dst) - self.tb.connect(src1, (insert_null_symbol,1)) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) + """ + @brief QA for Null symbol insertion. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_insert_null_symbol(self): + src_data0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + src_data1 = [0, 1, 0, 1, 0] + expected_result = [1, 2, 3, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15] + expected_result = [complex(x) for x in expected_result] + src0 = blocks.vector_source_c(src_data0) + src1 = blocks.vector_source_b(src_data1) + s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 3) + insert_null_symbol = dab.insert_null_symbol(5, 3) + dst = blocks.vector_sink_c() + self.tb.connect(src0, s2v, insert_null_symbol, dst) + self.tb.connect(src1, (insert_null_symbol, 1)) + self.tb.run() + result_data = dst.data() + # print expected_result + # print result_data + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa_mp2_decode_bs.py b/python/qa/qa_mp2_decode_bs.py similarity index 100% rename from python/qa_mp2_decode_bs.py rename to python/qa/qa_mp2_decode_bs.py diff --git a/python/qa_mp2_encode_sb.py b/python/qa/qa_mp2_encode_sb.py similarity index 100% rename from python/qa_mp2_encode_sb.py rename to python/qa/qa_mp2_encode_sb.py diff --git a/python/qa_mp4_decode_bs.py b/python/qa/qa_mp4_decode_bs.py similarity index 94% rename from python/qa_mp4_decode_bs.py rename to python/qa/qa_mp4_decode_bs.py index 3819815e..f0b00359 100755 --- a/python/qa_mp4_decode_bs.py +++ b/python/qa/qa_mp4_decode_bs.py @@ -26,6 +26,11 @@ import dab_swig as dab class qa_mp4_decode_bs (gr_unittest.TestCase): + """ + @brief QA for the mp4 decode block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () diff --git a/python/qa_mp4_encode_sb.py b/python/qa/qa_mp4_encode_sb.py similarity index 100% rename from python/qa_mp4_encode_sb.py rename to python/qa/qa_mp4_encode_sb.py diff --git a/python/qa_msc_decode.py b/python/qa/qa_msc_decode.py similarity index 100% rename from python/qa_msc_decode.py rename to python/qa/qa_msc_decode.py diff --git a/python/qa_msc_encode.py b/python/qa/qa_msc_encode.py similarity index 100% rename from python/qa_msc_encode.py rename to python/qa/qa_msc_encode.py diff --git a/python/qa/qa_ofdm_coarse_frequency_correct.py b/python/qa/qa_ofdm_coarse_frequency_correct.py deleted file mode 100755 index c1f106d9..00000000 --- a/python/qa/qa_ofdm_coarse_frequency_correct.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab -import cmath - -class qa_ofdm_coarse_frequency_correct(gr_unittest.TestCase): - """ - @brief QA for the coarse frequency correction class. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_ofdm_coarse_frequency_correct(self): - fft_length = 10 - num_carriers = 2 - cp_length = 3 - src_data0 = [0,1,2,3,4,5,6,7,8,9,1,2,0,5,7,6,0,4,0,6,1,1,1,0.8,0.1,1.3,1,0.7,1,1,0,1,2,3,4,5,6,7,8,9] - expected_result0 = [7,9,5,6,0.8,1.3,3,5] - offset = [3,3,-1,-1,-1,-1,-1,-1] - frame_index = [0,0, 0, 0, 0, 0, 1, 1] - expected_result0 = [complex(expected_result0[i])*cmath.exp(-2j*cmath.pi*offset[i]*cp_length/float(fft_length)*frame_index[i]) for i in range(0,8)] - src_data1 = [1,1,1,0] - expected_result1 = (1,1,1,0) - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, fft_length) - ofdm_coarse_frequency_correct = dab.ofdm_coarse_frequency_correct(fft_length,num_carriers,cp_length) - v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, num_carriers) - dst0 = blocks.vector_sink_c() - dst1 = blocks.vector_sink_b() - self.tb.connect(src0, s2v0, (ofdm_coarse_frequency_correct,0)) - self.tb.connect(src1, (ofdm_coarse_frequency_correct,1)) - self.tb.connect((ofdm_coarse_frequency_correct,0), v2s0, dst0) - self.tb.connect((ofdm_coarse_frequency_correct,1), dst1) - self.tb.run() - result_data0 = dst0.data() - result_data1 = dst1.data() - # print expected_result0 - # print result_data0 - self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 4) - self.assertEqual(result_data1, expected_result1) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_ofdm_ffe_all_in_one.py b/python/qa/qa_ofdm_ffe_all_in_one.py deleted file mode 100755 index c6647f06..00000000 --- a/python/qa/qa_ofdm_ffe_all_in_one.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab -import cmath -from math import pi - -class qa_ofdm_ffs_sample(gr_unittest.TestCase): - """ - @brief Module test for the OFDM ffs sampler with phase calculation. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_ofdm_ffe_all_in_one(self): - symbol_length = 5 - num_symbols = 2 - fft_length = 3 - alpha = 0.1 - src_data0 = [77*cmath.exp(2j*pi*x/20) for x in range(0,20)] - src_data0[4] = 100 # should not matter, as this area of the symbol is not evaluated - src_data0[12:19] = [100] * 7 # should not matter, as only the first two symbols are evaluated - src_data1 = (0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) - d = -2*pi/20 # phase diff between two consective samples - expected_result = (0,0,0,0,0,0,0,0,0,0,0,0,d,d,d,d,d,d,d,d) - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - ffe = dab.ofdm_ffe_all_in_one(symbol_length, fft_length, num_symbols, alpha, 10) - dst0 = blocks.vector_sink_f() - self.tb.connect(src0, (ffe,0)) - self.tb.connect(src1, (ffe,1)) - self.tb.connect(ffe, dst0) - self.tb.run() - result_data0 = dst0.data() - # print expected_result - # print result_data0 - self.assertFloatTuplesAlmostEqual(expected_result, result_data0, 3) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_ofdm_insert_pilot.py b/python/qa/qa_ofdm_insert_pilot.py index 0dc2d39d..c415b4ad 100755 --- a/python/qa/qa_ofdm_insert_pilot.py +++ b/python/qa/qa_ofdm_insert_pilot.py @@ -1,45 +1,46 @@ #!/usr/bin/env python from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab + class qa_ofdm_insert_pilot_vcc(gr_unittest.TestCase): - """ - @brief Module test for the class that inserts the pilot symbol. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_ofdm_insert_pilot_vcc(self): - pilot = [1j,2] - src_data0 = (0,1,2,3,4,5,6,7,8,9,0,1,2,3) - src_data1 = (1,0,0,1,0,1,0) - expected_result0 = (1j,2,0,1,2,3,4,5,1j,2,6,7,8,9,1j,2,0,1,2,3) - expected_result0 = [x+0j for x in expected_result0] - expected_result1 = (1,0,0,0,1,0,0,1,0,0) - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex,2) - ofdm_insert_pilot = dab.ofdm_insert_pilot_vcc(pilot) - v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex,2) - dst0 = blocks.vector_sink_c() - dst1 = blocks.vector_sink_b() - self.tb.connect(src0, s2v0, (ofdm_insert_pilot,0)) - self.tb.connect(src1, (ofdm_insert_pilot,1)) - self.tb.connect((ofdm_insert_pilot,0), v2s0, dst0) - self.tb.connect((ofdm_insert_pilot,1), dst1) - self.tb.run() - result_data0 = dst0.data() - result_data1 = dst1.data() - self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) - self.assertEqual(result_data1, expected_result1) + """ + @brief Module test for the class that inserts the pilot symbol. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_ofdm_insert_pilot_vcc(self): + pilot = [1j, 2] + src_data0 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3) + src_data1 = (1, 0, 0, 1, 0, 1, 0) + expected_result0 = (1j, 2, 0, 1, 2, 3, 4, 5, 1j, 2, 6, 7, 8, 9, 1j, 2, 0, 1, 2, 3) + expected_result0 = [x + 0j for x in expected_result0] + expected_result1 = (1, 0, 0, 0, 1, 0, 0, 1, 0, 0) + src0 = blocks.vector_source_c(src_data0) + src1 = blocks.vector_source_b(src_data1) + s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, 2) + ofdm_insert_pilot = dab.ofdm_insert_pilot_vcc(pilot) + v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, 2) + dst0 = blocks.vector_sink_c() + dst1 = blocks.vector_sink_b() + self.tb.connect(src0, s2v0, (ofdm_insert_pilot, 0)) + self.tb.connect(src1, (ofdm_insert_pilot, 1)) + self.tb.connect((ofdm_insert_pilot, 0), v2s0, dst0) + self.tb.connect((ofdm_insert_pilot, 1), dst1) + self.tb.run() + result_data0 = dst0.data() + result_data1 = dst1.data() + self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) + self.assertEqual(result_data1, expected_result1) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa/qa_ofdm_move_and_insert_zero.py b/python/qa/qa_ofdm_move_and_insert_zero.py index 60c95b38..6ec89a9b 100755 --- a/python/qa/qa_ofdm_move_and_insert_zero.py +++ b/python/qa/qa_ofdm_move_and_insert_zero.py @@ -1,40 +1,41 @@ #!/usr/bin/env python from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab + class qa_ofdm_move_and_insert_zero(gr_unittest.TestCase): - """ - @brief QA for the block that moves the signal to the middle of the band and inserts the zero carrier in the middle. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_ofdm_move_and_insert_zero(self): - num_carriers = 4 - fft_length = 10 - d_zeros_on_left = 3 - src_data0 = range(0,8) - expected_result0 = [0,0,0]+[0,1]+[0]+[2,3]+[0,0]+[0,0,0]+[4,5]+[0]+[6,7]+[0,0] - expected_result0 = [complex(x) for x in expected_result0] - src0 = blocks.vector_source_c(src_data0) - s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, num_carriers) - ofdm_move_and_insert_zero = dab.ofdm_move_and_insert_zero(fft_length,num_carriers) - v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length) - dst0 = blocks.vector_sink_c() - self.tb.connect(src0, s2v0, ofdm_move_and_insert_zero, v2s0, dst0) - self.tb.run() - result_data0 = dst0.data() - # print expected_result0 - # print result_data0 - self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) + """ + @brief QA for the block that moves the signal to the middle of the band and inserts the zero carrier in the middle. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_ofdm_move_and_insert_zero(self): + num_carriers = 4 + fft_length = 10 + d_zeros_on_left = 3 + src_data0 = range(0, 8) + expected_result0 = [0, 0, 0] + [0, 1] + [0] + [2, 3] + [0, 0] + [0, 0, 0] + [4, 5] + [0] + [6, 7] + [0, 0] + expected_result0 = [complex(x) for x in expected_result0] + src0 = blocks.vector_source_c(src_data0) + s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, num_carriers) + ofdm_move_and_insert_zero = dab.ofdm_move_and_insert_zero(fft_length, num_carriers) + v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length) + dst0 = blocks.vector_sink_c() + self.tb.connect(src0, s2v0, ofdm_move_and_insert_zero, v2s0, dst0) + self.tb.run() + result_data0 = dst0.data() + # print expected_result0 + # print result_data0 + self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa_ofdm_synchronization_cvf.py b/python/qa/qa_ofdm_synchronization_cvf.py similarity index 100% rename from python/qa_ofdm_synchronization_cvf.py rename to python/qa/qa_ofdm_synchronization_cvf.py diff --git a/python/qa_prune.py b/python/qa/qa_prune.py similarity index 92% rename from python/qa_prune.py rename to python/qa/qa_prune.py index b2032bf4..aeecd5ec 100755 --- a/python/qa_prune.py +++ b/python/qa/qa_prune.py @@ -24,6 +24,11 @@ import dab_swig as dab class qa_prune (gr_unittest.TestCase): + """ + @brief QA for the prune block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () @@ -40,7 +45,6 @@ def test_001_prune(self): self.tb.connect(src, prune, dst) self.tb.run() result_data = dst.data() - # print result_data self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) diff --git a/python/qa/qa_prune_vectors.py b/python/qa/qa_prune_vectors.py deleted file mode 100755 index 740aa931..00000000 --- a/python/qa/qa_prune_vectors.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks -import dab - -class qa_prune_vectors(gr_unittest.TestCase): - """ - @brief QA for the vector pruning block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_prune_vectors(self): - src_data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] - expected_result = [3,4,8,9,13,14] - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, 5) - prune_vectors = dab.prune_vectors(gr.sizeof_float,5,2,1) - v2s = blocks.vector_to_stream(gr.sizeof_float, 2) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, prune_vectors, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) - - def test_002_prune_vectors(self): - src_data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] - expected_result = [3,4,8,9,13,14] - src = blocks.vector_source_b(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_char, 5) - prune_vectors = dab.prune_vectors(gr.sizeof_char,5,2,1) - v2s = blocks.vector_to_stream(gr.sizeof_char, 2) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, prune_vectors, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa_puncture_bb.py b/python/qa/qa_puncture_bb.py similarity index 94% rename from python/qa_puncture_bb.py rename to python/qa/qa_puncture_bb.py index 3902320e..3f734cf7 100755 --- a/python/qa_puncture_bb.py +++ b/python/qa/qa_puncture_bb.py @@ -24,6 +24,11 @@ import dab_swig as dab class qa_puncture_bb (gr_unittest.TestCase): + """ + @brief QA for the puncture block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () diff --git a/python/qa/qa_puncture_vbb.py b/python/qa/qa_puncture_vbb.py deleted file mode 100755 index fd518edf..00000000 --- a/python/qa/qa_puncture_vbb.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks -import dab -import cmath - -class qa_puncture_vbb(gr_unittest.TestCase): - """ - @brief QA for the puncturing block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_puncture_vbb(self): - src_data = (0,77,78,78,1,80,2,3,4,5,81,82,83,6,84,7,8,9) - punc_seq = (1,0,0,0,1,0,1,1,1) - exp_res = (0,1,2,3,4,5,6,7,8,9) - src = blocks.vector_source_b(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_char, 9) - puncture_vbb = dab.puncture_vbb(punc_seq) - v2s = blocks.vector_to_stream(gr.sizeof_char, 5) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, puncture_vbb, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertEqual(exp_res, result_data) - - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_qpsk_demapper_vcb.py b/python/qa/qa_qpsk_demapper_vcb.py deleted file mode 100755 index 4f2abd26..00000000 --- a/python/qa/qa_qpsk_demapper_vcb.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks -import dab - -class qa_qpsk_demapper_vcb(gr_unittest.TestCase): - """ - @brief QA for the QPSK demapper. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_qpsk_demapper_vcb(self): - src_data = [1+2j,3+1j,-1+1j,-1+1j,-0.0001+1000j,1+1j,1+1j,1+1j] - expected_result = (10,128) - src = blocks.vector_source_c(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, 4) - qpsk_demapper_vcb = dab.qpsk_demapper_vcb(4) - v2s = blocks.vector_to_stream(gr.sizeof_char, 1) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, qpsk_demapper_vcb, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertEqual(expected_result, result_data) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_qpsk_mapper_vbc.py b/python/qa/qa_qpsk_mapper_vbc.py deleted file mode 100755 index 857fea4d..00000000 --- a/python/qa/qa_qpsk_mapper_vbc.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks -import dab -import math - -class qa_qpsk_mapper_vbc(gr_unittest.TestCase): - """ - @brief QA for the QPSK mapper. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_qpsk_mapper_vbc(self): - src_data = [10,128] - expected_result = [1+1j,1+1j,-1+1j,-1+1j,-1+1j,1+1j,1+1j,1+1j] - expected_result = [x/math.sqrt(2) for x in expected_result] - src = blocks.vector_source_b(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_char, 1) - qpsk_mapper_vbc = dab.qpsk_mapper_vbc(4) - v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, 4) - dst = blocks.vector_sink_c() - self.tb.connect(src, s2v, qpsk_mapper_vbc, v2s, dst) - self.tb.run() - result_data = dst.data() - # print expected_result - # print result_data - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa_reed_solomon_decode_bb.py b/python/qa/qa_reed_solomon_decode_bb.py similarity index 95% rename from python/qa_reed_solomon_decode_bb.py rename to python/qa/qa_reed_solomon_decode_bb.py index 15945071..c59185d9 100755 --- a/python/qa_reed_solomon_decode_bb.py +++ b/python/qa/qa_reed_solomon_decode_bb.py @@ -32,8 +32,10 @@ def setUp (self): def tearDown (self): self.tb = None -# insert 5 errors in rs-encoded prbs reference sequence and correct them with rs_decoder def test_001_t(self): + """ + insert 5 errors in rs-encoded prbs reference and correct them with rs_decoder + """ self.prbs = ( 154, 15, 22, 223, 146, 92, 238, 15, 39, 87, 230, 120, 80, 186, 147, 176, 169, 49, 253, 117, 245, 122, 30, 187, 74, 141, 148, 1, 181, 10, 0, 244, 250, 199, 227, 56, 155, 105, 187, 219, 135, 61, 241, 87, 223, 75, 59, 112, 78, @@ -47,7 +49,7 @@ def test_001_t(self): 241, 87, 223, 75, 59, 112, 78, 238, 63, 69, 246, 177, 92, 140, 117, 34, 254, 70, 18, 131, 116, 13, 51, 174, 239, 86, 135, 157, 180, 97, 156, 48, 179, 190, 218, 99, 171, 29, 49, 42, 78, 63, 3, 7, 3, 145, 60, 180, 134, 27, 104, 230, 32, 171, 6, 109, 106, 1, 6, 45, 104, - 206, 138, 38, 107, 242, 128, 228, 215, 34, 43, 109, 122, 92, 195, 54, 105, 246L) + 206, 138, 38, 107, 242, 128, 228, 215, 34, 43, 109, 122, 92, 195, 54, 105, 246) self.src = blocks.vector_source_b(self.corrupted_data) self.rs_decoder = dab.reed_solomon_decode_bb_make(1) diff --git a/python/qa_reed_solomon_encode_bb.py b/python/qa/qa_reed_solomon_encode_bb.py similarity index 92% rename from python/qa_reed_solomon_encode_bb.py rename to python/qa/qa_reed_solomon_encode_bb.py index af2c16d2..bcf619ec 100755 --- a/python/qa_reed_solomon_encode_bb.py +++ b/python/qa/qa_reed_solomon_encode_bb.py @@ -21,21 +21,26 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks -import random import dab_swig as dab class qa_reed_solomon_encode_bb(gr_unittest.TestCase): + """ + @brief QA for the reed solomon encode block + + This class implements a test bench to verify the corresponding C++ class. + """ + def setUp(self): self.tb = gr.top_block() def tearDown(self): self.tb = None - # test_001 encode prbs sequence and check with reference data - # test_002 insert 5 errors in rs-encoded prbs reference sequence and correct them with rs_decoder - def test_001_t(self): + """ + encode prbs sequence and check with reference data + """ self.prbs = ( 154, 15, 22, 223, 146, 92, 238, 15, 39, 87, 230, 120, 80, 186, 147, 176, 169, 49, 253, 117, 245, 122, 30, 187, 74, 141, 148, 1, 181, 10, 0, 244, 250, 199, 227, 56, 155, 105, 187, 219, 135, 61, 241, 87, 223, 75, 59, 112, 78, @@ -61,6 +66,9 @@ def test_001_t(self): def test_002_t(self): + """ + insert 5 errors in rs-encoded prbs reference sequence and correct them with rs_decoder + """ self.prbs = ( 154, 15, 22, 223, 146, 92, 238, 15, 39, 87, 230, 120, 80, 186, 147, 176, 169, 49, 253, 117, 245, 122, 30, 187, 74, 141, 148, 1, 181, 10, 0, 244, 250, 199, 227, 56, 155, 105, 187, 219, 135, 61, 241, 87, 223, 75, 59, 112, 78, diff --git a/python/qa/qa_select_vectors.py b/python/qa/qa_select_vectors.py deleted file mode 100755 index 36c7a610..00000000 --- a/python/qa/qa_select_vectors.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks -import dab - -class qa_select_vectors(gr_unittest.TestCase): - """ - @brief QA for the vector select block - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_select_vectors(self): - skip = 2 - len = 3 - vlen = 2 - src_data = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9) - trig = (0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0) - expected_data = (6,7,8,9,10,11,6,7,8,9) - expected_trig = (1, 0, 0, 1, 0) - src = blocks.vector_source_b(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_char, 2) - select_vectors = dab.select_vectors(gr.sizeof_char,vlen,len,skip) - v2s = blocks.vector_to_stream(gr.sizeof_char, 2) - dst = blocks.vector_sink_b() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors,1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - - def test_002_select_vectors(self): - skip = 2 - len = 3 - vlen = 2 - src_data = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,8,9) - trig = (0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0) - expected_data = (6,7,8,9,10,11,6,7,8,9) - expected_trig = (1, 0, 0, 1, 0) - src = blocks.vector_source_f(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_float, 2) - select_vectors = dab.select_vectors(gr.sizeof_float,vlen,len,skip) - v2s = blocks.vector_to_stream(gr.sizeof_float, 2) - dst = blocks.vector_sink_f() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors,1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - -if __name__ == '__main__': - gr_unittest.main() - diff --git a/python/qa/qa_sum_phasor_trig_vcc.py b/python/qa/qa_sum_phasor_trig_vcc.py index aaeb7cd6..6ee5aa78 100755 --- a/python/qa/qa_sum_phasor_trig_vcc.py +++ b/python/qa/qa_sum_phasor_trig_vcc.py @@ -1,67 +1,69 @@ #!/usr/bin/env python from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab + class qa_sum_phasor_trig_vcc(gr_unittest.TestCase): - """ - @brief QA for the phase summation class. + """ + @brief QA for the phase summation class. - This class implements a test bench to verify the corresponding C++ class. - """ + This class implements a test bench to verify the corresponding C++ class. + """ - def setUp(self): - self.tb = gr.top_block() + def setUp(self): + self.tb = gr.top_block() - def tearDown(self): - self.tb = None + def tearDown(self): + self.tb = None - def test_001_sum_phasor_trig_vcc(self): - src_data0 = (1,1j,1,1j,1j,1j,-1, 1j, 1,1j,1,1j) - src_data1 = (0, 1, 0, 0, 1, 0) - expected_result0 = (0,0, 1,1j,1j,-1,-1j,-1j,1,1j,1,-1) - expected_result0 = [x+0j for x in expected_result0] - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex,2) - sum_phasor_trig_vcc = dab.sum_phasor_trig_vcc(2) - v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex,2) - dst0 = blocks.vector_sink_c() - dst1 = blocks.vector_sink_b() - self.tb.connect(src0, s2v0, (sum_phasor_trig_vcc,0)) - self.tb.connect(src1, (sum_phasor_trig_vcc,1)) - self.tb.connect((sum_phasor_trig_vcc,0), v2s0, dst0) - self.tb.connect((sum_phasor_trig_vcc,1), dst1) - self.tb.run() - result_data0 = dst0.data() - result_data1 = dst1.data() - # print expected_result0 - # print result_data0 - self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) - self.assertEqual(result_data1, src_data1) + def test_001_sum_phasor_trig_vcc(self): + src_data0 = (1, 1j, 1, 1j, 1j, 1j, -1, 1j, 1, 1j, 1, 1j) + src_data1 = (0, 1, 0, 0, 1, 0) + expected_result0 = (0, 0, 1, 1j, 1j, -1, -1j, -1j, 1, 1j, 1, -1) + expected_result0 = [x + 0j for x in expected_result0] + src0 = blocks.vector_source_c(src_data0) + src1 = blocks.vector_source_b(src_data1) + s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, 2) + sum_phasor_trig_vcc = dab.sum_phasor_trig_vcc(2) + v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, 2) + dst0 = blocks.vector_sink_c() + dst1 = blocks.vector_sink_b() + self.tb.connect(src0, s2v0, (sum_phasor_trig_vcc, 0)) + self.tb.connect(src1, (sum_phasor_trig_vcc, 1)) + self.tb.connect((sum_phasor_trig_vcc, 0), v2s0, dst0) + self.tb.connect((sum_phasor_trig_vcc, 1), dst1) + self.tb.run() + result_data0 = dst0.data() + result_data1 = dst1.data() + # print expected_result0 + # print result_data0 + self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) + self.assertEqual(result_data1, src_data1) - def test_002_sum_phasor_trig_vcc(self): - src_data0 = (1,1j,-1,1,1)*50 # try it multiple times to decect problems when leaving the function in between - src_data1 = (1,0,0,1,0)*50 - expected_result0 = (1,1j,-1j,1,1)*50 - expected_result0 = [x+0j for x in expected_result0] - src0 = blocks.vector_source_c(src_data0) - src1 = blocks.vector_source_b(src_data1) - s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex,1) - sum_phasor_trig_vcc = dab.sum_phasor_trig_vcc(1) - v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex,1) - dst0 = blocks.vector_sink_c() - dst1 = blocks.vector_sink_b() - self.tb.connect(src0, s2v0, (sum_phasor_trig_vcc,0)) - self.tb.connect(src1, (sum_phasor_trig_vcc,1)) - self.tb.connect((sum_phasor_trig_vcc,0), v2s0, dst0) - self.tb.connect((sum_phasor_trig_vcc,1), dst1) - self.tb.run() - result_data0 = dst0.data() - result_data1 = dst1.data() - self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) - self.assertEqual(result_data1, src_data1) + def test_002_sum_phasor_trig_vcc(self): + src_data0 = (1, 1j, -1, 1, + 1) * 50 # try it multiple times to decect problems when leaving the function in between + src_data1 = (1, 0, 0, 1, 0) * 50 + expected_result0 = (1, 1j, -1j, 1, 1) * 50 + expected_result0 = [x + 0j for x in expected_result0] + src0 = blocks.vector_source_c(src_data0) + src1 = blocks.vector_source_b(src_data1) + s2v0 = blocks.stream_to_vector(gr.sizeof_gr_complex, 1) + sum_phasor_trig_vcc = dab.sum_phasor_trig_vcc(1) + v2s0 = blocks.vector_to_stream(gr.sizeof_gr_complex, 1) + dst0 = blocks.vector_sink_c() + dst1 = blocks.vector_sink_b() + self.tb.connect(src0, s2v0, (sum_phasor_trig_vcc, 0)) + self.tb.connect(src1, (sum_phasor_trig_vcc, 1)) + self.tb.connect((sum_phasor_trig_vcc, 0), v2s0, dst0) + self.tb.connect((sum_phasor_trig_vcc, 1), dst1) + self.tb.run() + result_data0 = dst0.data() + result_data1 = dst1.data() + self.assertComplexTuplesAlmostEqual(expected_result0, result_data0, 6) + self.assertEqual(result_data1, src_data1) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa_synchronization_ff.py b/python/qa/qa_synchronization_ff.py similarity index 100% rename from python/qa_synchronization_ff.py rename to python/qa/qa_synchronization_ff.py diff --git a/python/qa_time_deinterleave_ff.py b/python/qa/qa_time_deinterleave_ff.py similarity index 96% rename from python/qa_time_deinterleave_ff.py rename to python/qa/qa_time_deinterleave_ff.py index cc76e00d..5e3c4e38 100755 --- a/python/qa_time_deinterleave_ff.py +++ b/python/qa/qa_time_deinterleave_ff.py @@ -24,6 +24,11 @@ import dab_swig as dab class qa_time_deinterleave_ff (gr_unittest.TestCase): + """ + @brief QA for the time deinterleave block + + This class implements a test bench to verify the corresponding C++ class. + """ def setUp (self): self.tb = gr.top_block () diff --git a/python/qa/qa_unpuncture_vff.py b/python/qa/qa_unpuncture_vff.py index 28fdb063..f3de6abb 100755 --- a/python/qa/qa_unpuncture_vff.py +++ b/python/qa/qa_unpuncture_vff.py @@ -1,50 +1,51 @@ #!/usr/bin/env python from gnuradio import gr, gr_unittest, blocks -import dab +import dab_swig as dab import cmath + class qa_unpuncture_vff(gr_unittest.TestCase): - """ - @brief QA for the unpuncturing block. - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_unpuncture_vff(self): - src_data = (0,1,2,3,4,5,6,7,8,9) - punc_seq = (1,0,0,0,1,0,1,1,1) - exp_res = (0,77,77,77,1,77,2,3,4,5,77,77,77,6,77,7,8,9) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, 5) - unpuncture_vff = dab.unpuncture_vff(punc_seq, 77) - v2s = blocks.vector_to_stream(gr.sizeof_float, 9) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, unpuncture_vff, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(exp_res, result_data) - - def test_002_unpuncture_vff(self): - src_data = (0,1,2,3,4,5,6,7,8,9) - punc_seq = (1,0,0,0,1,0,1,1,1) - exp_res = (0,0,0,0,1,0,2,3,4,5,0,0,0,6,0,7,8,9) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, 5) - unpuncture_vff = dab.unpuncture_vff(punc_seq) - v2s = blocks.vector_to_stream(gr.sizeof_float, 9) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, unpuncture_vff, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(exp_res, result_data) + """ + @brief QA for the unpuncturing block. + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_unpuncture_vff(self): + src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + punc_seq = (1, 0, 0, 0, 1, 0, 1, 1, 1) + exp_res = (0, 77, 77, 77, 1, 77, 2, 3, 4, 5, 77, 77, 77, 6, 77, 7, 8, 9) + src = blocks.vector_source_f(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_float, 5) + unpuncture_vff = dab.unpuncture_vff(punc_seq, 77) + v2s = blocks.vector_to_stream(gr.sizeof_float, 9) + dst = blocks.vector_sink_f() + self.tb.connect(src, s2v, unpuncture_vff, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(exp_res, result_data) + + def test_002_unpuncture_vff(self): + src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + punc_seq = (1, 0, 0, 0, 1, 0, 1, 1, 1) + exp_res = (0, 0, 0, 0, 1, 0, 2, 3, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9) + src = blocks.vector_source_f(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_float, 5) + unpuncture_vff = dab.unpuncture_vff(punc_seq) + v2s = blocks.vector_to_stream(gr.sizeof_float, 9) + dst = blocks.vector_sink_f() + self.tb.connect(src, s2v, unpuncture_vff, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(exp_res, result_data) -if __name__ == '__main__': - gr_unittest.main() +if __name__ == '__main__': + gr_unittest.main() diff --git a/python/qa_valve_ff.py b/python/qa/qa_valve_ff.py similarity index 100% rename from python/qa_valve_ff.py rename to python/qa/qa_valve_ff.py diff --git a/python/qa_mapper_bc.py b/python/qa_mapper_bc.py deleted file mode 100755 index 434b4f25..00000000 --- a/python/qa_mapper_bc.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab -from math import sqrt - -class qa_mapper_bc (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_mapper_bc(self): - data = (1, 0, 1, 0, 1, 1, 0, 0) - expected_result = (-1 - 1j, 1 - 1j, -1 + 1j, 1 + 1j) - expected_result = [x / sqrt(2) for x in expected_result] - src = blocks.vector_source_b_make(data) - map = dab.mapper_bc_make(4) - dst = blocks.vector_sink_c() - self.tb.connect(src, map, dst) - self.tb.run() - result_data = dst.data() - #print expected_result - #print result_data - self.assertComplexTuplesAlmostEqual(expected_result, result_data, 6) - - -if __name__ == '__main__': - gr_unittest.run(qa_mapper_bc, "qa_mapper_bc.xml") diff --git a/python/qa_select_subch_vfvf.py b/python/qa_select_subch_vfvf.py deleted file mode 100755 index d591af35..00000000 --- a/python/qa_select_subch_vfvf.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab - -class qa_select_subch_vfvf (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_select_vectors(self): - vlen_in = 2 - vlen_out = 6 - total_size = 8 - address = 1 - src_data = ( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) - expected_data = (2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen_in) - select_subch = dab.select_subch_vfvf_make(vlen_in, vlen_out, address, total_size) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen_out) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, select_subch, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual2(result_data, expected_data) - - def test_002_select_vectors(self): - vlen_in = 2 - vlen_out = 10 - total_size = 10 - address = 3 - src_data = ( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0) - expected_data = (6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen_in) - select_subch = dab.select_subch_vfvf_make(vlen_in, vlen_out, address, total_size) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen_out) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, select_subch, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual2(result_data, expected_data) - - def test_003_select_vectors(self): - vlen_in = 4 - vlen_out = 4 - total_size = 1 - address = 0 - src_data = ( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19) - expected_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen_in) - select_subch = dab.select_subch_vfvf_make(vlen_in, vlen_out, address, total_size) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen_out) - dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, select_subch, v2s, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual2(result_data, expected_data) - -if __name__ == '__main__': - gr_unittest.run(qa_select_subch_vfvf, "qa_select_subch_vfvf.xml") diff --git a/python/qa_select_vectors.py b/python/qa_select_vectors.py deleted file mode 100755 index 4da6e1a3..00000000 --- a/python/qa_select_vectors.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest, blocks -import dab_swig as dab - - -class qa_select_vectors(gr_unittest.TestCase): - """ - @brief QA for the vector select block - - This class implements a test bench to verify the corresponding C++ class. - """ - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001_select_vectors(self): - skip = 2 - len = 3 - vlen = 2 - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - trig = (0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 ) - expected_data = (6, 7, 8, 9, 10, 11, 6, 7, 8, 9) - expected_trig = (1, 0, 0, 1, 0) - src = blocks.vector_source_b(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_char, 2) - select_vectors = dab.select_vectors(gr.sizeof_char, vlen, len, skip) - v2s = blocks.vector_to_stream(gr.sizeof_char, 2) - dst = blocks.vector_sink_b() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors, 1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - - def test_002_select_vectors(self): - skip = 2 - len = 3 - vlen = 2 - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - trig = (0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 ) - expected_data = (6, 7, 8, 9, 10, 11, 6, 7, 8, 9) - expected_trig = (1, 0, 0, 1, 0) - src = blocks.vector_source_f(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_float, 2) - select_vectors = dab.select_vectors(gr.sizeof_float, vlen, len, skip) - v2s = blocks.vector_to_stream(gr.sizeof_float, 2) - dst = blocks.vector_sink_f() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors, 1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - - def test_003_select_vectors(self): - skip = 3 - len = 2 - vlen = 3 - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - trig = (1, 0, 0, 0, 0, 0, 0, 0, 1 ) - expected_data = (9, 10, 11, 12, 13, 14) - expected_trig = (1, 0 ) - src = blocks.vector_source_f(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen) - select_vectors = dab.select_vectors(gr.sizeof_float, vlen, len, skip) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen) - dst = blocks.vector_sink_f() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors, 1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - - def test_004_select_vectors(self): - skip = 3 - len = 3 - vlen = 3 - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - trig = (1, 1, 0, 0, 0, 0, 1, 0, 1 ) - expected_data = (12, 13, 14, 15, 0, 1) - expected_trig = (1, 0 ) - src = blocks.vector_source_f(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen) - select_vectors = dab.select_vectors(gr.sizeof_float, vlen, len, skip) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen) - dst = blocks.vector_sink_f() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors, 1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - - def test_005_select_vectors(self): - skip = 3 - len = 2 - vlen = 3 - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - trig = (1, 1, 0, 0, 1, 0, 1, 0, 0 ) - expected_data = () - expected_trig = () - src = blocks.vector_source_f(src_data) - trigsrc = blocks.vector_source_b(trig) - s2v = blocks.stream_to_vector(gr.sizeof_float, vlen) - select_vectors = dab.select_vectors(gr.sizeof_float, vlen, len, skip) - v2s = blocks.vector_to_stream(gr.sizeof_float, vlen) - dst = blocks.vector_sink_f() - trigdst = blocks.vector_sink_b() - self.tb.connect(src, s2v, select_vectors, v2s, dst) - self.tb.connect(trigsrc, (select_vectors, 1), trigdst) - self.tb.run() - result_data = dst.data() - result_trig = trigdst.data() - # print expected_result - # print result_data - self.assertFloatTuplesAlmostEqual(expected_data, result_data) - self.assertEqual(expected_trig, result_trig) - -if __name__ == '__main__': - gr_unittest.main() diff --git a/python/qa_time_interleave_bb.py b/python/qa_time_interleave_bb.py deleted file mode 100755 index c0a8aa2f..00000000 --- a/python/qa_time_interleave_bb.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab - -class qa_time_interleave_bb (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_t (self): - vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) - expected_result = (1, 0, 3, 0, 5, 0, 7, 2, 9, 4, 11, 6, 13, 8, 15, 10, 17, 12) - src = blocks.vector_source_b(vector01, True) - s2v = blocks.stream_to_vector(gr.sizeof_char, 6) - time_interleaver = dab.time_interleave_bb(6, [0, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_char, 6) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char*6, 3), v2s, dst) - self.tb.run() - result = dst.data() - #print result - self.assertEqual(expected_result, result) - - def test_002_t(self): - vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) - expected_result = (1,0,0,0, 5, 0, 0, 4, 9,0,3,8, 13, 2, 7, 12) - src = blocks.vector_source_b(vector01, True) - s2v = blocks.stream_to_vector(gr.sizeof_char, 4) - time_interleaver = dab.time_interleave_bb(4, [0, 3, 2, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_char, 4) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char * 4, 4), v2s, dst) - self.tb.run() - result = dst.data() - #print result - self.assertEqual(expected_result, result) - - def test_003_t(self): - vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32) - expected_result = (0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 11, 4, 0, 0, 15, 8, 1, 0, 19, 12, 5, 0, 23, 16, 9, 2, 27, 20, 13, 6, 31, 24) - src = blocks.vector_source_b(vector01, True) - s2v = blocks.stream_to_vector(gr.sizeof_char, 8) - time_interleaver = dab.time_interleave_bb(8, [2, 3, 0, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_char, 8) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char * 8, 4), v2s, dst) - self.tb.run() - result = dst.data() - #print result - self.assertEqual(expected_result, result) - - def test_004_t(self): - vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36) - expected_result = (0, 0, 3, 0, 0, 0, 7, 0, 0, 0, 11, 4, 0, 0, 15, 8, 1, 0, 19, 12, 5, 0, 23, 16, 9, 2, 27, 20, 13, 6, 31, 24) - src = blocks.vector_source_b(vector01, True) - s2v = blocks.stream_to_vector(gr.sizeof_char, 8) - time_interleaver = dab.time_interleave_bb(8, [2, 3, 0, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_char, 8) - dst = blocks.vector_sink_b() - self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char * 8, 4), v2s, dst) - self.tb.run() - result = dst.data() - #print result - self.assertEqual(expected_result, result) - -if __name__ == '__main__': - gr_unittest.run(qa_time_interleave_bb, "qa_time_interleave_bb.xml") diff --git a/python/qa_unpuncture_ff.py b/python/qa_unpuncture_ff.py deleted file mode 100755 index bcf2bf51..00000000 --- a/python/qa_unpuncture_ff.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab - -class qa_unpuncture_ff (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_unpuncture_ff(self): - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - punc_seq = (1, 0, 0, 0, 1, 0, 1, 1, 1) - exp_res = (0, 77, 77, 77, 1, 77, 2, 3, 4, 5, 77, 77, 77, 6, 77, 7, 8, 9) - src = blocks.vector_source_f(src_data) - unpuncture_ff = dab.unpuncture_ff(punc_seq, 77) - dst = blocks.vector_sink_f() - self.tb.connect(src, unpuncture_ff, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(exp_res, result_data) - - def test_002_unpuncture_ff(self): - src_data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - punc_seq = (1, 0, 0, 0, 1, 0, 1, 1, 1) - exp_res = (0, 0, 0, 0, 1, 0, 2, 3, 4, 5, 0, 0, 0, 6, 0, 7, 8, 9) - src = blocks.vector_source_f(src_data) - unpuncture_ff = dab.unpuncture_ff(punc_seq, 0) - dst = blocks.vector_sink_f() - self.tb.connect(src, unpuncture_ff, dst) - self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(exp_res, result_data) - - -if __name__ == '__main__': - gr_unittest.run(qa_unpuncture_ff, "qa_unpuncture_ff.xml") diff --git a/python/test_ofdm_sync_dab.py b/python/test_ofdm_sync_dab.py deleted file mode 100755 index 913ee883..00000000 --- a/python/test_ofdm_sync_dab.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# test_ofdm_sync_dab.py - test the DAB OFDM synchronisation -# -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -from gnuradio import gr, blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -from ofdm_sync_dab import ofdm_sync_dab -import parameters -import random -import os - -class dab_ofdm_sync_test(gr.top_block): - """ - @brief Test application for the synchronisation block. - """ - def __init__(self): - gr.top_block.__init__(self) - - usage = "%prog: [options] samples_file" - parser = OptionParser(option_class=eng_option, usage=usage) - (options, args) = parser.parse_args () - if len(args)<1: - # print "using gaussian noise as source" - # self.sigsrc = gr.noise_source_c(gr.GR_GAUSSIAN,10e6) - print "using repeating random vector as source" - self.sigsrc = blocks.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True) - self.src = blocks.throttle( gr.sizeof_gr_complex,2048000) - self.connect(self.sigsrc, self.src) - else: - filename = args[0] - print "using samples from file " + filename - self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) - - dp = parameters.dab_parameters(1) - rp = parameters.receiver_parameters(1) - self.sync_dab = ofdm_sync_dab(dp, rp, False) - self.nop0 = blocks.nop(gr.sizeof_gr_complex) - self.nop1 = blocks.nop(gr.sizeof_char) - self.connect(self.src, self.sync_dab, self.nop0) - self.connect((self.sync_dab,1), self.nop1) - -if __name__=='__main__': - try: - dab_ofdm_sync_test().run() - except KeyboardInterrupt: - pass diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 9bed8ad6..853935eb 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -10,9 +10,7 @@ %{ #include "dab/diff_phasor_vcc.h" #include "dab/frequency_interleaver_vcc.h" -#include "dab/qpsk_demapper_vcb.h" #include "dab/complex_to_interleaved_float_vcf.h" -#include "dab/select_vectors.h" #include "dab/unpuncture_vff.h" #include "dab/fib_sink_vb.h" #include "dab/ofdm_insert_pilot_vcc.h" @@ -53,15 +51,11 @@ GR_SWIG_BLOCK_MAGIC2(dab, diff_phasor_vcc); %include "dab/frequency_interleaver_vcc.h" GR_SWIG_BLOCK_MAGIC2(dab, frequency_interleaver_vcc); -%include "dab/qpsk_demapper_vcb.h" -GR_SWIG_BLOCK_MAGIC2(dab, qpsk_demapper_vcb); + %include "dab/complex_to_interleaved_float_vcf.h" GR_SWIG_BLOCK_MAGIC2(dab, complex_to_interleaved_float_vcf); -%include "dab/select_vectors.h" -GR_SWIG_BLOCK_MAGIC2(dab, select_vectors); - %include "dab/unpuncture_vff.h" GR_SWIG_BLOCK_MAGIC2(dab, unpuncture_vff); From 5e33d328f38aebf11f9f93655ba81e96cf827518 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 8 Jan 2018 11:11:10 +0100 Subject: [PATCH 109/135] add qa test for qpsk_mapper_vbvc block --- python/CMakeLists.txt | 1 + python/qa/qa_qpsk_mapper_vbvc.py | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 python/qa/qa_qpsk_mapper_vbvc.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 4ac6b5da..90f54027 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -63,6 +63,7 @@ include(GrTest) set(GR_TEST_TARGET_DEPS gnuradio-dab) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) +GR_ADD_TEST(qa_qpsk_mapper_vbvc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_qpsk_mapper_vbvc.py) GR_ADD_TEST(qa_ofdm_insert_pilot.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_ofdm_insert_pilot.py) GR_ADD_TEST(qa_sum_phasor_trig_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_sum_phasor_trig_vcc.py) GR_ADD_TEST(qa_frequency_interleaver_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_frequency_interleaver_vcc.py) diff --git a/python/qa/qa_qpsk_mapper_vbvc.py b/python/qa/qa_qpsk_mapper_vbvc.py new file mode 100644 index 00000000..4f85fd35 --- /dev/null +++ b/python/qa/qa_qpsk_mapper_vbvc.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import math +import dab_swig as dab + + +class qa_qpsk_mapper_vbvc(gr_unittest.TestCase): + """ + @brief QA for the qpsk mapper block + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_qpsk_mapper_vbvc(self): + src_data = (31, 255) + vector_length = 8 + SQRT2 = 1.0/math.sqrt(2) + expected_result = (SQRT2 - SQRT2*1j, SQRT2 - SQRT2*1j, SQRT2 - SQRT2*1j, -SQRT2 - SQRT2*1j, -SQRT2 - SQRT2*1j, + -SQRT2 - SQRT2*1j, -SQRT2 - SQRT2*1j, -SQRT2 - SQRT2*1j) + src = blocks.vector_source_b(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_char, vector_length/4) + mapper = dab.qpsk_mapper_vbvc_make(vector_length) + v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, vector_length) + dst = blocks.vector_sink_c() + self.tb.connect(src, s2v, mapper, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) + + def test_002_qpsk_mapper_vbvc(self): + src_data = (0, 3) + vector_length = 8 + SQRT2 = 1.0/math.sqrt(2) + expected_result = (SQRT2 + SQRT2*1j, SQRT2 + SQRT2*1j, SQRT2 + SQRT2*1j, SQRT2 + SQRT2*1j, SQRT2 + SQRT2*1j, + SQRT2 + SQRT2*1j, SQRT2 - SQRT2*1j, SQRT2 - SQRT2*1j) + src = blocks.vector_source_b(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_char, vector_length/4) + mapper = dab.qpsk_mapper_vbvc_make(vector_length) + v2s = blocks.vector_to_stream(gr.sizeof_gr_complex, vector_length) + dst = blocks.vector_sink_c() + self.tb.connect(src, s2v, mapper, v2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) + + +if __name__ == '__main__': + gr_unittest.run(qa_qpsk_mapper_vbvc, "qa_qpsk_mapper_vbvc.xml") \ No newline at end of file From c9b7e20dc748ab78d45f67e5b1829cefdf5a5d06 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 8 Jan 2018 14:54:42 +0100 Subject: [PATCH 110/135] add qa test for time_interleave_bb block --- python/CMakeLists.txt | 2 +- python/qa/qa_qpsk_mapper_vbvc.py | 19 ++++++++ python/qa/qa_time_deinterleave_ff.py | 12 ----- python/qa/qa_time_interleave_bb.py | 68 ++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 python/qa/qa_time_interleave_bb.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 90f54027..1c2a8bca 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -77,6 +77,7 @@ GR_ADD_TEST(qa_puncture_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/q GR_ADD_TEST(qa_mp4_encode_sb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_encode_sb.py) GR_ADD_TEST(qa_reed_solomon_encode_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_encode_bb.py) GR_ADD_TEST(qa_msc_encode.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_msc_encode.py) +GR_ADD_TEST(qa_time_interleave_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_time_interleave_bb.py) GR_ADD_TEST(qa_dab_transmission_frame_mux_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_dab_transmission_frame_mux_bb.py) GR_ADD_TEST(qa_diff_phasor_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_diff_phasor_vcc.py) @@ -88,7 +89,6 @@ GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_ GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_decode_bb.py) GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_decode_bs.py) -#GR_ADD_TEST(qa_time_interleave_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_time_interleave_bb.py) #GR_ADD_TEST(qa_select_subch_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_select_subch_vfvf.py) #GR_ADD_TEST(qa_prune ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_prune.py) #GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) diff --git a/python/qa/qa_qpsk_mapper_vbvc.py b/python/qa/qa_qpsk_mapper_vbvc.py index 4f85fd35..104d8fb6 100644 --- a/python/qa/qa_qpsk_mapper_vbvc.py +++ b/python/qa/qa_qpsk_mapper_vbvc.py @@ -1,4 +1,23 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# from gnuradio import gr, gr_unittest from gnuradio import blocks diff --git a/python/qa/qa_time_deinterleave_ff.py b/python/qa/qa_time_deinterleave_ff.py index 5e3c4e38..bca6b0ef 100755 --- a/python/qa/qa_time_deinterleave_ff.py +++ b/python/qa/qa_time_deinterleave_ff.py @@ -41,14 +41,11 @@ def test_001_t(self): expected_result = (0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) src = blocks.vector_source_b(vector01, True) b2f = blocks.char_to_float_make() - s2v = blocks.stream_to_vector(gr.sizeof_float, 6) time_deinterleaver = dab.time_deinterleave_ff_make(6, [0, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_float, 6) dst = blocks.vector_sink_f() self.tb.connect(src, b2f, time_deinterleaver, blocks.head_make(gr.sizeof_float, 6*3), dst) self.tb.run() result = dst.data() - #print result self.assertEqual(expected_result, result) def test_002_t(self): @@ -56,14 +53,11 @@ def test_002_t(self): expected_result = (0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 1, 12, 3, 0) src = blocks.vector_source_b(vector01, True) b2f = blocks.char_to_float_make() - s2v = blocks.stream_to_vector(gr.sizeof_float, 4) time_deinterleaver = dab.time_deinterleave_ff_make(4, [0, 3, 2, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_float, 4) dst = blocks.vector_sink_f() self.tb.connect(src, b2f, time_deinterleaver, blocks.head_make(gr.sizeof_float, 4*4), dst) self.tb.run() result = dst.data() - #print result self.assertEqual(expected_result, result) def test_003_t(self): @@ -71,14 +65,11 @@ def test_003_t(self): expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 7, 8, 0, 0, 11, 12, 0, 0, 15, 16, 0, 0, 19,20, 0, 0, 23, 24, 0, 0) src = blocks.vector_source_b(vector01, True) b2f = blocks.char_to_float_make() - s2v = blocks.stream_to_vector(gr.sizeof_float, 8) time_deinterleaver = dab.time_deinterleave_ff_make(8, [2, 3, 0, 1]) - v2s = blocks.vector_to_stream(gr.sizeof_float, 8) dst = blocks.vector_sink_f() self.tb.connect(src, b2f, time_deinterleaver, blocks.head_make(gr.sizeof_float, 8*4), dst) self.tb.run() result = dst.data() - #print result self.assertEqual(expected_result, result) def test_004_t(self): @@ -86,14 +77,11 @@ def test_004_t(self): expected_result = (0,0,0,4,0,0,0,8,0,0,0,12,0,0,0,16,0,0,3,4,0,0,7,8,0,0,11,12,0,0,15,16) src = blocks.vector_source_b(vector01, True) b2f = blocks.char_to_float_make() - s2v = blocks.stream_to_vector(gr.sizeof_float, 16) time_deinterleaver = dab.time_deinterleave_ff_make(16, [0, 1, 2, 4]) - v2s = blocks.vector_to_stream(gr.sizeof_float, 16) dst = blocks.vector_sink_f() self.tb.connect(src, b2f, time_deinterleaver, blocks.head_make(gr.sizeof_float, 16*2), dst) self.tb.run() result = dst.data() - #print result self.assertEqual(expected_result, result) if __name__ == '__main__': diff --git a/python/qa/qa_time_interleave_bb.py b/python/qa/qa_time_interleave_bb.py new file mode 100644 index 00000000..92b2e5cf --- /dev/null +++ b/python/qa/qa_time_interleave_bb.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab_swig as dab + +class qa_time_interleave_bb (gr_unittest.TestCase): + """ + @brief QA for the time interleave block + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t(self): + vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) + expected_result = (1, 0, 3, 0, 5, 0, 7, 2, 9, 4, 11, 6, 13, 8, 15, 10, 17, 12) + src = blocks.vector_source_b(vector01, True) + s2v = blocks.stream_to_vector_make(gr.sizeof_char, 6) + time_interleaver = dab.time_interleave_bb_make(6, [0, 1]) + v2s = blocks.vector_to_stream_make(gr.sizeof_char, 6) + dst = blocks.vector_sink_b() + self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char*6, 3), v2s, dst) + self.tb.run() + result = dst.data() + print result + self.assertEqual(expected_result, result) + + def test_002_t(self): + vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) + expected_result = (1, 0, 0, 0, 5, 0, 0, 4, 9, 0, 3, 8, 13, 2, 7, 12) + src = blocks.vector_source_b(vector01, True) + s2v = blocks.stream_to_vector(gr.sizeof_char, 4) + time_interleaver = dab.time_interleave_bb_make(4, [0, 3, 2, 1]) + v2s = blocks.vector_to_stream(gr.sizeof_char, 4) + dst = blocks.vector_sink_b() + self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char*4, 4), v2s, dst) + self.tb.run() + result = dst.data() + #print result + self.assertEqual(expected_result, result) + +if __name__ == '__main__': + gr_unittest.run(qa_time_interleave_bb, "qa_time_interleave_bb.xml") From 8acc439334277de62c7a533fb9116976d8995c42 Mon Sep 17 00:00:00 2001 From: luca Date: Mon, 8 Jan 2018 15:45:45 +0100 Subject: [PATCH 111/135] add qa test for selct_cus_vfvf block and wrap up --- grc/CMakeLists.txt | 4 +- ...t_cus_vcvc.xml => dab_select_cus_vfvf.xml} | 6 +- grc/dab_select_subch_vfvf.xml | 37 -------- include/dab/CMakeLists.txt | 3 +- .../{select_cus_vcvc.h => select_cus_vfvf.h} | 16 ++-- include/dab/select_subch_vfvf.h | 64 ------------- lib/CMakeLists.txt | 3 +- ...s_vcvc_impl.cc => select_cus_vfvf_impl.cc} | 18 ++-- ...cus_vcvc_impl.h => select_cus_vfvf_impl.h} | 14 +-- lib/select_subch_vfvf_impl.cc | 94 ------------------- lib/select_subch_vfvf_impl.h | 63 ------------- python/CMakeLists.txt | 2 +- python/msc_decode.py | 2 +- python/qa/qa_select_cus_vfvf.py | 55 +++++++++++ python/qa/qa_time_interleave_bb.py | 2 - swig/dab_swig.i | 9 +- 16 files changed, 90 insertions(+), 302 deletions(-) rename grc/{dab_select_cus_vcvc.xml => dab_select_cus_vfvf.xml} (82%) delete mode 100644 grc/dab_select_subch_vfvf.xml rename include/dab/{select_cus_vcvc.h => select_cus_vfvf.h} (80%) delete mode 100644 include/dab/select_subch_vfvf.h rename lib/{select_cus_vcvc_impl.cc => select_cus_vfvf_impl.cc} (84%) rename lib/{select_cus_vcvc_impl.h => select_cus_vfvf_impl.h} (81%) delete mode 100644 lib/select_subch_vfvf_impl.cc delete mode 100644 lib/select_subch_vfvf_impl.h create mode 100644 python/qa/qa_select_cus_vfvf.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 87a309e3..86417485 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -21,7 +21,6 @@ install(FILES dab_diff_phasor_vcc.xml dab_frequency_interleaver_vcc.xml dab_complex_to_interleaved_float_vcf.xml - dab_fic_decode.xml dab_ofdm_demod.xml dab_ofdm_mod.xml dab_unpuncture_vff.xml @@ -35,7 +34,6 @@ install(FILES dab_crc16_bb.xml dab_msc_decode.xml dab_fib_source_b.xml - dab_select_subch_vfvf.xml dab_unpuncture_ff.xml dab_prune.xml dab_firecode_check_bb.xml @@ -61,6 +59,6 @@ install(FILES dab_demux_cc.xml dab_ofdm_demod_cc.xml dab_fic_decode_vc.xml - dab_select_cus_vcvc.xml + dab_select_cus_vfvf.xml dab_qpsk_mapper_vbvc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/dab_select_cus_vcvc.xml b/grc/dab_select_cus_vfvf.xml similarity index 82% rename from grc/dab_select_cus_vcvc.xml rename to grc/dab_select_cus_vfvf.xml index 7daf120b..ac1d248b 100644 --- a/grc/dab_select_cus_vcvc.xml +++ b/grc/dab_select_cus_vfvf.xml @@ -1,9 +1,9 @@ - Select cus vcvc - dab_select_cus_vcvc + Select CUs + dab_select_cus_vfvf DAB import dab - dab.select_cus_vcvc($vlen, $frame_len, $address, $size) + dab.select_cus_vfvf($vlen, $frame_len, $address, $size) Vlen vlen diff --git a/grc/dab_select_subch_vfvf.xml b/grc/dab_select_subch_vfvf.xml deleted file mode 100644 index f096e6a5..00000000 --- a/grc/dab_select_subch_vfvf.xml +++ /dev/null @@ -1,37 +0,0 @@ - - Select subchannel - dab_select_subch_vfvf - [DAB] - import dab - dab.select_subch_vfvf($vlen_in, $vlen_out, $address, $total_size) - - Vector length in - vlen_in - raw - - - Vector length out - vlen_out - raw - - - Address - address - raw - - - Total size - total_size - raw - - - in - float - $vlen_in - - - out - float - $vlen_out - - diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 459846bb..ab6de39e 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -35,7 +35,6 @@ install(FILES time_deinterleave_ff.h crc16_bb.h fib_source_b.h - select_subch_vfvf.h unpuncture_ff.h prune.h firecode_check_bb.h @@ -55,6 +54,6 @@ install(FILES ofdm_coarse_frequency_correction_vcvc.h frequency_deinterleave_cc.h demux_cc.h - select_cus_vcvc.h + select_cus_vfvf.h qpsk_mapper_vbvc.h DESTINATION include/dab ) diff --git a/include/dab/select_cus_vcvc.h b/include/dab/select_cus_vfvf.h similarity index 80% rename from include/dab/select_cus_vcvc.h rename to include/dab/select_cus_vfvf.h index 228f7a75..2aa47713 100644 --- a/include/dab/select_cus_vcvc.h +++ b/include/dab/select_cus_vfvf.h @@ -19,8 +19,8 @@ */ -#ifndef INCLUDED_DAB_SELECT_CUS_VCVC_H -#define INCLUDED_DAB_SELECT_CUS_VCVC_H +#ifndef INCLUDED_DAB_SELECT_CUS_VFVF_H +#define INCLUDED_DAB_SELECT_CUS_VFVF_H #include #include @@ -33,17 +33,17 @@ namespace gr { * \ingroup dab * */ - class DAB_API select_cus_vcvc : virtual public gr::block + class DAB_API select_cus_vfvf : virtual public gr::block { public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; /*! - * \brief Return a shared_ptr to a new instance of dab::select_cus_vcvc. + * \brief Return a shared_ptr to a new instance of dab::select_cus_vfvf. * - * To avoid accidental use of raw pointers, dab::select_cus_vcvc's + * To avoid accidental use of raw pointers, dab::select_cus_vfvf's * constructor is in a private implementation - * class. dab::select_cus_vcvc::make is the public interface for + * class. dab::select_cus_vfvf::make is the public interface for * creating new instances. */ static sptr make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); @@ -52,5 +52,5 @@ namespace gr { } // namespace dab } // namespace gr -#endif /* INCLUDED_DAB_SELECT_CUS_VCVC_H */ +#endif /* INCLUDED_DAB_SELECT_CUS_VFVF_H */ diff --git a/include/dab/select_subch_vfvf.h b/include/dab/select_subch_vfvf.h deleted file mode 100644 index 949b5337..00000000 --- a/include/dab/select_subch_vfvf.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_SELECT_SUBCH_VFVF_H -#define INCLUDED_DAB_SELECT_SUBCH_VFVF_H - -#include -#include - -namespace gr { - namespace dab { - -/*! \brief selects vectors out of input vectors that belong to one subchannel - * - * input: float vector of size vlen_in - * - * output: float vector of size vlen_out - * - * selects vlen_out/vlen_in vectors of total_size input vectors, beginning at address - * - * @param vlen_in Length of input vector in floats. - * @param vlen_out Length of output vector in floats. - * @param address number of input vector where output the output vector begins - * @param total_size size in input vectors of one frame (dumped after output vector is selected) - */ - class DAB_API select_subch_vfvf : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::select_subch_vfvf. - * - * To avoid accidental use of raw pointers, dab::select_subch_vfvf's - * constructor is in a private implementation - * class. dab::select_subch_vfvf::make is the public interface for - * creating new instances. - */ - static sptr make(unsigned int vlen_in, unsigned int vlen_out, unsigned int address, unsigned int total_size); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_SELECT_SUBCH_VFVF_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 11033789..2aaee427 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -39,7 +39,7 @@ list(APPEND dab_sources time_deinterleave_ff_impl.cc crc16_bb_impl.cc fib_source_b_impl.cc - select_subch_vfvf_impl.cc + select_cus_vfvf_impl.cc unpuncture_ff_impl.cc prune_impl.cc firecode-checker.cpp @@ -84,7 +84,6 @@ list(APPEND dab_sources ofdm_coarse_frequency_correction_vcvc_impl.cc frequency_deinterleave_cc_impl.cc demux_cc_impl.cc - select_cus_vcvc_impl.cc qpsk_mapper_vbvc_impl.cc ) diff --git a/lib/select_cus_vcvc_impl.cc b/lib/select_cus_vfvf_impl.cc similarity index 84% rename from lib/select_cus_vcvc_impl.cc rename to lib/select_cus_vfvf_impl.cc index e49c2515..3a73f899 100644 --- a/lib/select_cus_vcvc_impl.cc +++ b/lib/select_cus_vfvf_impl.cc @@ -23,23 +23,23 @@ #endif #include -#include "select_cus_vcvc_impl.h" +#include "select_cus_vfvf_impl.h" namespace gr { namespace dab { - select_cus_vcvc::sptr - select_cus_vcvc::make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) + select_cus_vfvf::sptr + select_cus_vfvf::make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) { return gnuradio::get_initial_sptr - (new select_cus_vcvc_impl(vlen, frame_len, address, size)); + (new select_cus_vfvf_impl(vlen, frame_len, address, size)); } /* * The private constructor */ - select_cus_vcvc_impl::select_cus_vcvc_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) - : gr::block("select_cus_vcvc", + select_cus_vfvf_impl::select_cus_vfvf_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) + : gr::block("select_cus_vfvf", gr::io_signature::make(1, 1, vlen * sizeof(float)), gr::io_signature::make(1, 1, vlen * sizeof(float))), d_vlen(vlen), @@ -51,18 +51,18 @@ namespace gr { /* * Our virtual destructor. */ - select_cus_vcvc_impl::~select_cus_vcvc_impl() + select_cus_vfvf_impl::~select_cus_vfvf_impl() { } void - select_cus_vcvc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) + select_cus_vfvf_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } int - select_cus_vcvc_impl::general_work (int noutput_items, + select_cus_vfvf_impl::general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) diff --git a/lib/select_cus_vcvc_impl.h b/lib/select_cus_vfvf_impl.h similarity index 81% rename from lib/select_cus_vcvc_impl.h rename to lib/select_cus_vfvf_impl.h index 2b548e08..982ce570 100644 --- a/lib/select_cus_vcvc_impl.h +++ b/lib/select_cus_vfvf_impl.h @@ -18,15 +18,15 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H -#define INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H +#ifndef INCLUDED_DAB_SELECT_CUS_VFVF_IMPL_H +#define INCLUDED_DAB_SELECT_CUS_VFVF_IMPL_H -#include +#include namespace gr { namespace dab { - class select_cus_vcvc_impl : public select_cus_vcvc + class select_cus_vfvf_impl : public select_cus_vfvf { private: unsigned int d_vlen; @@ -35,8 +35,8 @@ namespace gr { unsigned int d_size; public: - select_cus_vcvc_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); - ~select_cus_vcvc_impl(); + select_cus_vfvf_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); + ~select_cus_vfvf_impl(); // Where all the action really happens void forecast (int noutput_items, gr_vector_int &ninput_items_required); @@ -50,5 +50,5 @@ namespace gr { } // namespace dab } // namespace gr -#endif /* INCLUDED_DAB_SELECT_CUS_VCVC_IMPL_H */ +#endif /* INCLUDED_DAB_SELECT_CUS_VFVF_IMPL_H */ diff --git a/lib/select_subch_vfvf_impl.cc b/lib/select_subch_vfvf_impl.cc deleted file mode 100644 index 61a8ce51..00000000 --- a/lib/select_subch_vfvf_impl.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "select_subch_vfvf_impl.h" - -namespace gr { - namespace dab { - - select_subch_vfvf::sptr - select_subch_vfvf::make(unsigned int vlen_in, unsigned int vlen_out, unsigned int address, - unsigned int total_size) - { - return gnuradio::get_initial_sptr - (new select_subch_vfvf_impl(vlen_in, vlen_out, address, total_size)); - } - - /* - * The private constructor - */ - select_subch_vfvf_impl::select_subch_vfvf_impl(unsigned int vlen_in, unsigned int vlen_out, - unsigned int address, unsigned int total_size) - : gr::block("select_subch_vfvf", - gr::io_signature::make(1, 1, sizeof(float) * vlen_in), - gr::io_signature::make(1, 1, sizeof(float) * vlen_out)), - d_vlen_in(vlen_in), d_vlen_out(vlen_out), d_address(address), d_total_size(total_size) - { - //sanity check - if (vlen_out % vlen_in != 0) - throw std::invalid_argument("vlen_out no multiple of vlen_in"); - if (address * vlen_in + vlen_out > total_size * vlen_in) - throw std::out_of_range("vlen_out too long or address wrong"); - - set_relative_rate(1 / total_size); - } - - /* - * Our virtual destructor. - */ - select_subch_vfvf_impl::~select_subch_vfvf_impl() - { - } - - void - select_subch_vfvf_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items * d_total_size; - } - - int - select_subch_vfvf_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) { - memcpy(&out[i * d_vlen_out], &in[d_vlen_in * (i * d_total_size + d_address)], - d_vlen_out * sizeof(float)); - } - // Tell runtime system how many input items we consumed on - // each input stream. - consume_each(noutput_items * d_total_size); - - // Tell runtime system how many output items we produced. - return noutput_items; - } - - } /* namespace dab */ -} /* namespace gr */ - diff --git a/lib/select_subch_vfvf_impl.h b/lib/select_subch_vfvf_impl.h deleted file mode 100644 index cb46e3ce..00000000 --- a/lib/select_subch_vfvf_impl.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_SELECT_SUBCH_VFVF_IMPL_H -#define INCLUDED_DAB_SELECT_SUBCH_VFVF_IMPL_H - -#include - -namespace gr { - namespace dab { -/*! \brief selects vectors out of input vectors that belong to one subchannel - * - * input: float vector of size vlen_in - * - * output: float vector of size vlen_out - * - * selects vlen_out/vlen_in vectors of total_size input vectors, beginning at address - * - * @param vlen_in Length of input vector in floats. - * @param vlen_out Length of output vector in floats. - * @param address number of input vector where output the output vector begins - * @param total_size size in input vectors of one frame (dumped after output vector is selected) - */ - class select_subch_vfvf_impl : public select_subch_vfvf - { - private: - unsigned int d_vlen_in, d_vlen_out, d_address, d_total_size; - - public: - select_subch_vfvf_impl(unsigned int vlen_in, unsigned int vlen_out, unsigned int address, unsigned int total_size); - ~select_subch_vfvf_impl(); - - // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_SELECT_SUBCH_VFVF_IMPL_H */ - diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 1c2a8bca..ef64385a 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -82,6 +82,7 @@ GR_ADD_TEST(qa_dab_transmission_frame_mux_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CUR GR_ADD_TEST(qa_diff_phasor_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_diff_phasor_vcc.py) GR_ADD_TEST(qa_complex_to_interleaved_float_vcf.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_complex_to_interleaved_float_vcf.py) +GR_ADD_TEST(qa_select_cus_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_select_cus_vfvf.py) GR_ADD_TEST(qa_unpuncture_vff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_unpuncture_vff.py) GR_ADD_TEST(qa_prune.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_prune.py) GR_ADD_TEST(qa_fib_sink_vb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_fib_sink_vb.py) @@ -89,7 +90,6 @@ GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_ GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_decode_bb.py) GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_decode_bs.py) -#GR_ADD_TEST(qa_select_subch_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_select_subch_vfvf.py) #GR_ADD_TEST(qa_prune ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_prune.py) #GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) #GR_ADD_TEST(qa_dabplus_audio_decoder_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dabplus_audio_decoder_ff.py) diff --git a/python/msc_decode.py b/python/msc_decode.py index 2d057c62..da17137d 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -83,7 +83,7 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F # repartition vectors in capacity units (CUs) and select a sub-channel self.v2s_repart_to_cus = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.num_carriers*2) self.s2v_repart_to_cus = blocks.stream_to_vector_make(gr.sizeof_float, self.dp.msc_cu_size) - self.select_subch = dab.select_cus_vcvc_make(self.dp.msc_cu_size, self.dp.num_cus, self.address, self.size) + self.select_subch = dab.select_cus_vfvf_make(self.dp.msc_cu_size, self.dp.num_cus, self.address, self.size) # time deinterleaving self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size) diff --git a/python/qa/qa_select_cus_vfvf.py b/python/qa/qa_select_cus_vfvf.py new file mode 100644 index 00000000..f150c484 --- /dev/null +++ b/python/qa/qa_select_cus_vfvf.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import dab + +class qa_select_cus_vfvf (gr_unittest.TestCase): + """ + @brief QA for the select cus block + + This class implements a test bench to verify the corresponding C++ class. + """ + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t(self): + vector01 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) + expected_result = (1, 2, 3, 4, 9, 10, 11, 12) + src = blocks.vector_source_b(vector01, True) + b2f = blocks.char_to_float_make() + s2v = blocks.stream_to_vector_make(gr.sizeof_float, 4) + select_cus = dab.select_cus_vfvf_make(4, 2, 0, 1) + v2s = blocks.vector_to_stream_make(gr.sizeof_float, 4) + dst = blocks.vector_sink_f() + self.tb.connect(src, b2f, s2v, select_cus, blocks.head_make(gr.sizeof_float*4, 2), v2s, dst) + self.tb.run() + result = dst.data() + print result + self.assertEqual(expected_result, result) + +if __name__ == '__main__': + gr_unittest.run(qa_select_cus_vfvf, "qa_select_cus_vfvf.xml") diff --git a/python/qa/qa_time_interleave_bb.py b/python/qa/qa_time_interleave_bb.py index 92b2e5cf..ebb94d49 100644 --- a/python/qa/qa_time_interleave_bb.py +++ b/python/qa/qa_time_interleave_bb.py @@ -47,7 +47,6 @@ def test_001_t(self): self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char*6, 3), v2s, dst) self.tb.run() result = dst.data() - print result self.assertEqual(expected_result, result) def test_002_t(self): @@ -61,7 +60,6 @@ def test_002_t(self): self.tb.connect(src, s2v, time_interleaver, blocks.head_make(gr.sizeof_char*4, 4), v2s, dst) self.tb.run() result = dst.data() - #print result self.assertEqual(expected_result, result) if __name__ == '__main__': diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 853935eb..c5ad836f 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -21,7 +21,6 @@ #include "dab/time_deinterleave_ff.h" #include "dab/crc16_bb.h" #include "dab/fib_source_b.h" -#include "dab/select_subch_vfvf.h" #include "dab/unpuncture_ff.h" #include "dab/prune.h" #include "dab/firecode_check_bb.h" @@ -41,7 +40,7 @@ #include "dab/ofdm_coarse_frequency_correction_vcvc.h" #include "dab/frequency_deinterleave_cc.h" #include "dab/demux_cc.h" -#include "dab/select_cus_vcvc.h" +#include "dab/select_cus_vfvf.h" #include "dab/qpsk_mapper_vbvc.h" %} @@ -78,8 +77,6 @@ GR_SWIG_BLOCK_MAGIC2(dab, time_deinterleave_ff); GR_SWIG_BLOCK_MAGIC2(dab, crc16_bb); %include "dab/fib_source_b.h" GR_SWIG_BLOCK_MAGIC2(dab, fib_source_b); -%include "dab/select_subch_vfvf.h" -GR_SWIG_BLOCK_MAGIC2(dab, select_subch_vfvf); %include "dab/unpuncture_ff.h" GR_SWIG_BLOCK_MAGIC2(dab, unpuncture_ff); %include "dab/prune.h" @@ -126,7 +123,7 @@ GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); %include "dab/demux_cc.h" GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); -%include "dab/select_cus_vcvc.h" -GR_SWIG_BLOCK_MAGIC2(dab, select_cus_vcvc); +%include "dab/select_cus_vfvf.h" +GR_SWIG_BLOCK_MAGIC2(dab, select_cus_vfvf); %include "dab/qpsk_mapper_vbvc.h" GR_SWIG_BLOCK_MAGIC2(dab, qpsk_mapper_vbvc); From 52ade54870e0b32896f88d974ca16b07d77ee1ef Mon Sep 17 00:00:00 2001 From: luca Date: Tue, 9 Jan 2018 18:32:11 +0100 Subject: [PATCH 112/135] delete redundant files and wrap up --- grc/CMakeLists.txt | 5 - grc/dab_detect_null.xml | 23 -- grc/dab_frequency_deinterleave_cc.xml | 20 -- grc/dab_mapper_bc.xml | 20 -- grc/dab_ofdm_demod.xml | 160 ----------- grc/dab_synchronization_ff.xml | 30 -- include/dab/CMakeLists.txt | 3 - include/dab/frequency_deinterleave_cc.h | 56 ---- include/dab/mapper_bc.h | 56 ---- .../ofdm_coarse_frequency_correction_vcvc.h | 17 +- include/dab/ofdm_synchronization_cvf.h | 9 +- include/dab/select_cus_vfvf.h | 9 +- include/dab/synchronization_ff.h | 56 ---- lib/CMakeLists.txt | 3 - ...dab_correct_individual_phase_offset_vff.cc | 101 ------- lib/dab_correct_individual_phase_offset_vff.h | 88 ------ lib/dab_ofdm_ffs_sample.cc | 132 --------- lib/dab_ofdm_ffs_sample.h | 75 ----- lib/demux_cc_impl.cc | 14 +- lib/firecode_check_bb_impl.cc | 5 +- lib/frequency_deinterleave_cc_impl.cc | 84 ------ lib/frequency_deinterleave_cc_impl.h | 52 ---- lib/mapper_bc_impl.cc | 100 ------- lib/mapper_bc_impl.h | 60 ---- lib/mp4_decode_bs_impl.cc | 15 +- ...m_coarse_frequency_correction_vcvc_impl.cc | 41 +-- lib/ofdm_synchronization_cvf_impl.cc | 48 ++-- lib/qpsk_mapper_vbvc_impl.cc | 3 +- lib/synchronization_ff_impl.cc | 266 ------------------ lib/synchronization_ff_impl.h | 79 ------ python/CMakeLists.txt | 2 - python/ofdm_mod_bc.py | 182 ------------ swig/dab_swig.i | 11 +- 33 files changed, 74 insertions(+), 1751 deletions(-) delete mode 100644 grc/dab_detect_null.xml delete mode 100644 grc/dab_frequency_deinterleave_cc.xml delete mode 100644 grc/dab_mapper_bc.xml delete mode 100644 grc/dab_ofdm_demod.xml delete mode 100644 grc/dab_synchronization_ff.xml delete mode 100644 include/dab/frequency_deinterleave_cc.h delete mode 100644 include/dab/mapper_bc.h delete mode 100644 include/dab/synchronization_ff.h delete mode 100644 lib/dab_correct_individual_phase_offset_vff.cc delete mode 100644 lib/dab_correct_individual_phase_offset_vff.h delete mode 100644 lib/dab_ofdm_ffs_sample.cc delete mode 100644 lib/dab_ofdm_ffs_sample.h delete mode 100644 lib/frequency_deinterleave_cc_impl.cc delete mode 100644 lib/frequency_deinterleave_cc_impl.h delete mode 100644 lib/mapper_bc_impl.cc delete mode 100644 lib/mapper_bc_impl.h delete mode 100644 lib/synchronization_ff_impl.cc delete mode 100644 lib/synchronization_ff_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 86417485..6430e6f4 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -17,11 +17,9 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. install(FILES - dab_detect_null.xml dab_diff_phasor_vcc.xml dab_frequency_interleaver_vcc.xml dab_complex_to_interleaved_float_vcf.xml - dab_ofdm_demod.xml dab_ofdm_mod.xml dab_unpuncture_vff.xml dab_fib_sink_vb.xml @@ -43,7 +41,6 @@ install(FILES dab_dab_transmission_frame_mux_bb.xml dab_transmitter_c.xml dab_conv_encoder_bb.xml - dab_mapper_bc.xml dab_mp2_decode_bs.xml dab_mp4_decode_bs.xml dab_reed_solomon_decode_bb.xml @@ -52,10 +49,8 @@ install(FILES dab_mp4_encode_sb.xml dab_mp2_encode_sb.xml dab_valve_ff.xml - dab_synchronization_ff.xml dab_ofdm_synchronization_cvf.xml dab_ofdm_coarse_frequency_correction_vcvc.xml - dab_frequency_deinterleave_cc.xml dab_demux_cc.xml dab_ofdm_demod_cc.xml dab_fic_decode_vc.xml diff --git a/grc/dab_detect_null.xml b/grc/dab_detect_null.xml deleted file mode 100644 index adf206ef..00000000 --- a/grc/dab_detect_null.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - Detect NULL - dab_detect_null - [DAB] - import dab - dab.detect_null($length, False) - - NULL Len. in samples - length - int - - - - in - complex - - - - out - byte - - diff --git a/grc/dab_frequency_deinterleave_cc.xml b/grc/dab_frequency_deinterleave_cc.xml deleted file mode 100644 index 70a5979c..00000000 --- a/grc/dab_frequency_deinterleave_cc.xml +++ /dev/null @@ -1,20 +0,0 @@ - - Frequency deinterleave cc - dab_frequency_deinterleave_cc - DAB - import dab - dab.frequency_deinterleave_cc($interleaving_sequence) - - Interleaving_sequence - interleaving_sequence - raw - - - in - complex - - - out - complex - - diff --git a/grc/dab_mapper_bc.xml b/grc/dab_mapper_bc.xml deleted file mode 100644 index de83bc2f..00000000 --- a/grc/dab_mapper_bc.xml +++ /dev/null @@ -1,20 +0,0 @@ - - DAB: QPSK Mapper - dab_mapper_bc - [DAB] - import dab - dab.mapper_bc($symbol_length) - - Frame length - symbol_length - int - - - in - byte - - - out - complex - - diff --git a/grc/dab_ofdm_demod.xml b/grc/dab_ofdm_demod.xml deleted file mode 100644 index 8038c7dd..00000000 --- a/grc/dab_ofdm_demod.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - DAB: OFDM Demodulator old - dab_ofdm_demod - [DAB] - import dab - dab.ofdm_demod( - dab.parameters.dab_parameters( - mode=$dab_mode, - sample_rate=$samp_rate, - verbose=False - ), - dab.parameters.receiver_parameters( - mode=$dab_mode, - softbits=$soft_bits.soft, - input_fft_filter=$input_fft, - autocorrect_sample_rate=$autocorr_sr, - sample_rate_correction_factor=1, - verbose=False, - correct_ffe=$correct_ffe, - equalize_magnitude=$eq_mag - ) - ) - - - DAB Mode - dab_mode - 1 - enum - - - - - - - Sampling Rate - samp_rate - samp_rate - int - - - - Input FFT Filter - input_fft - True - enum - - - - - - Auto-corr. samplerate - autocorr_sr - True - enum - - - - - - Fine-Freq. corr. - correct_ffe - True - enum - - - - - - Equalize Magnitude - eq_mag - True - enum - - - - - - Soft Bits - soft_bits - soft - enum - - - - 1 <= $dab_mode <= 4 - - in - complex - - - dat - $soft_bits.type - $dab_mode.vlensize / $soft_bits.vlenfrac - - - sync - byte - - - Demodulates a whole DAB signal. - Output vector size depends on selected mode: - Mode I: 1536 complex samples or 384 bytes - Mode II: 384 complex samples or 96 bytes - Mode III: 192 complex samples or 48 bytes - Mode IV: 768 complex samples or 192 bytes - - diff --git a/grc/dab_synchronization_ff.xml b/grc/dab_synchronization_ff.xml deleted file mode 100644 index db7512be..00000000 --- a/grc/dab_synchronization_ff.xml +++ /dev/null @@ -1,30 +0,0 @@ - - Synchronization ff - dab_synchronization_ff - DAB - import dab - dab.synchronization_ff($symbol_length, $cyclic_prefix_length, $num_ofdm_symbols) - - Symbol_length - symbol_length - int - - - Cyclic_prefix_length - cyclic_prefix_length - int - - - Num_ofdm_symbols - num_ofdm_symbols - int - - - in - complex - - - out - float - - diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index ab6de39e..939bd7c5 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -41,7 +41,6 @@ install(FILES puncture_bb.h dab_transmission_frame_mux_bb.h conv_encoder_bb.h - mapper_bc.h mp2_decode_bs.h mp4_decode_bs.h reed_solomon_decode_bb.h @@ -49,10 +48,8 @@ install(FILES mp4_encode_sb.h mp2_encode_sb.h valve_ff.h - synchronization_ff.h ofdm_synchronization_cvf.h ofdm_coarse_frequency_correction_vcvc.h - frequency_deinterleave_cc.h demux_cc.h select_cus_vfvf.h qpsk_mapper_vbvc.h DESTINATION include/dab diff --git a/include/dab/frequency_deinterleave_cc.h b/include/dab/frequency_deinterleave_cc.h deleted file mode 100644 index 12e3911e..00000000 --- a/include/dab/frequency_deinterleave_cc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H -#define INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H - -#include -#include - -namespace gr { - namespace dab { - - /*! - * \brief <+description of block+> - * \ingroup dab - * - */ - class DAB_API frequency_deinterleave_cc : virtual public gr::sync_block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::frequency_deinterleave_cc. - * - * To avoid accidental use of raw pointers, dab::frequency_deinterleave_cc's - * constructor is in a private implementation - * class. dab::frequency_deinterleave_cc::make is the public interface for - * creating new instances. - */ - static sptr make(const std::vector &interleaving_sequence); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_H */ - diff --git a/include/dab/mapper_bc.h b/include/dab/mapper_bc.h deleted file mode 100644 index 06c71007..00000000 --- a/include/dab/mapper_bc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_MAPPER_BC_H -#define INCLUDED_DAB_MAPPER_BC_H - -#include -#include - -namespace gr { - namespace dab { - - /*! \brief QPSK mapper according to the DAB standard ETSI EN 300 401 V1.4.1, clause 14.5 - - * \ingroup dab - * - */ - class DAB_API mapper_bc : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::mapper_bc. - * - * To avoid accidental use of raw pointers, dab::mapper_bc's - * constructor is in a private implementation - * class. dab::mapper_bc::make is the public interface for - * creating new instances. - */ - static sptr make(int symbol_length); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_MAPPER_BC_H */ - diff --git a/include/dab/ofdm_coarse_frequency_correction_vcvc.h b/include/dab/ofdm_coarse_frequency_correction_vcvc.h index f074ee94..69928f4c 100644 --- a/include/dab/ofdm_coarse_frequency_correction_vcvc.h +++ b/include/dab/ofdm_coarse_frequency_correction_vcvc.h @@ -1,17 +1,22 @@ /* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * +/* + * 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * The content of this class is adopted from ODR-DabMod and written into a GNU Radio OutOfTree block. + * + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty + the Queen in Right of Canada (Communications Research Center Canada) + See https://github.com/Opendigitalradio/ODR-DabMod for licensing information of ODR-DabMod. + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -29,7 +34,7 @@ namespace gr { namespace dab { /*! - * \brief <+description of block+> + * \brief coarse frequency correction in mulitple of the sub-carrier spacing * \ingroup dab * */ diff --git a/include/dab/ofdm_synchronization_cvf.h b/include/dab/ofdm_synchronization_cvf.h index 9e4d0ab3..1445f3c6 100644 --- a/include/dab/ofdm_synchronization_cvf.h +++ b/include/dab/ofdm_synchronization_cvf.h @@ -1,6 +1,11 @@ /* -*- c++ -*- */ /* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * The content of this class is adopted from ODR-DabMod and written into a GNU Radio OutOfTree block. + * + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty + the Queen in Right of Canada (Communications Research Center Canada) + See https://github.com/Opendigitalradio/ODR-DabMod for licensing information of ODR-DabMod. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +34,7 @@ namespace gr { namespace dab { /*! - * \brief <+description of block+> + * \brief fine time and frequency offset measurement and correction * \ingroup dab * */ diff --git a/include/dab/select_cus_vfvf.h b/include/dab/select_cus_vfvf.h index 2aa47713..21ec00c8 100644 --- a/include/dab/select_cus_vfvf.h +++ b/include/dab/select_cus_vfvf.h @@ -1,6 +1,11 @@ /* -*- c++ -*- */ /* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. + * 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * The content of this class is adopted from ODR-DabMod and written into a GNU Radio OutOfTree block. + * + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Her Majesty + the Queen in Right of Canada (Communications Research Center Canada) + See https://github.com/Opendigitalradio/ODR-DabMod for licensing information of ODR-DabMod. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +34,7 @@ namespace gr { namespace dab { /*! - * \brief <+description of block+> + * \brief selects a number of CUs (capacity units) of a vector * \ingroup dab * */ diff --git a/include/dab/synchronization_ff.h b/include/dab/synchronization_ff.h deleted file mode 100644 index d3e1171c..00000000 --- a/include/dab/synchronization_ff.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 <+YOU OR YOUR COMPANY+>. - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_SYNCHRONIZATION_FF_H -#define INCLUDED_DAB_SYNCHRONIZATION_FF_H - -#include -#include - -namespace gr { - namespace dab { - - /*! - * \brief <+description of block+> - * \ingroup dab - * - */ - class DAB_API synchronization_ff : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::synchronization_ff. - * - * To avoid accidental use of raw pointers, dab::synchronization_ff's - * constructor is in a private implementation - * class. dab::synchronization_ff::make is the public interface for - * creating new instances. - */ - static sptr make(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_SYNCHRONIZATION_FF_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 2aaee427..0dbaece0 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -47,7 +47,6 @@ list(APPEND dab_sources puncture_bb_impl.cc dab_transmission_frame_mux_bb_impl.cc conv_encoder_bb_impl.cc - mapper_bc_impl.cc mp2_decode_bs_impl.cc mp4_decode_bs_impl.cc reed_solomon_decode_bb_impl.cc @@ -79,10 +78,8 @@ list(APPEND dab_sources ${LIBTOOLAME-DAB_SOURCE_DIR}/encode_new.c ${LIBTOOLAME-DAB_SOURCE_DIR}/portableio.c valve_ff_impl.cc - synchronization_ff_impl.cc ofdm_synchronization_cvf_impl.cc ofdm_coarse_frequency_correction_vcvc_impl.cc - frequency_deinterleave_cc_impl.cc demux_cc_impl.cc qpsk_mapper_vbvc_impl.cc ) diff --git a/lib/dab_correct_individual_phase_offset_vff.cc b/lib/dab_correct_individual_phase_offset_vff.cc deleted file mode 100644 index 74e527c8..00000000 --- a/lib/dab_correct_individual_phase_offset_vff.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#define M_PI_HALF M_PI/2 -#define M_PI_QUARTER M_PI/4 - -/* - * Create a new instance of dab_correct_individual_phase_offset_vff and return - * a boost shared_ptr. This is effectively the public constructor. - */ -dab_correct_individual_phase_offset_vff_sptr -dab_make_correct_individual_phase_offset_vff (unsigned int vlen, float alpha) -{ - return gnuradio::get_initial_sptr (new dab_correct_individual_phase_offset_vff (vlen, alpha)); -} - -dab_correct_individual_phase_offset_vff::dab_correct_individual_phase_offset_vff (unsigned int vlen, float alpha) : - gr_sync_block ("correct_individual_phase_offset_vff", - gr_make_io_signature (1, 1, sizeof(float)*vlen), - gr_make_io_signature (1, 1, sizeof(float)*vlen)), - d_vlen(vlen), d_alpha(alpha), d_debug(0) -{ - d_offset_estimation = new float[vlen]; - for (unsigned int i=0;iM_PI_HALF) // poor man's modulo pi/2 - ival-=M_PI_HALF; - while (ival<0) - ival+=M_PI_HALF; - d_offset_estimation[j] = (1-d_alpha)*d_offset_estimation[j] + d_alpha*(ival-M_PI_QUARTER); - out[0] = in[0] - d_offset_estimation[j]; - out++; - in++; - } - } - - /* debug */ - /* - d_debug++; - if (d_debug==10 || d_debug==50 || d_debug==100||d_debug==500) { - fprintf(stderr, "individual_phase_offset=["); - for (unsigned int i=0; i - -class dab_correct_individual_phase_offset_vff; - -/* - * We use boost::shared_ptr's instead of raw pointers for all access - * to gr_blocks (and many other data structures). The shared_ptr gets - * us transparent reference counting, which greatly simplifies storage - * management issues. This is especially helpful in our hybrid - * C++ / Python system. - * - * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm - * - * As a convention, the _sptr suffix indicates a boost::shared_ptr - */ -typedef boost::shared_ptr dab_correct_individual_phase_offset_vff_sptr; - -/*! - * \brief Return a shared_ptr to a new instance of dab_correct_individual_phase_offset_vff. - * - * To avoid accidental use of raw pointers, dab_correct_individual_phase_offset_vff's - * constructor is private. dab_make_correct_individual_phase_offset_vff is the public - * interface for creating new instances. - */ -dab_correct_individual_phase_offset_vff_sptr -dab_make_correct_individual_phase_offset_vff (unsigned int vlen, float alpha); - -/*! - * \brief Corrects the individual phase offset of each subcarrier by doing an estimation of the error. - * \ingroup DAB - * - * \param vlen length of the vector - * \param alpha adaptation speed fatcor: corr = (1-alpha)*corr + alpha*new_val) - * - * input: float vector stream with phase vectors of symbols - * output: float vector stream with corrected phases - * - * Note: This block only makes sense as long as the offset of the majority of - * the samples is smaller than pi/4 - */ -class dab_correct_individual_phase_offset_vff : public gr_sync_block -{ - private: - // The friend declaration allows dab_make_correct_individual_phase_offset_vff to - // access the private constructor. - - friend dab_correct_individual_phase_offset_vff_sptr - dab_make_correct_individual_phase_offset_vff (unsigned int vlen, float alpha); - - dab_correct_individual_phase_offset_vff (unsigned int vlen, float alpha); // private constructor - - unsigned int d_vlen; - float d_alpha; - float * d_offset_estimation; - unsigned int d_debug; - - public: - ~dab_correct_individual_phase_offset_vff (void); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_CORRECT_INDIVIDUAL_PHASE_OFFSET_VFF_H */ diff --git a/lib/dab_ofdm_ffs_sample.cc b/lib/dab_ofdm_ffs_sample.cc deleted file mode 100644 index fba0754f..00000000 --- a/lib/dab_ofdm_ffs_sample.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include - -/* - * Create a new instance of dab_ofdm_ffs_sample and return - * a boost shared_ptr. This is effectively the public constructor. - */ -dab_ofdm_ffs_sample_sptr -dab_make_ofdm_ffs_sample (unsigned int symbol_length, unsigned int fft_length, unsigned int num_symbols, float alpha, unsigned int sample_rate) -{ - return gnuradio::get_initial_sptr (new dab_ofdm_ffs_sample (symbol_length, fft_length, num_symbols, alpha, sample_rate)); -} - -dab_ofdm_ffs_sample::dab_ofdm_ffs_sample (unsigned int symbol_length, unsigned int fft_length, unsigned int num_symbols, float alpha, unsigned int sample_rate) : - gr_sync_block ("ofdm_ffs_sample", - gr_make_io_signature2 (2, 2, sizeof(float), sizeof(char)), - gr_make_io_signature (1, 1, sizeof(float))), - d_symbol_length(symbol_length), d_fft_length(fft_length), d_num_symbols(num_symbols), d_alpha(alpha), d_sample_rate(sample_rate), d_cur_symbol(num_symbols), d_cur_sample(0), d_ffs_error_sum(0), d_estimated_error(0), d_estimated_error_per_sample(0) -{ -} - - - -int -dab_ofdm_ffs_sample::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *iptr = (const float *) input_items[0]; - const char *trigger = (const char *) input_items[1]; - float *optr = (float *) output_items[0]; - - float new_estimate; - - for (int i=0; i0) { - if (d_ffs_error_sum < 0 && new_estimate > 0 && new_estimate - d_ffs_error_sum/d_cur_symbol > M_PI) - new_estimate -= 2*M_PI; - else if (d_ffs_error_sum > 0 && new_estimate < 0 && d_ffs_error_sum/d_cur_symbol - new_estimate > M_PI) - new_estimate += 2*M_PI; - } - - d_ffs_error_sum += new_estimate; - } - - if (d_cur_symbol == d_num_symbols-1) { /* update estimated error */ - d_ffs_error_sum /= d_num_symbols; /* average */ - - /* if the offset is close to half of the subcarrier bandwidth, it may - * jump from some large positive value to some large negative value. - * with averaging, this is a problem - we have to detect it (although - * it really only makes a difference when the offset is very close to - * half the subcarrier bandwidth) - - * note: if there is an offset of one subcarrier bandwidth, the phase - * offset in fft_length samples is 2pi */ - if (d_estimated_error < 0 && d_ffs_error_sum > 0 && d_ffs_error_sum - d_estimated_error > M_PI) { - fprintf(stderr, "ofdm_ffs_sample: switch detected: neg -> pos\n"); - d_estimated_error += 2*M_PI; - } else if (d_estimated_error > 0 && d_ffs_error_sum < 0 && d_estimated_error - d_ffs_error_sum > M_PI) { - fprintf(stderr, "ofdm_ffs_sample: switch detected: pos -> neg\n"); - d_estimated_error -= 2*M_PI; - } - - /* the following distinction is not really needed; but without it, - * simulation would need to run much longer, becuase the - * synchronisation would need time to adjust to the offset */ - if (d_estimated_error == 0) - d_estimated_error = d_ffs_error_sum; /* first time -> fast adjustment */ - else - d_estimated_error = d_alpha*d_ffs_error_sum + (1-d_alpha)*d_estimated_error; /* slow adjustment */ - - d_estimated_error_per_sample = d_estimated_error / (float)d_fft_length; - // fprintf(stderr, "ofdm_ffs_sample: d_estimated_error: %f (%3.2f Hz)\n", d_estimated_error, d_estimated_error_per_sample*d_sample_rate/(2*M_PI)); - } - - d_cur_symbol++; - } - - *optr++ = d_estimated_error_per_sample; - iptr++; - } - - return noutput_items; -} diff --git a/lib/dab_ofdm_ffs_sample.h b/lib/dab_ofdm_ffs_sample.h deleted file mode 100644 index 575259f7..00000000 --- a/lib/dab_ofdm_ffs_sample.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_DAB_OFDM_FFS_SAMPLE_H -#define INCLUDED_DAB_OFDM_FFS_SAMPLE_H - -#include - -class dab_ofdm_ffs_sample; - -typedef boost::shared_ptr dab_ofdm_ffs_sample_sptr; - -dab_ofdm_ffs_sample_sptr dab_make_ofdm_ffs_sample (unsigned int symbol_length, unsigned int fft_length, unsigned int num_symbols, float alpha, unsigned int sample_rate); - -/*! - * \brief samples FFS error estimation at the correct time and averages it - * \ingroup DAB - * \param symbol_length number of samples in an OFDM symbol - * \param fft_length number of samples in an OFDM symbol without the cyclic prefix - * \param num_symbols number of symbols to use for averaging (more symbols is better, but symbols towards the end of the frame tend to have larger time offsets and worse values) - * \param alpha how fast should we adapt to new FFS error values (1=immediately) - * \param sample_rate sampling rate - needed to calculate the offset estimation in Hz - * - * input: port 0: float - actual data; port 1: byte - trigger signal indicating the start of a frame - * output: float fine frequency offset estimation (in radian per sample) - */ -class dab_ofdm_ffs_sample : public gr_sync_block -{ - private: - // The friend declaration allows dab_make_ofdm_ffs_sample to - // access the private constructor. - - friend dab_ofdm_ffs_sample_sptr dab_make_ofdm_ffs_sample (unsigned int symbol_length, unsigned int fft_length, unsigned int num_symbols, float alpha, unsigned int sample_rate); - - dab_ofdm_ffs_sample (unsigned int symbol_length, unsigned int fft_length, unsigned int num_symbols, float alpha, unsigned int sample_rate); // private constructor - - unsigned int d_symbol_length; // length of a symbol in samples - unsigned int d_fft_length; // length of a symbol without cyclic prefix in samples - unsigned int d_num_symbols; // number of symbols per frame to average over - float d_alpha; // adjustment speed factor - unsigned int d_sample_rate; // sample rate -- only needed to print the ffs error in Hz - - unsigned int d_cur_symbol; // which symbol in the frame is currently under observation? - unsigned int d_cur_sample; // which sample in the symbol is currently under observation? - float d_ffs_error_sum; // sum of error samples in current frame - float d_estimated_error; // total estimated error - float d_estimated_error_per_sample; // total estimated error / fft_length - - public: - /*! \return fine frequency error estimate in Hz */ - float ffe_estimate() { return d_estimated_error_per_sample*d_sample_rate/(2*M_PI); } - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_OFDM_FFS_SAMPLE_H */ diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc index 732052f8..49a85f85 100644 --- a/lib/demux_cc_impl.cc +++ b/lib/demux_cc_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,19 +92,10 @@ namespace gr { unsigned int tag_count = 0; get_tags_in_window(tags, 0, 0, noutput_items, d_key); - /*fprintf(stderr, "Work call ####################################\n"); - fprintf(stderr, "nitems_read %d\n", nitems_read(0)); - fprintf(stderr, "noutput_items %d\n", noutput_items); - fprintf(stderr, "Tags: %d\n", tags.size()); - for(int i = 0; i < tags.size(); i++){ - fprintf(stderr, "Tag offset %d\n", tags[i].offset); - }*/ for (int i = 0; i < noutput_items; ++i) { if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0) - nconsumed == 0) { - //fprintf(stderr, "Tag detected\n"); // this input symbol is tagged: a new frame begins here if(d_fic_counter%d_symbols_fic == 0 && d_msc_counter%d_symbols_msc == 0){ - //fprintf(stderr, "Tag is at beginning of frame\n"); // we are at the beginning of a frame and also finished writing the last frame // we can remove this first symbol of the frame (phase reference symbol) and copy the other symbols tag_count++; @@ -143,9 +134,6 @@ namespace gr { // Tell runtime system how many output items we produced on each output stream separately. produce(0, fic_syms_written); produce(1, msc_syms_written); - /*fprintf(stderr, "fic_syms_written %d\n", fic_syms_written); - fprintf(stderr, "msc_syms_written %d\n", msc_syms_written); - fprintf(stderr, "nconsumed %d\n", nconsumed);*/ return WORK_CALLED_PRODUCE; } diff --git a/lib/firecode_check_bb_impl.cc b/lib/firecode_check_bb_impl.cc index b39ceb3f..98350fec 100644 --- a/lib/firecode_check_bb_impl.cc +++ b/lib/firecode_check_bb_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * The class firecode_checker is adapted from the Qt-DAB software, Copyright Jan van Katwijk (Lazy Chair Computing J.vanKatwijk@gmail.com) * * This is free software; you can redistribute it and/or modify @@ -80,14 +80,13 @@ namespace gr { while (d_nconsumed < noutput_items / d_frame_size - 4) { if (fc.check(&in[d_nconsumed * d_frame_size])) { - //GR_LOG_DEBUG(d_logger, format("fire code (%d %d) OK at frame %d") %(int)in[d_nconsumed*d_frame_size] %(int)in[d_nconsumed*d_frame_size+1] % (nitems_read(0) / d_frame_size)); // fire code OK, copy superframe to output memcpy(out + d_nproduced * d_frame_size, in + d_nconsumed * d_frame_size, d_frame_size * 5); d_nproduced += 5; d_nconsumed += 5; d_firecode_passed = true; } else { - //GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); + GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); // shift of one logical frame d_nconsumed++; d_firecode_passed = false; diff --git a/lib/frequency_deinterleave_cc_impl.cc b/lib/frequency_deinterleave_cc_impl.cc deleted file mode 100644 index a43f271a..00000000 --- a/lib/frequency_deinterleave_cc_impl.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "frequency_deinterleave_cc_impl.h" - -namespace gr { - namespace dab { - - frequency_deinterleave_cc::sptr - frequency_deinterleave_cc::make(const std::vector &interleaving_sequence) - { - return gnuradio::get_initial_sptr - (new frequency_deinterleave_cc_impl(interleaving_sequence)); - } - - /* - * The private constructor - */ - frequency_deinterleave_cc_impl::frequency_deinterleave_cc_impl(const std::vector &interleaving_sequence) - : gr::sync_block("frequency_deinterleave_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(gr_complex))), - d_interleaving_sequence(interleaving_sequence), - d_length(interleaving_sequence.size()) - { - // check if interleaving sequency matches with its size - for (int i = 0; i < d_length; ++i) { - if (d_interleaving_sequence[i] >= d_length) { - throw std::invalid_argument((boost::format("size of interleaving element (%d) exceeds length of symbol (%d)") %(int)d_interleaving_sequence[i] %(int)d_length).str()); - } - } - set_output_multiple(d_length); - } - - /* - * Our virtual destructor. - */ - frequency_deinterleave_cc_impl::~frequency_deinterleave_cc_impl() - { - } - - int - frequency_deinterleave_cc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - - for (int i = 0; i < noutput_items/d_length; ++i) { - for (int j = 0; j < d_length; ++j) { - out[i*d_length + d_interleaving_sequence[j]] = in[i*d_length + j]; - } - } - - // Tell runtime system how many output items we produced. - return noutput_items; - } - - } /* namespace dab */ -} /* namespace gr */ - diff --git a/lib/frequency_deinterleave_cc_impl.h b/lib/frequency_deinterleave_cc_impl.h deleted file mode 100644 index f92a1632..00000000 --- a/lib/frequency_deinterleave_cc_impl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H -#define INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H - -#include - -namespace gr { - namespace dab { - /*! \brief DAB frequency deinterleaving - * \param interleaving_sequence vector with scrambling info - */ - - class frequency_deinterleave_cc_impl : public frequency_deinterleave_cc - { - private: - std::vector d_interleaving_sequence; - unsigned int d_length; - - public: - frequency_deinterleave_cc_impl(const std::vector &interleaving_sequence); - ~frequency_deinterleave_cc_impl(); - - // Where all the action really happens - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_FREQUENCY_DEINTERLEAVE_CC_IMPL_H */ - diff --git a/lib/mapper_bc_impl.cc b/lib/mapper_bc_impl.cc deleted file mode 100644 index f720190d..00000000 --- a/lib/mapper_bc_impl.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Frank1Llin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "mapper_bc_impl.h" - -namespace gr { - namespace dab { - - mapper_bc::sptr - mapper_bc::make(int symbol_length) - { - return gnuradio::get_initial_sptr - (new mapper_bc_impl(symbol_length)); - } - - /* - * The private constructor - */ - mapper_bc_impl::mapper_bc_impl(int symbol_length) - : gr::block("mapper_bc", - gr::io_signature::make(1, 1, sizeof(char)), - gr::io_signature::make(1, 1, sizeof(gr_complex))), - d_symbol_length(symbol_length) - { - set_output_multiple(symbol_length); - } - - /* - * Our virtual destructor. - */ - mapper_bc_impl::~mapper_bc_impl() - { - } - - void - mapper_bc_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items * 2; - } - - int - mapper_bc_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const char *in = (const char *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - - // for each symbol - for (int i = 0; i < noutput_items / d_symbol_length; i++) { - // for d_symbol_length complex outputs - for (int j = 0; j < d_symbol_length; j++) { - //out[i*2*d_symbol_length + j] = gr_complex(in[(i*2)*d_symbol_length + j], in[(i*2 + 1)*d_symbol_length + j]); - if (in[(i * 2) * d_symbol_length + j] > 0) { - if (in[(i * 2 + 1) * d_symbol_length + j] > 0) - out[i * d_symbol_length + j] = gr_complex(-I_SQRT2, -I_SQRT2); //11 - else - out[i * d_symbol_length + j] = gr_complex(-I_SQRT2, I_SQRT2); //10 - } else { - if (in[(i * 2 + 1) * d_symbol_length + j] > 0) - out[i * d_symbol_length + j] = gr_complex(I_SQRT2, -I_SQRT2); //01 - else - out[i * d_symbol_length + j] = gr_complex(I_SQRT2, I_SQRT2); //00 - } - } - } - // Tell runtime system how many input items we consumed on - // each input stream. - consume_each(noutput_items * 2); - - // Tell runtime system how many output items we produced. - return noutput_items; - } - - } /* namespace dab */ -} /* namespace gr */ - diff --git a/lib/mapper_bc_impl.h b/lib/mapper_bc_impl.h deleted file mode 100644 index 9819cead..00000000 --- a/lib/mapper_bc_impl.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_MAPPER_BC_IMPL_H -#define INCLUDED_DAB_MAPPER_BC_IMPL_H - -#define I_SQRT2 0.707106781187 - -#include - -namespace gr { - namespace dab { -/*! \brief QPSK mapper according to the DAB standard ETSI EN 300 401 V1.4.1, clause 14.5 - * - * uses two unpacked bit frames of respectively length symbol_length to form a complex frame of length symbol_length - * two bits define a complex symbol, the first bit is taken from the the first bit frame at index i, the second bit from the second bit frame at index i, they form the complex symbol at index i - * - * @param symbol_length length of output frame - * - */ - class mapper_bc_impl : public mapper_bc { - private: - int d_symbol_length; - - public: - mapper_bc_impl(int symbol_length); - - ~mapper_bc_impl(); - - // Where all the action really happens - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_MAPPER_BC_IMPL_H */ - diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index ac96f8ca..92bf126b 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * GNU Radio block written for gr-dab including the following third party elements: * -QT-DAB: classes mp4Processor and faad-decoder except the reed-solomon class @@ -214,15 +214,9 @@ namespace gr { baudRate = sample_rate; } d_sample_rate = sample_rate; - //GR_LOG_DEBUG(d_logger, format("bytes consumed %d") % (int) (hInfo.bytesconsumed)); - /*GR_LOG_DEBUG(d_logger, - format("sample_rate = %d, samples = %d, channels = %d, error = %d, sbr = %d") % sample_rate % - samples % - (int) (hInfo.channels) % (int) (hInfo.error) % (int) (hInfo.sbr));*/ channels = hInfo.channels; if (hInfo.error != 0) { - fprintf(stderr, "Warning: %s\n", - faacDecGetErrorMessage(hInfo.error)); + GR_LOG_ERROR(d_logger, format("Warning: %s") % faacDecGetErrorMessage(hInfo.error)); return 0; } @@ -244,7 +238,6 @@ namespace gr { } else GR_LOG_ERROR(d_logger, "Cannot handle these channels -> dump samples"); - //GR_LOG_DEBUG(d_logger, format("Produced %d PCM samples (for each channel)") % (samples / 2)); d_nsamples_produced += samples / 2; return samples / 2; } @@ -307,10 +300,10 @@ namespace gr { d_ps_flag = (in[n * d_superframe_size + 2] >> 3) & 01; // bit 20 d_mpeg_surround = (in[n * d_superframe_size + 2] & 07); // bits 21 .. 23 // log header information - /*GR_LOG_DEBUG(d_logger, + GR_LOG_DEBUG(d_logger, format("superframe header: dac_rate %d, sbr_flag %d, aac_mode %d, ps_flag %d, surround %d") % (int) d_dac_rate % (int) d_sbr_flag % (int) d_aac_channel_mode % (int) d_ps_flag % - (int) d_mpeg_surround);*/ + (int) d_mpeg_surround); switch (2 * d_dac_rate + d_sbr_flag) { default: // cannot happen diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index 4234aa6d..24bea3ce 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -45,11 +45,10 @@ namespace gr { gr::io_signature::make(1, 1, num_carriers*sizeof(gr_complex))), d_fft_length(fft_length), d_num_carriers(num_carriers), - d_cyclic_prefix_length(cyclic_prefix_length) - { - d_freq_offset = 0; - d_snr = 0; - } + d_cyclic_prefix_length(cyclic_prefix_length), + d_freq_offset (0), + d_snr (0) + {} /* * Our virtual destructor. @@ -68,10 +67,12 @@ namespace gr { unsigned int i, index; float energy = 0, max = 0; // first energy measurement is processed completely - for (i=0; i max) { max = energy; @@ -103,18 +104,20 @@ namespace gr { { // measure normalized energy of occupied sub-carriers float energy = 0; - for (int i=0; i= d_symbols_per_frame) { - //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); d_symbol_count = 0; //TODO: skip forward more to safe computing many computing steps // switch to acquisition mode again to get the start of the next frame exactly @@ -232,19 +228,14 @@ namespace gr { // we expect the start of a new symbol here // correlation has to be calculated completely new, because of skipping samples before delayed_correlation(&in[i], true); - //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); // check if there is really a peak if (d_correlation_normalized_magnitude > 0.3) { //TODO: check if we are on right edge d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s - //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset_per_sample)); - //GR_LOG_DEBUG(d_logger, format("in track symbol %d") % (d_symbol_count)); } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; GR_LOG_DEBUG(d_logger, format("Lost track at %d, switching ot acquisition mode (%d)") %d_symbol_count % d_correlation_normalized_magnitude); - /*add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), - pmt::from_float(d_correlation_normalized_magnitude));*/ } } } else if (d_cyclic_prefix_length*0.75 <= d_symbol_element_count && d_symbol_element_count < d_cyclic_prefix_length*0.75 + d_symbol_length) { @@ -256,10 +247,8 @@ namespace gr { gr_complex fine_frequency_correction = gr_complex(oi, oq); // set tag at next item if it is the first element of the first symbol if (d_symbol_count == 0 && d_symbol_element_count == d_cyclic_prefix_length) { - //GR_LOG_DEBUG(d_logger, format("Set Tag %d")%(nitems_read(0)+i)); add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); - } // now we start copying one symbol length to the output out[d_nwritten++] = in[i] * fine_frequency_correction; @@ -273,8 +262,7 @@ namespace gr { */ d_phase += d_frequency_offset_per_sample; //place phase in [-pi, +pi[ -#define F_PI ((float)(M_PI)) - d_phase = std::fmod(d_phase + F_PI, 2.0f * F_PI) - F_PI; + d_phase = std::fmod(d_phase + M_PI, 2.0f * M_PI) - M_PI; } consume_each(noutput_items); diff --git a/lib/qpsk_mapper_vbvc_impl.cc b/lib/qpsk_mapper_vbvc_impl.cc index f9fa5763..6afc3480 100644 --- a/lib/qpsk_mapper_vbvc_impl.cc +++ b/lib/qpsk_mapper_vbvc_impl.cc @@ -63,7 +63,7 @@ namespace gr { for (int i = 0; i < noutput_items; ++i) { // iterate over each symbol vector for (int j = 0; j < d_symbol_length/8; ++j) { - // iterate over the symbo vector, but each byte has 8 bit, which are accessed manually + // iterate over the symbol vector, but each byte has 8 bit, which are accessed manually out[i*d_symbol_length + j*8 + 0] = gr_complex((in[i*(d_symbol_length/4) + j]&128)>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&128)>0?-I_SQRT2:I_SQRT2); out[i*d_symbol_length + j*8 + 1] = gr_complex((in[i*(d_symbol_length/4) + j]&64 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&64 )>0?-I_SQRT2:I_SQRT2); out[i*d_symbol_length + j*8 + 2] = gr_complex((in[i*(d_symbol_length/4) + j]&32 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&32 )>0?-I_SQRT2:I_SQRT2); @@ -74,7 +74,6 @@ namespace gr { out[i*d_symbol_length + j*8 + 7] = gr_complex((in[i*(d_symbol_length/4) + j]&1 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&1 )>0?-I_SQRT2:I_SQRT2); } } - // Tell runtime system how many output items we produced. return noutput_items; } diff --git a/lib/synchronization_ff_impl.cc b/lib/synchronization_ff_impl.cc deleted file mode 100644 index d98cbfab..00000000 --- a/lib/synchronization_ff_impl.cc +++ /dev/null @@ -1,266 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include "synchronization_ff_impl.h" -#include - -using namespace boost; - -namespace gr { - namespace dab { - - synchronization_ff::sptr - synchronization_ff::make(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) - { - return gnuradio::get_initial_sptr - (new synchronization_ff_impl(symbol_length, cyclic_prefix_length, num_ofdm_symbols)); - } - - /* - * The private constructor - */ - synchronization_ff_impl::synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols) - : gr::block("synchronization_ff", - gr::io_signature::make(1, 1, sizeof(gr_complex)), - //gr::io_signature::make(1, 1, sizeof(gr_complex))), - gr::io_signature::make(1, 1, sizeof(float))), - d_symbol_length(symbol_length), - d_cyclic_prefix_length(cyclic_prefix_length), - d_num_ofdm_symbols(num_ofdm_symbols) - { - set_min_noutput_items(symbol_length + cyclic_prefix_length+1); - d_correlation = 0; - d_energy_prefix = 1; - d_energy_repetition = 1; - d_NULL_symbol_energy = 1; - d_frequency_offset = 0; - d_NULL_detected = false; - d_moving_average_counter = 0; - d_frame_count = 1; - d_frame_length_count = 0; - d_wait_for_NULL = true; - d_on_triangle = false; - d_acquisition = false; - } - - /* - * Our virtual destructor. - */ - synchronization_ff_impl::~synchronization_ff_impl() - { - } - - void - synchronization_ff_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items; - } - - void - synchronization_ff_impl::delayed_correlation(const gr_complex *sample, bool new_calculation) - { - if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || new_calculation) { - if (d_moving_average_counter == 0 && (!new_calculation)) { - // first value is calculated completely, next values are calculated with moving average - d_moving_average_counter++; - } else { - // reset counter - d_moving_average_counter = 0; - } - // calculate delayed correlation for this sample completely - d_correlation = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_correlation += sample[j] * conj(sample[d_symbol_length + j]); - } - // calculate energy of cyclic prefix for this sample completely - d_energy_prefix = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_prefix += std::real(sample[j] * conj(sample[j])); - } - // calculate energy of its repetition for this sample completely - d_energy_repetition = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_repetition += std::real(sample[j + d_symbol_length] * conj(sample[j + d_symbol_length])); - } - } else { - // calculate next step for moving average - d_correlation += - sample[d_cyclic_prefix_length - 1] * conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); - d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * conj(sample[d_cyclic_prefix_length - 1])); - d_energy_repetition += std::real(sample[d_symbol_length + d_cyclic_prefix_length - 1] * - conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); - d_correlation -= sample[0] * conj(sample[d_symbol_length]); - d_energy_prefix -= std::real(sample[0] * conj(sample[0])); - d_energy_repetition -= std::real(sample[d_symbol_length] * conj(sample[d_symbol_length])); - d_moving_average_counter++; - } - // normalize - d_correlation_normalized = d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); - // calculate magnitude - d_correlation_normalized_magnitude = d_correlation_normalized.real() * d_correlation_normalized.real() + - d_correlation_normalized.imag() * d_correlation_normalized.imag(); - } - - /*! \brief returns true at a point with a little space before the peak of a correlation triangular - * - */ - bool - synchronization_ff_impl::detect_start_of_symbol() - { - if(d_on_triangle){ - if(d_correlation_normalized_magnitude < 0.5){ - // we left the triangle - d_on_triangle = false; - return false; - } - else{ - // we are still on the triangle but we already picked our pre-peak value - return false; - } - } - else{ - // not on a correlation triangle yet - if(d_correlation_normalized_magnitude > 0.85){ - // no we are on the triangle - d_on_triangle = true; - return true; - } - else{ - // no triangle here - return false; - } - } - } -/* - bool - synchronization_ff_impl::detect_peak() // on triangle used for detect_start_of_symbol() - { - if (!d_on_triangle && d_correlation_normalized_magnitude > 0.85) { - // over threshold, peak is coming soon - d_on_triangle = true; - return false; - } else if (d_on_triangle && d_correlation_normalized_magnitude < 0.8) { - // peak found - d_on_triangle = false; - return true; - } else { - return false; - } - }*/ - - int - synchronization_ff_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const gr_complex *in = (const gr_complex *) input_items[0]; - //gr_complex *out = (gr_complex *) output_items[0]; - float *out = (float *) output_items[0]; - d_nwritten = 0; - - for (int i = 0; i < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++i) { - // just for measurement reasons - if (d_wait_for_NULL) { - // acquisition mode: search for next correlation peak after a NULL symbol - delayed_correlation(&in[i], false); - if (detect_start_of_symbol()) { - if (d_NULL_detected && (d_energy_prefix > d_NULL_symbol_energy * 2)) { - // calculate new frequency offset - d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s - // set tag at beginning of new frame (first symbol after null symbol) - add_item_tag(0, nitems_written(0) + i, pmt::mp("Start"), - pmt::from_float(std::arg(d_correlation))); - GR_LOG_DEBUG(d_logger, format("Start of frame, freq offset %d")%d_frequency_offset); - out[d_nwritten++] = d_frequency_offset; - // reset NULL detector - d_NULL_detected = false; - // switch to tracking mode - d_wait_for_NULL = false; - } else { - //peak but not after NULL symbol - } - } else { - if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.1))) { - // NULL symbol detection, if energy is < 0.1 * energy a symbol time later - d_NULL_symbol_energy = d_energy_prefix; - d_NULL_detected = true; - } - } - } - else if (++d_frame_length_count >= (d_symbol_length + d_cyclic_prefix_length)) { - // &in[i] points now to the sample where the next symbol start (=peak) is expected - d_frame_length_count = 0; - // correlation has to be calculated completely new, because of skipping samples before - delayed_correlation(&in[i], true); - //GR_LOG_DEBUG(d_logger, format(" New possible peak %d (i=%d)") % d_correlation_normalized_magnitude % i); - // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.5) { //TODO: check if we are on right edge - d_frequency_offset = std::arg(d_correlation)/0.001246; // in rad/s - out[d_nwritten++] = d_frequency_offset; // in rad/s - //add_item_tag(0, nitems_written(0) + i, pmt::mp("on track"), pmt::from_float(d_frequency_offset)); - GR_LOG_DEBUG(d_logger, format("in track %d")%d_frequency_offset); - d_frame_count++; - // check if we arrived at the last symbol - if (d_frame_count >= d_num_ofdm_symbols) { - //GR_LOG_DEBUG(d_logger, format("Sucessfully finished!!!")); - d_frame_count = 1; - //TODO: skip forward more to safe computing many computing steps - // switch to acquisition mode again to get the start of the next frame exactly - d_wait_for_NULL = true; - } - } else { - // no peak found -> out of track; search for next NULL symbol - d_wait_for_NULL = true; - //GR_LOG_DEBUG(d_logger, format("Lost track, switching ot acquisition mode (%d)")%d_correlation_normalized_magnitude); - add_item_tag(0, nitems_written(0) + i, pmt::mp("Lost"), - pmt::from_float(d_correlation_normalized_magnitude)); - d_frame_count = 1; - } - } - // copy sample correcting the frequency offset - //out[i] = d_correlation_normalized_magnitude;; - } - - // pass iq samples through with set tags - // memcpy(out, in, (noutput_items - d_cyclic_prefix_length - d_symbol_length)* sizeof(gr_complex)); - - // debug output to check the delayed correlation - /*d_moving_average_counter = 0; - for (int j = 0; j < noutput_items - d_cyclic_prefix_length - d_symbol_length; ++j) { - delayed_correlation(&in[j], false); - out[j] = d_correlation_normalized; - }*/ - consume_each(noutput_items - d_cyclic_prefix_length - d_symbol_length); - return d_nwritten; - } - - } /* namespace dab */ -} /* namespace gr */ - diff --git a/lib/synchronization_ff_impl.h b/lib/synchronization_ff_impl.h deleted file mode 100644 index b3dbfcec..00000000 --- a/lib/synchronization_ff_impl.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H -#define INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H - -#include - -namespace gr { - namespace dab { -/*! \brief sets tag at the beginning of each OFDM frame - * - * \param symbol_length length of each OFDM symbol without guard intervall - * \param cyclic_prefix_length length of the cyclic prefix (= length of the guard intervall) - * \param num_ofdm_symbols number of OFDM symbols without the NULL symbol - * - */ - class synchronization_ff_impl : public synchronization_ff - { - private: - int d_symbol_length; - int d_cyclic_prefix_length; - int d_moving_average_counter; - gr_complex d_correlation; - gr_complex d_correlation_normalized; - float d_correlation_normalized_magnitude; - float d_correlation_normalized_phase; - float d_energy_prefix; - float d_energy_repetition; - float d_NULL_symbol_energy; - float d_frequency_offset; - bool d_NULL_detected; - int d_num_ofdm_symbols; - int d_frame_count; - int d_frame_length_count; - bool d_wait_for_NULL; - bool d_on_triangle; - bool d_acquisition; - - int d_nwritten; - - public: - synchronization_ff_impl(int symbol_length, int cyclic_prefix_length, int num_ofdm_symbols); - ~synchronization_ff_impl(); - - void delayed_correlation(const gr_complex *sample, bool new_calculation); - bool detect_peak(); - bool detect_start_of_symbol(); - - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - // Where all the action really happens - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_SYNCHRONIZATION_FF_IMPL_H */ - diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index ef64385a..e6ca7484 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -90,10 +90,8 @@ GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_ GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_decode_bb.py) GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_decode_bs.py) -#GR_ADD_TEST(qa_prune ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_prune.py) #GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) #GR_ADD_TEST(qa_dabplus_audio_decoder_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dabplus_audio_decoder_ff.py) #GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) #GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) -#GR_ADD_TEST(qa_synchronization_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_synchronization_ff.py) #GR_ADD_TEST(qa_ofdm_synchronization_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronization_cvf.py) diff --git a/python/ofdm_mod_bc.py b/python/ofdm_mod_bc.py index c24de3b5..126642b2 100644 --- a/python/ofdm_mod_bc.py +++ b/python/ofdm_mod_bc.py @@ -116,185 +116,3 @@ def __init__(self, dab_params, verbose=False, debug=False): self.connect(self.ifft, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/generated_signal_ifft.dat")) self.connect(self.prefixer, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal_prefixer.dat")) self.connect(self.insert_null, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal.dat")) - - - -class ofdm_demod(gr.hier_block2): - """ - @brief Block to demodulate a DAB signal into bits. - - Takes a stream of complex baseband samples and performs OFDM demodulation according to the DAB standard. - Expects an input sample rate of 2.048 MSPS. - """ - - def __init__(self, dab_params, rx_params, verbose=False, debug=False): - """ - Hierarchical block for OFDM demodulation - - @param dab_params DAB parameter object (dab.parameters.dab_parameters) - @param rx_params RX parameter object (dab.parameters.receiver_parameters) - @param debug enables debug output to files - @param verbose whether to produce verbose messages - """ - - self.dp = dp = dab_params - self.rp = rp = rx_params - self.verbose = verbose - - if self.rp.softbits: - gr.hier_block2.__init__(self,"ofdm_demod", - gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature - gr.io_signature2(2, 2, gr.sizeof_float*self.dp.num_carriers*2, gr.sizeof_char)) # output signature - else: - gr.hier_block2.__init__(self,"ofdm_demod", - gr.io_signature (1, 1, gr.sizeof_gr_complex), # input signature - gr.io_signature2(2, 2, gr.sizeof_char*self.dp.num_carriers/4, gr.sizeof_char)) # output signature - - - - # workaround for a problem that prevents connecting more than one block directly (see trac ticket #161) - #self.input = gr.kludge_copy(gr.sizeof_gr_complex) - self.input = blocks.multiply_const_cc(1.0) # FIXME - self.connect(self, self.input) - - # input filtering - if self.rp.input_fft_filter: - if verbose: print "--> RX filter enabled" - lowpass_taps = filter.firdes_low_pass(1.0, # gain - dp.sample_rate, # sampling rate - rp.filt_bw, # cutoff frequency - rp.filt_tb, # width of transition band - filter.firdes.WIN_HAMMING) # Hamming window - self.fft_filter = filter.fft_filter_ccc(1, lowpass_taps) - - - # correct sample rate offset, if enabled - if self.rp.autocorrect_sample_rate: - if verbose: print "--> dynamic sample rate correction enabled" - self.rate_detect_ns = dab.detect_null(dp.ns_length, False) - self.rate_estimator = dab.estimate_sample_rate_bf(dp.sample_rate, dp.frame_length) - self.rate_prober = blocks.probe_signal_f() - self.connect(self.input, self.rate_detect_ns, self.rate_estimator, self.rate_prober) - # self.resample = gr.fractional_interpolator_cc(0, 1) - self.resample = dab.fractional_interpolator_triggered_update_cc(0,1) - self.connect(self.rate_detect_ns, (self.resample,1)) - self.updater = Timer(0.1,self.update_correction) - # self.updater = threading.Thread(target=self.update_correction) - self.run_interpolater_update_thread = True - self.updater.setDaemon(True) - self.updater.start() - else: - self.run_interpolater_update_thread = False - if self.rp.sample_rate_correction_factor != 1: - if verbose: print "--> static sample rate correction enabled" - self.resample = gr.fractional_interpolator_cc(0, self.rp.sample_rate_correction_factor) - - # timing and fine frequency synchronisation - self.sync = dab.ofdm_sync_dab2(self.dp, self.rp, debug) - - # ofdm symbol sampler - self.sampler = dab.ofdm_sampler(dp.fft_length, dp.cp_length, dp.symbols_per_frame, rp.cp_gap) - - # fft for symbol vectors - self.fft = fft.fft_vcc(dp.fft_length, True, [], True) - - # coarse frequency synchronisation - self.cfs = dab.ofdm_coarse_frequency_correct(dp.fft_length, dp.num_carriers, dp.cp_length) - - # diff phasor - self.phase_diff = dab.diff_phasor_vcc(dp.num_carriers) - - # remove pilot symbol - self.remove_pilot = dab.ofdm_remove_first_symbol_vcc(dp.num_carriers) - - # magnitude equalisation - if self.rp.equalize_magnitude: - if verbose: print "--> magnitude equalization enabled" - self.equalizer = dab.magnitude_equalizer_vcc(dp.num_carriers, rp.symbols_for_magnitude_equalization) - - # frequency deinterleaving - self.deinterleave = dab.frequency_interleaver_vcc(dp.frequency_deinterleaving_sequence_array) - - # symbol demapping - self.demapper = dab.qpsk_demapper_vcb(dp.num_carriers) - - # - # connect everything - # - - if self.rp.autocorrect_sample_rate or self.rp.sample_rate_correction_factor != 1: - self.connect(self.input, self.resample) - self.input2 = self.resample - else: - self.input2 = self.input - if self.rp.input_fft_filter: - self.connect(self.input2, self.fft_filter, self.sync) - else: - self.connect(self.input2, self.sync) - - # data stream - self.connect((self.sync, 0), (self.sampler, 0), self.fft, (self.cfs, 0), self.phase_diff, (self.remove_pilot,0)) - if self.rp.equalize_magnitude: - self.connect((self.remove_pilot,0), (self.equalizer,0), self.deinterleave) - else: - self.connect((self.remove_pilot,0), self.deinterleave) - if self.rp.softbits: - if verbose: print "--> using soft bits" - self.softbit_interleaver = dab.complex_to_interleaved_float_vcf(self.dp.num_carriers) - self.connect(self.deinterleave, self.softbit_interleaver, (self,0)) - else: - self.connect(self.deinterleave, self.demapper, (self,0)) - - # control stream - self.connect((self.sync, 1), (self.sampler, 1), (self.cfs, 1), (self.remove_pilot,1)) - if self.rp.equalize_magnitude: - self.connect((self.remove_pilot,1), (self.equalizer,1), (self,1)) - else: - self.connect((self.remove_pilot,1), (self,1)) - - # calculate an estimate of the SNR - self.phase_var_decim = blocks.keep_one_in_n(gr.sizeof_gr_complex*self.dp.num_carriers, self.rp.phase_var_estimate_downsample) - self.phase_var_arg = blocks.complex_to_arg(dp.num_carriers) - self.phase_var_v2s = blocks.vector_to_stream(gr.sizeof_float, dp.num_carriers) - self.phase_var_mod = dab.modulo_ff(pi/2) - self.phase_var_avg_mod = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) - self.phase_var_sub_avg = blocks.sub_ff() - self.phase_var_sqr = blocks.multiply_ff() - self.phase_var_avg = filter.iir_filter_ffd([rp.phase_var_estimate_alpha], [0,1-rp.phase_var_estimate_alpha]) - self.probe_phase_var = blocks.probe_signal_f() - self.connect((self.remove_pilot,0), self.phase_var_decim, self.phase_var_arg, self.phase_var_v2s, self.phase_var_mod, (self.phase_var_sub_avg,0), (self.phase_var_sqr,0)) - self.connect(self.phase_var_mod, self.phase_var_avg_mod, (self.phase_var_sub_avg,1)) - self.connect(self.phase_var_sub_avg, (self.phase_var_sqr,1)) - self.connect(self.phase_var_sqr, self.phase_var_avg, self.probe_phase_var) - - # measure processing rate - self.measure_rate = dab.measure_processing_rate(gr.sizeof_gr_complex, 2000000) - self.connect(self.input, self.measure_rate) - - # debugging - if debug: - self.connect(self.fft, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/ofdm_after_fft.dat")) - self.connect((self.cfs,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_after_cfs.dat")) - self.connect(self.phase_diff, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_diff_phasor.dat")) - self.connect((self.remove_pilot,0), blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_pilot_removed.dat")) - self.connect((self.remove_pilot,1), blocks.file_sink(gr.sizeof_char, "debug/ofdm_after_cfs_trigger.dat")) - self.connect(self.deinterleave, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_deinterleaved.dat")) - if self.rp.equalize_magnitude: - self.connect(self.equalizer, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/ofdm_equalizer.dat")) - if self.rp.softbits: - self.connect(self.softbit_interleaver, blocks.file_sink(gr.sizeof_float*dp.num_carriers*2, "debug/softbits.dat")) - - def clear_state(self): - self.sync.clear_state() - - def update_correction(self): - while self.run_interpolater_update_thread: - rate = self.rate_prober.level() - if rate!=0: - self.resample.set_interp_ratio(rate/self.dp.sample_rate) - sleep(0.1) - - def stop(self): - if self.run_interpolater_update_thread: - self.run_interpolater_update_thread = False - self.updater.join() diff --git a/swig/dab_swig.i b/swig/dab_swig.i index c5ad836f..6428a5c7 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -27,7 +27,6 @@ #include "dab/puncture_bb.h" #include "dab/dab_transmission_frame_mux_bb.h" #include "dab/conv_encoder_bb.h" -#include "dab/mapper_bc.h" #include "dab/mp2_decode_bs.h" #include "dab/mp4_decode_bs.h" #include "dab/reed_solomon_decode_bb.h" @@ -35,10 +34,8 @@ #include "dab/mp4_encode_sb.h" #include "dab/mp2_encode_sb.h" #include "dab/valve_ff.h" -#include "dab/synchronization_ff.h" #include "dab/ofdm_synchronization_cvf.h" #include "dab/ofdm_coarse_frequency_correction_vcvc.h" -#include "dab/frequency_deinterleave_cc.h" #include "dab/demux_cc.h" #include "dab/select_cus_vfvf.h" #include "dab/qpsk_mapper_vbvc.h" @@ -89,8 +86,7 @@ GR_SWIG_BLOCK_MAGIC2(dab, puncture_bb); GR_SWIG_BLOCK_MAGIC2(dab, dab_transmission_frame_mux_bb); %include "dab/conv_encoder_bb.h" GR_SWIG_BLOCK_MAGIC2(dab, conv_encoder_bb); -%include "dab/mapper_bc.h" -GR_SWIG_BLOCK_MAGIC2(dab, mapper_bc); + %include "dab/mp2_decode_bs.h" GR_SWIG_BLOCK_MAGIC2(dab, mp2_decode_bs); @@ -109,16 +105,11 @@ GR_SWIG_BLOCK_MAGIC2(dab, mp2_encode_sb); %include "dab/valve_ff.h" GR_SWIG_BLOCK_MAGIC2(dab, valve_ff); - -%include "dab/synchronization_ff.h" -GR_SWIG_BLOCK_MAGIC2(dab, synchronization_ff); %include "dab/ofdm_synchronization_cvf.h" GR_SWIG_BLOCK_MAGIC2(dab, ofdm_synchronization_cvf); %include "dab/ofdm_coarse_frequency_correction_vcvc.h" GR_SWIG_BLOCK_MAGIC2(dab, ofdm_coarse_frequency_correction_vcvc); -%include "dab/frequency_deinterleave_cc.h" -GR_SWIG_BLOCK_MAGIC2(dab, frequency_deinterleave_cc); %include "dab/demux_cc.h" GR_SWIG_BLOCK_MAGIC2(dab, demux_cc); From 59c96314326116dd9b098c0ab558fb6f343f932c Mon Sep 17 00:00:00 2001 From: luca Date: Wed, 10 Jan 2018 15:45:05 +0100 Subject: [PATCH 113/135] volkize energy measurement in sync --- lib/ofdm_synchronization_cvf_impl.cc | 12 +++++++++--- lib/ofdm_synchronization_cvf_impl.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index cf1a41af..317b8b4a 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -28,6 +28,7 @@ #include #include #include "ofdm_synchronization_cvf_impl.h" +#include #include #include @@ -70,7 +71,10 @@ namespace gr { d_phase (0), d_correlation_maximum (0), d_peak_set (false) - {} + { + unsigned int alignment = volk_get_alignment(); + float* d_magnitude_squared = (float*)volk_malloc(sizeof(float)*d_cyclic_prefix_length, alignment); + } /* * Our virtual destructor. @@ -102,14 +106,16 @@ namespace gr { d_correlation += sample[j] * conj(sample[d_symbol_length + j]); } // calculate energy of cyclic prefix for this sample completely + volk_32fc_magnitude_squared_32f(d_magnitude_squared, sample, d_cyclic_prefix_length); d_energy_prefix = 0; for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_prefix += std::real(sample[j] * conj(sample[j])); + d_energy_prefix += d_magnitude_squared[j]; } // calculate energy of its repetition for this sample completely + volk_32fc_magnitude_squared_32f(d_magnitude_squared, &sample[d_symbol_length], d_cyclic_prefix_length); d_energy_repetition = 0; for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_repetition += std::real(sample[j + d_symbol_length] * conj(sample[j + d_symbol_length])); + d_energy_repetition += d_magnitude_squared[j]; } } else { // calculate next step for moving average diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index 93d5c09d..c5e0f068 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -43,6 +43,7 @@ namespace gr { gr_complex d_correlation_normalized; float d_correlation_normalized_magnitude; float d_correlation_normalized_phase; + float *d_magnitude_squared; float d_energy_prefix; float d_energy_repetition; float d_NULL_symbol_energy; From 7cec3a634a9f006e797a7a1b4a37f108fcbb2f7a Mon Sep 17 00:00:00 2001 From: luca Date: Wed, 10 Jan 2018 18:28:29 +0100 Subject: [PATCH 114/135] volkize all correlations and additions in coarse_frequency_correction --- lib/ofdm_synchronization_cvf_impl.cc | 25 +++++++++++-------------- lib/ofdm_synchronization_cvf_impl.h | 3 ++- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index 317b8b4a..eea85138 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -72,8 +72,10 @@ namespace gr { d_correlation_maximum (0), d_peak_set (false) { - unsigned int alignment = volk_get_alignment(); - float* d_magnitude_squared = (float*)volk_malloc(sizeof(float)*d_cyclic_prefix_length, alignment); + //allocation for repeating energy measurements + unsigned int alignment = volk_get_alignment(); + d_mag_squared = (float*)volk_malloc(sizeof(float)*d_cyclic_prefix_length, alignment); + d_fixed_lag_corr = (gr_complex*)volk_malloc(sizeof(gr_complex)*d_cyclic_prefix_length, alignment); } /* @@ -101,22 +103,17 @@ namespace gr { d_moving_average_counter = 0; } // calculate delayed correlation for this sample completely + volk_32fc_x2_conjugate_dot_prod_32fc(d_fixed_lag_corr, sample, &sample[d_symbol_length], d_cyclic_prefix_length); d_correlation = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_correlation += sample[j] * conj(sample[d_symbol_length + j]); + for (int i = 0; i < d_cyclic_prefix_length; ++i) { + d_correlation += d_fixed_lag_corr[i]; } // calculate energy of cyclic prefix for this sample completely - volk_32fc_magnitude_squared_32f(d_magnitude_squared, sample, d_cyclic_prefix_length); - d_energy_prefix = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_prefix += d_magnitude_squared[j]; - } + volk_32fc_magnitude_squared_32f(d_mag_squared, sample, d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_prefix, d_mag_squared, d_cyclic_prefix_length); // calculate energy of its repetition for this sample completely - volk_32fc_magnitude_squared_32f(d_magnitude_squared, &sample[d_symbol_length], d_cyclic_prefix_length); - d_energy_repetition = 0; - for (int j = 0; j < d_cyclic_prefix_length; j++) { - d_energy_repetition += d_magnitude_squared[j]; - } + volk_32fc_magnitude_squared_32f(d_mag_squared, &sample[d_symbol_length], d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_repetition, d_mag_squared, d_cyclic_prefix_length); } else { // calculate next step for moving average d_correlation += diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index c5e0f068..f9039bd9 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -41,9 +41,10 @@ namespace gr { int d_moving_average_counter; gr_complex d_correlation; gr_complex d_correlation_normalized; + float *d_mag_squared; + gr_complex *d_fixed_lag_corr; float d_correlation_normalized_magnitude; float d_correlation_normalized_phase; - float *d_magnitude_squared; float d_energy_prefix; float d_energy_repetition; float d_NULL_symbol_energy; From 4946c745b47e5af9f1ef205d3adf2b25ecf12140 Mon Sep 17 00:00:00 2001 From: luca Date: Sat, 13 Jan 2018 18:01:33 +0100 Subject: [PATCH 115/135] volkize all energy measurements (mag_squared) in measure_snr --- ...m_coarse_frequency_correction_vcvc_impl.cc | 54 ++++++++++--------- ...dm_coarse_frequency_correction_vcvc_impl.h | 3 +- lib/ofdm_synchronization_cvf_impl.cc | 2 +- lib/ofdm_synchronization_cvf_impl.h | 2 +- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index 24bea3ce..4e841d00 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include #include "ofdm_coarse_frequency_correction_vcvc_impl.h" +#include #include namespace gr { @@ -48,7 +49,10 @@ namespace gr { d_cyclic_prefix_length(cyclic_prefix_length), d_freq_offset (0), d_snr (0) - {} + { + unsigned int alignment = volk_get_alignment(); + d_mag_squared = (float*)volk_malloc(sizeof(float)*num_carriers+1, alignment); + } /* * Our virtual destructor. @@ -67,12 +71,10 @@ namespace gr { unsigned int i, index; float energy = 0, max = 0; // first energy measurement is processed completely - for (int i = 0; i < d_num_carriers/2; ++i) { - energy+=std::real(symbol[i])*std::real(symbol[i]) + std::imag(symbol[i])*std::imag(symbol[i]); - } - for (int i = d_num_carriers/2+1; i <= d_num_carriers; ++i) { - energy+=std::real(symbol[i])*std::real(symbol[i]) + std::imag(symbol[i])*std::imag(symbol[i]); - } + volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, d_num_carriers+1); + volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers+1); + // subtract the central (DC) carrier which is not occupied + energy -= std::real(symbol[d_num_carriers])*std::real(symbol[d_num_carriers]) + std::imag(symbol[d_num_carriers])*std::imag(symbol[d_num_carriers]); max = energy; index = 0; /* the energy measurements with all possible carrier offsets are calculated over a moving sum, @@ -104,28 +106,30 @@ namespace gr { { // measure normalized energy of occupied sub-carriers float energy = 0; - for (int i=0; i noise){ + if(energy > noise_total){ // now we can calculate the SNR in dB - d_snr = 10*log10((energy-noise)/noise); + d_snr = 10*log10((energy-noise_total)/noise_total); } } diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h index 93f1989a..1824e9db 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ namespace gr { int d_fft_length; int d_num_carriers; int d_cyclic_prefix_length; + float *d_mag_squared; unsigned int d_freq_offset; float d_snr; diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index eea85138..01db3c0d 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index f9039bd9..303be01e 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 417e1664bf40d1aaef8765496c9eb6f4e22664ea Mon Sep 17 00:00:00 2001 From: luca Date: Wed, 17 Jan 2018 20:23:27 +0100 Subject: [PATCH 116/135] add docu and rm redundant blocks --- lib/Introduction.md | 2 +- lib/complex_to_interleaved_float_vcf_impl.cc | 64 +- lib/complex_to_interleaved_float_vcf_impl.h | 30 +- lib/conv_encoder_bb_impl.cc | 22 +- lib/conv_encoder_bb_impl.h | 18 +- lib/crc16_bb_impl.cc | 36 +- lib/crc16_test.cc | 24 - lib/dab_concatenate_signals.cc | 97 --- lib/dab_concatenate_signals.h | 65 -- lib/dab_measure_ber_b.cc | 67 -- lib/dab_measure_ber_b.h | 70 -- lib/dab_moving_sum_cc.cc | 96 --- lib/dab_moving_sum_cc.h | 70 -- lib/dab_puncture_vbb.cc | 86 --- lib/dab_puncture_vbb.h | 62 -- lib/dab_sum_elements_vff.cc | 72 -- lib/dab_sum_elements_vff.h | 80 --- lib/dab_transmission_frame_mux_bb_impl.cc | 66 +- lib/dab_transmission_frame_mux_bb_impl.h | 13 +- lib/demux_cc_impl.cc | 84 +-- lib/demux_cc_impl.h | 30 +- lib/diff_phasor_vcc_impl.cc | 55 +- lib/diff_phasor_vcc_impl.h | 25 +- lib/fib_sink_vb_impl.cc | 222 +++--- lib/fib_sink_vb_impl.h | 29 +- lib/fib_source_b_impl.cc | 706 +++++++++++-------- lib/fib_source_b_impl.h | 17 +- lib/firecode-checker.cpp | 15 +- lib/firecode-checker.h | 2 +- lib/firecode_check_bb_impl.cc | 23 +- lib/firecode_check_bb_impl.h | 19 +- lib/frequency_interleaver_vcc_impl.cc | 66 +- lib/frequency_interleaver_vcc_impl.h | 32 +- lib/insert_null_symbol_impl.cc | 136 ++-- lib/insert_null_symbol_impl.h | 5 +- lib/mp2_decode_bs_impl.cc | 270 ++++--- lib/mp2_decode_bs_impl.h | 9 +- lib/mp2_encode_sb_impl.cc | 63 +- lib/mp2_encode_sb_impl.h | 16 +- lib/mp4_decode_bs_impl.cc | 97 +-- lib/mp4_decode_bs_impl.h | 6 +- lib/mp4_encode_sb_impl.cc | 122 ++-- lib/mp4_encode_sb_impl.h | 25 +- 43 files changed, 1322 insertions(+), 1792 deletions(-) delete mode 100644 lib/crc16_test.cc delete mode 100644 lib/dab_concatenate_signals.cc delete mode 100644 lib/dab_concatenate_signals.h delete mode 100644 lib/dab_measure_ber_b.cc delete mode 100644 lib/dab_measure_ber_b.h delete mode 100644 lib/dab_moving_sum_cc.cc delete mode 100644 lib/dab_moving_sum_cc.h delete mode 100644 lib/dab_puncture_vbb.cc delete mode 100644 lib/dab_puncture_vbb.h delete mode 100644 lib/dab_sum_elements_vff.cc delete mode 100644 lib/dab_sum_elements_vff.h diff --git a/lib/Introduction.md b/lib/Introduction.md index c189374a..f99db8dc 100644 --- a/lib/Introduction.md +++ b/lib/Introduction.md @@ -3,4 +3,4 @@ The GNU Radio Out-Of-Tree module gr-dab contains the necessary signal processing Copyright (C) Andreas Müller, 2011 -Additions made by Moritz Luca Schmid, 2017 (Google Summer of Code Project 2017, details see https://dabtransceiver.wordpress.com/about/) +Copyright (C) Moritz Luca Schmid, 2017 (Google Summer of Code Project 2017, details see https://dabtransceiver.wordpress.com/about/) diff --git a/lib/complex_to_interleaved_float_vcf_impl.cc b/lib/complex_to_interleaved_float_vcf_impl.cc index f6180020..cdcf9041 100644 --- a/lib/complex_to_interleaved_float_vcf_impl.cc +++ b/lib/complex_to_interleaved_float_vcf_impl.cc @@ -35,41 +35,43 @@ namespace gr { namespace dab { -complex_to_interleaved_float_vcf::sptr -complex_to_interleaved_float_vcf::make(unsigned int length) -{ - return gnuradio::get_initial_sptr - (new complex_to_interleaved_float_vcf_impl(length)); -} + complex_to_interleaved_float_vcf::sptr + complex_to_interleaved_float_vcf::make(unsigned int length) { + return gnuradio::get_initial_sptr + (new complex_to_interleaved_float_vcf_impl(length)); + } + + complex_to_interleaved_float_vcf_impl::complex_to_interleaved_float_vcf_impl( + unsigned int length) + : gr::sync_block("complex_to_interleaved_float_vcf", + gr::io_signature::make(1, 1, + sizeof(gr_complex) * + length), + gr::io_signature::make(1, 1, + sizeof(float) * length * + 2)), + d_length(length) { + } -complex_to_interleaved_float_vcf_impl::complex_to_interleaved_float_vcf_impl(unsigned int length) - : gr::sync_block("complex_to_interleaved_float_vcf", - gr::io_signature::make (1, 1, sizeof(gr_complex)*length), - gr::io_signature::make (1, 1, sizeof(float)*length*2)), - d_length(length) -{ -} + int + complex_to_interleaved_float_vcf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + gr_complex const *in = (const gr_complex *) input_items[0]; + float *out = (float *) output_items[0]; -int -complex_to_interleaved_float_vcf_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - float *out = (float *) output_items[0]; + for (int i = 0; i < noutput_items; i++) { + for (unsigned int j = 0; j < d_length; j++) { + out[j] = in[j].real(); + out[j + d_length] = in[j].imag(); + } + in += d_length; + out += 2 * d_length; + } - for (int i=0; i - +/*! \brief transforms a complex vector into a real vector + * The first half of the output vector includes the real parts of the + * complex input vector, followed by the imaginary parts. + * + * @param length length of the complex input vector + */ namespace gr { namespace dab { -class complex_to_interleaved_float_vcf_impl : public complex_to_interleaved_float_vcf -{ - private: + class complex_to_interleaved_float_vcf_impl + : public complex_to_interleaved_float_vcf { + private: + unsigned int d_length; /*!< length of the complex input vector */ - unsigned int d_length; + public: + complex_to_interleaved_float_vcf_impl(unsigned int length); - public: - complex_to_interleaved_float_vcf_impl(unsigned int length); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -} + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + } } #endif /* INCLUDED_DAB_COMPLEX_TO_INTERLEAVED_FLOAT_VCF_H */ diff --git a/lib/conv_encoder_bb_impl.cc b/lib/conv_encoder_bb_impl.cc index c00ee5f2..186326f5 100644 --- a/lib/conv_encoder_bb_impl.cc +++ b/lib/conv_encoder_bb_impl.cc @@ -35,8 +35,7 @@ namespace gr { namespace dab { conv_encoder_bb::sptr - conv_encoder_bb::make(int framesize) - { + conv_encoder_bb::make(int framesize) { return gnuradio::get_initial_sptr (new conv_encoder_bb_impl(framesize)); } @@ -66,9 +65,9 @@ namespace gr { conv_encoder_bb_impl::conv_encoder_bb_impl(int framesize) : gr::block("conv_encoder_bb", gr::io_signature::make(1, 1, sizeof(unsigned char)), - gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_framesize(framesize) - { + gr::io_signature::make(1, 1, + sizeof(unsigned char))), + d_framesize(framesize) { d_outsize = (d_framesize * 4) + 3; set_output_multiple(framesize * 4 + 3); } @@ -76,22 +75,21 @@ namespace gr { /* * Our virtual destructor. */ - conv_encoder_bb_impl::~conv_encoder_bb_impl() - { + conv_encoder_bb_impl::~conv_encoder_bb_impl() { } void - conv_encoder_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = (noutput_items / (d_framesize * 4 + 3)) * d_framesize; + conv_encoder_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = + (noutput_items / (d_framesize * 4 + 3)) * d_framesize; } int conv_encoder_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; d_memory = 0; diff --git a/lib/conv_encoder_bb_impl.h b/lib/conv_encoder_bb_impl.h index 62317903..a43de27a 100644 --- a/lib/conv_encoder_bb_impl.h +++ b/lib/conv_encoder_bb_impl.h @@ -31,10 +31,12 @@ namespace gr { namespace dab { -/*! \brief convolutional encoding for DAB without puncturing +/*! \brief convolutional encoding for DAB/DAB+ without puncturing * * convolutional encoder according to DAB standard ETSI EN 300 401 V1.4.1 - * code rate R=1/4, polyonoms in octal form: [133, 171, 145, 133], appends 3*8 tailbits to mother codeword (flush out of state register) + * code rate R=1/4, polyonoms in octal form: [133, 171, 145, 133], + * appends 3*8 tailbits to mother codeword (flush out of state register) + * * input and output are packed bytes * * @param framesize size of packed bytes in one frame; output framelenght is 4*framesize+3 in packed bytes @@ -42,10 +44,10 @@ namespace gr { */ class conv_encoder_bb_impl : public conv_encoder_bb { private: - int d_framesize; - int d_outsize; - unsigned int d_in_offset, d_out_offset; - uint16_t d_memory; + int d_framesize; /*!< size of packed bytes in one frame */ + int d_outsize; /*!< = d_framesize * 4 + 3 */ + unsigned int d_in_offset, d_out_offset; /*!< control variable for buffer read/write operations */ + uint16_t d_memory; /*!< virtual shift register for convolutional encoder */ public: @@ -54,14 +56,14 @@ namespace gr { ~conv_encoder_bb_impl(); // Where all the action really happens - void forecast(int noutput_items, gr_vector_int &ninput_items_required); + void + forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); }; - } // namespace dab } // namespace gr diff --git a/lib/crc16_bb_impl.cc b/lib/crc16_bb_impl.cc index 95bbe040..3a48978b 100644 --- a/lib/crc16_bb_impl.cc +++ b/lib/crc16_bb_impl.cc @@ -30,27 +30,29 @@ namespace gr { namespace dab { crc16_bb::sptr - crc16_bb::make(int length = 32, uint16_t generator = 0x1021, uint16_t initial_state = 0xFF) - { + crc16_bb::make(int length = 32, uint16_t generator = 0x1021, + uint16_t initial_state = 0xFF) { return gnuradio::get_initial_sptr (new crc16_bb_impl(length, generator, initial_state)); } - crc16_bb_impl::crc16_bb_impl(int length, uint16_t generator, uint16_t initial_state) + crc16_bb_impl::crc16_bb_impl(int length, uint16_t generator, + uint16_t initial_state) : gr::block("crc16_bb", - gr::io_signature::make(1, 1, length * sizeof(char)), /*FIB without CRC (zeros instead)*/ - gr::io_signature::make(1, 1, length * sizeof(char))), /*FIB with CRC16*/ - d_length(length), d_generator(generator), d_initial_state(initial_state) - { + gr::io_signature::make(1, 1, length * + sizeof(char)), /*FIB without CRC (zeros instead)*/ + gr::io_signature::make(1, 1, length * + sizeof(char))), /*FIB with CRC16*/ + d_length(length), d_generator(generator), + d_initial_state(initial_state) { } - crc16_bb_impl::~crc16_bb_impl() - { + crc16_bb_impl::~crc16_bb_impl() { } void - crc16_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + crc16_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } @@ -58,8 +60,7 @@ namespace gr { crc16_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const char *in = (const char *) input_items[0]; char *out = (char *) output_items[0]; @@ -69,7 +70,8 @@ namespace gr { out[i + n * d_length] = in[i + n * d_length]; } //calculate crc16 word - d_crc = crc16(in + n * d_length, d_length, d_generator, d_initial_state); + d_crc = crc16(in + n * d_length, d_length, d_generator, + d_initial_state); //sanity check (last 2 bytes should be zeros) if (in[30 + n * d_length] != 0 || in[31 + n * d_length] != 0) { @@ -77,9 +79,11 @@ namespace gr { } //write calculated crc to vector (overwrite last 2 bytes) - out[d_length - 2 + n * d_length] = (char) (d_crc >> 8);//add MSByte first to FIB + out[d_length - 2 + n * d_length] = (char) (d_crc + >> 8);//add MSByte first to FIB out[d_length - 1 + n * d_length] = - (char) (out[d_length - 2 + n * d_length] << 8) ^ d_crc; //add LSByte second to FIB + (char) (out[d_length - 2 + n * d_length] << 8) ^ + d_crc; //add LSByte second to FIB } // Tell runtime system how many input items we consumed on // each input stream. diff --git a/lib/crc16_test.cc b/lib/crc16_test.cc deleted file mode 100644 index e3e63461..00000000 --- a/lib/crc16_test.cc +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include -#include "crc16.h" - -char packet[] = {0x05,0x00,0x10,0x08,0x0E,0x3C,0x17,0x01,0x2C,0x00,0x88,0x30,0x3C,0x30,0x23,0x40,0x90,0x23,0x44,0xF0,0x2D,0x49,0x7C,0x1A,0x4D,0xC2,0x10,0x51,0xF2,0x23,0x7B,0xFA}; - -int main(void) { - uint16_t actual; - printf("actual CRC: %x\n",(uint8_t)packet[30]*256+(uint8_t)packet[31]); - actual = (uint8_t)packet[30]*256+(uint8_t)packet[31]; - printf("CRC of whole packet (should be zero): %x\n",crc16(packet,32,0x1021,0xffff)); - assert(crc16(packet,32,0x1021,0xffff)==0); - packet[10]=0; - printf("CRC of whole packet withe error (should not be zero): %x\n",crc16(packet,32,0x1021,0xffff)); - assert(crc16(packet,32,0x1021,0xffff)!=0); - packet[10] = 0x88; - packet[30]=0; - packet[31]=0; - printf("calculated CRC: %x\n",crc16(packet,32,0x1021,0xffff)); - assert(actual==crc16(packet,32,0x1021,0xffff)); - printf("ALL TESTS OK\n"); -} diff --git a/lib/dab_concatenate_signals.cc b/lib/dab_concatenate_signals.cc deleted file mode 100644 index 38324428..00000000 --- a/lib/dab_concatenate_signals.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include -#include - -dab_concatenate_signals_sptr -dab_make_concatenate_signals (size_t itemsize) -{ - return gnuradio::get_initial_sptr (new dab_concatenate_signals (itemsize)); -} - -dab_concatenate_signals::dab_concatenate_signals (size_t itemsize) - : gr_block ("concatenate_signals", - gr_make_io_signature (1, -1, itemsize), - gr_make_io_signature (1, 1, itemsize)), - d_itemsize(itemsize), d_current_signal(0), d_callmetwice(1) -{ -} - -void -dab_concatenate_signals::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned int ninputs = ninput_items_required.size(); - // printf("noutput_items: %d\n", noutput_items); - - if (d_current_signal make sure the scheduler notices it */ - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = noutput_items; - } -} - - -int -dab_concatenate_signals::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - unsigned int ninputs = input_items.size (); - int produced; - - // for (unsigned int i=0; i < ninputs; i++) - // printf("input %d: has %d items\n", i, ninput_items[i]); - // printf("current signal: %d\n", d_current_signal); - - if (d_current_signal == ninputs) /* no more streams - finished */ - return -1; - - if (ninput_items[d_current_signal]==0) { /* no more input - go to next stream */ - if (d_callmetwice == 0) /* workaround: general_work gets called with no inputs right at the start in any case */ - d_current_signal++; - else - d_callmetwice--; - // sched_yield(); [> let other threads run .. <] - return 0; - } - - d_callmetwice = 1; - - produced = (noutput_items - -class dab_concatenate_signals; -typedef boost::shared_ptr dab_concatenate_signals_sptr; - -dab_concatenate_signals_sptr dab_make_concatenate_signals (size_t itemsize); - -/*! - * \brief Concatenate all input signals in time - * - * \ingroup flow - * \param itemsize size of input and output items - * - * output: first input stream, as long as it has samples, then second input stream, etc... - * - * Note: Altough this block works with simple vectors, it seems that samples - * get lost when more complicated blocks are used. - */ -class dab_concatenate_signals : public gr_block -{ - private: - friend dab_concatenate_signals_sptr dab_make_concatenate_signals (size_t itemsize); - - dab_concatenate_signals (size_t itemsize); - - size_t d_itemsize; - unsigned int d_current_signal; - unsigned int d_callmetwice; - - public: - - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - void reset() { d_current_signal=0; } -}; - -#endif diff --git a/lib/dab_measure_ber_b.cc b/lib/dab_measure_ber_b.cc deleted file mode 100644 index a0c27113..00000000 --- a/lib/dab_measure_ber_b.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -dab_measure_ber_b_sptr -dab_make_measure_ber_b () -{ - return gnuradio::get_initial_sptr (new dab_measure_ber_b ()); -} - -dab_measure_ber_b::dab_measure_ber_b() - : gr_sync_block ("measure_ber_b", - gr_make_io_signature2(2, 2, sizeof(char), sizeof(char)), - gr_make_io_signature(0, 0, 0)), - d_bytes(0), d_errors(0) -{ -} - -unsigned int dab_measure_ber_b::bits_set(char byte) { - char bits = 0; - for (int i=0; i<8; i++) - if (byte&(1< - -class dab_measure_ber_b; -typedef boost::shared_ptr dab_measure_ber_b_sptr; - -dab_measure_ber_b_sptr dab_make_measure_ber_b(); - -/*! - * \brief Measure bit error rate of a byte stream - * - * input: port 0: actual byte stream - * input: port 1: expected byte stream - * - * \ingroup sink - */ -class dab_measure_ber_b : public gr_sync_block -{ - friend dab_measure_ber_b_sptr dab_make_measure_ber_b(); - - private: - unsigned long d_bytes; - unsigned long d_errors; - - protected: - unsigned int bits_set(char byte); - dab_measure_ber_b(); - - public: - /*! clear error and byte count */ - void clear() { d_errors=0; d_bytes=0; } - /*! \return bit error rate */ - float ber() { return (float)d_errors/(float)(d_bytes*8); } - /*! \return number of received bytes */ - unsigned long bytecount() { return d_bytes; } - /*! \return number of received bits */ - unsigned long bitcount() { return 8*d_bytes; } - /*! \return number of received bits with errors */ - unsigned long errorcount() { return d_errors; } - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_MEASURE_BER_B_H */ diff --git a/lib/dab_moving_sum_cc.cc b/lib/dab_moving_sum_cc.cc deleted file mode 100644 index 5f0d2e0a..00000000 --- a/lib/dab_moving_sum_cc.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -/* - * Create a new instance of dab_moving_sum_cc and return - * a boost shared_ptr. This is effectively the public constructor. - */ -dab_moving_sum_cc_sptr -dab_make_moving_sum_cc (int length) -{ - return gnuradio::get_initial_sptr (new dab_moving_sum_cc (length)); -} - -/* - * Specify constraints on number of input and output streams. - * This info is used to construct the input and output signatures - * (2nd & 3rd args to gr_block's constructor). The input and - * output signatures are used by the runtime system to - * check that a valid number and type of inputs and outputs - * are connected to this block. In this case, we accept - * only 1 input and 1 output. - */ -static const int MIN_IN = 1; // mininum number of input streams -static const int MAX_IN = 1; // maximum number of input streams -static const int MIN_OUT = 1; // minimum number of output streams -static const int MAX_OUT = 1; // maximum number of output streams - -/* - * The private constructor - */ -dab_moving_sum_cc::dab_moving_sum_cc (int length) - : gr_sync_block ("moving_sum_cc", - gr_make_io_signature (MIN_IN, MAX_IN, sizeof (gr_complex)), - gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex))), - d_sum(0), d_length(length) -{ - assert(length>=0); - set_history(length+1); - set_output_multiple(length+1); -} - -/* - * Our virtual destructor. - */ -dab_moving_sum_cc::~dab_moving_sum_cc () -{ - // nothing else required in this example -} - -int -dab_moving_sum_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - - for (int i=0; i < noutput_items; i++) { - d_sum+=(gr_complexd)in[i+d_length]-(gr_complexd)in[i]; - out[i] = (gr_complex)d_sum; - } - - // Tell runtime system how many output items we produced. - return noutput_items; -} diff --git a/lib/dab_moving_sum_cc.h b/lib/dab_moving_sum_cc.h deleted file mode 100644 index 97ab0117..00000000 --- a/lib/dab_moving_sum_cc.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_DAB_MOVING_SUM_CC_H -#define INCLUDED_DAB_MOVING_SUM_CC_H - -#include - -class dab_moving_sum_cc; - -typedef boost::shared_ptr dab_moving_sum_cc_sptr; - -dab_moving_sum_cc_sptr dab_make_moving_sum_cc (int length); - -/*! - * \brief Moving sum over a stream of complex floats. - * \ingroup filter - * \param length length of the moving sum (=number of taps) - * - * input: complex - * output: complex - * - * This is the same as an FIR filter with length taps 1, but much faster - * (linear time instead of O(n*m)). On the other hand, since only the diff is - * calculated for each sample, there is some chance of an accumulating error. - */ -class dab_moving_sum_cc : public gr_sync_block -{ -private: - // The friend declaration allows dab_make_moving_sum_cc to - // access the private constructor. - - friend dab_moving_sum_cc_sptr dab_make_moving_sum_cc (int length); - - dab_moving_sum_cc (int length); // private constructor - - gr_complexd d_sum; - int d_length; - - public: - ~dab_moving_sum_cc (); // public destructor - int length() const {return d_length;} - void reset() {d_sum=0;} - - // Where all the action really happens - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_MOVING_SUM_CC_H */ diff --git a/lib/dab_puncture_vbb.cc b/lib/dab_puncture_vbb.cc deleted file mode 100644 index 59524f0b..00000000 --- a/lib/dab_puncture_vbb.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -/* - * Create a new instance of dab_puncture_vbb and return - * a boost shared_ptr. This is effectively the public constructor. - */ -dab_puncture_vbb_sptr -dab_make_puncture_vbb(const std::vector &puncturing_vector) -{ - return gnuradio::get_initial_sptr(new dab_puncture_vbb(puncturing_vector)); -} - -unsigned int dab_puncture_vbb::ones(const std::vector &puncturing_vector) -{ - unsigned int onescount = 0; - for (unsigned int i = 0; i < puncturing_vector.size(); i++) { - if (puncturing_vector[i] == 1) - onescount++; - } - return onescount; -} - -dab_puncture_vbb::dab_puncture_vbb(const std::vector &puncturing_vector) : - gr_sync_block("puncture_vbb", - gr_make_io_signature(1, 1, sizeof(char) * puncturing_vector.size()), - gr_make_io_signature(1, 1, sizeof(char) * ones(puncturing_vector))), - d_puncturing_vector(puncturing_vector) -{ - d_vlen_in = puncturing_vector.size(); - d_vlen_out = ones(puncturing_vector); -} - -int -dab_puncture_vbb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int i; - unsigned int j; - - const char *in = (const char *) input_items[0]; - char *out = (char *) output_items[0]; - - for (i = 0; i < noutput_items; i++) { - for (j = 0; j < d_vlen_in; j++) { - if (d_puncturing_vector[j] == 1) { - *out++ = *in++; - } else - in++; - } - } - - return noutput_items; -} diff --git a/lib/dab_puncture_vbb.h b/lib/dab_puncture_vbb.h deleted file mode 100644 index 9d4eafc2..00000000 --- a/lib/dab_puncture_vbb.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_PUNCTURE_VBB_H -#define INCLUDED_DAB_PUNCTURE_VBB_H - -#include - -class dab_puncture_vbb; - -typedef boost::shared_ptr dab_puncture_vbb_sptr; - -dab_puncture_vbb_sptr -dab_make_puncture_vbb(const std::vector &puncturing_vector); - -/*! - * \brief Puncturing - remove bits, where the puncturing sequence is zero - * \ingroup DAB - * \param puncturing_vector describes, which bits are removed (1=keep, 0=remove) - * - * input: byte vector whose length equals the length of the puncturing vector - * output: byte vector whose length equeals the number of ones in the puncturing vector - */ -class dab_puncture_vbb : public gr_sync_block { -private: - friend dab_puncture_vbb_sptr - dab_make_puncture_vbb(const std::vector &puncturing_vector); - - unsigned int ones(const std::vector &puncturing_vector); - - dab_puncture_vbb(const std::vector &puncturing_vector); // private constructor - - std::vector d_puncturing_vector; - unsigned int d_vlen_in; - unsigned int d_vlen_out; - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_PUNCTURE_VBB_H */ diff --git a/lib/dab_sum_elements_vff.cc b/lib/dab_sum_elements_vff.cc deleted file mode 100644 index 66d16355..00000000 --- a/lib/dab_sum_elements_vff.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * config.h is generated by configure. It contains the results - * of probing for features, options etc. It should be the first - * file included in your .cc file. - */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -/* - * Create a new instance of dab_sum_elements_vff and return - * a boost shared_ptr. This is effectively the public constructor. - */ -dab_sum_elements_vff_sptr -dab_make_sum_elements_vff (unsigned int length) -{ - return gnuradio::get_initial_sptr (new dab_sum_elements_vff (length)); -} - -dab_sum_elements_vff::dab_sum_elements_vff (unsigned int length) : - gr_sync_block ("sum_elements_vff", - gr_make_io_signature (1, 1, sizeof(float)*length), - gr_make_io_signature (1, 1, sizeof(float))), - d_length(length) -{ -} - - -int -dab_sum_elements_vff::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - double sum; - - for (int i = 0; i < noutput_items; i++){ - sum = 0; - for (unsigned int j = 0; j < d_length; j++) - sum += *in++; - *out++ = (float)sum; - } - - return noutput_items; -} diff --git a/lib/dab_sum_elements_vff.h b/lib/dab_sum_elements_vff.h deleted file mode 100644 index 45d9fbaa..00000000 --- a/lib/dab_sum_elements_vff.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_DAB_SUM_ELEMENTS_VFF_H -#define INCLUDED_DAB_SUM_ELEMENTS_VFF_H - -#include - -class dab_sum_elements_vff; - -/* - * We use boost::shared_ptr's instead of raw pointers for all access - * to gr_blocks (and many other data structures). The shared_ptr gets - * us transparent reference counting, which greatly simplifies storage - * management issues. This is especially helpful in our hybrid - * C++ / Python system. - * - * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm - * - * As a convention, the _sptr suffix indicates a boost::shared_ptr - */ -typedef boost::shared_ptr dab_sum_elements_vff_sptr; - -/*! - * \brief Return a shared_ptr to a new instance of dab_sum_elements_vff. - * - * To avoid accidental use of raw pointers, dab_sum_elements_vff's - * constructor is private. dab_make_sum_elements_vff is the public - * interface for creating new instances. - */ -dab_sum_elements_vff_sptr -dab_make_sum_elements_vff (unsigned int length); - -/*! - * \brief Sum up all elements of a vector - * \ingroup math - * \param length length of the vector - * \return \f[ y[k] = \sum_{i=1}^n x_i[k]\f] - * - * input: float vector - * output: float - */ -class dab_sum_elements_vff : public gr_sync_block -{ - private: - // The friend declaration allows dab_make_sum_elements_vff to - // access the private constructor. - - friend dab_sum_elements_vff_sptr - dab_make_sum_elements_vff (unsigned int length); - - dab_sum_elements_vff (unsigned int length); // private constructor - - unsigned int d_length; - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_DAB_SUM_ELEMENTS_VFF_H */ diff --git a/lib/dab_transmission_frame_mux_bb_impl.cc b/lib/dab_transmission_frame_mux_bb_impl.cc index b33e3b54..9eed5f60 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.cc +++ b/lib/dab_transmission_frame_mux_bb_impl.cc @@ -31,22 +31,24 @@ namespace gr { dab_transmission_frame_mux_bb::sptr dab_transmission_frame_mux_bb::make(int transmission_mode, int num_subch, - const std::vector &subch_size) - { + const std::vector &subch_size) { return gnuradio::get_initial_sptr - (new dab_transmission_frame_mux_bb_impl(transmission_mode, num_subch, subch_size)); + (new dab_transmission_frame_mux_bb_impl(transmission_mode, + num_subch, subch_size)); } /* * The private constructor */ - dab_transmission_frame_mux_bb_impl::dab_transmission_frame_mux_bb_impl(int transmission_mode, int num_subch, - const std::vector &subch_size) + dab_transmission_frame_mux_bb_impl::dab_transmission_frame_mux_bb_impl( + int transmission_mode, int num_subch, + const std::vector &subch_size) : gr::block("dab_transmission_frame_mux_bb", - gr::io_signature::make(1 + num_subch, 1 + num_subch, sizeof(unsigned char)), + gr::io_signature::make(1 + num_subch, 1 + num_subch, + sizeof(unsigned char)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_transmission_mode(transmission_mode), d_subch_size(subch_size), d_num_subch(num_subch) - { + d_transmission_mode(transmission_mode), d_subch_size(subch_size), + d_num_subch(num_subch) { switch (transmission_mode) { case 1: d_num_fibs = 12; @@ -65,10 +67,13 @@ namespace gr { d_num_cifs = 2; break; default: - throw std::invalid_argument((boost::format("Transmission mode %d doesn't exist") % transmission_mode).str()); + throw std::invalid_argument( + (boost::format("Transmission mode %d doesn't exist") % + transmission_mode).str()); } if (subch_size.size() != num_subch) { - GR_LOG_WARN(d_logger, "sizeof vector subch_size does not match with num_subch"); + GR_LOG_WARN(d_logger, + "sizeof vector subch_size does not match with num_subch"); } d_vlen_out = d_num_fibs * d_fib_len + d_num_cifs * d_cif_len; d_fic_len = d_num_fibs * d_fib_len; @@ -77,38 +82,42 @@ namespace gr { d_subch_total_size += subch_size[i]; } if (d_subch_total_size * d_cu_len > d_cif_len) { - throw std::out_of_range((boost::format("subchannels are %d bytes too long for CIF") % (d_subch_total_size * d_cu_len - d_cif_len)).str()); + throw std::out_of_range( + (boost::format("subchannels are %d bytes too long for CIF") % + (d_subch_total_size * d_cu_len - d_cif_len)).str()); } - GR_LOG_DEBUG(d_logger, boost::format("MUX init with: fic_len = %d, subch_total_size = %d, vlen_out = %d")%d_fic_len %d_subch_total_size %d_vlen_out); + GR_LOG_DEBUG(d_logger, boost::format( + "MUX init with: fic_len = %d, subch_total_size = %d, vlen_out = %d") % + d_fic_len % d_subch_total_size % d_vlen_out); set_output_multiple(d_vlen_out); // generate PRBS for padding generate_prbs(d_prbs, sizeof(d_prbs)); - GR_LOG_DEBUG(d_logger, boost::format("key num_subch: %d") %d_num_subch); + GR_LOG_DEBUG(d_logger, boost::format("key num_subch: %d") % d_num_subch); } /* * Our virtual destructor. */ - dab_transmission_frame_mux_bb_impl::~dab_transmission_frame_mux_bb_impl() - { + dab_transmission_frame_mux_bb_impl::~dab_transmission_frame_mux_bb_impl() { } void - dab_transmission_frame_mux_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + dab_transmission_frame_mux_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { // the first input is always the FIC ninput_items_required[0] = d_fic_len * (noutput_items / d_vlen_out); for (int i = 0; i < d_num_subch; ++i) { // the amount of consumed data of each sub-channel depends on its size - ninput_items_required[i + 1] = d_subch_size[i] * d_cu_len * d_num_cifs * (noutput_items / d_vlen_out); + ninput_items_required[i + 1] = d_subch_size[i] * d_cu_len * d_num_cifs * + (noutput_items / d_vlen_out); } } void - dab_transmission_frame_mux_bb_impl::generate_prbs(unsigned char *out_ptr, int length) - { + dab_transmission_frame_mux_bb_impl::generate_prbs(unsigned char *out_ptr, + int length) { char bits[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; char newbit; unsigned char temp = 0; @@ -129,8 +138,7 @@ namespace gr { dab_transmission_frame_mux_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { unsigned char *out = (unsigned char *) output_items[0]; //unsigned char *triggerout = (unsigned char *) output_items[1]; //const unsigned char *in; @@ -150,30 +158,32 @@ namespace gr { // write sub-channels unsigned int cu_index = 0; for (int j = 0; j < d_num_subch; ++j) { - const unsigned char *in_msc = (const unsigned char *) input_items[j + 1]; + const unsigned char *in_msc = (const unsigned char *) input_items[j + + 1]; for (int i = 0; i < noutput_items / d_vlen_out; ++i) { for (int k = 0; k < d_num_cifs; ++k) { - memcpy(out + i * d_vlen_out + d_fic_len + k * d_cif_len + cu_index * d_cu_len, in_msc + (i * d_num_cifs + k) * d_subch_size[j] * d_cu_len, d_subch_size[j] * d_cu_len); - //printf("input %d, item %d, cif %d, in_adress %d, in_val %d, out_adress %d\n", j, i, k, (i*d_num_cifs + k)*d_subch_size[j]*d_cu_len, in[(i*d_num_cifs + k)*d_subch_size[j]*d_cu_len], i*d_vlen_out + d_fic_len + k*d_cif_len + cu_index*d_cu_len); + memcpy(out + i * d_vlen_out + d_fic_len + k * d_cif_len + + cu_index * d_cu_len, + in_msc + (i * d_num_cifs + k) * d_subch_size[j] * d_cu_len, + d_subch_size[j] * d_cu_len); } } cu_index += d_subch_size[j]; } // fill remaining cus with padding for (int i = 0; i < noutput_items / d_vlen_out; ++i) { - //memcpy(out + i*d_vlen_out + d_num_fibs*d_fib_len + d_subch_total_size*d_cu_len, d_prbs + d_subch_total_size*d_cu_len*8, (d_vlen_out - d_num_fibs*d_fib_len - d_subch_total_size*d_cu_len)*8); for (int j = d_subch_total_size * d_cu_len; j < d_cif_len; ++j) { for (int k = 0; k < d_num_cifs; ++k) { out[i * d_vlen_out + d_fic_len + k * d_cif_len + j] = d_prbs[j]; } } } - // Tell runtime system how many input items we consumed on // each input stream. consume(0, noutput_items / d_vlen_out * d_fic_len); for (int j = 0; j < d_num_subch; ++j) { - consume(j + 1, noutput_items / d_vlen_out * d_subch_size[j] * d_cu_len * d_num_cifs); + consume(j + 1, noutput_items / d_vlen_out * d_subch_size[j] * d_cu_len * + d_num_cifs); } // Tell runtime system how many output items we produced. diff --git a/lib/dab_transmission_frame_mux_bb_impl.h b/lib/dab_transmission_frame_mux_bb_impl.h index 40ff73f9..684d5c19 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.h +++ b/lib/dab_transmission_frame_mux_bb_impl.h @@ -27,19 +27,22 @@ namespace gr { namespace dab { /*! \brief multiplex to DAB transmission frames * - * block multiplexes the FIBs of the FIC and all subchannels of the MCI to a transmission frame according to ETSI EN 300 401 - * the number of FIBs per CIF and the number of CIFs per transmission frame depends on the transmission mode - * the maximum number of supported sub-channels is 7 + * block multiplexes the FIBs of the FIC and all subchannels of the MCI to a + * transmission frame according to ETSI EN 300 401 + * the number of FIBs per CIF and the number of CIFs per transmission frame + * depends on the transmission mode * * @param transmission_mode transmission mode 1-4 after DAB standard * @param subch_size vector with size of each subchannel */ - class dab_transmission_frame_mux_bb_impl : public dab_transmission_frame_mux_bb { + class dab_transmission_frame_mux_bb_impl + : public dab_transmission_frame_mux_bb { private: int d_transmission_mode; int d_num_subch; std::vector d_subch_size; - const static unsigned int d_fib_len = 32*3; // length of a fib in bytes (*3 because bit rate = 1/3) + const static unsigned int d_fib_len = + 32 * 3; // length of a fib in bytes (*3 because bit rate = 1/3) const static unsigned int d_cif_len = 6912; // length of a cif in bytes const static unsigned int d_cu_len = 8; // length of a capacity unit in bytes unsigned int d_vlen_out, d_num_cifs, d_num_fibs, d_subch_total_size; diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc index 49a85f85..b1021721 100644 --- a/lib/demux_cc_impl.cc +++ b/lib/demux_cc_impl.cc @@ -34,50 +34,50 @@ namespace gr { namespace dab { demux_cc::sptr - demux_cc::make(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) - { + demux_cc::make(unsigned int symbol_length, unsigned int symbols_fic, + unsigned int symbol_msc, gr_complex fillval) { return gnuradio::get_initial_sptr - (new demux_cc_impl(symbol_length, symbols_fic, symbol_msc, fillval)); + (new demux_cc_impl(symbol_length, symbols_fic, symbol_msc, + fillval)); } /* * The private constructor */ - demux_cc_impl::demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) - : gr::block("demux_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex)*symbol_length), - gr::io_signature::make(2, 2, sizeof(gr_complex)*symbol_length)), - d_symbol_lenght(symbol_length), - d_symbols_fic(symbols_fic), - d_symbols_msc(symbol_msc), - d_fillval(fillval) - { + demux_cc_impl::demux_cc_impl(unsigned int symbol_length, + unsigned int symbols_fic, + unsigned int symbol_msc, gr_complex fillval) + : gr::block("demux_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex) * + symbol_length), + gr::io_signature::make(2, 2, sizeof(gr_complex) * + symbol_length)), + d_symbol_lenght(symbol_length), + d_symbols_fic(symbols_fic), + d_symbols_msc(symbol_msc), + d_fillval(fillval) { set_tag_propagation_policy(TPP_DONT); - d_symbol_count = 0; d_fic_counter = 0; d_msc_counter = 0; - d_on_fic = true; } /* * Our virtual destructor. */ - demux_cc_impl::~demux_cc_impl() - { + demux_cc_impl::~demux_cc_impl() { } void - demux_cc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) - { + demux_cc_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } int - demux_cc_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + demux_cc_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *fic_out = (gr_complex *) output_items[0]; gr_complex *msc_out = (gr_complex *) output_items[1]; @@ -86,50 +86,54 @@ namespace gr { unsigned int msc_syms_written = 0; // get tags for the beginning of a frame - std::vector tags; + std::vector tags; const std::string s = "Start"; pmt::pmt_t d_key = pmt::string_to_symbol(s); unsigned int tag_count = 0; get_tags_in_window(tags, 0, 0, noutput_items, d_key); for (int i = 0; i < noutput_items; ++i) { - if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0) - nconsumed == 0) { + if (tag_count < tags.size() && + tags[tag_count].offset - nitems_read(0) - nconsumed == 0) { // this input symbol is tagged: a new frame begins here - if(d_fic_counter%d_symbols_fic == 0 && d_msc_counter%d_symbols_msc == 0){ + if (d_fic_counter % d_symbols_fic == 0 && + d_msc_counter % d_symbols_msc == 0) { // we are at the beginning of a frame and also finished writing the last frame // we can remove this first symbol of the frame (phase reference symbol) and copy the other symbols tag_count++; nconsumed++; d_fic_counter = 0; d_msc_counter = 0; - } - else{ + } else { // we did not finish the last frame, maybe we lost track in sync // lets fill the remaining symbols with fillval before continuing with the new input frame - if(d_fic_counter%d_symbols_fic != 0){ - memset(&fic_out[fic_syms_written++*d_symbol_lenght], 0, d_symbol_lenght * sizeof(gr_complex)); + if (d_fic_counter % d_symbols_fic != 0) { + memset(&fic_out[fic_syms_written++ * d_symbol_lenght], 0, + d_symbol_lenght * sizeof(gr_complex)); d_fic_counter++; - } - else{ - memset(&msc_out[msc_syms_written++*d_symbol_lenght], 0, d_symbol_lenght * sizeof(gr_complex)); + } else { + memset(&msc_out[msc_syms_written++ * d_symbol_lenght], 0, + d_symbol_lenght * sizeof(gr_complex)); d_msc_counter++; } } - } - else if (d_fic_counter < d_symbols_fic){ + } else if (d_fic_counter < d_symbols_fic) { // copy this symbol to fic output - memcpy(&fic_out[fic_syms_written++*d_symbol_lenght], &in[nconsumed++*d_symbol_lenght], d_symbol_lenght * sizeof(gr_complex)); + memcpy(&fic_out[fic_syms_written++ * d_symbol_lenght], + &in[nconsumed++ * d_symbol_lenght], + d_symbol_lenght * sizeof(gr_complex)); d_fic_counter++; - } - else if (d_msc_counter < d_symbols_msc){ + } else if (d_msc_counter < d_symbols_msc) { // copy this output to msc output - memcpy(&msc_out[msc_syms_written++*d_symbol_lenght], &in[nconsumed++*d_symbol_lenght], d_symbol_lenght * sizeof(gr_complex)); + memcpy(&msc_out[msc_syms_written++ * d_symbol_lenght], + &in[nconsumed++ * d_symbol_lenght], + d_symbol_lenght * sizeof(gr_complex)); d_msc_counter++; } } // Tell runtime system how many input items we consumed on // each input stream. - consume_each (nconsumed); + consume_each(nconsumed); // Tell runtime system how many output items we produced on each output stream separately. produce(0, fic_syms_written); diff --git a/lib/demux_cc_impl.h b/lib/demux_cc_impl.h index 249831b7..1a11b1b2 100644 --- a/lib/demux_cc_impl.h +++ b/lib/demux_cc_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,29 +32,31 @@ namespace gr { * \param fillval complex value to fill in if sync has been lost during frame */ - class demux_cc_impl : public demux_cc - { - private: + class demux_cc_impl : public demux_cc { + private: unsigned int d_symbol_lenght; unsigned int d_symbols_fic; - unsigned int d_fic_counter; unsigned int d_symbols_msc; - unsigned int d_msc_counter; - unsigned int d_symbol_count; - bool d_on_fic; gr_complex d_fillval; + unsigned int d_fic_counter; +/*!< counts the symbols containing fic data; + * the number of fic symbols per transmission frame does not match + * with the number of transmitted fibs*/ + unsigned int d_msc_counter; /*!< counts the symbols containing msc data*/ + + public: + demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, + unsigned int symbol_msc, gr_complex fillval); - public: - demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval); ~demux_cc_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/diff_phasor_vcc_impl.cc b/lib/diff_phasor_vcc_impl.cc index 3ba6b616..d50fd37a 100644 --- a/lib/diff_phasor_vcc_impl.cc +++ b/lib/diff_phasor_vcc_impl.cc @@ -36,37 +36,36 @@ namespace gr { namespace dab { -diff_phasor_vcc::sptr -diff_phasor_vcc::make(unsigned int length) -{ - return gnuradio::get_initial_sptr - (new diff_phasor_vcc_impl(length)); -} + diff_phasor_vcc::sptr + diff_phasor_vcc::make(unsigned int length) { + return gnuradio::get_initial_sptr + (new diff_phasor_vcc_impl(length)); + } -diff_phasor_vcc_impl::diff_phasor_vcc_impl(unsigned int length) - : gr::sync_block("diff_phasor_vcc", - gr::io_signature::make (1, 1, sizeof(gr_complex)*length), - gr::io_signature::make (1, 1, sizeof(gr_complex)*length)), - d_length(length) -{ - set_history(2); -} + diff_phasor_vcc_impl::diff_phasor_vcc_impl(unsigned int length) + : gr::sync_block("diff_phasor_vcc", + gr::io_signature::make(1, 1, sizeof(gr_complex) * + length), + gr::io_signature::make(1, 1, sizeof(gr_complex) * + length)), + d_length(length) { + set_history(2); + } -int -diff_phasor_vcc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; + int + diff_phasor_vcc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + gr_complex const *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; - for(unsigned int i = 0; i < noutput_items*d_length; i++){ - out[i] = in[i+d_length] * conj(in[i]); - } - - return noutput_items; -} + for (unsigned int i = 0; i < noutput_items * d_length; i++) { + out[i] = in[i + d_length] * conj(in[i]); + } -} + return noutput_items; + } + + } } diff --git a/lib/diff_phasor_vcc_impl.h b/lib/diff_phasor_vcc_impl.h index c5ae6f0f..67718651 100644 --- a/lib/diff_phasor_vcc_impl.h +++ b/lib/diff_phasor_vcc_impl.h @@ -26,21 +26,24 @@ namespace gr { namespace dab { +/*! \brief vector wise working differential phasor calculation + * this block has the same functionality as the gr-digital diff_phasor_cc block, + * but is working on vector basis + */ + class diff_phasor_vcc_impl : public diff_phasor_vcc { + private: -class diff_phasor_vcc_impl : public diff_phasor_vcc -{ - private: + unsigned int d_length; - unsigned int d_length; + public: + diff_phasor_vcc_impl(unsigned int length); - public: - diff_phasor_vcc_impl(unsigned int length); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; -} + } } #endif /* INCLUDED_DAB_DIFF_PHASOR_VCC_H */ diff --git a/lib/fib_sink_vb_impl.cc b/lib/fib_sink_vb_impl.cc index 4ef9cc16..fabde6a3 100644 --- a/lib/fib_sink_vb_impl.cc +++ b/lib/fib_sink_vb_impl.cc @@ -1,7 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright belongs to Andreas Mueller - * Modified 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2008 by Andreas Mueller * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,8 +41,7 @@ namespace gr { namespace dab { fib_sink_vb::sptr - fib_sink_vb::make() - { + fib_sink_vb::make() { return gnuradio::get_initial_sptr (new fib_sink_vb_impl()); } @@ -51,8 +50,7 @@ namespace gr { fib_sink_vb_impl::fib_sink_vb_impl() : gr::sync_block("fib_sink_vb", gr::io_signature::make(1, 1, sizeof(char) * 32), - gr::io_signature::make(0, 0, 0)) - { + gr::io_signature::make(0, 0, 0)) { d_service_info_written_trigger = -1; d_service_labels_written_trigger = -1; d_subch_info_written_trigger = -1; @@ -61,8 +59,7 @@ namespace gr { } int - fib_sink_vb_impl::process_fib(const char *fib) - { + fib_sink_vb_impl::process_fib(const char *fib) { uint8_t type, length, pos; if (crc16(fib, FIB_LENGTH, FIB_CRC_POLY, FIB_CRC_INITSTATE) != 0) { GR_LOG_DEBUG(d_logger, "FIB CRC error"); @@ -72,7 +69,8 @@ namespace gr { GR_LOG_DEBUG(d_logger, "FIB correct"); d_crc_passed = true; pos = 0; - while (pos < FIB_LENGTH - FIB_CRC_LENGTH && (uint8_t) fib[pos] != FIB_ENDMARKER && + while (pos < FIB_LENGTH - FIB_CRC_LENGTH && + (uint8_t) fib[pos] != FIB_ENDMARKER && (uint8_t) fib[pos] != 0) { //TODO correct? type = fib[pos] >> 5; length = fib[pos] & 0x1f; @@ -85,35 +83,43 @@ namespace gr { } int - fib_sink_vb_impl::process_fig(uint8_t type, const char *data, uint8_t length) - { + fib_sink_vb_impl::process_fig(uint8_t type, const char *data, + uint8_t length) { uint8_t cn, oe, pd, extension; switch (type) { case FIB_FIG_TYPE_MCI: GR_LOG_DEBUG(d_logger, "FIG type 0"); extension = (uint8_t)(data[1] & 0x1f); cn = (uint8_t)(data[1] & 0x80); - if (cn == 1) GR_LOG_DEBUG(d_logger, "[WARNING, INFO FOR FUTURE CONFIGURATION]: "); + if (cn == 1) + GR_LOG_DEBUG(d_logger, + "[WARNING, INFO FOR FUTURE CONFIGURATION]: "); oe = (uint8_t)(data[1] & 0x40); - if (cn == 1) GR_LOG_DEBUG(d_logger, "[WARNING, INFO FOR OTHER ENSEMBLE]"); + if (cn == 1) + GR_LOG_DEBUG(d_logger, "[WARNING, INFO FOR OTHER ENSEMBLE]"); pd = (uint8_t)(data[1] & 0x20); if (pd == 1) GR_LOG_DEBUG(d_logger, "[WARNING, LONG IDENTIFIER"); switch (extension) { case FIB_MCI_EXTENSION_ENSEMBLE_INFO: { uint8_t country_ID = (uint8_t)((data[2] & 0xf0) >> 4); - uint16_t ensemble_reference = (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; + uint16_t ensemble_reference = + (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; uint8_t change_flag = (uint8_t)((data[4] & 0xc0) >> 6); uint8_t occurrence_change = data[6]; if (change_flag != 0) GR_LOG_DEBUG(d_logger, - format(", [CHANGE OF SUBCHANNEL OR SERVICE ORGA (%d)](at CIF %d) ") % (int) change_flag % + format(", [CHANGE OF SUBCHANNEL OR SERVICE ORGA (%d)](at CIF %d) ") % + (int) change_flag % (int) occurrence_change); uint8_t alarm_flag = (uint8_t)((data[4] & 0x20) >> 5); - if (alarm_flag == 1) GR_LOG_DEBUG(d_logger, ", [ALARM MESSAGE ACCESSIBLE] "); - uint16_t CIF_counter = (uint16_t)((data[4] & 0x1f) * 250 + (data[5])); + if (alarm_flag == 1) + GR_LOG_DEBUG(d_logger, ", [ALARM MESSAGE ACCESSIBLE] "); + uint16_t CIF_counter = (uint16_t)( + (data[4] & 0x1f) * 250 + (data[5])); GR_LOG_DEBUG(d_logger, - format("ensemble info: reference %d, country ID %d, CIF counter = %d") % ensemble_reference % + format("ensemble info: reference %d, country ID %d, CIF counter = %d") % + ensemble_reference % (int) country_ID % CIF_counter); break; } @@ -121,25 +127,35 @@ namespace gr { uint8_t subch_counter = 0; GR_LOG_DEBUG(d_logger, "subchannel orga: "); do { - uint8_t subchID = (uint8_t)((data[2 + subch_counter] & 0xfc) >> 2); - uint16_t start_address = (uint16_t)((data[2 + subch_counter] & 0x03) << 8) | - (uint8_t)(data[3 + subch_counter]); + uint8_t subchID = (uint8_t)( + (data[2 + subch_counter] & 0xfc) >> 2); + uint16_t start_address = + (uint16_t)((data[2 + subch_counter] & 0x03) << 8) | + (uint8_t)(data[3 + subch_counter]); uint8_t sl_form = (uint8_t)(data[4] & 0x80); if (sl_form == 0) { - uint8_t table_switch = (uint8_t)(data[4 + subch_counter] & 0x40); - if (table_switch != 0) GR_LOG_DEBUG(d_logger, " [WARNING: OTHER TABLE USED] "); - uint8_t table_index = (uint8_t)(data[4 + subch_counter] & 0x3f); - GR_LOG_DEBUG(d_logger, format("subchID = %d , start address = %d, index %d") % (int) subchID % - (int) start_address % (int) table_index); + uint8_t table_switch = (uint8_t)( + data[4 + subch_counter] & 0x40); + if (table_switch != 0) + GR_LOG_DEBUG(d_logger, " [WARNING: OTHER TABLE USED] "); + uint8_t table_index = (uint8_t)( + data[4 + subch_counter] & 0x3f); + GR_LOG_DEBUG(d_logger, + format("subchID = %d , start address = %d, index %d") % + (int) subchID % + (int) start_address % (int) table_index); subch_counter += 3; } else { uint8_t option = (uint8_t)(data[4 + subch_counter] & 0x70); - uint8_t protect_level = (uint8_t)((data[4 + subch_counter] & 0x0c) >> 2); - uint16_t subch_size = (uint16_t)((data[4 + subch_counter] & 0x03) << 8) | - (uint8_t)(data[5 + subch_counter]); + uint8_t protect_level = (uint8_t)( + (data[4 + subch_counter] & 0x0c) >> 2); + uint16_t subch_size = + (uint16_t)((data[4 + subch_counter] & 0x03) << 8) | + (uint8_t)(data[5 + subch_counter]); GR_LOG_DEBUG(d_logger, format("subchID = %d , start address = %d, option %d, protect level %d, subch size %d") % - (int) subchID % (int) start_address % (int) option % (int) protect_level % + (int) subchID % (int) start_address % + (int) option % (int) protect_level % (int) subch_size); subch_counter += 4; @@ -148,8 +164,10 @@ namespace gr { d_subch_info_written_trigger = (int) subchID; } else { std::stringstream ss; - ss << d_subch_info_current << ",{" << "\"ID\":" << (int) subchID << ",\"address\":" - << (int) start_address << ",\"protection\":" << (int) protect_level << ",\"size\":" + ss << d_subch_info_current << ",{" << "\"ID\":" + << (int) subchID << ",\"address\":" + << (int) start_address << ",\"protection\":" + << (int) protect_level << ",\"size\":" << (int) subch_size << "}\0"; d_subch_info_current = ss.str(); if ((int) subchID == d_subch_info_written_trigger) { @@ -168,32 +186,48 @@ namespace gr { case FIB_MCI_EXTENSION_SERVICE_ORGA: { uint8_t service_counter = 1; do { //iterate over services - uint16_t service_reference = (uint16_t)(data[service_counter + 1] & 0x0f) << 8 | - (uint8_t) data[service_counter + 2]; - GR_LOG_DEBUG(d_logger, format("service orga: reference %d ") % service_reference); - uint8_t local_flag = (uint8_t)((data[service_counter + 3] & 0x80) >> 7); - if (local_flag == 1) GR_LOG_DEBUG(d_logger, "[LOCAL FLAG SET] "); + uint16_t service_reference = + (uint16_t)(data[service_counter + 1] & 0x0f) << 8 | + (uint8_t) data[service_counter + 2]; + GR_LOG_DEBUG(d_logger, format("service orga: reference %d ") % + service_reference); + uint8_t local_flag = (uint8_t)( + (data[service_counter + 3] & 0x80) >> 7); + if (local_flag == 1) + GR_LOG_DEBUG(d_logger, "[LOCAL FLAG SET] "); uint8_t ca = (uint8_t)((data[service_counter + 3] & 0x70) >> 4); - if (ca != 0) GR_LOG_DEBUG(d_logger, "[CONDITIONAL ACCESS USED] "); - uint8_t num_service_comps = (uint8_t)(data[service_counter + 3] & 0x0f); - GR_LOG_DEBUG(d_logger, format("(%d components):") % (int) num_service_comps); - for (int i = 0; i < num_service_comps; i++) { //iterate over service components - uint8_t TMID = (uint8_t)((data[service_counter + 4 + i * 2] & 0xc0) >> 6); - uint8_t comp_type = (uint8_t)(data[service_counter + 4 + i * 2] & 0x3f); - uint8_t subchID = (uint8_t)((data[service_counter + 5 + i * 2] & 0xfc) >> 2); - uint8_t ps = (uint8_t)((data[service_counter + 5 + i * 2 + 1] & 0x02) >> 1); + if (ca != 0) + GR_LOG_DEBUG(d_logger, "[CONDITIONAL ACCESS USED] "); + uint8_t num_service_comps = (uint8_t)( + data[service_counter + 3] & 0x0f); + GR_LOG_DEBUG(d_logger, format("(%d components):") % + (int) num_service_comps); + for (int i = 0; i < + num_service_comps; i++) { //iterate over service components + uint8_t TMID = (uint8_t)( + (data[service_counter + 4 + i * 2] & 0xc0) >> 6); + uint8_t comp_type = (uint8_t)( + data[service_counter + 4 + i * 2] & 0x3f); + uint8_t subchID = (uint8_t)( + (data[service_counter + 5 + i * 2] & 0xfc) >> 2); + uint8_t ps = (uint8_t)( + (data[service_counter + 5 + i * 2 + 1] & 0x02) >> 1); if (TMID == 0) { GR_LOG_DEBUG(d_logger, - format("(audio stream, type %d, subchID %d, primary %d)") % (int) comp_type % + format("(audio stream, type %d, subchID %d, primary %d)") % + (int) comp_type % (int) subchID % (int) ps); // write service info from specififc subchannel to json if (d_service_info_written_trigger < 0) { d_service_info_written_trigger = (int) subchID; } else { std::stringstream ss; - ss << d_service_info_current << ",{" << "\"reference\":" << (int) service_reference << ",\"ID\":" - << (int) subchID << ",\"primary\":" << ((ps == 1) ? "true" : "false") << ",\"DAB+\":" - << (((int) comp_type == 63) ? "true" : "false") << "}\0"; + ss << d_service_info_current << ",{" << "\"reference\":" + << (int) service_reference << ",\"ID\":" + << (int) subchID << ",\"primary\":" + << ((ps == 1) ? "true" : "false") << ",\"DAB+\":" + << (((int) comp_type == 63) ? "true" : "false") + << "}\0"; d_service_info_current = ss.str(); if ((int) subchID == d_service_info_written_trigger) { std::stringstream ss_json; @@ -206,11 +240,13 @@ namespace gr { } } else if (TMID == 1) { GR_LOG_DEBUG(d_logger, - format("(data stream, type %d, subchID %d, primary %d)") % (int) comp_type % + format("(data stream, type %d, subchID %d, primary %d)") % + (int) comp_type % (int) subchID % (int) ps); } else if (TMID == 2) { GR_LOG_DEBUG(d_logger, - format("(FIDC, type %d, subchID %d, primary %d)") % (int) comp_type % (int) subchID % + format("(FIDC, type %d, subchID %d, primary %d)") % + (int) comp_type % (int) subchID % (int) ps); } else { GR_LOG_DEBUG(d_logger, "[packed data]"); @@ -232,18 +268,23 @@ namespace gr { case FIB_MCI_EXTENSION_SERVICE_COMP_GLOBAL_DEFINITION: { uint8_t service_comp_counter = 0; do { - uint16_t service_reference = (uint16_t)(data[service_comp_counter + 2] & 0x0f) << 8 | - (uint8_t) data[service_comp_counter + 3]; - uint8_t SCIdS = (uint8_t)(data[service_comp_counter + 4] & 0x0f); + uint16_t service_reference = + (uint16_t)(data[service_comp_counter + 2] & 0x0f) << 8 | + (uint8_t) data[service_comp_counter + 3]; + uint8_t SCIdS = (uint8_t)( + data[service_comp_counter + 4] & 0x0f); if ((data[service_comp_counter + 5] & 0x80) == 0) { - uint8_t subchID = (uint8_t)(data[service_comp_counter + 5] & 0x3f); + uint8_t subchID = (uint8_t)( + data[service_comp_counter + 5] & 0x3f); GR_LOG_DEBUG(d_logger, format("service component global definition: reference %d, SCIdS %d, subchID %d") % service_reference % (int) SCIdS % (int) subchID); service_comp_counter += 5; } else { - uint16_t subchID = (uint16_t)(data[service_comp_counter + 5] & 0x0f) << 8 | - (uint8_t) data[service_comp_counter + 6]; + uint16_t subchID = + (uint16_t)(data[service_comp_counter + 5] & 0x0f) + << 8 | + (uint8_t) data[service_comp_counter + 6]; GR_LOG_DEBUG(d_logger, format("service component global definition: reference %d, SCIdS %d, subchID %d") % service_reference % (int) SCIdS % (int) subchID); @@ -265,22 +306,28 @@ namespace gr { GR_LOG_DEBUG(d_logger, "programme number"); break; case FIB_SI_EXTENSION_PROGRAMME_TYPE: { - GR_LOG_DEBUG(d_logger, format("programme type, %d components") %((length-1)/4)); - for(int i = 0; i < (length-1)/4; i++) { - uint8_t programme_type = (uint8_t)(data[2 + i*4 + 3] & 0x1f); - uint16_t service_reference = (uint16_t)(data[2 + i*4] & 0x0f) << 8 | - (uint8_t) data[2 + i*4 + 1]; - GR_LOG_DEBUG(d_logger, format("reference %d, type: %d") %service_reference %(int)programme_type); + GR_LOG_DEBUG(d_logger, format("programme type, %d components") % + ((length - 1) / 4)); + for (int i = 0; i < (length - 1) / 4; i++) { + uint8_t programme_type = (uint8_t)(data[2 + i * 4 + 3] & 0x1f); + uint16_t service_reference = + (uint16_t)(data[2 + i * 4] & 0x0f) << 8 | + (uint8_t) data[2 + i * 4 + 1]; + GR_LOG_DEBUG(d_logger, format("reference %d, type: %d") % + service_reference % + (int) programme_type); // write programme type to json if (d_programme_type_written_trigger < 0) { d_programme_type_written_trigger = (int) service_reference; } else { std::stringstream ss; - ss << d_programme_type_current << ",{" << "\"reference\":" << (int) service_reference << ",\"programme_type\":" + ss << d_programme_type_current << ",{" << "\"reference\":" + << (int) service_reference << ",\"programme_type\":" << (int) programme_type << "}\0"; d_programme_type_current = ss.str(); - if ((int) service_reference == d_programme_type_written_trigger) { + if ((int) service_reference == + d_programme_type_written_trigger) { std::stringstream ss_json; ss_json << d_programme_type_current << "]" << "\0"; d_programme_type_current = "\0"; @@ -299,7 +346,8 @@ namespace gr { GR_LOG_DEBUG(d_logger, "announcement switching"); break; default: - GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % (int) extension); + GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % + (int) extension); break; } break; @@ -313,27 +361,33 @@ namespace gr { case FIB_SI_EXTENSION_ENSEMBLE_LABEL: { uint8_t country_ID = (uint8_t)((data[2] & 0xf0) >> 4); memcpy(label, &data[4], 16); - GR_LOG_DEBUG(d_logger, format("[ensemble label](%d): %s") % (int) country_ID % label); + GR_LOG_DEBUG(d_logger, format("[ensemble label](%d): %s") % + (int) country_ID % label); // write json for ensemble label and country ID std::stringstream ss; - ss << "{" << "\"" << label << "\":{" << "\"country_ID\":" << (int) country_ID << "}}"; + ss << "{" << "\"" << label << "\":{" << "\"country_ID\":" + << (int) country_ID << "}}"; d_json_ensemble_info = ss.str(); break; } case FIB_SI_EXTENSION_PROGRAMME_SERVICE_LABEL: { - uint16_t service_reference = (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; + uint16_t service_reference = + (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; memcpy(label, &data[4], 16); GR_LOG_DEBUG(d_logger, - format("[programme service label] (reference %d): %s") % service_reference % label); + format("[programme service label] (reference %d): %s") % + service_reference % label); // write service labels from services to json if (d_service_labels_written_trigger < 0) { d_service_labels_written_trigger = (int) service_reference; } else { std::stringstream ss; - ss << d_service_labels_current << ",{" << "\"label\":\"" << label << "\",\"reference\":" + ss << d_service_labels_current << ",{" << "\"label\":\"" + << label << "\",\"reference\":" << (int) service_reference << "}\0"; d_service_labels_current = ss.str(); - if ((int) service_reference == d_service_labels_written_trigger) { + if ((int) service_reference == + d_service_labels_written_trigger) { std::stringstream ss_json; ss_json << d_service_labels_current << "]" << "\0"; d_service_labels_current = "\0"; @@ -346,14 +400,17 @@ namespace gr { } case FIB_SI_EXTENSION_SERVICE_COMP_LABEL: memcpy(label, &data[5], 16); - GR_LOG_DEBUG(d_logger, format("[service component label] %s") % label); + GR_LOG_DEBUG(d_logger, + format("[service component label] %s") % label); break; case FIB_SI_EXTENSION_DATA_SERVICE_LABEL: memcpy(label, &data[5], 16); - GR_LOG_DEBUG(d_logger, format("[data service label]: %s") % label); + GR_LOG_DEBUG(d_logger, + format("[data service label]: %s") % label); break; default: - GR_LOG_DEBUG(d_logger, format("[unknown extension (%d)") % (int) extension); + GR_LOG_DEBUG(d_logger, + format("[unknown extension (%d)") % (int) extension); break; } break; @@ -366,17 +423,21 @@ namespace gr { GR_LOG_DEBUG(d_logger, "paging - not supported yet"); break; case FIB_FIDC_EXTENSION_TMC: - GR_LOG_DEBUG(d_logger, "TMC (traffic message channel) - not supported yet"); + GR_LOG_DEBUG(d_logger, + "TMC (traffic message channel) - not supported yet"); break; case FIB_FIDC_EXTENSION_EWS: - GR_LOG_DEBUG(d_logger, "EWS (emergency warning service) - not supported yet"); + GR_LOG_DEBUG(d_logger, + "EWS (emergency warning service) - not supported yet"); break; default: - GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % (int) extension); + GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % + (int) extension); } break; case FIB_FIG_TYPE_CA: - GR_LOG_DEBUG(d_logger, "FIB type CA (conditional access) not supported yet"); + GR_LOG_DEBUG(d_logger, + "FIB type CA (conditional access) not supported yet"); break; default: GR_LOG_DEBUG(d_logger, "unsupported FIG type"); @@ -388,8 +449,7 @@ namespace gr { int fib_sink_vb_impl::work(int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const char *in = (const char *) input_items[0]; for (int i = 0; i < noutput_items; i++) { diff --git a/lib/fib_sink_vb_impl.h b/lib/fib_sink_vb_impl.h index da621a78..39906429 100644 --- a/lib/fib_sink_vb_impl.h +++ b/lib/fib_sink_vb_impl.h @@ -1,7 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright belongs to Andreas Mueller - * Modified 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2008 by Andreas Mueller * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,10 @@ namespace gr { namespace dab { -/*! \brief sink for DAB FIBs, interprets MSC and SI +/*! \brief sink for DAB/DAB+ FIBs, interprets MSC and SI + * crc16 check of incoming fibs + * reads correct fibs + * generates json objects with service and multiplex information * */ class fib_sink_vb_impl : public fib_sink_vb { @@ -55,28 +58,20 @@ namespace gr { std::string d_programme_type_current; int d_programme_type_written_trigger; - - public: fib_sink_vb_impl(); - virtual std::string get_ensemble_info() - { return d_json_ensemble_info; } + virtual std::string get_ensemble_info() { return d_json_ensemble_info; } - virtual std::string get_service_info() - { return d_json_service_info;} + virtual std::string get_service_info() { return d_json_service_info; } - virtual std::string get_service_labels() - { return d_json_service_labels;} + virtual std::string get_service_labels() { return d_json_service_labels; } - virtual std::string get_subch_info() - { return d_json_subch_info;} + virtual std::string get_subch_info() { return d_json_subch_info; } - virtual std::string get_programme_type() - { return d_json_programme_type;} + virtual std::string get_programme_type() { return d_json_programme_type; } - virtual bool get_crc_passed() - { return d_crc_passed;} + virtual bool get_crc_passed() { return d_crc_passed; } int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index d94278e3..aca58304 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -31,340 +31,446 @@ #include namespace gr { - namespace dab { + namespace dab { //////////////////////////////////////// /// MCI-FIGs, ready to transmit //////////////////////////////////////// - //ensemble info, CIF counter has to increase with each CIF - const char fib_source_b_impl::d_ensemble_info[56] = {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - // 000 00110 000 00000 0100000000000000 00 0 0000000000000 00000000 + //ensemble info, CIF counter has to increase with each CIF + const char fib_source_b_impl::d_ensemble_info[56] = {0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, + 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, + 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + // 000 00110 000 00000 0100000000000000 00 0 0000000000000 00000000 - //service orga header - const char fib_source_b_impl::d_service_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; - //000 00100 000 00010 + //service orga header + const char fib_source_b_impl::d_service_orga_header[16] = {0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0}; + //000 00100 000 00010 - //service orga for one service containing one subchannel - const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; - // 0100000000000000 0 000 0001 00 111111 000000 00 + //service orga for one service containing one subchannel + const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0}; + // 0100000000000000 0 000 0001 00 111111 000000 00 - //subchannel orga header, length has to be changed according to the number of subchannel-orga fields - const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - //000 00100 000 00001 + //subchannel orga header, length has to be changed according to the number of subchannel-orga fields + const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, + 0, 0, 1, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 1}; + //000 00100 000 00001 - //subchannel orga field (long form) (array has to be modified (subchID, start adress, protection level and subchannel size)) - const char fib_source_b_impl::d_subchannel_orga_field[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - // 000000 0000000000 0 1 000 00 0000000000 long form (table 7, p. 51) + //subchannel orga field (long form) (array has to be modified (subchID, start adress, protection level and subchannel size)) + const char fib_source_b_impl::d_subchannel_orga_field[32] = {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 1, 0, + 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0}; + // 000000 0000000000 0 1 000 00 0000000000 long form (table 7, p. 51) ///////////////////////////////////////////// /// SI-FIGs, ready to transmit ///////////////////////////////////////////// - //Ensemble label - char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, - 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, - 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, - 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, - 0}; - //"001 10101 0000 0 000 0000 000000000000 01011111 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01001110 01100101 01110111 01110011 01011111 01011111 01011111 0011100011111000"; // Ensemble label: "__Galaxy_News___" + //Ensemble label + char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 1, + 1, 1, 1, 1, + 0, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 0, 0, 0, 1, 1, 1, + 0, 1, 1, 0, + 0, 0, 0, 1, 0, 1, 1, 0, + 1, 1, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 1, + 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 1, + 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 0, + 1, 1, 1, 0, 0, 1, 1, 0, + 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 0, + 1, 1, 1, 1, 1, 0, 0, + 0}; + //"001 10101 0000 0 000 0000 000000000000 01011111 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01001110 01100101 01110111 01110011 01011111 01011111 01011111 0011100011111000"; // Ensemble label: "__Galaxy_News___" - //Programme Service label - char fib_source_b_impl::d_programme_service_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, - 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, - 1, 0, 0, - 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, - 0, 0, 1, - 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, - 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, - 0, 0, 0, - 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, - 1, 1, 0, - 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, - 1, 0, 1, - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, - 1, 0, 0}; - //001 10101 0000 0 001 0100000000000000 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01010010 01100001 01100100 01101001 01101111 00110001 01011111 01011111 0111000111100100 + //Programme Service label + char fib_source_b_impl::d_programme_service_label[176] = {0, 0, 1, 1, 0, + 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, + 1, 1, 1, 0, + 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 1, 0, 0, 0, + 0, 1, 0, 1, 1, + 0, 1, 1, 0, + 0, 0, 1, + 1, 0, 0, 0, 0, + 1, 0, 1, 1, 1, + 1, 0, 0, 0, 0, + 1, 1, 1, 1, + 0, 0, 1, + 0, 1, 0, 1, 1, + 1, 1, 1, 0, 1, + 0, 1, 0, 0, 1, + 0, 0, 1, 1, + 0, 0, 0, + 0, 1, 0, 1, 1, + 0, 0, 1, 0, 0, + 0, 1, 1, 0, 1, + 0, 0, 1, 0, + 1, 1, 0, + 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0, + 0, 1, 0, 1, 0, + 1, 1, 1, 1, + 1, 0, 1, + 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, + 0, 0, 0, 1, 1, + 1, 1, 0, 0, + 1, 0, 0}; + //001 10101 0000 0 001 0100000000000000 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01010010 01100001 01100100 01101001 01101111 00110001 01011111 01011111 0111000111100100 - fib_source_b::sptr - fib_source_b::make(int transmission_mode, int country_ID, int num_subch, std::string ensemble_label, - std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, - const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus) - { - return gnuradio::get_initial_sptr - (new fib_source_b_impl(transmission_mode, country_ID, num_subch, ensemble_label, - programme_service_labels, service_comp_label, service_comp_lang, protection_mode, - data_rate_n, dabplus)); - } + fib_source_b::sptr + fib_source_b::make(int transmission_mode, int country_ID, int num_subch, + std::string ensemble_label, + std::string programme_service_labels, + std::string service_comp_label, + uint8_t service_comp_lang, + const std::vector &protection_mode, + const std::vector &data_rate_n, + const std::vector &dabplus) { + return gnuradio::get_initial_sptr + (new fib_source_b_impl(transmission_mode, country_ID, + num_subch, ensemble_label, + programme_service_labels, + service_comp_label, service_comp_lang, + protection_mode, + data_rate_n, dabplus)); + } - /* - * The private constructor - */ - fib_source_b_impl::fib_source_b_impl(int transmission_mode, int country_ID, int num_subch, std::string ensemble_label, - std::string programme_service_labels, std::string service_comp_label, - uint8_t service_comp_lang, const std::vector &protection_mode, - const std::vector &data_rate_n, const std::vector &dabplus) - : gr::sync_block("fib_source_b", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(1, 1, sizeof(char))), - d_transmission_mode(transmission_mode), d_num_subch(num_subch), d_nFIBs_written(0), - d_protection_mode(protection_mode), d_data_rate_n(data_rate_n), d_dabplus(dabplus), d_country_ID(country_ID) - { - if (d_transmission_mode != 3) set_output_multiple((8 * FIB_LENGTH) * 3); - else set_output_multiple((8 * FIB_LENGTH) * 4); - //write the ensemble label with input string once at beginning - write_label(d_ensemble_label + 32, ensemble_label); - if (protection_mode.size() != num_subch) { - throw std::invalid_argument((boost::format("size of vector protection_mode (%d) does not fit with number of subchannels (%d)") % protection_mode.size() % num_subch).str()); - } - if (data_rate_n.size() != num_subch) { - throw std::invalid_argument((boost::format("size of vector data_rate_n (%d) does not fit with number of subchannels (%d)") % data_rate_n.size() % num_subch).str()); - } - // init counter for iterating over the services - d_label_counter = 0; - d_service_labels = programme_service_labels; - // the string programme_service_labels containts num_subch * 16 chars, appended. Note that every subchannel is strutured in a different service in this implementation. - if (programme_service_labels.size() != 16*num_subch){ - throw std::invalid_argument((boost::format("size of service label strings is (%d) but should be %d * 16 = %d") % programme_service_labels.size() % num_subch % (16*num_subch)).str()); - } - } + /* + * The private constructor + */ + fib_source_b_impl::fib_source_b_impl(int transmission_mode, + int country_ID, int num_subch, + std::string ensemble_label, + std::string programme_service_labels, + std::string service_comp_label, + uint8_t service_comp_lang, + const std::vector &protection_mode, + const std::vector &data_rate_n, + const std::vector &dabplus) + : gr::sync_block("fib_source_b", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, 1, sizeof(char))), + d_transmission_mode(transmission_mode), + d_num_subch(num_subch), d_nFIBs_written(0), + d_protection_mode(protection_mode), + d_data_rate_n(data_rate_n), d_dabplus(dabplus), + d_country_ID(country_ID) { + if (d_transmission_mode != 3) + set_output_multiple((8 * FIB_LENGTH) * 3); + else set_output_multiple((8 * FIB_LENGTH) * 4); + //write the ensemble label with input string once at beginning + write_label(d_ensemble_label + 32, ensemble_label); + if (protection_mode.size() != num_subch) { + throw std::invalid_argument((boost::format( + "size of vector protection_mode (%d) does not fit with number of subchannels (%d)") % + protection_mode.size() % + num_subch).str()); + } + if (data_rate_n.size() != num_subch) { + throw std::invalid_argument((boost::format( + "size of vector data_rate_n (%d) does not fit with number of subchannels (%d)") % + data_rate_n.size() % num_subch).str()); + } + // init counter for iterating over the services + d_label_counter = 0; + d_service_labels = programme_service_labels; + // the string programme_service_labels containts num_subch * 16 chars, appended. Note that every subchannel is strutured in a different service in this implementation. + if (programme_service_labels.size() != 16 * num_subch) { + throw std::invalid_argument((boost::format( + "size of service label strings is (%d) but should be %d * 16 = %d") % + programme_service_labels.size() % + num_subch % (16 * num_subch)).str()); + } + } - /* - * Our virtual destructor. - */ - fib_source_b_impl::~fib_source_b_impl() - { - } + /* + * Our virtual destructor. + */ + fib_source_b_impl::~fib_source_b_impl() { + } - /* - * overwrites an integer value to num_bits bits to the num_bits bits before trigger (overwrites default zeros)), e.g. for number of subchannels in ensemble info - */ - void fib_source_b_impl::bit_adaption(char *out_ptr, int number, int num_bits) - { - for (int i = 0; i < num_bits; i++) { - if (pow(2, num_bits - 1 - i) > number) { - out_ptr[i - num_bits] = 0; - } else { - out_ptr[i - num_bits] = 1; - number -= pow(2, num_bits - 1 - i); + /* + * overwrites an integer value to num_bits bits to the num_bits bits before trigger (overwrites default zeros)), e.g. for number of subchannels in ensemble info + */ + void fib_source_b_impl::bit_adaption(char *out_ptr, int number, + int num_bits) { + for (int i = 0; i < num_bits; i++) { + if (pow(2, num_bits - 1 - i) > number) { + out_ptr[i - num_bits] = 0; + } else { + out_ptr[i - num_bits] = 1; + number -= pow(2, num_bits - 1 - i); + } + } } - } - } - /* - * calculates the CIF modulo counters and changes the bits in d_ensemble_info with bit_adaption - */ - void fib_source_b_impl::CIF_counter(char *out_ptr, int counter) - { - //mod 250 counter - int mod_250 = counter % 250; - bit_adaption(out_ptr, mod_250, 8); - //mod 20 counter - int mod_20 = ((counter - mod_250) / 250) % 20; - bit_adaption(out_ptr - 8, mod_20, 5); - } + /* + * calculates the CIF modulo counters and changes the bits in d_ensemble_info with bit_adaption + */ + void fib_source_b_impl::CIF_counter(char *out_ptr, int counter) { + //mod 250 counter + int mod_250 = counter % 250; + bit_adaption(out_ptr, mod_250, 8); + //mod 20 counter + int mod_20 = ((counter - mod_250) / 250) % 20; + bit_adaption(out_ptr - 8, mod_20, 5); + } - /* - * converts string to bits and writes it to the stream - * outputs the number of written bits to update d_offset - */ - int fib_source_b_impl::write_label(char *out_ptr, std::string label, int num_chars) - { - for (std::size_t i = 0; i < label.size(); ++i) { - bit_adaption(out_ptr + (i + 1) * 8, (int) label.c_str()[i], 8); - } - std::size_t written_size = label.size(); - while (written_size < num_chars) {//fill rest of label with spaces - bit_adaption(out_ptr + (written_size + 1) * 8, (int) ' ', 8); - written_size++; - } - return 8 * num_chars; - } + /* + * converts string to bits and writes it to the stream + * outputs the number of written bits to update d_offset + */ + int fib_source_b_impl::write_label(char *out_ptr, std::string label, + int num_chars) { + for (std::size_t i = 0; i < label.size(); ++i) { + bit_adaption(out_ptr + (i + 1) * 8, (int) label.c_str()[i], 8); + } + std::size_t written_size = label.size(); + while (written_size < num_chars) {//fill rest of label with spaces + bit_adaption(out_ptr + (written_size + 1) * 8, (int) ' ', 8); + written_size++; + } + return 8 * num_chars; + } - int - fib_source_b_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - char *out = (char *) output_items[0]; - d_offset = 0; + int + fib_source_b_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + char *out = (char *) output_items[0]; + d_offset = 0; - do { - //only MCI in this FIB when this FIB ist first in Row (Row are 3 FIBs for d_transmission_mode=1,2,4 or 4 FIBs for d_transmission_mode=3) - if ((d_nFIBs_written % 3 == 0 && d_transmission_mode != 3) || - (d_nFIBs_written % 4 == 0 && d_transmission_mode == 3)) { + do { + //only MCI in this FIB when this FIB ist first in Row (Row are 3 FIBs for d_transmission_mode=1,2,4 or 4 FIBs for d_transmission_mode=3) + if ((d_nFIBs_written % 3 == 0 && d_transmission_mode != 3) || + (d_nFIBs_written % 4 == 0 && d_transmission_mode == 3)) { //////////////////////////////////////////////// /// add first FIB with only MCI (max services = 4) //////////////////////////////////////////////// - //ensemble info - std::memcpy(out + d_offset, d_ensemble_info, d_size_ensemble_info); - d_offset += d_size_ensemble_info; - //increase CIF counter - if (d_transmission_mode != 3) CIF_counter(out + d_offset, d_nFIBs_written / 3); - else CIF_counter(out + d_offset, d_nFIBs_written / 4); + //ensemble info + std::memcpy(out + d_offset, d_ensemble_info, + d_size_ensemble_info); + d_offset += d_size_ensemble_info; + //increase CIF counter + if (d_transmission_mode != 3) + CIF_counter(out + d_offset, d_nFIBs_written / 3); + else CIF_counter(out + d_offset, d_nFIBs_written / 4); - //service orga - //header - std::memcpy(out + d_offset, d_service_orga_header, d_size_service_orga_header); - d_offset += d_size_service_orga_header; - //change FIG length depending on number of services - bit_adaption(out + d_offset - 8, 1 + 5*d_num_subch, 5); - //data field for every service (each containing one service component) - for (int service_count = 0; service_count < d_num_subch; service_count++) { - std::memcpy(out + d_offset, d_service_orga, d_size_service_orga); - d_offset += d_size_service_orga; - //change service Identifier - bit_adaption(out + d_offset - 24, service_count, 8); - //change subchannel ID - bit_adaption(out + d_offset - 2, service_count, 6); - //change DAB+ mode if not DAB+ but DAB - if(d_dabplus[service_count] != 1){ - bit_adaption(out + d_offset -8, 0, 6); - } - } - //MCI is set, set EndMarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) - for (int i = 0; i < 8; i++) { - out[i + d_offset] = 1; - } - } - d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) - out[d_offset] = 0; - d_offset++; - } - d_nFIBs_written++; - }//first FIB in row (with only MCI) is finished + //service orga + //header + std::memcpy(out + d_offset, d_service_orga_header, + d_size_service_orga_header); + d_offset += d_size_service_orga_header; + //change FIG length depending on number of services + bit_adaption(out + d_offset - 8, 1 + 5 * d_num_subch, 5); + //data field for every service (each containing one service component) + for (int service_count = 0; + service_count < d_num_subch; service_count++) { + std::memcpy(out + d_offset, d_service_orga, + d_size_service_orga); + d_offset += d_size_service_orga; + //change service Identifier + bit_adaption(out + d_offset - 24, service_count, 8); + //change subchannel ID + bit_adaption(out + d_offset - 2, service_count, 6); + //change DAB+ mode if not DAB+ but DAB + if (d_dabplus[service_count] != 1) { + bit_adaption(out + d_offset - 8, 0, 6); + } + } + //MCI is set, set EndMarker and padding + if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= + 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) + for (int i = 0; i < 8; i++) { + out[i + d_offset] = 1; + } + } + d_offset += 8; + while (d_offset % (8 * FIB_LENGTH) != + 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + out[d_offset] = 0; + d_offset++; + } + d_nFIBs_written++; + }//first FIB in row (with only MCI) is finished - //second FIB in row reserved for subchannel orga - else if ((d_nFIBs_written % 3 == 1 && d_transmission_mode != 3) || - (d_nFIBs_written % 4 == 1 && d_transmission_mode == 3)) { - //////////////////////////////////////////////// - /// add second FIB with only subchannel orga (max numSubCh = 7) - //////////////////////////////////////////////// - //subchannel orga - d_start_adress = 0; - //subchannel orga header (write only once for all subchannels) - std::memcpy(out + d_offset, d_subchannel_orga_header, d_size_subchannel_orga_header); - d_offset += d_size_subchannel_orga_header; - //change length of FIG header according to number of subchannel orga fields that are added - bit_adaption(out + d_offset - 8, d_num_subch * (d_size_subchannel_orga_field / 8) + 1, 5); - //subchannel orga field - for (int subch_count = 0; subch_count < d_num_subch; subch_count++) {//iterate over all subchannels - std::memcpy(out + d_offset + d_size_subchannel_orga_field * subch_count, d_subchannel_orga_field, - d_size_subchannel_orga_field); - d_offset += d_size_subchannel_orga_field; + //second FIB in row reserved for subchannel orga + else if ((d_nFIBs_written % 3 == 1 && d_transmission_mode != 3) || + (d_nFIBs_written % 4 == 1 && d_transmission_mode == 3)) { + //////////////////////////////////////////////// + /// add second FIB with only subchannel orga (max numSubCh = 7) + //////////////////////////////////////////////// + //subchannel orga + d_start_adress = 0; + //subchannel orga header (write only once for all subchannels) + std::memcpy(out + d_offset, d_subchannel_orga_header, + d_size_subchannel_orga_header); + d_offset += d_size_subchannel_orga_header; + //change length of FIG header according to number of subchannel orga fields that are added + bit_adaption(out + d_offset - 8, + d_num_subch * (d_size_subchannel_orga_field / 8) + 1, + 5); + //subchannel orga field + for (int subch_count = 0; subch_count < + d_num_subch; subch_count++) {//iterate over all subchannels + std::memcpy(out + d_offset + + d_size_subchannel_orga_field * subch_count, + d_subchannel_orga_field, + d_size_subchannel_orga_field); + d_offset += d_size_subchannel_orga_field; - //change SubChID, start address, protection level and subch size of each sub channel - //the SubChannel ID has to increase, to be different - bit_adaption(out + d_offset - 26, subch_count, 6); - //the start address (in CUs) of the next subch is increased about size of previous subch - bit_adaption(out + d_offset - 16, d_start_adress, 10); - //protection level - bit_adaption(out + d_offset - 10, d_protection_mode[subch_count], 2); - //calculate size of subchannel in CUs (table 7, p. 51) - switch (d_protection_mode[subch_count]) { - case 0: - d_subch_size = 12 * d_data_rate_n[subch_count]; - break; - case 1: - d_subch_size = 8 * d_data_rate_n[subch_count]; - break; - case 2: - d_subch_size = 6 * d_data_rate_n[subch_count]; - break; - case 3: - d_subch_size = 4 * d_data_rate_n[subch_count]; - break; - default: - //error - break; - } - //write subchannel size - bit_adaption(out + d_offset - 0, d_subch_size, 10); - //shift start address - d_start_adress += d_subch_size; - } - //subchannel orga is set, set EndMarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) - for (int i = 0; i < 8; i++) { //find:: binde FIC.h ein und verwende die konstaten statt FIB_size - out[i + d_offset] = 1; - } - } - d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) - out[d_offset] = 0; - d_offset++; - } - d_nFIBs_written++; - }//second FIB is finished - else { + //change SubChID, start address, protection level and subch size of each sub channel + //the SubChannel ID has to increase, to be different + bit_adaption(out + d_offset - 26, subch_count, 6); + //the start address (in CUs) of the next subch is increased about size of previous subch + bit_adaption(out + d_offset - 16, d_start_adress, 10); + //protection level + bit_adaption(out + d_offset - 10, + d_protection_mode[subch_count], 2); + //calculate size of subchannel in CUs (table 7, p. 51) + switch (d_protection_mode[subch_count]) { + case 0: + d_subch_size = 12 * d_data_rate_n[subch_count]; + break; + case 1: + d_subch_size = 8 * d_data_rate_n[subch_count]; + break; + case 2: + d_subch_size = 6 * d_data_rate_n[subch_count]; + break; + case 3: + d_subch_size = 4 * d_data_rate_n[subch_count]; + break; + default: + //error + break; + } + //write subchannel size + bit_adaption(out + d_offset - 0, d_subch_size, 10); + //shift start address + d_start_adress += d_subch_size; + } + //subchannel orga is set, set EndMarker and padding + if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= + 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) + for (int i = 0; i < + 8; i++) { //find:: binde FIC.h ein und verwende die konstaten statt FIB_size + out[i + d_offset] = 1; + } + } + d_offset += 8; + while (d_offset % (8 * FIB_LENGTH) != + 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + out[d_offset] = 0; + d_offset++; + } + d_nFIBs_written++; + }//second FIB is finished + else { ///////////////////////////////////////////////// /// write a not primary FIB with SI ///////////////////////////////////////////////// - do { //fill FIB with FIGs - if(d_label_counter == 0){ - // write ensemble label - std::memcpy(out + d_offset, d_ensemble_label, d_size_label); - d_offset += d_size_label; - // change country ID - bit_adaption(out + d_offset-(d_size_label-20), d_country_ID, 4); - ++d_label_counter; - } - else{ - // write service label - std::memcpy(out + d_offset, d_programme_service_label, d_size_label); - // change label - std::string label = d_service_labels.substr((d_label_counter-1)*16, 16); - write_label(out + d_offset + 32, label); - d_offset += d_size_label; - bit_adaption(out + d_offset - 144, d_label_counter-1, 8); - if(++d_label_counter > d_num_subch){ - d_label_counter = 0; - } + do { //fill FIB with FIGs + if (d_label_counter == 0) { + // write ensemble label + std::memcpy(out + d_offset, d_ensemble_label, d_size_label); + d_offset += d_size_label; + // change country ID + bit_adaption(out + d_offset - (d_size_label - 20), + d_country_ID, 4); + ++d_label_counter; + } else { + // write service label + std::memcpy(out + d_offset, d_programme_service_label, + d_size_label); + // change label + std::string label = d_service_labels.substr( + (d_label_counter - 1) * 16, 16); + write_label(out + d_offset + 32, label); + d_offset += d_size_label; + bit_adaption(out + d_offset - 144, d_label_counter - 1, 8); + if (++d_label_counter > d_num_subch) { + d_label_counter = 0; + } - } - } while ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= 176); //check if there is enough space for next FIG - //FIB is filled, set endmarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG - for (int i = 0; i < 8; i++) { - out[i + d_offset] = 1; - } - } - d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) - out[d_offset] = 0; - d_offset++; - } - d_nFIBs_written++; - }//FIB finished + } + } while ((8 * FIB_DATA_FIELD_LENGTH) - + (d_offset % (8 * FIB_LENGTH)) >= + 176); //check if there is enough space for next FIG + //FIB is filled, set endmarker and padding + if ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= + 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG + for (int i = 0; i < 8; i++) { + out[i + d_offset] = 1; + } + } + d_offset += 8; + while (d_offset % (8 * FIB_LENGTH) != + 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + out[d_offset] = 0; + d_offset++; + } + d_nFIBs_written++; + }//FIB finished - } while ((d_nFIBs_written % 3 != 0 && d_transmission_mode != 3) || (d_nFIBs_written % 4 != 0 && - d_transmission_mode == - 3)); //finished writing a row of FIBs (3 or 4) (number of FIBS for 1 Transmission Frame) + } while ((d_nFIBs_written % 3 != 0 && d_transmission_mode != 3) || + (d_nFIBs_written % 4 != 0 && + d_transmission_mode == + 3)); //finished writing a row of FIBs (3 or 4) (number of FIBS for 1 Transmission Frame) - // Tell runtime system how many output items we produced. - if (d_transmission_mode != 3) return 3 * (8 * FIB_LENGTH); - else return 4 * (8 * FIB_LENGTH); - } + // Tell runtime system how many output items we produced. + if (d_transmission_mode != 3) return 3 * (8 * FIB_LENGTH); + else return 4 * (8 * FIB_LENGTH); + } - } /* namespace dab */ + } /* namespace dab */ } /* namespace gr */ diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index 6cdb4af4..eaa9b576 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -55,7 +55,8 @@ namespace gr { const static char d_ensemble_info[56]; //CIF counter changes every FIB const static int d_size_ensemble_info = 56; - void CIF_counter(char *out_ptr, int counter);//implementation of the mod 20 and mod 250 counter + void CIF_counter(char *out_ptr, + int counter);//implementation of the mod 20 and mod 250 counter const static char d_service_orga_header[16]; //*const const static int d_size_service_orga_header = 16; const static char d_service_orga[40]; //*services @@ -74,12 +75,18 @@ namespace gr { static char d_programme_service_label[176]; //21*8+8, service label (FIG 1/0) std::string d_service_labels; - int write_label(char *out_ptr, std::string label, int num_chars = 16);//default for 16 characters (16 byte) + int write_label(char *out_ptr, std::string label, + int num_chars = 16);//default for 16 characters (16 byte) public: - fib_source_b_impl(int transmission_mode, int coutry_ID, int num_subch, std::string ensemble_label, - std::string programme_service_labels, std::string service_comp_label, uint8_t service_comp_lang, - const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus); + fib_source_b_impl(int transmission_mode, int coutry_ID, + int num_subch, std::string ensemble_label, + std::string programme_service_labels, + std::string service_comp_label, + uint8_t service_comp_lang, + const std::vector &protection_mode, + const std::vector &data_rate_n, + const std::vector &dabplus); ~fib_source_b_impl(); diff --git a/lib/firecode-checker.cpp b/lib/firecode-checker.cpp index 42e8103b..3261397d 100644 --- a/lib/firecode-checker.cpp +++ b/lib/firecode-checker.cpp @@ -28,10 +28,10 @@ #include // g(x)=(x^11+1)(x^5+x^3+x^2+x+1)=1+x+x^2+x^3+x^5+x^11+x^12+x^13+x^14+x^16 -const uint8_t firecode_checker::g[16] = {1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0}; +const uint8_t firecode_checker::g[16] = {1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 0}; -firecode_checker::firecode_checker(void) -{ +firecode_checker::firecode_checker(void) { // prepare the table uint8_t regs[16]; int16_t i, j; @@ -51,12 +51,10 @@ firecode_checker::firecode_checker(void) } } -firecode_checker::~firecode_checker(void) -{ +firecode_checker::~firecode_checker(void) { } -uint16_t firecode_checker::run8(uint8_t regs[]) -{ +uint16_t firecode_checker::run8(uint8_t regs[]) { int16_t i, j; uint16_t z; uint16_t v = 0; @@ -74,8 +72,7 @@ uint16_t firecode_checker::run8(uint8_t regs[]) return v; } -bool firecode_checker::check(const uint8_t *x) -{ +bool firecode_checker::check(const uint8_t *x) { int16_t i; uint16_t state = (x[2] << 8) | x[3]; uint16_t istate; diff --git a/lib/firecode-checker.h b/lib/firecode-checker.h index 3c2b3050..729b0462 100644 --- a/lib/firecode-checker.h +++ b/lib/firecode-checker.h @@ -27,7 +27,7 @@ #ifndef FIRECODE_CHECKER #define FIRECODE_CHECKER -#include +#include class firecode_checker { diff --git a/lib/firecode_check_bb_impl.cc b/lib/firecode_check_bb_impl.cc index 98350fec..953fdd1d 100644 --- a/lib/firecode_check_bb_impl.cc +++ b/lib/firecode_check_bb_impl.cc @@ -1,5 +1,6 @@ /* -*- c++ -*- */ /* + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * The class firecode_checker is adapted from the Qt-DAB software, Copyright Jan van Katwijk (Lazy Chair Computing J.vanKatwijk@gmail.com) * @@ -36,8 +37,7 @@ namespace gr { namespace dab { firecode_check_bb::sptr - firecode_check_bb::make(int bit_rate_n) - { + firecode_check_bb::make(int bit_rate_n) { return gnuradio::get_initial_sptr (new firecode_check_bb_impl(bit_rate_n)); } @@ -48,8 +48,7 @@ namespace gr { firecode_check_bb_impl::firecode_check_bb_impl(int bit_rate_n) : gr::block("firecode_check_bb", gr::io_signature::make(1, 1, sizeof(unsigned char)), - gr::io_signature::make(1, 1, sizeof(unsigned char))) - { + gr::io_signature::make(1, 1, sizeof(unsigned char))) { d_frame_size = 24 * bit_rate_n; set_output_multiple(d_frame_size * 5); //logical frame } @@ -57,13 +56,12 @@ namespace gr { /* * Our virtual destructor. */ - firecode_check_bb_impl::~firecode_check_bb_impl() - { + firecode_check_bb_impl::~firecode_check_bb_impl() { } void - firecode_check_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + firecode_check_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } @@ -71,8 +69,7 @@ namespace gr { firecode_check_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; d_nproduced = 0; @@ -81,12 +78,14 @@ namespace gr { while (d_nconsumed < noutput_items / d_frame_size - 4) { if (fc.check(&in[d_nconsumed * d_frame_size])) { // fire code OK, copy superframe to output - memcpy(out + d_nproduced * d_frame_size, in + d_nconsumed * d_frame_size, d_frame_size * 5); + memcpy(out + d_nproduced * d_frame_size, + in + d_nconsumed * d_frame_size, d_frame_size * 5); d_nproduced += 5; d_nconsumed += 5; d_firecode_passed = true; } else { - GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); + GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % + (nitems_read(0) / d_frame_size)); // shift of one logical frame d_nconsumed++; d_firecode_passed = false; diff --git a/lib/firecode_check_bb_impl.h b/lib/firecode_check_bb_impl.h index b7c74273..1672ece6 100644 --- a/lib/firecode_check_bb_impl.h +++ b/lib/firecode_check_bb_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * The class firecode_checker is adapted from the Qt-DAB software, Copyright Jan van Katwijk (Lazy Chair Computing J.vanKatwijk@gmail.com) * * This is free software; you can redistribute it and/or modify @@ -29,26 +29,25 @@ namespace gr { namespace dab { /*! \brief checks firecode of logical frames * - * checks firecode of each logical frame as a qa test for the msc_decoder. - * According to ETSI TS 102 563 every fifth logical frame starts with 16 bit firecode - * + * Checks firecode of each logical frame as a qa test for the msc_decoder. + * According to ETSI TS 102 563 every fifth logical frame starts with a 16 bit firecode word. * + * @param bit_rate_n data rate in multiples of 8kbit/s */ class firecode_check_bb_impl : public firecode_check_bb { private: - int d_frame_size; int d_bit_rate_n; - int d_nproduced, d_nconsumed; - bool d_firecode_passed; - firecode_checker fc; + int d_frame_size; /*!< size in bytes of one transmission frame (depending on bit_rate)*/ + int d_nproduced, d_nconsumed; /*!< control variable for buffer read/write operations */ + bool d_firecode_passed; /*!< boolean variable for displaying firecode fails*/ + firecode_checker fc; /*!< instance of the class firecode_checker*/ public: firecode_check_bb_impl(int bit_rate_n); ~firecode_check_bb_impl(); - virtual bool get_firecode_passed() - { return d_firecode_passed; } + virtual bool get_firecode_passed() { return d_firecode_passed; } // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/frequency_interleaver_vcc_impl.cc b/lib/frequency_interleaver_vcc_impl.cc index a0f4f3b6..307fa434 100644 --- a/lib/frequency_interleaver_vcc_impl.cc +++ b/lib/frequency_interleaver_vcc_impl.cc @@ -35,42 +35,44 @@ namespace gr { namespace dab { -frequency_interleaver_vcc::sptr -frequency_interleaver_vcc::make(const std::vector &interleaving_sequence) -{ - return gnuradio::get_initial_sptr - (new frequency_interleaver_vcc_impl(interleaving_sequence)); -} + frequency_interleaver_vcc::sptr + frequency_interleaver_vcc::make( + const std::vector &interleaving_sequence) { + return gnuradio::get_initial_sptr + (new frequency_interleaver_vcc_impl(interleaving_sequence)); + } -frequency_interleaver_vcc_impl::frequency_interleaver_vcc_impl(const std::vector &interleaving_sequence) - : gr::sync_block("frequency_interleaver_vcc", - gr::io_signature::make (1, 1, sizeof(gr_complex)*interleaving_sequence.size()), - gr::io_signature::make (1, 1, sizeof(gr_complex)*interleaving_sequence.size())), - d_interleaving_sequence(interleaving_sequence), d_length(interleaving_sequence.size()) -{ - for (unsigned int i=0; i &interleaving_sequence) + : gr::sync_block("frequency_interleaver_vcc", + gr::io_signature::make(1, 1, sizeof(gr_complex) * + interleaving_sequence.size()), + gr::io_signature::make(1, 1, sizeof(gr_complex) * + interleaving_sequence.size())), + d_interleaving_sequence(interleaving_sequence), + d_length(interleaving_sequence.size()) { + for (unsigned int i = 0; i < d_length; i++) + assert(d_interleaving_sequence[i] < (short) d_length); + } -int -frequency_interleaver_vcc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; + int + frequency_interleaver_vcc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + gr_complex const *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; - for (int i = 0; i < noutput_items; i++) { - for (unsigned int j = 0; j < d_length; j++) - out[d_interleaving_sequence[j]] = in[j]; - out += d_length; - in += d_length; - } - - return noutput_items; -} + for (int i = 0; i < noutput_items; i++) { + for (unsigned int j = 0; j < d_length; j++) + out[d_interleaving_sequence[j]] = in[j]; + out += d_length; + in += d_length; + } -} + return noutput_items; + } + + } } diff --git a/lib/frequency_interleaver_vcc_impl.h b/lib/frequency_interleaver_vcc_impl.h index 29249c92..183c1047 100644 --- a/lib/frequency_interleaver_vcc_impl.h +++ b/lib/frequency_interleaver_vcc_impl.h @@ -26,23 +26,29 @@ namespace gr { namespace dab { +/*! \brief interleaves vector elements after the rules of a given interleaving sequence + * + * @param interleaving_sequence sequence defining the interleaving rules + */ + class frequency_interleaver_vcc_impl : public frequency_interleaver_vcc { + private: -class frequency_interleaver_vcc_impl : public frequency_interleaver_vcc -{ - private: + std::vector d_interleaving_sequence; + unsigned int d_length; /*!< length of d_interleaving_sequence*/ - std::vector d_interleaving_sequence; - unsigned int d_length; + public: + frequency_interleaver_vcc_impl( + const std::vector &interleaving_sequence); - public: - frequency_interleaver_vcc_impl(const std::vector &interleaving_sequence); - void set_sequence(const std::vector &interleaving_sequence) { d_interleaving_sequence = interleaving_sequence; } - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; + void set_sequence( + const std::vector &interleaving_sequence) { d_interleaving_sequence = interleaving_sequence; } -} + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } } #endif /* INCLUDED_DAB_FREQUENCY_INTERLEAVER_VCC_H */ diff --git a/lib/insert_null_symbol_impl.cc b/lib/insert_null_symbol_impl.cc index 9d5ff5f8..71a52ba7 100644 --- a/lib/insert_null_symbol_impl.cc +++ b/lib/insert_null_symbol_impl.cc @@ -35,78 +35,82 @@ namespace gr { namespace dab { -insert_null_symbol::sptr -insert_null_symbol::make(int ns_length, int symbol_length) -{ - return gnuradio::get_initial_sptr - (new insert_null_symbol_impl(ns_length, symbol_length)); -} + insert_null_symbol::sptr + insert_null_symbol::make(int ns_length, int symbol_length) { + return gnuradio::get_initial_sptr + (new insert_null_symbol_impl(ns_length, symbol_length)); + } -insert_null_symbol_impl::insert_null_symbol_impl(int ns_length, int symbol_length) - : gr::block("insert_null_symbol", - gr::io_signature::make2 (2, 2, sizeof(gr_complex)*symbol_length, sizeof(char)), - gr::io_signature::make (1, 1, sizeof(gr_complex))), - d_ns_length(ns_length), d_symbol_length(symbol_length), d_ns_added(0) -{ - /* note: setting output_multiple to a high value without setting the relative rate produces - * - * gr_vmcircbuf_sysv_shm: shmget (1): Invalid argument - * gr_buffer::allocate_buffer: failed to allocate buffer of size 102080 KB - * terminate called after throwing an instance of 'std::bad_alloc' - * what(): St9bad_alloc - * - * maybe the scheduler thinks that d_symbol_length input items are needed, which uses a lot of memory - **/ - set_output_multiple(d_symbol_length); - set_relative_rate(d_symbol_length); -} + insert_null_symbol_impl::insert_null_symbol_impl(int ns_length, + int symbol_length) + : gr::block("insert_null_symbol", + gr::io_signature::make2(2, 2, sizeof(gr_complex) * + symbol_length, + sizeof(char)), + gr::io_signature::make(1, 1, sizeof(gr_complex))), + d_ns_length(ns_length), d_symbol_length(symbol_length), + d_ns_added(0) { + /* note: setting output_multiple to a high value without setting the relative rate produces + * + * gr_vmcircbuf_sysv_shm: shmget (1): Invalid argument + * gr_buffer::allocate_buffer: failed to allocate buffer of size 102080 KB + * terminate called after throwing an instance of 'std::bad_alloc' + * what(): St9bad_alloc + * + * maybe the scheduler thinks that d_symbol_length input items are needed, which uses a lot of memory + **/ + set_output_multiple(d_symbol_length); + set_relative_rate(d_symbol_length); + } -void -insert_null_symbol_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - int in_req = noutput_items / d_symbol_length; - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = in_req; -} + void + insert_null_symbol_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + int in_req = noutput_items / d_symbol_length; + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = in_req; + } -int -insert_null_symbol_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *iptr = (const gr_complex *) input_items[0]; - const char *trigger = (const char *) input_items[1]; - - gr_complex *optr = (gr_complex *) output_items[0]; + int + insert_null_symbol_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + const gr_complex *iptr = (const gr_complex *) input_items[0]; + const char *trigger = (const char *) input_items[1]; - int produced_items=0; - int consumed_items=0; - int i; - - while (noutput_items-produced_items>=d_symbol_length && consumed_items= d_symbol_length && + consumed_items < ninput_items[0] && + consumed_items < ninput_items[1]) { + if (*trigger == 1 && d_ns_added < d_ns_length) { + for (i = 0; i < d_ns_length - d_ns_added && + i < noutput_items - produced_items; i++) + *optr++ = 0; + produced_items += i; + d_ns_added += i; + } else { + if (*trigger == 0) + d_ns_added = 0; + for (int i = 0; i < d_symbol_length; i++) + *optr++ = *iptr++; + produced_items += d_symbol_length; + trigger++; + consumed_items++; + } + } + + consume_each(consumed_items); + return produced_items; + } + + } } diff --git a/lib/insert_null_symbol_impl.h b/lib/insert_null_symbol_impl.h index 90acac57..5a88b2b6 100644 --- a/lib/insert_null_symbol_impl.h +++ b/lib/insert_null_symbol_impl.h @@ -26,7 +26,10 @@ namespace gr { namespace dab { - +/*! \brief inserting complex zeros at the beginning of each transmission frame + * @param symbol_length length of the symbol vector + * @param ns_length length of null symbol + */ class insert_null_symbol_impl : public insert_null_symbol { private: diff --git a/lib/mp2_decode_bs_impl.cc b/lib/mp2_decode_bs_impl.cc index cda9adda..06895600 100644 --- a/lib/mp2_decode_bs_impl.cc +++ b/lib/mp2_decode_bs_impl.cc @@ -61,8 +61,10 @@ namespace gr { // bitrate table static const short bitrates[28] = { - 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, // MPEG-1 - 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 // MPEG-2 + 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, + 384, // MPEG-1 + 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, + 160 // MPEG-2 }; // scale factor base values (24-bit fixed-point) @@ -72,70 +74,134 @@ namespace gr { // synthesis window static const int D[512] = { - 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, -0x00001, - -0x00001, -0x00001, -0x00001, -0x00002, -0x00002, -0x00003, -0x00003, -0x00004, - -0x00004, -0x00005, -0x00006, -0x00006, -0x00007, -0x00008, -0x00009, -0x0000A, - -0x0000C, -0x0000D, -0x0000F, -0x00010, -0x00012, -0x00014, -0x00017, -0x00019, - -0x0001C, -0x0001E, -0x00022, -0x00025, -0x00028, -0x0002C, -0x00030, -0x00034, - -0x00039, -0x0003E, -0x00043, -0x00048, -0x0004E, -0x00054, -0x0005A, -0x00060, - -0x00067, -0x0006E, -0x00074, -0x0007C, -0x00083, -0x0008A, -0x00092, -0x00099, - -0x000A0, -0x000A8, -0x000AF, -0x000B6, -0x000BD, -0x000C3, -0x000C9, -0x000CF, - 0x000D5, 0x000DA, 0x000DE, 0x000E1, 0x000E3, 0x000E4, 0x000E4, 0x000E3, - 0x000E0, 0x000DD, 0x000D7, 0x000D0, 0x000C8, 0x000BD, 0x000B1, 0x000A3, - 0x00092, 0x0007F, 0x0006A, 0x00053, 0x00039, 0x0001D, -0x00001, -0x00023, - -0x00047, -0x0006E, -0x00098, -0x000C4, -0x000F3, -0x00125, -0x0015A, -0x00190, - -0x001CA, -0x00206, -0x00244, -0x00284, -0x002C6, -0x0030A, -0x0034F, -0x00396, - -0x003DE, -0x00427, -0x00470, -0x004B9, -0x00502, -0x0054B, -0x00593, -0x005D9, - -0x0061E, -0x00661, -0x006A1, -0x006DE, -0x00718, -0x0074D, -0x0077E, -0x007A9, - -0x007D0, -0x007EF, -0x00808, -0x0081A, -0x00824, -0x00826, -0x0081F, -0x0080E, - 0x007F5, 0x007D0, 0x007A0, 0x00765, 0x0071E, 0x006CB, 0x0066C, 0x005FF, - 0x00586, 0x00500, 0x0046B, 0x003CA, 0x0031A, 0x0025D, 0x00192, 0x000B9, - -0x0002C, -0x0011F, -0x00220, -0x0032D, -0x00446, -0x0056B, -0x0069B, -0x007D5, - -0x00919, -0x00A66, -0x00BBB, -0x00D16, -0x00E78, -0x00FDE, -0x01148, -0x012B3, - -0x01420, -0x0158C, -0x016F6, -0x0185C, -0x019BC, -0x01B16, -0x01C66, -0x01DAC, - -0x01EE5, -0x02010, -0x0212A, -0x02232, -0x02325, -0x02402, -0x024C7, -0x02570, - -0x025FE, -0x0266D, -0x026BB, -0x026E6, -0x026ED, -0x026CE, -0x02686, -0x02615, - -0x02577, -0x024AC, -0x023B2, -0x02287, -0x0212B, -0x01F9B, -0x01DD7, -0x01BDD, - 0x019AE, 0x01747, 0x014A8, 0x011D1, 0x00EC0, 0x00B77, 0x007F5, 0x0043A, - 0x00046, -0x003E5, -0x00849, -0x00CE3, -0x011B4, -0x016B9, -0x01BF1, -0x0215B, - -0x026F6, -0x02CBE, -0x032B3, -0x038D3, -0x03F1A, -0x04586, -0x04C15, -0x052C4, - -0x05990, -0x06075, -0x06771, -0x06E80, -0x0759F, -0x07CCA, -0x083FE, -0x08B37, - -0x09270, -0x099A7, -0x0A0D7, -0x0A7FD, -0x0AF14, -0x0B618, -0x0BD05, -0x0C3D8, - -0x0CA8C, -0x0D11D, -0x0D789, -0x0DDC9, -0x0E3DC, -0x0E9BD, -0x0EF68, -0x0F4DB, - -0x0FA12, -0x0FF09, -0x103BD, -0x1082C, -0x10C53, -0x1102E, -0x113BD, -0x116FB, - -0x119E8, -0x11C82, -0x11EC6, -0x120B3, -0x12248, -0x12385, -0x12467, -0x124EF, - 0x1251E, 0x124F0, 0x12468, 0x12386, 0x12249, 0x120B4, 0x11EC7, 0x11C83, - 0x119E9, 0x116FC, 0x113BE, 0x1102F, 0x10C54, 0x1082D, 0x103BE, 0x0FF0A, - 0x0FA13, 0x0F4DC, 0x0EF69, 0x0E9BE, 0x0E3DD, 0x0DDCA, 0x0D78A, 0x0D11E, - 0x0CA8D, 0x0C3D9, 0x0BD06, 0x0B619, 0x0AF15, 0x0A7FE, 0x0A0D8, 0x099A8, - 0x09271, 0x08B38, 0x083FF, 0x07CCB, 0x075A0, 0x06E81, 0x06772, 0x06076, - 0x05991, 0x052C5, 0x04C16, 0x04587, 0x03F1B, 0x038D4, 0x032B4, 0x02CBF, - 0x026F7, 0x0215C, 0x01BF2, 0x016BA, 0x011B5, 0x00CE4, 0x0084A, 0x003E6, - -0x00045, -0x00439, -0x007F4, -0x00B76, -0x00EBF, -0x011D0, -0x014A7, -0x01746, - 0x019AE, 0x01BDE, 0x01DD8, 0x01F9C, 0x0212C, 0x02288, 0x023B3, 0x024AD, - 0x02578, 0x02616, 0x02687, 0x026CF, 0x026EE, 0x026E7, 0x026BC, 0x0266E, - 0x025FF, 0x02571, 0x024C8, 0x02403, 0x02326, 0x02233, 0x0212B, 0x02011, - 0x01EE6, 0x01DAD, 0x01C67, 0x01B17, 0x019BD, 0x0185D, 0x016F7, 0x0158D, - 0x01421, 0x012B4, 0x01149, 0x00FDF, 0x00E79, 0x00D17, 0x00BBC, 0x00A67, - 0x0091A, 0x007D6, 0x0069C, 0x0056C, 0x00447, 0x0032E, 0x00221, 0x00120, - 0x0002D, -0x000B8, -0x00191, -0x0025C, -0x00319, -0x003C9, -0x0046A, -0x004FF, - -0x00585, -0x005FE, -0x0066B, -0x006CA, -0x0071D, -0x00764, -0x0079F, -0x007CF, - 0x007F5, 0x0080F, 0x00820, 0x00827, 0x00825, 0x0081B, 0x00809, 0x007F0, - 0x007D1, 0x007AA, 0x0077F, 0x0074E, 0x00719, 0x006DF, 0x006A2, 0x00662, - 0x0061F, 0x005DA, 0x00594, 0x0054C, 0x00503, 0x004BA, 0x00471, 0x00428, - 0x003DF, 0x00397, 0x00350, 0x0030B, 0x002C7, 0x00285, 0x00245, 0x00207, - 0x001CB, 0x00191, 0x0015B, 0x00126, 0x000F4, 0x000C5, 0x00099, 0x0006F, - 0x00048, 0x00024, 0x00002, -0x0001C, -0x00038, -0x00052, -0x00069, -0x0007E, - -0x00091, -0x000A2, -0x000B0, -0x000BC, -0x000C7, -0x000CF, -0x000D6, -0x000DC, - -0x000DF, -0x000E2, -0x000E3, -0x000E3, -0x000E2, -0x000E0, -0x000DD, -0x000D9, - 0x000D5, 0x000D0, 0x000CA, 0x000C4, 0x000BE, 0x000B7, 0x000B0, 0x000A9, - 0x000A1, 0x0009A, 0x00093, 0x0008B, 0x00084, 0x0007D, 0x00075, 0x0006F, - 0x00068, 0x00061, 0x0005B, 0x00055, 0x0004F, 0x00049, 0x00044, 0x0003F, - 0x0003A, 0x00035, 0x00031, 0x0002D, 0x00029, 0x00026, 0x00023, 0x0001F, - 0x0001D, 0x0001A, 0x00018, 0x00015, 0x00013, 0x00011, 0x00010, 0x0000E, - 0x0000D, 0x0000B, 0x0000A, 0x00009, 0x00008, 0x00007, 0x00007, 0x00006, - 0x00005, 0x00005, 0x00004, 0x00004, 0x00003, 0x00003, 0x00002, 0x00002, - 0x00002, 0x00002, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001 + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, + -0x00001, + -0x00001, -0x00001, -0x00001, -0x00002, -0x00002, -0x00003, + -0x00003, -0x00004, + -0x00004, -0x00005, -0x00006, -0x00006, -0x00007, -0x00008, + -0x00009, -0x0000A, + -0x0000C, -0x0000D, -0x0000F, -0x00010, -0x00012, -0x00014, + -0x00017, -0x00019, + -0x0001C, -0x0001E, -0x00022, -0x00025, -0x00028, -0x0002C, + -0x00030, -0x00034, + -0x00039, -0x0003E, -0x00043, -0x00048, -0x0004E, -0x00054, + -0x0005A, -0x00060, + -0x00067, -0x0006E, -0x00074, -0x0007C, -0x00083, -0x0008A, + -0x00092, -0x00099, + -0x000A0, -0x000A8, -0x000AF, -0x000B6, -0x000BD, -0x000C3, + -0x000C9, -0x000CF, + 0x000D5, 0x000DA, 0x000DE, 0x000E1, 0x000E3, 0x000E4, 0x000E4, + 0x000E3, + 0x000E0, 0x000DD, 0x000D7, 0x000D0, 0x000C8, 0x000BD, 0x000B1, + 0x000A3, + 0x00092, 0x0007F, 0x0006A, 0x00053, 0x00039, 0x0001D, -0x00001, + -0x00023, + -0x00047, -0x0006E, -0x00098, -0x000C4, -0x000F3, -0x00125, + -0x0015A, -0x00190, + -0x001CA, -0x00206, -0x00244, -0x00284, -0x002C6, -0x0030A, + -0x0034F, -0x00396, + -0x003DE, -0x00427, -0x00470, -0x004B9, -0x00502, -0x0054B, + -0x00593, -0x005D9, + -0x0061E, -0x00661, -0x006A1, -0x006DE, -0x00718, -0x0074D, + -0x0077E, -0x007A9, + -0x007D0, -0x007EF, -0x00808, -0x0081A, -0x00824, -0x00826, + -0x0081F, -0x0080E, + 0x007F5, 0x007D0, 0x007A0, 0x00765, 0x0071E, 0x006CB, 0x0066C, + 0x005FF, + 0x00586, 0x00500, 0x0046B, 0x003CA, 0x0031A, 0x0025D, 0x00192, + 0x000B9, + -0x0002C, -0x0011F, -0x00220, -0x0032D, -0x00446, -0x0056B, + -0x0069B, -0x007D5, + -0x00919, -0x00A66, -0x00BBB, -0x00D16, -0x00E78, -0x00FDE, + -0x01148, -0x012B3, + -0x01420, -0x0158C, -0x016F6, -0x0185C, -0x019BC, -0x01B16, + -0x01C66, -0x01DAC, + -0x01EE5, -0x02010, -0x0212A, -0x02232, -0x02325, -0x02402, + -0x024C7, -0x02570, + -0x025FE, -0x0266D, -0x026BB, -0x026E6, -0x026ED, -0x026CE, + -0x02686, -0x02615, + -0x02577, -0x024AC, -0x023B2, -0x02287, -0x0212B, -0x01F9B, + -0x01DD7, -0x01BDD, + 0x019AE, 0x01747, 0x014A8, 0x011D1, 0x00EC0, 0x00B77, 0x007F5, + 0x0043A, + 0x00046, -0x003E5, -0x00849, -0x00CE3, -0x011B4, -0x016B9, -0x01BF1, + -0x0215B, + -0x026F6, -0x02CBE, -0x032B3, -0x038D3, -0x03F1A, -0x04586, + -0x04C15, -0x052C4, + -0x05990, -0x06075, -0x06771, -0x06E80, -0x0759F, -0x07CCA, + -0x083FE, -0x08B37, + -0x09270, -0x099A7, -0x0A0D7, -0x0A7FD, -0x0AF14, -0x0B618, + -0x0BD05, -0x0C3D8, + -0x0CA8C, -0x0D11D, -0x0D789, -0x0DDC9, -0x0E3DC, -0x0E9BD, + -0x0EF68, -0x0F4DB, + -0x0FA12, -0x0FF09, -0x103BD, -0x1082C, -0x10C53, -0x1102E, + -0x113BD, -0x116FB, + -0x119E8, -0x11C82, -0x11EC6, -0x120B3, -0x12248, -0x12385, + -0x12467, -0x124EF, + 0x1251E, 0x124F0, 0x12468, 0x12386, 0x12249, 0x120B4, 0x11EC7, + 0x11C83, + 0x119E9, 0x116FC, 0x113BE, 0x1102F, 0x10C54, 0x1082D, 0x103BE, + 0x0FF0A, + 0x0FA13, 0x0F4DC, 0x0EF69, 0x0E9BE, 0x0E3DD, 0x0DDCA, 0x0D78A, + 0x0D11E, + 0x0CA8D, 0x0C3D9, 0x0BD06, 0x0B619, 0x0AF15, 0x0A7FE, 0x0A0D8, + 0x099A8, + 0x09271, 0x08B38, 0x083FF, 0x07CCB, 0x075A0, 0x06E81, 0x06772, + 0x06076, + 0x05991, 0x052C5, 0x04C16, 0x04587, 0x03F1B, 0x038D4, 0x032B4, + 0x02CBF, + 0x026F7, 0x0215C, 0x01BF2, 0x016BA, 0x011B5, 0x00CE4, 0x0084A, + 0x003E6, + -0x00045, -0x00439, -0x007F4, -0x00B76, -0x00EBF, -0x011D0, + -0x014A7, -0x01746, + 0x019AE, 0x01BDE, 0x01DD8, 0x01F9C, 0x0212C, 0x02288, 0x023B3, + 0x024AD, + 0x02578, 0x02616, 0x02687, 0x026CF, 0x026EE, 0x026E7, 0x026BC, + 0x0266E, + 0x025FF, 0x02571, 0x024C8, 0x02403, 0x02326, 0x02233, 0x0212B, + 0x02011, + 0x01EE6, 0x01DAD, 0x01C67, 0x01B17, 0x019BD, 0x0185D, 0x016F7, + 0x0158D, + 0x01421, 0x012B4, 0x01149, 0x00FDF, 0x00E79, 0x00D17, 0x00BBC, + 0x00A67, + 0x0091A, 0x007D6, 0x0069C, 0x0056C, 0x00447, 0x0032E, 0x00221, + 0x00120, + 0x0002D, -0x000B8, -0x00191, -0x0025C, -0x00319, -0x003C9, -0x0046A, + -0x004FF, + -0x00585, -0x005FE, -0x0066B, -0x006CA, -0x0071D, -0x00764, + -0x0079F, -0x007CF, + 0x007F5, 0x0080F, 0x00820, 0x00827, 0x00825, 0x0081B, 0x00809, + 0x007F0, + 0x007D1, 0x007AA, 0x0077F, 0x0074E, 0x00719, 0x006DF, 0x006A2, + 0x00662, + 0x0061F, 0x005DA, 0x00594, 0x0054C, 0x00503, 0x004BA, 0x00471, + 0x00428, + 0x003DF, 0x00397, 0x00350, 0x0030B, 0x002C7, 0x00285, 0x00245, + 0x00207, + 0x001CB, 0x00191, 0x0015B, 0x00126, 0x000F4, 0x000C5, 0x00099, + 0x0006F, + 0x00048, 0x00024, 0x00002, -0x0001C, -0x00038, -0x00052, -0x00069, + -0x0007E, + -0x00091, -0x000A2, -0x000B0, -0x000BC, -0x000C7, -0x000CF, + -0x000D6, -0x000DC, + -0x000DF, -0x000E2, -0x000E3, -0x000E3, -0x000E2, -0x000E0, + -0x000DD, -0x000D9, + 0x000D5, 0x000D0, 0x000CA, 0x000C4, 0x000BE, 0x000B7, 0x000B0, + 0x000A9, + 0x000A1, 0x0009A, 0x00093, 0x0008B, 0x00084, 0x0007D, 0x00075, + 0x0006F, + 0x00068, 0x00061, 0x0005B, 0x00055, 0x0004F, 0x00049, 0x00044, + 0x0003F, + 0x0003A, 0x00035, 0x00031, 0x0002D, 0x00029, 0x00026, 0x00023, + 0x0001F, + 0x0001D, 0x0001A, 0x00018, 0x00015, 0x00013, 0x00011, 0x00010, + 0x0000E, + 0x0000D, 0x0000B, 0x0000A, 0x00009, 0x00008, 0x00007, 0x00007, + 0x00006, + 0x00005, 0x00005, 0x00004, 0x00004, 0x00003, 0x00003, 0x00002, + 0x00002, + 0x00002, 0x00002, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001, + 0x00001 }; ///////////// Table 3-B.2: Possible quantization per subband /////////////////// @@ -219,8 +285,7 @@ namespace gr { mp2_decode_bs::sptr - mp2_decode_bs::make(int bit_rate_n) - { + mp2_decode_bs::make(int bit_rate_n) { return gnuradio::get_initial_sptr (new mp2_decode_bs_impl(bit_rate_n)); } @@ -231,9 +296,9 @@ namespace gr { mp2_decode_bs_impl::mp2_decode_bs_impl(int bit_rate_n) : gr::block("mp2_decode_bs", gr::io_signature::make(1, 1, sizeof(unsigned char)), - gr::io_signature::make(2, 2, sizeof(int16_t))), /* output is always stereo*/ - d_bit_rate_n(bit_rate_n) - { + gr::io_signature::make(2, 2, + sizeof(int16_t))), /* output is always stereo*/ + d_bit_rate_n(bit_rate_n) { d_bit_rate = d_bit_rate_n * 8; int16_t i, j; @@ -269,15 +334,13 @@ namespace gr { /* * Our virtual destructor. */ - mp2_decode_bs_impl::~mp2_decode_bs_impl() - { + mp2_decode_bs_impl::~mp2_decode_bs_impl() { delete[] d_mp2_frame; } #define valid(x) ((x == 48000) || (x == 24000)) - void mp2_decode_bs_impl::set_samplerate(int32_t rate) - { + void mp2_decode_bs_impl::set_samplerate(int32_t rate) { if (d_baud_rate == rate) return; if (!valid (rate)) @@ -286,29 +349,28 @@ namespace gr { d_baud_rate = rate; } - int32_t mp2_decode_bs_impl::mp2_samplerate(uint8_t *frame) - { + int32_t mp2_decode_bs_impl::mp2_samplerate(uint8_t *frame) { if (!frame) return 0; if ((frame[0] != 0xFF) // no valid syncword? || ((frame[1] & 0xF6) != 0xF4) // no MPEG-1/2 Audio Layer II? || ((frame[2] - 0x10) >= 0xE0)) // invalid bitrate? return 0; - d_sample_rate = sample_rates[(((frame[1] & 0x08) >> 1) ^ 4) // MPEG-1/2 switch - + ((frame[2] >> 2) & 3)]; // actual rate + d_sample_rate = sample_rates[ + (((frame[1] & 0x08) >> 1) ^ 4) // MPEG-1/2 switch + + ((frame[2] >> 2) & 3)]; // actual rate return d_sample_rate; } - struct quantizer_spec *mp2_decode_bs_impl::read_allocation(int sb, int b2_table) - { + struct quantizer_spec * + mp2_decode_bs_impl::read_allocation(int sb, int b2_table) { int table_idx = quant_lut_step3[b2_table][sb]; table_idx = quant_lut_step4[table_idx & 15][get_bits(table_idx >> 4)]; return table_idx ? (&quantizer_table[table_idx - 1]) : 0; } void mp2_decode_bs_impl::read_samples(struct quantizer_spec *q, - int scalefactor, int *sample) - { + int scalefactor, int *sample) { int idx, adj, scale; register int val; @@ -347,15 +409,15 @@ namespace gr { val = (adj - sample[idx]) * scale; // step 2: apply scalefactor sample[idx] = (val * (scalefactor >> 12) // upper part - + ((val * (scalefactor & 4095) + 2048) >> 12)) // lower part + + ((val * (scalefactor & 4095) + 2048) + >> 12)) // lower part >> 12; // scale adjust } } #define show_bits(bit_count) (bit_window >> (24 - (bit_count))) - int32_t mp2_decode_bs_impl::get_bits(int32_t bit_count) - { + int32_t mp2_decode_bs_impl::get_bits(int32_t bit_count) { //int32_t result = show_bits (bit_count); int32_t result = bit_window >> (24 - bit_count); @@ -372,8 +434,7 @@ namespace gr { // FRAME DECODE FUNCTION // //////////////////////////////////////////////////////////////////////////////// - int32_t mp2_decode_bs_impl::mp2_decode_frame(uint8_t *frame, int16_t *pcm) - { + int32_t mp2_decode_bs_impl::mp2_decode_frame(uint8_t *frame, int16_t *pcm) { uint32_t bit_rate_index_minus1; uint32_t sampling_frequency; uint32_t padding_bit; @@ -588,8 +649,7 @@ namespace gr { return frame_size; } - void mp2_decode_bs_impl::add_bit_to_mp2(uint8_t *v, uint8_t b, int16_t nm) - { + void mp2_decode_bs_impl::add_bit_to_mp2(uint8_t *v, uint8_t b, int16_t nm) { uint8_t byte = v[nm / 8]; int16_t bitnr = 7 - (nm & 7); uint8_t newbyte = (01 << bitnr); @@ -602,25 +662,27 @@ namespace gr { } void - mp2_decode_bs_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items / d_output_size * d_mp2_framesize; + mp2_decode_bs_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = + noutput_items / d_output_size * d_mp2_framesize; } int mp2_decode_bs_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; // input are unpacked bytes int16_t *out_left = (int16_t *) output_items[0]; int16_t *out_right = (int16_t *) output_items[1]; d_nproduced = 0; - for (int logical_frame_count; logical_frame_count < noutput_items / d_output_size; logical_frame_count++) { + for (int logical_frame_count; logical_frame_count < noutput_items / + d_output_size; logical_frame_count++) { int16_t i, j; - int16_t lf = d_baud_rate == 48000 ? d_mp2_framesize : 2 * d_mp2_framesize; + int16_t lf = + d_baud_rate == 48000 ? d_mp2_framesize : 2 * d_mp2_framesize; uint8_t help[24 * d_bit_rate_n]; int16_t vlength = 24 * d_bit_rate / 8; @@ -629,7 +691,9 @@ namespace gr { for (i = 0; i < d_mp2_framesize; i++) { // decoder is in sync with MPEG frame if (d_mp2_header_OK == 2) { - add_bit_to_mp2(d_mp2_frame, in[logical_frame_count * d_mp2_framesize + i], d_mp2_bit_count++); + add_bit_to_mp2(d_mp2_frame, + in[logical_frame_count * d_mp2_framesize + i], + d_mp2_bit_count++); if (d_mp2_bit_count >= lf) { // prepare buffer for PCM stereo samples int16_t sample_buf[KJMP2_SAMPLES_PER_FRAME * 2]; @@ -637,8 +701,8 @@ namespace gr { if (mp2_decode_frame(d_mp2_frame, sample_buf)) { // write successfully decoded data to output buffer for (int n = 0; n < KJMP2_SAMPLES_PER_FRAME; n++) { - out_left[d_nproduced + n] = sample_buf[n*2]; - out_right[d_nproduced + n] = sample_buf[n*2+1]; + out_left[d_nproduced + n] = sample_buf[n * 2]; + out_right[d_nproduced + n] = sample_buf[n * 2 + 1]; } d_nproduced += KJMP2_SAMPLES_PER_FRAME; GR_LOG_DEBUG(d_logger, "mp2 decoding succeeded"); @@ -658,11 +722,13 @@ namespace gr { add_bit_to_mp2(d_mp2_frame, 1, d_mp2_bit_count++); d_mp2_header_OK = 1; } - }else { + } else { d_mp2_header_count = 0; } } else if (d_mp2_header_OK == 1) { - add_bit_to_mp2(d_mp2_frame, in[logical_frame_count * d_mp2_framesize + i], d_mp2_bit_count++); + add_bit_to_mp2(d_mp2_frame, + in[logical_frame_count * d_mp2_framesize + i], + d_mp2_bit_count++); if (d_mp2_bit_count == 24) { set_samplerate(mp2_samplerate(d_mp2_frame)); d_mp2_header_OK = 2; diff --git a/lib/mp2_decode_bs_impl.h b/lib/mp2_decode_bs_impl.h index 62ca2b7e..f1137bc6 100644 --- a/lib/mp2_decode_bs_impl.h +++ b/lib/mp2_decode_bs_impl.h @@ -33,9 +33,9 @@ #define INCLUDED_DAB_MP2_DECODE_BS_IMPL_H #include -#include -#include -#include +#include +#include +#include //#include "pad-handler.h" namespace gr { @@ -106,8 +106,7 @@ namespace gr { ~mp2_decode_bs_impl(); - virtual int32_t get_sample_rate() - {return d_sample_rate;} + virtual int32_t get_sample_rate() { return d_sample_rate; } // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/mp2_encode_sb_impl.cc b/lib/mp2_encode_sb_impl.cc index a0e5fa29..f638a2ec 100644 --- a/lib/mp2_encode_sb_impl.cc +++ b/lib/mp2_encode_sb_impl.cc @@ -39,8 +39,7 @@ namespace gr { namespace dab { mp2_encode_sb::sptr - mp2_encode_sb::make(int bit_rate_n, int channels, int sample_rate) - { + mp2_encode_sb::make(int bit_rate_n, int channels, int sample_rate) { return gnuradio::get_initial_sptr (new mp2_encode_sb_impl(bit_rate_n, channels, sample_rate)); } @@ -48,17 +47,21 @@ namespace gr { /* * The private constructor */ - mp2_encode_sb_impl::mp2_encode_sb_impl(int bit_rate_n, int channels, int sample_rate) + mp2_encode_sb_impl::mp2_encode_sb_impl(int bit_rate_n, int channels, + int sample_rate) : gr::block("mp2_encode_sb", - gr::io_signature::make(channels, channels, sizeof(int16_t)), + gr::io_signature::make(channels, channels, + sizeof(int16_t)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_bit_rate_n(bit_rate_n), d_channels(channels), d_samp_rate(sample_rate) - { - if(init_encoder()){ + d_bit_rate_n(bit_rate_n), d_channels(channels), + d_samp_rate(sample_rate) { + if (init_encoder()) { GR_LOG_DEBUG(d_logger, "libtoolame-dab init succeeded"); } if (!(d_samp_rate == 24000 || d_samp_rate == 48000)) { - throw std::invalid_argument((format("samp_rate must be 24kHz or 48kHz, not %d") % d_samp_rate).str()); + throw std::invalid_argument( + (format("samp_rate must be 24kHz or 48kHz, not %d") % + d_samp_rate).str()); } d_input_size = 1152; // output size depends on bitrate and sample_rate, d_output_size is max output size @@ -69,16 +72,14 @@ namespace gr { /* * Our virtual destructor. */ - mp2_encode_sb_impl::~mp2_encode_sb_impl() - { + mp2_encode_sb_impl::~mp2_encode_sb_impl() { } /*! \brief initialization of the libtoolame encoder * * @return true if init succeeded */ - bool mp2_encode_sb_impl::init_encoder() - { + bool mp2_encode_sb_impl::init_encoder() { // initialize int err = toolame_init(); // set samplerate @@ -100,7 +101,8 @@ namespace gr { } else if (d_channels == 1) { dab_channel_mode = 'm'; // Default to mono } else { - GR_LOG_ERROR(d_logger, format("Unsupported channels number %d") % d_channels); + GR_LOG_ERROR(d_logger, + format("Unsupported channels number %d") % d_channels); return false; } if (err == 0) { @@ -114,24 +116,22 @@ namespace gr { if (err) { GR_LOG_ERROR(d_logger, "libtoolame-dab init failed"); return false; - } - else{ + } else { return true; } } void - mp2_encode_sb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items*d_input_size/d_output_size; + mp2_encode_sb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = noutput_items * d_input_size / d_output_size; } int mp2_encode_sb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const int16_t *in_ch1 = (const int16_t *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; // input buffer for one MPEG output frame @@ -144,23 +144,28 @@ namespace gr { unsigned char pad_buf[padlen + 1]; int num_out_bytes; - for (int i = 0; i < noutput_items/d_output_size; ++i) { + for (int i = 0; i < noutput_items / d_output_size; ++i) { // write next frame to buffer (1 or 2 channels for mono or stereo respectively) - if (d_channels == 1){ - memcpy(input_buffers[0], &in_ch1[d_nconsumed], d_input_size * sizeof(int16_t)); - } - else if(d_channels == 2) { // merge channels if stereo + if (d_channels == 1) { + memcpy(input_buffers[0], &in_ch1[d_nconsumed], + d_input_size * sizeof(int16_t)); + } else if (d_channels == 2) { // merge channels if stereo const int16_t *in_ch2 = (const int16_t *) input_items[1]; - memcpy(input_buffers[0], &in_ch1[d_nconsumed], d_input_size * sizeof(int16_t)); - memcpy(input_buffers[1], &in_ch2[d_nconsumed], d_input_size * sizeof(int16_t)); + memcpy(input_buffers[0], &in_ch1[d_nconsumed], + d_input_size * sizeof(int16_t)); + memcpy(input_buffers[1], &in_ch2[d_nconsumed], + d_input_size * sizeof(int16_t)); } // encode - num_out_bytes = toolame_encode_frame(input_buffers, pad_buf, padlen, &out[d_nproduced], d_output_size); + num_out_bytes = toolame_encode_frame(input_buffers, pad_buf, padlen, + &out[d_nproduced], d_output_size); // we always consume d_input_size = 1152 samples per channel d_nconsumed += d_input_size; // we only produce an output frame every 4-10 cycles (depends on configuration) d_nproduced += num_out_bytes; - GR_LOG_DEBUG(d_logger, format("Encoded frame successfully: %d consumed, %d produced") %d_nconsumed %num_out_bytes); + GR_LOG_DEBUG(d_logger, + format("Encoded frame successfully: %d consumed, %d produced") % + d_nconsumed % num_out_bytes); } // Tell runtime system how many input items we consumed on diff --git a/lib/mp2_encode_sb_impl.h b/lib/mp2_encode_sb_impl.h index 8d052d1d..ca34945f 100644 --- a/lib/mp2_encode_sb_impl.h +++ b/lib/mp2_encode_sb_impl.h @@ -40,26 +40,26 @@ namespace gr { * @param sample_rate sample rate of the PCM audio stream * */ - class mp2_encode_sb_impl : public mp2_encode_sb - { - private: + class mp2_encode_sb_impl : public mp2_encode_sb { + private: int d_bit_rate_n, d_channels, d_samp_rate; int d_output_size, d_input_size; int d_nproduced, d_nconsumed; bool init_encoder(); - public: + public: mp2_encode_sb_impl(int bit_rate_n, int channels, int sample_rate); + ~mp2_encode_sb_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index 92bf126b..bf30b5c8 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -44,8 +44,7 @@ namespace gr { namespace dab { mp4_decode_bs::sptr - mp4_decode_bs::make(int bit_rate_n) - { + mp4_decode_bs::make(int bit_rate_n) { return gnuradio::get_initial_sptr (new mp4_decode_bs_impl(bit_rate_n)); } @@ -57,12 +56,12 @@ namespace gr { : gr::block("mp4_decode_bs", gr::io_signature::make(1, 1, sizeof(unsigned char)), gr::io_signature::make(2, 2, sizeof(int16_t))), - d_bit_rate_n(bit_rate_n) - { + d_bit_rate_n(bit_rate_n) { d_superframe_size = bit_rate_n * 110; d_aacInitialized = false; baudRate = 48000; - set_output_multiple(960 * 4); //TODO: right? baudRate*0.12 for output of one superframe + set_output_multiple(960 * + 4); //TODO: right? baudRate*0.12 for output of one superframe aacHandle = NeAACDecOpen(); //memset(d_aac_frame, 0, 960); d_sample_rate = -1; @@ -71,19 +70,18 @@ namespace gr { /* * Our virtual destructor. */ - mp4_decode_bs_impl::~mp4_decode_bs_impl() - { + mp4_decode_bs_impl::~mp4_decode_bs_impl() { } void - mp4_decode_bs_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + mp4_decode_bs_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; //TODO: how to calculate actual rate? } // returns aac channel configuration - int mp4_decode_bs_impl::get_aac_channel_configuration(int16_t m_mpeg_surround_config, uint8_t aacChannelMode) - { + int mp4_decode_bs_impl::get_aac_channel_configuration( + int16_t m_mpeg_surround_config, uint8_t aacChannelMode) { switch (m_mpeg_surround_config) { case 0: // no surround return aacChannelMode ? 2 : 1; @@ -99,8 +97,7 @@ namespace gr { bool mp4_decode_bs_impl::initialize(uint8_t dacRate, uint8_t sbrFlag, int16_t mpegSurround, - uint8_t aacChannelMode) - { + uint8_t aacChannelMode) { long unsigned int sample_rate; uint8_t channels; /* AudioSpecificConfig structure (the only way to select 960 transform here!) @@ -153,8 +150,7 @@ namespace gr { uint8_t mpegSurround, uint8_t aacChannelMode, int16_t *out_sample1, - int16_t *out_sample2) - { + int16_t *out_sample2) { // copy AU to process it uint8_t au[2 * 960 + 10]; // sure, large enough memcpy(au, v, frame_length); @@ -186,8 +182,7 @@ namespace gr { uint8_t buffer[], int16_t bufferLength, int16_t *out_sample1, - int16_t *out_sample2) - { + int16_t *out_sample2) { int16_t samples; long unsigned int sample_rate; int16_t *outBuffer; @@ -203,7 +198,8 @@ namespace gr { GR_LOG_DEBUG(d_logger, "AAC initialized"); } - outBuffer = (int16_t *) NeAACDecDecode(aacHandle, &hInfo, buffer, bufferLength); + outBuffer = (int16_t *) NeAACDecDecode(aacHandle, &hInfo, buffer, + bufferLength); sample_rate = hInfo.samplerate; samples = hInfo.samples; @@ -216,7 +212,8 @@ namespace gr { d_sample_rate = sample_rate; channels = hInfo.channels; if (hInfo.error != 0) { - GR_LOG_ERROR(d_logger, format("Warning: %s") % faacDecGetErrorMessage(hInfo.error)); + GR_LOG_ERROR(d_logger, format("Warning: %s") % + faacDecGetErrorMessage(hInfo.error)); return 0; } @@ -248,8 +245,7 @@ namespace gr { * @param len length of dataword without the 2 bytes crc at the end * @return true if CRC passed */ - bool mp4_decode_bs_impl::crc16(const uint8_t *msg, int16_t len) - { + bool mp4_decode_bs_impl::crc16(const uint8_t *msg, int16_t len) { int i, j; uint16_t accumulator = 0xFFFF; uint16_t crc; @@ -270,10 +266,12 @@ namespace gr { return (crc ^ accumulator) == 0; } - uint16_t mp4_decode_bs_impl::BinToDec(const uint8_t *data, size_t offset, size_t length) - { - uint32_t output = (*(data + offset / 8) << 16) | ((*(data + offset / 8 + 1)) << 8) | - (*(data + offset / 8 + 2)); // should be big/little endian save + uint16_t mp4_decode_bs_impl::BinToDec(const uint8_t *data, size_t offset, + size_t length) { + uint32_t output = + (*(data + offset / 8) << 16) | ((*(data + offset / 8 + 1)) << 8) | + (*(data + offset / 8 + + 2)); // should be big/little endian save output >>= 24 - length - offset % 8; output &= (0xFFFF >> (16 - length)); return static_cast(output); @@ -283,9 +281,9 @@ namespace gr { mp4_decode_bs_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - const unsigned char *in = (const unsigned char *) input_items[0] + d_superframe_size; + gr_vector_void_star &output_items) { + const unsigned char *in = + (const unsigned char *) input_items[0] + d_superframe_size; int16_t *out1 = (int16_t *) output_items[0]; int16_t *out2 = (int16_t *) output_items[1]; d_nsamples_produced = 0; @@ -296,13 +294,15 @@ namespace gr { // bit 16 is unused d_dac_rate = (in[n * d_superframe_size + 2] >> 6) & 01; // bit 17 d_sbr_flag = (in[n * d_superframe_size + 2] >> 5) & 01; // bit 18 - d_aac_channel_mode = (in[n * d_superframe_size + 2] >> 4) & 01; // bit 19 + d_aac_channel_mode = + (in[n * d_superframe_size + 2] >> 4) & 01; // bit 19 d_ps_flag = (in[n * d_superframe_size + 2] >> 3) & 01; // bit 20 d_mpeg_surround = (in[n * d_superframe_size + 2] & 07); // bits 21 .. 23 // log header information GR_LOG_DEBUG(d_logger, format("superframe header: dac_rate %d, sbr_flag %d, aac_mode %d, ps_flag %d, surround %d") % - (int) d_dac_rate % (int) d_sbr_flag % (int) d_aac_channel_mode % (int) d_ps_flag % + (int) d_dac_rate % (int) d_sbr_flag % + (int) d_aac_channel_mode % (int) d_ps_flag % (int) d_mpeg_surround); switch (2 * d_dac_rate + d_sbr_flag) { @@ -310,35 +310,45 @@ namespace gr { case 0: d_num_aus = 4; d_au_start[0] = 8; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; - d_au_start[3] = in[n * d_superframe_size + 6] * 16 + (in[n * d_superframe_size + 7] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + + in[n * d_superframe_size + 5]; + d_au_start[3] = in[n * d_superframe_size + 6] * 16 + + (in[n * d_superframe_size + 7] >> 4); d_au_start[4] = d_superframe_size; break; case 1: d_num_aus = 2; d_au_start[n * d_superframe_size + 0] = 5; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + + (in[n * d_superframe_size + 4] >> 4); d_au_start[2] = d_superframe_size; break; case 2: d_num_aus = 6; d_au_start[0] = 11; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; - d_au_start[3] = in[n * d_superframe_size + 6] * 16 + (in[n * d_superframe_size + 7] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + + in[n * d_superframe_size + 5]; + d_au_start[3] = in[n * d_superframe_size + 6] * 16 + + (in[n * d_superframe_size + 7] >> 4); d_au_start[4] = (in[n * d_superframe_size + 7] & 0xf) * 256 + in[8]; - d_au_start[5] = in[n * d_superframe_size + 9] * 16 + (in[n * d_superframe_size + 10] >> 4); + d_au_start[5] = in[n * d_superframe_size + 9] * 16 + + (in[n * d_superframe_size + 10] >> 4); d_au_start[6] = d_superframe_size; break; case 3: d_num_aus = 3; d_au_start[0] = 6; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + + in[n * d_superframe_size + 5]; d_au_start[3] = d_superframe_size; break; } @@ -357,11 +367,14 @@ namespace gr { // sanity check for the aac_frame_length if ((aac_frame_length >= 960) || (aac_frame_length < 0)) { - throw std::out_of_range((boost::format("aac frame length not in range (%d)") % aac_frame_length).str()); + throw std::out_of_range( + (boost::format("aac frame length not in range (%d)") % + aac_frame_length).str()); } // CRC check of each AU (the 2 byte (16 bit) CRC word is excluded in aac_frame_length) - if (crc16(&in[n * d_superframe_size + d_au_start[i]], aac_frame_length)) { + if (crc16(&in[n * d_superframe_size + d_au_start[i]], + aac_frame_length)) { //GR_LOG_DEBUG(d_logger, format("CRC check of AU %d successful") % i); // handle proper AU handle_aac_frame(&in[n * d_superframe_size + d_au_start[i]], diff --git a/lib/mp4_decode_bs_impl.h b/lib/mp4_decode_bs_impl.h index 45e7a4bb..0f64c629 100644 --- a/lib/mp4_decode_bs_impl.h +++ b/lib/mp4_decode_bs_impl.h @@ -55,7 +55,8 @@ namespace gr { uint16_t BinToDec(const uint8_t *data, size_t offset, size_t length); - int get_aac_channel_configuration(int16_t m_mpeg_surround_config, uint8_t aacChannelMode); + int get_aac_channel_configuration(int16_t m_mpeg_surround_config, + uint8_t aacChannelMode); bool initialize(uint8_t dacRate, uint8_t sbrFlag, @@ -85,8 +86,7 @@ namespace gr { ~mp4_decode_bs_impl(); - virtual int get_sample_rate() - { return d_sample_rate; } + virtual int get_sample_rate() { return d_sample_rate; } // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/mp4_encode_sb_impl.cc b/lib/mp4_encode_sb_impl.cc index a46028e6..f84047d4 100644 --- a/lib/mp4_encode_sb_impl.cc +++ b/lib/mp4_encode_sb_impl.cc @@ -41,45 +41,53 @@ namespace gr { namespace dab { mp4_encode_sb::sptr - mp4_encode_sb::make(int bit_rate_n, int channels, int samp_rate, int afterburner) - { + mp4_encode_sb::make(int bit_rate_n, int channels, int samp_rate, + int afterburner) { return gnuradio::get_initial_sptr - (new mp4_encode_sb_impl(bit_rate_n, channels, samp_rate, afterburner)); + (new mp4_encode_sb_impl(bit_rate_n, channels, samp_rate, + afterburner)); } /* * The private constructor */ - mp4_encode_sb_impl::mp4_encode_sb_impl(int bit_rate_n, int channels, int samp_rate, int afterburner) + mp4_encode_sb_impl::mp4_encode_sb_impl(int bit_rate_n, int channels, + int samp_rate, int afterburner) : gr::block("mp4_encode_sb", - gr::io_signature::make(channels, channels, sizeof(int16_t)), + gr::io_signature::make(channels, channels, + sizeof(int16_t)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_bit_rate_n(bit_rate_n), d_channels(channels), d_samp_rate(samp_rate), d_afterburner(afterburner) - { + d_bit_rate_n(bit_rate_n), d_channels(channels), + d_samp_rate(samp_rate), d_afterburner(afterburner) { // check input arguments if (d_bit_rate_n < 1 || d_bit_rate_n > 24) { - throw std::out_of_range((format("bit_rate_n out of range (%d)") % d_bit_rate_n).str()); + throw std::out_of_range( + (format("bit_rate_n out of range (%d)") % d_bit_rate_n).str()); } if (!(d_samp_rate == 32000 || d_samp_rate == 48000)) { - throw std::invalid_argument((format("samp_rate must be 32kHz or 48kHz, not %d") % d_samp_rate).str()); + throw std::invalid_argument( + (format("samp_rate must be 32kHz or 48kHz, not %d") % + d_samp_rate).str()); } // initialize AAC encoder d_aot = AOT_NONE; - if (init_aac_encoder(&d_aac_encoder, d_channels, d_samp_rate, d_afterburner, &d_aot)) { + if (init_aac_encoder(&d_aac_encoder, d_channels, d_samp_rate, + d_afterburner, &d_aot)) { GR_LOG_INFO(d_logger, "AAC enc init succeeded"); } else { GR_LOG_ERROR(d_logger, "AAC enc init failed"); - throw std::runtime_error("AAC enc init failed"); + throw std::runtime_error("AAC enc init failed"); } // check encoder status if (aacEncInfo(d_aac_encoder, &info) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to get the encoder info"); - throw std::runtime_error("AAC enc init failed"); + throw std::runtime_error("AAC enc init failed"); } - + // set input size (number of items per channel(in this case one item is a int16_t)) d_input_size = info.frameLength; - GR_LOG_INFO(d_logger, format("AAC Encoding: framelen = %d") % info.frameLength); + GR_LOG_INFO(d_logger, + format("AAC Encoding: framelen = %d") % info.frameLength); // set output size to the superframe size (without Reed Solomon parity check words) d_output_size = d_bit_rate_n * 110; @@ -89,8 +97,7 @@ namespace gr { /* * Our virtual destructor. */ - mp4_encode_sb_impl::~mp4_encode_sb_impl() - { + mp4_encode_sb_impl::~mp4_encode_sb_impl() { aacEncClose(&d_aac_encoder); } @@ -108,8 +115,7 @@ namespace gr { int channels, int sample_rate, int afterburner, - int *aot) - { + int *aot) { // set number of channels CHANNEL_MODE mode; switch (channels) { @@ -120,7 +126,8 @@ namespace gr { mode = MODE_2; break; default: - GR_LOG_ERROR(d_logger, format("Unsupported channels number %d") % channels); + GR_LOG_ERROR(d_logger, + format("Unsupported channels number %d") % channels); return false; } @@ -135,19 +142,22 @@ namespace gr { if (channels == 2 && d_bit_rate_n <= 6) { *aot = AOT_DABPLUS_PS; GR_LOG_INFO(d_logger, "AOT set to AAC Parametric Stereo"); - } else if ((channels == 1 && d_bit_rate_n <= 8) || (channels == 2 && d_bit_rate_n <= 10)) { + } else if ((channels == 1 && d_bit_rate_n <= 8) || + (channels == 2 && d_bit_rate_n <= 10)) { *aot = AOT_DABPLUS_SBR; - GR_LOG_INFO(d_logger, "AOT set to AAC SBR (Spectral Band Replication)"); + GR_LOG_INFO(d_logger, + "AOT set to AAC SBR (Spectral Band Replication)"); } else { *aot = AOT_DABPLUS_AAC_LC; GR_LOG_INFO(d_logger, "AOT set to AAC LC (Low Complexity)"); } } - GR_LOG_INFO(d_logger, format("Using %d subchannels. channels = %d, sample_rate = %d") - % d_bit_rate_n - % channels - % sample_rate); + GR_LOG_INFO(d_logger, + format("Using %d subchannels. channels = %d, sample_rate = %d") + % d_bit_rate_n + % channels + % sample_rate); // set AAC parameters if (aacEncoder_SetParam(*encoder, AACENC_AOT, *aot) != AACENC_OK) { @@ -155,12 +165,14 @@ namespace gr { return false; } // set aac samplerate - if (aacEncoder_SetParam(*encoder, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_SAMPLERATE, sample_rate) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the sample rate"); return false; } // set aac channel mode - if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE, mode) != AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE, mode) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the channel mode"); return false; } @@ -170,23 +182,28 @@ namespace gr { return false; } // set aac granule length (in samples) to 960 (DRM/DAB+) - if (aacEncoder_SetParam(*encoder, AACENC_GRANULE_LENGTH, 960) != AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_GRANULE_LENGTH, 960) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the granule length"); return false; } // set aac transport type - if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX, TT_DABPLUS) != AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX, TT_DABPLUS) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the RAW transmux"); return false; } // set aac bit rate - GR_LOG_INFO(d_logger, format("AAC bitrate set to: %d") % (d_bit_rate_n * 8000)); - if (aacEncoder_SetParam(*encoder, AACENC_BITRATE, d_bit_rate_n * 8000) != AACENC_OK) { + GR_LOG_INFO(d_logger, + format("AAC bitrate set to: %d") % (d_bit_rate_n * 8000)); + if (aacEncoder_SetParam(*encoder, AACENC_BITRATE, d_bit_rate_n * 8000) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the bitrate"); return false; } // set aac afterburner tool - if (aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, afterburner) != AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, afterburner) != + AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the afterburner mode"); return false; } @@ -209,9 +226,10 @@ namespace gr { * @param size_output_buffer size of output buffer * @return true if no errors occurred */ - bool mp4_encode_sb_impl::encode(int16_t *input_buffer, int size_input_buffer, unsigned char *output_buffer, - int size_output_buffer) - { + bool + mp4_encode_sb_impl::encode(int16_t *input_buffer, int size_input_buffer, + unsigned char *output_buffer, + int size_output_buffer) { AACENC_ERROR err; // prepare input buffer @@ -249,20 +267,25 @@ namespace gr { return false; } // if no error occurred we assume everything is fine and dump input frame - nconsumed += out_args.numInSamples / 2; //(each half of numInSamples came from one of the 2 channels) + nconsumed += out_args.numInSamples / + 2; //(each half of numInSamples came from one of the 2 channels) GR_LOG_DEBUG(d_logger, - format("Encoder: consumed %d, produced %d,") % out_args.numInSamples % out_args.numOutBytes); + format("Encoder: consumed %d, produced %d,") % + out_args.numInSamples % out_args.numOutBytes); // buffer check - if (out_args.numInSamples > size_input_buffer || out_args.numOutBytes > size_output_buffer) { - throw std::runtime_error((format("too much samples (%d) to write in ouput buffer (%d samples left)") %out_args.numOutBytes %size_output_buffer).str()); + if (out_args.numInSamples > size_input_buffer || + out_args.numOutBytes > size_output_buffer) { + throw std::runtime_error( + (format("too much samples (%d) to write in ouput buffer (%d samples left)") % + out_args.numOutBytes % size_output_buffer).str()); } nproduced += out_args.numOutBytes; return true; } void - mp4_encode_sb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + mp4_encode_sb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items * d_input_size / d_output_size; ninput_items_required[1] = noutput_items * d_input_size / d_output_size; } @@ -271,21 +294,21 @@ namespace gr { mp4_encode_sb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const int16_t *in_ch1 = (const int16_t *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; int16_t input_buffer[d_input_size * 2]; - GR_LOG_DEBUG(d_logger, format("New buffer with %d samples") % noutput_items); + GR_LOG_DEBUG(d_logger, + format("New buffer with %d samples") % noutput_items); nconsumed = 0; nproduced = 0; do { // copy frame to buffer - if (d_channels == 1){ - memcpy(input_buffer, &in_ch1[nconsumed], d_input_size * sizeof(int16_t)); - } - else if(d_channels == 2) { // merge channels if stereo + if (d_channels == 1) { + memcpy(input_buffer, &in_ch1[nconsumed], + d_input_size * sizeof(int16_t)); + } else if (d_channels == 2) { // merge channels if stereo const int16_t *in_ch2 = (const int16_t *) input_items[1]; for (int i = 0; i < d_input_size; ++i) { input_buffer[2 * i] = in_ch1[nconsumed + i]; @@ -293,7 +316,8 @@ namespace gr { } } // send filled buffer to encoder - encode(input_buffer, d_input_size * d_channels, &out[nproduced], noutput_items - nproduced); // encode input stream + encode(input_buffer, d_input_size * d_channels, &out[nproduced], + noutput_items - nproduced); // encode input stream } while (nproduced < noutput_items / d_output_size); // Tell runtime system how many input items we consumed on diff --git a/lib/mp4_encode_sb_impl.h b/lib/mp4_encode_sb_impl.h index 037d5a5b..0163b65e 100644 --- a/lib/mp4_encode_sb_impl.h +++ b/lib/mp4_encode_sb_impl.h @@ -37,33 +37,36 @@ namespace gr { * @param bit_rate_n data rate in multiples of 8kbit/s * @param channels number of input audio channels */ - class mp4_encode_sb_impl : public mp4_encode_sb - { - private: + class mp4_encode_sb_impl : public mp4_encode_sb { + private: int d_bit_rate_n, d_channels, d_samp_rate, d_afterburner, d_aot; int nconsumed, nproduced; int d_input_size, d_output_size; HANDLE_AACENCODER d_aac_encoder; - AACENC_InfoStruct info = { 0 }; + AACENC_InfoStruct info = {0}; bool init_aac_encoder(HANDLE_AACENCODER *encoder, int channels, int sample_rate, int afterburner, int *aot); - bool encode(int16_t *input_buffer, int size_input_buffer, unsigned char *output_buffer, int size_output_buffer); - public: - mp4_encode_sb_impl(int bit_rate_n, int channels, int samp_rate, int afterburner); + bool encode(int16_t *input_buffer, int size_input_buffer, + unsigned char *output_buffer, int size_output_buffer); + + public: + mp4_encode_sb_impl(int bit_rate_n, int channels, int samp_rate, + int afterburner); + ~mp4_encode_sb_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab From ed03d09af5862800563db5434bedcfc155fc5df6 Mon Sep 17 00:00:00 2001 From: luca Date: Wed, 17 Jan 2018 21:01:52 +0100 Subject: [PATCH 117/135] add docu, wrap up --- lib/neaacdec.h | 128 +++++++------- ...m_coarse_frequency_correction_vcvc_impl.cc | 127 +++++++++----- ...dm_coarse_frequency_correction_vcvc_impl.h | 37 ++-- lib/ofdm_insert_pilot_vcc_impl.cc | 107 ++++++------ lib/ofdm_insert_pilot_vcc_impl.h | 27 ++- lib/ofdm_move_and_insert_zero_impl.cc | 93 +++++----- lib/ofdm_move_and_insert_zero_impl.h | 27 +-- lib/ofdm_synchronization_cvf_impl.cc | 161 ++++++++++-------- lib/ofdm_synchronization_cvf_impl.h | 9 +- lib/prune_impl.cc | 38 +++-- lib/prune_impl.h | 3 +- lib/puncture_bb_impl.cc | 23 ++- lib/qa_dab.cc | 3 +- lib/qa_dab.h | 12 +- 14 files changed, 436 insertions(+), 359 deletions(-) diff --git a/lib/neaacdec.h b/lib/neaacdec.h index 3769d3f0..17900f34 100644 --- a/lib/neaacdec.h +++ b/lib/neaacdec.h @@ -60,14 +60,14 @@ extern "C" { #ifdef _WIN32 - #pragma pack(push, 8) - #ifndef NEAACDECAPI - #define NEAACDECAPI __cdecl - #endif +#pragma pack(push, 8) +#ifndef NEAACDECAPI +#define NEAACDECAPI __cdecl +#endif #else - #ifndef NEAACDECAPI - #define NEAACDECAPI - #endif +#ifndef NEAACDECAPI +#define NEAACDECAPI +#endif #endif #define FAAD2_VERSION "2.7" @@ -138,74 +138,72 @@ extern "C" { typedef void *NeAACDecHandle; -typedef struct mp4AudioSpecificConfig -{ - /* Audio Specific Info */ - unsigned char objectTypeIndex; - unsigned char samplingFrequencyIndex; - unsigned long samplingFrequency; - unsigned char channelsConfiguration; - - /* GA Specific Info */ - unsigned char frameLengthFlag; - unsigned char dependsOnCoreCoder; - unsigned short coreCoderDelay; - unsigned char extensionFlag; - unsigned char aacSectionDataResilienceFlag; - unsigned char aacScalefactorDataResilienceFlag; - unsigned char aacSpectralDataResilienceFlag; - unsigned char epConfig; - - char sbr_present_flag; - char forceUpSampling; - char downSampledSBR; +typedef struct mp4AudioSpecificConfig { + /* Audio Specific Info */ + unsigned char objectTypeIndex; + unsigned char samplingFrequencyIndex; + unsigned long samplingFrequency; + unsigned char channelsConfiguration; + + /* GA Specific Info */ + unsigned char frameLengthFlag; + unsigned char dependsOnCoreCoder; + unsigned short coreCoderDelay; + unsigned char extensionFlag; + unsigned char aacSectionDataResilienceFlag; + unsigned char aacScalefactorDataResilienceFlag; + unsigned char aacSpectralDataResilienceFlag; + unsigned char epConfig; + + char sbr_present_flag; + char forceUpSampling; + char downSampledSBR; } mp4AudioSpecificConfig; -typedef struct NeAACDecConfiguration -{ - unsigned char defObjectType; - unsigned long defSampleRate; - unsigned char outputFormat; - unsigned char downMatrix; - unsigned char useOldADTSFormat; - unsigned char dontUpSampleImplicitSBR; +typedef struct NeAACDecConfiguration { + unsigned char defObjectType; + unsigned long defSampleRate; + unsigned char outputFormat; + unsigned char downMatrix; + unsigned char useOldADTSFormat; + unsigned char dontUpSampleImplicitSBR; } NeAACDecConfiguration, *NeAACDecConfigurationPtr; -typedef struct NeAACDecFrameInfo -{ - unsigned long bytesconsumed; - unsigned long samples; - unsigned char channels; - unsigned char error; - unsigned long samplerate; +typedef struct NeAACDecFrameInfo { + unsigned long bytesconsumed; + unsigned long samples; + unsigned char channels; + unsigned char error; + unsigned long samplerate; - /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ - unsigned char sbr; + /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ + unsigned char sbr; - /* MPEG-4 ObjectType */ - unsigned char object_type; + /* MPEG-4 ObjectType */ + unsigned char object_type; - /* AAC header type; MP4 will be signalled as RAW also */ - unsigned char header_type; + /* AAC header type; MP4 will be signalled as RAW also */ + unsigned char header_type; - /* multichannel configuration */ - unsigned char num_front_channels; - unsigned char num_side_channels; - unsigned char num_back_channels; - unsigned char num_lfe_channels; - unsigned char channel_position[64]; + /* multichannel configuration */ + unsigned char num_front_channels; + unsigned char num_side_channels; + unsigned char num_back_channels; + unsigned char num_lfe_channels; + unsigned char channel_position[64]; - /* PS: 0: off, 1: on */ - unsigned char ps; + /* PS: 0: off, 1: on */ + unsigned char ps; } NeAACDecFrameInfo; -char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode); +char *NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode); unsigned long NEAACDECAPI NeAACDecGetCapabilities(void); NeAACDecHandle NEAACDECAPI NeAACDecOpen(void); -NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); +NeAACDecConfigurationPtr NEAACDECAPI +NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder, NeAACDecConfigurationPtr config); @@ -226,24 +224,24 @@ char NEAACDECAPI NeAACDecInit2(NeAACDecHandle hDecoder, /* Init the library for DRM */ char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hDecoder, - unsigned long samplerate, + unsigned long samplerate, unsigned char channels); char NEAACDECAPI NeAACDecInitDAB(NeAACDecHandle *hDecoder, - unsigned long samplerate, + unsigned long samplerate, unsigned char channels, - unsigned char sbr); + unsigned char sbr); void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame); void NEAACDECAPI NeAACDecClose(NeAACDecHandle hDecoder); -void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, +void *NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, unsigned char *buffer, unsigned long buffer_size); -void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, +void *NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, unsigned char *buffer, unsigned long buffer_size, @@ -255,7 +253,7 @@ char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer, mp4AudioSpecificConfig *mp4ASC); #ifdef _WIN32 - #pragma pack(pop) +#pragma pack(pop) #endif #ifdef __cplusplus diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index 4e841d00..36d975b7 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -31,34 +31,39 @@ namespace gr { namespace dab { ofdm_coarse_frequency_correction_vcvc::sptr - ofdm_coarse_frequency_correction_vcvc::make(int fft_length, int num_carriers, int cyclic_prefix_length) - { + ofdm_coarse_frequency_correction_vcvc::make(int fft_length, + int num_carriers, + int cyclic_prefix_length) { return gnuradio::get_initial_sptr - (new ofdm_coarse_frequency_correction_vcvc_impl(fft_length, num_carriers, cyclic_prefix_length)); + (new ofdm_coarse_frequency_correction_vcvc_impl(fft_length, + num_carriers, + cyclic_prefix_length)); } /* * The private constructor */ - ofdm_coarse_frequency_correction_vcvc_impl::ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, int num_carriers, int cyclic_prefix_length) - : gr::sync_block("ofdm_coarse_frequency_correction_vcvc", - gr::io_signature::make(1, 1, fft_length*sizeof(gr_complex)), - gr::io_signature::make(1, 1, num_carriers*sizeof(gr_complex))), - d_fft_length(fft_length), - d_num_carriers(num_carriers), - d_cyclic_prefix_length(cyclic_prefix_length), - d_freq_offset (0), - d_snr (0) - { + ofdm_coarse_frequency_correction_vcvc_impl::ofdm_coarse_frequency_correction_vcvc_impl( + int fft_length, int num_carriers, int cyclic_prefix_length) + : gr::sync_block("ofdm_coarse_frequency_correction_vcvc", + gr::io_signature::make(1, 1, fft_length * + sizeof(gr_complex)), + gr::io_signature::make(1, 1, num_carriers * + sizeof(gr_complex))), + d_fft_length(fft_length), + d_num_carriers(num_carriers), + d_cyclic_prefix_length(cyclic_prefix_length), + d_freq_offset(0), + d_snr(0) { unsigned int alignment = volk_get_alignment(); - d_mag_squared = (float*)volk_malloc(sizeof(float)*num_carriers+1, alignment); + d_mag_squared = (float *) volk_malloc(sizeof(float) * num_carriers + 1, + alignment); } /* * Our virtual destructor. */ - ofdm_coarse_frequency_correction_vcvc_impl::~ofdm_coarse_frequency_correction_vcvc_impl() - { + ofdm_coarse_frequency_correction_vcvc_impl::~ofdm_coarse_frequency_correction_vcvc_impl() { } /*! Energy measurement over the num_carriers sub_carriers + the central carrier. @@ -66,28 +71,42 @@ namespace gr { * Fine frequency synchronization in the range of one sub-carrier spacing is already done. */ void - ofdm_coarse_frequency_correction_vcvc_impl::measure_energy(const gr_complex *symbol) - { + ofdm_coarse_frequency_correction_vcvc_impl::measure_energy( + const gr_complex *symbol) { unsigned int i, index; float energy = 0, max = 0; // first energy measurement is processed completely - volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, d_num_carriers+1); - volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers+1); + volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, + d_num_carriers + 1); + volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers + 1); // subtract the central (DC) carrier which is not occupied - energy -= std::real(symbol[d_num_carriers])*std::real(symbol[d_num_carriers]) + std::imag(symbol[d_num_carriers])*std::imag(symbol[d_num_carriers]); + energy -= std::real(symbol[d_num_carriers]) * + std::real(symbol[d_num_carriers]) + + std::imag(symbol[d_num_carriers]) * + std::imag(symbol[d_num_carriers]); max = energy; index = 0; /* the energy measurements with all possible carrier offsets are calculated over a moving sum, * searching for a maximum of energy */ - for (i=1; i max) { max = energy; @@ -101,15 +120,19 @@ namespace gr { /*! SNR measurement by comparing the energy of occupied sub-carriers with the ones of empty sub-carriers * @return estimated SNR float value */ - void - ofdm_coarse_frequency_correction_vcvc_impl::measure_snr(const gr_complex *symbol) - { + void + ofdm_coarse_frequency_correction_vcvc_impl::measure_snr( + const gr_complex *symbol) { // measure normalized energy of occupied sub-carriers float energy = 0; - volk_32fc_magnitude_squared_32f(d_mag_squared, &symbol[d_freq_offset], d_num_carriers+1); - volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers+1); + volk_32fc_magnitude_squared_32f(d_mag_squared, &symbol[d_freq_offset], + d_num_carriers + 1); + volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers + 1); // subtract the central (DC) carrier which is not assigned - energy -= std::real(symbol[d_num_carriers+d_freq_offset])*std::real(symbol[d_num_carriers+d_freq_offset]) + std::imag(symbol[d_num_carriers+d_freq_offset])*std::imag(symbol[d_num_carriers+d_freq_offset]); + energy -= std::real(symbol[d_num_carriers + d_freq_offset]) * + std::real(symbol[d_num_carriers + d_freq_offset]) + + std::imag(symbol[d_num_carriers + d_freq_offset]) * + std::imag(symbol[d_num_carriers + d_freq_offset]); // measure normalized energy of empty sub-carriers float noise_left = 0, noise_right, noise_total; @@ -117,30 +140,38 @@ namespace gr { volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, d_freq_offset); volk_32f_accumulator_s32f(&noise_left, d_mag_squared, d_freq_offset); // empty sub-carriers on right side - volk_32fc_magnitude_squared_32f(d_mag_squared, &symbol[d_freq_offset + d_num_carriers + 1], d_fft_length-d_num_carriers-d_freq_offset-1); - volk_32f_accumulator_s32f(&noise_right, d_mag_squared, d_fft_length-d_num_carriers-d_freq_offset-1); + volk_32fc_magnitude_squared_32f(d_mag_squared, + &symbol[d_freq_offset + d_num_carriers + + 1], + d_fft_length - d_num_carriers - + d_freq_offset - 1); + volk_32f_accumulator_s32f(&noise_right, d_mag_squared, + d_fft_length - d_num_carriers - d_freq_offset - + 1); // add noise energies from both sides to total noise noise_total = noise_left + noise_right; - noise_total += std::real(symbol[d_freq_offset+d_num_carriers/2])*std::real(symbol[d_freq_offset+d_num_carriers/2]) + std::imag(symbol[d_freq_offset+d_num_carriers/2])*std::imag(symbol[d_freq_offset+d_num_carriers/2]); + noise_total += std::real(symbol[d_freq_offset + d_num_carriers / 2]) * + std::real(symbol[d_freq_offset + d_num_carriers / 2]) + + std::imag(symbol[d_freq_offset + d_num_carriers / 2]) * + std::imag(symbol[d_freq_offset + d_num_carriers / 2]); // normalize - energy = energy/d_num_carriers; - noise_total = noise_total /(d_fft_length-d_num_carriers); + energy = energy / d_num_carriers; + noise_total = noise_total / (d_fft_length - d_num_carriers); // check if ratio is in the definition range of the log - if(energy > noise_total){ + if (energy > noise_total) { // now we can calculate the SNR in dB - d_snr = 10*log10((energy-noise_total)/noise_total); + d_snr = 10 * log10((energy - noise_total) / noise_total); } } int ofdm_coarse_frequency_correction_vcvc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - std::vector tags; + std::vector tags; unsigned int tag_count = 0; // get tags for the beginning of a frame get_tags_in_window(tags, 0, 0, noutput_items); @@ -148,15 +179,19 @@ namespace gr { /* new calculation for each new frame, measured at the pilot symbol and frequency correction * applied for all symbols of this frame */ - if(tag_count < tags.size() && tags[tag_count].offset-nitems_read(0)-i == 0) { + if (tag_count < tags.size() && + tags[tag_count].offset - nitems_read(0) - i == 0) { measure_energy(&in[i * d_fft_length]); measure_snr(&in[i * d_fft_length]); tag_count++; } // copy the first half (left of central sub-carrier) of the sub-carriers to the output - memcpy(out, &in[i*d_fft_length+d_freq_offset], d_num_carriers/2 * sizeof(gr_complex)); + memcpy(out, &in[i * d_fft_length + d_freq_offset], + d_num_carriers / 2 * sizeof(gr_complex)); // copy the second half (right of central sub-carrier) of the sub-carriers to the output - memcpy(out+d_num_carriers/2, &in[i*d_fft_length+d_freq_offset+d_num_carriers/2+1], d_num_carriers/2 * sizeof(gr_complex)); + memcpy(out + d_num_carriers / 2, + &in[i * d_fft_length + d_freq_offset + d_num_carriers / 2 + 1], + d_num_carriers / 2 * sizeof(gr_complex)); out += d_num_carriers; } diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h index 1824e9db..ed1ab5e0 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h @@ -25,31 +25,40 @@ namespace gr { namespace dab { - - class ofdm_coarse_frequency_correction_vcvc_impl : public ofdm_coarse_frequency_correction_vcvc - { - private: +/*! \brief coarse frequency correction on multiples of the sub-carrier spacing + * synchronization on sub-carriers for DAB/DAB+ by energy measurements of the sub-carriers + * + * @param fft_length length of the applied FFT; corresponding to the input vector length + * @param num_carriers number of occupied carriers; corresponding to the output vector length + * @param cyclic_prefix_length length of the cyclic prefix; corresponding to the length of the energy measurement + */ + class ofdm_coarse_frequency_correction_vcvc_impl + : public ofdm_coarse_frequency_correction_vcvc { + private: int d_fft_length; int d_num_carriers; int d_cyclic_prefix_length; float *d_mag_squared; - unsigned int d_freq_offset; - float d_snr; + unsigned int d_freq_offset; /*!< measured position of the first occupied sub-carrier*/ + float d_snr; /*!< measured snr*/ + + public: + ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, + int num_carriers, + int cyclic_prefix_length); - public: - ofdm_coarse_frequency_correction_vcvc_impl(int fft_length, int num_carriers, int cyclic_prefix_length); ~ofdm_coarse_frequency_correction_vcvc_impl(); - void measure_energy(const gr_complex*); - void measure_snr(const gr_complex*); + void measure_energy(const gr_complex *); + + void measure_snr(const gr_complex *); - virtual float get_snr() - { return d_snr;} + virtual float get_snr() { return d_snr; } // Where all the action really happens int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/ofdm_insert_pilot_vcc_impl.cc b/lib/ofdm_insert_pilot_vcc_impl.cc index 1a044d5f..06f5fdcc 100644 --- a/lib/ofdm_insert_pilot_vcc_impl.cc +++ b/lib/ofdm_insert_pilot_vcc_impl.cc @@ -35,65 +35,68 @@ namespace gr { namespace dab { -ofdm_insert_pilot_vcc::sptr -ofdm_insert_pilot_vcc::make(const std::vector &pilot) -{ - return gnuradio::get_initial_sptr - (new ofdm_insert_pilot_vcc_impl(pilot)); -} + ofdm_insert_pilot_vcc::sptr + ofdm_insert_pilot_vcc::make(const std::vector &pilot) { + return gnuradio::get_initial_sptr + (new ofdm_insert_pilot_vcc_impl(pilot)); + } -ofdm_insert_pilot_vcc_impl::ofdm_insert_pilot_vcc_impl(const std::vector &pilot) - : gr::block("ofdm_insert_pilot_vcc", - gr::io_signature::make2 (2, 2, sizeof(gr_complex)*pilot.size(), sizeof(char)), - gr::io_signature::make2 (2, 2, sizeof(gr_complex)*pilot.size(), sizeof(char))), - d_pilot(pilot), d_start(0) -{ -} + ofdm_insert_pilot_vcc_impl::ofdm_insert_pilot_vcc_impl( + const std::vector &pilot) + : gr::block("ofdm_insert_pilot_vcc", + gr::io_signature::make2(2, 2, sizeof(gr_complex) * + pilot.size(), + sizeof(char)), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * + pilot.size(), + sizeof(char))), + d_pilot(pilot), d_start(0) { + } -void -ofdm_insert_pilot_vcc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size (); - for (unsigned int i = 0; i < ninputs; i++) - ninput_items_required[i] = noutput_items; -} + void + ofdm_insert_pilot_vcc_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items; + } -int -ofdm_insert_pilot_vcc_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *iptr = (const gr_complex *) input_items[0]; - const char *frame_start = (const char *) input_items[1]; - - gr_complex *optr = (gr_complex *) output_items[0]; - char *o_frame_start = (char *) output_items[1]; + int + ofdm_insert_pilot_vcc_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + const gr_complex *iptr = (const gr_complex *) input_items[0]; + const char *frame_start = (const char *) input_items[1]; - int n_produced = 0; - int n_consumed = 0; + gr_complex *optr = (gr_complex *) output_items[0]; + char *o_frame_start = (char *) output_items[1]; - for ( ; n_consumed d_pilot; + char d_start; - std::vector d_pilot; - char d_start; + public: + ofdm_insert_pilot_vcc_impl(const std::vector &pilot); - public: - ofdm_insert_pilot_vcc_impl(const std::vector &pilot); - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; -} + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + } } #endif /* INCLUDED_DAB_OFDM_INSERT_PILOT_VCC_H */ diff --git a/lib/ofdm_move_and_insert_zero_impl.cc b/lib/ofdm_move_and_insert_zero_impl.cc index 72c491d2..fc0ed22b 100644 --- a/lib/ofdm_move_and_insert_zero_impl.cc +++ b/lib/ofdm_move_and_insert_zero_impl.cc @@ -35,55 +35,56 @@ namespace gr { namespace dab { -ofdm_move_and_insert_zero::sptr -ofdm_move_and_insert_zero::make(unsigned int fft_length,unsigned int num_carriers) -{ - return gnuradio::get_initial_sptr - (new ofdm_move_and_insert_zero_impl(fft_length, num_carriers)); -} + ofdm_move_and_insert_zero::sptr + ofdm_move_and_insert_zero::make(unsigned int fft_length, + unsigned int num_carriers) { + return gnuradio::get_initial_sptr + (new ofdm_move_and_insert_zero_impl(fft_length, num_carriers)); + } -ofdm_move_and_insert_zero_impl::ofdm_move_and_insert_zero_impl(unsigned int fft_length,unsigned int num_carriers) - : gr::sync_block("ofdm_move_and_insert_zero", - gr::io_signature::make (1, 1, sizeof(gr_complex)*num_carriers), - gr::io_signature::make (1, 1, sizeof(gr_complex)*fft_length)), - d_fft_length(fft_length), d_num_carriers(num_carriers) -{ - d_zeros_on_left = (d_fft_length-d_num_carriers)/2; -} + ofdm_move_and_insert_zero_impl::ofdm_move_and_insert_zero_impl( + unsigned int fft_length, unsigned int num_carriers) + : gr::sync_block("ofdm_move_and_insert_zero", + gr::io_signature::make(1, 1, sizeof(gr_complex) * + num_carriers), + gr::io_signature::make(1, 1, sizeof(gr_complex) * + fft_length)), + d_fft_length(fft_length), d_num_carriers(num_carriers) { + d_zeros_on_left = (d_fft_length - d_num_carriers) / 2; + } -int -ofdm_move_and_insert_zero_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int i; - unsigned int j,k; - /* partially adapted from gr_ofdm_frame_acquisition.cc */ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; + int + ofdm_move_and_insert_zero_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + int i; + unsigned int j, k; + /* partially adapted from gr_ofdm_frame_acquisition.cc */ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; - for (i=0; i 100000 || d_moving_average_counter == 0 || new_calculation) { + ofdm_synchronization_cvf_impl::delayed_correlation(const gr_complex *sample, + bool new_calculation) { + if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || + new_calculation) { if (d_moving_average_counter == 0 && (!new_calculation)) { // first value is calculated completely, next values are calculated with moving average d_moving_average_counter++; @@ -103,70 +109,80 @@ namespace gr { d_moving_average_counter = 0; } // calculate delayed correlation for this sample completely - volk_32fc_x2_conjugate_dot_prod_32fc(d_fixed_lag_corr, sample, &sample[d_symbol_length], d_cyclic_prefix_length); + volk_32fc_x2_conjugate_dot_prod_32fc(d_fixed_lag_corr, sample, + &sample[d_symbol_length], + d_cyclic_prefix_length); d_correlation = 0; for (int i = 0; i < d_cyclic_prefix_length; ++i) { d_correlation += d_fixed_lag_corr[i]; } // calculate energy of cyclic prefix for this sample completely - volk_32fc_magnitude_squared_32f(d_mag_squared, sample, d_cyclic_prefix_length); - volk_32f_accumulator_s32f(&d_energy_prefix, d_mag_squared, d_cyclic_prefix_length); + volk_32fc_magnitude_squared_32f(d_mag_squared, sample, + d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_prefix, d_mag_squared, + d_cyclic_prefix_length); // calculate energy of its repetition for this sample completely - volk_32fc_magnitude_squared_32f(d_mag_squared, &sample[d_symbol_length], d_cyclic_prefix_length); - volk_32f_accumulator_s32f(&d_energy_repetition, d_mag_squared, d_cyclic_prefix_length); + volk_32fc_magnitude_squared_32f(d_mag_squared, &sample[d_symbol_length], + d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_repetition, d_mag_squared, + d_cyclic_prefix_length); } else { // calculate next step for moving average d_correlation += - sample[d_cyclic_prefix_length - 1] * conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); - d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * conj(sample[d_cyclic_prefix_length - 1])); - d_energy_repetition += std::real(sample[d_symbol_length + d_cyclic_prefix_length - 1] * - conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); + sample[d_cyclic_prefix_length - 1] * + conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); + d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * + conj(sample[d_cyclic_prefix_length - 1])); + d_energy_repetition += std::real( + sample[d_symbol_length + d_cyclic_prefix_length - 1] * + conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); d_correlation -= sample[0] * conj(sample[d_symbol_length]); d_energy_prefix -= std::real(sample[0] * conj(sample[0])); - d_energy_repetition -= std::real(sample[d_symbol_length] * conj(sample[d_symbol_length])); + d_energy_repetition -= std::real( + sample[d_symbol_length] * conj(sample[d_symbol_length])); d_moving_average_counter++; } // normalize - d_correlation_normalized = d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); + d_correlation_normalized = + d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); // calculate magnitude - d_correlation_normalized_magnitude = d_correlation_normalized.real() * d_correlation_normalized.real() + - d_correlation_normalized.imag() * d_correlation_normalized.imag(); + d_correlation_normalized_magnitude = d_correlation_normalized.real() * + d_correlation_normalized.real() + + d_correlation_normalized.imag() * + d_correlation_normalized.imag(); } /*! \brief returns true at a point with a little space before the peak of a correlation triangular * */ bool - ofdm_synchronization_cvf_impl::detect_start_of_symbol() - { - if(d_on_triangle){ - if(d_correlation_normalized_magnitude > d_correlation_maximum){ + ofdm_synchronization_cvf_impl::detect_start_of_symbol() { + if (d_on_triangle) { + if (d_correlation_normalized_magnitude > d_correlation_maximum) { d_correlation_maximum = d_correlation_normalized_magnitude; } - if(d_correlation_normalized_magnitude < d_correlation_maximum-0.05 && !d_peak_set){ + if (d_correlation_normalized_magnitude < d_correlation_maximum - 0.05 && + !d_peak_set) { // we are right behind the peak d_peak_set = true; return true; } - if(d_correlation_normalized_magnitude < 0.25){ + if (d_correlation_normalized_magnitude < 0.25) { d_peak_set = false; d_on_triangle = false; d_correlation_maximum = 0; - } - else{ + } else { // we are still on the triangle but have not reached the end return false; } - } - else{ + } else { // not on a correlation triangle yet - if(d_correlation_normalized_magnitude > 0.35){ + if (d_correlation_normalized_magnitude > 0.35) { // no we are on the triangle d_on_triangle = true; return false; - } - else{ + } else { // no triangle here return false; } @@ -177,8 +193,7 @@ namespace gr { ofdm_synchronization_cvf_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; d_nwritten = 0; @@ -191,7 +206,8 @@ namespace gr { if (detect_start_of_symbol()) { if (d_NULL_detected /*&& (d_energy_prefix > d_NULL_symbol_energy * 2)*/) { // calculate new frequency offset - d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/sample + d_frequency_offset_per_sample = + std::arg(d_correlation) / d_fft_length; // in rad/sample //GR_LOG_DEBUG(d_logger, format("Start of frame, abs offset %d")%(nitems_read(0)+i)); /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. @@ -208,14 +224,16 @@ namespace gr { d_NULL_detected = false; } } else { - if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.4))) { + if (((!d_NULL_detected) && + (d_energy_prefix / d_energy_repetition < 0.4))) { // NULL symbol detection, if energy is < 0.1 * energy a symbol time later d_NULL_symbol_energy = d_energy_prefix; d_NULL_detected = true; } } } else { // tracking mode - if (d_symbol_element_count >= (d_symbol_length + d_cyclic_prefix_length)) { + if (d_symbol_element_count >= + (d_symbol_length + d_cyclic_prefix_length)) { // we expect the start of a new symbol here or the a NULL symbol if we arrived at the end of the frame d_symbol_count++; // next symbol expecting @@ -232,16 +250,22 @@ namespace gr { // correlation has to be calculated completely new, because of skipping samples before delayed_correlation(&in[i], true); // check if there is really a peak - if (d_correlation_normalized_magnitude > 0.3) { //TODO: check if we are on right edge - d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/s + if (d_correlation_normalized_magnitude > + 0.3) { //TODO: check if we are on right edge + d_frequency_offset_per_sample = + std::arg(d_correlation) / d_fft_length; // in rad/s } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; - GR_LOG_DEBUG(d_logger, format("Lost track at %d, switching ot acquisition mode (%d)") %d_symbol_count % - d_correlation_normalized_magnitude); + GR_LOG_DEBUG(d_logger, + format("Lost track at %d, switching ot acquisition mode (%d)") % + d_symbol_count % + d_correlation_normalized_magnitude); } } - } else if (d_cyclic_prefix_length*0.75 <= d_symbol_element_count && d_symbol_element_count < d_cyclic_prefix_length*0.75 + d_symbol_length) { + } else if (d_cyclic_prefix_length * 0.75 <= d_symbol_element_count && + d_symbol_element_count < + d_cyclic_prefix_length * 0.75 + d_symbol_length) { // calculate the complex frequency correction value float oi, oq; // fixed point sine and cosine @@ -249,7 +273,8 @@ namespace gr { gr::fxpt::sincos(angle, &oq, &oi); gr_complex fine_frequency_correction = gr_complex(oi, oq); // set tag at next item if it is the first element of the first symbol - if (d_symbol_count == 0 && d_symbol_element_count == d_cyclic_prefix_length) { + if (d_symbol_count == 0 && + d_symbol_element_count == d_cyclic_prefix_length) { add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); } diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index 303be01e..1d9b7313 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -32,8 +32,7 @@ namespace gr { * \param num_ofdm_symbols number of OFDM symbols without the NULL symbol * */ - class ofdm_synchronization_cvf_impl : public ofdm_synchronization_cvf - { + class ofdm_synchronization_cvf_impl : public ofdm_synchronization_cvf { private: int d_symbol_length; int d_cyclic_prefix_length; @@ -62,11 +61,15 @@ namespace gr { int d_nwritten; public: - ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame); + ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, + int fft_length, int symbols_per_frame); + ~ofdm_synchronization_cvf_impl(); void delayed_correlation(const gr_complex *sample, bool new_calculation); + bool detect_peak(); + bool detect_start_of_symbol(); void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/prune_impl.cc b/lib/prune_impl.cc index 5672ee24..b440f069 100644 --- a/lib/prune_impl.cc +++ b/lib/prune_impl.cc @@ -33,8 +33,8 @@ namespace gr { namespace dab { prune::sptr - prune::make(size_t itemsize, unsigned int length, unsigned int prune_start, unsigned int prune_end) - { + prune::make(size_t itemsize, unsigned int length, unsigned int prune_start, + unsigned int prune_end) { return gnuradio::get_initial_sptr (new prune_impl(itemsize, length, prune_start, prune_end)); } @@ -42,14 +42,17 @@ namespace gr { /* * The private constructor */ - prune_impl::prune_impl(size_t itemsize, unsigned int length, unsigned int prune_start, unsigned int prune_end) + prune_impl::prune_impl(size_t itemsize, unsigned int length, + unsigned int prune_start, unsigned int prune_end) : gr::block("prune", gr::io_signature::make(1, 1, sizeof(char)), gr::io_signature::make(1, 1, sizeof(char))), - d_itemsize(itemsize), d_length(length), d_prune_start(prune_start), d_prune_end(prune_end) - { + d_itemsize(itemsize), d_length(length), + d_prune_start(prune_start), d_prune_end(prune_end) { if (prune_start + prune_end > length) - throw std::out_of_range((boost::format("want to cut %d more items than stream is long") % (prune_start + prune_end - length)).str()); + throw std::out_of_range((boost::format( + "want to cut %d more items than stream is long") % + (prune_start + prune_end - length)).str()); set_output_multiple(length - prune_start - prune_end); set_relative_rate((length - prune_start - prune_end) / length); @@ -58,32 +61,35 @@ namespace gr { /* * Our virtual destructor. */ - prune_impl::~prune_impl() - { + prune_impl::~prune_impl() { } void - prune_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = (noutput_items / (d_length - d_prune_start - d_prune_end)) * d_length; + prune_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = + (noutput_items / (d_length - d_prune_start - d_prune_end)) * + d_length; } int prune_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const char *in = (const char *) input_items[0]; char *out = (char *) output_items[0]; - for (int i = 0; i < noutput_items / (d_length - d_prune_start - d_prune_end); i++) { - memcpy(out, in + d_prune_start * d_itemsize, (d_length - d_prune_start - d_prune_end) * d_itemsize); + for (int i = 0; + i < noutput_items / (d_length - d_prune_start - d_prune_end); i++) { + memcpy(out, in + d_prune_start * d_itemsize, + (d_length - d_prune_start - d_prune_end) * d_itemsize); in += d_length * d_itemsize; out += (d_length - d_prune_start - d_prune_end) * d_itemsize; } // Tell runtime system how many input items we consumed on // each input stream. - consume_each((noutput_items / (d_length - d_prune_start - d_prune_end)) * d_length); + consume_each((noutput_items / (d_length - d_prune_start - d_prune_end)) * + d_length); // Tell runtime system how many output items we produced. return noutput_items; diff --git a/lib/prune_impl.h b/lib/prune_impl.h index 61879df0..f95afa4f 100644 --- a/lib/prune_impl.h +++ b/lib/prune_impl.h @@ -41,7 +41,8 @@ namespace gr { unsigned int d_prune_end; public: - prune_impl(size_t itemsize, unsigned int length, unsigned int prune_start, unsigned int prune_end); + prune_impl(size_t itemsize, unsigned int length, unsigned int prune_start, + unsigned int prune_end); ~prune_impl(); diff --git a/lib/puncture_bb_impl.cc b/lib/puncture_bb_impl.cc index a9dca4f6..b30ec926 100644 --- a/lib/puncture_bb_impl.cc +++ b/lib/puncture_bb_impl.cc @@ -29,14 +29,13 @@ namespace gr { namespace dab { puncture_bb::sptr - puncture_bb::make(const std::vector &puncturing_vector) - { + puncture_bb::make(const std::vector &puncturing_vector) { return gnuradio::get_initial_sptr (new puncture_bb_impl(puncturing_vector)); } - unsigned int puncture_bb_impl::ones(const std::vector &puncturing_vector) - { + unsigned int puncture_bb_impl::ones( + const std::vector &puncturing_vector) { unsigned int onescount = 0; for (unsigned int i = 0; i < puncturing_vector.size(); i++) { if (puncturing_vector[i] == 1) @@ -48,12 +47,12 @@ namespace gr { /* * The private constructor */ - puncture_bb_impl::puncture_bb_impl(const std::vector &puncturing_vector) + puncture_bb_impl::puncture_bb_impl( + const std::vector &puncturing_vector) : gr::block("puncture_bb", gr::io_signature::make(1, 1, sizeof(unsigned char)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_puncturing_vector(puncturing_vector) - { + d_puncturing_vector(puncturing_vector) { d_vlen_in = puncturing_vector.size(); d_vlen_out = ones(puncturing_vector); set_output_multiple(d_vlen_out); @@ -63,13 +62,12 @@ namespace gr { /* * Our virtual destructor. */ - puncture_bb_impl::~puncture_bb_impl() - { + puncture_bb_impl::~puncture_bb_impl() { } void - puncture_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { + puncture_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items * d_vlen_in / d_vlen_out; } @@ -77,8 +75,7 @@ namespace gr { puncture_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; diff --git a/lib/qa_dab.cc b/lib/qa_dab.cc index 4b1ce4d0..c633227a 100644 --- a/lib/qa_dab.cc +++ b/lib/qa_dab.cc @@ -28,8 +28,7 @@ #include "qa_dab.h" CppUnit::TestSuite * -qa_dab::suite() -{ +qa_dab::suite() { CppUnit::TestSuite *s = new CppUnit::TestSuite("dab"); return s; diff --git a/lib/qa_dab.h b/lib/qa_dab.h index 14eec333..140ee250 100644 --- a/lib/qa_dab.h +++ b/lib/qa_dab.h @@ -26,13 +26,13 @@ #include #include -//! collect all the tests for the gr-filter directory +//! collect all the tests for the gr-dab directory class __GR_ATTR_EXPORT qa_dab -{ - public: - //! return suite of tests for all of gr-filter directory - static CppUnit::TestSuite *suite(); -}; + { + public: + //! return suite of tests for all of gr-dab directory + static CppUnit::TestSuite *suite(); + }; #endif /* _QA_DAB_H_ */ From 7a74ad5bec9b3a04b722c3d7b7377791943b82c5 Mon Sep 17 00:00:00 2001 From: luca Date: Wed, 17 Jan 2018 21:18:11 +0100 Subject: [PATCH 118/135] using the great technique of a loop to reduce code --- lib/qpsk_mapper_vbvc_impl.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/qpsk_mapper_vbvc_impl.cc b/lib/qpsk_mapper_vbvc_impl.cc index 6afc3480..0df7ad7e 100644 --- a/lib/qpsk_mapper_vbvc_impl.cc +++ b/lib/qpsk_mapper_vbvc_impl.cc @@ -64,14 +64,9 @@ namespace gr { // iterate over each symbol vector for (int j = 0; j < d_symbol_length/8; ++j) { // iterate over the symbol vector, but each byte has 8 bit, which are accessed manually - out[i*d_symbol_length + j*8 + 0] = gr_complex((in[i*(d_symbol_length/4) + j]&128)>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&128)>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 1] = gr_complex((in[i*(d_symbol_length/4) + j]&64 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&64 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 2] = gr_complex((in[i*(d_symbol_length/4) + j]&32 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&32 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 3] = gr_complex((in[i*(d_symbol_length/4) + j]&16 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&16 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 4] = gr_complex((in[i*(d_symbol_length/4) + j]&8 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&8 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 5] = gr_complex((in[i*(d_symbol_length/4) + j]&4 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&4 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 6] = gr_complex((in[i*(d_symbol_length/4) + j]&2 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&2 )>0?-I_SQRT2:I_SQRT2); - out[i*d_symbol_length + j*8 + 7] = gr_complex((in[i*(d_symbol_length/4) + j]&1 )>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&1 )>0?-I_SQRT2:I_SQRT2); + for (int k = 0; k < 8; k++) { + out[i*d_symbol_length + j*8 + k] = gr_complex((in[i*(d_symbol_length/4) + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2); + } } } // Tell runtime system how many output items we produced. From e80bacda2538e109cf4cf1b9837be606eb25f6f2 Mon Sep 17 00:00:00 2001 From: luca Date: Thu, 18 Jan 2018 16:53:02 +0100 Subject: [PATCH 119/135] wrap up, rm redundancy, add docu --- grc/CMakeLists.txt | 1 - grc/dab_unpuncture_ff.xml | 25 ------- include/dab/CMakeLists.txt | 1 - include/dab/unpuncture_ff.h | 55 --------------- lib/CMakeLists.txt | 1 - lib/fib_source_b_impl.h | 2 +- lib/qpsk_mapper_vbvc_impl.cc | 2 +- lib/qpsk_mapper_vbvc_impl.h | 21 +++--- lib/reed_solomon_decode_bb_impl.cc | 25 +++---- lib/reed_solomon_decode_bb_impl.h | 13 ++-- lib/reed_solomon_encode_bb_impl.cc | 43 ++++++------ lib/reed_solomon_encode_bb_impl.h | 20 +++--- lib/select_cus_vfvf_impl.cc | 50 ++++++------- lib/select_cus_vfvf_impl.h | 28 +++++--- lib/sum_phasor_trig_vcc_impl.cc | 109 +++++++++++++++-------------- lib/sum_phasor_trig_vcc_impl.h | 24 +++---- lib/test_dab.cc | 6 +- lib/time_deinterleave_ff_impl.cc | 25 ++++--- lib/time_deinterleave_ff_impl.h | 46 ++++++------ lib/time_interleave_bb_impl.cc | 35 +++++---- lib/time_interleave_bb_impl.h | 38 +++++----- lib/unpuncture_ff_impl.cc | 104 --------------------------- lib/unpuncture_ff_impl.h | 63 ----------------- lib/unpuncture_vff_impl.cc | 90 ++++++++++++------------ lib/unpuncture_vff_impl.h | 38 ++++++---- lib/valve_ff_impl.cc | 46 ++++++------ lib/valve_ff_impl.h | 20 +++--- python/msc_decode.py | 8 ++- swig/dab_swig.i | 4 +- 29 files changed, 362 insertions(+), 581 deletions(-) delete mode 100644 grc/dab_unpuncture_ff.xml delete mode 100644 include/dab/unpuncture_ff.h delete mode 100644 lib/unpuncture_ff_impl.cc delete mode 100644 lib/unpuncture_ff_impl.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 6430e6f4..ab3b498d 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -32,7 +32,6 @@ install(FILES dab_crc16_bb.xml dab_msc_decode.xml dab_fib_source_b.xml - dab_unpuncture_ff.xml dab_prune.xml dab_firecode_check_bb.xml dab_fic_encode.xml diff --git a/grc/dab_unpuncture_ff.xml b/grc/dab_unpuncture_ff.xml deleted file mode 100644 index 78527dc9..00000000 --- a/grc/dab_unpuncture_ff.xml +++ /dev/null @@ -1,25 +0,0 @@ - - Unpuncture - dab_unpuncture_ff - [DAB] - import dab - dab.unpuncture_ff($puncturing_vector, $fillval) - - Puncturing vector - puncturing_vector - raw - - - Fillvalue - fillval - float - - - in - float - - - out - float - - diff --git a/include/dab/CMakeLists.txt b/include/dab/CMakeLists.txt index 939bd7c5..066b4283 100644 --- a/include/dab/CMakeLists.txt +++ b/include/dab/CMakeLists.txt @@ -35,7 +35,6 @@ install(FILES time_deinterleave_ff.h crc16_bb.h fib_source_b.h - unpuncture_ff.h prune.h firecode_check_bb.h puncture_bb.h diff --git a/include/dab/unpuncture_ff.h b/include/dab/unpuncture_ff.h deleted file mode 100644 index ca303577..00000000 --- a/include/dab/unpuncture_ff.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef INCLUDED_DAB_UNPUNCTURE_FF_H -#define INCLUDED_DAB_UNPUNCTURE_FF_H - -#include -#include - -namespace gr { - namespace dab { - - /*! - * unpuncturing of a stream sequence - * - */ - class DAB_API unpuncture_ff : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of dab::unpuncture_ff. - * - * To avoid accidental use of raw pointers, dab::unpuncture_ff's - * constructor is in a private implementation - * class. dab::unpuncture_ff::make is the public interface for - * creating new instances. - */ - static sptr make(const std::vector &puncturing_vector, float fillval=0); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_UNPUNCTURE_FF_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0dbaece0..f56adf13 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -40,7 +40,6 @@ list(APPEND dab_sources crc16_bb_impl.cc fib_source_b_impl.cc select_cus_vfvf_impl.cc - unpuncture_ff_impl.cc prune_impl.cc firecode-checker.cpp firecode_check_bb_impl.cc diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index eaa9b576..6ab5eb6e 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -25,7 +25,7 @@ namespace gr { namespace dab { -/*! \brief source that produces Fast Information Blocks (FIBs) according to the DAB standard +/*! \brief source that produces Fast Information Blocks (FIBs) according to the DAB standard ETSI EN 300 401 * * output: unpacked byte stream with FIBs (each 256 bit) and zeros at last 16 bits for following CRC16 * diff --git a/lib/qpsk_mapper_vbvc_impl.cc b/lib/qpsk_mapper_vbvc_impl.cc index 0df7ad7e..7620b263 100644 --- a/lib/qpsk_mapper_vbvc_impl.cc +++ b/lib/qpsk_mapper_vbvc_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/lib/qpsk_mapper_vbvc_impl.h b/lib/qpsk_mapper_vbvc_impl.h index 091f4b27..bc0b804a 100644 --- a/lib/qpsk_mapper_vbvc_impl.h +++ b/lib/qpsk_mapper_vbvc_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,20 +27,25 @@ namespace gr { namespace dab { - - class qpsk_mapper_vbvc_impl : public qpsk_mapper_vbvc - { - private: +/*! \brief vector wise working qpsk mapper + * QPSK mapper according to the DAB/DAB+ standard ETSI EN 300 401 + * + * @ingroup packed byte vectors of length symbol_length/4 + * @param symbol_length size of the complex output vectors + */ + class qpsk_mapper_vbvc_impl : public qpsk_mapper_vbvc { + private: unsigned int d_symbol_length; - public: + public: qpsk_mapper_vbvc_impl(unsigned int symbol_length); + ~qpsk_mapper_vbvc_impl(); // Where all the action really happens int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/reed_solomon_decode_bb_impl.cc b/lib/reed_solomon_decode_bb_impl.cc index e1702caa..8a1dea25 100644 --- a/lib/reed_solomon_decode_bb_impl.cc +++ b/lib/reed_solomon_decode_bb_impl.cc @@ -41,8 +41,7 @@ namespace gr { namespace dab { reed_solomon_decode_bb::sptr - reed_solomon_decode_bb::make(int bit_rate_n) - { + reed_solomon_decode_bb::make(int bit_rate_n) { return gnuradio::get_initial_sptr (new reed_solomon_decode_bb_impl(bit_rate_n)); } @@ -54,8 +53,7 @@ namespace gr { : gr::block("reed_solomon_decode_bb", gr::io_signature::make(1, 1, sizeof(unsigned char)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_bit_rate_n(bit_rate_n) - { + d_bit_rate_n(bit_rate_n) { rs_handle = init_rs_char(8, 0x11D, 0, 1, 10, 135); if (!rs_handle) { GR_LOG_DEBUG(d_logger, "RS init failed"); @@ -71,13 +69,12 @@ namespace gr { /* * Our virtual destructor. */ - reed_solomon_decode_bb_impl::~reed_solomon_decode_bb_impl() - { + reed_solomon_decode_bb_impl::~reed_solomon_decode_bb_impl() { free_rs_char(rs_handle); } - void reed_solomon_decode_bb_impl::DecodeSuperframe(uint8_t *sf, size_t sf_len) - { + void + reed_solomon_decode_bb_impl::DecodeSuperframe(uint8_t *sf, size_t sf_len) { // // insert errors for test // sf[0] ^= 0xFF; // sf[10] ^= 0xFF; @@ -114,17 +111,16 @@ namespace gr { void - reed_solomon_decode_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items*120/110; + reed_solomon_decode_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = noutput_items * 120 / 110; } int reed_solomon_decode_bb_impl::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; @@ -132,7 +128,8 @@ namespace gr { uint8_t superframe[d_superframe_size]; memcpy(superframe, &in[n * d_superframe_size], d_superframe_size); DecodeSuperframe(superframe, d_superframe_size); - memcpy(&out[n * d_superframe_size_rs], superframe, d_superframe_size_rs); + memcpy(&out[n * d_superframe_size_rs], superframe, + d_superframe_size_rs); } // Tell runtime system how many input items we consumed on // each input stream. diff --git a/lib/reed_solomon_decode_bb_impl.h b/lib/reed_solomon_decode_bb_impl.h index 0dcf011c..6a05e13d 100644 --- a/lib/reed_solomon_decode_bb_impl.h +++ b/lib/reed_solomon_decode_bb_impl.h @@ -45,12 +45,12 @@ namespace gr { class reed_solomon_decode_bb_impl : public reed_solomon_decode_bb { private: int d_bit_rate_n; - int d_superframe_size; - int d_superframe_size_rs; + int d_superframe_size; /*!< size of a superframe in byte with rs code words*/ + int d_superframe_size_rs; /*!< size of a superframe in byte without rs code words*/ void *rs_handle; - uint8_t rs_packet[120]; - int corr_pos[10]; - int d_corrected_errors; + uint8_t rs_packet[120]; /*!< buffer for rs algorithm*/ + int corr_pos[10]; /*!< positions of detected and correctable errors*/ + int d_corrected_errors; /*!< number of corrected errors in the current superframe*/ void DecodeSuperframe(uint8_t *sf, size_t sf_len); @@ -59,8 +59,7 @@ namespace gr { ~reed_solomon_decode_bb_impl(); - virtual int get_corrected_errors() - { return d_corrected_errors; } + virtual int get_corrected_errors() { return d_corrected_errors; } // Where all the action really happens void forecast(int noutput_items, gr_vector_int &ninput_items_required); diff --git a/lib/reed_solomon_encode_bb_impl.cc b/lib/reed_solomon_encode_bb_impl.cc index 7ed96050..ff9f2f60 100644 --- a/lib/reed_solomon_encode_bb_impl.cc +++ b/lib/reed_solomon_encode_bb_impl.cc @@ -41,21 +41,19 @@ namespace gr { namespace dab { reed_solomon_encode_bb::sptr - reed_solomon_encode_bb::make(int bit_rate_n) - { + reed_solomon_encode_bb::make(int bit_rate_n) { return gnuradio::get_initial_sptr - (new reed_solomon_encode_bb_impl(bit_rate_n)); + (new reed_solomon_encode_bb_impl(bit_rate_n)); } /* * The private constructor */ reed_solomon_encode_bb_impl::reed_solomon_encode_bb_impl(int bit_rate_n) - : gr::block("reed_solomon_encode_bb", - gr::io_signature::make(1, 1, sizeof(unsigned char)), - gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_bit_rate_n(bit_rate_n) - { + : gr::block("reed_solomon_encode_bb", + gr::io_signature::make(1, 1, sizeof(unsigned char)), + gr::io_signature::make(1, 1, sizeof(unsigned char))), + d_bit_rate_n(bit_rate_n) { //initialize Reed Solomon rs_handle = init_rs_char(8, 0x11D, 0, 1, 10, 135); if (!rs_handle) { @@ -71,50 +69,49 @@ namespace gr { /* * Our virtual destructor. */ - reed_solomon_encode_bb_impl::~reed_solomon_encode_bb_impl() - { + reed_solomon_encode_bb_impl::~reed_solomon_encode_bb_impl() { free_rs_char(rs_handle); } void - reed_solomon_encode_bb_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items*110/120; + reed_solomon_encode_bb_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { + ninput_items_required[0] = noutput_items * 110 / 120; } int - reed_solomon_encode_bb_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + reed_solomon_encode_bb_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; unsigned char rs_in[110]; unsigned char rs_parity[10]; - for(int n=0; n < noutput_items/d_superframe_size_rs; n++){ + for (int n = 0; n < noutput_items / d_superframe_size_rs; n++) { // virtual interleaving: a d_bit_rate_n x 110 block is now read row wise instead of column wise for (int row = 0; row < d_bit_rate_n; row++) { // write scrambled in_vector for RS for (int i = 0; i < 110; ++i) { - rs_in[i] = in[n * d_superframe_size_in + d_bit_rate_n*i + row]; + rs_in[i] = in[n * d_superframe_size_in + d_bit_rate_n * i + row]; } // calculate parity bytes encode_rs_char(rs_handle, rs_in, rs_parity); // write to output buffer for (int i = 0; i < 110; ++i) { - out[n*d_superframe_size_rs + d_bit_rate_n*i + row] = rs_in[i]; + out[n * d_superframe_size_rs + d_bit_rate_n * i + row] = rs_in[i]; } for (int i = 110; i < 120; ++i) { - out[n*d_superframe_size_rs + d_bit_rate_n*i + row] = rs_parity[i-110]; + out[n * d_superframe_size_rs + d_bit_rate_n * i + row] = rs_parity[ + i - 110]; } } } // Tell runtime system how many input items we consumed on // each input stream. - consume_each (noutput_items*110/120); + consume_each(noutput_items * 110 / 120); // Tell runtime system how many output items we produced. return noutput_items; diff --git a/lib/reed_solomon_encode_bb_impl.h b/lib/reed_solomon_encode_bb_impl.h index 5afb8eb4..b5c4f342 100644 --- a/lib/reed_solomon_encode_bb_impl.h +++ b/lib/reed_solomon_encode_bb_impl.h @@ -40,25 +40,25 @@ namespace gr { * @param bit_rate_n data rate in multiples of 8kbit/s */ - class reed_solomon_encode_bb_impl : public reed_solomon_encode_bb - { - private: + class reed_solomon_encode_bb_impl : public reed_solomon_encode_bb { + private: int d_bit_rate_n; - int d_superframe_size_rs; - int d_superframe_size_in; + int d_superframe_size_rs; /*!< size of a superframe in byte with appended rs code words*/ + int d_superframe_size_in; /*!< size of a superframe in byte without rs code words*/ void *rs_handle; - public: + public: reed_solomon_encode_bb_impl(int bit_rate_n); + ~reed_solomon_encode_bb_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/select_cus_vfvf_impl.cc b/lib/select_cus_vfvf_impl.cc index 3a73f899..321f264d 100644 --- a/lib/select_cus_vfvf_impl.cc +++ b/lib/select_cus_vfvf_impl.cc @@ -29,57 +29,59 @@ namespace gr { namespace dab { select_cus_vfvf::sptr - select_cus_vfvf::make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) - { + select_cus_vfvf::make(unsigned int vlen, unsigned int frame_len, + unsigned int address, unsigned int size) { return gnuradio::get_initial_sptr - (new select_cus_vfvf_impl(vlen, frame_len, address, size)); + (new select_cus_vfvf_impl(vlen, frame_len, address, size)); } /* * The private constructor */ - select_cus_vfvf_impl::select_cus_vfvf_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) - : gr::block("select_cus_vfvf", - gr::io_signature::make(1, 1, vlen * sizeof(float)), - gr::io_signature::make(1, 1, vlen * sizeof(float))), - d_vlen(vlen), - d_frame_len(frame_len), - d_address(address), - d_size(size) - {} + select_cus_vfvf_impl::select_cus_vfvf_impl(unsigned int vlen, + unsigned int frame_len, + unsigned int address, + unsigned int size) + : gr::block("select_cus_vfvf", + gr::io_signature::make(1, 1, vlen * sizeof(float)), + gr::io_signature::make(1, 1, vlen * sizeof(float))), + d_vlen(vlen), + d_frame_len(frame_len), + d_address(address), + d_size(size) {} /* * Our virtual destructor. */ - select_cus_vfvf_impl::~select_cus_vfvf_impl() - { + select_cus_vfvf_impl::~select_cus_vfvf_impl() { } void - select_cus_vfvf_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) - { + select_cus_vfvf_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } int - select_cus_vfvf_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + select_cus_vfvf_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float *) input_items[0]; float *out = (float *) output_items[0]; unsigned int nwritten = 0; for (int i = 0; i < noutput_items; ++i) { - if(d_address <= (nitems_read(0)+i)%d_frame_len && (nitems_read(0)+i)%d_frame_len < d_address + d_size){ + if (d_address <= (nitems_read(0) + i) % d_frame_len && + (nitems_read(0) + i) % d_frame_len < d_address + d_size) { //this cu is one of the selected subchannel -> copy it to ouput buffer - memcpy(&out[nwritten++*d_vlen], &in[i*d_vlen], d_vlen * sizeof(float)); + memcpy(&out[nwritten++ * d_vlen], &in[i * d_vlen], + d_vlen * sizeof(float)); } } // Tell runtime system how many input items we consumed on // each input stream. - consume_each (noutput_items); + consume_each(noutput_items); // Tell runtime system how many output items we produced. return nwritten; diff --git a/lib/select_cus_vfvf_impl.h b/lib/select_cus_vfvf_impl.h index 982ce570..24106269 100644 --- a/lib/select_cus_vfvf_impl.h +++ b/lib/select_cus_vfvf_impl.h @@ -25,26 +25,34 @@ namespace gr { namespace dab { - - class select_cus_vfvf_impl : public select_cus_vfvf - { - private: +/*! \brief selects items out of a stream, defined by start address and size + * This block is used to select the data of one MSC sub-channel out of a transmission frame. + * + * @param vlen vector size of input and output vectors, defining the item size on witch the address and size variables base on + * @param frame_length length in items of a frame (each item is a vector with size vlen) + * @param address number of the first item in each frame to be copied + * @param size number of items to copy in each frame + */ + class select_cus_vfvf_impl : public select_cus_vfvf { + private: unsigned int d_vlen; unsigned int d_frame_len; unsigned int d_address; unsigned int d_size; - public: - select_cus_vfvf_impl(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size); + public: + select_cus_vfvf_impl(unsigned int vlen, unsigned int frame_len, + unsigned int address, unsigned int size); + ~select_cus_vfvf_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/lib/sum_phasor_trig_vcc_impl.cc b/lib/sum_phasor_trig_vcc_impl.cc index bff21dba..c96b0aa8 100644 --- a/lib/sum_phasor_trig_vcc_impl.cc +++ b/lib/sum_phasor_trig_vcc_impl.cc @@ -37,67 +37,68 @@ namespace gr { namespace dab { -sum_phasor_trig_vcc::sptr -sum_phasor_trig_vcc::make(unsigned int length) -{ - return gnuradio::get_initial_sptr - (new sum_phasor_trig_vcc_impl(length)); -} + sum_phasor_trig_vcc::sptr + sum_phasor_trig_vcc::make(unsigned int length) { + return gnuradio::get_initial_sptr + (new sum_phasor_trig_vcc_impl(length)); + } -sum_phasor_trig_vcc_impl::sum_phasor_trig_vcc_impl(unsigned int length) - : gr::sync_block("sum_phasor_trig_vcc", - gr::io_signature::make2 (2, 2, sizeof(gr_complex)*length, sizeof(char)), - gr::io_signature::make2 (2, 2, sizeof(gr_complex)*length, sizeof(char))), - d_length(length), d_last_symbol(length,0) -{ -} + sum_phasor_trig_vcc_impl::sum_phasor_trig_vcc_impl(unsigned int length) + : gr::sync_block("sum_phasor_trig_vcc", + gr::io_signature::make2(2, 2, sizeof(gr_complex) * + length, + sizeof(char)), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * + length, + sizeof(char))), + d_length(length), d_last_symbol(length, 0) { + } -int -sum_phasor_trig_vcc_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - gr_complex *lastout; - const char *frame_start = (const char *) input_items[1]; - char *o_frame_start = (char *) output_items[1]; - - for(int i = 0; i < noutput_items; i++){ - if (*frame_start==1) { - for (unsigned int j=0; j d_last_symbol; + unsigned int d_length; + std::vector d_last_symbol; - public: - sum_phasor_trig_vcc_impl(unsigned int length); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; + public: + sum_phasor_trig_vcc_impl(unsigned int length); -} + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } } #endif /* INCLUDED_DAB_SUM_PHASOR_TRIG_VCC_H */ diff --git a/lib/test_dab.cc b/lib/test_dab.cc index 1b8f46e3..4ba1f341 100644 --- a/lib/test_dab.cc +++ b/lib/test_dab.cc @@ -33,11 +33,11 @@ #include int -main (int argc, char **argv) -{ +main(int argc, char **argv) { CppUnit::TextTestRunner runner; std::ofstream xmlfile(get_unittest_path("dab.xml").c_str()); - CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), + xmlfile); runner.addTest(qa_dab::suite()); runner.setOutputter(xmlout); diff --git a/lib/time_deinterleave_ff_impl.cc b/lib/time_deinterleave_ff_impl.cc index 72279225..a76a441e 100644 --- a/lib/time_deinterleave_ff_impl.cc +++ b/lib/time_deinterleave_ff_impl.cc @@ -28,8 +28,8 @@ namespace gr { namespace dab { time_deinterleave_ff::sptr - time_deinterleave_ff::make(int vector_length, const std::vector &scrambling_vector) - { + time_deinterleave_ff::make(int vector_length, + const std::vector &scrambling_vector) { return gnuradio::get_initial_sptr (new time_deinterleave_ff_impl(vector_length, scrambling_vector)); } @@ -42,32 +42,35 @@ namespace gr { : gr::sync_block("time_deinterleave_ff", gr::io_signature::make(1, 1, sizeof(float)), gr::io_signature::make(1, 1, sizeof(float))), - d_vector_length(vector_length), d_scrambling_vector(scrambling_vector) - { + d_vector_length(vector_length), + d_scrambling_vector(scrambling_vector) { d_scrambling_length = scrambling_vector.size(); // size of the scrambling vector set_output_multiple(d_vector_length); - set_history((d_scrambling_length-1)*d_vector_length + 1); //need for max delay of (scrambling_length-1) * 24ms + set_history((d_scrambling_length - 1) * d_vector_length + + 1); //need for max delay of (scrambling_length-1) * 24ms } /* * Our virtual destructor. */ - time_deinterleave_ff_impl::~time_deinterleave_ff_impl() - { + time_deinterleave_ff_impl::~time_deinterleave_ff_impl() { } int time_deinterleave_ff_impl::work(int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const float *in = (const float *) input_items[0]; float *out = (float *) output_items[0]; - for (int i = 0; i < noutput_items/d_vector_length; i++) { + for (int i = 0; i < noutput_items / d_vector_length; i++) { // produce output vectors for (int j = 0; j < d_vector_length; j++) { - *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - ((d_scrambling_length - 1) - d_scrambling_vector[j % d_scrambling_length])) + j]; + *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - + ((d_scrambling_length - 1) - + d_scrambling_vector[j % + d_scrambling_length])) + + j]; //*out++ = in[i*d_vector_length + d_scrambling_vector[j%d_scrambling_length]*d_vector_length + j - (j%d_scrambling_length) + d_scrambling_vector[j%d_scrambling_length]]; } } diff --git a/lib/time_deinterleave_ff_impl.h b/lib/time_deinterleave_ff_impl.h index 0f0171a3..35bd0f79 100644 --- a/lib/time_deinterleave_ff_impl.h +++ b/lib/time_deinterleave_ff_impl.h @@ -24,35 +24,37 @@ #include namespace gr { - namespace dab { + namespace dab { /*! \brief applies time deinterleaving to a vector (convolutional deinterleaving -> descrambling and delay) * - * applies convolutional deinterleaving to a vector with its max[vector_length] followers, the scrambling_vector describes which vector element comes from which follower - * delays the elements of a max delay of d_scrambling_length-1 - * more information to the interleaving rules on ETSI EN 300 401 chapter 12 - * this deinterleaver restores a bitstream interleaved by the block time_interleave_bb + * Applies convolutional deinterleaving to a vector with its max[vector_length] followers, + * the scrambling_vector describes which vector element comes from which follower. + * Delays the elements of a max delay of d_scrambling_length-1. + * More information to the interleaving rules on ETSI EN 300 401 chapter 12. + * This deinterleaver restores a bitstream interleaved by the block time_interleave_bb. * * @param vector_length length of input vectors * @param scrambling_vector vector with scrambling parameters (see DAB standard p.138) * */ - class time_deinterleave_ff_impl : public time_deinterleave_ff - { - private: - int d_scrambling_length, d_vector_length; - std::vector d_scrambling_vector; - - public: - time_deinterleave_ff_impl(int vector_length, const std::vector &scrambling_vector); - ~time_deinterleave_ff_impl(); - - // Where all the action really happens - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab + class time_deinterleave_ff_impl : public time_deinterleave_ff { + private: + int d_scrambling_length, d_vector_length; + std::vector d_scrambling_vector; + + public: + time_deinterleave_ff_impl(int vector_length, + const std::vector &scrambling_vector); + + ~time_deinterleave_ff_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab } // namespace gr #endif /* INCLUDED_DAB_TIME_DEINTERLEAVE_FF_IMPL_H */ diff --git a/lib/time_interleave_bb_impl.cc b/lib/time_interleave_bb_impl.cc index 8cbc33c7..66410016 100644 --- a/lib/time_interleave_bb_impl.cc +++ b/lib/time_interleave_bb_impl.cc @@ -29,8 +29,8 @@ namespace gr { namespace dab { time_interleave_bb::sptr - time_interleave_bb::make(int vector_length, const std::vector &scrambling_vector) - { + time_interleave_bb::make(int vector_length, + const std::vector &scrambling_vector) { return gnuradio::get_initial_sptr (new time_interleave_bb_impl(vector_length, scrambling_vector)); } @@ -41,34 +41,41 @@ namespace gr { time_interleave_bb_impl::time_interleave_bb_impl(int vector_length, const std::vector &scrambling_vector) : gr::sync_block("time_interleave_bb", - gr::io_signature::make(1, 1, sizeof(unsigned char) * vector_length), - gr::io_signature::make(1, 1, sizeof(unsigned char) * vector_length)), - d_vector_length(vector_length), d_scrambling_vector(scrambling_vector) - { + gr::io_signature::make(1, 1, + sizeof(unsigned char) * + vector_length), + gr::io_signature::make(1, 1, + sizeof(unsigned char) * + vector_length)), + d_vector_length(vector_length), + d_scrambling_vector(scrambling_vector) { d_scrambling_length = scrambling_vector.size(); //size of the scrambling vector - set_history(d_scrambling_length); //need for max delay of (scrambling_length-1) * 24ms + set_history( + d_scrambling_length); //need for max delay of (scrambling_length-1) * 24ms } /* * Our virtual destructor. */ - time_interleave_bb_impl::~time_interleave_bb_impl() - { + time_interleave_bb_impl::~time_interleave_bb_impl() { } int time_interleave_bb_impl::work(int noutput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + gr_vector_void_star &output_items) { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; // produce output vectors - for (int i = 0; i < noutput_items; i++) { //iteration over produced output vectors - for (int j = 0; j < d_vector_length; j++) { //iteration over elements of vector + for (int i = 0; + i < noutput_items; i++) { //iteration over produced output vectors + for (int j = 0; + j < d_vector_length; j++) { //iteration over elements of vector //*out++ = in[vec_length * (i + (scrambling_length-1) - d_scrambling_vector[j % scrambling_length]) + j]; - *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - d_scrambling_vector[j % d_scrambling_length]) + + *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - + d_scrambling_vector[j % + d_scrambling_length]) + j]; } } diff --git a/lib/time_interleave_bb_impl.h b/lib/time_interleave_bb_impl.h index 330abdb0..ccf8f12b 100644 --- a/lib/time_interleave_bb_impl.h +++ b/lib/time_interleave_bb_impl.h @@ -24,35 +24,37 @@ #include namespace gr { - namespace dab { + namespace dab { /*! \brief applies time interleaving to a vector (convolutional interleaving -> scrambling and delay) * - * applies convolutional interleaving to a vector with its max[vector_length] followers, the scrambling_vector describes which vector element comes from which follower - * delays the elements of a max delay of d_scrambling_length-1 - * more information to the interleaving rules on ETSI EN 300 401 chapter 12 + * Applies convolutional interleaving to a vector with its max[vector_length] followers, + * the scrambling_vector describes which vector element comes from which follower. + * Delays the elements of a max delay of d_scrambling_length-1. + * More information to the interleaving rules on ETSI EN 300 401 chapter 12. * * @param vector_length length of input vectors * @param scrambling_vector vector with scrambling parameters (see DAB standard p.138) * */ - class time_interleave_bb_impl : public time_interleave_bb - { - private: - int d_scrambling_length, d_vector_length; - std::vector d_scrambling_vector; + class time_interleave_bb_impl : public time_interleave_bb { + private: + int d_scrambling_length, d_vector_length; + std::vector d_scrambling_vector; - public: - time_interleave_bb_impl(int vector_length, const std::vector &scrambling_vector); - ~time_interleave_bb_impl(); + public: + time_interleave_bb_impl(int vector_length, + const std::vector &scrambling_vector); - // Where all the action really happens - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; + ~time_interleave_bb_impl(); - } // namespace dab + // Where all the action really happens + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } // namespace dab } // namespace gr #endif /* INCLUDED_DAB_TIME_interleave_BB_IMPL_H */ diff --git a/lib/unpuncture_ff_impl.cc b/lib/unpuncture_ff_impl.cc deleted file mode 100644 index 8bcde8f2..00000000 --- a/lib/unpuncture_ff_impl.cc +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "unpuncture_ff_impl.h" - -namespace gr { - namespace dab { - - unpuncture_ff::sptr - unpuncture_ff::make(const std::vector &puncturing_vector, float fillval) - { - return gnuradio::get_initial_sptr - (new unpuncture_ff_impl(puncturing_vector, fillval)); - } - - unsigned int unpuncture_ff_impl::ones(const std::vector &puncturing_vector) - { - unsigned int onescount = 0; - for (unsigned int i = 0; i < puncturing_vector.size(); i++) { - if (puncturing_vector[i] == 1) - onescount++; - } - return onescount; - } - - /* - * The private constructor - */ - unpuncture_ff_impl::unpuncture_ff_impl(const std::vector &puncturing_vector, float fillval) - : gr::block("unpuncture_ff", - gr::io_signature::make(1, 1, sizeof(float)), - gr::io_signature::make(1, 1, sizeof(float))), - d_puncturing_vector(puncturing_vector), d_fillval(fillval) - { - d_vlen_in = ones(puncturing_vector); - d_vlen_out = puncturing_vector.size(); - set_output_multiple(d_vlen_out); - set_relative_rate(d_vlen_out / d_vlen_in); - } - - /* - * Our virtual destructor. - */ - unpuncture_ff_impl::~unpuncture_ff_impl() - { - } - - void - unpuncture_ff_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) - { - ninput_items_required[0] = noutput_items * d_vlen_in / d_vlen_out; - } - - int - unpuncture_ff_impl::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - int i; - unsigned int j; - - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; - - for (i = 0; i < noutput_items; i++) { - if (d_puncturing_vector[i % d_vlen_out] == 1) - *out++ = *in++; - else - *out++ = d_fillval; - } - // Tell runtime system how many input items we consumed on - // each input stream. - consume_each(noutput_items * d_vlen_in / d_vlen_out); - - // Tell runtime system how many output items we produced. - return noutput_items; - } - - } /* namespace dab */ -} /* namespace gr */ - diff --git a/lib/unpuncture_ff_impl.h b/lib/unpuncture_ff_impl.h deleted file mode 100644 index d8bb4bf2..00000000 --- a/lib/unpuncture_ff_impl.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * - * This 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, or (at your option) - * any later version. - * - * This software 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 software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_DAB_UNPUNCTURE_FF_IMPL_H -#define INCLUDED_DAB_UNPUNCTURE_FF_IMPL_H - -#include - -namespace gr { - namespace dab { -/*! \brief unpuncturing of a stream sequence - * - * unpuncturing of a stream sequence according to the puncturing_vector (writing a stream element at a '1' and writing the fillval at a '0') - * - * @param puncturing_vector vector with puncturing sequence, length of puncturing_vector is length of a stream sequence - * @param fillval value to fill in for a zero of the puncturing vector - * - */ - class unpuncture_ff_impl : public unpuncture_ff { - private: - unsigned int ones(const std::vector &puncturing_vector); - - std::vector d_puncturing_vector; - float d_fillval; - unsigned int d_vlen_in; - unsigned int d_vlen_out; - - public: - unpuncture_ff_impl(const std::vector &puncturing_vector, float fillval); - - ~unpuncture_ff_impl(); - - // Where all the action really happens - void forecast(int noutput_items, gr_vector_int &ninput_items_required); - - int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - }; - - } // namespace dab -} // namespace gr - -#endif /* INCLUDED_DAB_UNPUNCTURE_FF_IMPL_H */ - diff --git a/lib/unpuncture_vff_impl.cc b/lib/unpuncture_vff_impl.cc index 2ba57947..131e4755 100644 --- a/lib/unpuncture_vff_impl.cc +++ b/lib/unpuncture_vff_impl.cc @@ -35,54 +35,56 @@ namespace gr { namespace dab { -unpuncture_vff::sptr -unpuncture_vff::make(const std::vector &puncturing_vector, float fillval) -{ - return gnuradio::get_initial_sptr - (new unpuncture_vff_impl(puncturing_vector, fillval)); -} + unpuncture_vff::sptr + unpuncture_vff::make(const std::vector &puncturing_vector, + float fillval) { + return gnuradio::get_initial_sptr + (new unpuncture_vff_impl(puncturing_vector, fillval)); + } -unsigned int unpuncture_vff_impl::ones (const std::vector &puncturing_vector) { - unsigned int onescount = 0; - for (unsigned int i=0; i &puncturing_vector) { + unsigned int onescount = 0; + for (unsigned int i = 0; i < puncturing_vector.size(); i++) { + if (puncturing_vector[i] == 1) + onescount++; + } + return onescount; + } -unpuncture_vff_impl::unpuncture_vff_impl(const std::vector &puncturing_vector, float fillval) - : gr::sync_block("unpuncture_vff", - gr::io_signature::make (1, 1, sizeof(float)*ones(puncturing_vector)), - gr::io_signature::make (1, 1, sizeof(float)*puncturing_vector.size())), - d_puncturing_vector(puncturing_vector), d_fillval(fillval) -{ - d_vlen_in = ones(puncturing_vector); - d_vlen_out = puncturing_vector.size(); -} + unpuncture_vff_impl::unpuncture_vff_impl( + const std::vector &puncturing_vector, float fillval) + : gr::sync_block("unpuncture_vff", + gr::io_signature::make(1, 1, sizeof(float) * + ones(puncturing_vector)), + gr::io_signature::make(1, 1, sizeof(float) * + puncturing_vector.size())), + d_puncturing_vector(puncturing_vector), d_fillval(fillval) { + d_vlen_in = ones(puncturing_vector); + d_vlen_out = puncturing_vector.size(); + } -int -unpuncture_vff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int i; - unsigned int j; - - const float *in = (const float *) input_items[0]; - float *out = (float *) output_items[0]; + int + unpuncture_vff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + int i; + unsigned int j; - for (i=0; i &puncturing_vector); -class unpuncture_vff_impl : public unpuncture_vff -{ - private: - unsigned int ones (const std::vector &puncturing_vector); + std::vector d_puncturing_vector; + float d_fillval; + unsigned int d_vlen_in; + unsigned int d_vlen_out; - std::vector d_puncturing_vector; - float d_fillval; - unsigned int d_vlen_in; - unsigned int d_vlen_out; + public: + unpuncture_vff_impl(const std::vector &puncturing_vector, + float fillval); - public: - unpuncture_vff_impl(const std::vector &puncturing_vector, float fillval); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; -} + } } #endif /* INCLUDED_DAB_UNPUNCTURE_VFF_H */ diff --git a/lib/valve_ff_impl.cc b/lib/valve_ff_impl.cc index 8e43c40b..2db6cbe7 100644 --- a/lib/valve_ff_impl.cc +++ b/lib/valve_ff_impl.cc @@ -29,61 +29,55 @@ namespace gr { namespace dab { valve_ff::sptr - valve_ff::make(bool closed, bool feed_with_zeros) - { + valve_ff::make(bool closed, bool feed_with_zeros) { return gnuradio::get_initial_sptr - (new valve_ff_impl(closed, feed_with_zeros)); + (new valve_ff_impl(closed, feed_with_zeros)); } /* * The private constructor */ valve_ff_impl::valve_ff_impl(bool closed, bool feed_with_zeros) - : gr::block("valve_ff", - gr::io_signature::make(1, 1, sizeof(float)), - gr::io_signature::make(1, 1, sizeof(float))), - d_feed_with_zeros(feed_with_zeros), d_closed(closed) - {} + : gr::block("valve_ff", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(1, 1, sizeof(float))), + d_feed_with_zeros(feed_with_zeros), d_closed(closed) {} /* * Our virtual destructor. */ - valve_ff_impl::~valve_ff_impl() - { + valve_ff_impl::~valve_ff_impl() { } void - valve_ff_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) - { + valve_ff_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } int - valve_ff_impl::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { + valve_ff_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float *) input_items[0]; float *out = (float *) output_items[0]; - if (d_closed){ - if (d_feed_with_zeros){ + if (d_closed) { + if (d_feed_with_zeros) { // send zeros instead of the incoming floats as idle state memset(out, 0, noutput_items * sizeof(float)); - consume_each (noutput_items); + consume_each(noutput_items); return noutput_items; - } - else{ + } else { // dump incoming frames and send nothing - consume_each (noutput_items); + consume_each(noutput_items); return 0; } - } - else{ + } else { // valve opened, simply pass through the floats memcpy(out, in, noutput_items * sizeof(float)); - consume_each (noutput_items); + consume_each(noutput_items); return noutput_items; } } diff --git a/lib/valve_ff_impl.h b/lib/valve_ff_impl.h index 8294cbe8..ff987bfa 100644 --- a/lib/valve_ff_impl.h +++ b/lib/valve_ff_impl.h @@ -29,26 +29,28 @@ namespace gr { * @param feed_with_zeros if valve is closed feed_with_zeros decides if zeros are sent or nothing * @param closed decides if valve is closed or opened */ - class valve_ff_impl : public valve_ff - { - private: + class valve_ff_impl : public valve_ff { + private: bool d_feed_with_zeros; bool d_closed; - public: + public: valve_ff_impl(bool closed, bool feed_with_zeros); + ~valve_ff_impl(); // Where all the action really happens - void forecast (int noutput_items, gr_vector_int &ninput_items_required); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); void set_closed(bool closed) { d_closed = closed; } - void set_feed_with_zeros(bool feed_with_zeros) { d_feed_with_zeros = feed_with_zeros; } + + void set_feed_with_zeros( + bool feed_with_zeros) { d_feed_with_zeros = feed_with_zeros; } int general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); }; } // namespace dab diff --git a/python/msc_decode.py b/python/msc_decode.py index da17137d..9f305f5e 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -88,9 +88,11 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F # time deinterleaving self.time_v2s = blocks.vector_to_stream_make(gr.sizeof_float, self.dp.msc_cu_size) self.time_deinterleaver = dab.time_deinterleave_ff_make(self.dp.msc_cu_size * self.size, self.dp.scrambling_vector) + # unpuncture - self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.msc_punctured_codeword_length) - self.unpuncture = dab.unpuncture_ff_make(self.assembled_msc_puncturing_sequence, 0) + self.unpuncture_s2v = blocks.stream_to_vector(gr.sizeof_float, self.msc_punctured_codeword_length) + self.unpuncture = dab.unpuncture_vff_make(self.assembled_msc_puncturing_sequence, 0) + self.unpuncture_v2s = blocks.vector_to_stream(gr.sizeof_float, self.msc_conv_codeword_length) # convolutional decoding self.fsm = trellis.fsm(1, 4, [0133, 0171, 0145, 0133]) # OK (dumped to text and verified partially) @@ -136,7 +138,9 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F self.select_subch, self.time_v2s, self.time_deinterleaver, + self.unpuncture_s2v, self.unpuncture, + self.unpuncture_v2s, self.conv_decode, self.conv_prune, self.add_mod_2, diff --git a/swig/dab_swig.i b/swig/dab_swig.i index 6428a5c7..0b97fb9e 100644 --- a/swig/dab_swig.i +++ b/swig/dab_swig.i @@ -21,7 +21,6 @@ #include "dab/time_deinterleave_ff.h" #include "dab/crc16_bb.h" #include "dab/fib_source_b.h" -#include "dab/unpuncture_ff.h" #include "dab/prune.h" #include "dab/firecode_check_bb.h" #include "dab/puncture_bb.h" @@ -74,8 +73,7 @@ GR_SWIG_BLOCK_MAGIC2(dab, time_deinterleave_ff); GR_SWIG_BLOCK_MAGIC2(dab, crc16_bb); %include "dab/fib_source_b.h" GR_SWIG_BLOCK_MAGIC2(dab, fib_source_b); -%include "dab/unpuncture_ff.h" -GR_SWIG_BLOCK_MAGIC2(dab, unpuncture_ff); + %include "dab/prune.h" GR_SWIG_BLOCK_MAGIC2(dab, prune); %include "dab/firecode_check_bb.h" From 7f59a1c396bce6902a832dcd14a759da99114085 Mon Sep 17 00:00:00 2001 From: luca Date: Thu, 18 Jan 2018 17:08:42 +0100 Subject: [PATCH 120/135] fix error in qa test --- python/qa/qa_fic_encode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/qa/qa_fic_encode.py b/python/qa/qa_fic_encode.py index 12e7e58b..1d2e66e8 100755 --- a/python/qa/qa_fic_encode.py +++ b/python/qa/qa_fic_encode.py @@ -49,10 +49,10 @@ def test_001_t (self): self.unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) # mapper - self.map = dab.mapper_bc_make(self.dp.num_carriers) + self.s2v = blocks.stream_to_vector_make(gr.sizeof_char, self.dp.num_carriers/4) + self.map = dab.qpsk_mapper_vbvc_make(self.dp.num_carriers) # demapper - self.s2v = blocks.stream_to_vector_make(gr.sizeof_gr_complex, self.dp.num_carriers) self.soft_interleaver = dab.complex_to_interleaved_float_vcf_make(self.dp.num_carriers) # decode @@ -62,8 +62,8 @@ def test_001_t (self): blocks.head_make(gr.sizeof_char, 100000), self.fib_enc, self.unpack, - self.map, self.s2v, + self.map, self.soft_interleaver, self.fic_decoder ) From 61320c485b329736169d8f8af9d555de6b2dbd8d Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sun, 21 Jan 2018 22:46:11 +0100 Subject: [PATCH 121/135] remove unused stuff --- python/fic.py | 162 ----------------------- python/fic_decode_vc.py | 2 - python/frequency_offset_variance.py | 68 ---------- python/msc_decode.py | 1 - python/ofdm_demod_cc.py | 1 - python/qa/qa_ofdm_synchronization_cvf.py | 41 ------ python/qa/qa_synchronization_ff.py | 41 ------ 7 files changed, 316 deletions(-) delete mode 100644 python/fic.py delete mode 100755 python/frequency_offset_variance.py delete mode 100755 python/qa/qa_ofdm_synchronization_cvf.py delete mode 100755 python/qa/qa_synchronization_ff.py diff --git a/python/fic.py b/python/fic.py deleted file mode 100644 index 7ec29fbd..00000000 --- a/python/fic.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -from gnuradio import gr, trellis, blocks -import dab_swig as dab -from math import sqrt - -""" -DAB FIC layer -""" - -class fic_decode(gr.hier_block2): - """ - @brief block to decode FIBs (fast information blocks) from the FIC (fast information channel) of a demodulated DAB signal - - - get FIBs from byte stream - - do convolutional decoding - - undo energy dispersal - - get FIC information - """ - - def __init__(self, dab_params, verbose=False, debug=False): - """ - Hierarchical block for FIC decoding - - @param dab_params DAB parameter object (dab.parameters.dab_parameters) - """ - gr.hier_block2.__init__(self, "fic", - #gr.io_signature2(2, 2, gr.sizeof_float * dab_params.num_carriers * 2, gr.sizeof_char), - gr.io_signature2(1, 1, gr.sizeof_float * dab_params.num_carriers * 2), - gr.io_signature(1, 1, gr.sizeof_char * 32)) - - self.dp = dab_params - self.verbose = verbose - self.debug = debug - - # FIB selection and block partitioning - self.select_fic_syms = dab.select_vectors(gr.sizeof_float, self.dp.num_carriers * 2, self.dp.num_fic_syms, 0) - self.repartition_fic = dab.repartition_vectors(gr.sizeof_float, self.dp.num_carriers * 2, - self.dp.fic_punctured_codeword_length, self.dp.num_fic_syms, - self.dp.num_cifs) - - # unpuncturing - self.unpuncture = dab.unpuncture_vff(self.dp.assembled_fic_puncturing_sequence, 0) - - # convolutional coding - # self.fsm = trellis.fsm(self.dp.conv_code_in_bits, self.dp.conv_code_out_bits, self.dp.conv_code_generator_polynomials) - self.fsm = trellis.fsm(1, 4, [0133, 0171, 0145, 0133]) # OK (dumped to text and verified partially) - self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.dp.fic_conv_codeword_length) - # self.conv_decode = trellis.viterbi_combined_fb(self.fsm, 20, 0, 0, 1, [1./sqrt(2),-1/sqrt(2)] , trellis.TRELLIS_EUCLIDEAN) - table = [ - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 1, 0, - 0, 0, 1, 1, - 0, 1, 0, 0, - 0, 1, 0, 1, - 0, 1, 1, 0, - 0, 1, 1, 1, - 1, 0, 0, 0, - 1, 0, 0, 1, - 1, 0, 1, 0, - 1, 0, 1, 1, - 1, 1, 0, 0, - 1, 1, 0, 1, - 1, 1, 1, 0, - 1, 1, 1, 1 - ] - assert (len(table) / 4 == self.fsm.O()) - table = [(1 - 2 * x) / sqrt(2) for x in table] - self.conv_decode = trellis.viterbi_combined_fb(self.fsm, 774, 0, 0, 4, table, trellis.TRELLIS_EUCLIDEAN) - #self.conv_s2v = blocks.stream_to_vector(gr.sizeof_char, 774) - self.conv_prune = dab.prune(gr.sizeof_char, self.dp.fic_conv_codeword_length / 4, 0, - self.dp.conv_code_add_bits_input) - - # energy dispersal - self.prbs_src = blocks.vector_source_b(self.dp.prbs(self.dp.energy_dispersal_fic_vector_length), True) - #self.energy_v2s = blocks.vector_to_stream(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length) - self.add_mod_2 = blocks.xor_bb() - self.energy_s2v = blocks.stream_to_vector(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length) - self.cut_into_fibs = dab.repartition_vectors(gr.sizeof_char, self.dp.energy_dispersal_fic_vector_length, - self.dp.fib_bits, 1, self.dp.energy_dispersal_fic_fibs_per_vector) - - # connect all - self.nullsink = blocks.null_sink(gr.sizeof_char) - self.pack = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) - self.fibout = blocks.stream_to_vector(1, 32) - # self.filesink = gr.file_sink(gr.sizeof_char, "debug/fic.dat") - self.fibsink = dab.fib_sink_vb() - - # self.connect((self,0), (self.select_fic_syms,0), (self.repartition_fic,0), self.unpuncture, self.conv_v2s, self.conv_decode, self.conv_s2v, self.conv_prune, self.energy_v2s, self.add_mod_2, self.energy_s2v, (self.cut_into_fibs,0), gr.vector_to_stream(1,256), gr.unpacked_to_packed_bb(1,gr.GR_MSB_FIRST), self.filesink) - self.connect((self, 0), - (self.select_fic_syms, 0), - (self.repartition_fic, 0), - self.unpuncture, - self.conv_v2s, - self.conv_decode, - #self.conv_s2v, - self.conv_prune, - #self.energy_v2s, - self.add_mod_2, - self.energy_s2v, - (self.cut_into_fibs, 0), - blocks.vector_to_stream(1, 256), - self.pack, - self.fibout, - self.fibsink) - self.connect(self.fibout, self) - self.connect(self.prbs_src, (self.add_mod_2, 1)) - self.connect((self, 1), (self.select_fic_syms, 1), (self.repartition_fic, 1), (self.cut_into_fibs, 1), - self.nullsink) - - if self.debug: - self.connect((self, 0), blocks.file_sink(gr.sizeof_float * self.dp.num_carriers * 2, "debug/transmission_frame.dat")) - self.connect((self, 1), blocks.file_sink(gr.sizeof_char, "debug/transmission_frame_trigger.dat")) - self.connect(self.select_fic_syms, blocks.file_sink(gr.sizeof_float * self.dp.num_carriers * 2, "debug/fic_select_syms.dat")) - self.connect(self.repartition_fic, blocks.file_sink(gr.sizeof_float * self.dp.fic_punctured_codeword_length, "debug/fic_repartitioned.dat")) - self.connect(self.unpuncture, blocks.file_sink(gr.sizeof_float * self.dp.fic_conv_codeword_length, "debug/fic_unpunctured.dat")) - self.connect(self.conv_decode, blocks.file_sink(gr.sizeof_char, "debug/fic_decoded.dat")) - self.connect(self.conv_prune, blocks.file_sink(gr.sizeof_char, "debug/fic_decoded_pruned.dat")) - #self.connect(self.conv_decode, blocks.file_sink(gr.sizeof_char * self.dp.energy_dispersal_fic_vector_length, "debug/fic_energy_dispersal_undone.dat")) - self.connect(self.pack, blocks.file_sink(gr.sizeof_char, "debug/fic_energy_undone.dat")) - - def get_ensemble_info(self): - return self.fibsink.get_ensemble_info() - - def get_service_info(self): - return self.fibsink.get_service_info() - - def get_service_labels(self): - return self.fibsink.get_service_labels() - - def get_subch_info(self): - return self.fibsink.get_subch_info() - - def get_programme_type(self): - return self.fibsink.get_programme_type() - - def get_crc_passed(self): - return self.fibsink.get_crc_passed() \ No newline at end of file diff --git a/python/fic_decode_vc.py b/python/fic_decode_vc.py index e7e79e6b..0bb68223 100644 --- a/python/fic_decode_vc.py +++ b/python/fic_decode_vc.py @@ -51,10 +51,8 @@ def __init__(self, dab_params): self.unpuncture = dab.unpuncture_vff(self.dp.assembled_fic_puncturing_sequence, 0) # convolutional coding - # self.fsm = trellis.fsm(self.dp.conv_code_in_bits, self.dp.conv_code_out_bits, self.dp.conv_code_generator_polynomials) self.fsm = trellis.fsm(1, 4, [0133, 0171, 0145, 0133]) # OK (dumped to text and verified partially) self.conv_v2s = blocks.vector_to_stream(gr.sizeof_float, self.dp.fic_conv_codeword_length) - # self.conv_decode = trellis.viterbi_combined_fb(self.fsm, 20, 0, 0, 1, [1./sqrt(2),-1/sqrt(2)] , trellis.TRELLIS_EUCLIDEAN) table = [ 0, 0, 0, 0, 0, 0, 0, 1, diff --git a/python/frequency_offset_variance.py b/python/frequency_offset_variance.py deleted file mode 100755 index 4cb9bdce..00000000 --- a/python/frequency_offset_variance.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import numpy as np -from gnuradio import gr -from gnuradio import blocks -from gnuradio import filter -import dab - -''' -Messung der Varianz des Frequenzoffsets bei verschiedenen SNR Szenarien -''' - -class measure_freq_offset(gr.top_block): - def __init__(self): - gr.top_block.__init__(self) - - #data_source = blocks.vector_source_c_make(signal) - data_source = blocks.file_source_make(gr.sizeof_gr_complex, "data/gen_iq_dab_normalized_resampled.dat") - measure = dab.synchronization_ff_make(2048, 504, 76) - head = blocks.head_make(gr.sizeof_float, 2) - sink = blocks.vector_sink_f_make() - self.connect(data_source, measure, head, sink) - self.run() - self.sink_data = sink.data() - #self.data = np.asarray(self.sink_data) - print self.sink_data - -flowgraph = measure_freq_offset() -# input original iq data -#iq_gen = np.fromfile('data/gen_iq_dab_normalized_resampled.dat', dtype=complex) -#len = len(iq_gen) -# SNR vector -# noise_range = np.asarray((-10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0)) -# # calculate frequency offset for each SNR -# for SNR in noise_range: -# print "Calculating freq offset for SNR: " + str(SNR) -# # generate noise signal -# #n = (np.sqrt(np.power(10.0, -SNR/10.0)/2.0) * (np.random.normal(0, 1, len) + 1j * np.random.normal(0, 1, len))) -# # add noise to signal -# #rx = np.add(iq_gen, n) -# # feed noisy signal in flowgraph -# flowgraph = measure_freq_offset() -# #f_offset = flowgraph.data -# # convert to Hz -# #f_offset = np.multiply(f_offset, 1.0/(2.0*np.pi)) -# #print f_offset -# # calculate variance -# # var = np.var(f_offset) -# # print var \ No newline at end of file diff --git a/python/msc_decode.py b/python/msc_decode.py index 9f305f5e..2f7fe48b 100644 --- a/python/msc_decode.py +++ b/python/msc_decode.py @@ -123,7 +123,6 @@ def __init__(self, dab_params, address, size, protection, verbose=False, debug=F #energy descramble self.prbs_src = blocks.vector_source_b(self.dp.prbs(self.msc_I), True) - self.energy_v2s = blocks.vector_to_stream(gr.sizeof_char, self.msc_I) self.add_mod_2 = blocks.xor_bb() #pack bits diff --git a/python/ofdm_demod_cc.py b/python/ofdm_demod_cc.py index 5fc01509..6741ebce 100644 --- a/python/ofdm_demod_cc.py +++ b/python/ofdm_demod_cc.py @@ -59,7 +59,6 @@ def __init__(self, dab_params): self.coarse_freq_corr = dab.ofdm_coarse_frequency_correction_vcvc_make(self.dp.fft_length, self.dp.num_carriers, self.dp.cp_length) - self.v2s_fft = blocks.vector_to_stream_make(gr.sizeof_gr_complex, self.dp.num_carriers) # differential phasor self.differential_phasor = dab.diff_phasor_vcc_make(1536) diff --git a/python/qa/qa_ofdm_synchronization_cvf.py b/python/qa/qa_ofdm_synchronization_cvf.py deleted file mode 100755 index 76a16265..00000000 --- a/python/qa/qa_ofdm_synchronization_cvf.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 <+YOU OR YOUR COMPANY+>. -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab - -class qa_ofdm_synchronization_cvf (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_t (self): - # set up fg - self.tb.run () - # check data - - -if __name__ == '__main__': - gr_unittest.run(qa_ofdm_synchronization_cvf, "qa_ofdm_synchronization_cvf.xml") diff --git a/python/qa/qa_synchronization_ff.py b/python/qa/qa_synchronization_ff.py deleted file mode 100755 index 10f579db..00000000 --- a/python/qa/qa_synchronization_ff.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2017 <+YOU OR YOUR COMPANY+>. -# -# This 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, or (at your option) -# any later version. -# -# This software 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 software; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -from gnuradio import blocks -import dab_swig as dab - -class qa_synchronization_ff (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_001_t (self): - # set up fg - self.tb.run () - # check data - - -if __name__ == '__main__': - gr_unittest.run(qa_synchronization_ff, "qa_synchronization_ff.xml") From 7a47098a1f757d4f62b18cb6edf8aa9d5c68ce36 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sun, 21 Jan 2018 23:24:17 +0100 Subject: [PATCH 122/135] fix except status in python module init --- python/__init__.py | 40 ++++---- python/dab_estimate_samplerate.py | 78 --------------- python/ofdm_mod_bc.py | 156 +++++++++++++++--------------- python/test_ofdm.py | 101 ------------------- 4 files changed, 97 insertions(+), 278 deletions(-) delete mode 100755 python/dab_estimate_samplerate.py delete mode 100755 python/test_ofdm.py diff --git a/python/__init__.py b/python/__init__.py index db68a90a..7d2bea06 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -19,32 +19,30 @@ # The presence of this file turns this directory into a Python package ''' -This is the GNU Radio DAB module. Place your Python package -description here (python/__init__.py). +This is the GNU Radio DAB module. ''' +# The presence of this file turns this directory into a Python package +import os + # import swig generated symbols into the dab namespace try: - # this might fail if the module is python-only - from dab_swig import * + # this might fail if the module is python-only + from dab_swig import * except ImportError: - pass - -# import any pure python here + dirname, filename = os.path.split(os.path.abspath(__file__)) + __path__.append(os.path.join(dirname, "..", "..", "swig")) + from dab_swig import * +from parameters import * +from ofdm_demod_cc import * +from ofdm_mod_bc import * +from fic_decode_vc import * +from fic_encode import * +from msc_decode import * +from msc_encode import * +from transmitter_c import * +from dabplus_audio_decoder_ff import * -from detect_null import detect_null -from parameters import dab_parameters -from parameters import receiver_parameters -from ofdm import ofdm_mod -from ofdm import ofdm_demod -from fic import fic_decode -from msc_decode import msc_decode -from fic_encode import fic_encode -from msc_encode import msc_encode -from transmitter_c import transmitter_c -from dabplus_audio_decoder_ff import dabplus_audio_decoder_ff -from ofdm_demod_cc import ofdm_demod_cc -from fic_decode_vc import fic_decode_vc import constants -# + diff --git a/python/dab_estimate_samplerate.py b/python/dab_estimate_samplerate.py deleted file mode 100755 index 5e24fd31..00000000 --- a/python/dab_estimate_samplerate.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -""" -estimate the sample rate of DAB samples by looking at the Null symbols -""" - -from gnuradio import gr, blocks -from gnuradio.eng_option import eng_option -import dab -from optparse import OptionParser - -class estimate_samplerate(gr.top_block): - """ - @brief Estimate actual sample rate - - Looks for Null symbols and estimates the real sample rate by counting - the samples between two Null symbols. - """ - def __init__(self): - gr.top_block.__init__(self) - - usage = "%prog: [options] samples_file" - parser = OptionParser(option_class=eng_option, usage=usage) - parser.add_option("-m", "--dab-mode", type="int", default=1, - help="DAB mode [default=%default]") - parser.add_option('-u', '--usrp-source', action="store_true", default=False, - help="Samples from USRP (-> resample from 2 MSPS to 2.048 MSPS)") - (options, args) = parser.parse_args () - - dp = dab.dab_parameters(options.dab_mode) - filename = args[0] - - self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) - self.resample = blocks.rational_resampler_ccc(2048,2000) - self.rate_detect_ns = dab.detect_null.detect_null(dp.ns_length, False) - self.rate_estimator = dab.blocks.estimate_sample_rate_bf(dp.sample_rate, dp.frame_length) - self.decimate = blocks.keep_one_in_n(gr.sizeof_float, dp.frame_length) - self.ignore_first = blocks.skiphead(gr.sizeof_float, 1) - self.sink = blocks.vector_sink_f() - - if options.usrp_source: - self.connect(self.src, self.resample, self.rate_detect_ns, self.rate_estimator, self.decimate, self.ignore_first, self.sink) - else: - self.connect(self.src, self.rate_detect_ns, self.rate_estimator, self.decimate, self.ignore_first, self.sink) - - -if __name__=='__main__': - try: - es = estimate_samplerate() - es.run() - print "sample rate estimation (average): " + str(sum(es.sink.data())/len(es.sink.data())) + " SPS" - except KeyboardInterrupt: - pass - - diff --git a/python/ofdm_mod_bc.py b/python/ofdm_mod_bc.py index 126642b2..7bf2c241 100644 --- a/python/ofdm_mod_bc.py +++ b/python/ofdm_mod_bc.py @@ -35,84 +35,84 @@ from math import sqrt """ -modulator and demodulator for the DAB physical layer +OFDM modulator for DAB/DAB+ """ -class ofdm_mod(gr.hier_block2): - """ - @brief Block to create a DAB signal from bits. - - Takes a data stream and performs OFDM modulation according to the DAB standard. - The output sample rate is 2.048 MSPS. - """ - - def __init__(self, dab_params, verbose=False, debug=False): - """ - Hierarchical block for OFDM modulation - - @param dab_params DAB parameter object (dab.parameters.dab_parameters) - @param debug enables debug output to files - """ - - dp = dab_params - - gr.hier_block2.__init__(self,"ofdm_mod", - gr.io_signature2(2, 2, gr.sizeof_char*dp.num_carriers/4, gr.sizeof_char), # input signature - gr.io_signature (1, 1, gr.sizeof_gr_complex)) # output signature - - - # symbol mapping - #self.mapper_v2s = blocks.vector_to_stream_make(gr.sizeof_char, 384) - #self.mapper_unpack = blocks.packed_to_unpacked_bb_make(1, gr.GR_MSB_FIRST) - #self.mapper = dab.mapper_bc_make(dp.num_carriers) - #self.mapper_s2v = blocks.stream_to_vector_make(gr.sizeof_gr_complex, 1536) - self.mapper = dab.qpsk_mapper_vbvc(dp.num_carriers) - - # add pilot symbol - self.insert_pilot = dab.ofdm_insert_pilot_vcc(dp.prn) - - # phase sum - self.sum_phase = dab.sum_phasor_trig_vcc(dp.num_carriers) - - # frequency interleaving - self.interleave = dab.frequency_interleaver_vcc(dp.frequency_interleaving_sequence_array) - # add central carrier & move to middle - self.move_and_insert_carrier = dab.ofdm_move_and_insert_zero(dp.fft_length, dp.num_carriers) - - # ifft - self.ifft = fft.fft_vcc(dp.fft_length, False, [], True) - - # cyclic prefixer - self.prefixer = digital.ofdm_cyclic_prefixer(dp.fft_length, dp.symbol_length) - - # normalize to energy = 1 after IFFT - self.multiply_const = blocks.multiply_const_cc(1.0/sqrt(2048)) - - # convert back to vectors - self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, dp.symbol_length) - - # add null symbol - self.insert_null = dab.insert_null_symbol(dp.ns_length, dp.symbol_length) - - # - # connect it all - # - - # data - #self.connect((self,0), self.mapper_v2s, self.mapper_unpack, self.mapper, self.mapper_s2v, (self.insert_pilot,0), (self.sum_phase,0), self.interleave, self.move_and_insert_carrier, self.ifft, self.prefixer, self.s2v, (self.insert_null,0)) - self.connect((self,0), self.mapper, (self.insert_pilot,0), (self.sum_phase,0), self.interleave, self.move_and_insert_carrier, self.ifft, self.prefixer, self.multiply_const, self.s2v, (self.insert_null,0)) - self.connect(self.insert_null, self) - - # control signal (frame start) - self.connect((self,1), (self.insert_pilot,1), (self.sum_phase,1), (self.insert_null,1)) - - if False: - self.connect(self.mapper, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_mapper.dat")) - self.connect(self.insert_pilot, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_pilot_inserted.dat")) - self.connect(self.sum_phase, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_sum_phase.dat")) - self.connect(self.interleave, blocks.file_sink(gr.sizeof_gr_complex*dp.num_carriers, "debug/generated_signal_interleave.dat")) - self.connect(self.move_and_insert_carrier, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/generated_signal_move_and_insert_carrier.dat")) - self.connect(self.ifft, blocks.file_sink(gr.sizeof_gr_complex*dp.fft_length, "debug/generated_signal_ifft.dat")) - self.connect(self.prefixer, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal_prefixer.dat")) - self.connect(self.insert_null, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal.dat")) +class ofdm_mod(gr.hier_block2): + """ + @brief Block to create a DAB signal from bits. + + Takes a data stream and performs OFDM modulation according to the DAB standard. + The output sample rate is 2.048 MSPS. + """ + + def __init__(self, dab_params, verbose=False, debug=False): + """ + Hierarchical block for OFDM modulation + + @param dab_params DAB parameter object (dab.parameters.dab_parameters) + @param debug enables debug output to files + """ + + dp = dab_params + + gr.hier_block2.__init__(self, "ofdm_mod", + gr.io_signature2(2, 2, gr.sizeof_char * dp.num_carriers / 4, gr.sizeof_char), + # input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # output signature + + # symbol mapping + self.mapper = dab.qpsk_mapper_vbvc(dp.num_carriers) + + # add pilot symbol + self.insert_pilot = dab.ofdm_insert_pilot_vcc(dp.prn) + + # phase sum + self.sum_phase = dab.sum_phasor_trig_vcc(dp.num_carriers) + + # frequency interleaving + self.interleave = dab.frequency_interleaver_vcc(dp.frequency_interleaving_sequence_array) + + # add central carrier & move to middle + self.move_and_insert_carrier = dab.ofdm_move_and_insert_zero(dp.fft_length, dp.num_carriers) + + # ifft + self.ifft = fft.fft_vcc(dp.fft_length, False, [], True) + + # cyclic prefixer + self.prefixer = digital.ofdm_cyclic_prefixer(dp.fft_length, dp.symbol_length) + + # normalize to energy = 1 after IFFT + self.multiply_const = blocks.multiply_const_cc(1.0 / sqrt(2048)) + + # convert back to vectors + self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, dp.symbol_length) + + # add null symbol + self.insert_null = dab.insert_null_symbol(dp.ns_length, dp.symbol_length) + + # data + self.connect((self, 0), self.mapper, (self.insert_pilot, 0), (self.sum_phase, 0), self.interleave, + self.move_and_insert_carrier, self.ifft, self.prefixer, self.multiply_const, self.s2v, + (self.insert_null, 0)) + self.connect(self.insert_null, self) + + # control signal (frame start) + self.connect((self, 1), (self.insert_pilot, 1), (self.sum_phase, 1), (self.insert_null, 1)) + + if debug: + self.connect(self.mapper, + blocks.file_sink(gr.sizeof_gr_complex * dp.num_carriers, "debug/generated_signal_mapper.dat")) + self.connect(self.insert_pilot, blocks.file_sink(gr.sizeof_gr_complex * dp.num_carriers, + "debug/generated_signal_pilot_inserted.dat")) + self.connect(self.sum_phase, blocks.file_sink(gr.sizeof_gr_complex * dp.num_carriers, + "debug/generated_signal_sum_phase.dat")) + self.connect(self.interleave, blocks.file_sink(gr.sizeof_gr_complex * dp.num_carriers, + "debug/generated_signal_interleave.dat")) + self.connect(self.move_and_insert_carrier, blocks.file_sink(gr.sizeof_gr_complex * dp.fft_length, + "debug/generated_signal_move_and_insert_carrier.dat")) + self.connect(self.ifft, + blocks.file_sink(gr.sizeof_gr_complex * dp.fft_length, "debug/generated_signal_ifft.dat")) + self.connect(self.prefixer, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal_prefixer.dat")) + self.connect(self.insert_null, blocks.file_sink(gr.sizeof_gr_complex, "debug/generated_signal.dat")) diff --git a/python/test_ofdm.py b/python/test_ofdm.py deleted file mode 100755 index b6e88de5..00000000 --- a/python/test_ofdm.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -# test_ofdm.py - test the ofdm demod block -# -# Andreas Mueller, 2008 -# andrmuel@ee.ethz.ch - -from gnuradio import gr, blocks -from gnuradio.eng_option import eng_option -from optparse import OptionParser -from dab import ofdm -import parameters -import random - -class test_ofdm(gr.top_block): - """ - @brief Test program for the ofdm_demod class. - """ - def __init__(self): - gr.top_block.__init__(self) - - - usage = "%prog: [options] samples_file" - parser = OptionParser(option_class=eng_option, usage=usage) - parser.add_option("-m", "--dab-mode", type="int", default=1, - help="DAB mode [default=%default]") - parser.add_option("-F", "--filter-input", action="store_true", default=False, - help="Enable FFT filter at input") - parser.add_option("-s", "--resample-fixed", type="float", default=1, - help="resample by a fixed factor (fractional interpolation)") - parser.add_option("-S", "--autocorrect-sample-rate", action="store_true", default=False, - help="Estimate sample rate offset and resample (dynamic fractional interpolation)") - parser.add_option('-r', '--sample-rate', type="int", default=2048000, - help="Use non-standard sample rate (default=%default)") - parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False, - help="Enable individual carrier magnitude equalizer") - parser.add_option('-d', '--debug', action="store_true", default=False, - help="Write output to files") - parser.add_option('-v', '--verbose', action="store_true", default=False, - help="Print status messages") - (options, args) = parser.parse_args () - - dp = parameters.dab_parameters(options.dab_mode, verbose=options.verbose, sample_rate=options.sample_rate) - - rp = parameters.receiver_parameters(options.dab_mode, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, equalize_magnitude=options.equalize_magnitude, verbose=options.verbose) - - if len(args)<1: - if options.verbose: print "-> using repeating random vector as source" - self.sigsrc = blocks.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True) - self.ns_simulate = blocks.vector_source_c([0.01]*dp.ns_length+[1]*dp.symbols_per_frame*dp.symbol_length,1) - self.mult = blocks.multiply_cc() # simulate null symbols ... - self.src = blocks.throttle( gr.sizeof_gr_complex,2048000) - self.connect(self.sigsrc, (self.mult, 0)) - self.connect(self.ns_simulate, (self.mult, 1)) - self.connect(self.mult, self.src) - else: - filename = args[0] - if options.verbose: print "-> using samples from file " + filename - self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) - - self.dab_demod = ofdm.ofdm_demod(dp, rp, debug=options.debug, verbose=options.verbose) - - self.connect(self.src, self.dab_demod) - - # sink output to nowhere - self.nop0 = blocks.nop(gr.sizeof_char*dp.num_carriers/4) - self.nop1 = blocks.nop(gr.sizeof_char) - self.connect((self.dab_demod,0),self.nop0) - self.connect((self.dab_demod,1),self.nop1) - -if __name__=='__main__': - try: - to = test_ofdm() - # to.run() - to.run() - to.dump() - to.dab_demod.stop() - - except KeyboardInterrupt: - pass - From 3312591b849833d833c38ffefc3d12e232a67bb1 Mon Sep 17 00:00:00 2001 From: luca Date: Tue, 23 Jan 2018 16:17:11 +0100 Subject: [PATCH 123/135] generate user_frontend.py on the fly while building --- .gitignore | 1 + python/CMakeLists.txt | 7 +- python/GUI/CMakeLists.txt | 11 + python/GUI/frontend.py | 8 - python/GUI/user_frontend.py | 1601 -------------------------------- python/qa/qa_unpuncture_vff.py | 19 + python/qa/qa_valve_ff.py | 10 +- 7 files changed, 37 insertions(+), 1620 deletions(-) delete mode 100644 python/GUI/frontend.py delete mode 100644 python/GUI/user_frontend.py diff --git a/.gitignore b/.gitignore index bee6f383..8300b471 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ log_default.conf python/.unittests/ .idea/ examples/top_block.py +python/GUI/user_frontend.py diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e6ca7484..1eff45eb 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -79,7 +79,6 @@ GR_ADD_TEST(qa_reed_solomon_encode_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SO GR_ADD_TEST(qa_msc_encode.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_msc_encode.py) GR_ADD_TEST(qa_time_interleave_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_time_interleave_bb.py) GR_ADD_TEST(qa_dab_transmission_frame_mux_bb.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_dab_transmission_frame_mux_bb.py) - GR_ADD_TEST(qa_diff_phasor_vcc.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_diff_phasor_vcc.py) GR_ADD_TEST(qa_complex_to_interleaved_float_vcf.py ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_complex_to_interleaved_float_vcf.py) GR_ADD_TEST(qa_select_cus_vfvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_select_cus_vfvf.py) @@ -89,9 +88,5 @@ GR_ADD_TEST(qa_fib_sink_vb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/q GR_ADD_TEST(qa_time_deinterleave_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_time_deinterleave_ff.py) GR_ADD_TEST(qa_reed_solomon_decode_bb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_reed_solomon_decode_bb.py) GR_ADD_TEST(qa_mp4_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa/qa_mp4_decode_bs.py) +GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) -#GR_ADD_TEST(qa_mp2_decode_bs ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_decode_bs.py) -#GR_ADD_TEST(qa_dabplus_audio_decoder_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dabplus_audio_decoder_ff.py) -#GR_ADD_TEST(qa_mp2_encode_sb ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_mp2_encode_sb.py) -#GR_ADD_TEST(qa_valve_ff ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_valve_ff.py) -#GR_ADD_TEST(qa_ofdm_synchronization_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronization_cvf.py) diff --git a/python/GUI/CMakeLists.txt b/python/GUI/CMakeLists.txt index e243f8bb..3fa6daf9 100644 --- a/python/GUI/CMakeLists.txt +++ b/python/GUI/CMakeLists.txt @@ -35,3 +35,14 @@ install(FILES led_green.png DESTINATION ${GR_PKG_DAB_DATA_DIR} ) + +######################################################################## +# Generate the GUI python code user_frontend.py from the user interface user_frontend.ui +######################################################################## +set(GUI_UI ${CMAKE_CURRENT_SOURCE_DIR}/user_frontend.ui) +set(GUI_PY ${CMAKE_CURRENT_BINARY_DIR}/user_frontend.py) +add_custom_command(OUTPUT ${GUI_UI} + COMMAND ${PYUIC4_EXECUTABLE} pyuic4 ${GUI_UI} -o ${GUI_PY} + DEPENDS ${GUI_UI} + COMMENT "Generating python code from the user interface" +) diff --git a/python/GUI/frontend.py b/python/GUI/frontend.py deleted file mode 100644 index 9894632e..00000000 --- a/python/GUI/frontend.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'frontend.ui' -# -# Created by: PyQt4 UI code generator 4.11.4 -# -# WARNING! All changes made in this file will be lost! - diff --git a/python/GUI/user_frontend.py b/python/GUI/user_frontend.py deleted file mode 100644 index 77050152..00000000 --- a/python/GUI/user_frontend.py +++ /dev/null @@ -1,1601 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'user_frontend.ui' -# -# Created by: PyQt4 UI code generator 4.11.4 -# -# WARNING! All changes made in this file will be lost! - -from PyQt4 import QtCore, QtGui - -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - def _fromUtf8(s): - return s - -try: - _encoding = QtGui.QApplication.UnicodeUTF8 - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig, _encoding) -except AttributeError: - def _translate(context, text, disambig): - return QtGui.QApplication.translate(context, text, disambig) - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName(_fromUtf8("MainWindow")) - MainWindow.resize(1203, 739) - self.centralwidget = QtGui.QWidget(MainWindow) - self.centralwidget.setEnabled(True) - self.centralwidget.setObjectName(_fromUtf8("centralwidget")) - self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget) - self.verticalLayout.setObjectName(_fromUtf8("verticalLayout")) - self.horizontalLayout_21 = QtGui.QHBoxLayout() - self.horizontalLayout_21.setObjectName(_fromUtf8("horizontalLayout_21")) - self.label_5 = QtGui.QLabel(self.centralwidget) - self.label_5.setObjectName(_fromUtf8("label_5")) - self.horizontalLayout_21.addWidget(self.label_5) - self.label_logo = QtGui.QLabel(self.centralwidget) - self.label_logo.setObjectName(_fromUtf8("label_logo")) - self.horizontalLayout_21.addWidget(self.label_logo) - spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_21.addItem(spacerItem) - self.btn_dev_mode_close = QtGui.QPushButton(self.centralwidget) - self.btn_dev_mode_close.setEnabled(True) - icon = QtGui.QIcon.fromTheme(_fromUtf8("list-remove")) - self.btn_dev_mode_close.setIcon(icon) - self.btn_dev_mode_close.setObjectName(_fromUtf8("btn_dev_mode_close")) - self.horizontalLayout_21.addWidget(self.btn_dev_mode_close) - self.btn_dev_mode_open = QtGui.QPushButton(self.centralwidget) - self.btn_dev_mode_open.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("list-add")) - self.btn_dev_mode_open.setIcon(icon) - self.btn_dev_mode_open.setObjectName(_fromUtf8("btn_dev_mode_open")) - self.horizontalLayout_21.addWidget(self.btn_dev_mode_open) - self.verticalLayout.addLayout(self.horizontalLayout_21) - self.mode_tabs = QtGui.QTabWidget(self.centralwidget) - self.mode_tabs.setEnabled(True) - self.mode_tabs.setObjectName(_fromUtf8("mode_tabs")) - self.tab_reception = QtGui.QWidget() - self.tab_reception.setObjectName(_fromUtf8("tab_reception")) - self.verticalLayout_2 = QtGui.QVBoxLayout(self.tab_reception) - self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2")) - self.horizontal_layout_reception = QtGui.QHBoxLayout() - self.horizontal_layout_reception.setObjectName(_fromUtf8("horizontal_layout_reception")) - self.verticalLayout_6 = QtGui.QVBoxLayout() - self.verticalLayout_6.setObjectName(_fromUtf8("verticalLayout_6")) - self.horizontalLayout_8 = QtGui.QHBoxLayout() - self.horizontalLayout_8.setObjectName(_fromUtf8("horizontalLayout_8")) - self.verticalLayout_6.addLayout(self.horizontalLayout_8) - self.horizontalLayout = QtGui.QHBoxLayout() - self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout")) - self.rbtn_USRP = QtGui.QRadioButton(self.tab_reception) - self.rbtn_USRP.setChecked(True) - self.rbtn_USRP.setAutoRepeat(False) - self.rbtn_USRP.setObjectName(_fromUtf8("rbtn_USRP")) - self.horizontalLayout.addWidget(self.rbtn_USRP) - self.rbtn_RTL = QtGui.QRadioButton(self.tab_reception) - self.rbtn_RTL.setObjectName(_fromUtf8("rbtn_RTL")) - self.horizontalLayout.addWidget(self.rbtn_RTL) - spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout.addItem(spacerItem1) - self.label_frequency = QtGui.QLabel(self.tab_reception) - self.label_frequency.setObjectName(_fromUtf8("label_frequency")) - self.horizontalLayout.addWidget(self.label_frequency) - self.spinbox_frequency = QtGui.QSpinBox(self.tab_reception) - self.spinbox_frequency.setMaximum(1000000000) - self.spinbox_frequency.setProperty("value", 208064000) - self.spinbox_frequency.setObjectName(_fromUtf8("spinbox_frequency")) - self.horizontalLayout.addWidget(self.spinbox_frequency) - self.label_4 = QtGui.QLabel(self.tab_reception) - self.label_4.setObjectName(_fromUtf8("label_4")) - self.horizontalLayout.addWidget(self.label_4) - self.verticalLayout_6.addLayout(self.horizontalLayout) - self.horizontalLayout_6 = QtGui.QHBoxLayout() - self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6")) - self.rbtn_File = QtGui.QRadioButton(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.rbtn_File.sizePolicy().hasHeightForWidth()) - self.rbtn_File.setSizePolicy(sizePolicy) - self.rbtn_File.setObjectName(_fromUtf8("rbtn_File")) - self.horizontalLayout_6.addWidget(self.rbtn_File) - self.label_path = QtGui.QLabel(self.tab_reception) - self.label_path.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_path.sizePolicy().hasHeightForWidth()) - self.label_path.setSizePolicy(sizePolicy) - self.label_path.setMinimumSize(QtCore.QSize(100, 0)) - self.label_path.setFrameShape(QtGui.QFrame.Box) - self.label_path.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_path.setObjectName(_fromUtf8("label_path")) - self.horizontalLayout_6.addWidget(self.label_path) - self.btn_file_path = QtGui.QToolButton(self.tab_reception) - self.btn_file_path.setEnabled(False) - self.btn_file_path.setObjectName(_fromUtf8("btn_file_path")) - self.horizontalLayout_6.addWidget(self.btn_file_path) - self.verticalLayout_6.addLayout(self.horizontalLayout_6) - self.horizontalLayout_30 = QtGui.QHBoxLayout() - self.horizontalLayout_30.setObjectName(_fromUtf8("horizontalLayout_30")) - spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_30.addItem(spacerItem2) - self.label_6 = QtGui.QLabel(self.tab_reception) - self.label_6.setObjectName(_fromUtf8("label_6")) - self.horizontalLayout_30.addWidget(self.label_6) - self.spin_dab_mode = QtGui.QSpinBox(self.tab_reception) - self.spin_dab_mode.setMinimum(1) - self.spin_dab_mode.setMaximum(4) - self.spin_dab_mode.setObjectName(_fromUtf8("spin_dab_mode")) - self.horizontalLayout_30.addWidget(self.spin_dab_mode) - self.verticalLayout_6.addLayout(self.horizontalLayout_30) - self.horizontalLayout_3 = QtGui.QHBoxLayout() - self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3")) - self.verticalLayout_6.addLayout(self.horizontalLayout_3) - self.table_mci = QtGui.QTableWidget(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.table_mci.sizePolicy().hasHeightForWidth()) - self.table_mci.setSizePolicy(sizePolicy) - self.table_mci.setObjectName(_fromUtf8("table_mci")) - self.table_mci.setColumnCount(4) - self.table_mci.setRowCount(0) - item = QtGui.QTableWidgetItem() - self.table_mci.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.table_mci.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() - self.table_mci.setHorizontalHeaderItem(2, item) - item = QtGui.QTableWidgetItem() - self.table_mci.setHorizontalHeaderItem(3, item) - self.table_mci.horizontalHeader().setCascadingSectionResizes(False) - self.table_mci.horizontalHeader().setDefaultSectionSize(100) - self.table_mci.horizontalHeader().setStretchLastSection(True) - self.verticalLayout_6.addWidget(self.table_mci) - self.horizontal_layout_reception.addLayout(self.verticalLayout_6) - self.line_8 = QtGui.QFrame(self.tab_reception) - self.line_8.setFrameShape(QtGui.QFrame.VLine) - self.line_8.setFrameShadow(QtGui.QFrame.Sunken) - self.line_8.setObjectName(_fromUtf8("line_8")) - self.horizontal_layout_reception.addWidget(self.line_8) - self.verticalLayout_7 = QtGui.QVBoxLayout() - self.verticalLayout_7.setObjectName(_fromUtf8("verticalLayout_7")) - self.horizontalLayout_27 = QtGui.QHBoxLayout() - self.horizontalLayout_27.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) - self.horizontalLayout_27.setSpacing(6) - self.horizontalLayout_27.setObjectName(_fromUtf8("horizontalLayout_27")) - self.label_ensemble = QtGui.QLabel(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_ensemble.sizePolicy().hasHeightForWidth()) - self.label_ensemble.setSizePolicy(sizePolicy) - font = QtGui.QFont() - font.setPointSize(17) - self.label_ensemble.setFont(font) - self.label_ensemble.setAlignment(QtCore.Qt.AlignCenter) - self.label_ensemble.setObjectName(_fromUtf8("label_ensemble")) - self.horizontalLayout_27.addWidget(self.label_ensemble) - self.verticalLayout_10 = QtGui.QVBoxLayout() - self.verticalLayout_10.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) - self.verticalLayout_10.setObjectName(_fromUtf8("verticalLayout_10")) - self.horizontalLayout_28 = QtGui.QHBoxLayout() - self.horizontalLayout_28.setSizeConstraint(QtGui.QLayout.SetDefaultConstraint) - self.horizontalLayout_28.setObjectName(_fromUtf8("horizontalLayout_28")) - self.label_26 = QtGui.QLabel(self.tab_reception) - self.label_26.setObjectName(_fromUtf8("label_26")) - self.horizontalLayout_28.addWidget(self.label_26) - self.lcd_number_num_subch = QtGui.QLCDNumber(self.tab_reception) - self.lcd_number_num_subch.setEnabled(True) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.lcd_number_num_subch.sizePolicy().hasHeightForWidth()) - self.lcd_number_num_subch.setSizePolicy(sizePolicy) - self.lcd_number_num_subch.setNumDigits(2) - self.lcd_number_num_subch.setSegmentStyle(QtGui.QLCDNumber.Flat) - self.lcd_number_num_subch.setObjectName(_fromUtf8("lcd_number_num_subch")) - self.horizontalLayout_28.addWidget(self.lcd_number_num_subch) - self.verticalLayout_10.addLayout(self.horizontalLayout_28) - self.label_country = QtGui.QLabel(self.tab_reception) - self.label_country.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_country.setObjectName(_fromUtf8("label_country")) - self.verticalLayout_10.addWidget(self.label_country) - self.horizontalLayout_27.addLayout(self.verticalLayout_10) - self.verticalLayout_7.addLayout(self.horizontalLayout_27) - self.line_11 = QtGui.QFrame(self.tab_reception) - self.line_11.setFrameShape(QtGui.QFrame.HLine) - self.line_11.setFrameShadow(QtGui.QFrame.Sunken) - self.line_11.setObjectName(_fromUtf8("line_11")) - self.verticalLayout_7.addWidget(self.line_11) - spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem3) - self.horizontalLayout_23 = QtGui.QHBoxLayout() - self.horizontalLayout_23.setObjectName(_fromUtf8("horizontalLayout_23")) - self.bar_snr = QtGui.QProgressBar(self.tab_reception) - self.bar_snr.setStyleSheet(_fromUtf8("tfadsf")) - self.bar_snr.setMinimum(0) - self.bar_snr.setMaximum(40) - self.bar_snr.setProperty("value", 0) - self.bar_snr.setFormat(_fromUtf8("")) - self.bar_snr.setObjectName(_fromUtf8("bar_snr")) - self.horizontalLayout_23.addWidget(self.bar_snr) - self.label_snr = QtGui.QLabel(self.tab_reception) - self.label_snr.setObjectName(_fromUtf8("label_snr")) - self.horizontalLayout_23.addWidget(self.label_snr) - self.lcd_snr = QtGui.QLCDNumber(self.tab_reception) - self.lcd_snr.setSmallDecimalPoint(False) - self.lcd_snr.setNumDigits(4) - self.lcd_snr.setSegmentStyle(QtGui.QLCDNumber.Flat) - self.lcd_snr.setObjectName(_fromUtf8("lcd_snr")) - self.horizontalLayout_23.addWidget(self.lcd_snr) - self.label_7 = QtGui.QLabel(self.tab_reception) - self.label_7.setObjectName(_fromUtf8("label_7")) - self.horizontalLayout_23.addWidget(self.label_7) - self.verticalLayout_7.addLayout(self.horizontalLayout_23) - self.vertical_layout_dev_mode_right_vertical = QtGui.QVBoxLayout() - self.vertical_layout_dev_mode_right_vertical.setObjectName(_fromUtf8("vertical_layout_dev_mode_right_vertical")) - self.horizontalLayout_29 = QtGui.QHBoxLayout() - self.horizontalLayout_29.setObjectName(_fromUtf8("horizontalLayout_29")) - self.label_firecode = QtGui.QLabel(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_firecode.sizePolicy().hasHeightForWidth()) - self.label_firecode.setSizePolicy(sizePolicy) - self.label_firecode.setMinimumSize(QtCore.QSize(365, 80)) - self.label_firecode.setMaximumSize(QtCore.QSize(365, 80)) - self.label_firecode.setFrameShape(QtGui.QFrame.Box) - self.label_firecode.setFrameShadow(QtGui.QFrame.Sunken) - self.label_firecode.setLineWidth(2) - self.label_firecode.setMidLineWidth(0) - self.label_firecode.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) - self.label_firecode.setObjectName(_fromUtf8("label_firecode")) - self.horizontalLayout_29.addWidget(self.label_firecode) - self.verticalLayout_13 = QtGui.QVBoxLayout() - self.verticalLayout_13.setObjectName(_fromUtf8("verticalLayout_13")) - spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem4) - self.led_msc = QtGui.QLabel(self.tab_reception) - self.led_msc.setObjectName(_fromUtf8("led_msc")) - self.verticalLayout_13.addWidget(self.led_msc) - spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_13.addItem(spacerItem5) - self.horizontalLayout_29.addLayout(self.verticalLayout_13) - self.label_label_msc = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_label_msc.setFont(font) - self.label_label_msc.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.label_label_msc.setObjectName(_fromUtf8("label_label_msc")) - self.horizontalLayout_29.addWidget(self.label_label_msc) - spacerItem6 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_29.addItem(spacerItem6) - self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_29) - self.horizontalLayout_32 = QtGui.QHBoxLayout() - self.horizontalLayout_32.setObjectName(_fromUtf8("horizontalLayout_32")) - self.label_fic = QtGui.QLabel(self.tab_reception) - self.label_fic.setMinimumSize(QtCore.QSize(365, 80)) - self.label_fic.setMaximumSize(QtCore.QSize(365, 80)) - self.label_fic.setFrameShape(QtGui.QFrame.Box) - self.label_fic.setFrameShadow(QtGui.QFrame.Sunken) - self.label_fic.setLineWidth(2) - self.label_fic.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) - self.label_fic.setObjectName(_fromUtf8("label_fic")) - self.horizontalLayout_32.addWidget(self.label_fic) - self.verticalLayout_14 = QtGui.QVBoxLayout() - self.verticalLayout_14.setObjectName(_fromUtf8("verticalLayout_14")) - spacerItem7 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem7) - self.led_fic = QtGui.QLabel(self.tab_reception) - self.led_fic.setObjectName(_fromUtf8("led_fic")) - self.verticalLayout_14.addWidget(self.led_fic) - spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_14.addItem(spacerItem8) - self.horizontalLayout_32.addLayout(self.verticalLayout_14) - self.label_label_fic = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_label_fic.setFont(font) - self.label_label_fic.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.label_label_fic.setObjectName(_fromUtf8("label_label_fic")) - self.horizontalLayout_32.addWidget(self.label_label_fic) - spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_32.addItem(spacerItem9) - self.vertical_layout_dev_mode_right_vertical.addLayout(self.horizontalLayout_32) - self.verticalLayout_7.addLayout(self.vertical_layout_dev_mode_right_vertical) - spacerItem10 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem10) - self.line_6 = QtGui.QFrame(self.tab_reception) - self.line_6.setFrameShape(QtGui.QFrame.HLine) - self.line_6.setFrameShadow(QtGui.QFrame.Sunken) - self.line_6.setObjectName(_fromUtf8("line_6")) - self.verticalLayout_7.addWidget(self.line_6) - self.horizontalLayout_24 = QtGui.QHBoxLayout() - self.horizontalLayout_24.setObjectName(_fromUtf8("horizontalLayout_24")) - self.label_service = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setPointSize(24) - self.label_service.setFont(font) - self.label_service.setAlignment(QtCore.Qt.AlignCenter) - self.label_service.setObjectName(_fromUtf8("label_service")) - self.horizontalLayout_24.addWidget(self.label_service) - self.verticalLayout_7.addLayout(self.horizontalLayout_24) - self.label_programme_type = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setPointSize(12) - self.label_programme_type.setFont(font) - self.label_programme_type.setAlignment(QtCore.Qt.AlignCenter) - self.label_programme_type.setObjectName(_fromUtf8("label_programme_type")) - self.verticalLayout_7.addWidget(self.label_programme_type) - self.horizontalLayout_25 = QtGui.QHBoxLayout() - self.horizontalLayout_25.setObjectName(_fromUtf8("horizontalLayout_25")) - self.label_bit_rate = QtGui.QLabel(self.tab_reception) - self.label_bit_rate.setAlignment(QtCore.Qt.AlignCenter) - self.label_bit_rate.setObjectName(_fromUtf8("label_bit_rate")) - self.horizontalLayout_25.addWidget(self.label_bit_rate) - self.label_primary = QtGui.QLabel(self.tab_reception) - self.label_primary.setAlignment(QtCore.Qt.AlignCenter) - self.label_primary.setObjectName(_fromUtf8("label_primary")) - self.horizontalLayout_25.addWidget(self.label_primary) - self.label_dabplus = QtGui.QLabel(self.tab_reception) - self.label_dabplus.setAlignment(QtCore.Qt.AlignCenter) - self.label_dabplus.setObjectName(_fromUtf8("label_dabplus")) - self.horizontalLayout_25.addWidget(self.label_dabplus) - self.verticalLayout_7.addLayout(self.horizontalLayout_25) - self.line_7 = QtGui.QFrame(self.tab_reception) - self.line_7.setFrameShape(QtGui.QFrame.HLine) - self.line_7.setFrameShadow(QtGui.QFrame.Sunken) - self.line_7.setObjectName(_fromUtf8("line_7")) - self.verticalLayout_7.addWidget(self.line_7) - self.horizontalLayout_26 = QtGui.QHBoxLayout() - self.horizontalLayout_26.setObjectName(_fromUtf8("horizontalLayout_26")) - self.btn_init = QtGui.QPushButton(self.tab_reception) - font = QtGui.QFont() - font.setKerning(True) - self.btn_init.setFont(font) - icon = QtGui.QIcon.fromTheme(_fromUtf8("network-receive")) - self.btn_init.setIcon(icon) - self.btn_init.setCheckable(False) - self.btn_init.setFlat(False) - self.btn_init.setObjectName(_fromUtf8("btn_init")) - self.horizontalLayout_26.addWidget(self.btn_init) - self.btn_update_info = QtGui.QPushButton(self.tab_reception) - self.btn_update_info.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("system-search")) - self.btn_update_info.setIcon(icon) - self.btn_update_info.setObjectName(_fromUtf8("btn_update_info")) - self.horizontalLayout_26.addWidget(self.btn_update_info) - self.verticalLayout_7.addLayout(self.horizontalLayout_26) - self.horizontalLayout_40 = QtGui.QHBoxLayout() - self.horizontalLayout_40.setObjectName(_fromUtf8("horizontalLayout_40")) - self.label_10 = QtGui.QLabel(self.tab_reception) - self.label_10.setObjectName(_fromUtf8("label_10")) - self.horizontalLayout_40.addWidget(self.label_10) - self.gain_spin = QtGui.QSpinBox(self.tab_reception) - self.gain_spin.setMaximum(100) - self.gain_spin.setProperty("value", 50) - self.gain_spin.setObjectName(_fromUtf8("gain_spin")) - self.horizontalLayout_40.addWidget(self.gain_spin) - spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_40.addItem(spacerItem11) - self.verticalLayout_7.addLayout(self.horizontalLayout_40) - self.line_9 = QtGui.QFrame(self.tab_reception) - self.line_9.setFrameShape(QtGui.QFrame.HLine) - self.line_9.setFrameShadow(QtGui.QFrame.Sunken) - self.line_9.setObjectName(_fromUtf8("line_9")) - self.verticalLayout_7.addWidget(self.line_9) - spacerItem12 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.verticalLayout_7.addItem(spacerItem12) - self.label_2 = QtGui.QLabel(self.tab_reception) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_2.setFont(font) - self.label_2.setLayoutDirection(QtCore.Qt.LeftToRight) - self.label_2.setObjectName(_fromUtf8("label_2")) - self.verticalLayout_7.addWidget(self.label_2) - self.horizontalLayout_5 = QtGui.QHBoxLayout() - self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5")) - self.btn_play = QtGui.QPushButton(self.tab_reception) - self.btn_play.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-start")) - self.btn_play.setIcon(icon) - self.btn_play.setObjectName(_fromUtf8("btn_play")) - self.horizontalLayout_5.addWidget(self.btn_play) - self.btn_stop = QtGui.QPushButton(self.tab_reception) - self.btn_stop.setEnabled(True) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-stop")) - self.btn_stop.setIcon(icon) - self.btn_stop.setObjectName(_fromUtf8("btn_stop")) - self.horizontalLayout_5.addWidget(self.btn_stop) - self.btn_record = QtGui.QPushButton(self.tab_reception) - self.btn_record.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.btn_record.setIcon(icon) - self.btn_record.setObjectName(_fromUtf8("btn_record")) - self.horizontalLayout_5.addWidget(self.btn_record) - self.verticalLayout_7.addLayout(self.horizontalLayout_5) - self.horizontalLayout_4 = QtGui.QHBoxLayout() - self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4")) - self.label_3 = QtGui.QLabel(self.tab_reception) - self.label_3.setObjectName(_fromUtf8("label_3")) - self.horizontalLayout_4.addWidget(self.label_3) - self.slider_volume = QtGui.QSlider(self.tab_reception) - self.slider_volume.setEnabled(False) - self.slider_volume.setMaximum(100) - self.slider_volume.setProperty("value", 80) - self.slider_volume.setSliderPosition(80) - self.slider_volume.setOrientation(QtCore.Qt.Horizontal) - self.slider_volume.setObjectName(_fromUtf8("slider_volume")) - self.horizontalLayout_4.addWidget(self.slider_volume) - self.verticalLayout_7.addLayout(self.horizontalLayout_4) - self.horizontal_layout_reception.addLayout(self.verticalLayout_7) - self.line_12 = QtGui.QFrame(self.tab_reception) - self.line_12.setFrameShape(QtGui.QFrame.VLine) - self.line_12.setFrameShadow(QtGui.QFrame.Sunken) - self.line_12.setObjectName(_fromUtf8("line_12")) - self.horizontal_layout_reception.addWidget(self.line_12) - self.dev_scroll_area = QtGui.QScrollArea(self.tab_reception) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.dev_scroll_area.sizePolicy().hasHeightForWidth()) - self.dev_scroll_area.setSizePolicy(sizePolicy) - self.dev_scroll_area.setMinimumSize(QtCore.QSize(0, 0)) - self.dev_scroll_area.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.dev_scroll_area.setWidgetResizable(True) - self.dev_scroll_area.setObjectName(_fromUtf8("dev_scroll_area")) - self.dev_scroll_area_content = QtGui.QWidget() - self.dev_scroll_area_content.setGeometry(QtCore.QRect(0, 0, 200, 602)) - self.dev_scroll_area_content.setObjectName(_fromUtf8("dev_scroll_area_content")) - self.verticalLayout_12 = QtGui.QVBoxLayout(self.dev_scroll_area_content) - self.verticalLayout_12.setObjectName(_fromUtf8("verticalLayout_12")) - self.vertical_layout_dev_mode_right = QtGui.QVBoxLayout() - self.vertical_layout_dev_mode_right.setObjectName(_fromUtf8("vertical_layout_dev_mode_right")) - self.verticalLayout_12.addLayout(self.vertical_layout_dev_mode_right) - self.dev_scroll_area.setWidget(self.dev_scroll_area_content) - self.horizontal_layout_reception.addWidget(self.dev_scroll_area) - self.verticalLayout_2.addLayout(self.horizontal_layout_reception) - self.mode_tabs.addTab(self.tab_reception, _fromUtf8("")) - self.tab_transmission = QtGui.QWidget() - self.tab_transmission.setObjectName(_fromUtf8("tab_transmission")) - self.verticalLayout_3 = QtGui.QVBoxLayout(self.tab_transmission) - self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3")) - self.horizontalLayout_7 = QtGui.QHBoxLayout() - self.horizontalLayout_7.setObjectName(_fromUtf8("horizontalLayout_7")) - self.verticalLayout_5 = QtGui.QVBoxLayout() - self.verticalLayout_5.setObjectName(_fromUtf8("verticalLayout_5")) - self.horizontalLayout_9 = QtGui.QHBoxLayout() - self.horizontalLayout_9.setObjectName(_fromUtf8("horizontalLayout_9")) - self.t_rbtn_USRP = QtGui.QRadioButton(self.tab_transmission) - self.t_rbtn_USRP.setEnabled(True) - self.t_rbtn_USRP.setChecked(True) - self.t_rbtn_USRP.setObjectName(_fromUtf8("t_rbtn_USRP")) - self.horizontalLayout_9.addWidget(self.t_rbtn_USRP) - spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_9.addItem(spacerItem13) - self.t_label_frequency = QtGui.QLabel(self.tab_transmission) - self.t_label_frequency.setObjectName(_fromUtf8("t_label_frequency")) - self.horizontalLayout_9.addWidget(self.t_label_frequency) - self.t_spinbox_frequency = QtGui.QSpinBox(self.tab_transmission) - self.t_spinbox_frequency.setMaximum(1000000000) - self.t_spinbox_frequency.setProperty("value", 201072000) - self.t_spinbox_frequency.setObjectName(_fromUtf8("t_spinbox_frequency")) - self.horizontalLayout_9.addWidget(self.t_spinbox_frequency) - self.label = QtGui.QLabel(self.tab_transmission) - self.label.setObjectName(_fromUtf8("label")) - self.horizontalLayout_9.addWidget(self.label) - self.verticalLayout_5.addLayout(self.horizontalLayout_9) - self.horizontalLayout_10 = QtGui.QHBoxLayout() - self.horizontalLayout_10.setObjectName(_fromUtf8("horizontalLayout_10")) - self.t_rbtn_File = QtGui.QRadioButton(self.tab_transmission) - self.t_rbtn_File.setObjectName(_fromUtf8("t_rbtn_File")) - self.horizontalLayout_10.addWidget(self.t_rbtn_File) - self.t_edit_file_name = QtGui.QLineEdit(self.tab_transmission) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_edit_file_name.sizePolicy().hasHeightForWidth()) - self.t_edit_file_name.setSizePolicy(sizePolicy) - self.t_edit_file_name.setObjectName(_fromUtf8("t_edit_file_name")) - self.horizontalLayout_10.addWidget(self.t_edit_file_name) - self.t_label_sink = QtGui.QLabel(self.tab_transmission) - self.t_label_sink.setEnabled(False) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_sink.sizePolicy().hasHeightForWidth()) - self.t_label_sink.setSizePolicy(sizePolicy) - self.t_label_sink.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_sink.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.t_label_sink.setFrameShape(QtGui.QFrame.Box) - self.t_label_sink.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_sink.setObjectName(_fromUtf8("t_label_sink")) - self.horizontalLayout_10.addWidget(self.t_label_sink) - self.t_btn_file_path = QtGui.QToolButton(self.tab_transmission) - self.t_btn_file_path.setEnabled(False) - self.t_btn_file_path.setObjectName(_fromUtf8("t_btn_file_path")) - self.horizontalLayout_10.addWidget(self.t_btn_file_path) - self.verticalLayout_5.addLayout(self.horizontalLayout_10) - self.horizontalLayout_31 = QtGui.QHBoxLayout() - self.horizontalLayout_31.setObjectName(_fromUtf8("horizontalLayout_31")) - spacerItem14 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_31.addItem(spacerItem14) - self.label_8 = QtGui.QLabel(self.tab_transmission) - self.label_8.setObjectName(_fromUtf8("label_8")) - self.horizontalLayout_31.addWidget(self.label_8) - self.t_spin_dab_mode = QtGui.QSpinBox(self.tab_transmission) - self.t_spin_dab_mode.setMinimum(1) - self.t_spin_dab_mode.setMaximum(4) - self.t_spin_dab_mode.setObjectName(_fromUtf8("t_spin_dab_mode")) - self.horizontalLayout_31.addWidget(self.t_spin_dab_mode) - self.verticalLayout_5.addLayout(self.horizontalLayout_31) - self.line_4 = QtGui.QFrame(self.tab_transmission) - self.line_4.setFrameShape(QtGui.QFrame.HLine) - self.line_4.setFrameShadow(QtGui.QFrame.Sunken) - self.line_4.setObjectName(_fromUtf8("line_4")) - self.verticalLayout_5.addWidget(self.line_4) - self.scrollArea = QtGui.QScrollArea(self.tab_transmission) - self.scrollArea.setWidgetResizable(True) - self.scrollArea.setObjectName(_fromUtf8("scrollArea")) - self.scrollAreaWidgetContents = QtGui.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 553, 1514)) - self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents")) - self.verticalLayout_9 = QtGui.QVBoxLayout(self.scrollAreaWidgetContents) - self.verticalLayout_9.setObjectName(_fromUtf8("verticalLayout_9")) - self.verticalLayout_4 = QtGui.QVBoxLayout() - self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4")) - self.formLayout_3 = QtGui.QFormLayout() - self.formLayout_3.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow) - self.formLayout_3.setObjectName(_fromUtf8("formLayout_3")) - self.line_2 = QtGui.QFrame(self.scrollAreaWidgetContents) - self.line_2.setFrameShape(QtGui.QFrame.HLine) - self.line_2.setFrameShadow(QtGui.QFrame.Sunken) - self.line_2.setObjectName(_fromUtf8("line_2")) - self.formLayout_3.setWidget(0, QtGui.QFormLayout.LabelRole, self.line_2) - self.t_label_heading_service_comp = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(15) - font.setBold(True) - font.setWeight(75) - self.t_label_heading_service_comp.setFont(font) - self.t_label_heading_service_comp.setObjectName(_fromUtf8("t_label_heading_service_comp")) - self.formLayout_3.setWidget(1, QtGui.QFormLayout.LabelRole, self.t_label_heading_service_comp) - self.t_label_comp1 = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp1.setFont(font) - self.t_label_comp1.setObjectName(_fromUtf8("t_label_comp1")) - self.formLayout_3.setWidget(2, QtGui.QFormLayout.LabelRole, self.t_label_comp1) - self.t_label_rate1 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate1.setObjectName(_fromUtf8("t_label_rate1")) - self.formLayout_3.setWidget(4, QtGui.QFormLayout.LabelRole, self.t_label_rate1) - self.t_spin_rate1 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate1.setMaximum(999) - self.t_spin_rate1.setProperty("value", 112) - self.t_spin_rate1.setObjectName(_fromUtf8("t_spin_rate1")) - self.formLayout_3.setWidget(4, QtGui.QFormLayout.FieldRole, self.t_spin_rate1) - self.t_label_prot1 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot1.setObjectName(_fromUtf8("t_label_prot1")) - self.formLayout_3.setWidget(5, QtGui.QFormLayout.LabelRole, self.t_label_prot1) - self.t_label_comp_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src1.setObjectName(_fromUtf8("t_label_comp_src1")) - self.formLayout_3.setWidget(7, QtGui.QFormLayout.LabelRole, self.t_label_comp_src1) - self.horizontalLayout_13 = QtGui.QHBoxLayout() - self.horizontalLayout_13.setObjectName(_fromUtf8("horizontalLayout_13")) - self.t_btn_record1 = QtGui.QPushButton(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_btn_record1.sizePolicy().hasHeightForWidth()) - self.t_btn_record1.setSizePolicy(sizePolicy) - self.t_btn_record1.setMinimumSize(QtCore.QSize(27, 27)) - self.t_btn_record1.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record1.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record1.setIcon(icon) - self.t_btn_record1.setDefault(False) - self.t_btn_record1.setFlat(False) - self.t_btn_record1.setObjectName(_fromUtf8("t_btn_record1")) - self.horizontalLayout_13.addWidget(self.t_btn_record1) - self.t_label_path_src1 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src1.sizePolicy().hasHeightForWidth()) - self.t_label_path_src1.setSizePolicy(sizePolicy) - self.t_label_path_src1.setMinimumSize(QtCore.QSize(100, 0)) - font = QtGui.QFont() - font.setUnderline(False) - font.setStrikeOut(False) - self.t_label_path_src1.setFont(font) - self.t_label_path_src1.setAutoFillBackground(False) - self.t_label_path_src1.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src1.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src1.setObjectName(_fromUtf8("t_label_path_src1")) - self.horizontalLayout_13.addWidget(self.t_label_path_src1) - self.t_btn_path_src1 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src1.setObjectName(_fromUtf8("t_btn_path_src1")) - self.horizontalLayout_13.addWidget(self.t_btn_path_src1) - self.formLayout_3.setLayout(7, QtGui.QFormLayout.FieldRole, self.horizontalLayout_13) - self.t_label_comp2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp2.setEnabled(True) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp2.setFont(font) - self.t_label_comp2.setObjectName(_fromUtf8("t_label_comp2")) - self.formLayout_3.setWidget(8, QtGui.QFormLayout.LabelRole, self.t_label_comp2) - self.t_label_rate2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate2.setObjectName(_fromUtf8("t_label_rate2")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.LabelRole, self.t_label_rate2) - self.t_spin_rate2 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate2.setMaximum(999) - self.t_spin_rate2.setProperty("value", 112) - self.t_spin_rate2.setObjectName(_fromUtf8("t_spin_rate2")) - self.formLayout_3.setWidget(10, QtGui.QFormLayout.FieldRole, self.t_spin_rate2) - self.t_label_prot2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot2.setObjectName(_fromUtf8("t_label_prot2")) - self.formLayout_3.setWidget(11, QtGui.QFormLayout.LabelRole, self.t_label_prot2) - self.t_label_comp_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src2.setObjectName(_fromUtf8("t_label_comp_src2")) - self.formLayout_3.setWidget(13, QtGui.QFormLayout.LabelRole, self.t_label_comp_src2) - self.horizontalLayout_14 = QtGui.QHBoxLayout() - self.horizontalLayout_14.setObjectName(_fromUtf8("horizontalLayout_14")) - self.t_btn_record2 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record2.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record2.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record2.setIcon(icon) - self.t_btn_record2.setObjectName(_fromUtf8("t_btn_record2")) - self.horizontalLayout_14.addWidget(self.t_btn_record2) - self.t_label_path_src2 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src2.sizePolicy().hasHeightForWidth()) - self.t_label_path_src2.setSizePolicy(sizePolicy) - self.t_label_path_src2.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src2.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src2.setObjectName(_fromUtf8("t_label_path_src2")) - self.horizontalLayout_14.addWidget(self.t_label_path_src2) - self.t_btn_path_src2 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src2.setObjectName(_fromUtf8("t_btn_path_src2")) - self.horizontalLayout_14.addWidget(self.t_btn_path_src2) - self.formLayout_3.setLayout(13, QtGui.QFormLayout.FieldRole, self.horizontalLayout_14) - self.t_label_comp3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp3.setEnabled(True) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp3.setFont(font) - self.t_label_comp3.setObjectName(_fromUtf8("t_label_comp3")) - self.formLayout_3.setWidget(14, QtGui.QFormLayout.LabelRole, self.t_label_comp3) - self.t_label_rate3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate3.setObjectName(_fromUtf8("t_label_rate3")) - self.formLayout_3.setWidget(16, QtGui.QFormLayout.LabelRole, self.t_label_rate3) - self.t_spin_rate3 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate3.setMaximum(999) - self.t_spin_rate3.setProperty("value", 112) - self.t_spin_rate3.setObjectName(_fromUtf8("t_spin_rate3")) - self.formLayout_3.setWidget(16, QtGui.QFormLayout.FieldRole, self.t_spin_rate3) - self.t_label_prot3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot3.setObjectName(_fromUtf8("t_label_prot3")) - self.formLayout_3.setWidget(17, QtGui.QFormLayout.LabelRole, self.t_label_prot3) - self.t_label_comp_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src3.setObjectName(_fromUtf8("t_label_comp_src3")) - self.formLayout_3.setWidget(19, QtGui.QFormLayout.LabelRole, self.t_label_comp_src3) - self.horizontalLayout_15 = QtGui.QHBoxLayout() - self.horizontalLayout_15.setObjectName(_fromUtf8("horizontalLayout_15")) - self.t_btn_record3 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record3.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record3.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record3.setIcon(icon) - self.t_btn_record3.setObjectName(_fromUtf8("t_btn_record3")) - self.horizontalLayout_15.addWidget(self.t_btn_record3) - self.t_label_path_src3 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src3.sizePolicy().hasHeightForWidth()) - self.t_label_path_src3.setSizePolicy(sizePolicy) - self.t_label_path_src3.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src3.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src3.setObjectName(_fromUtf8("t_label_path_src3")) - self.horizontalLayout_15.addWidget(self.t_label_path_src3) - self.t_btn_path_src3 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src3.setObjectName(_fromUtf8("t_btn_path_src3")) - self.horizontalLayout_15.addWidget(self.t_btn_path_src3) - self.formLayout_3.setLayout(19, QtGui.QFormLayout.FieldRole, self.horizontalLayout_15) - self.t_label_comp4 = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp4.setFont(font) - self.t_label_comp4.setObjectName(_fromUtf8("t_label_comp4")) - self.formLayout_3.setWidget(20, QtGui.QFormLayout.LabelRole, self.t_label_comp4) - self.t_label_rate4 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate4.setObjectName(_fromUtf8("t_label_rate4")) - self.formLayout_3.setWidget(22, QtGui.QFormLayout.LabelRole, self.t_label_rate4) - self.t_spin_rate4 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate4.setMaximum(999) - self.t_spin_rate4.setProperty("value", 112) - self.t_spin_rate4.setObjectName(_fromUtf8("t_spin_rate4")) - self.formLayout_3.setWidget(22, QtGui.QFormLayout.FieldRole, self.t_spin_rate4) - self.t_label_prot4 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot4.setObjectName(_fromUtf8("t_label_prot4")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.LabelRole, self.t_label_prot4) - self.t_label_comp_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src4.setObjectName(_fromUtf8("t_label_comp_src4")) - self.formLayout_3.setWidget(25, QtGui.QFormLayout.LabelRole, self.t_label_comp_src4) - self.horizontalLayout_16 = QtGui.QHBoxLayout() - self.horizontalLayout_16.setObjectName(_fromUtf8("horizontalLayout_16")) - self.t_btn_record4 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record4.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record4.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record4.setIcon(icon) - self.t_btn_record4.setObjectName(_fromUtf8("t_btn_record4")) - self.horizontalLayout_16.addWidget(self.t_btn_record4) - self.t_label_path_src4 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src4.sizePolicy().hasHeightForWidth()) - self.t_label_path_src4.setSizePolicy(sizePolicy) - self.t_label_path_src4.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src4.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src4.setObjectName(_fromUtf8("t_label_path_src4")) - self.horizontalLayout_16.addWidget(self.t_label_path_src4) - self.t_btn_path_src4 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src4.setObjectName(_fromUtf8("t_btn_path_src4")) - self.horizontalLayout_16.addWidget(self.t_btn_path_src4) - self.formLayout_3.setLayout(25, QtGui.QFormLayout.FieldRole, self.horizontalLayout_16) - self.t_label_comp5 = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp5.setFont(font) - self.t_label_comp5.setObjectName(_fromUtf8("t_label_comp5")) - self.formLayout_3.setWidget(26, QtGui.QFormLayout.LabelRole, self.t_label_comp5) - self.t_label_rate5 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate5.setObjectName(_fromUtf8("t_label_rate5")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.LabelRole, self.t_label_rate5) - self.t_spin_rate5 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate5.setMaximum(999) - self.t_spin_rate5.setProperty("value", 112) - self.t_spin_rate5.setObjectName(_fromUtf8("t_spin_rate5")) - self.formLayout_3.setWidget(28, QtGui.QFormLayout.FieldRole, self.t_spin_rate5) - self.t_label_prot5 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot5.setObjectName(_fromUtf8("t_label_prot5")) - self.formLayout_3.setWidget(29, QtGui.QFormLayout.LabelRole, self.t_label_prot5) - self.t_label_comp_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src5.setObjectName(_fromUtf8("t_label_comp_src5")) - self.formLayout_3.setWidget(31, QtGui.QFormLayout.LabelRole, self.t_label_comp_src5) - self.horizontalLayout_17 = QtGui.QHBoxLayout() - self.horizontalLayout_17.setObjectName(_fromUtf8("horizontalLayout_17")) - self.t_btn_record5 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record5.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record5.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record5.setIcon(icon) - self.t_btn_record5.setObjectName(_fromUtf8("t_btn_record5")) - self.horizontalLayout_17.addWidget(self.t_btn_record5) - self.t_label_path_src5 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src5.sizePolicy().hasHeightForWidth()) - self.t_label_path_src5.setSizePolicy(sizePolicy) - self.t_label_path_src5.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src5.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src5.setObjectName(_fromUtf8("t_label_path_src5")) - self.horizontalLayout_17.addWidget(self.t_label_path_src5) - self.t_btn_path_src5 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src5.setObjectName(_fromUtf8("t_btn_path_src5")) - self.horizontalLayout_17.addWidget(self.t_btn_path_src5) - self.formLayout_3.setLayout(31, QtGui.QFormLayout.FieldRole, self.horizontalLayout_17) - self.t_label_comp6 = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp6.setFont(font) - self.t_label_comp6.setObjectName(_fromUtf8("t_label_comp6")) - self.formLayout_3.setWidget(32, QtGui.QFormLayout.LabelRole, self.t_label_comp6) - self.t_label_rate6 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate6.setObjectName(_fromUtf8("t_label_rate6")) - self.formLayout_3.setWidget(34, QtGui.QFormLayout.LabelRole, self.t_label_rate6) - self.t_spin_rate6 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate6.setMaximum(999) - self.t_spin_rate6.setProperty("value", 112) - self.t_spin_rate6.setObjectName(_fromUtf8("t_spin_rate6")) - self.formLayout_3.setWidget(34, QtGui.QFormLayout.FieldRole, self.t_spin_rate6) - self.t_label_prot6 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot6.setObjectName(_fromUtf8("t_label_prot6")) - self.formLayout_3.setWidget(35, QtGui.QFormLayout.LabelRole, self.t_label_prot6) - self.t_label_comp_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src6.setObjectName(_fromUtf8("t_label_comp_src6")) - self.formLayout_3.setWidget(37, QtGui.QFormLayout.LabelRole, self.t_label_comp_src6) - self.horizontalLayout_18 = QtGui.QHBoxLayout() - self.horizontalLayout_18.setObjectName(_fromUtf8("horizontalLayout_18")) - self.t_btn_record6 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record6.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record6.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record6.setIcon(icon) - self.t_btn_record6.setObjectName(_fromUtf8("t_btn_record6")) - self.horizontalLayout_18.addWidget(self.t_btn_record6) - self.t_label_path_src6 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src6.sizePolicy().hasHeightForWidth()) - self.t_label_path_src6.setSizePolicy(sizePolicy) - self.t_label_path_src6.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src6.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src6.setObjectName(_fromUtf8("t_label_path_src6")) - self.horizontalLayout_18.addWidget(self.t_label_path_src6) - self.t_btn_path_src6 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src6.setObjectName(_fromUtf8("t_btn_path_src6")) - self.horizontalLayout_18.addWidget(self.t_btn_path_src6) - self.formLayout_3.setLayout(37, QtGui.QFormLayout.FieldRole, self.horizontalLayout_18) - self.t_label_comp7 = QtGui.QLabel(self.scrollAreaWidgetContents) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.t_label_comp7.setFont(font) - self.t_label_comp7.setObjectName(_fromUtf8("t_label_comp7")) - self.formLayout_3.setWidget(38, QtGui.QFormLayout.LabelRole, self.t_label_comp7) - self.t_label_rate7 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_rate7.setObjectName(_fromUtf8("t_label_rate7")) - self.formLayout_3.setWidget(40, QtGui.QFormLayout.LabelRole, self.t_label_rate7) - self.t_spin_rate7 = QtGui.QSpinBox(self.scrollAreaWidgetContents) - self.t_spin_rate7.setMaximum(999) - self.t_spin_rate7.setProperty("value", 112) - self.t_spin_rate7.setObjectName(_fromUtf8("t_spin_rate7")) - self.formLayout_3.setWidget(40, QtGui.QFormLayout.FieldRole, self.t_spin_rate7) - self.t_label_prot7 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_prot7.setObjectName(_fromUtf8("t_label_prot7")) - self.formLayout_3.setWidget(41, QtGui.QFormLayout.LabelRole, self.t_label_prot7) - self.t_label_comp_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_comp_src7.setObjectName(_fromUtf8("t_label_comp_src7")) - self.formLayout_3.setWidget(43, QtGui.QFormLayout.LabelRole, self.t_label_comp_src7) - self.horizontalLayout_19 = QtGui.QHBoxLayout() - self.horizontalLayout_19.setObjectName(_fromUtf8("horizontalLayout_19")) - self.t_btn_record7 = QtGui.QPushButton(self.scrollAreaWidgetContents) - self.t_btn_record7.setMaximumSize(QtCore.QSize(27, 27)) - self.t_btn_record7.setText(_fromUtf8("")) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record")) - self.t_btn_record7.setIcon(icon) - self.t_btn_record7.setObjectName(_fromUtf8("t_btn_record7")) - self.horizontalLayout_19.addWidget(self.t_btn_record7) - self.t_label_path_src7 = QtGui.QLabel(self.scrollAreaWidgetContents) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.t_label_path_src7.sizePolicy().hasHeightForWidth()) - self.t_label_path_src7.setSizePolicy(sizePolicy) - self.t_label_path_src7.setMinimumSize(QtCore.QSize(100, 0)) - self.t_label_path_src7.setFrameShape(QtGui.QFrame.Box) - self.t_label_path_src7.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.t_label_path_src7.setObjectName(_fromUtf8("t_label_path_src7")) - self.horizontalLayout_19.addWidget(self.t_label_path_src7) - self.t_btn_path_src7 = QtGui.QToolButton(self.scrollAreaWidgetContents) - self.t_btn_path_src7.setObjectName(_fromUtf8("t_btn_path_src7")) - self.horizontalLayout_19.addWidget(self.t_btn_path_src7) - self.formLayout_3.setLayout(43, QtGui.QFormLayout.FieldRole, self.horizontalLayout_19) - self.t_label_label1 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label1.setObjectName(_fromUtf8("t_label_label1")) - self.formLayout_3.setWidget(3, QtGui.QFormLayout.LabelRole, self.t_label_label1) - self.t_label_label2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label2.setObjectName(_fromUtf8("t_label_label2")) - self.formLayout_3.setWidget(9, QtGui.QFormLayout.LabelRole, self.t_label_label2) - self.t_label_label3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label3.setObjectName(_fromUtf8("t_label_label3")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.LabelRole, self.t_label_label3) - self.t_label_label4 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label4.setObjectName(_fromUtf8("t_label_label4")) - self.formLayout_3.setWidget(21, QtGui.QFormLayout.LabelRole, self.t_label_label4) - self.t_label_label5 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label5.setObjectName(_fromUtf8("t_label_label5")) - self.formLayout_3.setWidget(27, QtGui.QFormLayout.LabelRole, self.t_label_label5) - self.t_label_label6 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label6.setObjectName(_fromUtf8("t_label_label6")) - self.formLayout_3.setWidget(33, QtGui.QFormLayout.LabelRole, self.t_label_label6) - self.t_label_label7 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_label7.setObjectName(_fromUtf8("t_label_label7")) - self.formLayout_3.setWidget(39, QtGui.QFormLayout.LabelRole, self.t_label_label7) - self.t_edit_service_label1 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label1.setObjectName(_fromUtf8("t_edit_service_label1")) - self.formLayout_3.setWidget(3, QtGui.QFormLayout.FieldRole, self.t_edit_service_label1) - self.t_edit_service_label2 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label2.setObjectName(_fromUtf8("t_edit_service_label2")) - self.formLayout_3.setWidget(9, QtGui.QFormLayout.FieldRole, self.t_edit_service_label2) - self.t_edit_service_label3 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label3.setObjectName(_fromUtf8("t_edit_service_label3")) - self.formLayout_3.setWidget(15, QtGui.QFormLayout.FieldRole, self.t_edit_service_label3) - self.t_edit_service_label4 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label4.setObjectName(_fromUtf8("t_edit_service_label4")) - self.formLayout_3.setWidget(21, QtGui.QFormLayout.FieldRole, self.t_edit_service_label4) - self.t_edit_service_label5 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label5.setObjectName(_fromUtf8("t_edit_service_label5")) - self.formLayout_3.setWidget(27, QtGui.QFormLayout.FieldRole, self.t_edit_service_label5) - self.t_edit_service_label6 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label6.setObjectName(_fromUtf8("t_edit_service_label6")) - self.formLayout_3.setWidget(33, QtGui.QFormLayout.FieldRole, self.t_edit_service_label6) - self.t_edit_service_label7 = QtGui.QLineEdit(self.scrollAreaWidgetContents) - self.t_edit_service_label7.setObjectName(_fromUtf8("t_edit_service_label7")) - self.formLayout_3.setWidget(39, QtGui.QFormLayout.FieldRole, self.t_edit_service_label7) - self.t_layout_combo_dabplus1 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus1.setObjectName(_fromUtf8("t_layout_combo_dabplus1")) - spacerItem15 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus1.addItem(spacerItem15) - self.t_combo_dabplus1 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus1.setObjectName(_fromUtf8("t_combo_dabplus1")) - self.t_combo_dabplus1.addItem(_fromUtf8("")) - self.t_combo_dabplus1.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus1.addWidget(self.t_combo_dabplus1) - self.formLayout_3.setLayout(2, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus1) - self.t_layout_combo_dabplus2 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus2.setObjectName(_fromUtf8("t_layout_combo_dabplus2")) - spacerItem16 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus2.addItem(spacerItem16) - self.t_combo_dabplus2 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus2.setObjectName(_fromUtf8("t_combo_dabplus2")) - self.t_combo_dabplus2.addItem(_fromUtf8("")) - self.t_combo_dabplus2.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus2.addWidget(self.t_combo_dabplus2) - self.formLayout_3.setLayout(8, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus2) - self.t_layout_combo_dabplus3 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus3.setObjectName(_fromUtf8("t_layout_combo_dabplus3")) - spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus3.addItem(spacerItem17) - self.t_combo_dabplus3 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus3.setObjectName(_fromUtf8("t_combo_dabplus3")) - self.t_combo_dabplus3.addItem(_fromUtf8("")) - self.t_combo_dabplus3.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus3.addWidget(self.t_combo_dabplus3) - self.formLayout_3.setLayout(14, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus3) - self.t_layout_combo_dabplus4 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus4.setObjectName(_fromUtf8("t_layout_combo_dabplus4")) - spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus4.addItem(spacerItem18) - self.t_combo_dabplus4 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus4.setObjectName(_fromUtf8("t_combo_dabplus4")) - self.t_combo_dabplus4.addItem(_fromUtf8("")) - self.t_combo_dabplus4.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus4.addWidget(self.t_combo_dabplus4) - self.formLayout_3.setLayout(20, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus4) - self.t_layout_combo_dabplus5 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus5.setObjectName(_fromUtf8("t_layout_combo_dabplus5")) - spacerItem19 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus5.addItem(spacerItem19) - self.t_combo_dabplus5 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus5.setObjectName(_fromUtf8("t_combo_dabplus5")) - self.t_combo_dabplus5.addItem(_fromUtf8("")) - self.t_combo_dabplus5.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus5.addWidget(self.t_combo_dabplus5) - self.formLayout_3.setLayout(26, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus5) - self.t_layout_combo_dabplus6 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus6.setObjectName(_fromUtf8("t_layout_combo_dabplus6")) - spacerItem20 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus6.addItem(spacerItem20) - self.t_combo_dabplus6 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus6.setObjectName(_fromUtf8("t_combo_dabplus6")) - self.t_combo_dabplus6.addItem(_fromUtf8("")) - self.t_combo_dabplus6.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus6.addWidget(self.t_combo_dabplus6) - self.formLayout_3.setLayout(32, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus6) - self.t_layout_combo_dabplus7 = QtGui.QHBoxLayout() - self.t_layout_combo_dabplus7.setObjectName(_fromUtf8("t_layout_combo_dabplus7")) - spacerItem21 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.t_layout_combo_dabplus7.addItem(spacerItem21) - self.t_combo_dabplus7 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_dabplus7.setObjectName(_fromUtf8("t_combo_dabplus7")) - self.t_combo_dabplus7.addItem(_fromUtf8("")) - self.t_combo_dabplus7.addItem(_fromUtf8("")) - self.t_layout_combo_dabplus7.addWidget(self.t_combo_dabplus7) - self.formLayout_3.setLayout(38, QtGui.QFormLayout.FieldRole, self.t_layout_combo_dabplus7) - self.t_combo_prot1 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot1.setObjectName(_fromUtf8("t_combo_prot1")) - self.t_combo_prot1.addItem(_fromUtf8("")) - self.t_combo_prot1.addItem(_fromUtf8("")) - self.t_combo_prot1.addItem(_fromUtf8("")) - self.t_combo_prot1.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_combo_prot1) - self.t_combo_prot2 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot2.setObjectName(_fromUtf8("t_combo_prot2")) - self.t_combo_prot2.addItem(_fromUtf8("")) - self.t_combo_prot2.addItem(_fromUtf8("")) - self.t_combo_prot2.addItem(_fromUtf8("")) - self.t_combo_prot2.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(11, QtGui.QFormLayout.FieldRole, self.t_combo_prot2) - self.t_combo_prot3 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot3.setObjectName(_fromUtf8("t_combo_prot3")) - self.t_combo_prot3.addItem(_fromUtf8("")) - self.t_combo_prot3.addItem(_fromUtf8("")) - self.t_combo_prot3.addItem(_fromUtf8("")) - self.t_combo_prot3.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(17, QtGui.QFormLayout.FieldRole, self.t_combo_prot3) - self.t_combo_prot4 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot4.setObjectName(_fromUtf8("t_combo_prot4")) - self.t_combo_prot4.addItem(_fromUtf8("")) - self.t_combo_prot4.addItem(_fromUtf8("")) - self.t_combo_prot4.addItem(_fromUtf8("")) - self.t_combo_prot4.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(23, QtGui.QFormLayout.FieldRole, self.t_combo_prot4) - self.t_combo_prot5 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot5.setObjectName(_fromUtf8("t_combo_prot5")) - self.t_combo_prot5.addItem(_fromUtf8("")) - self.t_combo_prot5.addItem(_fromUtf8("")) - self.t_combo_prot5.addItem(_fromUtf8("")) - self.t_combo_prot5.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(29, QtGui.QFormLayout.FieldRole, self.t_combo_prot5) - self.t_combo_prot6 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot6.setObjectName(_fromUtf8("t_combo_prot6")) - self.t_combo_prot6.addItem(_fromUtf8("")) - self.t_combo_prot6.addItem(_fromUtf8("")) - self.t_combo_prot6.addItem(_fromUtf8("")) - self.t_combo_prot6.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(35, QtGui.QFormLayout.FieldRole, self.t_combo_prot6) - self.t_combo_prot7 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_prot7.setObjectName(_fromUtf8("t_combo_prot7")) - self.t_combo_prot7.addItem(_fromUtf8("")) - self.t_combo_prot7.addItem(_fromUtf8("")) - self.t_combo_prot7.addItem(_fromUtf8("")) - self.t_combo_prot7.addItem(_fromUtf8("")) - self.formLayout_3.setWidget(41, QtGui.QFormLayout.FieldRole, self.t_combo_prot7) - self.t_label_audio_rate1 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate1.setObjectName(_fromUtf8("t_label_audio_rate1")) - self.formLayout_3.setWidget(6, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate1) - self.t_label_audio_rate2 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate2.setObjectName(_fromUtf8("t_label_audio_rate2")) - self.formLayout_3.setWidget(12, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate2) - self.t_label_audio_rate3 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate3.setObjectName(_fromUtf8("t_label_audio_rate3")) - self.formLayout_3.setWidget(18, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate3) - self.t_label_audio_rate4 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate4.setObjectName(_fromUtf8("t_label_audio_rate4")) - self.formLayout_3.setWidget(24, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate4) - self.t_label_audio_rate5 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate5.setObjectName(_fromUtf8("t_label_audio_rate5")) - self.formLayout_3.setWidget(30, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate5) - self.t_label_audio_rate6 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate6.setObjectName(_fromUtf8("t_label_audio_rate6")) - self.formLayout_3.setWidget(36, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate6) - self.t_label_audio_rate7 = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_audio_rate7.setObjectName(_fromUtf8("t_label_audio_rate7")) - self.formLayout_3.setWidget(42, QtGui.QFormLayout.LabelRole, self.t_label_audio_rate7) - self.horizontalLayout_2 = QtGui.QHBoxLayout() - self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2")) - self.t_combo_stereo1 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo1.setObjectName(_fromUtf8("t_combo_stereo1")) - self.t_combo_stereo1.addItem(_fromUtf8("")) - self.t_combo_stereo1.addItem(_fromUtf8("")) - self.horizontalLayout_2.addWidget(self.t_combo_stereo1) - self.t_combo_audio_rate1 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate1.setObjectName(_fromUtf8("t_combo_audio_rate1")) - self.t_combo_audio_rate1.addItem(_fromUtf8("")) - self.t_combo_audio_rate1.addItem(_fromUtf8("")) - self.horizontalLayout_2.addWidget(self.t_combo_audio_rate1) - self.t_combo_audio_rate_dab1 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab1.setObjectName(_fromUtf8("t_combo_audio_rate_dab1")) - self.t_combo_audio_rate_dab1.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab1.addItem(_fromUtf8("")) - self.horizontalLayout_2.addWidget(self.t_combo_audio_rate_dab1) - self.formLayout_3.setLayout(6, QtGui.QFormLayout.FieldRole, self.horizontalLayout_2) - self.horizontalLayout_33 = QtGui.QHBoxLayout() - self.horizontalLayout_33.setObjectName(_fromUtf8("horizontalLayout_33")) - self.t_combo_stereo2 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo2.setObjectName(_fromUtf8("t_combo_stereo2")) - self.t_combo_stereo2.addItem(_fromUtf8("")) - self.t_combo_stereo2.addItem(_fromUtf8("")) - self.horizontalLayout_33.addWidget(self.t_combo_stereo2) - self.t_combo_audio_rate2 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate2.setObjectName(_fromUtf8("t_combo_audio_rate2")) - self.t_combo_audio_rate2.addItem(_fromUtf8("")) - self.t_combo_audio_rate2.addItem(_fromUtf8("")) - self.horizontalLayout_33.addWidget(self.t_combo_audio_rate2) - self.t_combo_audio_rate_dab2 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab2.setObjectName(_fromUtf8("t_combo_audio_rate_dab2")) - self.t_combo_audio_rate_dab2.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab2.addItem(_fromUtf8("")) - self.horizontalLayout_33.addWidget(self.t_combo_audio_rate_dab2) - self.formLayout_3.setLayout(12, QtGui.QFormLayout.FieldRole, self.horizontalLayout_33) - self.horizontalLayout_34 = QtGui.QHBoxLayout() - self.horizontalLayout_34.setObjectName(_fromUtf8("horizontalLayout_34")) - self.t_combo_stereo3 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo3.setObjectName(_fromUtf8("t_combo_stereo3")) - self.t_combo_stereo3.addItem(_fromUtf8("")) - self.t_combo_stereo3.addItem(_fromUtf8("")) - self.horizontalLayout_34.addWidget(self.t_combo_stereo3) - self.t_combo_audio_rate3 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate3.setObjectName(_fromUtf8("t_combo_audio_rate3")) - self.t_combo_audio_rate3.addItem(_fromUtf8("")) - self.t_combo_audio_rate3.addItem(_fromUtf8("")) - self.horizontalLayout_34.addWidget(self.t_combo_audio_rate3) - self.t_combo_audio_rate_dab3 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab3.setObjectName(_fromUtf8("t_combo_audio_rate_dab3")) - self.t_combo_audio_rate_dab3.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab3.addItem(_fromUtf8("")) - self.horizontalLayout_34.addWidget(self.t_combo_audio_rate_dab3) - self.formLayout_3.setLayout(18, QtGui.QFormLayout.FieldRole, self.horizontalLayout_34) - self.horizontalLayout_35 = QtGui.QHBoxLayout() - self.horizontalLayout_35.setObjectName(_fromUtf8("horizontalLayout_35")) - self.t_combo_stereo4 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo4.setObjectName(_fromUtf8("t_combo_stereo4")) - self.t_combo_stereo4.addItem(_fromUtf8("")) - self.t_combo_stereo4.addItem(_fromUtf8("")) - self.horizontalLayout_35.addWidget(self.t_combo_stereo4) - self.t_combo_audio_rate4 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate4.setObjectName(_fromUtf8("t_combo_audio_rate4")) - self.t_combo_audio_rate4.addItem(_fromUtf8("")) - self.t_combo_audio_rate4.addItem(_fromUtf8("")) - self.horizontalLayout_35.addWidget(self.t_combo_audio_rate4) - self.t_combo_audio_rate_dab4 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab4.setObjectName(_fromUtf8("t_combo_audio_rate_dab4")) - self.t_combo_audio_rate_dab4.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab4.addItem(_fromUtf8("")) - self.horizontalLayout_35.addWidget(self.t_combo_audio_rate_dab4) - self.formLayout_3.setLayout(24, QtGui.QFormLayout.FieldRole, self.horizontalLayout_35) - self.horizontalLayout_36 = QtGui.QHBoxLayout() - self.horizontalLayout_36.setObjectName(_fromUtf8("horizontalLayout_36")) - self.t_combo_stereo5 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo5.setObjectName(_fromUtf8("t_combo_stereo5")) - self.t_combo_stereo5.addItem(_fromUtf8("")) - self.t_combo_stereo5.addItem(_fromUtf8("")) - self.horizontalLayout_36.addWidget(self.t_combo_stereo5) - self.t_combo_audio_rate5 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate5.setObjectName(_fromUtf8("t_combo_audio_rate5")) - self.t_combo_audio_rate5.addItem(_fromUtf8("")) - self.t_combo_audio_rate5.addItem(_fromUtf8("")) - self.horizontalLayout_36.addWidget(self.t_combo_audio_rate5) - self.t_combo_audio_rate_dab5 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab5.setObjectName(_fromUtf8("t_combo_audio_rate_dab5")) - self.t_combo_audio_rate_dab5.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab5.addItem(_fromUtf8("")) - self.horizontalLayout_36.addWidget(self.t_combo_audio_rate_dab5) - self.formLayout_3.setLayout(30, QtGui.QFormLayout.FieldRole, self.horizontalLayout_36) - self.horizontalLayout_37 = QtGui.QHBoxLayout() - self.horizontalLayout_37.setObjectName(_fromUtf8("horizontalLayout_37")) - self.t_combo_stereo6 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo6.setObjectName(_fromUtf8("t_combo_stereo6")) - self.t_combo_stereo6.addItem(_fromUtf8("")) - self.t_combo_stereo6.addItem(_fromUtf8("")) - self.horizontalLayout_37.addWidget(self.t_combo_stereo6) - self.t_combo_audio_rate6 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate6.setObjectName(_fromUtf8("t_combo_audio_rate6")) - self.t_combo_audio_rate6.addItem(_fromUtf8("")) - self.t_combo_audio_rate6.addItem(_fromUtf8("")) - self.horizontalLayout_37.addWidget(self.t_combo_audio_rate6) - self.t_combo_audio_rate_dab6 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab6.setObjectName(_fromUtf8("t_combo_audio_rate_dab6")) - self.t_combo_audio_rate_dab6.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab6.addItem(_fromUtf8("")) - self.horizontalLayout_37.addWidget(self.t_combo_audio_rate_dab6) - self.formLayout_3.setLayout(36, QtGui.QFormLayout.FieldRole, self.horizontalLayout_37) - self.horizontalLayout_38 = QtGui.QHBoxLayout() - self.horizontalLayout_38.setObjectName(_fromUtf8("horizontalLayout_38")) - self.t_combo_stereo7 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_stereo7.setObjectName(_fromUtf8("t_combo_stereo7")) - self.t_combo_stereo7.addItem(_fromUtf8("")) - self.t_combo_stereo7.addItem(_fromUtf8("")) - self.horizontalLayout_38.addWidget(self.t_combo_stereo7) - self.t_combo_audio_rate7 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate7.setObjectName(_fromUtf8("t_combo_audio_rate7")) - self.t_combo_audio_rate7.addItem(_fromUtf8("")) - self.t_combo_audio_rate7.addItem(_fromUtf8("")) - self.horizontalLayout_38.addWidget(self.t_combo_audio_rate7) - self.t_combo_audio_rate_dab7 = QtGui.QComboBox(self.scrollAreaWidgetContents) - self.t_combo_audio_rate_dab7.setObjectName(_fromUtf8("t_combo_audio_rate_dab7")) - self.t_combo_audio_rate_dab7.addItem(_fromUtf8("")) - self.t_combo_audio_rate_dab7.addItem(_fromUtf8("")) - self.horizontalLayout_38.addWidget(self.t_combo_audio_rate_dab7) - self.formLayout_3.setLayout(42, QtGui.QFormLayout.FieldRole, self.horizontalLayout_38) - self.verticalLayout_4.addLayout(self.formLayout_3) - self.line_15 = QtGui.QFrame(self.scrollAreaWidgetContents) - self.line_15.setFrameShape(QtGui.QFrame.HLine) - self.line_15.setFrameShadow(QtGui.QFrame.Sunken) - self.line_15.setObjectName(_fromUtf8("line_15")) - self.verticalLayout_4.addWidget(self.line_15) - self.t_label_increase_num_subch_info = QtGui.QLabel(self.scrollAreaWidgetContents) - self.t_label_increase_num_subch_info.setEnabled(False) - font = QtGui.QFont() - font.setItalic(True) - font.setStrikeOut(False) - self.t_label_increase_num_subch_info.setFont(font) - self.t_label_increase_num_subch_info.setObjectName(_fromUtf8("t_label_increase_num_subch_info")) - self.verticalLayout_4.addWidget(self.t_label_increase_num_subch_info) - self.verticalLayout_9.addLayout(self.verticalLayout_4) - self.scrollArea.setWidget(self.scrollAreaWidgetContents) - self.verticalLayout_5.addWidget(self.scrollArea) - self.horizontalLayout_7.addLayout(self.verticalLayout_5) - self.line_3 = QtGui.QFrame(self.tab_transmission) - self.line_3.setFrameShape(QtGui.QFrame.VLine) - self.line_3.setFrameShadow(QtGui.QFrame.Sunken) - self.line_3.setObjectName(_fromUtf8("line_3")) - self.horizontalLayout_7.addWidget(self.line_3) - self.verticalLayout_8 = QtGui.QVBoxLayout() - self.verticalLayout_8.setObjectName(_fromUtf8("verticalLayout_8")) - self.line_5 = QtGui.QFrame(self.tab_transmission) - self.line_5.setFrameShape(QtGui.QFrame.HLine) - self.line_5.setFrameShadow(QtGui.QFrame.Sunken) - self.line_5.setObjectName(_fromUtf8("line_5")) - self.verticalLayout_8.addWidget(self.line_5) - self.formLayout_2 = QtGui.QFormLayout() - self.formLayout_2.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow) - self.formLayout_2.setObjectName(_fromUtf8("formLayout_2")) - self.label_12 = QtGui.QLabel(self.tab_transmission) - font = QtGui.QFont() - font.setPointSize(13) - font.setBold(True) - font.setWeight(75) - self.label_12.setFont(font) - self.label_12.setObjectName(_fromUtf8("label_12")) - self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_12) - self.label_13 = QtGui.QLabel(self.tab_transmission) - self.label_13.setObjectName(_fromUtf8("label_13")) - self.formLayout_2.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_13) - self.t_edit_ensemble_label = QtGui.QLineEdit(self.tab_transmission) - self.t_edit_ensemble_label.setObjectName(_fromUtf8("t_edit_ensemble_label")) - self.formLayout_2.setWidget(1, QtGui.QFormLayout.FieldRole, self.t_edit_ensemble_label) - self.label_14 = QtGui.QLabel(self.tab_transmission) - self.label_14.setObjectName(_fromUtf8("label_14")) - self.formLayout_2.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_14) - self.t_combo_country = QtGui.QComboBox(self.tab_transmission) - self.t_combo_country.setObjectName(_fromUtf8("t_combo_country")) - self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.t_combo_country) - self.line = QtGui.QFrame(self.tab_transmission) - self.line.setFrameShape(QtGui.QFrame.HLine) - self.line.setFrameShadow(QtGui.QFrame.Sunken) - self.line.setObjectName(_fromUtf8("line")) - self.formLayout_2.setWidget(3, QtGui.QFormLayout.LabelRole, self.line) - self.label_17 = QtGui.QLabel(self.tab_transmission) - self.label_17.setObjectName(_fromUtf8("label_17")) - self.formLayout_2.setWidget(4, QtGui.QFormLayout.LabelRole, self.label_17) - self.t_spin_num_subch = QtGui.QSpinBox(self.tab_transmission) - self.t_spin_num_subch.setMaximum(4) - self.t_spin_num_subch.setProperty("value", 1) - self.t_spin_num_subch.setObjectName(_fromUtf8("t_spin_num_subch")) - self.formLayout_2.setWidget(4, QtGui.QFormLayout.FieldRole, self.t_spin_num_subch) - self.label_23 = QtGui.QLabel(self.tab_transmission) - self.label_23.setObjectName(_fromUtf8("label_23")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.LabelRole, self.label_23) - self.t_combo_language = QtGui.QComboBox(self.tab_transmission) - self.t_combo_language.setObjectName(_fromUtf8("t_combo_language")) - self.formLayout_2.setWidget(5, QtGui.QFormLayout.FieldRole, self.t_combo_language) - spacerItem22 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.formLayout_2.setItem(6, QtGui.QFormLayout.FieldRole, spacerItem22) - self.verticalLayout_8.addLayout(self.formLayout_2) - self.horizontalLayout_22 = QtGui.QHBoxLayout() - self.horizontalLayout_22.setObjectName(_fromUtf8("horizontalLayout_22")) - self.t_btn_init = QtGui.QPushButton(self.tab_transmission) - icon = QtGui.QIcon.fromTheme(_fromUtf8("network-transmit")) - self.t_btn_init.setIcon(icon) - self.t_btn_init.setObjectName(_fromUtf8("t_btn_init")) - self.horizontalLayout_22.addWidget(self.t_btn_init) - self.label_22 = QtGui.QLabel(self.tab_transmission) - self.label_22.setObjectName(_fromUtf8("label_22")) - self.horizontalLayout_22.addWidget(self.label_22) - self.t_label_status = QtGui.QLabel(self.tab_transmission) - self.t_label_status.setObjectName(_fromUtf8("t_label_status")) - self.horizontalLayout_22.addWidget(self.t_label_status) - spacerItem23 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_22.addItem(spacerItem23) - self.verticalLayout_8.addLayout(self.horizontalLayout_22) - self.horizontalLayout_39 = QtGui.QHBoxLayout() - self.horizontalLayout_39.setObjectName(_fromUtf8("horizontalLayout_39")) - self.label_9 = QtGui.QLabel(self.tab_transmission) - self.label_9.setObjectName(_fromUtf8("label_9")) - self.horizontalLayout_39.addWidget(self.label_9) - self.tx_gain = QtGui.QSpinBox(self.tab_transmission) - self.tx_gain.setMaximum(80) - self.tx_gain.setProperty("value", 30) - self.tx_gain.setObjectName(_fromUtf8("tx_gain")) - self.horizontalLayout_39.addWidget(self.tx_gain) - spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) - self.horizontalLayout_39.addItem(spacerItem24) - self.verticalLayout_8.addLayout(self.horizontalLayout_39) - self.line_10 = QtGui.QFrame(self.tab_transmission) - self.line_10.setFrameShape(QtGui.QFrame.HLine) - self.line_10.setFrameShadow(QtGui.QFrame.Sunken) - self.line_10.setObjectName(_fromUtf8("line_10")) - self.verticalLayout_8.addWidget(self.line_10) - self.label_20 = QtGui.QLabel(self.tab_transmission) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_20.setFont(font) - self.label_20.setObjectName(_fromUtf8("label_20")) - self.verticalLayout_8.addWidget(self.label_20) - self.horizontalLayout_20 = QtGui.QHBoxLayout() - self.horizontalLayout_20.setObjectName(_fromUtf8("horizontalLayout_20")) - self.label_18 = QtGui.QLabel(self.tab_transmission) - self.label_18.setObjectName(_fromUtf8("label_18")) - self.horizontalLayout_20.addWidget(self.label_18) - self.t_spin_listen_to_component = QtGui.QSpinBox(self.tab_transmission) - self.t_spin_listen_to_component.setMinimum(1) - self.t_spin_listen_to_component.setMaximum(1) - self.t_spin_listen_to_component.setProperty("value", 1) - self.t_spin_listen_to_component.setObjectName(_fromUtf8("t_spin_listen_to_component")) - self.horizontalLayout_20.addWidget(self.t_spin_listen_to_component) - self.verticalLayout_8.addLayout(self.horizontalLayout_20) - self.horizontalLayout_11 = QtGui.QHBoxLayout() - self.horizontalLayout_11.setObjectName(_fromUtf8("horizontalLayout_11")) - self.t_btn_play = QtGui.QPushButton(self.tab_transmission) - self.t_btn_play.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-start")) - self.t_btn_play.setIcon(icon) - self.t_btn_play.setObjectName(_fromUtf8("t_btn_play")) - self.horizontalLayout_11.addWidget(self.t_btn_play) - self.t_btn_stop = QtGui.QPushButton(self.tab_transmission) - self.t_btn_stop.setEnabled(False) - icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-stop")) - self.t_btn_stop.setIcon(icon) - self.t_btn_stop.setObjectName(_fromUtf8("t_btn_stop")) - self.horizontalLayout_11.addWidget(self.t_btn_stop) - self.verticalLayout_8.addLayout(self.horizontalLayout_11) - self.horizontalLayout_12 = QtGui.QHBoxLayout() - self.horizontalLayout_12.setObjectName(_fromUtf8("horizontalLayout_12")) - self.label_19 = QtGui.QLabel(self.tab_transmission) - self.label_19.setEnabled(False) - self.label_19.setObjectName(_fromUtf8("label_19")) - self.horizontalLayout_12.addWidget(self.label_19) - self.t_slider_volume = QtGui.QSlider(self.tab_transmission) - self.t_slider_volume.setEnabled(False) - self.t_slider_volume.setMaximum(100) - self.t_slider_volume.setProperty("value", 80) - self.t_slider_volume.setOrientation(QtCore.Qt.Horizontal) - self.t_slider_volume.setObjectName(_fromUtf8("t_slider_volume")) - self.horizontalLayout_12.addWidget(self.t_slider_volume) - self.verticalLayout_8.addLayout(self.horizontalLayout_12) - self.horizontalLayout_7.addLayout(self.verticalLayout_8) - self.verticalLayout_3.addLayout(self.horizontalLayout_7) - self.mode_tabs.addTab(self.tab_transmission, _fromUtf8("")) - self.verticalLayout.addWidget(self.mode_tabs) - MainWindow.setCentralWidget(self.centralwidget) - self.statusBar = QtGui.QStatusBar(MainWindow) - self.statusBar.setAutoFillBackground(False) - self.statusBar.setObjectName(_fromUtf8("statusBar")) - MainWindow.setStatusBar(self.statusBar) - - self.retranslateUi(MainWindow) - self.mode_tabs.setCurrentIndex(0) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) - self.label_5.setText(_translate("MainWindow", "


", None)) - self.label_logo.setText(_translate("MainWindow", "

DABstep

", None)) - self.btn_dev_mode_close.setText(_translate("MainWindow", "Developer Mode", None)) - self.btn_dev_mode_open.setText(_translate("MainWindow", "Developer Mode", None)) - self.rbtn_USRP.setText(_translate("MainWindow", "USRP", None)) - self.rbtn_RTL.setText(_translate("MainWindow", "RTL-SDR", None)) - self.label_frequency.setText(_translate("MainWindow", "Frequency", None)) - self.label_4.setText(_translate("MainWindow", "Hz ", None)) - self.rbtn_File.setText(_translate("MainWindow", "File", None)) - self.label_path.setText(_translate("MainWindow", "select path", None)) - self.btn_file_path.setText(_translate("MainWindow", "...", None)) - self.label_6.setText(_translate("MainWindow", "Transmission Mode", None)) - item = self.table_mci.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "ID", None)) - item = self.table_mci.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Component", None)) - item = self.table_mci.horizontalHeaderItem(2) - item.setText(_translate("MainWindow", "Mode", None)) - item = self.table_mci.horizontalHeaderItem(3) - item.setText(_translate("MainWindow", "Type", None)) - self.label_ensemble.setText(_translate("MainWindow", "ENSEMBLE", None)) - self.label_26.setText(_translate("MainWindow", "services:", None)) - self.label_country.setText(_translate("MainWindow", "Country", None)) - self.label_snr.setText(_translate("MainWindow", "SNR:", None)) - self.label_7.setText(_translate("MainWindow", "dB", None)) - self.label_firecode.setText(_translate("MainWindow", "

Superframes:

", None)) - self.led_msc.setText(_translate("MainWindow", "led", None)) - self.label_label_msc.setText(_translate("MainWindow", "MSC", None)) - self.label_fic.setText(_translate("MainWindow", "

FIC:

", None)) - self.led_fic.setText(_translate("MainWindow", "led", None)) - self.label_label_fic.setText(_translate("MainWindow", "FIC", None)) - self.label_service.setText(_translate("MainWindow", "SERVICE", None)) - self.label_programme_type.setText(_translate("MainWindow", "programme type\n" -"", None)) - self.label_bit_rate.setText(_translate("MainWindow", "bit rate", None)) - self.label_primary.setText(_translate("MainWindow", "primary", None)) - self.label_dabplus.setText(_translate("MainWindow", "DAB", None)) - self.btn_init.setText(_translate("MainWindow", "start receiver", None)) - self.btn_update_info.setText(_translate("MainWindow", "scan ensemble", None)) - self.label_10.setText(_translate("MainWindow", "Gain", None)) - self.label_2.setText(_translate("MainWindow", "Audio Player", None)) - self.btn_play.setText(_translate("MainWindow", " Play", None)) - self.btn_stop.setText(_translate("MainWindow", " Stop", None)) - self.btn_record.setText(_translate("MainWindow", " Record", None)) - self.label_3.setText(_translate("MainWindow", "Volume", None)) - self.mode_tabs.setTabText(self.mode_tabs.indexOf(self.tab_reception), _translate("MainWindow", "Receiver", None)) - self.t_rbtn_USRP.setText(_translate("MainWindow", "USRP", None)) - self.t_label_frequency.setText(_translate("MainWindow", "Frequency", None)) - self.label.setText(_translate("MainWindow", "Hz ", None)) - self.t_rbtn_File.setText(_translate("MainWindow", "File", None)) - self.t_edit_file_name.setText(_translate("MainWindow", "gen_iq_dab.dat", None)) - self.t_label_sink.setText(_translate("MainWindow", "select path", None)) - self.t_btn_file_path.setText(_translate("MainWindow", "...", None)) - self.label_8.setText(_translate("MainWindow", "Transmission Mode", None)) - self.t_label_heading_service_comp.setText(_translate("MainWindow", "Service Components", None)) - self.t_label_comp1.setText(_translate("MainWindow", "Component 1", None)) - self.t_label_rate1.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot1.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src1.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src1.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src1.setText(_translate("MainWindow", "...", None)) - self.t_label_comp2.setText(_translate("MainWindow", "Component 2 ", None)) - self.t_label_rate2.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot2.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src2.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src2.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src2.setText(_translate("MainWindow", "...", None)) - self.t_label_comp3.setText(_translate("MainWindow", "Component 3", None)) - self.t_label_rate3.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot3.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src3.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src3.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src3.setText(_translate("MainWindow", "...", None)) - self.t_label_comp4.setText(_translate("MainWindow", "Component 4", None)) - self.t_label_rate4.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot4.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src4.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src4.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src4.setText(_translate("MainWindow", "...", None)) - self.t_label_comp5.setText(_translate("MainWindow", "Component 5", None)) - self.t_label_rate5.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot5.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src5.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src5.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src5.setText(_translate("MainWindow", "...", None)) - self.t_label_comp6.setText(_translate("MainWindow", "Component 6", None)) - self.t_label_rate6.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot6.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src6.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src6.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src6.setText(_translate("MainWindow", "...", None)) - self.t_label_comp7.setText(_translate("MainWindow", "Component 7", None)) - self.t_label_rate7.setText(_translate("MainWindow", "Data rate [kbit/s]", None)) - self.t_label_prot7.setText(_translate("MainWindow", "Protection Mode", None)) - self.t_label_comp_src7.setText(_translate("MainWindow", "Audio Source", None)) - self.t_label_path_src7.setText(_translate("MainWindow", "select audio", None)) - self.t_btn_path_src7.setText(_translate("MainWindow", "...", None)) - self.t_label_label1.setText(_translate("MainWindow", "Name", None)) - self.t_label_label2.setText(_translate("MainWindow", "Name", None)) - self.t_label_label3.setText(_translate("MainWindow", "Name", None)) - self.t_label_label4.setText(_translate("MainWindow", "Name", None)) - self.t_label_label5.setText(_translate("MainWindow", "Name", None)) - self.t_label_label6.setText(_translate("MainWindow", "Name", None)) - self.t_label_label7.setText(_translate("MainWindow", "Name", None)) - self.t_combo_dabplus1.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus1.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus2.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus2.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus3.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus3.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus4.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus4.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus5.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus5.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus6.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus6.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_dabplus7.setItemText(0, _translate("MainWindow", "DAB+", None)) - self.t_combo_dabplus7.setItemText(1, _translate("MainWindow", "DAB", None)) - self.t_combo_prot1.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot1.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot1.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot1.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot2.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot2.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot2.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot2.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot3.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot3.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot3.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot3.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot4.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot4.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot4.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot4.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot5.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot5.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot5.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot5.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot6.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot6.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot6.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot6.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_combo_prot7.setItemText(0, _translate("MainWindow", "A1", None)) - self.t_combo_prot7.setItemText(1, _translate("MainWindow", "A2", None)) - self.t_combo_prot7.setItemText(2, _translate("MainWindow", "A3", None)) - self.t_combo_prot7.setItemText(3, _translate("MainWindow", "A4", None)) - self.t_label_audio_rate1.setText(_translate("MainWindow", "Audio settings", None)) - self.t_label_audio_rate2.setText(_translate("MainWindow", "Audio settings", None)) - self.t_label_audio_rate3.setText(_translate("MainWindow", "Audio sampling", None)) - self.t_label_audio_rate4.setText(_translate("MainWindow", "Audio sampling", None)) - self.t_label_audio_rate5.setText(_translate("MainWindow", "audio sampling", None)) - self.t_label_audio_rate6.setText(_translate("MainWindow", "Audio sampling", None)) - self.t_label_audio_rate7.setText(_translate("MainWindow", "Audio sampling", None)) - self.t_combo_stereo1.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo1.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate1.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate1.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab1.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab1.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo2.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo2.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate2.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate2.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab2.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab2.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo3.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo3.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate3.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate3.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab3.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab3.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo4.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo4.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate4.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate4.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab4.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab4.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo5.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo5.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate5.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate5.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab5.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab5.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo6.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo6.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate6.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate6.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab6.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab6.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_combo_stereo7.setItemText(0, _translate("MainWindow", "stereo", None)) - self.t_combo_stereo7.setItemText(1, _translate("MainWindow", "mono", None)) - self.t_combo_audio_rate7.setItemText(0, _translate("MainWindow", "32 kHz", None)) - self.t_combo_audio_rate7.setItemText(1, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab7.setItemText(0, _translate("MainWindow", "48 kHz", None)) - self.t_combo_audio_rate_dab7.setItemText(1, _translate("MainWindow", "24 kHz", None)) - self.t_label_increase_num_subch_info.setText(_translate("MainWindow", "increase \"Number of channels\" for more components", None)) - self.label_12.setText(_translate("MainWindow", "Ensemble info", None)) - self.label_13.setText(_translate("MainWindow", "Label", None)) - self.t_edit_ensemble_label.setText(_translate("MainWindow", "Galaxy News", None)) - self.label_14.setText(_translate("MainWindow", "Country", None)) - self.label_17.setText(_translate("MainWindow", "Number of channels", None)) - self.label_23.setText(_translate("MainWindow", "Language", None)) - self.t_btn_init.setText(_translate("MainWindow", "start transmitter", None)) - self.label_22.setText(_translate("MainWindow", "Status:", None)) - self.t_label_status.setText(_translate("MainWindow", "not running", None)) - self.label_9.setText(_translate("MainWindow", "Gain", None)) - self.label_20.setText(_translate("MainWindow", "Audio Player", None)) - self.label_18.setText(_translate("MainWindow", "Listen to component", None)) - self.t_btn_play.setText(_translate("MainWindow", " Play", None)) - self.t_btn_stop.setText(_translate("MainWindow", " Stop", None)) - self.label_19.setText(_translate("MainWindow", "Volume", None)) - self.mode_tabs.setTabText(self.mode_tabs.indexOf(self.tab_transmission), _translate("MainWindow", "Transmitter", None)) - diff --git a/python/qa/qa_unpuncture_vff.py b/python/qa/qa_unpuncture_vff.py index f3de6abb..2cdecd66 100755 --- a/python/qa/qa_unpuncture_vff.py +++ b/python/qa/qa_unpuncture_vff.py @@ -1,4 +1,23 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# +# This 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, or (at your option) +# any later version. +# +# This software 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 software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# from gnuradio import gr, gr_unittest, blocks import dab_swig as dab diff --git a/python/qa/qa_valve_ff.py b/python/qa/qa_valve_ff.py index f6da153c..384922c7 100755 --- a/python/qa/qa_valve_ff.py +++ b/python/qa/qa_valve_ff.py @@ -1,18 +1,18 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# -# Copyright 2017 <+YOU OR YOUR COMPANY+>. -# +# +# Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). +# # This 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, or (at your option) # any later version. -# +# # This software 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 software; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, From f117e0b8131ed4206d81f208d15023449abcb9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20M=C3=BCller?= Date: Tue, 23 Jan 2018 16:43:17 +0100 Subject: [PATCH 124/135] PyQt4 pyuic integration fix --- CMakeLists.txt | 2 +- cmake/Modules/FindPyQt4.cmake | 61 +++++++++++++++++++++++++++++++++++ python/GUI/CMakeLists.txt | 12 +++---- 3 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 cmake/Modules/FindPyQt4.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index f0266b8e..3e2aba12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ else() message(STATUS "LIBTOOLAME-DAB found: ${LIBTOOLAME-DAB_SOURCE_DIR}") endif () - +find_package(PyQt4 REQUIRED) ######################################################################## # Find boost ######################################################################## diff --git a/cmake/Modules/FindPyQt4.cmake b/cmake/Modules/FindPyQt4.cmake new file mode 100644 index 00000000..c1f3f288 --- /dev/null +++ b/cmake/Modules/FindPyQt4.cmake @@ -0,0 +1,61 @@ +# Find PyQt4 +# ~~~~~~~~~~ +# Copyright (c) 2007-2008, Simon Edwards +# Copyright (c) 2012, Nicholas Corgan +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# PyQt4 website: http://www.riverbankcomputing.co.uk/pyqt/index.php +# +# Find the installed version of PyQt4. FindPyQt4 should only be called after +# Python has been found. +# +# This file defines the following variables: +# +# PYQT4_VERSION - The version of PyQt4 found expressed as a 6 digit hex number +# suitable for comparision as a string +# +# PYQT4_VERSION_STR - The version of PyQt4 as a human readable string. +# +# PYQT4_VERSION_TAG - The PyQt version tag using by PyQt's sip files. +# +# PYQT4_SIP_DIR - The directory holding the PyQt4 .sip files. +# +# PYQT4_SIP_FLAGS - The SIP flags used to build PyQt. + +IF(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) + # Already in cache, be silent + SET(PYQT4_FOUND TRUE) + SET(PYUIC4_FOUND TRUE) +ELSE(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) + + FIND_FILE(_find_pyqt_py FindPyQt.py PATHS ${CMAKE_MODULE_PATH}) + + EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt_py} OUTPUT_VARIABLE pyqt_config) + IF(pyqt_config) + STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT4_VERSION ${pyqt_config}) + STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT4_VERSION_STR ${pyqt_config}) + STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT4_VERSION_TAG ${pyqt_config}) + STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT4_SIP_DIR ${pyqt_config}) + STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT4_SIP_FLAGS ${pyqt_config}) + + SET(PYQT4_FOUND TRUE) + ENDIF(pyqt_config) + + FIND_PROGRAM(PYUIC4_EXECUTABLE NAMES pyuic4) + IF(PYUIC4_EXECUTABLE) + SET(PYUIC4_FOUND TRUE) + ENDIF(PYUIC4_EXECUTABLE) + + IF(PYQT4_FOUND AND PYUIC4_FOUND) + IF(NOT PYQT4_FIND_QUIETLY) + MESSAGE(STATUS "Found PyQt4 version: ${PYQT4_VERSION_STR}") + MESSAGE(STATUS "Found pyuic4: ${PYUIC4_EXECUTABLE}") + ENDIF(NOT PYQT4_FIND_QUIETLY) + ELSE(PYQT4_FOUND AND PYUIC4_FOUND) + IF(PYQT4_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Python") + ENDIF(PYQT4_FIND_REQUIRED) + ENDIF(PYQT4_FOUND AND PYUIC4_FOUND) + +ENDIF(EXISTS PYQT4_VERSION AND EXISTS PYUIC4_EXECUTABLE) diff --git a/python/GUI/CMakeLists.txt b/python/GUI/CMakeLists.txt index 3fa6daf9..9688f183 100644 --- a/python/GUI/CMakeLists.txt +++ b/python/GUI/CMakeLists.txt @@ -23,17 +23,17 @@ GR_PYTHON_INSTALL( FILES usrp_dab_rx.py usrp_dab_tx.py - user_frontend.py + ${GUI_PY} DESTINATION ${GR_PYTHON_DIR}/dab COMPONENT "dab_python" ) set(GR_PKG_DAB_DATA_DIR ${GR_PKG_DATA_DIR}) -install(FILES +install(FILES DAB_logo.png led_red.png led_orange.png - led_green.png - DESTINATION ${GR_PKG_DAB_DATA_DIR} + led_green.png + DESTINATION ${GR_PKG_DAB_DATA_DIR} ) ######################################################################## @@ -41,8 +41,8 @@ install(FILES ######################################################################## set(GUI_UI ${CMAKE_CURRENT_SOURCE_DIR}/user_frontend.ui) set(GUI_PY ${CMAKE_CURRENT_BINARY_DIR}/user_frontend.py) -add_custom_command(OUTPUT ${GUI_UI} - COMMAND ${PYUIC4_EXECUTABLE} pyuic4 ${GUI_UI} -o ${GUI_PY} +add_custom_command(OUTPUT ${GUI_PY} + COMMAND ${PYUIC4_EXECUTABLE} ${GUI_UI} -o ${GUI_PY} DEPENDS ${GUI_UI} COMMENT "Generating python code from the user interface" ) From fa166fd53e446af461786c6f18b57bd5fdf75385 Mon Sep 17 00:00:00 2001 From: luca Date: Thu, 22 Feb 2018 12:14:15 +0100 Subject: [PATCH 125/135] GUI: suppress the SNR update info, closes #29 --- apps/DABstep | 1 - python/GUI/main.py | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/DABstep b/apps/DABstep index 3993d9a6..c7ed0f3e 100755 --- a/apps/DABstep +++ b/apps/DABstep @@ -475,7 +475,6 @@ class DABstep(QtGui.QMainWindow, user_frontend.Ui_MainWindow): def adjust_audio_sampling_rate(self): self.timer_audio_sampling_rate.stop() new_sampling_rate = self.my_receiver.get_sample_rate() - print "key adjust" if new_sampling_rate != self.audio_bit_rate and new_sampling_rate != -1: self.audio_bit_rate = new_sampling_rate self.statusBar.showMessage("Adjusting audio sampling rate to " + str(new_sampling_rate)) diff --git a/python/GUI/main.py b/python/GUI/main.py index 1adcc8d6..04927a5a 100644 --- a/python/GUI/main.py +++ b/python/GUI/main.py @@ -475,7 +475,6 @@ def stop_audio(self): def adjust_audio_sampling_rate(self): self.timer_audio_sampling_rate.stop() new_sampling_rate = self.my_receiver.get_sample_rate() - print "key adjust" if new_sampling_rate != self.audio_bit_rate and new_sampling_rate != -1: self.audio_bit_rate = new_sampling_rate self.statusBar.showMessage("Adjusting audio sampling rate to " + str(new_sampling_rate)) From cea6fc7bb3d74778458ea6da573faa22cf243c03 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Fri, 23 Feb 2018 20:44:17 +0100 Subject: [PATCH 126/135] GUI: correct CMake installation order in python/GUI --- python/GUI/CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/python/GUI/CMakeLists.txt b/python/GUI/CMakeLists.txt index 9688f183..c2b6abb7 100644 --- a/python/GUI/CMakeLists.txt +++ b/python/GUI/CMakeLists.txt @@ -19,6 +19,16 @@ include(GrPython) +######################################################################## +# Generate the GUI python code user_frontend.py from the user interface user_frontend.ui +######################################################################## +set(GUI_UI ${CMAKE_CURRENT_SOURCE_DIR}/user_frontend.ui) +set(GUI_PY ${CMAKE_CURRENT_BINARY_DIR}/user_frontend.py) +add_custom_command(OUTPUT ${GUI_PY} + COMMAND ${PYUIC4_EXECUTABLE} ${GUI_UI} -o ${GUI_PY} + DEPENDS ${GUI_UI} + COMMENT "Generating python code from the user interface" +) GR_PYTHON_INSTALL( FILES usrp_dab_rx.py @@ -36,13 +46,3 @@ install(FILES DESTINATION ${GR_PKG_DAB_DATA_DIR} ) -######################################################################## -# Generate the GUI python code user_frontend.py from the user interface user_frontend.ui -######################################################################## -set(GUI_UI ${CMAKE_CURRENT_SOURCE_DIR}/user_frontend.ui) -set(GUI_PY ${CMAKE_CURRENT_BINARY_DIR}/user_frontend.py) -add_custom_command(OUTPUT ${GUI_PY} - COMMAND ${PYUIC4_EXECUTABLE} ${GUI_UI} -o ${GUI_PY} - DEPENDS ${GUI_UI} - COMMENT "Generating python code from the user interface" -) From 1e781241b67204dd5c000a1df9038eb8039e3b50 Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sat, 24 Feb 2018 22:33:33 +0100 Subject: [PATCH 127/135] reformat auto-formatted garbage --- lib/fib_sink_vb_impl.cc | 24 +- lib/fib_source_b_impl.cc | 339 ++++++++++---------------- lib/fib_source_b_impl.h | 3 +- lib/frequency_interleaver_vcc_impl.cc | 9 +- lib/insert_null_symbol_impl.cc | 9 +- lib/neaacdec.h | 128 +++++----- lib/prune_impl.cc | 3 +- lib/qpsk_mapper_vbvc_impl.cc | 4 +- lib/reed_solomon_decode_bb_impl.cc | 3 +- lib/select_cus_vfvf_impl.cc | 3 +- lib/sum_phasor_trig_vcc_impl.cc | 14 +- lib/test_dab.cc | 3 +- lib/time_interleave_bb_impl.cc | 5 +- python/__init__.py | 8 +- 14 files changed, 235 insertions(+), 320 deletions(-) diff --git a/lib/fib_sink_vb_impl.cc b/lib/fib_sink_vb_impl.cc index fabde6a3..a2960d3a 100644 --- a/lib/fib_sink_vb_impl.cc +++ b/lib/fib_sink_vb_impl.cc @@ -92,8 +92,7 @@ namespace gr { extension = (uint8_t)(data[1] & 0x1f); cn = (uint8_t)(data[1] & 0x80); if (cn == 1) - GR_LOG_DEBUG(d_logger, - "[WARNING, INFO FOR FUTURE CONFIGURATION]: "); + GR_LOG_DEBUG(d_logger, "[WARNING, INFO FOR FUTURE CONFIGURATION]: "); oe = (uint8_t)(data[1] & 0x40); if (cn == 1) GR_LOG_DEBUG(d_logger, "[WARNING, INFO FOR OTHER ENSEMBLE]"); @@ -113,8 +112,9 @@ namespace gr { (int) change_flag % (int) occurrence_change); uint8_t alarm_flag = (uint8_t)((data[4] & 0x20) >> 5); - if (alarm_flag == 1) + if (alarm_flag == 1) { GR_LOG_DEBUG(d_logger, ", [ALARM MESSAGE ACCESSIBLE] "); + } uint16_t CIF_counter = (uint16_t)( (data[4] & 0x1f) * 250 + (data[5])); GR_LOG_DEBUG(d_logger, @@ -400,17 +400,14 @@ namespace gr { } case FIB_SI_EXTENSION_SERVICE_COMP_LABEL: memcpy(label, &data[5], 16); - GR_LOG_DEBUG(d_logger, - format("[service component label] %s") % label); + GR_LOG_DEBUG(d_logger, format("[service component label] %s") % label); break; case FIB_SI_EXTENSION_DATA_SERVICE_LABEL: memcpy(label, &data[5], 16); - GR_LOG_DEBUG(d_logger, - format("[data service label]: %s") % label); + GR_LOG_DEBUG(d_logger, format("[data service label]: %s") % label); break; default: - GR_LOG_DEBUG(d_logger, - format("[unknown extension (%d)") % (int) extension); + GR_LOG_DEBUG(d_logger, format("[unknown extension (%d)") % (int) extension); break; } break; @@ -423,12 +420,10 @@ namespace gr { GR_LOG_DEBUG(d_logger, "paging - not supported yet"); break; case FIB_FIDC_EXTENSION_TMC: - GR_LOG_DEBUG(d_logger, - "TMC (traffic message channel) - not supported yet"); + GR_LOG_DEBUG(d_logger, "TMC (traffic message channel) - not supported yet"); break; case FIB_FIDC_EXTENSION_EWS: - GR_LOG_DEBUG(d_logger, - "EWS (emergency warning service) - not supported yet"); + GR_LOG_DEBUG(d_logger, "EWS (emergency warning service) - not supported yet"); break; default: GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % @@ -436,8 +431,7 @@ namespace gr { } break; case FIB_FIG_TYPE_CA: - GR_LOG_DEBUG(d_logger, - "FIB type CA (conditional access) not supported yet"); + GR_LOG_DEBUG(d_logger, "FIB type CA (conditional access) not supported yet"); break; default: GR_LOG_DEBUG(d_logger, "unsupported FIG type"); diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index aca58304..24e16f40 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -38,132 +38,60 @@ namespace gr { //////////////////////////////////////// //ensemble info, CIF counter has to increase with each CIF - const char fib_source_b_impl::d_ensemble_info[56] = {0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, - 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0}; + const char fib_source_b_impl::d_ensemble_info[56] = {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; // 000 00110 000 00000 0100000000000000 00 0 0000000000000 00000000 //service orga header - const char fib_source_b_impl::d_service_orga_header[16] = {0, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 0, - 0, 0, 1, 0}; + const char fib_source_b_impl::d_service_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; //000 00100 000 00010 //service orga for one service containing one subchannel - const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 1, 1, - 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0}; + const char fib_source_b_impl::d_service_orga[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0}; // 0100000000000000 0 000 0001 00 111111 000000 00 //subchannel orga header, length has to be changed according to the number of subchannel-orga fields - const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, - 0, 0, 1, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 1}; + const char fib_source_b_impl::d_subchannel_orga_header[16] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; //000 00100 000 00001 //subchannel orga field (long form) (array has to be modified (subchID, start adress, protection level and subchannel size)) - const char fib_source_b_impl::d_subchannel_orga_field[32] = {0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 1, 0, - 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0}; + const char fib_source_b_impl::d_subchannel_orga_field[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 000000 0000000000 0 1 000 00 0000000000 long form (table 7, p. 51) ///////////////////////////////////////////// /// SI-FIGs, ready to transmit ///////////////////////////////////////////// //Ensemble label - char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 1, - 1, 1, 1, 1, - 0, 1, 0, 1, 1, 1, 1, 1, - 0, 1, 0, 0, 0, 1, 1, 1, - 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 0, - 1, 1, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 1, - 0, 1, 1, 1, 1, 0, 0, 0, - 0, 1, 1, 1, 1, 0, 0, 1, - 0, 1, 0, 1, - 1, 1, 1, 1, 0, 1, 0, 0, - 1, 1, 1, 0, 0, 1, 1, 0, - 0, 1, 0, 1, - 0, 1, 1, 1, 0, 1, 1, 1, - 0, 1, 1, 1, 0, 0, 1, 1, - 0, 1, 0, 1, - 1, 1, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 0, 1, 0, 1, - 1, 1, 1, 1, - 0, 0, 1, 1, 1, 0, 0, 0, - 1, 1, 1, 1, 1, 0, 0, - 0}; + char fib_source_b_impl::d_ensemble_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, + 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}; //"001 10101 0000 0 000 0000 000000000000 01011111 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01001110 01100101 01110111 01110011 01011111 01011111 01011111 0011100011111000"; // Ensemble label: "__Galaxy_News___" //Programme Service label - char fib_source_b_impl::d_programme_service_label[176] = {0, 0, 1, 1, 0, - 1, 0, 1, 0, 0, - 0, 0, 0, 0, 0, - 1, 0, 1, 0, - 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 1, 0, 1, 1, - 1, 1, 1, 0, - 1, 0, 0, - 0, 1, 1, 1, 0, - 1, 1, 0, 0, 0, - 0, 1, 0, 1, 1, - 0, 1, 1, 0, - 0, 0, 1, - 1, 0, 0, 0, 0, - 1, 0, 1, 1, 1, - 1, 0, 0, 0, 0, - 1, 1, 1, 1, - 0, 0, 1, - 0, 1, 0, 1, 1, - 1, 1, 1, 0, 1, - 0, 1, 0, 0, 1, - 0, 0, 1, 1, - 0, 0, 0, - 0, 1, 0, 1, 1, - 0, 0, 1, 0, 0, - 0, 1, 1, 0, 1, - 0, 0, 1, 0, - 1, 1, 0, - 1, 1, 1, 1, 0, - 0, 1, 1, 0, 0, - 0, 1, 0, 1, 0, - 1, 1, 1, 1, - 1, 0, 1, - 0, 1, 1, 1, 1, - 1, 0, 1, 1, 1, - 0, 0, 0, 1, 1, - 1, 1, 0, 0, - 1, 0, 0}; + char fib_source_b_impl::d_programme_service_label[176] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, + 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, + 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0}; //001 10101 0000 0 001 0100000000000000 01011111 01000111 01100001 01101100 01100001 01111000 01111001 01011111 01010010 01100001 01100100 01101001 01101111 00110001 01011111 01011111 0111000111100100 fib_source_b::sptr @@ -204,29 +132,31 @@ namespace gr { d_protection_mode(protection_mode), d_data_rate_n(data_rate_n), d_dabplus(dabplus), d_country_ID(country_ID) { - if (d_transmission_mode != 3) + if (d_transmission_mode != 3) { set_output_multiple((8 * FIB_LENGTH) * 3); - else set_output_multiple((8 * FIB_LENGTH) * 4); + } else { + set_output_multiple((8 * FIB_LENGTH) * 4); + } //write the ensemble label with input string once at beginning write_label(d_ensemble_label + 32, ensemble_label); if (protection_mode.size() != num_subch) { - throw std::invalid_argument((boost::format( - "size of vector protection_mode (%d) does not fit with number of subchannels (%d)") % + throw std::invalid_argument((boost::format("size of vector protection_mode (%d) does not fit with number of subchannels (%d)") % protection_mode.size() % num_subch).str()); } if (data_rate_n.size() != num_subch) { - throw std::invalid_argument((boost::format( - "size of vector data_rate_n (%d) does not fit with number of subchannels (%d)") % - data_rate_n.size() % num_subch).str()); + throw std::invalid_argument((boost::format("size of vector data_rate_n (%d) does not fit with number of subchannels (%d)") % + data_rate_n.size() % + num_subch).str()); } // init counter for iterating over the services d_label_counter = 0; d_service_labels = programme_service_labels; - // the string programme_service_labels containts num_subch * 16 chars, appended. Note that every subchannel is strutured in a different service in this implementation. + /* The string programme_service_labels contains num_subch * 16 chars. + * Note that every subchannel is strutured in a different service in + * this implementation. */ if (programme_service_labels.size() != 16 * num_subch) { - throw std::invalid_argument((boost::format( - "size of service label strings is (%d) but should be %d * 16 = %d") % + throw std::invalid_argument((boost::format("size of service label strings is (%d) but should be %d * 16 = %d") % programme_service_labels.size() % num_subch % (16 * num_subch)).str()); } @@ -239,7 +169,9 @@ namespace gr { } /* - * overwrites an integer value to num_bits bits to the num_bits bits before trigger (overwrites default zeros)), e.g. for number of subchannels in ensemble info + * Overwrites an integer value to num_bits bits to the num_bits bits + * before trigger (overwrites default zeros)), + * e.g. for number of subchannels in ensemble info. */ void fib_source_b_impl::bit_adaption(char *out_ptr, int number, int num_bits) { @@ -254,20 +186,21 @@ namespace gr { } /* - * calculates the CIF modulo counters and changes the bits in d_ensemble_info with bit_adaption + * Calculates the CIF modulo counters and changes the bits in + * d_ensemble_info with bit_adaption. */ void fib_source_b_impl::CIF_counter(char *out_ptr, int counter) { - //mod 250 counter + // mod 250 counter int mod_250 = counter % 250; bit_adaption(out_ptr, mod_250, 8); - //mod 20 counter + // mod 20 counter int mod_20 = ((counter - mod_250) / 250) % 20; bit_adaption(out_ptr - 8, mod_20, 5); } /* - * converts string to bits and writes it to the stream - * outputs the number of written bits to update d_offset + * Converts string to bits and writes it to stream. + * Outputs the number of written bits to update d_offset. */ int fib_source_b_impl::write_label(char *out_ptr, std::string label, int num_chars) { @@ -290,93 +223,92 @@ namespace gr { d_offset = 0; do { - //only MCI in this FIB when this FIB ist first in Row (Row are 3 FIBs for d_transmission_mode=1,2,4 or 4 FIBs for d_transmission_mode=3) + // Only MCI in this FIB when this FIB ist first in row. + // (Row are 3 FIBs for d_transmission_mode = 1,2,4 or + // 4 FIBs for d_transmission_mode = 3). if ((d_nFIBs_written % 3 == 0 && d_transmission_mode != 3) || (d_nFIBs_written % 4 == 0 && d_transmission_mode == 3)) { //////////////////////////////////////////////// /// add first FIB with only MCI (max services = 4) //////////////////////////////////////////////// //ensemble info - std::memcpy(out + d_offset, d_ensemble_info, - d_size_ensemble_info); + std::memcpy(out + d_offset, d_ensemble_info, d_size_ensemble_info); d_offset += d_size_ensemble_info; - //increase CIF counter - if (d_transmission_mode != 3) + // Increase CIF counter. + if (d_transmission_mode != 3) { CIF_counter(out + d_offset, d_nFIBs_written / 3); - else CIF_counter(out + d_offset, d_nFIBs_written / 4); - - //service orga - //header - std::memcpy(out + d_offset, d_service_orga_header, - d_size_service_orga_header); + } else { + CIF_counter(out + d_offset, d_nFIBs_written / 4); + } + // service orga + // header + std::memcpy(out + d_offset, d_service_orga_header, d_size_service_orga_header); d_offset += d_size_service_orga_header; - //change FIG length depending on number of services + // Change FIG length depending on number of services. bit_adaption(out + d_offset - 8, 1 + 5 * d_num_subch, 5); - //data field for every service (each containing one service component) - for (int service_count = 0; - service_count < d_num_subch; service_count++) { - std::memcpy(out + d_offset, d_service_orga, - d_size_service_orga); + // data field for every service (each containing one service component) + for (int service_count = 0; service_count < d_num_subch; service_count++) { + std::memcpy(out + d_offset, d_service_orga, d_size_service_orga); d_offset += d_size_service_orga; - //change service Identifier + // change service Identifier bit_adaption(out + d_offset - 24, service_count, 8); - //change subchannel ID + // change subchannel ID bit_adaption(out + d_offset - 2, service_count, 6); - //change DAB+ mode if not DAB+ but DAB + // change DAB+ mode if not DAB+ but DAB if (d_dabplus[service_count] != 1) { bit_adaption(out + d_offset - 8, 0, 6); } } - //MCI is set, set EndMarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) + // MCI is set, set EndMarker and padding. + if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= 8) { + /* Add EndMarker (111 11111) if there is minimum one byte left + * in FIG (FIG without 16 bit crc16). */ for (int i = 0; i < 8; i++) { out[i + d_offset] = 1; } } d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + /* Padding. (fill rest of FIB with zeroes, + * as well the last 16 crc bits) */ + while (d_offset % (8 * FIB_LENGTH) != 0) { out[d_offset] = 0; d_offset++; } d_nFIBs_written++; - }//first FIB in row (with only MCI) is finished + } // First FIB in row (with only MCI) is finished. - //second FIB in row reserved for subchannel orga + // Second FIB in row reserved for subchannel orga. else if ((d_nFIBs_written % 3 == 1 && d_transmission_mode != 3) || (d_nFIBs_written % 4 == 1 && d_transmission_mode == 3)) { //////////////////////////////////////////////// /// add second FIB with only subchannel orga (max numSubCh = 7) //////////////////////////////////////////////// - //subchannel orga + // subchannel orga d_start_adress = 0; - //subchannel orga header (write only once for all subchannels) - std::memcpy(out + d_offset, d_subchannel_orga_header, - d_size_subchannel_orga_header); + // subchannel orga header (write only once for all subchannels) + std::memcpy(out + d_offset, d_subchannel_orga_header, d_size_subchannel_orga_header); d_offset += d_size_subchannel_orga_header; - //change length of FIG header according to number of subchannel orga fields that are added - bit_adaption(out + d_offset - 8, - d_num_subch * (d_size_subchannel_orga_field / 8) + 1, - 5); - //subchannel orga field - for (int subch_count = 0; subch_count < - d_num_subch; subch_count++) {//iterate over all subchannels - std::memcpy(out + d_offset + - d_size_subchannel_orga_field * subch_count, + /* Change length of FIG header according to number of + * subchannel orga fields which are added. */ + bit_adaption(out + d_offset - 8, d_num_subch * (d_size_subchannel_orga_field / 8) + 1, 5); + // subchannel orga field + // Iterate over all subchannels. + for (int subch_count = 0; subch_count < d_num_subch; subch_count++) { + std::memcpy(out + d_offset + d_size_subchannel_orga_field * subch_count, d_subchannel_orga_field, d_size_subchannel_orga_field); d_offset += d_size_subchannel_orga_field; - //change SubChID, start address, protection level and subch size of each sub channel - //the SubChannel ID has to increase, to be different + /* Change SubChID, start address, protection level and + * subch size of each sub channel. + * The SubChannel ID has to increase, to be different. */ bit_adaption(out + d_offset - 26, subch_count, 6); - //the start address (in CUs) of the next subch is increased about size of previous subch + /* The start address (in CUs) of the next subch is increased + * about size of previous subch. */ bit_adaption(out + d_offset - 16, d_start_adress, 10); - //protection level - bit_adaption(out + d_offset - 10, - d_protection_mode[subch_count], 2); - //calculate size of subchannel in CUs (table 7, p. 51) + // protection level + bit_adaption(out + d_offset - 10, d_protection_mode[subch_count], 2); + // Calculate size of subchannel in CUs. (table 7, p. 51) switch (d_protection_mode[subch_count]) { case 0: d_subch_size = 12 * d_data_rate_n[subch_count]; @@ -394,47 +326,44 @@ namespace gr { //error break; } - //write subchannel size + // write subchannel size bit_adaption(out + d_offset - 0, d_subch_size, 10); - //shift start address + // shift start address d_start_adress += d_subch_size; } - //subchannel orga is set, set EndMarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG (FIG without 16 bit crc16) - for (int i = 0; i < - 8; i++) { //find:: binde FIC.h ein und verwende die konstaten statt FIB_size + // Subchannel orga is set, set EndMarker and padding. + if ((8 * FIB_DATA_FIELD_LENGTH) - d_offset >= 8) { + /* Add EndMarker (111 11111) if there is minimum one byte left + * in FIG. (FIG without 16 bit crc16) */ + for (int i = 0; i < 8; i++) { out[i + d_offset] = 1; } } d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + while (d_offset % (8 * FIB_LENGTH) != 0) { + /* Padding. (fill rest of FIB with zeroes, as well the last 16 crc bits) */ out[d_offset] = 0; d_offset++; } d_nFIBs_written++; - }//second FIB is finished + }// second FIB is finished else { ///////////////////////////////////////////////// /// write a not primary FIB with SI ///////////////////////////////////////////////// - do { //fill FIB with FIGs + do { // Fill FIB with FIGs. if (d_label_counter == 0) { - // write ensemble label + // Write ensemble label. std::memcpy(out + d_offset, d_ensemble_label, d_size_label); d_offset += d_size_label; - // change country ID - bit_adaption(out + d_offset - (d_size_label - 20), - d_country_ID, 4); + // Change country ID. + bit_adaption(out + d_offset - (d_size_label - 20), d_country_ID, 4); ++d_label_counter; } else { - // write service label - std::memcpy(out + d_offset, d_programme_service_label, - d_size_label); - // change label - std::string label = d_service_labels.substr( - (d_label_counter - 1) * 16, 16); + // Write service label. + std::memcpy(out + d_offset, d_programme_service_label, d_size_label); + // Change label. + std::string label = d_service_labels.substr((d_label_counter - 1) * 16, 16); write_label(out + d_offset + 32, label); d_offset += d_size_label; bit_adaption(out + d_offset - 144, d_label_counter - 1, 8); @@ -443,33 +372,35 @@ namespace gr { } } - } while ((8 * FIB_DATA_FIELD_LENGTH) - - (d_offset % (8 * FIB_LENGTH)) >= - 176); //check if there is enough space for next FIG - //FIB is filled, set endmarker and padding - if ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= - 8) {//add EndMarker (111 11111) if there is minimum one byte left in FIG + /* Check if there is enough space for next FIG. */ + } while ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= 176); + // FIB is filled, set endmarker and padding. + /* Add EndMarker (111 11111) if there is minimum one byte left in FIG */ + if ((8 * FIB_DATA_FIELD_LENGTH) - (d_offset % (8 * FIB_LENGTH)) >= 8) { for (int i = 0; i < 8; i++) { - out[i + d_offset] = 1; + out[i + d_offset] = 1;//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) } } d_offset += 8; - while (d_offset % (8 * FIB_LENGTH) != - 0) {//padding (fill rest of FIB with zeroes, as well the last 16 crc bits) + // Padding (fill rest of FIB with zeroes, as well the last 16 crc bits). + while (d_offset % (8 * FIB_LENGTH) != 0) { out[d_offset] = 0; d_offset++; } d_nFIBs_written++; - }//FIB finished + }// FIB finished. } while ((d_nFIBs_written % 3 != 0 && d_transmission_mode != 3) || - (d_nFIBs_written % 4 != 0 && - d_transmission_mode == - 3)); //finished writing a row of FIBs (3 or 4) (number of FIBS for 1 Transmission Frame) + (d_nFIBs_written % 4 != 0 && d_transmission_mode == 3)); + // Finished writing a row of FIBs (3 or 4) (number of FIBS for 1 Transmission Frame). // Tell runtime system how many output items we produced. - if (d_transmission_mode != 3) return 3 * (8 * FIB_LENGTH); - else return 4 * (8 * FIB_LENGTH); + if (d_transmission_mode != 3) { + return 3 * (8 * FIB_LENGTH); + } + else { + return 4 * (8 * FIB_LENGTH); + } } } /* namespace dab */ diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index 6ab5eb6e..a05bd989 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -75,8 +75,7 @@ namespace gr { static char d_programme_service_label[176]; //21*8+8, service label (FIG 1/0) std::string d_service_labels; - int write_label(char *out_ptr, std::string label, - int num_chars = 16);//default for 16 characters (16 byte) + int write_label(char *out_ptr, std::string label, int num_chars = 16); //default for 16 characters (16 byte) public: fib_source_b_impl(int transmission_mode, int coutry_ID, diff --git a/lib/frequency_interleaver_vcc_impl.cc b/lib/frequency_interleaver_vcc_impl.cc index 307fa434..b048cf26 100644 --- a/lib/frequency_interleaver_vcc_impl.cc +++ b/lib/frequency_interleaver_vcc_impl.cc @@ -36,10 +36,8 @@ namespace gr { namespace dab { frequency_interleaver_vcc::sptr - frequency_interleaver_vcc::make( - const std::vector &interleaving_sequence) { - return gnuradio::get_initial_sptr - (new frequency_interleaver_vcc_impl(interleaving_sequence)); + frequency_interleaver_vcc::make(const std::vector &interleaving_sequence) { + return gnuradio::get_initial_sptr(new frequency_interleaver_vcc_impl(interleaving_sequence)); } frequency_interleaver_vcc_impl::frequency_interleaver_vcc_impl( @@ -64,8 +62,9 @@ namespace gr { gr_complex *out = (gr_complex *) output_items[0]; for (int i = 0; i < noutput_items; i++) { - for (unsigned int j = 0; j < d_length; j++) + for (unsigned int j = 0; j < d_length; j++) { out[d_interleaving_sequence[j]] = in[j]; + } out += d_length; in += d_length; } diff --git a/lib/insert_null_symbol_impl.cc b/lib/insert_null_symbol_impl.cc index 71a52ba7..dc25dc17 100644 --- a/lib/insert_null_symbol_impl.cc +++ b/lib/insert_null_symbol_impl.cc @@ -92,16 +92,17 @@ namespace gr { consumed_items < ninput_items[0] && consumed_items < ninput_items[1]) { if (*trigger == 1 && d_ns_added < d_ns_length) { - for (i = 0; i < d_ns_length - d_ns_added && - i < noutput_items - produced_items; i++) + for (i = 0; i < d_ns_length - d_ns_added && i < noutput_items - produced_items; i++) { *optr++ = 0; + } produced_items += i; d_ns_added += i; } else { if (*trigger == 0) d_ns_added = 0; - for (int i = 0; i < d_symbol_length; i++) - *optr++ = *iptr++; + memcpy(optr, iptr, d_symbol_length); + iptr += d_symbol_length; + optr += d_symbol_length; produced_items += d_symbol_length; trigger++; consumed_items++; diff --git a/lib/neaacdec.h b/lib/neaacdec.h index 17900f34..3769d3f0 100644 --- a/lib/neaacdec.h +++ b/lib/neaacdec.h @@ -60,14 +60,14 @@ extern "C" { #ifdef _WIN32 -#pragma pack(push, 8) -#ifndef NEAACDECAPI -#define NEAACDECAPI __cdecl -#endif + #pragma pack(push, 8) + #ifndef NEAACDECAPI + #define NEAACDECAPI __cdecl + #endif #else -#ifndef NEAACDECAPI -#define NEAACDECAPI -#endif + #ifndef NEAACDECAPI + #define NEAACDECAPI + #endif #endif #define FAAD2_VERSION "2.7" @@ -138,72 +138,74 @@ extern "C" { typedef void *NeAACDecHandle; -typedef struct mp4AudioSpecificConfig { - /* Audio Specific Info */ - unsigned char objectTypeIndex; - unsigned char samplingFrequencyIndex; - unsigned long samplingFrequency; - unsigned char channelsConfiguration; - - /* GA Specific Info */ - unsigned char frameLengthFlag; - unsigned char dependsOnCoreCoder; - unsigned short coreCoderDelay; - unsigned char extensionFlag; - unsigned char aacSectionDataResilienceFlag; - unsigned char aacScalefactorDataResilienceFlag; - unsigned char aacSpectralDataResilienceFlag; - unsigned char epConfig; - - char sbr_present_flag; - char forceUpSampling; - char downSampledSBR; +typedef struct mp4AudioSpecificConfig +{ + /* Audio Specific Info */ + unsigned char objectTypeIndex; + unsigned char samplingFrequencyIndex; + unsigned long samplingFrequency; + unsigned char channelsConfiguration; + + /* GA Specific Info */ + unsigned char frameLengthFlag; + unsigned char dependsOnCoreCoder; + unsigned short coreCoderDelay; + unsigned char extensionFlag; + unsigned char aacSectionDataResilienceFlag; + unsigned char aacScalefactorDataResilienceFlag; + unsigned char aacSpectralDataResilienceFlag; + unsigned char epConfig; + + char sbr_present_flag; + char forceUpSampling; + char downSampledSBR; } mp4AudioSpecificConfig; -typedef struct NeAACDecConfiguration { - unsigned char defObjectType; - unsigned long defSampleRate; - unsigned char outputFormat; - unsigned char downMatrix; - unsigned char useOldADTSFormat; - unsigned char dontUpSampleImplicitSBR; +typedef struct NeAACDecConfiguration +{ + unsigned char defObjectType; + unsigned long defSampleRate; + unsigned char outputFormat; + unsigned char downMatrix; + unsigned char useOldADTSFormat; + unsigned char dontUpSampleImplicitSBR; } NeAACDecConfiguration, *NeAACDecConfigurationPtr; -typedef struct NeAACDecFrameInfo { - unsigned long bytesconsumed; - unsigned long samples; - unsigned char channels; - unsigned char error; - unsigned long samplerate; +typedef struct NeAACDecFrameInfo +{ + unsigned long bytesconsumed; + unsigned long samples; + unsigned char channels; + unsigned char error; + unsigned long samplerate; - /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ - unsigned char sbr; + /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ + unsigned char sbr; - /* MPEG-4 ObjectType */ - unsigned char object_type; + /* MPEG-4 ObjectType */ + unsigned char object_type; - /* AAC header type; MP4 will be signalled as RAW also */ - unsigned char header_type; + /* AAC header type; MP4 will be signalled as RAW also */ + unsigned char header_type; - /* multichannel configuration */ - unsigned char num_front_channels; - unsigned char num_side_channels; - unsigned char num_back_channels; - unsigned char num_lfe_channels; - unsigned char channel_position[64]; + /* multichannel configuration */ + unsigned char num_front_channels; + unsigned char num_side_channels; + unsigned char num_back_channels; + unsigned char num_lfe_channels; + unsigned char channel_position[64]; - /* PS: 0: off, 1: on */ - unsigned char ps; + /* PS: 0: off, 1: on */ + unsigned char ps; } NeAACDecFrameInfo; -char *NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode); +char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode); unsigned long NEAACDECAPI NeAACDecGetCapabilities(void); NeAACDecHandle NEAACDECAPI NeAACDecOpen(void); -NeAACDecConfigurationPtr NEAACDECAPI -NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); +NeAACDecConfigurationPtr NEAACDECAPI NeAACDecGetCurrentConfiguration(NeAACDecHandle hDecoder); unsigned char NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder, NeAACDecConfigurationPtr config); @@ -224,24 +226,24 @@ char NEAACDECAPI NeAACDecInit2(NeAACDecHandle hDecoder, /* Init the library for DRM */ char NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hDecoder, - unsigned long samplerate, + unsigned long samplerate, unsigned char channels); char NEAACDECAPI NeAACDecInitDAB(NeAACDecHandle *hDecoder, - unsigned long samplerate, + unsigned long samplerate, unsigned char channels, - unsigned char sbr); + unsigned char sbr); void NEAACDECAPI NeAACDecPostSeekReset(NeAACDecHandle hDecoder, long frame); void NEAACDECAPI NeAACDecClose(NeAACDecHandle hDecoder); -void *NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, +void* NEAACDECAPI NeAACDecDecode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, unsigned char *buffer, unsigned long buffer_size); -void *NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, +void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, unsigned char *buffer, unsigned long buffer_size, @@ -253,7 +255,7 @@ char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer, mp4AudioSpecificConfig *mp4ASC); #ifdef _WIN32 -#pragma pack(pop) + #pragma pack(pop) #endif #ifdef __cplusplus diff --git a/lib/prune_impl.cc b/lib/prune_impl.cc index b440f069..d91546d8 100644 --- a/lib/prune_impl.cc +++ b/lib/prune_impl.cc @@ -88,8 +88,7 @@ namespace gr { } // Tell runtime system how many input items we consumed on // each input stream. - consume_each((noutput_items / (d_length - d_prune_start - d_prune_end)) * - d_length); + consume_each((noutput_items / (d_length - d_prune_start - d_prune_end)) * d_length); // Tell runtime system how many output items we produced. return noutput_items; diff --git a/lib/qpsk_mapper_vbvc_impl.cc b/lib/qpsk_mapper_vbvc_impl.cc index 7620b263..86b4d4f4 100644 --- a/lib/qpsk_mapper_vbvc_impl.cc +++ b/lib/qpsk_mapper_vbvc_impl.cc @@ -65,7 +65,9 @@ namespace gr { for (int j = 0; j < d_symbol_length/8; ++j) { // iterate over the symbol vector, but each byte has 8 bit, which are accessed manually for (int k = 0; k < 8; k++) { - out[i*d_symbol_length + j*8 + k] = gr_complex((in[i*(d_symbol_length/4) + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2,(in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2); + out[i*d_symbol_length + j*8 + k] = + gr_complex((in[i*(d_symbol_length/4) + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2, + (in[i*(d_symbol_length/4) + d_symbol_length/8 + j]&(0x80>>k))>0?-I_SQRT2:I_SQRT2); } } } diff --git a/lib/reed_solomon_decode_bb_impl.cc b/lib/reed_solomon_decode_bb_impl.cc index 8a1dea25..96c60c5a 100644 --- a/lib/reed_solomon_decode_bb_impl.cc +++ b/lib/reed_solomon_decode_bb_impl.cc @@ -128,8 +128,7 @@ namespace gr { uint8_t superframe[d_superframe_size]; memcpy(superframe, &in[n * d_superframe_size], d_superframe_size); DecodeSuperframe(superframe, d_superframe_size); - memcpy(&out[n * d_superframe_size_rs], superframe, - d_superframe_size_rs); + memcpy(&out[n * d_superframe_size_rs], superframe, d_superframe_size_rs); } // Tell runtime system how many input items we consumed on // each input stream. diff --git a/lib/select_cus_vfvf_impl.cc b/lib/select_cus_vfvf_impl.cc index 321f264d..91407134 100644 --- a/lib/select_cus_vfvf_impl.cc +++ b/lib/select_cus_vfvf_impl.cc @@ -48,7 +48,8 @@ namespace gr { d_vlen(vlen), d_frame_len(frame_len), d_address(address), - d_size(size) {} + d_size(size) { + } /* * Our virtual destructor. diff --git a/lib/sum_phasor_trig_vcc_impl.cc b/lib/sum_phasor_trig_vcc_impl.cc index c96b0aa8..b1def7e1 100644 --- a/lib/sum_phasor_trig_vcc_impl.cc +++ b/lib/sum_phasor_trig_vcc_impl.cc @@ -45,13 +45,14 @@ namespace gr { sum_phasor_trig_vcc_impl::sum_phasor_trig_vcc_impl(unsigned int length) : gr::sync_block("sum_phasor_trig_vcc", - gr::io_signature::make2(2, 2, sizeof(gr_complex) * - length, + gr::io_signature::make2(2, 2, + sizeof(gr_complex) * length, sizeof(char)), - gr::io_signature::make2(2, 2, sizeof(gr_complex) * - length, + gr::io_signature::make2(2, 2, + sizeof(gr_complex) * length, sizeof(char))), - d_length(length), d_last_symbol(length, 0) { + d_length(length), + d_last_symbol(length, 0) { } @@ -75,10 +76,7 @@ namespace gr { out[j] = in[j] * d_last_symbol[j]; } else { for (unsigned int j = 0; j < d_length; j++) { - // printf("%p\n", &lastout[j]); - // printf("%p\n", &out[j+ptrdiff_t(-d_length)]); out[j] = in[j] * lastout[j]; - // out[j] = in[j] * (&out[j-d_length])[0]; } } diff --git a/lib/test_dab.cc b/lib/test_dab.cc index 4ba1f341..3b642b6d 100644 --- a/lib/test_dab.cc +++ b/lib/test_dab.cc @@ -36,8 +36,7 @@ int main(int argc, char **argv) { CppUnit::TextTestRunner runner; std::ofstream xmlfile(get_unittest_path("dab.xml").c_str()); - CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), - xmlfile); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); runner.addTest(qa_dab::suite()); runner.setOutputter(xmlout); diff --git a/lib/time_interleave_bb_impl.cc b/lib/time_interleave_bb_impl.cc index 66410016..afa6382b 100644 --- a/lib/time_interleave_bb_impl.cc +++ b/lib/time_interleave_bb_impl.cc @@ -73,10 +73,7 @@ namespace gr { for (int j = 0; j < d_vector_length; j++) { //iteration over elements of vector //*out++ = in[vec_length * (i + (scrambling_length-1) - d_scrambling_vector[j % scrambling_length]) + j]; - *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - - d_scrambling_vector[j % - d_scrambling_length]) + - j]; + *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - d_scrambling_vector[j % d_scrambling_length]) + j]; } } diff --git a/python/__init__.py b/python/__init__.py index 7d2bea06..bfbe1bca 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -26,13 +26,7 @@ import os # import swig generated symbols into the dab namespace -try: - # this might fail if the module is python-only - from dab_swig import * -except ImportError: - dirname, filename = os.path.split(os.path.abspath(__file__)) - __path__.append(os.path.join(dirname, "..", "..", "swig")) - from dab_swig import * +from dab_swig import * from parameters import * from ofdm_demod_cc import * From b43c759ea3c00b57ee3e1805520990345f453b9e Mon Sep 17 00:00:00 2001 From: MoritzLucaSchmid Date: Sun, 25 Feb 2018 18:06:01 +0100 Subject: [PATCH 128/135] reformatting and docu --- lib/complex_to_interleaved_float_vcf_impl.cc | 12 +- lib/complex_to_interleaved_float_vcf_impl.h | 3 +- lib/conv_encoder_bb_impl.cc | 3 +- lib/crc16_bb_impl.cc | 28 +- lib/dab_transmission_frame_mux_bb_impl.cc | 52 ++-- lib/dab_transmission_frame_mux_bb_impl.h | 22 +- lib/demux_cc_impl.cc | 25 +- lib/demux_cc_impl.h | 14 +- lib/diff_phasor_vcc_impl.cc | 6 +- lib/diff_phasor_vcc_impl.h | 5 +- lib/fib_sink_vb_impl.cc | 150 +++++----- lib/fib_sink_vb_impl.h | 22 +- lib/fib_source_b_impl.cc | 15 +- lib/fib_source_b_impl.h | 7 + lib/firecode_check_bb_impl.cc | 20 +- lib/firecode_check_bb_impl.h | 12 +- lib/frequency_interleaver_vcc_impl.cc | 7 +- lib/frequency_interleaver_vcc_impl.h | 12 +- lib/insert_null_symbol_impl.cc | 22 +- lib/mp2_decode_bs_impl.cc | 261 +++++++----------- lib/mp2_decode_bs_impl.h | 11 +- lib/mp2_encode_sb_impl.cc | 36 +-- lib/mp2_encode_sb_impl.h | 9 +- lib/mp4_decode_bs_impl.cc | 72 ++--- lib/mp4_encode_sb_impl.cc | 72 +++-- lib/mp4_encode_sb_impl.h | 3 +- ...m_coarse_frequency_correction_vcvc_impl.cc | 85 +++--- ...dm_coarse_frequency_correction_vcvc_impl.h | 6 +- 28 files changed, 426 insertions(+), 566 deletions(-) diff --git a/lib/complex_to_interleaved_float_vcf_impl.cc b/lib/complex_to_interleaved_float_vcf_impl.cc index cdcf9041..fcd409dc 100644 --- a/lib/complex_to_interleaved_float_vcf_impl.cc +++ b/lib/complex_to_interleaved_float_vcf_impl.cc @@ -37,19 +37,15 @@ namespace gr { complex_to_interleaved_float_vcf::sptr complex_to_interleaved_float_vcf::make(unsigned int length) { - return gnuradio::get_initial_sptr - (new complex_to_interleaved_float_vcf_impl(length)); + return gnuradio::get_initial_sptr(new complex_to_interleaved_float_vcf_impl(length)); } - complex_to_interleaved_float_vcf_impl::complex_to_interleaved_float_vcf_impl( - unsigned int length) + complex_to_interleaved_float_vcf_impl::complex_to_interleaved_float_vcf_impl(unsigned int length) : gr::sync_block("complex_to_interleaved_float_vcf", gr::io_signature::make(1, 1, - sizeof(gr_complex) * - length), + sizeof(gr_complex) * length), gr::io_signature::make(1, 1, - sizeof(float) * length * - 2)), + sizeof(float) * length * 2)), d_length(length) { } diff --git a/lib/complex_to_interleaved_float_vcf_impl.h b/lib/complex_to_interleaved_float_vcf_impl.h index c78ca4fd..186b1d72 100644 --- a/lib/complex_to_interleaved_float_vcf_impl.h +++ b/lib/complex_to_interleaved_float_vcf_impl.h @@ -32,8 +32,7 @@ namespace gr { namespace dab { - class complex_to_interleaved_float_vcf_impl - : public complex_to_interleaved_float_vcf { + class complex_to_interleaved_float_vcf_impl : public complex_to_interleaved_float_vcf { private: unsigned int d_length; /*!< length of the complex input vector */ diff --git a/lib/conv_encoder_bb_impl.cc b/lib/conv_encoder_bb_impl.cc index 186326f5..8b0ab495 100644 --- a/lib/conv_encoder_bb_impl.cc +++ b/lib/conv_encoder_bb_impl.cc @@ -81,8 +81,7 @@ namespace gr { void conv_encoder_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { - ninput_items_required[0] = - (noutput_items / (d_framesize * 4 + 3)) * d_framesize; + ninput_items_required[0] = (noutput_items / (d_framesize * 4 + 3)) * d_framesize; } int diff --git a/lib/crc16_bb_impl.cc b/lib/crc16_bb_impl.cc index 3a48978b..b7d11e45 100644 --- a/lib/crc16_bb_impl.cc +++ b/lib/crc16_bb_impl.cc @@ -32,17 +32,16 @@ namespace gr { crc16_bb::sptr crc16_bb::make(int length = 32, uint16_t generator = 0x1021, uint16_t initial_state = 0xFF) { - return gnuradio::get_initial_sptr - (new crc16_bb_impl(length, generator, initial_state)); + return gnuradio::get_initial_sptr(new crc16_bb_impl(length, generator, initial_state)); } crc16_bb_impl::crc16_bb_impl(int length, uint16_t generator, uint16_t initial_state) : gr::block("crc16_bb", - gr::io_signature::make(1, 1, length * - sizeof(char)), /*FIB without CRC (zeros instead)*/ - gr::io_signature::make(1, 1, length * - sizeof(char))), /*FIB with CRC16*/ + /*Input item: FIB without CRC, but zeros instead.*/ + gr::io_signature::make(1, 1, length * sizeof(char)), + /*Output item: FIB with CRC16.*/ + gr::io_signature::make(1, 1, length * sizeof(char))), d_length(length), d_generator(generator), d_initial_state(initial_state) { } @@ -51,8 +50,7 @@ namespace gr { } void - crc16_bb_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + crc16_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } @@ -70,20 +68,18 @@ namespace gr { out[i + n * d_length] = in[i + n * d_length]; } //calculate crc16 word - d_crc = crc16(in + n * d_length, d_length, d_generator, - d_initial_state); + d_crc = crc16(in + n * d_length, d_length, d_generator, d_initial_state); //sanity check (last 2 bytes should be zeros) if (in[30 + n * d_length] != 0 || in[31 + n * d_length] != 0) { GR_LOG_DEBUG(d_logger, "CRC16 overwrites data (zeros expected)"); } - //write calculated crc to vector (overwrite last 2 bytes) - out[d_length - 2 + n * d_length] = (char) (d_crc - >> 8);//add MSByte first to FIB - out[d_length - 1 + n * d_length] = - (char) (out[d_length - 2 + n * d_length] << 8) ^ - d_crc; //add LSByte second to FIB + // Write calculated crc to vector. (overwrite last 2 bytes) + // Add MSByte first to FIB. + out[d_length - 2 + n * d_length] = (char) (d_crc >> 8); + // Add LSByte second to FIB. + out[d_length - 1 + n * d_length] = (char) (out[d_length - 2 + n * d_length] << 8) ^ d_crc; } // Tell runtime system how many input items we consumed on // each input stream. diff --git a/lib/dab_transmission_frame_mux_bb_impl.cc b/lib/dab_transmission_frame_mux_bb_impl.cc index 9eed5f60..49c849ee 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.cc +++ b/lib/dab_transmission_frame_mux_bb_impl.cc @@ -32,9 +32,9 @@ namespace gr { dab_transmission_frame_mux_bb::sptr dab_transmission_frame_mux_bb::make(int transmission_mode, int num_subch, const std::vector &subch_size) { - return gnuradio::get_initial_sptr - (new dab_transmission_frame_mux_bb_impl(transmission_mode, - num_subch, subch_size)); + return gnuradio::get_initial_sptr( + new dab_transmission_frame_mux_bb_impl(transmission_mode, + num_subch, subch_size)); } /* @@ -67,13 +67,11 @@ namespace gr { d_num_cifs = 2; break; default: - throw std::invalid_argument( - (boost::format("Transmission mode %d doesn't exist") % - transmission_mode).str()); + throw std::invalid_argument((boost::format("Transmission mode %d doesn't exist") + % transmission_mode).str()); } if (subch_size.size() != num_subch) { - GR_LOG_WARN(d_logger, - "sizeof vector subch_size does not match with num_subch"); + GR_LOG_WARN(d_logger, "sizeof vector subch_size does not match with num_subch"); } d_vlen_out = d_num_fibs * d_fib_len + d_num_cifs * d_cif_len; d_fic_len = d_num_fibs * d_fib_len; @@ -82,16 +80,13 @@ namespace gr { d_subch_total_size += subch_size[i]; } if (d_subch_total_size * d_cu_len > d_cif_len) { - throw std::out_of_range( - (boost::format("subchannels are %d bytes too long for CIF") % - (d_subch_total_size * d_cu_len - d_cif_len)).str()); + throw std::out_of_range((boost::format("subchannels are %d bytes too long for CIF") + % (d_subch_total_size * d_cu_len - d_cif_len)).str()); } - GR_LOG_DEBUG(d_logger, boost::format( - "MUX init with: fic_len = %d, subch_total_size = %d, vlen_out = %d") % - d_fic_len % d_subch_total_size % d_vlen_out); + GR_LOG_DEBUG(d_logger, boost::format( "MUX init with: fic_len = %d, subch_total_size = %d, vlen_out = %d") + % d_fic_len % d_subch_total_size % d_vlen_out); set_output_multiple(d_vlen_out); - // generate PRBS for padding generate_prbs(d_prbs, sizeof(d_prbs)); GR_LOG_DEBUG(d_logger, boost::format("key num_subch: %d") % d_num_subch); @@ -104,20 +99,17 @@ namespace gr { } void - dab_transmission_frame_mux_bb_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + dab_transmission_frame_mux_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { // the first input is always the FIC ninput_items_required[0] = d_fic_len * (noutput_items / d_vlen_out); for (int i = 0; i < d_num_subch; ++i) { // the amount of consumed data of each sub-channel depends on its size - ninput_items_required[i + 1] = d_subch_size[i] * d_cu_len * d_num_cifs * - (noutput_items / d_vlen_out); + ninput_items_required[i + 1] = d_subch_size[i] * d_cu_len * d_num_cifs * (noutput_items / d_vlen_out); } } void - dab_transmission_frame_mux_bb_impl::generate_prbs(unsigned char *out_ptr, - int length) { + dab_transmission_frame_mux_bb_impl::generate_prbs(unsigned char *out_ptr, int length) { char bits[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; char newbit; unsigned char temp = 0; @@ -140,15 +132,6 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { unsigned char *out = (unsigned char *) output_items[0]; - //unsigned char *triggerout = (unsigned char *) output_items[1]; - //const unsigned char *in; - - // create control stream for ofdm with trigger at start of frame and set zero - /*memset(triggerout, 0, noutput_items); - for (int i = 0; i < noutput_items / d_vlen_out; ++i) { - triggerout[i * d_vlen_out] = 1; - }*/ - // write FIBs const unsigned char *in_fic = (const unsigned char *) input_items[0]; for (int i = 0; i < noutput_items / d_vlen_out; ++i) { @@ -158,12 +141,10 @@ namespace gr { // write sub-channels unsigned int cu_index = 0; for (int j = 0; j < d_num_subch; ++j) { - const unsigned char *in_msc = (const unsigned char *) input_items[j + - 1]; + const unsigned char *in_msc = (const unsigned char *) input_items[j + 1]; for (int i = 0; i < noutput_items / d_vlen_out; ++i) { for (int k = 0; k < d_num_cifs; ++k) { - memcpy(out + i * d_vlen_out + d_fic_len + k * d_cif_len + - cu_index * d_cu_len, + memcpy(out + i * d_vlen_out + d_fic_len + k * d_cif_len + cu_index * d_cu_len, in_msc + (i * d_num_cifs + k) * d_subch_size[j] * d_cu_len, d_subch_size[j] * d_cu_len); } @@ -182,8 +163,7 @@ namespace gr { // each input stream. consume(0, noutput_items / d_vlen_out * d_fic_len); for (int j = 0; j < d_num_subch; ++j) { - consume(j + 1, noutput_items / d_vlen_out * d_subch_size[j] * d_cu_len * - d_num_cifs); + consume(j + 1, noutput_items / d_vlen_out * d_subch_size[j] * d_cu_len * d_num_cifs); } // Tell runtime system how many output items we produced. diff --git a/lib/dab_transmission_frame_mux_bb_impl.h b/lib/dab_transmission_frame_mux_bb_impl.h index 684d5c19..c646afd6 100644 --- a/lib/dab_transmission_frame_mux_bb_impl.h +++ b/lib/dab_transmission_frame_mux_bb_impl.h @@ -32,25 +32,35 @@ namespace gr { * the number of FIBs per CIF and the number of CIFs per transmission frame * depends on the transmission mode * - * @param transmission_mode transmission mode 1-4 after DAB standard - * @param subch_size vector with size of each subchannel + * @param transmission_mode Transmission mode 1-4 after DAB standard. + * @param subch_size Vector with size of each sub-channel. */ class dab_transmission_frame_mux_bb_impl : public dab_transmission_frame_mux_bb { private: int d_transmission_mode; + /*!< Transmission_mode transmission mode 1-4 after DAB standard. */ int d_num_subch; + /*!< Number of sub-channels in the transmission frame and ensemble. */ std::vector d_subch_size; - const static unsigned int d_fib_len = - 32 * 3; // length of a fib in bytes (*3 because bit rate = 1/3) - const static unsigned int d_cif_len = 6912; // length of a cif in bytes - const static unsigned int d_cu_len = 8; // length of a capacity unit in bytes + /*!< Vector containing the sizes in CUs of each subchannel. */ + const static unsigned int d_fib_len = 32 * 3; + /*!< Length of a fib in bytes. (*3 because bit rate = 1/3) */ + const static unsigned int d_cif_len = 6912; + /*!< Length of a Common Interleaved Frame (CIF) in bytes. */ + const static unsigned int d_cu_len = 8; + /*!< Length of a capacity unit in bytes. */ unsigned int d_vlen_out, d_num_cifs, d_num_fibs, d_subch_total_size; unsigned int d_fic_len; unsigned char d_prbs[d_cif_len]; + /*!< Vector for the PRBS, used for padding at the end of each frame. */ void generate_prbs(unsigned char *out_ptr, int length); + /*!< Generates a PRBS after the rules of ETSI EN 300 401 and writes it to output buffer out_ptr. + * @param length Required length of the PRBS and number of bytes that are written to out_ptr. + * @param out_ptr Pointer to the first element of the buffer to write the PRBS. + */ public: dab_transmission_frame_mux_bb_impl(int transmission_mode, int num_subch, diff --git a/lib/demux_cc_impl.cc b/lib/demux_cc_impl.cc index b1021721..fe01e5da 100644 --- a/lib/demux_cc_impl.cc +++ b/lib/demux_cc_impl.cc @@ -36,9 +36,8 @@ namespace gr { demux_cc::sptr demux_cc::make(unsigned int symbol_length, unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) { - return gnuradio::get_initial_sptr - (new demux_cc_impl(symbol_length, symbols_fic, symbol_msc, - fillval)); + return gnuradio::get_initial_sptr(new demux_cc_impl(symbol_length, symbols_fic, + symbol_msc, fillval)); } /* @@ -48,10 +47,8 @@ namespace gr { unsigned int symbols_fic, unsigned int symbol_msc, gr_complex fillval) : gr::block("demux_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * - symbol_length), - gr::io_signature::make(2, 2, sizeof(gr_complex) * - symbol_length)), + gr::io_signature::make(1, 1, sizeof(gr_complex) * symbol_length), + gr::io_signature::make(2, 2, sizeof(gr_complex) * symbol_length)), d_symbol_lenght(symbol_length), d_symbols_fic(symbols_fic), d_symbols_msc(symbol_msc), @@ -95,18 +92,20 @@ namespace gr { for (int i = 0; i < noutput_items; ++i) { if (tag_count < tags.size() && tags[tag_count].offset - nitems_read(0) - nconsumed == 0) { - // this input symbol is tagged: a new frame begins here + // This input symbol is tagged: a new frame begins here. if (d_fic_counter % d_symbols_fic == 0 && d_msc_counter % d_symbols_msc == 0) { - // we are at the beginning of a frame and also finished writing the last frame - // we can remove this first symbol of the frame (phase reference symbol) and copy the other symbols + /* We are at the beginning of a frame and also finished writing the last frame. + * We can remove this first symbol of the frame (phase reference symbol) + * and copy the other symbols. */ tag_count++; nconsumed++; d_fic_counter = 0; d_msc_counter = 0; } else { - // we did not finish the last frame, maybe we lost track in sync - // lets fill the remaining symbols with fillval before continuing with the new input frame + /* We did not finish the last frame, maybe we lost track in sync during a frame. + * Let's fill the remaining symbols with fillval + * before continuing with the new input frame. */ if (d_fic_counter % d_symbols_fic != 0) { memset(&fic_out[fic_syms_written++ * d_symbol_lenght], 0, d_symbol_lenght * sizeof(gr_complex)); @@ -118,7 +117,7 @@ namespace gr { } } } else if (d_fic_counter < d_symbols_fic) { - // copy this symbol to fic output + // copy this symbol to fic output. memcpy(&fic_out[fic_syms_written++ * d_symbol_lenght], &in[nconsumed++ * d_symbol_lenght], d_symbol_lenght * sizeof(gr_complex)); diff --git a/lib/demux_cc_impl.h b/lib/demux_cc_impl.h index 1a11b1b2..387c4550 100644 --- a/lib/demux_cc_impl.h +++ b/lib/demux_cc_impl.h @@ -35,14 +35,20 @@ namespace gr { class demux_cc_impl : public demux_cc { private: unsigned int d_symbol_lenght; + /*!< Length in bytes of one OFDM symbol. */ unsigned int d_symbols_fic; + /*!< Number of OFDM symbols with FIC content per transmission frame. */ unsigned int d_symbols_msc; + /*!< Number of OFDM symbols with MSC content per transmission frame. */ gr_complex d_fillval; + /*!< Complex value, used to fill gaps in the transmission frame + * (e.g. caused to a loss of sync) to avoid discontinuity in data flow. */ + unsigned int d_fic_counter; -/*!< counts the symbols containing fic data; - * the number of fic symbols per transmission frame does not match - * with the number of transmitted fibs*/ - unsigned int d_msc_counter; /*!< counts the symbols containing msc data*/ + /*!< Counts the symbols containing fic data. + * The number of fic symbols per transmission frame does not match + * with the number of transmitted fibs. */ + unsigned int d_msc_counter; /*!< Counts the symbols containing msc data. */ public: demux_cc_impl(unsigned int symbol_length, unsigned int symbols_fic, diff --git a/lib/diff_phasor_vcc_impl.cc b/lib/diff_phasor_vcc_impl.cc index d50fd37a..c4cbb35b 100644 --- a/lib/diff_phasor_vcc_impl.cc +++ b/lib/diff_phasor_vcc_impl.cc @@ -44,10 +44,8 @@ namespace gr { diff_phasor_vcc_impl::diff_phasor_vcc_impl(unsigned int length) : gr::sync_block("diff_phasor_vcc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * - length), - gr::io_signature::make(1, 1, sizeof(gr_complex) * - length)), + gr::io_signature::make(1, 1, sizeof(gr_complex) * length), + gr::io_signature::make(1, 1, sizeof(gr_complex) * length)), d_length(length) { set_history(2); } diff --git a/lib/diff_phasor_vcc_impl.h b/lib/diff_phasor_vcc_impl.h index 67718651..2f9fdacb 100644 --- a/lib/diff_phasor_vcc_impl.h +++ b/lib/diff_phasor_vcc_impl.h @@ -28,12 +28,11 @@ namespace gr { namespace dab { /*! \brief vector wise working differential phasor calculation * this block has the same functionality as the gr-digital diff_phasor_cc block, - * but is working on vector basis + * but is working on vector basis. */ class diff_phasor_vcc_impl : public diff_phasor_vcc { private: - - unsigned int d_length; + unsigned int d_length; /*!< Length of each complex vector. */ public: diff_phasor_vcc_impl(unsigned int length); diff --git a/lib/fib_sink_vb_impl.cc b/lib/fib_sink_vb_impl.cc index a2960d3a..40bcc4be 100644 --- a/lib/fib_sink_vb_impl.cc +++ b/lib/fib_sink_vb_impl.cc @@ -42,11 +42,9 @@ namespace gr { fib_sink_vb::sptr fib_sink_vb::make() { - return gnuradio::get_initial_sptr - (new fib_sink_vb_impl()); + return gnuradio::get_initial_sptr(new fib_sink_vb_impl()); } - fib_sink_vb_impl::fib_sink_vb_impl() : gr::sync_block("fib_sink_vb", gr::io_signature::make(1, 1, sizeof(char) * 32), @@ -82,9 +80,8 @@ namespace gr { return 0; } - int - fib_sink_vb_impl::process_fig(uint8_t type, const char *data, - uint8_t length) { + void + fib_sink_vb_impl::process_fig(uint8_t type, const char *data, uint8_t length) { uint8_t cn, oe, pd, extension; switch (type) { case FIB_FIG_TYPE_MCI: @@ -102,8 +99,7 @@ namespace gr { switch (extension) { case FIB_MCI_EXTENSION_ENSEMBLE_INFO: { uint8_t country_ID = (uint8_t)((data[2] & 0xf0) >> 4); - uint16_t ensemble_reference = - (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; + uint16_t ensemble_reference = (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; uint8_t change_flag = (uint8_t)((data[4] & 0xc0) >> 6); uint8_t occurrence_change = data[6]; if (change_flag != 0) @@ -115,47 +111,43 @@ namespace gr { if (alarm_flag == 1) { GR_LOG_DEBUG(d_logger, ", [ALARM MESSAGE ACCESSIBLE] "); } - uint16_t CIF_counter = (uint16_t)( - (data[4] & 0x1f) * 250 + (data[5])); + uint16_t CIF_counter = (uint16_t)( (data[4] & 0x1f) * 250 + (data[5])); GR_LOG_DEBUG(d_logger, format("ensemble info: reference %d, country ID %d, CIF counter = %d") % ensemble_reference % - (int) country_ID % CIF_counter); + (int) country_ID % + CIF_counter); break; } case FIB_MCI_EXTENSION_SUBCHANNEL_ORGA: { uint8_t subch_counter = 0; GR_LOG_DEBUG(d_logger, "subchannel orga: "); do { - uint8_t subchID = (uint8_t)( - (data[2 + subch_counter] & 0xfc) >> 2); - uint16_t start_address = - (uint16_t)((data[2 + subch_counter] & 0x03) << 8) | - (uint8_t)(data[3 + subch_counter]); + uint8_t subchID = (uint8_t)((data[2 + subch_counter] & 0xfc) >> 2); + uint16_t start_address = (uint16_t)((data[2 + subch_counter] & 0x03) << 8) | (uint8_t)(data[3 + subch_counter]); uint8_t sl_form = (uint8_t)(data[4] & 0x80); if (sl_form == 0) { - uint8_t table_switch = (uint8_t)( - data[4 + subch_counter] & 0x40); - if (table_switch != 0) + uint8_t table_switch = (uint8_t)(data[4 + subch_counter] & 0x40); + if (table_switch != 0) { GR_LOG_DEBUG(d_logger, " [WARNING: OTHER TABLE USED] "); - uint8_t table_index = (uint8_t)( - data[4 + subch_counter] & 0x3f); + } + uint8_t table_index = (uint8_t)(data[4 + subch_counter] & 0x3f); GR_LOG_DEBUG(d_logger, format("subchID = %d , start address = %d, index %d") % (int) subchID % - (int) start_address % (int) table_index); + (int) start_address % + (int) table_index); subch_counter += 3; } else { uint8_t option = (uint8_t)(data[4 + subch_counter] & 0x70); - uint8_t protect_level = (uint8_t)( - (data[4 + subch_counter] & 0x0c) >> 2); - uint16_t subch_size = - (uint16_t)((data[4 + subch_counter] & 0x03) << 8) | - (uint8_t)(data[5 + subch_counter]); + uint8_t protect_level = (uint8_t)((data[4 + subch_counter] & 0x0c) >> 2); + uint16_t subch_size = (uint16_t)((data[4 + subch_counter] & 0x03) << 8) | (uint8_t)(data[5 + subch_counter]); GR_LOG_DEBUG(d_logger, format("subchID = %d , start address = %d, option %d, protect level %d, subch size %d") % - (int) subchID % (int) start_address % - (int) option % (int) protect_level % + (int) subchID % + (int) start_address % + (int) option % + (int) protect_level % (int) subch_size); subch_counter += 4; @@ -186,32 +178,23 @@ namespace gr { case FIB_MCI_EXTENSION_SERVICE_ORGA: { uint8_t service_counter = 1; do { //iterate over services - uint16_t service_reference = - (uint16_t)(data[service_counter + 1] & 0x0f) << 8 | - (uint8_t) data[service_counter + 2]; - GR_LOG_DEBUG(d_logger, format("service orga: reference %d ") % - service_reference); - uint8_t local_flag = (uint8_t)( - (data[service_counter + 3] & 0x80) >> 7); - if (local_flag == 1) + uint16_t service_reference = (uint16_t)(data[service_counter + 1] & 0x0f) << 8 | (uint8_t) data[service_counter + 2]; + GR_LOG_DEBUG(d_logger, format("service orga: reference %d ") % service_reference); + uint8_t local_flag = (uint8_t)((data[service_counter + 3] & 0x80) >> 7); + if (local_flag == 1) { GR_LOG_DEBUG(d_logger, "[LOCAL FLAG SET] "); + } uint8_t ca = (uint8_t)((data[service_counter + 3] & 0x70) >> 4); - if (ca != 0) + if (ca != 0) { GR_LOG_DEBUG(d_logger, "[CONDITIONAL ACCESS USED] "); - uint8_t num_service_comps = (uint8_t)( - data[service_counter + 3] & 0x0f); - GR_LOG_DEBUG(d_logger, format("(%d components):") % - (int) num_service_comps); - for (int i = 0; i < - num_service_comps; i++) { //iterate over service components - uint8_t TMID = (uint8_t)( - (data[service_counter + 4 + i * 2] & 0xc0) >> 6); - uint8_t comp_type = (uint8_t)( - data[service_counter + 4 + i * 2] & 0x3f); - uint8_t subchID = (uint8_t)( - (data[service_counter + 5 + i * 2] & 0xfc) >> 2); - uint8_t ps = (uint8_t)( - (data[service_counter + 5 + i * 2 + 1] & 0x02) >> 1); + } + uint8_t num_service_comps = (uint8_t)(data[service_counter + 3] & 0x0f); + GR_LOG_DEBUG(d_logger, format("(%d components):") % (int) num_service_comps); + for (int i = 0; i < num_service_comps; i++) { //iterate over service components + uint8_t TMID = (uint8_t)( (data[service_counter + 4 + i * 2] & 0xc0) >> 6); + uint8_t comp_type = (uint8_t)( data[service_counter + 4 + i * 2] & 0x3f); + uint8_t subchID = (uint8_t)((data[service_counter + 5 + i * 2] & 0xfc) >> 2); + uint8_t ps = (uint8_t)((data[service_counter + 5 + i * 2 + 1] & 0x02) >> 1); if (TMID == 0) { GR_LOG_DEBUG(d_logger, format("(audio stream, type %d, subchID %d, primary %d)") % @@ -242,11 +225,13 @@ namespace gr { GR_LOG_DEBUG(d_logger, format("(data stream, type %d, subchID %d, primary %d)") % (int) comp_type % - (int) subchID % (int) ps); + (int) subchID % + (int) ps); } else if (TMID == 2) { GR_LOG_DEBUG(d_logger, format("(FIDC, type %d, subchID %d, primary %d)") % - (int) comp_type % (int) subchID % + (int) comp_type % + (int) subchID % (int) ps); } else { GR_LOG_DEBUG(d_logger, "[packed data]"); @@ -269,25 +254,24 @@ namespace gr { uint8_t service_comp_counter = 0; do { uint16_t service_reference = - (uint16_t)(data[service_comp_counter + 2] & 0x0f) << 8 | - (uint8_t) data[service_comp_counter + 3]; - uint8_t SCIdS = (uint8_t)( - data[service_comp_counter + 4] & 0x0f); + (uint16_t)(data[service_comp_counter + 2] & 0x0f) << 8 | (uint8_t) data[service_comp_counter + 3]; + uint8_t SCIdS = (uint8_t)(data[service_comp_counter + 4] & 0x0f); if ((data[service_comp_counter + 5] & 0x80) == 0) { - uint8_t subchID = (uint8_t)( - data[service_comp_counter + 5] & 0x3f); + uint8_t subchID = (uint8_t)(data[service_comp_counter + 5] & 0x3f); GR_LOG_DEBUG(d_logger, format("service component global definition: reference %d, SCIdS %d, subchID %d") % - service_reference % (int) SCIdS % (int) subchID); + service_reference % + (int) SCIdS % + (int) subchID); service_comp_counter += 5; } else { uint16_t subchID = - (uint16_t)(data[service_comp_counter + 5] & 0x0f) - << 8 | - (uint8_t) data[service_comp_counter + 6]; + (uint16_t)(data[service_comp_counter + 5] & 0x0f)<< 8 | (uint8_t) data[service_comp_counter + 6]; GR_LOG_DEBUG(d_logger, format("service component global definition: reference %d, SCIdS %d, subchID %d") % - service_reference % (int) SCIdS % (int) subchID); + service_reference % + (int) SCIdS % + (int) subchID); service_comp_counter += 6; } } while (1 + service_comp_counter < length); @@ -306,16 +290,14 @@ namespace gr { GR_LOG_DEBUG(d_logger, "programme number"); break; case FIB_SI_EXTENSION_PROGRAMME_TYPE: { - GR_LOG_DEBUG(d_logger, format("programme type, %d components") % - ((length - 1) / 4)); + GR_LOG_DEBUG(d_logger, format("programme type, %d components") % ((length - 1) / 4)); for (int i = 0; i < (length - 1) / 4; i++) { uint8_t programme_type = (uint8_t)(data[2 + i * 4 + 3] & 0x1f); - uint16_t service_reference = - (uint16_t)(data[2 + i * 4] & 0x0f) << 8 | - (uint8_t) data[2 + i * 4 + 1]; - GR_LOG_DEBUG(d_logger, format("reference %d, type: %d") % - service_reference % - (int) programme_type); + uint16_t service_reference = (uint16_t)(data[2 + i * 4] & 0x0f) << 8 | (uint8_t) data[2 + i * 4 + 1]; + GR_LOG_DEBUG(d_logger, + format("reference %d, type: %d") % + service_reference % + (int) programme_type); // write programme type to json if (d_programme_type_written_trigger < 0) { @@ -326,8 +308,7 @@ namespace gr { << (int) service_reference << ",\"programme_type\":" << (int) programme_type << "}\0"; d_programme_type_current = ss.str(); - if ((int) service_reference == - d_programme_type_written_trigger) { + if ((int) service_reference == d_programme_type_written_trigger) { std::stringstream ss_json; ss_json << d_programme_type_current << "]" << "\0"; d_programme_type_current = "\0"; @@ -346,8 +327,7 @@ namespace gr { GR_LOG_DEBUG(d_logger, "announcement switching"); break; default: - GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % - (int) extension); + GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % (int) extension); break; } break; @@ -361,18 +341,15 @@ namespace gr { case FIB_SI_EXTENSION_ENSEMBLE_LABEL: { uint8_t country_ID = (uint8_t)((data[2] & 0xf0) >> 4); memcpy(label, &data[4], 16); - GR_LOG_DEBUG(d_logger, format("[ensemble label](%d): %s") % - (int) country_ID % label); + GR_LOG_DEBUG(d_logger, format("[ensemble label](%d): %s") % (int) country_ID % label); // write json for ensemble label and country ID std::stringstream ss; - ss << "{" << "\"" << label << "\":{" << "\"country_ID\":" - << (int) country_ID << "}}"; + ss << "{" << "\"" << label << "\":{" << "\"country_ID\":" << (int) country_ID << "}}"; d_json_ensemble_info = ss.str(); break; } case FIB_SI_EXTENSION_PROGRAMME_SERVICE_LABEL: { - uint16_t service_reference = - (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; + uint16_t service_reference = (uint16_t)(data[2] & 0x0f) << 8 | (uint8_t) data[3]; memcpy(label, &data[4], 16); GR_LOG_DEBUG(d_logger, format("[programme service label] (reference %d): %s") % @@ -386,8 +363,7 @@ namespace gr { << label << "\",\"reference\":" << (int) service_reference << "}\0"; d_service_labels_current = ss.str(); - if ((int) service_reference == - d_service_labels_written_trigger) { + if ((int) service_reference == d_service_labels_written_trigger) { std::stringstream ss_json; ss_json << d_service_labels_current << "]" << "\0"; d_service_labels_current = "\0"; @@ -426,8 +402,7 @@ namespace gr { GR_LOG_DEBUG(d_logger, "EWS (emergency warning service) - not supported yet"); break; default: - GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % - (int) extension); + GR_LOG_DEBUG(d_logger, format("unsupported extension (%d)") % (int) extension); } break; case FIB_FIG_TYPE_CA: @@ -437,7 +412,6 @@ namespace gr { GR_LOG_DEBUG(d_logger, "unsupported FIG type"); break; } - return 0; } int diff --git a/lib/fib_sink_vb_impl.h b/lib/fib_sink_vb_impl.h index 39906429..512c6442 100644 --- a/lib/fib_sink_vb_impl.h +++ b/lib/fib_sink_vb_impl.h @@ -26,16 +26,28 @@ namespace gr { namespace dab { /*! \brief sink for DAB/DAB+ FIBs, interprets MSC and SI - * crc16 check of incoming fibs - * reads correct fibs - * generates json objects with service and multiplex information - * + * CRC16 check of incoming fibs. + * Reads correct fibs. + * Generates json objects with service and multiplex information. */ class fib_sink_vb_impl : public fib_sink_vb { private: + /*! \brief Processes an incoming FIB. + * If CRC16 fails, dump the FIB, + * otherwise extract Fast Information Groups (FIGs) and read header information. + * + * @param fib Pointer to the first byte of the 30 byte FIB. + * @return 0 if CRC failed, 1 if CRC succeeded. + */ int process_fib(const char *fib); - + /*! \brief Processes a FIG. + * Switch between FIG types, extract information and write it to logger. + * Write and collect information in JSON objects for transport to GUI. + * @param type Type of the FIG. See ETSI EN 300 401 chapter 5.2.2. + * @param data Pointer to the FIG data buffer. + * @param length Length of the FIG data buffer in bytes. + */ int process_fig(uint8_t type, const char *data, uint8_t length); bool d_crc_passed; diff --git a/lib/fib_source_b_impl.cc b/lib/fib_source_b_impl.cc index 24e16f40..ef59ae5b 100644 --- a/lib/fib_source_b_impl.cc +++ b/lib/fib_source_b_impl.cc @@ -103,13 +103,14 @@ namespace gr { const std::vector &protection_mode, const std::vector &data_rate_n, const std::vector &dabplus) { - return gnuradio::get_initial_sptr - (new fib_source_b_impl(transmission_mode, country_ID, - num_subch, ensemble_label, - programme_service_labels, - service_comp_label, service_comp_lang, - protection_mode, - data_rate_n, dabplus)); + return gnuradio::get_initial_sptr(new fib_source_b_impl(transmission_mode, + country_ID, num_subch, + ensemble_label, + programme_service_labels, + service_comp_label, + service_comp_lang, + protection_mode, data_rate_n, + dabplus)); } /* diff --git a/lib/fib_source_b_impl.h b/lib/fib_source_b_impl.h index a05bd989..1cd9ac46 100644 --- a/lib/fib_source_b_impl.h +++ b/lib/fib_source_b_impl.h @@ -75,6 +75,13 @@ namespace gr { static char d_programme_service_label[176]; //21*8+8, service label (FIG 1/0) std::string d_service_labels; + /*! \brief Writes a character string as utf-8 to byte buffer. + * + * @param out_ptr Pointer to output buffer. + * @param label String object. + * @param num_chars Lenght of the character string (without end indicator). + * @return Number of processed bits (= num_chars * 8). + */ int write_label(char *out_ptr, std::string label, int num_chars = 16); //default for 16 characters (16 byte) public: diff --git a/lib/firecode_check_bb_impl.cc b/lib/firecode_check_bb_impl.cc index 953fdd1d..6d505094 100644 --- a/lib/firecode_check_bb_impl.cc +++ b/lib/firecode_check_bb_impl.cc @@ -1,8 +1,10 @@ /* -*- c++ -*- */ /* - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * The class firecode_checker is adapted from the Qt-DAB software, Copyright Jan van Katwijk (Lazy Chair Computing J.vanKatwijk@gmail.com) + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). + * + * The class firecode_checker is adapted from the Qt-DAB software + * Copyright Jan van Katwijk (Lazy Chair Computing J.vanKatwijk@gmail.com) * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,8 +40,7 @@ namespace gr { firecode_check_bb::sptr firecode_check_bb::make(int bit_rate_n) { - return gnuradio::get_initial_sptr - (new firecode_check_bb_impl(bit_rate_n)); + return gnuradio::get_initial_sptr(new firecode_check_bb_impl(bit_rate_n)); } /* @@ -60,8 +61,7 @@ namespace gr { } void - firecode_check_bb_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + firecode_check_bb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } @@ -78,14 +78,12 @@ namespace gr { while (d_nconsumed < noutput_items / d_frame_size - 4) { if (fc.check(&in[d_nconsumed * d_frame_size])) { // fire code OK, copy superframe to output - memcpy(out + d_nproduced * d_frame_size, - in + d_nconsumed * d_frame_size, d_frame_size * 5); + memcpy(out + d_nproduced * d_frame_size, in + d_nconsumed * d_frame_size, d_frame_size * 5); d_nproduced += 5; d_nconsumed += 5; d_firecode_passed = true; } else { - GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % - (nitems_read(0) / d_frame_size)); + GR_LOG_DEBUG(d_logger, format("fire code failed at frame %d") % (nitems_read(0) / d_frame_size)); // shift of one logical frame d_nconsumed++; d_firecode_passed = false; diff --git a/lib/firecode_check_bb_impl.h b/lib/firecode_check_bb_impl.h index 1672ece6..cc998c2d 100644 --- a/lib/firecode_check_bb_impl.h +++ b/lib/firecode_check_bb_impl.h @@ -28,19 +28,17 @@ namespace gr { namespace dab { /*! \brief checks firecode of logical frames - * * Checks firecode of each logical frame as a qa test for the msc_decoder. * According to ETSI TS 102 563 every fifth logical frame starts with a 16 bit firecode word. - * * @param bit_rate_n data rate in multiples of 8kbit/s */ class firecode_check_bb_impl : public firecode_check_bb { private: - int d_bit_rate_n; - int d_frame_size; /*!< size in bytes of one transmission frame (depending on bit_rate)*/ - int d_nproduced, d_nconsumed; /*!< control variable for buffer read/write operations */ - bool d_firecode_passed; /*!< boolean variable for displaying firecode fails*/ - firecode_checker fc; /*!< instance of the class firecode_checker*/ + int d_bit_rate_n; /*!< Byte rate. */ + int d_frame_size; /*!< Size in bytes of one transmission frame (depending on bit_rate_n).*/ + int d_nproduced, d_nconsumed; /*!< Control variable for buffer read/write operations. */ + bool d_firecode_passed; /*!< Boolean variable for displaying firecode fails. */ + firecode_checker fc; /*!< Instance of the class firecode_checker. */ public: firecode_check_bb_impl(int bit_rate_n); diff --git a/lib/frequency_interleaver_vcc_impl.cc b/lib/frequency_interleaver_vcc_impl.cc index b048cf26..b291f4ee 100644 --- a/lib/frequency_interleaver_vcc_impl.cc +++ b/lib/frequency_interleaver_vcc_impl.cc @@ -43,17 +43,14 @@ namespace gr { frequency_interleaver_vcc_impl::frequency_interleaver_vcc_impl( const std::vector &interleaving_sequence) : gr::sync_block("frequency_interleaver_vcc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * - interleaving_sequence.size()), - gr::io_signature::make(1, 1, sizeof(gr_complex) * - interleaving_sequence.size())), + gr::io_signature::make(1, 1, sizeof(gr_complex) * interleaving_sequence.size()), + gr::io_signature::make(1, 1, sizeof(gr_complex) * interleaving_sequence.size())), d_interleaving_sequence(interleaving_sequence), d_length(interleaving_sequence.size()) { for (unsigned int i = 0; i < d_length; i++) assert(d_interleaving_sequence[i] < (short) d_length); } - int frequency_interleaver_vcc_impl::work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/lib/frequency_interleaver_vcc_impl.h b/lib/frequency_interleaver_vcc_impl.h index 183c1047..771853a0 100644 --- a/lib/frequency_interleaver_vcc_impl.h +++ b/lib/frequency_interleaver_vcc_impl.h @@ -34,14 +34,16 @@ namespace gr { private: std::vector d_interleaving_sequence; - unsigned int d_length; /*!< length of d_interleaving_sequence*/ + /*!< Vector containing the sequence, which is controlling the interleaving + * of the OFDM sub carriers. */ + unsigned int d_length; /*!< Length of the vector d_interleaving_sequence. */ public: - frequency_interleaver_vcc_impl( - const std::vector &interleaving_sequence); + frequency_interleaver_vcc_impl(const std::vector &interleaving_sequence); - void set_sequence( - const std::vector &interleaving_sequence) { d_interleaving_sequence = interleaving_sequence; } + void set_sequence(const std::vector &interleaving_sequence) { + d_interleaving_sequence = interleaving_sequence; + } int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/lib/insert_null_symbol_impl.cc b/lib/insert_null_symbol_impl.cc index dc25dc17..e07afab0 100644 --- a/lib/insert_null_symbol_impl.cc +++ b/lib/insert_null_symbol_impl.cc @@ -42,12 +42,9 @@ namespace gr { } - insert_null_symbol_impl::insert_null_symbol_impl(int ns_length, - int symbol_length) + insert_null_symbol_impl::insert_null_symbol_impl(int ns_length, int symbol_length) : gr::block("insert_null_symbol", - gr::io_signature::make2(2, 2, sizeof(gr_complex) * - symbol_length, - sizeof(char)), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * symbol_length, sizeof(char)), gr::io_signature::make(1, 1, sizeof(gr_complex))), d_ns_length(ns_length), d_symbol_length(symbol_length), d_ns_added(0) { @@ -65,12 +62,12 @@ namespace gr { } void - insert_null_symbol_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + insert_null_symbol_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { int in_req = noutput_items / d_symbol_length; unsigned ninputs = ninput_items_required.size(); - for (unsigned i = 0; i < ninputs; i++) + for (unsigned i = 0; i < ninputs; i++) { ninput_items_required[i] = in_req; + } } @@ -88,9 +85,9 @@ namespace gr { int consumed_items = 0; int i; - while (noutput_items - produced_items >= d_symbol_length && - consumed_items < ninput_items[0] && - consumed_items < ninput_items[1]) { + while (noutput_items - produced_items >= d_symbol_length + && consumed_items < ninput_items[0] + && consumed_items < ninput_items[1]) { if (*trigger == 1 && d_ns_added < d_ns_length) { for (i = 0; i < d_ns_length - d_ns_added && i < noutput_items - produced_items; i++) { *optr++ = 0; @@ -98,8 +95,9 @@ namespace gr { produced_items += i; d_ns_added += i; } else { - if (*trigger == 0) + if (*trigger == 0) { d_ns_added = 0; + } memcpy(optr, iptr, d_symbol_length); iptr += d_symbol_length; optr += d_symbol_length; diff --git a/lib/mp2_decode_bs_impl.cc b/lib/mp2_decode_bs_impl.cc index 06895600..fbd184fb 100644 --- a/lib/mp2_decode_bs_impl.cc +++ b/lib/mp2_decode_bs_impl.cc @@ -1,10 +1,13 @@ /* -*- c++ -*- */ /* -* 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -* A major part of this code is adapted from the kjmp2 library, slightly modified and written into a GNURadio block. -* Note that this is an altered version of kjmp2 and not the original library. -*/ + * 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). + * + * A major part of this code is adapted from the kjmp2 library, + * slightly modified and written into a GNURadio block. + * Note that this is an altered version of kjmp2 and not the original library. + */ /****************************************************************************** ** kjmp2 -- a minimal MPEG-1/2 Audio Layer II decoder library ** @@ -61,10 +64,8 @@ namespace gr { // bitrate table static const short bitrates[28] = { - 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, - 384, // MPEG-1 - 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, - 160 // MPEG-2 + 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, // MPEG-1 + 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 // MPEG-2 }; // scale factor base values (24-bit fixed-point) @@ -74,136 +75,73 @@ namespace gr { // synthesis window static const int D[512] = { - 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, - -0x00001, - -0x00001, -0x00001, -0x00001, -0x00002, -0x00002, -0x00003, - -0x00003, -0x00004, - -0x00004, -0x00005, -0x00006, -0x00006, -0x00007, -0x00008, - -0x00009, -0x0000A, - -0x0000C, -0x0000D, -0x0000F, -0x00010, -0x00012, -0x00014, - -0x00017, -0x00019, - -0x0001C, -0x0001E, -0x00022, -0x00025, -0x00028, -0x0002C, - -0x00030, -0x00034, - -0x00039, -0x0003E, -0x00043, -0x00048, -0x0004E, -0x00054, - -0x0005A, -0x00060, - -0x00067, -0x0006E, -0x00074, -0x0007C, -0x00083, -0x0008A, - -0x00092, -0x00099, - -0x000A0, -0x000A8, -0x000AF, -0x000B6, -0x000BD, -0x000C3, - -0x000C9, -0x000CF, - 0x000D5, 0x000DA, 0x000DE, 0x000E1, 0x000E3, 0x000E4, 0x000E4, - 0x000E3, - 0x000E0, 0x000DD, 0x000D7, 0x000D0, 0x000C8, 0x000BD, 0x000B1, - 0x000A3, - 0x00092, 0x0007F, 0x0006A, 0x00053, 0x00039, 0x0001D, -0x00001, - -0x00023, - -0x00047, -0x0006E, -0x00098, -0x000C4, -0x000F3, -0x00125, - -0x0015A, -0x00190, - -0x001CA, -0x00206, -0x00244, -0x00284, -0x002C6, -0x0030A, - -0x0034F, -0x00396, - -0x003DE, -0x00427, -0x00470, -0x004B9, -0x00502, -0x0054B, - -0x00593, -0x005D9, - -0x0061E, -0x00661, -0x006A1, -0x006DE, -0x00718, -0x0074D, - -0x0077E, -0x007A9, - -0x007D0, -0x007EF, -0x00808, -0x0081A, -0x00824, -0x00826, - -0x0081F, -0x0080E, - 0x007F5, 0x007D0, 0x007A0, 0x00765, 0x0071E, 0x006CB, 0x0066C, - 0x005FF, - 0x00586, 0x00500, 0x0046B, 0x003CA, 0x0031A, 0x0025D, 0x00192, - 0x000B9, - -0x0002C, -0x0011F, -0x00220, -0x0032D, -0x00446, -0x0056B, - -0x0069B, -0x007D5, - -0x00919, -0x00A66, -0x00BBB, -0x00D16, -0x00E78, -0x00FDE, - -0x01148, -0x012B3, - -0x01420, -0x0158C, -0x016F6, -0x0185C, -0x019BC, -0x01B16, - -0x01C66, -0x01DAC, - -0x01EE5, -0x02010, -0x0212A, -0x02232, -0x02325, -0x02402, - -0x024C7, -0x02570, - -0x025FE, -0x0266D, -0x026BB, -0x026E6, -0x026ED, -0x026CE, - -0x02686, -0x02615, - -0x02577, -0x024AC, -0x023B2, -0x02287, -0x0212B, -0x01F9B, - -0x01DD7, -0x01BDD, - 0x019AE, 0x01747, 0x014A8, 0x011D1, 0x00EC0, 0x00B77, 0x007F5, - 0x0043A, - 0x00046, -0x003E5, -0x00849, -0x00CE3, -0x011B4, -0x016B9, -0x01BF1, - -0x0215B, - -0x026F6, -0x02CBE, -0x032B3, -0x038D3, -0x03F1A, -0x04586, - -0x04C15, -0x052C4, - -0x05990, -0x06075, -0x06771, -0x06E80, -0x0759F, -0x07CCA, - -0x083FE, -0x08B37, - -0x09270, -0x099A7, -0x0A0D7, -0x0A7FD, -0x0AF14, -0x0B618, - -0x0BD05, -0x0C3D8, - -0x0CA8C, -0x0D11D, -0x0D789, -0x0DDC9, -0x0E3DC, -0x0E9BD, - -0x0EF68, -0x0F4DB, - -0x0FA12, -0x0FF09, -0x103BD, -0x1082C, -0x10C53, -0x1102E, - -0x113BD, -0x116FB, - -0x119E8, -0x11C82, -0x11EC6, -0x120B3, -0x12248, -0x12385, - -0x12467, -0x124EF, - 0x1251E, 0x124F0, 0x12468, 0x12386, 0x12249, 0x120B4, 0x11EC7, - 0x11C83, - 0x119E9, 0x116FC, 0x113BE, 0x1102F, 0x10C54, 0x1082D, 0x103BE, - 0x0FF0A, - 0x0FA13, 0x0F4DC, 0x0EF69, 0x0E9BE, 0x0E3DD, 0x0DDCA, 0x0D78A, - 0x0D11E, - 0x0CA8D, 0x0C3D9, 0x0BD06, 0x0B619, 0x0AF15, 0x0A7FE, 0x0A0D8, - 0x099A8, - 0x09271, 0x08B38, 0x083FF, 0x07CCB, 0x075A0, 0x06E81, 0x06772, - 0x06076, - 0x05991, 0x052C5, 0x04C16, 0x04587, 0x03F1B, 0x038D4, 0x032B4, - 0x02CBF, - 0x026F7, 0x0215C, 0x01BF2, 0x016BA, 0x011B5, 0x00CE4, 0x0084A, - 0x003E6, - -0x00045, -0x00439, -0x007F4, -0x00B76, -0x00EBF, -0x011D0, - -0x014A7, -0x01746, - 0x019AE, 0x01BDE, 0x01DD8, 0x01F9C, 0x0212C, 0x02288, 0x023B3, - 0x024AD, - 0x02578, 0x02616, 0x02687, 0x026CF, 0x026EE, 0x026E7, 0x026BC, - 0x0266E, - 0x025FF, 0x02571, 0x024C8, 0x02403, 0x02326, 0x02233, 0x0212B, - 0x02011, - 0x01EE6, 0x01DAD, 0x01C67, 0x01B17, 0x019BD, 0x0185D, 0x016F7, - 0x0158D, - 0x01421, 0x012B4, 0x01149, 0x00FDF, 0x00E79, 0x00D17, 0x00BBC, - 0x00A67, - 0x0091A, 0x007D6, 0x0069C, 0x0056C, 0x00447, 0x0032E, 0x00221, - 0x00120, - 0x0002D, -0x000B8, -0x00191, -0x0025C, -0x00319, -0x003C9, -0x0046A, - -0x004FF, - -0x00585, -0x005FE, -0x0066B, -0x006CA, -0x0071D, -0x00764, - -0x0079F, -0x007CF, - 0x007F5, 0x0080F, 0x00820, 0x00827, 0x00825, 0x0081B, 0x00809, - 0x007F0, - 0x007D1, 0x007AA, 0x0077F, 0x0074E, 0x00719, 0x006DF, 0x006A2, - 0x00662, - 0x0061F, 0x005DA, 0x00594, 0x0054C, 0x00503, 0x004BA, 0x00471, - 0x00428, - 0x003DF, 0x00397, 0x00350, 0x0030B, 0x002C7, 0x00285, 0x00245, - 0x00207, - 0x001CB, 0x00191, 0x0015B, 0x00126, 0x000F4, 0x000C5, 0x00099, - 0x0006F, - 0x00048, 0x00024, 0x00002, -0x0001C, -0x00038, -0x00052, -0x00069, - -0x0007E, - -0x00091, -0x000A2, -0x000B0, -0x000BC, -0x000C7, -0x000CF, - -0x000D6, -0x000DC, - -0x000DF, -0x000E2, -0x000E3, -0x000E3, -0x000E2, -0x000E0, - -0x000DD, -0x000D9, - 0x000D5, 0x000D0, 0x000CA, 0x000C4, 0x000BE, 0x000B7, 0x000B0, - 0x000A9, - 0x000A1, 0x0009A, 0x00093, 0x0008B, 0x00084, 0x0007D, 0x00075, - 0x0006F, - 0x00068, 0x00061, 0x0005B, 0x00055, 0x0004F, 0x00049, 0x00044, - 0x0003F, - 0x0003A, 0x00035, 0x00031, 0x0002D, 0x00029, 0x00026, 0x00023, - 0x0001F, - 0x0001D, 0x0001A, 0x00018, 0x00015, 0x00013, 0x00011, 0x00010, - 0x0000E, - 0x0000D, 0x0000B, 0x0000A, 0x00009, 0x00008, 0x00007, 0x00007, - 0x00006, - 0x00005, 0x00005, 0x00004, 0x00004, 0x00003, 0x00003, 0x00002, - 0x00002, - 0x00002, 0x00002, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001, - 0x00001 + 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,-0x00001, + -0x00001,-0x00001,-0x00001,-0x00002,-0x00002,-0x00003,-0x00003,-0x00004, + -0x00004,-0x00005,-0x00006,-0x00006,-0x00007,-0x00008,-0x00009,-0x0000A, + -0x0000C,-0x0000D,-0x0000F,-0x00010,-0x00012,-0x00014,-0x00017,-0x00019, + -0x0001C,-0x0001E,-0x00022,-0x00025,-0x00028,-0x0002C,-0x00030,-0x00034, + -0x00039,-0x0003E,-0x00043,-0x00048,-0x0004E,-0x00054,-0x0005A,-0x00060, + -0x00067,-0x0006E,-0x00074,-0x0007C,-0x00083,-0x0008A,-0x00092,-0x00099, + -0x000A0,-0x000A8,-0x000AF,-0x000B6,-0x000BD,-0x000C3,-0x000C9,-0x000CF, + 0x000D5, 0x000DA, 0x000DE, 0x000E1, 0x000E3, 0x000E4, 0x000E4, 0x000E3, + 0x000E0, 0x000DD, 0x000D7, 0x000D0, 0x000C8, 0x000BD, 0x000B1, 0x000A3, + 0x00092, 0x0007F, 0x0006A, 0x00053, 0x00039, 0x0001D,-0x00001,-0x00023, + -0x00047,-0x0006E,-0x00098,-0x000C4,-0x000F3,-0x00125,-0x0015A,-0x00190, + -0x001CA,-0x00206,-0x00244,-0x00284,-0x002C6,-0x0030A,-0x0034F,-0x00396, + -0x003DE,-0x00427,-0x00470,-0x004B9,-0x00502,-0x0054B,-0x00593,-0x005D9, + -0x0061E,-0x00661,-0x006A1,-0x006DE,-0x00718,-0x0074D,-0x0077E,-0x007A9, + -0x007D0,-0x007EF,-0x00808,-0x0081A,-0x00824,-0x00826,-0x0081F,-0x0080E, + 0x007F5, 0x007D0, 0x007A0, 0x00765, 0x0071E, 0x006CB, 0x0066C, 0x005FF, + 0x00586, 0x00500, 0x0046B, 0x003CA, 0x0031A, 0x0025D, 0x00192, 0x000B9, + -0x0002C,-0x0011F,-0x00220,-0x0032D,-0x00446,-0x0056B,-0x0069B,-0x007D5, + -0x00919,-0x00A66,-0x00BBB,-0x00D16,-0x00E78,-0x00FDE,-0x01148,-0x012B3, + -0x01420,-0x0158C,-0x016F6,-0x0185C,-0x019BC,-0x01B16,-0x01C66,-0x01DAC, + -0x01EE5,-0x02010,-0x0212A,-0x02232,-0x02325,-0x02402,-0x024C7,-0x02570, + -0x025FE,-0x0266D,-0x026BB,-0x026E6,-0x026ED,-0x026CE,-0x02686,-0x02615, + -0x02577,-0x024AC,-0x023B2,-0x02287,-0x0212B,-0x01F9B,-0x01DD7,-0x01BDD, + 0x019AE, 0x01747, 0x014A8, 0x011D1, 0x00EC0, 0x00B77, 0x007F5, 0x0043A, + 0x00046,-0x003E5,-0x00849,-0x00CE3,-0x011B4,-0x016B9,-0x01BF1,-0x0215B, + -0x026F6,-0x02CBE,-0x032B3,-0x038D3,-0x03F1A,-0x04586,-0x04C15,-0x052C4, + -0x05990,-0x06075,-0x06771,-0x06E80,-0x0759F,-0x07CCA,-0x083FE,-0x08B37, + -0x09270,-0x099A7,-0x0A0D7,-0x0A7FD,-0x0AF14,-0x0B618,-0x0BD05,-0x0C3D8, + -0x0CA8C,-0x0D11D,-0x0D789,-0x0DDC9,-0x0E3DC,-0x0E9BD,-0x0EF68,-0x0F4DB, + -0x0FA12,-0x0FF09,-0x103BD,-0x1082C,-0x10C53,-0x1102E,-0x113BD,-0x116FB, + -0x119E8,-0x11C82,-0x11EC6,-0x120B3,-0x12248,-0x12385,-0x12467,-0x124EF, + 0x1251E, 0x124F0, 0x12468, 0x12386, 0x12249, 0x120B4, 0x11EC7, 0x11C83, + 0x119E9, 0x116FC, 0x113BE, 0x1102F, 0x10C54, 0x1082D, 0x103BE, 0x0FF0A, + 0x0FA13, 0x0F4DC, 0x0EF69, 0x0E9BE, 0x0E3DD, 0x0DDCA, 0x0D78A, 0x0D11E, + 0x0CA8D, 0x0C3D9, 0x0BD06, 0x0B619, 0x0AF15, 0x0A7FE, 0x0A0D8, 0x099A8, + 0x09271, 0x08B38, 0x083FF, 0x07CCB, 0x075A0, 0x06E81, 0x06772, 0x06076, + 0x05991, 0x052C5, 0x04C16, 0x04587, 0x03F1B, 0x038D4, 0x032B4, 0x02CBF, + 0x026F7, 0x0215C, 0x01BF2, 0x016BA, 0x011B5, 0x00CE4, 0x0084A, 0x003E6, + -0x00045,-0x00439,-0x007F4,-0x00B76,-0x00EBF,-0x011D0,-0x014A7,-0x01746, + 0x019AE, 0x01BDE, 0x01DD8, 0x01F9C, 0x0212C, 0x02288, 0x023B3, 0x024AD, + 0x02578, 0x02616, 0x02687, 0x026CF, 0x026EE, 0x026E7, 0x026BC, 0x0266E, + 0x025FF, 0x02571, 0x024C8, 0x02403, 0x02326, 0x02233, 0x0212B, 0x02011, + 0x01EE6, 0x01DAD, 0x01C67, 0x01B17, 0x019BD, 0x0185D, 0x016F7, 0x0158D, + 0x01421, 0x012B4, 0x01149, 0x00FDF, 0x00E79, 0x00D17, 0x00BBC, 0x00A67, + 0x0091A, 0x007D6, 0x0069C, 0x0056C, 0x00447, 0x0032E, 0x00221, 0x00120, + 0x0002D,-0x000B8,-0x00191,-0x0025C,-0x00319,-0x003C9,-0x0046A,-0x004FF, + -0x00585,-0x005FE,-0x0066B,-0x006CA,-0x0071D,-0x00764,-0x0079F,-0x007CF, + 0x007F5, 0x0080F, 0x00820, 0x00827, 0x00825, 0x0081B, 0x00809, 0x007F0, + 0x007D1, 0x007AA, 0x0077F, 0x0074E, 0x00719, 0x006DF, 0x006A2, 0x00662, + 0x0061F, 0x005DA, 0x00594, 0x0054C, 0x00503, 0x004BA, 0x00471, 0x00428, + 0x003DF, 0x00397, 0x00350, 0x0030B, 0x002C7, 0x00285, 0x00245, 0x00207, + 0x001CB, 0x00191, 0x0015B, 0x00126, 0x000F4, 0x000C5, 0x00099, 0x0006F, + 0x00048, 0x00024, 0x00002,-0x0001C,-0x00038,-0x00052,-0x00069,-0x0007E, + -0x00091,-0x000A2,-0x000B0,-0x000BC,-0x000C7,-0x000CF,-0x000D6,-0x000DC, + -0x000DF,-0x000E2,-0x000E3,-0x000E3,-0x000E2,-0x000E0,-0x000DD,-0x000D9, + 0x000D5, 0x000D0, 0x000CA, 0x000C4, 0x000BE, 0x000B7, 0x000B0, 0x000A9, + 0x000A1, 0x0009A, 0x00093, 0x0008B, 0x00084, 0x0007D, 0x00075, 0x0006F, + 0x00068, 0x00061, 0x0005B, 0x00055, 0x0004F, 0x00049, 0x00044, 0x0003F, + 0x0003A, 0x00035, 0x00031, 0x0002D, 0x00029, 0x00026, 0x00023, 0x0001F, + 0x0001D, 0x0001A, 0x00018, 0x00015, 0x00013, 0x00011, 0x00010, 0x0000E, + 0x0000D, 0x0000B, 0x0000A, 0x00009, 0x00008, 0x00007, 0x00007, 0x00006, + 0x00005, 0x00005, 0x00004, 0x00004, 0x00003, 0x00003, 0x00002, 0x00002, + 0x00002, 0x00002, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001, 0x00001 }; + ///////////// Table 3-B.2: Possible quantization per subband /////////////////// // quantizer lookup, step 1: bitrate classes @@ -231,26 +169,27 @@ namespace gr { // quantizer lookup, step 3: B2 table, subband -> nbal, row index // (upper 4 bits: nbal, lower 4 bits: row index) static - uint8_t quant_lut_step3[3][32] = { + const char quant_lut_step3[3][32] = { // low-rate table (3-B.2c and 3-B.2d) - {0x44, 0x44, // SB 0 - 1 - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34 // SB 2 - 12 + { 0x44,0x44, // SB 0 - 1 + 0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x34 // SB 2 - 12 }, // high-rate table (3-B.2a and 3-B.2b) - {0x43, 0x43, 0x43, // SB 0 - 2 - 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, // SB 3 - 10 - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, // SB 11 - 22 - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 // SB 23 - 29 + { 0x43,0x43,0x43, // SB 0 - 2 + 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42, // SB 3 - 10 + 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31, // SB 11 - 22 + 0x20,0x20,0x20,0x20,0x20,0x20,0x20 // SB 23 - 29 }, // MPEG-2 LSR table (B.2 in ISO 13818-3) - {0x45, 0x45, 0x45, 0x45, // SB 0 - 3 - 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, // SB 4 - 10 - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, // SB 11 - - 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24 // - 29 + { 0x45,0x45,0x45,0x45, // SB 0 - 3 + 0x34,0x34,0x34,0x34,0x34,0x34,0x34, // SB 4 - 10 + 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, // SB 11 - + 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24 // - 29 } }; -// quantizer lookup, step 4: table row, allocation[] value -> quant table index + + // quantizer lookup, step 4: table row, allocation[] value -> quant table index static const char quant_lut_step4[6][16] = { {0, 1, 2, 17}, @@ -369,8 +308,7 @@ namespace gr { return table_idx ? (&quantizer_table[table_idx - 1]) : 0; } - void mp2_decode_bs_impl::read_samples(struct quantizer_spec *q, - int scalefactor, int *sample) { + void mp2_decode_bs_impl::read_samples(struct quantizer_spec *q, int scalefactor, int *sample) { int idx, adj, scale; register int val; @@ -577,10 +515,10 @@ namespace gr { d_scalefactor[1][sb][part] = d_scalefactor[0][sb][part]; } -// coefficient input and reconstruction + // coefficient input and reconstruction for (part = 0; part < 3; ++part) { for (gr = 0; gr < 4; ++gr) { -// read the samples + // read the samples for (sb = 0; sb < bound; ++sb) for (ch = 0; ch < 2; ++ch) read_samples(d_allocation[ch][sb], @@ -599,23 +537,22 @@ namespace gr { for (idx = 0; idx < 3; ++idx) d_sample[ch][sb][idx] = 0; -// synthesis loop + // synthesis loop for (idx = 0; idx < 3; ++idx) { -// shifting step + // shifting step d_V_offs = table_idx = (d_V_offs - 64) & 1023; for (ch = 0; ch < 2; ++ch) { -// matrixing + // matrixing for (i = 0; i < 64; ++i) { sum = 0; for (j = 0; j < 32; ++j) // 8b*15b=23b sum += d_N[i][j] * d_sample[ch][j][idx]; -// intermediate value is 28 bit (23 + 5), clamp to 14b -// + // intermediate value is 28 bit (23 + 5), clamp to 14b d_V[ch][table_idx + i] = (sum + 8192) >> 14; } -// construction of U + // construction of U for (i = 0; i < 8; ++i) for (j = 0; j < 32; ++j) { d_U[(i << 6) + j] @@ -624,11 +561,11 @@ namespace gr { d_V[ch][(table_idx + (i << 7) + j + 96) & 1023]; } -// apply window + // apply window for (i = 0; i < 512; ++i) d_U[i] = (d_U[i] * D[i] + 32) >> 6; -// output samples + // output samples for (j = 0; j < 32; ++j) { sum = 0; for (i = 0; i < 16; ++i) @@ -642,7 +579,7 @@ namespace gr { } } // end of synthesis channel loop } // end of synthesis sub-block loop -// adjust PCM output pointer: decoded 3 * 32 = 96 stereo samples + // adjust PCM output pointer: decoded 3 * 32 = 96 stereo samples pcm += 192; } // decoding of the granule finished } @@ -714,7 +651,7 @@ namespace gr { d_mp2_bit_count = 0; } } else if (d_mp2_header_OK == 0) { -// apparently , we are not in sync yet + // apparently , we are not in sync yet if (in[logical_frame_count * d_mp2_framesize + i] == 01) { if (++d_mp2_header_count == 12) { d_mp2_bit_count = 0; diff --git a/lib/mp2_decode_bs_impl.h b/lib/mp2_decode_bs_impl.h index f1137bc6..2b105690 100644 --- a/lib/mp2_decode_bs_impl.h +++ b/lib/mp2_decode_bs_impl.h @@ -1,10 +1,13 @@ /* -*- c++ -*- */ /* -* 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). -* A major part of this code is adapted from the kjmp2 library, slightly modified and written into a GNURadio block. -* Note that this is an altered version of kjmp2 and not the original library. -*/ + * 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). + * + * A major part of this code is adapted from the kjmp2 library, + * slightly modified and written into a GNURadio block. + * Note that this is an altered version of kjmp2 and not the original library. + */ /****************************************************************************** ** kjmp2 -- a minimal MPEG-1/2 Audio Layer II decoder library ** diff --git a/lib/mp2_encode_sb_impl.cc b/lib/mp2_encode_sb_impl.cc index f638a2ec..e34d7476 100644 --- a/lib/mp2_encode_sb_impl.cc +++ b/lib/mp2_encode_sb_impl.cc @@ -1,10 +1,13 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * Code from the following third party modules is used: - * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; Licensed under the Apache License, Version 2.0 (the "License") - * - libtoolame-dab taken from ODR-AudioEnc, derived from TooLAME, licensed under LGPL v2.1 or later. See libtoolame-dab/LGPL.txt. This is built into a shared library. + * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; + * Licensed under the Apache License, Version 2.0 (the "License") + * - libtoolame-dab taken from ODR-AudioEnc, derived from TooLAME, licensed under LGPL v2.1 or later. + * See libtoolame-dab/LGPL.txt. This is built into a shared library. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,18 +43,15 @@ namespace gr { mp2_encode_sb::sptr mp2_encode_sb::make(int bit_rate_n, int channels, int sample_rate) { - return gnuradio::get_initial_sptr - (new mp2_encode_sb_impl(bit_rate_n, channels, sample_rate)); + return gnuradio::get_initial_sptr(new mp2_encode_sb_impl(bit_rate_n, channels, sample_rate)); } /* * The private constructor */ - mp2_encode_sb_impl::mp2_encode_sb_impl(int bit_rate_n, int channels, - int sample_rate) + mp2_encode_sb_impl::mp2_encode_sb_impl(int bit_rate_n, int channels, int sample_rate) : gr::block("mp2_encode_sb", - gr::io_signature::make(channels, channels, - sizeof(int16_t)), + gr::io_signature::make(channels, channels, sizeof(int16_t)), gr::io_signature::make(1, 1, sizeof(unsigned char))), d_bit_rate_n(bit_rate_n), d_channels(channels), d_samp_rate(sample_rate) { @@ -60,8 +60,7 @@ namespace gr { } if (!(d_samp_rate == 24000 || d_samp_rate == 48000)) { throw std::invalid_argument( - (format("samp_rate must be 24kHz or 48kHz, not %d") % - d_samp_rate).str()); + (format("samp_rate must be 24kHz or 48kHz, not %d") % d_samp_rate).str()); } d_input_size = 1152; // output size depends on bitrate and sample_rate, d_output_size is max output size @@ -101,8 +100,7 @@ namespace gr { } else if (d_channels == 1) { dab_channel_mode = 'm'; // Default to mono } else { - GR_LOG_ERROR(d_logger, - format("Unsupported channels number %d") % d_channels); + GR_LOG_ERROR(d_logger, format("Unsupported channels number %d") % d_channels); return false; } if (err == 0) { @@ -122,8 +120,7 @@ namespace gr { } void - mp2_encode_sb_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + mp2_encode_sb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items * d_input_size / d_output_size; } @@ -147,14 +144,11 @@ namespace gr { for (int i = 0; i < noutput_items / d_output_size; ++i) { // write next frame to buffer (1 or 2 channels for mono or stereo respectively) if (d_channels == 1) { - memcpy(input_buffers[0], &in_ch1[d_nconsumed], - d_input_size * sizeof(int16_t)); + memcpy(input_buffers[0], &in_ch1[d_nconsumed], d_input_size * sizeof(int16_t)); } else if (d_channels == 2) { // merge channels if stereo const int16_t *in_ch2 = (const int16_t *) input_items[1]; - memcpy(input_buffers[0], &in_ch1[d_nconsumed], - d_input_size * sizeof(int16_t)); - memcpy(input_buffers[1], &in_ch2[d_nconsumed], - d_input_size * sizeof(int16_t)); + memcpy(input_buffers[0], &in_ch1[d_nconsumed], d_input_size * sizeof(int16_t)); + memcpy(input_buffers[1], &in_ch2[d_nconsumed], d_input_size * sizeof(int16_t)); } // encode num_out_bytes = toolame_encode_frame(input_buffers, pad_buf, padlen, diff --git a/lib/mp2_encode_sb_impl.h b/lib/mp2_encode_sb_impl.h index ca34945f..35fa7b26 100644 --- a/lib/mp2_encode_sb_impl.h +++ b/lib/mp2_encode_sb_impl.h @@ -1,10 +1,13 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * Code from the following third party modules is used: - * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; Licensed under the Apache License, Version 2.0 (the "License") - * - libtoolame-dab taken from ODR-AudioEnc, derived from TooLAME, licensed under LGPL v2.1 or later. See libtoolame-dab/LGPL.txt. This is built into a shared library. + * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; + * Licensed under the Apache License, Version 2.0 (the "License") + * - libtoolame-dab taken from ODR-AudioEnc, derived from TooLAME, licensed under LGPL v2.1 or later. + * See libtoolame-dab/LGPL.txt. This is built into a shared library. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index bf30b5c8..a2e59337 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -74,8 +74,7 @@ namespace gr { } void - mp4_decode_bs_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + mp4_decode_bs_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; //TODO: how to calculate actual rate? } @@ -117,11 +116,8 @@ namespace gr { * support AudioObjectType 29 (PS) */ - int core_sr_index = - dacRate ? (sbrFlag ? 6 : 3) : - (sbrFlag ? 8 : 5); // 24/48/16/32 kHz - int core_ch_config = get_aac_channel_configuration(mpegSurround, - aacChannelMode); + int core_sr_index = dacRate ? (sbrFlag ? 6 : 3) : (sbrFlag ? 8 : 5); // 24/48/16/32 kHz + int core_ch_config = get_aac_channel_configuration(mpegSurround, aacChannelMode); if (core_ch_config == -1) { GR_LOG_ERROR(d_logger, "Unrecognized mpeg surround config (ignored)"); return false; @@ -192,14 +188,14 @@ namespace gr { // initialize AAC decoder at the beginning if (!d_aacInitialized) { - if (!initialize(dacRate, sbrFlag, mpegSurround, aacChannelMode)) + if (!initialize(dacRate, sbrFlag, mpegSurround, aacChannelMode)) { return 0; + } d_aacInitialized = true; GR_LOG_DEBUG(d_logger, "AAC initialized"); } - outBuffer = (int16_t *) NeAACDecDecode(aacHandle, &hInfo, buffer, - bufferLength); + outBuffer = (int16_t *) NeAACDecDecode(aacHandle, &hInfo, buffer, bufferLength); sample_rate = hInfo.samplerate; samples = hInfo.samples; @@ -266,12 +262,8 @@ namespace gr { return (crc ^ accumulator) == 0; } - uint16_t mp4_decode_bs_impl::BinToDec(const uint8_t *data, size_t offset, - size_t length) { - uint32_t output = - (*(data + offset / 8) << 16) | ((*(data + offset / 8 + 1)) << 8) | - (*(data + offset / 8 + - 2)); // should be big/little endian save + uint16_t mp4_decode_bs_impl::BinToDec(const uint8_t *data, size_t offset, size_t length) { + uint32_t output = (*(data + offset / 8) << 16) | ((*(data + offset / 8 + 1)) << 8) | (*(data + offset / 8 + 2)); output >>= 24 - length - offset % 8; output &= (0xFFFF >> (16 - length)); return static_cast(output); @@ -282,8 +274,7 @@ namespace gr { gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - const unsigned char *in = - (const unsigned char *) input_items[0] + d_superframe_size; + const unsigned char *in = (const unsigned char *) input_items[0] + d_superframe_size; int16_t *out1 = (int16_t *) output_items[0]; int16_t *out2 = (int16_t *) output_items[1]; d_nsamples_produced = 0; @@ -294,15 +285,16 @@ namespace gr { // bit 16 is unused d_dac_rate = (in[n * d_superframe_size + 2] >> 6) & 01; // bit 17 d_sbr_flag = (in[n * d_superframe_size + 2] >> 5) & 01; // bit 18 - d_aac_channel_mode = - (in[n * d_superframe_size + 2] >> 4) & 01; // bit 19 + d_aac_channel_mode = (in[n * d_superframe_size + 2] >> 4) & 01; // bit 19 d_ps_flag = (in[n * d_superframe_size + 2] >> 3) & 01; // bit 20 d_mpeg_surround = (in[n * d_superframe_size + 2] & 07); // bits 21 .. 23 // log header information GR_LOG_DEBUG(d_logger, format("superframe header: dac_rate %d, sbr_flag %d, aac_mode %d, ps_flag %d, surround %d") % - (int) d_dac_rate % (int) d_sbr_flag % - (int) d_aac_channel_mode % (int) d_ps_flag % + (int) d_dac_rate % + (int) d_sbr_flag % + (int) d_aac_channel_mode % + (int) d_ps_flag % (int) d_mpeg_surround); switch (2 * d_dac_rate + d_sbr_flag) { @@ -310,50 +302,41 @@ namespace gr { case 0: d_num_aus = 4; d_au_start[0] = 8; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + - (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + - in[n * d_superframe_size + 5]; - d_au_start[3] = in[n * d_superframe_size + 6] * 16 + - (in[n * d_superframe_size + 7] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; + d_au_start[3] = in[n * d_superframe_size + 6] * 16 + (in[n * d_superframe_size + 7] >> 4); d_au_start[4] = d_superframe_size; break; case 1: d_num_aus = 2; d_au_start[n * d_superframe_size + 0] = 5; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + - (in[n * d_superframe_size + 4] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); d_au_start[2] = d_superframe_size; break; case 2: d_num_aus = 6; d_au_start[0] = 11; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + - (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + - in[n * d_superframe_size + 5]; - d_au_start[3] = in[n * d_superframe_size + 6] * 16 + - (in[n * d_superframe_size + 7] >> 4); + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; + d_au_start[3] = in[n * d_superframe_size + 6] * 16 + (in[n * d_superframe_size + 7] >> 4); d_au_start[4] = (in[n * d_superframe_size + 7] & 0xf) * 256 + in[8]; - d_au_start[5] = in[n * d_superframe_size + 9] * 16 + - (in[n * d_superframe_size + 10] >> 4); + d_au_start[5] = in[n * d_superframe_size + 9] * 16 + (in[n * d_superframe_size + 10] >> 4); d_au_start[6] = d_superframe_size; break; case 3: d_num_aus = 3; d_au_start[0] = 6; - d_au_start[1] = in[n * d_superframe_size + 3] * 16 + - (in[n * d_superframe_size + 4] >> 4); - d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + - in[n * d_superframe_size + 5]; + d_au_start[1] = in[n * d_superframe_size + 3] * 16 + (in[n * d_superframe_size + 4] >> 4); + d_au_start[2] = (in[n * d_superframe_size + 4] & 0xf) * 256 + in[n * d_superframe_size + 5]; d_au_start[3] = d_superframe_size; break; } - // each of the d_num_aus AUs of each superframe (110 * d_bit_rate_n packed bytes) is now processed separately + /* Each of the d_num_aus AUs of each superframe (110 * d_bit_rate_n packed bytes) + * is now processed separately. */ for (int i = 0; i < d_num_aus; i++) { int16_t aac_frame_length; @@ -373,8 +356,7 @@ namespace gr { } // CRC check of each AU (the 2 byte (16 bit) CRC word is excluded in aac_frame_length) - if (crc16(&in[n * d_superframe_size + d_au_start[i]], - aac_frame_length)) { + if (crc16(&in[n * d_superframe_size + d_au_start[i]], aac_frame_length)) { //GR_LOG_DEBUG(d_logger, format("CRC check of AU %d successful") % i); // handle proper AU handle_aac_frame(&in[n * d_superframe_size + d_au_start[i]], diff --git a/lib/mp4_encode_sb_impl.cc b/lib/mp4_encode_sb_impl.cc index f84047d4..081cf3ed 100644 --- a/lib/mp4_encode_sb_impl.cc +++ b/lib/mp4_encode_sb_impl.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * Code from the following third party modules is used: * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; Licensed under the Apache License, Version 2.0 (the "License") @@ -43,22 +44,26 @@ namespace gr { mp4_encode_sb::sptr mp4_encode_sb::make(int bit_rate_n, int channels, int samp_rate, int afterburner) { - return gnuradio::get_initial_sptr - (new mp4_encode_sb_impl(bit_rate_n, channels, samp_rate, - afterburner)); + return gnuradio::get_initial_sptr(new mp4_encode_sb_impl(bit_rate_n, + channels, + samp_rate, + afterburner)); } /* * The private constructor */ - mp4_encode_sb_impl::mp4_encode_sb_impl(int bit_rate_n, int channels, - int samp_rate, int afterburner) + mp4_encode_sb_impl::mp4_encode_sb_impl(int bit_rate_n, + int channels, + int samp_rate, + int afterburner) : gr::block("mp4_encode_sb", - gr::io_signature::make(channels, channels, - sizeof(int16_t)), + gr::io_signature::make(channels, channels, sizeof(int16_t)), gr::io_signature::make(1, 1, sizeof(unsigned char))), - d_bit_rate_n(bit_rate_n), d_channels(channels), - d_samp_rate(samp_rate), d_afterburner(afterburner) { + d_bit_rate_n(bit_rate_n), + d_channels(channels), + d_samp_rate(samp_rate), + d_afterburner(afterburner) { // check input arguments if (d_bit_rate_n < 1 || d_bit_rate_n > 24) { throw std::out_of_range( @@ -71,8 +76,7 @@ namespace gr { } // initialize AAC encoder d_aot = AOT_NONE; - if (init_aac_encoder(&d_aac_encoder, d_channels, d_samp_rate, - d_afterburner, &d_aot)) { + if (init_aac_encoder(&d_aac_encoder, d_channels, d_samp_rate, d_afterburner, &d_aot)) { GR_LOG_INFO(d_logger, "AAC enc init succeeded"); } else { GR_LOG_ERROR(d_logger, "AAC enc init failed"); @@ -86,8 +90,7 @@ namespace gr { // set input size (number of items per channel(in this case one item is a int16_t)) d_input_size = info.frameLength; - GR_LOG_INFO(d_logger, - format("AAC Encoding: framelen = %d") % info.frameLength); + GR_LOG_INFO(d_logger, format("AAC Encoding: framelen = %d") % info.frameLength); // set output size to the superframe size (without Reed Solomon parity check words) d_output_size = d_bit_rate_n * 110; @@ -126,8 +129,7 @@ namespace gr { mode = MODE_2; break; default: - GR_LOG_ERROR(d_logger, - format("Unsupported channels number %d") % channels); + GR_LOG_ERROR(d_logger, format("Unsupported channels number %d") % channels); return false; } @@ -165,14 +167,12 @@ namespace gr { return false; } // set aac samplerate - if (aacEncoder_SetParam(*encoder, AACENC_SAMPLERATE, sample_rate) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the sample rate"); return false; } // set aac channel mode - if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE, mode) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_CHANNELMODE, mode) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the channel mode"); return false; } @@ -182,28 +182,24 @@ namespace gr { return false; } // set aac granule length (in samples) to 960 (DRM/DAB+) - if (aacEncoder_SetParam(*encoder, AACENC_GRANULE_LENGTH, 960) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_GRANULE_LENGTH, 960) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the granule length"); return false; } // set aac transport type - if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX, TT_DABPLUS) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_TRANSMUX, TT_DABPLUS) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the RAW transmux"); return false; } // set aac bit rate GR_LOG_INFO(d_logger, format("AAC bitrate set to: %d") % (d_bit_rate_n * 8000)); - if (aacEncoder_SetParam(*encoder, AACENC_BITRATE, d_bit_rate_n * 8000) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_BITRATE, d_bit_rate_n * 8000) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the bitrate"); return false; } // set aac afterburner tool - if (aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, afterburner) != - AACENC_OK) { + if (aacEncoder_SetParam(*encoder, AACENC_AFTERBURNER, afterburner) != AACENC_OK) { GR_LOG_ERROR(d_logger, "Unable to set the afterburner mode"); return false; } @@ -227,7 +223,8 @@ namespace gr { * @return true if no errors occurred */ bool - mp4_encode_sb_impl::encode(int16_t *input_buffer, int size_input_buffer, + mp4_encode_sb_impl::encode(int16_t *input_buffer, + int size_input_buffer, unsigned char *output_buffer, int size_output_buffer) { AACENC_ERROR err; @@ -277,15 +274,15 @@ namespace gr { out_args.numOutBytes > size_output_buffer) { throw std::runtime_error( (format("too much samples (%d) to write in ouput buffer (%d samples left)") % - out_args.numOutBytes % size_output_buffer).str()); + out_args.numOutBytes % + size_output_buffer).str()); } nproduced += out_args.numOutBytes; return true; } void - mp4_encode_sb_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + mp4_encode_sb_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items * d_input_size / d_output_size; ninput_items_required[1] = noutput_items * d_input_size / d_output_size; } @@ -298,16 +295,14 @@ namespace gr { const int16_t *in_ch1 = (const int16_t *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; int16_t input_buffer[d_input_size * 2]; - GR_LOG_DEBUG(d_logger, - format("New buffer with %d samples") % noutput_items); + GR_LOG_DEBUG(d_logger, format("New buffer with %d samples") % noutput_items); nconsumed = 0; nproduced = 0; do { // copy frame to buffer if (d_channels == 1) { - memcpy(input_buffer, &in_ch1[nconsumed], - d_input_size * sizeof(int16_t)); + memcpy(input_buffer, &in_ch1[nconsumed], d_input_size * sizeof(int16_t)); } else if (d_channels == 2) { // merge channels if stereo const int16_t *in_ch2 = (const int16_t *) input_items[1]; for (int i = 0; i < d_input_size; ++i) { @@ -315,9 +310,8 @@ namespace gr { input_buffer[2 * i + 1] = in_ch2[nconsumed + i]; } } - // send filled buffer to encoder - encode(input_buffer, d_input_size * d_channels, &out[nproduced], - noutput_items - nproduced); // encode input stream + // send filled buffer to encoder and encode input stream + encode(input_buffer, d_input_size * d_channels, &out[nproduced], noutput_items - nproduced); } while (nproduced < noutput_items / d_output_size); // Tell runtime system how many input items we consumed on diff --git a/lib/mp4_encode_sb_impl.h b/lib/mp4_encode_sb_impl.h index 0163b65e..5437d16e 100644 --- a/lib/mp4_encode_sb_impl.h +++ b/lib/mp4_encode_sb_impl.h @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * Code from the following third party modules is used: * - ODR-AudioEnc, Copyright (C) 2011 Martin Storsjo, (C) 2017 Matthias P. Braendli; Licensed under the Apache License, Version 2.0 (the "License") diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc index 36d975b7..a046aab4 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,10 +35,10 @@ namespace gr { ofdm_coarse_frequency_correction_vcvc::make(int fft_length, int num_carriers, int cyclic_prefix_length) { - return gnuradio::get_initial_sptr - (new ofdm_coarse_frequency_correction_vcvc_impl(fft_length, - num_carriers, - cyclic_prefix_length)); + return gnuradio::get_initial_sptr( + new ofdm_coarse_frequency_correction_vcvc_impl(fft_length, + num_carriers, + cyclic_prefix_length)); } /* @@ -46,20 +47,16 @@ namespace gr { ofdm_coarse_frequency_correction_vcvc_impl::ofdm_coarse_frequency_correction_vcvc_impl( int fft_length, int num_carriers, int cyclic_prefix_length) : gr::sync_block("ofdm_coarse_frequency_correction_vcvc", - gr::io_signature::make(1, 1, fft_length * - sizeof(gr_complex)), - gr::io_signature::make(1, 1, num_carriers * - sizeof(gr_complex))), + gr::io_signature::make(1, 1, fft_length * sizeof(gr_complex)), + gr::io_signature::make(1, 1, num_carriers * sizeof(gr_complex))), d_fft_length(fft_length), d_num_carriers(num_carriers), d_cyclic_prefix_length(cyclic_prefix_length), d_freq_offset(0), d_snr(0) { unsigned int alignment = volk_get_alignment(); - d_mag_squared = (float *) volk_malloc(sizeof(float) * num_carriers + 1, - alignment); + d_mag_squared = (float *) volk_malloc(sizeof(float) * num_carriers + 1, alignment); } - /* * Our virtual destructor. */ @@ -71,19 +68,15 @@ namespace gr { * Fine frequency synchronization in the range of one sub-carrier spacing is already done. */ void - ofdm_coarse_frequency_correction_vcvc_impl::measure_energy( - const gr_complex *symbol) { + ofdm_coarse_frequency_correction_vcvc_impl::measure_energy(const gr_complex *symbol) { unsigned int i, index; float energy = 0, max = 0; // first energy measurement is processed completely - volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, - d_num_carriers + 1); + volk_32fc_magnitude_squared_32f(d_mag_squared, symbol, d_num_carriers + 1); volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers + 1); // subtract the central (DC) carrier which is not occupied - energy -= std::real(symbol[d_num_carriers]) * - std::real(symbol[d_num_carriers]) + - std::imag(symbol[d_num_carriers]) * - std::imag(symbol[d_num_carriers]); + energy -= std::real(symbol[d_num_carriers]) * std::real(symbol[d_num_carriers]) + + std::imag(symbol[d_num_carriers]) * std::imag(symbol[d_num_carriers]); max = energy; index = 0; /* the energy measurements with all possible carrier offsets are calculated over a moving sum, @@ -94,26 +87,19 @@ namespace gr { energy -= std::real(symbol[i - 1]) * std::real(symbol[i - 1]) + std::imag(symbol[i - 1]) * std::imag(symbol[i - 1]); /* diff for zero carrier */ - energy += std::real(symbol[i + d_num_carriers / 2 - 1]) * - std::real(symbol[i + d_num_carriers / 2 - 1]) + - std::imag(symbol[i + d_num_carriers / 2 - 1]) * - std::imag(symbol[i + d_num_carriers / 2 - 1]); - energy -= std::real(symbol[i + d_num_carriers / 2]) * - std::real(symbol[i + d_num_carriers / 2]) + - std::imag(symbol[i + d_num_carriers / 2]) * - std::imag(symbol[i + d_num_carriers / 2]); + energy += std::real(symbol[i + d_num_carriers / 2 - 1]) * std::real(symbol[i + d_num_carriers / 2 - 1]) + + std::imag(symbol[i + d_num_carriers / 2 - 1]) * std::imag(symbol[i + d_num_carriers / 2 - 1]); + energy -= std::real(symbol[i + d_num_carriers / 2]) * std::real(symbol[i + d_num_carriers / 2]) + + std::imag(symbol[i + d_num_carriers / 2]) * std::imag(symbol[i + d_num_carriers / 2]); /* diff on rigth side */ - energy += std::real(symbol[i + d_num_carriers]) * - std::real(symbol[i + d_num_carriers]) + - std::imag(symbol[i + d_num_carriers]) * - std::imag(symbol[i + d_num_carriers]); + energy += std::real(symbol[i + d_num_carriers]) * std::real(symbol[i + d_num_carriers]) + + std::imag(symbol[i + d_num_carriers]) * std::imag(symbol[i + d_num_carriers]); /* new max found? */ if (energy > max) { max = energy; index = i; } } - d_freq_offset = index; } @@ -121,18 +107,14 @@ namespace gr { * @return estimated SNR float value */ void - ofdm_coarse_frequency_correction_vcvc_impl::measure_snr( - const gr_complex *symbol) { + ofdm_coarse_frequency_correction_vcvc_impl::measure_snr(const gr_complex *symbol) { // measure normalized energy of occupied sub-carriers float energy = 0; - volk_32fc_magnitude_squared_32f(d_mag_squared, &symbol[d_freq_offset], - d_num_carriers + 1); + volk_32fc_magnitude_squared_32f(d_mag_squared, &symbol[d_freq_offset], d_num_carriers + 1); volk_32f_accumulator_s32f(&energy, d_mag_squared, d_num_carriers + 1); // subtract the central (DC) carrier which is not assigned - energy -= std::real(symbol[d_num_carriers + d_freq_offset]) * - std::real(symbol[d_num_carriers + d_freq_offset]) + - std::imag(symbol[d_num_carriers + d_freq_offset]) * - std::imag(symbol[d_num_carriers + d_freq_offset]); + energy -= std::real(symbol[d_num_carriers + d_freq_offset]) * std::real(symbol[d_num_carriers + d_freq_offset]) + + std::imag(symbol[d_num_carriers + d_freq_offset]) * std::imag(symbol[d_num_carriers + d_freq_offset]); // measure normalized energy of empty sub-carriers float noise_left = 0, noise_right, noise_total; @@ -141,19 +123,15 @@ namespace gr { volk_32f_accumulator_s32f(&noise_left, d_mag_squared, d_freq_offset); // empty sub-carriers on right side volk_32fc_magnitude_squared_32f(d_mag_squared, - &symbol[d_freq_offset + d_num_carriers + - 1], - d_fft_length - d_num_carriers - - d_freq_offset - 1); - volk_32f_accumulator_s32f(&noise_right, d_mag_squared, - d_fft_length - d_num_carriers - d_freq_offset - - 1); + &symbol[d_freq_offset + d_num_carriers + 1], + d_fft_length - d_num_carriers - d_freq_offset - 1); + volk_32f_accumulator_s32f(&noise_right, + d_mag_squared, + d_fft_length - d_num_carriers - d_freq_offset - 1); // add noise energies from both sides to total noise noise_total = noise_left + noise_right; - noise_total += std::real(symbol[d_freq_offset + d_num_carriers / 2]) * - std::real(symbol[d_freq_offset + d_num_carriers / 2]) + - std::imag(symbol[d_freq_offset + d_num_carriers / 2]) * - std::imag(symbol[d_freq_offset + d_num_carriers / 2]); + noise_total += std::real(symbol[d_freq_offset + d_num_carriers / 2]) * std::real(symbol[d_freq_offset + d_num_carriers / 2]) + + std::imag(symbol[d_freq_offset + d_num_carriers / 2]) * std::imag(symbol[d_freq_offset + d_num_carriers / 2]); // normalize energy = energy / d_num_carriers; @@ -186,8 +164,7 @@ namespace gr { tag_count++; } // copy the first half (left of central sub-carrier) of the sub-carriers to the output - memcpy(out, &in[i * d_fft_length + d_freq_offset], - d_num_carriers / 2 * sizeof(gr_complex)); + memcpy(out, &in[i * d_fft_length + d_freq_offset], d_num_carriers / 2 * sizeof(gr_complex)); // copy the second half (right of central sub-carrier) of the sub-carriers to the output memcpy(out + d_num_carriers / 2, &in[i * d_fft_length + d_freq_offset + d_num_carriers / 2 + 1], diff --git a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h index ed1ab5e0..e2490476 100644 --- a/lib/ofdm_coarse_frequency_correction_vcvc_impl.h +++ b/lib/ofdm_coarse_frequency_correction_vcvc_impl.h @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,8 +33,7 @@ namespace gr { * @param num_carriers number of occupied carriers; corresponding to the output vector length * @param cyclic_prefix_length length of the cyclic prefix; corresponding to the length of the energy measurement */ - class ofdm_coarse_frequency_correction_vcvc_impl - : public ofdm_coarse_frequency_correction_vcvc { + class ofdm_coarse_frequency_correction_vcvc_impl : public ofdm_coarse_frequency_correction_vcvc { private: int d_fft_length; int d_num_carriers; From 4a343fd717bdb78a2168f466f58bbee8164a965f Mon Sep 17 00:00:00 2001 From: luca Date: Tue, 6 Mar 2018 19:33:57 +0100 Subject: [PATCH 129/135] reformatting and documentation --- lib/doxygen-config | 2 +- lib/fib_sink_vb_impl.h | 2 +- lib/ofdm_insert_pilot_vcc_impl.cc | 26 +++---- lib/ofdm_insert_pilot_vcc_impl.h | 3 +- lib/ofdm_move_and_insert_zero_impl.cc | 10 +-- lib/ofdm_move_and_insert_zero_impl.h | 3 +- lib/ofdm_synchronization_cvf_impl.cc | 104 +++++++++----------------- lib/ofdm_synchronization_cvf_impl.h | 89 +++++++++++++++++----- lib/reed_solomon_encode_bb_impl.h | 14 ++-- lib/select_cus_vfvf_impl.cc | 9 ++- lib/select_cus_vfvf_impl.h | 15 ++-- lib/sum_phasor_trig_vcc_impl.cc | 15 ++-- lib/time_deinterleave_ff_impl.cc | 16 ++-- lib/time_deinterleave_ff_impl.h | 9 ++- lib/time_interleave_bb_impl.cc | 22 ++---- lib/time_interleave_bb_impl.h | 8 +- lib/unpuncture_vff_impl.cc | 18 ++--- lib/unpuncture_vff_impl.h | 13 ++-- lib/valve_ff_impl.cc | 9 +-- lib/valve_ff_impl.h | 6 +- 20 files changed, 203 insertions(+), 190 deletions(-) diff --git a/lib/doxygen-config b/lib/doxygen-config index ecdb5808..87b11cad 100644 --- a/lib/doxygen-config +++ b/lib/doxygen-config @@ -441,7 +441,7 @@ EXTRACT_ALL = NO # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. diff --git a/lib/fib_sink_vb_impl.h b/lib/fib_sink_vb_impl.h index 512c6442..53a87682 100644 --- a/lib/fib_sink_vb_impl.h +++ b/lib/fib_sink_vb_impl.h @@ -48,7 +48,7 @@ namespace gr { * @param data Pointer to the FIG data buffer. * @param length Length of the FIG data buffer in bytes. */ - int process_fig(uint8_t type, const char *data, uint8_t length); + void process_fig(uint8_t type, const char *data, uint8_t length); bool d_crc_passed; diff --git a/lib/ofdm_insert_pilot_vcc_impl.cc b/lib/ofdm_insert_pilot_vcc_impl.cc index 06f5fdcc..8ea8434a 100644 --- a/lib/ofdm_insert_pilot_vcc_impl.cc +++ b/lib/ofdm_insert_pilot_vcc_impl.cc @@ -44,21 +44,17 @@ namespace gr { ofdm_insert_pilot_vcc_impl::ofdm_insert_pilot_vcc_impl( const std::vector &pilot) : gr::block("ofdm_insert_pilot_vcc", - gr::io_signature::make2(2, 2, sizeof(gr_complex) * - pilot.size(), - sizeof(char)), - gr::io_signature::make2(2, 2, sizeof(gr_complex) * - pilot.size(), - sizeof(char))), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * pilot.size(), sizeof(char)), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * pilot.size(), sizeof(char))), d_pilot(pilot), d_start(0) { } void - ofdm_insert_pilot_vcc_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + ofdm_insert_pilot_vcc_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { unsigned ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) + for (unsigned int i = 0; i < ninputs; i++) { ninput_items_required[i] = noutput_items; + } } @@ -76,15 +72,16 @@ namespace gr { int n_produced = 0; int n_consumed = 0; - for (; n_consumed < ninput_items[1] && n_consumed < ninput_items[1] && - n_produced < noutput_items; n_produced++) { + for (; n_consumed < ninput_items[1] && n_consumed < ninput_items[1] && n_produced < noutput_items; n_produced++) { if (*frame_start == 1 && d_start == 0) { d_start = 1; - for (unsigned int j = 0; j < d_pilot.size(); j++) + for (unsigned int j = 0; j < d_pilot.size(); j++) { *optr++ = d_pilot[j]; + } } else { - for (unsigned int j = 0; j < d_pilot.size(); j++) + for (unsigned int j = 0; j < d_pilot.size(); j++) { *optr++ = *iptr++; + } frame_start++; n_consumed++; d_start = 0; @@ -92,9 +89,6 @@ namespace gr { *o_frame_start++ = d_start; } consume_each(n_consumed); - - // printf("ninput_items: %d, noutput_items: %d, consumed: %d, produced: %d\n",ninput_items[0],noutput_items, n_consumed, n_produced); - return n_produced; } diff --git a/lib/ofdm_insert_pilot_vcc_impl.h b/lib/ofdm_insert_pilot_vcc_impl.h index 449115d9..53e58d9f 100644 --- a/lib/ofdm_insert_pilot_vcc_impl.h +++ b/lib/ofdm_insert_pilot_vcc_impl.h @@ -26,9 +26,10 @@ namespace gr { namespace dab { + class ofdm_insert_pilot_vcc_impl : public ofdm_insert_pilot_vcc { - private: + private: std::vector d_pilot; char d_start; diff --git a/lib/ofdm_move_and_insert_zero_impl.cc b/lib/ofdm_move_and_insert_zero_impl.cc index fc0ed22b..78bf8530 100644 --- a/lib/ofdm_move_and_insert_zero_impl.cc +++ b/lib/ofdm_move_and_insert_zero_impl.cc @@ -38,17 +38,15 @@ namespace gr { ofdm_move_and_insert_zero::sptr ofdm_move_and_insert_zero::make(unsigned int fft_length, unsigned int num_carriers) { - return gnuradio::get_initial_sptr - (new ofdm_move_and_insert_zero_impl(fft_length, num_carriers)); + return gnuradio::get_initial_sptr(new ofdm_move_and_insert_zero_impl(fft_length, + num_carriers)); } ofdm_move_and_insert_zero_impl::ofdm_move_and_insert_zero_impl( unsigned int fft_length, unsigned int num_carriers) : gr::sync_block("ofdm_move_and_insert_zero", - gr::io_signature::make(1, 1, sizeof(gr_complex) * - num_carriers), - gr::io_signature::make(1, 1, sizeof(gr_complex) * - fft_length)), + gr::io_signature::make(1, 1, sizeof(gr_complex) * num_carriers), + gr::io_signature::make(1, 1, sizeof(gr_complex) * fft_length)), d_fft_length(fft_length), d_num_carriers(num_carriers) { d_zeros_on_left = (d_fft_length - d_num_carriers) / 2; } diff --git a/lib/ofdm_move_and_insert_zero_impl.h b/lib/ofdm_move_and_insert_zero_impl.h index 531c1f93..923ffe20 100644 --- a/lib/ofdm_move_and_insert_zero_impl.h +++ b/lib/ofdm_move_and_insert_zero_impl.h @@ -35,8 +35,7 @@ namespace gr { unsigned int d_zeros_on_left; public: - ofdm_move_and_insert_zero_impl(unsigned int fft_length, - unsigned int num_carriers); + ofdm_move_and_insert_zero_impl(unsigned int fft_length, unsigned int num_carriers); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index 7484a071..0c8d2a28 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,11 +41,10 @@ namespace gr { ofdm_synchronization_cvf::sptr ofdm_synchronization_cvf::make(int symbol_length, int cyclic_prefix_length, int fft_length, int symbols_per_frame) { - return gnuradio::get_initial_sptr - (new ofdm_synchronization_cvf_impl(symbol_length, - cyclic_prefix_length, - fft_length, - symbols_per_frame)); + return gnuradio::get_initial_sptr(new ofdm_synchronization_cvf_impl(symbol_length, + cyclic_prefix_length, + fft_length, + symbols_per_frame)); } /* @@ -63,7 +63,6 @@ namespace gr { d_correlation(0), d_energy_prefix(1), d_energy_repetition(1), - d_NULL_symbol_energy(1), d_frequency_offset_per_sample(0), d_NULL_detected(false), d_moving_average_counter(0), @@ -71,16 +70,13 @@ namespace gr { d_symbol_element_count(0), d_wait_for_NULL(true), d_on_triangle(false), - d_control_counter(0), d_phase(0), d_correlation_maximum(0), d_peak_set(false) { //allocation for repeating energy measurements unsigned int alignment = volk_get_alignment(); - d_mag_squared = (float *) volk_malloc( - sizeof(float) * d_cyclic_prefix_length, alignment); - d_fixed_lag_corr = (gr_complex *) volk_malloc( - sizeof(gr_complex) * d_cyclic_prefix_length, alignment); + d_mag_squared = (float *) volk_malloc(sizeof(float) * d_cyclic_prefix_length, alignment); + d_fixed_lag_corr = (gr_complex *) volk_malloc(sizeof(gr_complex) * d_cyclic_prefix_length, alignment); } /* @@ -90,17 +86,13 @@ namespace gr { } void - ofdm_synchronization_cvf_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { - ninput_items_required[0] = - noutput_items + d_symbol_length + d_cyclic_prefix_length + 1; + ofdm_synchronization_cvf_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { + ninput_items_required[0] = noutput_items + d_symbol_length + d_cyclic_prefix_length + 1; } void - ofdm_synchronization_cvf_impl::delayed_correlation(const gr_complex *sample, - bool new_calculation) { - if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || - new_calculation) { + ofdm_synchronization_cvf_impl::delayed_correlation(const gr_complex *sample, bool new_calculation) { + if (d_moving_average_counter > 100000 || d_moving_average_counter == 0 || new_calculation) { if (d_moving_average_counter == 0 && (!new_calculation)) { // first value is calculated completely, next values are calculated with moving average d_moving_average_counter++; @@ -117,39 +109,27 @@ namespace gr { d_correlation += d_fixed_lag_corr[i]; } // calculate energy of cyclic prefix for this sample completely - volk_32fc_magnitude_squared_32f(d_mag_squared, sample, - d_cyclic_prefix_length); - volk_32f_accumulator_s32f(&d_energy_prefix, d_mag_squared, - d_cyclic_prefix_length); + volk_32fc_magnitude_squared_32f(d_mag_squared, sample, d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_prefix, d_mag_squared, d_cyclic_prefix_length); // calculate energy of its repetition for this sample completely - volk_32fc_magnitude_squared_32f(d_mag_squared, &sample[d_symbol_length], - d_cyclic_prefix_length); - volk_32f_accumulator_s32f(&d_energy_repetition, d_mag_squared, - d_cyclic_prefix_length); + volk_32fc_magnitude_squared_32f(d_mag_squared, &sample[d_symbol_length], d_cyclic_prefix_length); + volk_32f_accumulator_s32f(&d_energy_repetition, d_mag_squared, d_cyclic_prefix_length); } else { // calculate next step for moving average - d_correlation += - sample[d_cyclic_prefix_length - 1] * - conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); - d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * - conj(sample[d_cyclic_prefix_length - 1])); - d_energy_repetition += std::real( - sample[d_symbol_length + d_cyclic_prefix_length - 1] * - conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); + d_correlation += sample[d_cyclic_prefix_length - 1] * conj(sample[d_symbol_length + d_cyclic_prefix_length - 1]); + d_energy_prefix += std::real(sample[d_cyclic_prefix_length - 1] * conj(sample[d_cyclic_prefix_length - 1])); + d_energy_repetition += std::real( sample[d_symbol_length + d_cyclic_prefix_length - 1] * + conj(sample[d_symbol_length + d_cyclic_prefix_length - 1])); d_correlation -= sample[0] * conj(sample[d_symbol_length]); d_energy_prefix -= std::real(sample[0] * conj(sample[0])); - d_energy_repetition -= std::real( - sample[d_symbol_length] * conj(sample[d_symbol_length])); + d_energy_repetition -= std::real(sample[d_symbol_length] * conj(sample[d_symbol_length])); d_moving_average_counter++; } // normalize - d_correlation_normalized = - d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); + d_correlation_normalized = d_correlation / std::sqrt(d_energy_prefix * d_energy_repetition); // calculate magnitude - d_correlation_normalized_magnitude = d_correlation_normalized.real() * - d_correlation_normalized.real() + - d_correlation_normalized.imag() * - d_correlation_normalized.imag(); + d_correlation_normalized_magnitude = d_correlation_normalized.real() * d_correlation_normalized.real() + + d_correlation_normalized.imag() * d_correlation_normalized.imag(); } /*! \brief returns true at a point with a little space before the peak of a correlation triangular @@ -160,10 +140,8 @@ namespace gr { if (d_on_triangle) { if (d_correlation_normalized_magnitude > d_correlation_maximum) { d_correlation_maximum = d_correlation_normalized_magnitude; - } - if (d_correlation_normalized_magnitude < d_correlation_maximum - 0.05 && - !d_peak_set) { + if (d_correlation_normalized_magnitude < d_correlation_maximum - 0.05 && !d_peak_set) { // we are right behind the peak d_peak_set = true; return true; @@ -179,7 +157,7 @@ namespace gr { } else { // not on a correlation triangle yet if (d_correlation_normalized_magnitude > 0.35) { - // no we are on the triangle + // now we are on the triangle d_on_triangle = true; return false; } else { @@ -204,11 +182,9 @@ namespace gr { // acquisition mode: search for next correlation peak after a NULL symbol delayed_correlation(&in[i], false); if (detect_start_of_symbol()) { - if (d_NULL_detected /*&& (d_energy_prefix > d_NULL_symbol_energy * 2)*/) { + if (d_NULL_detected) { // calculate new frequency offset - d_frequency_offset_per_sample = - std::arg(d_correlation) / d_fft_length; // in rad/sample - //GR_LOG_DEBUG(d_logger, format("Start of frame, abs offset %d")%(nitems_read(0)+i)); + d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/sample /* The start of the first symbol after the NULL symbol has been detected. The ideal start to copy * the symbol is &in[i+d_cyclic_prefix_length] to minimize ISI. */ @@ -224,16 +200,13 @@ namespace gr { d_NULL_detected = false; } } else { - if (((!d_NULL_detected) && - (d_energy_prefix / d_energy_repetition < 0.4))) { - // NULL symbol detection, if energy is < 0.1 * energy a symbol time later - d_NULL_symbol_energy = d_energy_prefix; + if (((!d_NULL_detected) && (d_energy_prefix / d_energy_repetition < 0.4))) { + // NULL symbol detection, if energy is < 0.4 * energy a symbol time later d_NULL_detected = true; } } } else { // tracking mode - if (d_symbol_element_count >= - (d_symbol_length + d_cyclic_prefix_length)) { + if (d_symbol_element_count >= (d_symbol_length + d_cyclic_prefix_length)) { // we expect the start of a new symbol here or the a NULL symbol if we arrived at the end of the frame d_symbol_count++; // next symbol expecting @@ -250,10 +223,8 @@ namespace gr { // correlation has to be calculated completely new, because of skipping samples before delayed_correlation(&in[i], true); // check if there is really a peak - if (d_correlation_normalized_magnitude > - 0.3) { //TODO: check if we are on right edge - d_frequency_offset_per_sample = - std::arg(d_correlation) / d_fft_length; // in rad/s + if (d_correlation_normalized_magnitude > 0.3) { //TODO: check if we are on right edge + d_frequency_offset_per_sample = std::arg(d_correlation) / d_fft_length; // in rad/sample } else { // no peak found -> out of track; search for next NULL symbol d_wait_for_NULL = true; @@ -264,8 +235,7 @@ namespace gr { } } } else if (d_cyclic_prefix_length * 0.75 <= d_symbol_element_count && - d_symbol_element_count < - d_cyclic_prefix_length * 0.75 + d_symbol_length) { + d_symbol_element_count < d_cyclic_prefix_length * 0.75 + d_symbol_length) { // calculate the complex frequency correction value float oi, oq; // fixed point sine and cosine @@ -273,8 +243,7 @@ namespace gr { gr::fxpt::sincos(angle, &oq, &oi); gr_complex fine_frequency_correction = gr_complex(oi, oq); // set tag at next item if it is the first element of the first symbol - if (d_symbol_count == 0 && - d_symbol_element_count == d_cyclic_prefix_length) { + if (d_symbol_count == 0 && d_symbol_element_count == d_cyclic_prefix_length) { add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), pmt::from_float(std::arg(d_correlation))); } @@ -285,7 +254,8 @@ namespace gr { } /* fine frequency correction: * The frequency offset estimation is done above with the correlation. - * The modulated frequency runs parralel to the whole input stream, including the cyclic prefix, and is mixed + * The modulated frequency runs parallel to the whole input stream, + * including the cyclic prefix, and is mixed * to the output symbol samples. */ d_phase += d_frequency_offset_per_sample; diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index 1d9b7313..f8a3d4fe 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* - * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) + * Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,40 +26,100 @@ namespace gr { namespace dab { -/*! \brief sets tag at the beginning of each OFDM frame +/*! \brief Sets tag at the beginning of each OFDM frame. + * Lets only pass the one OFDM frames (without the NULL symbol), which + * were detected completely. * - * \param symbol_length length of each OFDM symbol without guard intervall - * \param cyclic_prefix_length length of the cyclic prefix (= length of the guard intervall) - * \param num_ofdm_symbols number of OFDM symbols without the NULL symbol + * \param symbol_length Length of each OFDM symbol without guard intervall. + * \param cyclic_prefix_length Length of the cyclic prefix. (= length of the guard intervall) + * \param fft_length Length of the FFT vector. + * \param symbols_per_frame Number of OFDM symbols without the NULL symbol. * */ class ofdm_synchronization_cvf_impl : public ofdm_synchronization_cvf { private: - int d_symbol_length; - int d_cyclic_prefix_length; - int d_fft_length; + int d_symbol_length; /*!< Length of each OFDM symbol without guard intervall. */ + int d_cyclic_prefix_length; /*!< Length of the cyclic prefix. (= length of the guard intervall) */ + int d_fft_length; /*!< Length of the FFT vector.*/ int d_moving_average_counter; + /*!< Counts the number of steps the moving average did, to reset it + * from time to time to avoid value drifting caused by float rounding.*/ gr_complex d_correlation; + /*!< Fixed lag correlation (not normalized) with the lag length + * equal to the cyclic prefix length. + */ gr_complex d_correlation_normalized; + /*!< Normalized version of d_correlation. The normalization value + * is the mean energy of the correlation sequence, averaged between the + * two parts of the correlation. + */ float *d_mag_squared; + /*!< Allocated buffer for volk function. + * We write the calculated magnitued squared samples to this buffer to + * accumulate them in the next step. + */ gr_complex *d_fixed_lag_corr; + /*!< Allocated buffer for volk function. + * We write the calculated correlation samples to this buffer\ + * accumulate them in the next step. + */ float d_correlation_normalized_magnitude; + /*!< Magnitude of the current fixed correlation value.*/ float d_correlation_normalized_phase; + /*!< Phase of the current fixed correlation value. */ float d_energy_prefix; + /*!< Energy of the upcoming cyclic_prefix_length samples. This value + * is used for normalization and NULL symbol detection. + */ float d_energy_repetition; - float d_NULL_symbol_energy; + /*!< Energy of cyclic_prefix_length samplex, starting symbol_length + * samples from the current sample. This value is used for normalization + * and NULL symbol detection. When we are at the beginning of a OFDM symbol, + * this is equal to the energy of the cyclic prefix. + */ float d_frequency_offset_per_sample; + /*!< Frequency offset, described as a phase shift per sample. (in rad/sample)*/ bool d_NULL_detected; + /*!< Signalizes if we recently detected a NULL symbol and + * therefore expect the first symbol of the next frame now. + */ int d_symbols_per_frame; - int d_symbol_count; + /*!< Number of OFDM symbols without the NULL symbol. */ + int d_symbol_count; /*!< Counts the number of detected symbols.*/ int d_symbol_element_count; + /*!< Counts the number of samples in each symbol. */ bool d_wait_for_NULL; + /*!< Signalizes if we detected the last symbol of an OFDM frame and + * we are now expecting the NULL symbol. */ bool d_on_triangle; - int d_control_counter; + /*!< Signalizes if we are over the correlation threshold. + * This is used to do a kind of early late synchronization to find + * the correalation peak. + */ float d_phase; bool d_peak_set; + /*!< Signalizes if we already set the peak on the current + * correlation triangle. + */ float d_correlation_maximum; + /*!< Stores the max correlation value we detected so far on the current + * correlation triangle. + */ int d_nwritten; + /*!< Stores the number of items, we already wrote to the output buffer.*/ + + /*! \brief Calculates a fixed lag correlation over the given sample sequence. + * + * @param sample Pointer to the first sample of the sequence. + * @param new_calculation If true, calculated the correlation from scratch, else do a moving average. + */ + void delayed_correlation(const gr_complex *sample, bool new_calculation); + + /*! \brief Checks if we reached the maximum of a correlation triangle. + * Peak detection with a very simple, a-causal method. + * @return True, if we found the peak and therefore are at the start of a symbol. + */ + bool detect_start_of_symbol(); public: ofdm_synchronization_cvf_impl(int symbol_length, int cyclic_prefix_length, @@ -66,12 +127,6 @@ namespace gr { ~ofdm_synchronization_cvf_impl(); - void delayed_correlation(const gr_complex *sample, bool new_calculation); - - bool detect_peak(); - - bool detect_start_of_symbol(); - void forecast(int noutput_items, gr_vector_int &ninput_items_required); // Where all the action really happens diff --git a/lib/reed_solomon_encode_bb_impl.h b/lib/reed_solomon_encode_bb_impl.h index b5c4f342..489d3a8a 100644 --- a/lib/reed_solomon_encode_bb_impl.h +++ b/lib/reed_solomon_encode_bb_impl.h @@ -35,16 +35,20 @@ extern "C" { namespace gr { namespace dab { -/*! \brief Reed Solomon encoder for DAB+ transmission - * Reed Solomon RS(120, 110, t=5) with virtual interleaving; derived from RS(255, 245, t=5). Details see ETSI TS 102 563 clause 6.0 and 6.1. - * @param bit_rate_n data rate in multiples of 8kbit/s +/*! \brief Reed Solomon encoder for DAB+ transmission. + * Reed Solomon RS(120, 110, t=5) with virtual interleaving. + * Derived from RS(255, 245, t=5). Details see ETSI TS 102 563 clause 6.0 and 6.1. + * @param bit_rate_n Data rate in multiples of 8kbit/s. */ class reed_solomon_encode_bb_impl : public reed_solomon_encode_bb { + private: int d_bit_rate_n; - int d_superframe_size_rs; /*!< size of a superframe in byte with appended rs code words*/ - int d_superframe_size_in; /*!< size of a superframe in byte without rs code words*/ + int d_superframe_size_rs; + /*!< size of a superframe in byte with appended rs code words*/ + int d_superframe_size_in; + /*!< size of a superframe in byte without rs code words*/ void *rs_handle; public: diff --git a/lib/select_cus_vfvf_impl.cc b/lib/select_cus_vfvf_impl.cc index 91407134..1aa47046 100644 --- a/lib/select_cus_vfvf_impl.cc +++ b/lib/select_cus_vfvf_impl.cc @@ -31,8 +31,10 @@ namespace gr { select_cus_vfvf::sptr select_cus_vfvf::make(unsigned int vlen, unsigned int frame_len, unsigned int address, unsigned int size) { - return gnuradio::get_initial_sptr - (new select_cus_vfvf_impl(vlen, frame_len, address, size)); + return gnuradio::get_initial_sptr(new select_cus_vfvf_impl(vlen, + frame_len, + address, + size)); } /* @@ -76,8 +78,7 @@ namespace gr { if (d_address <= (nitems_read(0) + i) % d_frame_len && (nitems_read(0) + i) % d_frame_len < d_address + d_size) { //this cu is one of the selected subchannel -> copy it to ouput buffer - memcpy(&out[nwritten++ * d_vlen], &in[i * d_vlen], - d_vlen * sizeof(float)); + memcpy(&out[nwritten++ * d_vlen], &in[i * d_vlen], d_vlen * sizeof(float)); } } // Tell runtime system how many input items we consumed on diff --git a/lib/select_cus_vfvf_impl.h b/lib/select_cus_vfvf_impl.h index 24106269..df22c133 100644 --- a/lib/select_cus_vfvf_impl.h +++ b/lib/select_cus_vfvf_impl.h @@ -25,13 +25,16 @@ namespace gr { namespace dab { -/*! \brief selects items out of a stream, defined by start address and size - * This block is used to select the data of one MSC sub-channel out of a transmission frame. +/*! \brief Selects items out of a stream, defined by start address and size. + * This block is used to select the data of one MSC sub-channel + * out of a transmission frame. * - * @param vlen vector size of input and output vectors, defining the item size on witch the address and size variables base on - * @param frame_length length in items of a frame (each item is a vector with size vlen) - * @param address number of the first item in each frame to be copied - * @param size number of items to copy in each frame + * @param vlen Vector size of input and output vectors, + * defining the item size on witch the address and size variables base on. + * @param frame_length Length in items of a frame. + * (each item is a vector with size vlen) + * @param address Number of the first item in each frame to be copied. + * @param size Number of items to copy in each frame. */ class select_cus_vfvf_impl : public select_cus_vfvf { private: diff --git a/lib/sum_phasor_trig_vcc_impl.cc b/lib/sum_phasor_trig_vcc_impl.cc index b1def7e1..79533626 100644 --- a/lib/sum_phasor_trig_vcc_impl.cc +++ b/lib/sum_phasor_trig_vcc_impl.cc @@ -45,12 +45,8 @@ namespace gr { sum_phasor_trig_vcc_impl::sum_phasor_trig_vcc_impl(unsigned int length) : gr::sync_block("sum_phasor_trig_vcc", - gr::io_signature::make2(2, 2, - sizeof(gr_complex) * length, - sizeof(char)), - gr::io_signature::make2(2, 2, - sizeof(gr_complex) * length, - sizeof(char))), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * length, sizeof(char)), + gr::io_signature::make2(2, 2, sizeof(gr_complex) * length, sizeof(char))), d_length(length), d_last_symbol(length, 0) { } @@ -68,8 +64,9 @@ namespace gr { for (int i = 0; i < noutput_items; i++) { if (*frame_start == 1) { - for (unsigned int j = 0; j < d_length; j++) + for (unsigned int j = 0; j < d_length; j++) { out[j] = in[j]; + } } else { if (i == 0) { for (unsigned int j = 0; j < d_length; j++) @@ -86,14 +83,14 @@ namespace gr { /* need to remember last OFDM symbol before leaving function */ if (i == noutput_items - 1) { - for (unsigned int j = 0; j < d_length; j++) + for (unsigned int j = 0; j < d_length; j++) { d_last_symbol[j] = out[j]; + } } lastout = out; out += d_length; in += d_length; - } return noutput_items; diff --git a/lib/time_deinterleave_ff_impl.cc b/lib/time_deinterleave_ff_impl.cc index a76a441e..cda45d85 100644 --- a/lib/time_deinterleave_ff_impl.cc +++ b/lib/time_deinterleave_ff_impl.cc @@ -30,8 +30,8 @@ namespace gr { time_deinterleave_ff::sptr time_deinterleave_ff::make(int vector_length, const std::vector &scrambling_vector) { - return gnuradio::get_initial_sptr - (new time_deinterleave_ff_impl(vector_length, scrambling_vector)); + return gnuradio::get_initial_sptr(new time_deinterleave_ff_impl(vector_length, + scrambling_vector)); } /* @@ -46,8 +46,8 @@ namespace gr { d_scrambling_vector(scrambling_vector) { d_scrambling_length = scrambling_vector.size(); // size of the scrambling vector set_output_multiple(d_vector_length); - set_history((d_scrambling_length - 1) * d_vector_length + - 1); //need for max delay of (scrambling_length-1) * 24ms + // set history (need for max delay of (scrambling_length-1) * 24ms) + set_history((d_scrambling_length - 1) * d_vector_length + 1); } /* @@ -66,12 +66,8 @@ namespace gr { for (int i = 0; i < noutput_items / d_vector_length; i++) { // produce output vectors for (int j = 0; j < d_vector_length; j++) { - *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - - ((d_scrambling_length - 1) - - d_scrambling_vector[j % - d_scrambling_length])) + - j]; - //*out++ = in[i*d_vector_length + d_scrambling_vector[j%d_scrambling_length]*d_vector_length + j - (j%d_scrambling_length) + d_scrambling_vector[j%d_scrambling_length]]; + *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - ((d_scrambling_length - 1) - + d_scrambling_vector[j % d_scrambling_length])) + j]; } } // Tell runtime system how many output items we produced. diff --git a/lib/time_deinterleave_ff_impl.h b/lib/time_deinterleave_ff_impl.h index 35bd0f79..60e3e265 100644 --- a/lib/time_deinterleave_ff_impl.h +++ b/lib/time_deinterleave_ff_impl.h @@ -25,7 +25,8 @@ namespace gr { namespace dab { -/*! \brief applies time deinterleaving to a vector (convolutional deinterleaving -> descrambling and delay) +/*! \brief Applies time deinterleaving to a vector + * convolutional deinterleaving -> descrambling and delay * * Applies convolutional deinterleaving to a vector with its max[vector_length] followers, * the scrambling_vector describes which vector element comes from which follower. @@ -33,11 +34,13 @@ namespace gr { * More information to the interleaving rules on ETSI EN 300 401 chapter 12. * This deinterleaver restores a bitstream interleaved by the block time_interleave_bb. * - * @param vector_length length of input vectors - * @param scrambling_vector vector with scrambling parameters (see DAB standard p.138) + * @param vector_length Length of the input vectors. + * @param scrambling_vector Vector with scrambling parameters. + * (see ETSI EN 300 401 chapter 12) * */ class time_deinterleave_ff_impl : public time_deinterleave_ff { + private: int d_scrambling_length, d_vector_length; std::vector d_scrambling_vector; diff --git a/lib/time_interleave_bb_impl.cc b/lib/time_interleave_bb_impl.cc index afa6382b..277c24c9 100644 --- a/lib/time_interleave_bb_impl.cc +++ b/lib/time_interleave_bb_impl.cc @@ -31,8 +31,8 @@ namespace gr { time_interleave_bb::sptr time_interleave_bb::make(int vector_length, const std::vector &scrambling_vector) { - return gnuradio::get_initial_sptr - (new time_interleave_bb_impl(vector_length, scrambling_vector)); + return gnuradio::get_initial_sptr(new time_interleave_bb_impl(vector_length, + scrambling_vector)); } /* @@ -41,12 +41,8 @@ namespace gr { time_interleave_bb_impl::time_interleave_bb_impl(int vector_length, const std::vector &scrambling_vector) : gr::sync_block("time_interleave_bb", - gr::io_signature::make(1, 1, - sizeof(unsigned char) * - vector_length), - gr::io_signature::make(1, 1, - sizeof(unsigned char) * - vector_length)), + gr::io_signature::make(1, 1, sizeof(unsigned char) * vector_length), + gr::io_signature::make(1, 1, sizeof(unsigned char) * vector_length)), d_vector_length(vector_length), d_scrambling_vector(scrambling_vector) { d_scrambling_length = scrambling_vector.size(); //size of the scrambling vector @@ -68,12 +64,10 @@ namespace gr { unsigned char *out = (unsigned char *) output_items[0]; // produce output vectors - for (int i = 0; - i < noutput_items; i++) { //iteration over produced output vectors - for (int j = 0; - j < d_vector_length; j++) { //iteration over elements of vector - //*out++ = in[vec_length * (i + (scrambling_length-1) - d_scrambling_vector[j % scrambling_length]) + j]; - *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - d_scrambling_vector[j % d_scrambling_length]) + j]; + for (int i = 0; i < noutput_items; i++) { //iteration over produced output vectors + for (int j = 0; j < d_vector_length; j++) { //iteration over elements of vector + *out++ = in[d_vector_length * (i + (d_scrambling_length - 1) - + d_scrambling_vector[j % d_scrambling_length]) + j]; } } diff --git a/lib/time_interleave_bb_impl.h b/lib/time_interleave_bb_impl.h index ccf8f12b..d7dd5b27 100644 --- a/lib/time_interleave_bb_impl.h +++ b/lib/time_interleave_bb_impl.h @@ -25,7 +25,8 @@ namespace gr { namespace dab { -/*! \brief applies time interleaving to a vector (convolutional interleaving -> scrambling and delay) +/*! \brief Applies time interleaving to a vector + * convolutional interleaving -> scrambling and delay * * Applies convolutional interleaving to a vector with its max[vector_length] followers, * the scrambling_vector describes which vector element comes from which follower. @@ -33,7 +34,7 @@ namespace gr { * More information to the interleaving rules on ETSI EN 300 401 chapter 12. * * @param vector_length length of input vectors - * @param scrambling_vector vector with scrambling parameters (see DAB standard p.138) + * @param scrambling_vector vector with scrambling parameters (see ETSI EN 300 401 chapter 12) * */ @@ -43,8 +44,7 @@ namespace gr { std::vector d_scrambling_vector; public: - time_interleave_bb_impl(int vector_length, - const std::vector &scrambling_vector); + time_interleave_bb_impl(int vector_length, const std::vector &scrambling_vector); ~time_interleave_bb_impl(); diff --git a/lib/unpuncture_vff_impl.cc b/lib/unpuncture_vff_impl.cc index 131e4755..c86bf30e 100644 --- a/lib/unpuncture_vff_impl.cc +++ b/lib/unpuncture_vff_impl.cc @@ -38,12 +38,10 @@ namespace gr { unpuncture_vff::sptr unpuncture_vff::make(const std::vector &puncturing_vector, float fillval) { - return gnuradio::get_initial_sptr - (new unpuncture_vff_impl(puncturing_vector, fillval)); + return gnuradio::get_initial_sptr(new unpuncture_vff_impl(puncturing_vector, fillval)); } - unsigned int unpuncture_vff_impl::ones( - const std::vector &puncturing_vector) { + unsigned int unpuncture_vff_impl::ones(const std::vector &puncturing_vector) { unsigned int onescount = 0; for (unsigned int i = 0; i < puncturing_vector.size(); i++) { if (puncturing_vector[i] == 1) @@ -55,10 +53,8 @@ namespace gr { unpuncture_vff_impl::unpuncture_vff_impl( const std::vector &puncturing_vector, float fillval) : gr::sync_block("unpuncture_vff", - gr::io_signature::make(1, 1, sizeof(float) * - ones(puncturing_vector)), - gr::io_signature::make(1, 1, sizeof(float) * - puncturing_vector.size())), + gr::io_signature::make(1, 1, sizeof(float) * ones(puncturing_vector)), + gr::io_signature::make(1, 1, sizeof(float) * puncturing_vector.size())), d_puncturing_vector(puncturing_vector), d_fillval(fillval) { d_vlen_in = ones(puncturing_vector); d_vlen_out = puncturing_vector.size(); @@ -76,10 +72,12 @@ namespace gr { for (i = 0; i < noutput_items; i++) { for (j = 0; j < d_vlen_out; j++) { - if (d_puncturing_vector[j] == 1) + if (d_puncturing_vector[j] == 1) { *out++ = *in++; - else + } + else { *out++ = d_fillval; + } } } diff --git a/lib/unpuncture_vff_impl.h b/lib/unpuncture_vff_impl.h index f375fab5..4ffde2a0 100644 --- a/lib/unpuncture_vff_impl.h +++ b/lib/unpuncture_vff_impl.h @@ -26,12 +26,14 @@ namespace gr { namespace dab { -/*! \brief unpuncturing of a stream sequence +/*! \brief Unpuncturing of a stream bit sequence. * - * unpuncturing of a stream sequence according to the puncturing_vector (writing a stream element at a '1' and writing the fillval at a '0') + * Unpuncturing of a stream sequence according to the puncturing_vector. + * (writing a stream element at a '1' and writing the fillval at a '0') * - * @param puncturing_vector vector with puncturing sequence, length of puncturing_vector is length of a stream sequence - * @param fillval value to fill in for a zero of the puncturing vector + * @param puncturing_vector Vector with puncturing sequence, + * length of puncturing_vector is length of a stream sequence. + * @param fillval Value to fill in for a zero of the puncturing vector. * */ class unpuncture_vff_impl : public unpuncture_vff { @@ -44,8 +46,7 @@ namespace gr { unsigned int d_vlen_out; public: - unpuncture_vff_impl(const std::vector &puncturing_vector, - float fillval); + unpuncture_vff_impl(const std::vector &puncturing_vector, float fillval); int work(int noutput_items, gr_vector_const_void_star &input_items, diff --git a/lib/valve_ff_impl.cc b/lib/valve_ff_impl.cc index 2db6cbe7..182b6e97 100644 --- a/lib/valve_ff_impl.cc +++ b/lib/valve_ff_impl.cc @@ -30,8 +30,7 @@ namespace gr { valve_ff::sptr valve_ff::make(bool closed, bool feed_with_zeros) { - return gnuradio::get_initial_sptr - (new valve_ff_impl(closed, feed_with_zeros)); + return gnuradio::get_initial_sptr(new valve_ff_impl(closed, feed_with_zeros)); } /* @@ -41,7 +40,8 @@ namespace gr { : gr::block("valve_ff", gr::io_signature::make(1, 1, sizeof(float)), gr::io_signature::make(1, 1, sizeof(float))), - d_feed_with_zeros(feed_with_zeros), d_closed(closed) {} + d_feed_with_zeros(feed_with_zeros), d_closed(closed) { + } /* * Our virtual destructor. @@ -50,8 +50,7 @@ namespace gr { } void - valve_ff_impl::forecast(int noutput_items, - gr_vector_int &ninput_items_required) { + valve_ff_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { ninput_items_required[0] = noutput_items; } diff --git a/lib/valve_ff_impl.h b/lib/valve_ff_impl.h index ff987bfa..284c8320 100644 --- a/lib/valve_ff_impl.h +++ b/lib/valve_ff_impl.h @@ -25,9 +25,9 @@ namespace gr { namespace dab { -/*! \brief lets samples pass or not depending on the state of closed - * @param feed_with_zeros if valve is closed feed_with_zeros decides if zeros are sent or nothing - * @param closed decides if valve is closed or opened +/*! \brief Lets samples pass or not depending on the state of an input variable. + * @param feed_with_zeros If valve is closed send zeros if true, else send nothing. + * @param closed Controls if valve is closed or opened. */ class valve_ff_impl : public valve_ff { private: From 5ac53adf9d69bfcd763cc7e6334cf297200bf413 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Tue, 14 Aug 2018 14:39:07 +0200 Subject: [PATCH 130/135] relative_rate: cast integer values to float before division --- lib/insert_null_symbol_impl.cc | 12 ++++++++---- lib/prune_impl.cc | 12 ++++++------ lib/puncture_bb_impl.cc | 12 ++++++------ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/insert_null_symbol_impl.cc b/lib/insert_null_symbol_impl.cc index e07afab0..0cacc0f7 100644 --- a/lib/insert_null_symbol_impl.cc +++ b/lib/insert_null_symbol_impl.cc @@ -1,19 +1,20 @@ /* -*- c++ -*- */ /* * Copyright 2004 Free Software Foundation, Inc. - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This file is part of GNU Radio - * + * * GNU Radio 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, or (at your option) * any later version. - * + * * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -57,6 +58,9 @@ namespace gr { * * maybe the scheduler thinks that d_symbol_length input items are needed, which uses a lot of memory **/ + if (d_symbol_length <= 0){ + throw std::runtime_error("Symbol length must be greater zero!"); + } set_output_multiple(d_symbol_length); set_relative_rate(d_symbol_length); } diff --git a/lib/prune_impl.cc b/lib/prune_impl.cc index d91546d8..741c4127 100644 --- a/lib/prune_impl.cc +++ b/lib/prune_impl.cc @@ -1,17 +1,18 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -55,7 +56,7 @@ namespace gr { (prune_start + prune_end - length)).str()); set_output_multiple(length - prune_start - prune_end); - set_relative_rate((length - prune_start - prune_end) / length); + set_relative_rate(static_cast(length - prune_start - prune_end) / static_cast(length)); } /* @@ -96,4 +97,3 @@ namespace gr { } /* namespace dab */ } /* namespace gr */ - diff --git a/lib/puncture_bb_impl.cc b/lib/puncture_bb_impl.cc index b30ec926..400de916 100644 --- a/lib/puncture_bb_impl.cc +++ b/lib/puncture_bb_impl.cc @@ -1,17 +1,18 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -56,7 +57,7 @@ namespace gr { d_vlen_in = puncturing_vector.size(); d_vlen_out = ones(puncturing_vector); set_output_multiple(d_vlen_out); - set_relative_rate(d_vlen_out / d_vlen_in); + set_relative_rate(static_cast(d_vlen_out) / static_cast(d_vlen_in)); } /* @@ -95,4 +96,3 @@ namespace gr { } /* namespace dab */ } /* namespace gr */ - From 3ae983ad1b6e0d7d641dde66dd95e44b58879ec9 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Tue, 14 Aug 2018 14:39:07 +0200 Subject: [PATCH 131/135] relative_rate: cast integer values to float before division --- lib/insert_null_symbol_impl.cc | 12 ++++++++---- lib/prune_impl.cc | 12 ++++++------ lib/puncture_bb_impl.cc | 12 ++++++------ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/insert_null_symbol_impl.cc b/lib/insert_null_symbol_impl.cc index e07afab0..0cacc0f7 100644 --- a/lib/insert_null_symbol_impl.cc +++ b/lib/insert_null_symbol_impl.cc @@ -1,19 +1,20 @@ /* -*- c++ -*- */ /* * Copyright 2004 Free Software Foundation, Inc. - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This file is part of GNU Radio - * + * * GNU Radio 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, or (at your option) * any later version. - * + * * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -57,6 +58,9 @@ namespace gr { * * maybe the scheduler thinks that d_symbol_length input items are needed, which uses a lot of memory **/ + if (d_symbol_length <= 0){ + throw std::runtime_error("Symbol length must be greater zero!"); + } set_output_multiple(d_symbol_length); set_relative_rate(d_symbol_length); } diff --git a/lib/prune_impl.cc b/lib/prune_impl.cc index d91546d8..741c4127 100644 --- a/lib/prune_impl.cc +++ b/lib/prune_impl.cc @@ -1,17 +1,18 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -55,7 +56,7 @@ namespace gr { (prune_start + prune_end - length)).str()); set_output_multiple(length - prune_start - prune_end); - set_relative_rate((length - prune_start - prune_end) / length); + set_relative_rate(static_cast(length - prune_start - prune_end) / static_cast(length)); } /* @@ -96,4 +97,3 @@ namespace gr { } /* namespace dab */ } /* namespace gr */ - diff --git a/lib/puncture_bb_impl.cc b/lib/puncture_bb_impl.cc index b30ec926..400de916 100644 --- a/lib/puncture_bb_impl.cc +++ b/lib/puncture_bb_impl.cc @@ -1,17 +1,18 @@ /* -*- c++ -*- */ -/* +/* * Copyright 2017 Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). - * + * Copyright 2018 Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). + * * This 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, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -56,7 +57,7 @@ namespace gr { d_vlen_in = puncturing_vector.size(); d_vlen_out = ones(puncturing_vector); set_output_multiple(d_vlen_out); - set_relative_rate(d_vlen_out / d_vlen_in); + set_relative_rate(static_cast(d_vlen_out) / static_cast(d_vlen_in)); } /* @@ -95,4 +96,3 @@ namespace gr { } /* namespace dab */ } /* namespace gr */ - From fa9eb52587ead7729e770b3d6d1a200fb95624ad Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Tue, 28 Aug 2018 16:28:45 +0200 Subject: [PATCH 132/135] ofdm_sync: speed improvements through volkizing --- lib/ofdm_synchronization_cvf_impl.cc | 64 +++++++++++++++------------- lib/ofdm_synchronization_cvf_impl.h | 3 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/lib/ofdm_synchronization_cvf_impl.cc b/lib/ofdm_synchronization_cvf_impl.cc index 0c8d2a28..91d0cea3 100644 --- a/lib/ofdm_synchronization_cvf_impl.cc +++ b/lib/ofdm_synchronization_cvf_impl.cc @@ -2,6 +2,7 @@ /* * Copyright 2017, 2018 Moritz Luca Schmid, Communications Engineering Lab (CEL) * Karlsruhe Institute of Technology (KIT). + * Copyright 2018 Communications Engineering Lab (CEL) Karlsruhe Institute of Technology (KIT). * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,14 +24,14 @@ #include "config.h" #endif -#include -#include -#include -#include -#include #include "ofdm_synchronization_cvf_impl.h" +#include +#include #include -#include +#include +#include +#include +#include #include using namespace boost; @@ -70,13 +71,14 @@ namespace gr { d_symbol_element_count(0), d_wait_for_NULL(true), d_on_triangle(false), - d_phase(0), - d_correlation_maximum(0), - d_peak_set(false) { + d_phase(gr_complex(1,0)), + d_peak_set(false), + d_correlation_maximum(0){ //allocation for repeating energy measurements unsigned int alignment = volk_get_alignment(); d_mag_squared = (float *) volk_malloc(sizeof(float) * d_cyclic_prefix_length, alignment); d_fixed_lag_corr = (gr_complex *) volk_malloc(sizeof(gr_complex) * d_cyclic_prefix_length, alignment); + this->set_output_multiple(d_symbol_length); } /* @@ -172,6 +174,7 @@ namespace gr { gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + // Initialize this run of work const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; d_nwritten = 0; @@ -234,21 +237,29 @@ namespace gr { d_correlation_normalized_magnitude); } } - } else if (d_cyclic_prefix_length * 0.75 <= d_symbol_element_count && - d_symbol_element_count < d_cyclic_prefix_length * 0.75 + d_symbol_length) { - // calculate the complex frequency correction value - float oi, oq; - // fixed point sine and cosine - int32_t angle = gr::fxpt::float_to_fixed(d_phase); - gr::fxpt::sincos(angle, &oq, &oi); - gr_complex fine_frequency_correction = gr_complex(oi, oq); - // set tag at next item if it is the first element of the first symbol - if (d_symbol_count == 0 && d_symbol_element_count == d_cyclic_prefix_length) { - add_item_tag(0, nitems_written(0) + d_nwritten, pmt::mp("Start"), - pmt::from_float(std::arg(d_correlation))); + } else if (d_symbol_element_count == (3 * d_cyclic_prefix_length)/4){ + // No full OFDM symbol in the input left + if (noutput_items - i < d_symbol_length || ninput_items[0] - i < d_symbol_length) { + this->consume_each(i); + return d_nwritten; + } else { + d_phase *= + std::polar(float(1.0), + static_cast(d_cyclic_prefix_length * + d_frequency_offset_per_sample)); + if (d_symbol_count == 0) { + this->add_item_tag(0, this->nitems_written(0) + d_nwritten + d_cyclic_prefix_length - d_symbol_element_count, + pmt::mp("Start"), + pmt::from_float(std::arg(d_correlation))); + } + volk_32fc_s32fc_x2_rotator_32fc( + &out[d_nwritten], &in[i], + std::polar(float(1.0), d_frequency_offset_per_sample), + &d_phase, d_symbol_length); + d_nwritten += d_symbol_length; + d_symbol_element_count += d_symbol_length - 1; + i += d_symbol_length - 1; } - // now we start copying one symbol length to the output - out[d_nwritten++] = in[i] * fine_frequency_correction; } d_symbol_element_count++; } @@ -258,15 +269,10 @@ namespace gr { * including the cyclic prefix, and is mixed * to the output symbol samples. */ - d_phase += d_frequency_offset_per_sample; - //place phase in [-pi, +pi[ - d_phase = std::fmod(d_phase + M_PI, 2.0f * M_PI) - M_PI; - } - + } consume_each(noutput_items); return d_nwritten; } } /* namespace dab */ } /* namespace gr */ - diff --git a/lib/ofdm_synchronization_cvf_impl.h b/lib/ofdm_synchronization_cvf_impl.h index f8a3d4fe..84ee5ae8 100644 --- a/lib/ofdm_synchronization_cvf_impl.h +++ b/lib/ofdm_synchronization_cvf_impl.h @@ -96,7 +96,7 @@ namespace gr { * This is used to do a kind of early late synchronization to find * the correalation peak. */ - float d_phase; + gr_complex d_phase; bool d_peak_set; /*!< Signalizes if we already set the peak on the current * correlation triangle. @@ -139,4 +139,3 @@ namespace gr { } // namespace gr #endif /* INCLUDED_DAB_OFDM_SYNCHRONIZATION_CVF_IMPL_H */ - From 8ec05f48aee6097039f215eb09edb3d1fe418773 Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Mon, 3 Sep 2018 09:56:20 +0200 Subject: [PATCH 133/135] diff_phasor: volkize --- lib/diff_phasor_vcc_impl.cc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/diff_phasor_vcc_impl.cc b/lib/diff_phasor_vcc_impl.cc index c4cbb35b..cc904bd9 100644 --- a/lib/diff_phasor_vcc_impl.cc +++ b/lib/diff_phasor_vcc_impl.cc @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* * Copyright 2004 Free Software Foundation, Inc. - * + * * This file is part of GNU Radio - * + * * GNU Radio 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, or (at your option) * any later version. - * + * * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -32,6 +32,7 @@ #include #include #include "diff_phasor_vcc_impl.h" +#include "volk/volk.h" namespace gr { namespace dab { @@ -57,11 +58,7 @@ namespace gr { gr_vector_void_star &output_items) { gr_complex const *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - - for (unsigned int i = 0; i < noutput_items * d_length; i++) { - out[i] = in[i + d_length] * conj(in[i]); - } - + volk_32fc_x2_multiply_conjugate_32fc(out, in + d_length, in, noutput_items * d_length); return noutput_items; } From 8ab7ed77ae72301470273a8cb3d838e5649a242d Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Mon, 3 Sep 2018 09:57:02 +0200 Subject: [PATCH 134/135] fib_sink: replace assert, comment not working solution --- lib/fib_sink_vb_impl.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/fib_sink_vb_impl.cc b/lib/fib_sink_vb_impl.cc index 40bcc4be..5eef6f83 100644 --- a/lib/fib_sink_vb_impl.cc +++ b/lib/fib_sink_vb_impl.cc @@ -2,7 +2,7 @@ /* * Copyright 2017 by Moritz Luca Schmid, Communications Engineering Lab (CEL) / Karlsruhe Institute of Technology (KIT). * Copyright 2008 by Andreas Mueller - * + * * This 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, or (at your option) @@ -72,8 +72,14 @@ namespace gr { (uint8_t) fib[pos] != 0) { //TODO correct? type = fib[pos] >> 5; length = fib[pos] & 0x1f; - assert(pos + length <= FIB_LENGTH - FIB_CRC_LENGTH); - assert(length != 0); + // if ((pos + length) > (FIB_LENGTH - FIB_CRC_LENGTH)){ + // GR_LOG_INFO(d_logger, "pos + length: " + std::to_string((pos + length))); + // return 1; + // } + // if (length != 0){ + // GR_LOG_INFO(d_logger, "length must be greater than zero!"); + // return 1; + // } process_fig(type, &fib[pos], length); pos += length + 1; } From 2b8efb61da2ba3bf34edec90bbd2803fede80a3e Mon Sep 17 00:00:00 2001 From: Andrej Rode Date: Mon, 3 Sep 2018 09:57:29 +0200 Subject: [PATCH 135/135] mp4_decode: replace throw with debug statement --- lib/mp4_decode_bs_impl.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/mp4_decode_bs_impl.cc b/lib/mp4_decode_bs_impl.cc index a2e59337..64549c96 100644 --- a/lib/mp4_decode_bs_impl.cc +++ b/lib/mp4_decode_bs_impl.cc @@ -14,12 +14,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * This software 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 software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -343,7 +343,12 @@ namespace gr { // sanity check for the address if (d_au_start[i + 1] < d_au_start[i]) { - throw std::runtime_error("AU start address invalid"); + // throw std::runtime_error("AU start address invalid"); + std::cout << "AU start address invalid" + << "d_au_start[" << i + << "] = " << d_au_start[i] << "; d_au_start[" << (i+1) + << "]=" << d_au_start[i + 1] << std::endl; + continue; // should not happen, the header is firecode checked } aac_frame_length = d_au_start[i + 1] - d_au_start[i] - 2;