[THIS MAY BREAK THINGS, BE AWARE] Merge Win32 support and C++ dvmbridge into master. (#67)
* experimental support for WIN32 compilation (tested only with VS2022); * fix up incorrect return; * make debug compile verbose; ensure ws2_32.lib is included; * initial commit of vocoder library to main source tree; initial commit of C++ port of bridge (non-functional); * calculate the length of the preamble tone and properly write it; * implement MDC callback to detect MDC unit ID; implement UDP audio reception; implement local audio reception; * very alpha working verison; * correct buffer size; * correct issue with enabled Tx mode not properly being set on the network; correct issue with DMR not setting the appropriate frame length after packing AMBE bits; correct false call starts by faking the txStreamId (this isn't correct but works for now); fix issue with P25 non-GROUP LCOs causing audio breaks; correct bad logic for call lockup thread; * cleanup and properly align log messages; * implement missing Rx/Tx manual gain control; fix missing srcId overrides; * eliminate the __ALLOC_VLA macro (this really only works on VS2022, GCC explodes in a fit of horror); * fix missing comment; * fix bad CFLAGS; correct missing dl library when linking dvmbridge on linux; fix various typos and bad variable types in bridge; * fix some bad memset calls not taking array size into account; fix some missing parens; * implement missing cal options; * don't start the timer till the first LDU1 for cal mode; * I'm just full of bad mistakes today; * ignore logging excessive sync frame errors; * update modem submodule; * Add DVM-V24 Firmware Submodule And Enable Building It (#66) * Added v24 firmware as a submodule * Added v24 firmware compilation * V24 doesn't have make clean, so remove it from cmake * Added V24 firmware to tarballs * Fix my 1D107 error... --------- Co-authored-by: faulty <faulty@evilcomputing.net> * correct compilation flags for Win32; add support to dump sample levels on bridge (this is useful for tuning the vox level); add various fixes for local audio flag; add various fixes for not starting loops until completely running; ensure audio input/output device settings are output to the log; fix issue with Rx and Tx gain controls not being applied appropriately; * fix compilation issues for RPI_ARM; ensure math constants are defined; remove unused command line arguments; --------- Co-authored-by: Jim <25770089+faultywarrior@users.noreply.github.com> Co-authored-by: faulty <faulty@evilcomputing.net>pull/69/head
parent
37e058731c
commit
65fa91b7cb
@ -0,0 +1,136 @@
|
|||||||
|
#
|
||||||
|
# Digital Voice Modem - Bridge
|
||||||
|
#
|
||||||
|
# @package DVM / Bridge
|
||||||
|
#
|
||||||
|
|
||||||
|
# Flag indicating whether the host will run as a background or foreground task.
|
||||||
|
daemon: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Logging Configuration
|
||||||
|
#
|
||||||
|
# Logging Levels:
|
||||||
|
# 1 - Debug
|
||||||
|
# 2 - Message
|
||||||
|
# 3 - Informational
|
||||||
|
# 4 - Warning
|
||||||
|
# 5 - Error
|
||||||
|
# 6 - Fatal
|
||||||
|
#
|
||||||
|
log:
|
||||||
|
# Console display logging level (used when in foreground).
|
||||||
|
displayLevel: 1
|
||||||
|
# File logging level.
|
||||||
|
fileLevel: 1
|
||||||
|
# Flag indicating file logs should be sent to syslog instead of a file.
|
||||||
|
useSyslog: false
|
||||||
|
# Full path for the directory to store the log files.
|
||||||
|
filePath: .
|
||||||
|
# Full path for the directory to store the activity log files.
|
||||||
|
activityFilePath: .
|
||||||
|
# Log filename prefix.
|
||||||
|
fileRoot: dvmbridge
|
||||||
|
|
||||||
|
#
|
||||||
|
# Network Configuration
|
||||||
|
#
|
||||||
|
network:
|
||||||
|
# Network Peer ID
|
||||||
|
id: 9000123
|
||||||
|
# Hostname/IP address of FNE master to connect to.
|
||||||
|
address: 127.0.0.1
|
||||||
|
# Port number to connect to.
|
||||||
|
port: 62031
|
||||||
|
# FNE access password.
|
||||||
|
password: RPT1234
|
||||||
|
|
||||||
|
# Flag indicating whether or not host endpoint networking is encrypted.
|
||||||
|
encrypted: false
|
||||||
|
# AES-256 32-byte Preshared Key
|
||||||
|
# (This field *must* be 32 hex bytes in length or 64 characters
|
||||||
|
# 0 - 9, A - F.)
|
||||||
|
presharedKey: "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"
|
||||||
|
|
||||||
|
# Flag indicating whether or not verbose debug logging is enabled.
|
||||||
|
debug: false
|
||||||
|
|
||||||
|
# Enable PCM audio over UDP.
|
||||||
|
udpAudio: false
|
||||||
|
# Enable meta data such as dstId and srcId in the UDP data
|
||||||
|
udpMetaData: false
|
||||||
|
# PCM over UDP send port.
|
||||||
|
udpSendPort: 34001
|
||||||
|
# PCM over UDP send address destination.
|
||||||
|
udpSendAddress: "127.0.0.1"
|
||||||
|
# PCM over UDP receive port.
|
||||||
|
udpReceivePort: 32001
|
||||||
|
# PCM over UDP receive address.
|
||||||
|
udpReceiveAddress: "127.0.0.1"
|
||||||
|
|
||||||
|
# Source "Radio ID" for transmitted audio frames.
|
||||||
|
sourceId: 1234567
|
||||||
|
# Flag indicating the source "Radio ID" will be overridden from the detected
|
||||||
|
# MDC1200 pre- PTT ID.
|
||||||
|
overrideSourceIdFromMDC: false
|
||||||
|
# Flag indicating the source "Radio ID" will be overridden from the received
|
||||||
|
# UDP SRC ID.
|
||||||
|
overrideSourceIdFromUDP: false
|
||||||
|
# Talkgroup ID for transmitted/received audio frames.
|
||||||
|
destinationId: 1
|
||||||
|
# Slot for received/transmitted audio frames.
|
||||||
|
slot: 1
|
||||||
|
|
||||||
|
system:
|
||||||
|
# Textual Name
|
||||||
|
identity: BRIDGE
|
||||||
|
|
||||||
|
# PCM audio gain for received (from digital network) audio frames.
|
||||||
|
# - This is used to apply gain to the decoded IMBE/AMBE audio, post-decoding.
|
||||||
|
rxAudioGain: 1.0
|
||||||
|
# Vocoder audio gain for decoded (from digital network) audio frames.
|
||||||
|
# - This is used to apply gain to the decoded IMBE/AMBE audio in the vocoder.
|
||||||
|
# - (Not used when utilizing external USB vocoder!)
|
||||||
|
vocoderDecoderAudioGain: 3.0
|
||||||
|
# Flag indicating AGC should be used for frames received/decoded.
|
||||||
|
# - This is used to apply automatic gain control to decoded IMBE/AMBE audio in the vocoder.
|
||||||
|
# - (Not used when utilizing external USB vocoder!)
|
||||||
|
vocoderDecoderAutoGain: false
|
||||||
|
|
||||||
|
# PCM audio gain for transmitted (to digital network) audio frames.
|
||||||
|
# - This is used to apply gain to the encoded IMBE/AMBE audio, pre-encoding.
|
||||||
|
txAudioGain: 1.0
|
||||||
|
# Vocoder audio gain for transmitted/encoded (to digital network) audio frames.
|
||||||
|
# - This is used to apply gain to the encoded IMBE/AMBE audio in the vocoder.
|
||||||
|
# - (Not used when utilizing external USB vocoder!)
|
||||||
|
vocoderEncoderAudioGain: 3.0
|
||||||
|
|
||||||
|
# Audio transmit mode (1 - DMR, 2 - P25).
|
||||||
|
txMode: 1
|
||||||
|
|
||||||
|
# Relative sample level for VOX to activate.
|
||||||
|
voxSampleLevel: 80.0
|
||||||
|
# Amount of time (ms) from loss of active VOX level to drop audio.
|
||||||
|
dropTimeMs: 180
|
||||||
|
|
||||||
|
# Enables detection of MDC1200 packets on the PCM side of the bridge.
|
||||||
|
# (This is useful for pre-MDC to set the transmitting source ID.)
|
||||||
|
detectAnalogMDC1200: false
|
||||||
|
|
||||||
|
# Flag indicating whether the analog preamble leader is enabled.
|
||||||
|
# (This enables a leader control tone before audio frames from the
|
||||||
|
# network are sent.)
|
||||||
|
preambleLeaderTone: false
|
||||||
|
# Frequency of preamble tone.
|
||||||
|
preambleTone: 2175
|
||||||
|
# Amount of time (ms) to transmit preamble tone.
|
||||||
|
preambleLength: 200
|
||||||
|
|
||||||
|
# Flag indicating the detected VOX sample level should be dumped to the log (useful for setting VOX levels).
|
||||||
|
dumpSampleLevel: false
|
||||||
|
|
||||||
|
# Flag indicating whether a network grant demand packet will be sent before audio.
|
||||||
|
grantDemand: false
|
||||||
|
|
||||||
|
# Enable local audio over speakers.
|
||||||
|
localAudio: true
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "ActivityLog.h"
|
||||||
|
#include "common/network/BaseNetwork.h"
|
||||||
|
#include "common/Log.h" // for CurrentLogFileLevel() and LogGetNetwork()
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include "common/Clock.h"
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
#if defined(CATCH2_TEST_COMPILATION)
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define EOL "\r\n"
|
||||||
|
|
||||||
|
const uint32_t ACT_LOG_BUFFER_LEN = 501U;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Variables
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static std::string m_actFilePath;
|
||||||
|
static std::string m_actFileRoot;
|
||||||
|
|
||||||
|
static FILE* m_actFpLog = nullptr;
|
||||||
|
|
||||||
|
static struct tm m_actTm;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Helper to open the activity log file, file handle. */
|
||||||
|
|
||||||
|
static bool ActivityLogOpen()
|
||||||
|
{
|
||||||
|
if (CurrentLogFileLevel() == 0U)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
time_t now;
|
||||||
|
::time(&now);
|
||||||
|
|
||||||
|
struct tm* tm = ::gmtime(&now);
|
||||||
|
|
||||||
|
if (tm->tm_mday == m_actTm.tm_mday && tm->tm_mon == m_actTm.tm_mon && tm->tm_year == m_actTm.tm_year) {
|
||||||
|
if (m_actFpLog != nullptr)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_actFpLog != nullptr)
|
||||||
|
::fclose(m_actFpLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
char filename[200U];
|
||||||
|
::sprintf(filename, "%s/%s-%04d-%02d-%02d.activity.log", LogGetFilePath().c_str(), LogGetFileRoot().c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||||
|
|
||||||
|
m_actFpLog = ::fopen(filename, "a+t");
|
||||||
|
m_actTm = *tm;
|
||||||
|
|
||||||
|
return m_actFpLog != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initializes the activity log. */
|
||||||
|
|
||||||
|
bool ActivityLogInitialise(const std::string& filePath, const std::string& fileRoot)
|
||||||
|
{
|
||||||
|
#if defined(CATCH2_TEST_COMPILATION)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
m_actFilePath = filePath;
|
||||||
|
m_actFileRoot = fileRoot;
|
||||||
|
|
||||||
|
return ::ActivityLogOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalizes the activity log. */
|
||||||
|
|
||||||
|
void ActivityLogFinalise()
|
||||||
|
{
|
||||||
|
#if defined(CATCH2_TEST_COMPILATION)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
if (m_actFpLog != nullptr)
|
||||||
|
::fclose(m_actFpLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes a new entry to the activity log. */
|
||||||
|
|
||||||
|
void ActivityLog(const char* msg, ...)
|
||||||
|
{
|
||||||
|
#if defined(CATCH2_TEST_COMPILATION)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
assert(msg != nullptr);
|
||||||
|
|
||||||
|
char buffer[ACT_LOG_BUFFER_LEN];
|
||||||
|
time_t now;
|
||||||
|
::time(&now);
|
||||||
|
struct tm* tm = ::localtime(&now);
|
||||||
|
|
||||||
|
struct timeval nowMillis;
|
||||||
|
::gettimeofday(&nowMillis, NULL);
|
||||||
|
|
||||||
|
::sprintf(buffer, "A: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, nowMillis.tv_usec / 1000U);
|
||||||
|
|
||||||
|
va_list vl, vl_len;
|
||||||
|
va_start(vl, msg);
|
||||||
|
va_copy(vl_len, vl);
|
||||||
|
|
||||||
|
size_t len = ::vsnprintf(nullptr, 0U, msg, vl_len);
|
||||||
|
::vsnprintf(buffer + ::strlen(buffer), len + 1U, msg, vl);
|
||||||
|
|
||||||
|
va_end(vl_len);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
bool ret = ::ActivityLogOpen();
|
||||||
|
if (!ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (LogGetNetwork() != nullptr) {
|
||||||
|
network::BaseNetwork* network = (network::BaseNetwork*)LogGetNetwork();;
|
||||||
|
network->writeActLog(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentLogFileLevel() == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
::fprintf(m_actFpLog, "%s\n", buffer);
|
||||||
|
::fflush(m_actFpLog);
|
||||||
|
|
||||||
|
if (2U >= g_logDisplayLevel && g_logDisplayLevel != 0U) {
|
||||||
|
::fprintf(stdout, "%s" EOL, buffer);
|
||||||
|
::fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file ActivityLog.h
|
||||||
|
* @ingroup bridge
|
||||||
|
* @file ActivityLog.cpp
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
#if !defined(__ACTIVITY_LOG_H__)
|
||||||
|
#define __ACTIVITY_LOG_H__
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the activity log.
|
||||||
|
* @param filePath File path for the log file.
|
||||||
|
* @param fileRoot Root name for log file.
|
||||||
|
*/
|
||||||
|
extern HOST_SW_API bool ActivityLogInitialise(const std::string& filePath, const std::string& fileRoot);
|
||||||
|
/**
|
||||||
|
* @brief Finalizes the activity log.
|
||||||
|
*/
|
||||||
|
extern HOST_SW_API void ActivityLogFinalise();
|
||||||
|
/**
|
||||||
|
* @brief Writes a new entry to the activity log.
|
||||||
|
* @param msg String format.
|
||||||
|
*
|
||||||
|
* This is a variable argument function.
|
||||||
|
*/
|
||||||
|
extern HOST_SW_API void ActivityLog(const char* msg, ...);
|
||||||
|
|
||||||
|
#endif // __ACTIVITY_LOG_H__
|
||||||
@ -0,0 +1,272 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "Defines.h"
|
||||||
|
#include "common/Log.h"
|
||||||
|
#include "bridge/ActivityLog.h"
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include "audio/miniaudio.h"
|
||||||
|
#include "BridgeMain.h"
|
||||||
|
#include "HostBridge.h"
|
||||||
|
|
||||||
|
using namespace network;
|
||||||
|
using namespace lookups;
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Macros
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define IS(s) (::strcmp(argv[i], s) == 0)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Variables
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int g_signal = 0;
|
||||||
|
std::string g_progExe = std::string(__EXE_NAME__);
|
||||||
|
std::string g_iniFile = std::string(DEFAULT_CONF_FILE);
|
||||||
|
std::string g_lockFile = std::string(DEFAULT_LOCK_FILE);
|
||||||
|
|
||||||
|
bool g_foreground = false;
|
||||||
|
bool g_killed = false;
|
||||||
|
bool g_hideMessages = false;
|
||||||
|
|
||||||
|
int g_inputDevice = -1;
|
||||||
|
int g_outputDevice = -1;
|
||||||
|
|
||||||
|
uint8_t* g_gitHashBytes = nullptr;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(CATCH2_TEST_COMPILATION)
|
||||||
|
/* Internal signal handler. */
|
||||||
|
|
||||||
|
static void sigHandler(int signum)
|
||||||
|
{
|
||||||
|
g_signal = signum;
|
||||||
|
g_killed = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Helper to print a fatal error message and exit. */
|
||||||
|
|
||||||
|
void fatal(const char* msg, ...)
|
||||||
|
{
|
||||||
|
char buffer[400U];
|
||||||
|
::memset(buffer, 0x20U, 400U);
|
||||||
|
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, msg);
|
||||||
|
|
||||||
|
::vsprintf(buffer, msg, vl);
|
||||||
|
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
::fprintf(stderr, "%s: %s\n", g_progExe.c_str(), buffer);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to pring usage the command line arguments. (And optionally an error.) */
|
||||||
|
|
||||||
|
void usage(const char* message, const char* arg)
|
||||||
|
{
|
||||||
|
::fprintf(stdout, __PROG_NAME__ " %s (built %s)\r\n", __VER__, __BUILD__);
|
||||||
|
::fprintf(stdout, "Copyright (c) 2017-2024 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\n");
|
||||||
|
::fprintf(stdout, "Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others\n\n");
|
||||||
|
if (message != nullptr) {
|
||||||
|
::fprintf(stderr, "%s: ", g_progExe.c_str());
|
||||||
|
::fprintf(stderr, message, arg);
|
||||||
|
::fprintf(stderr, "\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
::fprintf(stdout,
|
||||||
|
"usage: %s [-vhf]"
|
||||||
|
"[-i <input audio device id>]"
|
||||||
|
"[-o <output audio device id>]"
|
||||||
|
"[-c <configuration file>]"
|
||||||
|
"\n\n"
|
||||||
|
" -v show version information\n"
|
||||||
|
" -h show this screen\n"
|
||||||
|
" -f foreground mode\n"
|
||||||
|
"\n"
|
||||||
|
" -i input audio device\n"
|
||||||
|
" -o output audio device\n"
|
||||||
|
"\n"
|
||||||
|
" -c <file> specifies the configuration file to use\n"
|
||||||
|
"\n"
|
||||||
|
" -- stop handling options\n",
|
||||||
|
g_progExe.c_str());
|
||||||
|
|
||||||
|
ma_context context;
|
||||||
|
if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
|
||||||
|
fprintf(stderr, "Failed to initialize audio context.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_device_info* playbackDevices;
|
||||||
|
ma_device_info* captureDevices;
|
||||||
|
ma_uint32 playbackDeviceCount, captureDeviceCount;
|
||||||
|
ma_result result = ma_context_get_devices(&context, &playbackDevices, &playbackDeviceCount, &captureDevices, &captureDeviceCount);
|
||||||
|
if (result != MA_SUCCESS) {
|
||||||
|
fprintf(stderr, "Failed to retrieve audio device information.\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "\nAudio Input Devices:\n");
|
||||||
|
for (uint32_t i = 0; i < captureDeviceCount; ++i) {
|
||||||
|
fprintf(stdout, " %u: %s\n", i, captureDevices[i].name);
|
||||||
|
}
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
|
||||||
|
fprintf(stdout, "Audio Output Devices:\n");
|
||||||
|
for (uint32_t i = 0; i < playbackDeviceCount; ++i) {
|
||||||
|
fprintf(stdout, " %u: %s\n", i, playbackDevices[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_context_uninit(&context);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to validate the command line arguments. */
|
||||||
|
|
||||||
|
int checkArgs(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
int i, p = 0;
|
||||||
|
|
||||||
|
// iterate through arguments
|
||||||
|
for (i = 1; i <= argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i] == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*argv[i] != '-') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (IS("--")) {
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IS("-f")) {
|
||||||
|
g_foreground = true;
|
||||||
|
}
|
||||||
|
else if (IS("-i")) {
|
||||||
|
if ((argc - 1) <= 0)
|
||||||
|
usage("error: %s", "must specify the input audio device to use");
|
||||||
|
g_inputDevice = ::atoi(argv[++i]);
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
else if (IS("-o")) {
|
||||||
|
if ((argc - 1) <= 0)
|
||||||
|
usage("error: %s", "must specify the output audio device to use");
|
||||||
|
g_outputDevice = ::atoi(argv[++i]);
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
else if (IS("-c")) {
|
||||||
|
if (argc-- <= 0)
|
||||||
|
usage("error: %s", "must specify the configuration file to use");
|
||||||
|
g_iniFile = std::string(argv[++i]);
|
||||||
|
|
||||||
|
if (g_iniFile.empty())
|
||||||
|
usage("error: %s", "configuration file cannot be blank!");
|
||||||
|
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
else if (IS("-v")) {
|
||||||
|
::fprintf(stdout, __PROG_NAME__ " %s (built %s)\r\n", __VER__, __BUILD__);
|
||||||
|
::fprintf(stdout, "Copyright (c) 2017-2024 Bryan Biedenkapp, N2PLL and DVMProject (https://github.com/dvmproject) Authors.\n");
|
||||||
|
::fprintf(stdout, "Portions Copyright (c) 2015-2021 by Jonathan Naylor, G4KLX and others\n\n");
|
||||||
|
if (argc == 2)
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else if (IS("-h")) {
|
||||||
|
usage(nullptr, nullptr);
|
||||||
|
if (argc == 2)
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usage("unrecognized option `%s'", argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p < 0 || p > argc) {
|
||||||
|
p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Program Entry Point
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
#if !defined(CATCH2_TEST_COMPILATION)
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
g_gitHashBytes = new uint8_t[4U];
|
||||||
|
::memset(g_gitHashBytes, 0x00U, 4U);
|
||||||
|
|
||||||
|
uint32_t hash = ::strtoul(__GIT_VER_HASH__, 0, 16);
|
||||||
|
__SET_UINT32(hash, g_gitHashBytes, 0U);
|
||||||
|
|
||||||
|
if (argv[0] != nullptr && *argv[0] != 0)
|
||||||
|
g_progExe = std::string(argv[0]);
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
// check arguments
|
||||||
|
int i = checkArgs(argc, argv);
|
||||||
|
if (i < argc) {
|
||||||
|
argc -= i;
|
||||||
|
argv += i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::signal(SIGINT, sigHandler);
|
||||||
|
::signal(SIGTERM, sigHandler);
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
::signal(SIGHUP, sigHandler);
|
||||||
|
#endif // !defined(_WIN32)
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
g_signal = 0;
|
||||||
|
g_killed = false;
|
||||||
|
|
||||||
|
HostBridge*bridge = new HostBridge(g_iniFile);
|
||||||
|
ret = bridge->run();
|
||||||
|
delete bridge;
|
||||||
|
|
||||||
|
if (g_signal == 2)
|
||||||
|
::LogInfoEx(LOG_HOST, "Exited on receipt of SIGINT");
|
||||||
|
|
||||||
|
if (g_signal == 15)
|
||||||
|
::LogInfoEx(LOG_HOST, "Exited on receipt of SIGTERM");
|
||||||
|
|
||||||
|
if (g_signal == 1)
|
||||||
|
::LogInfoEx(LOG_HOST, "Restarting on receipt of SIGHUP");
|
||||||
|
} while (g_signal == 1);
|
||||||
|
|
||||||
|
::LogFinalise();
|
||||||
|
::ActivityLogFinalise();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file BridgeMain.h
|
||||||
|
* @ingroup bridge
|
||||||
|
* @file BridgeMain.cpp
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
#if !defined(__BRIDGE_MAIN_H__)
|
||||||
|
#define __BRIDGE_MAIN_H__
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Externs
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** @brief */
|
||||||
|
extern int g_signal;
|
||||||
|
/** @brief */
|
||||||
|
extern std::string g_progExe;
|
||||||
|
/** @brief */
|
||||||
|
extern std::string g_iniFile;
|
||||||
|
/** @brief */
|
||||||
|
extern std::string g_lockFile;
|
||||||
|
|
||||||
|
/** @brief (Global) Flag indicating foreground operation. */
|
||||||
|
extern bool g_foreground;
|
||||||
|
/** @brief (Global) Flag indicating the FNE should stop immediately. */
|
||||||
|
extern bool g_killed;
|
||||||
|
|
||||||
|
/** @brief Audio Input Device Index. */
|
||||||
|
extern int g_inputDevice;
|
||||||
|
/** @brief Audio Output Device Index. */
|
||||||
|
extern int g_outputDevice;
|
||||||
|
|
||||||
|
extern uint8_t* g_gitHashBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to trigger a fatal error message. This will cause the program to terminate
|
||||||
|
* immediately with an error message.
|
||||||
|
*
|
||||||
|
* @param msg String format.
|
||||||
|
*
|
||||||
|
* This is a variable argument function.
|
||||||
|
*/
|
||||||
|
extern HOST_SW_API void fatal(const char* msg, ...);
|
||||||
|
|
||||||
|
#endif // __BRIDGE_MAIN_H__
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#/*
|
||||||
|
# * Digital Voice Modem - Bridge
|
||||||
|
# * GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
# *
|
||||||
|
# * Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
# *
|
||||||
|
# */
|
||||||
|
file(GLOB bridge_SRC
|
||||||
|
"src/host/network/Network.h"
|
||||||
|
"src/host/network/Network.cpp"
|
||||||
|
|
||||||
|
"src/bridge/audio/*.h"
|
||||||
|
"src/bridge/audio/*.c"
|
||||||
|
|
||||||
|
"src/bridge/mdc/*.h"
|
||||||
|
"src/bridge/mdc/*.c"
|
||||||
|
|
||||||
|
"src/bridge/network/*.h"
|
||||||
|
"src/bridge/network/*.cpp"
|
||||||
|
"src/bridge/*.h"
|
||||||
|
"src/bridge/*.cpp"
|
||||||
|
)
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @defgroup bridge Bridge
|
||||||
|
* @brief Digital Voice Modem - Bridge
|
||||||
|
* @details Analog audio bridge, this provides facilities to convert analog audio into digital audio.
|
||||||
|
* @ingroup bridge
|
||||||
|
*
|
||||||
|
* @file Defines.h
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
#if !defined(__DEFINES_H__)
|
||||||
|
#define __DEFINES_H__
|
||||||
|
|
||||||
|
#include "common/Defines.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#undef __PROG_NAME__
|
||||||
|
#define __PROG_NAME__ "Digital Voice Modem (DVM) Bridge"
|
||||||
|
#undef __EXE_NAME__
|
||||||
|
#define __EXE_NAME__ "bridge"
|
||||||
|
|
||||||
|
#undef __NETVER__
|
||||||
|
#define __NETVER__ "BRIDGE_R" VERSION_MAJOR VERSION_REV VERSION_MINOR
|
||||||
|
|
||||||
|
#undef DEFAULT_CONF_FILE
|
||||||
|
#define DEFAULT_CONF_FILE "bridge-config.yml"
|
||||||
|
#undef DEFAULT_LOCK_FILE
|
||||||
|
#define DEFAULT_LOCK_FILE "/tmp/dvmbridge.lock"
|
||||||
|
|
||||||
|
#endif // __DEFINES_H__
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,435 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file HostBridge.h
|
||||||
|
* @ingroup bridge
|
||||||
|
* @file HostBridge.cpp
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
#if !defined(__HOST_BRIDGE_H__)
|
||||||
|
#define __HOST_BRIDGE_H__
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
#include "common/dmr/data/EmbeddedData.h"
|
||||||
|
#include "common/dmr/lc/LC.h"
|
||||||
|
#include "common/dmr/lc/PrivacyLC.h"
|
||||||
|
#include "common/network/udp/Socket.h"
|
||||||
|
#include "common/yaml/Yaml.h"
|
||||||
|
#include "common/RingBuffer.h"
|
||||||
|
#include "common/Timer.h"
|
||||||
|
#include "vocoder/MBEDecoder.h"
|
||||||
|
#include "vocoder/MBEEncoder.h"
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include "audio/miniaudio.h"
|
||||||
|
#include "mdc/mdc_decode.h"
|
||||||
|
#include "network/PeerNetwork.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define MBE_SAMPLES_LENGTH 160
|
||||||
|
#define NO_BIT_STEAL 0
|
||||||
|
|
||||||
|
#define ECMODE_NOISE_SUPPRESS 0x40
|
||||||
|
#define ECMODE_AGC 0x2000
|
||||||
|
|
||||||
|
#define DECSTATE_SIZE 2048
|
||||||
|
#define ENCSTATE_SIZE 6144
|
||||||
|
|
||||||
|
const uint8_t FULL_RATE_MODE = 0x00U;
|
||||||
|
const uint8_t HALF_RATE_MODE = 0x01U;
|
||||||
|
|
||||||
|
const uint8_t TX_MODE_DMR = 1U;
|
||||||
|
const uint8_t TX_MODE_P25 = 2U;
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper callback, called when audio data is available.
|
||||||
|
* @param device
|
||||||
|
* @param output
|
||||||
|
* @param input
|
||||||
|
* @param frameCount
|
||||||
|
*/
|
||||||
|
void audioCallback(ma_device* device, void* output, const void* input, ma_uint32 frameCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper callback, called when MDC packets are detected.
|
||||||
|
* @param frameCount
|
||||||
|
* @param op MDC Opcode.
|
||||||
|
* @param arg MDC Argument.
|
||||||
|
* @param unitID Unit ID.
|
||||||
|
* @param extra0 1st extra byte.
|
||||||
|
* @param extra1 2nd extra byte.
|
||||||
|
* @param extra2 3rd extra byte.
|
||||||
|
* @param extra3 4th extra byte.
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
void mdcPacketDetected(int frameCount, mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID,
|
||||||
|
mdc_u8_t extra0, mdc_u8_t extra1, mdc_u8_t extra2, mdc_u8_t extra3, void* context);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class implements the core service logic.
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
class HOST_SW_API HostBridge {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the HostBridge class.
|
||||||
|
* @param confFile Full-path to the configuration file.
|
||||||
|
*/
|
||||||
|
HostBridge(const std::string& confFile);
|
||||||
|
/**
|
||||||
|
* @brief Finalizes a instance of the HostBridge class.
|
||||||
|
*/
|
||||||
|
~HostBridge();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Executes the main host processing loop.
|
||||||
|
* @returns int Zero if successful, otherwise error occurred.
|
||||||
|
*/
|
||||||
|
int run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend void ::audioCallback(ma_device* device, void* output, const void* input, ma_uint32 frameCount);
|
||||||
|
friend void ::mdcPacketDetected(int frameCount, mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID,
|
||||||
|
mdc_u8_t extra0, mdc_u8_t extra1, mdc_u8_t extra2, mdc_u8_t extra3, void* context);
|
||||||
|
|
||||||
|
const std::string& m_confFile;
|
||||||
|
yaml::Node m_conf;
|
||||||
|
|
||||||
|
network::PeerNetwork* m_network;
|
||||||
|
network::udp::Socket* m_udpAudioSocket;
|
||||||
|
|
||||||
|
bool m_udpAudio;
|
||||||
|
bool m_udpMetadata;
|
||||||
|
uint16_t m_udpSendPort;
|
||||||
|
std::string m_udpSendAddress;
|
||||||
|
uint16_t m_udpReceivePort;
|
||||||
|
std::string m_udpReceiveAddress;
|
||||||
|
|
||||||
|
uint32_t m_srcId;
|
||||||
|
uint32_t m_srcIdOverride;
|
||||||
|
bool m_overrideSrcIdFromMDC;
|
||||||
|
bool m_overrideSrcIdFromUDP;
|
||||||
|
uint32_t m_dstId;
|
||||||
|
uint8_t m_slot;
|
||||||
|
|
||||||
|
std::string m_identity;
|
||||||
|
float m_rxAudioGain;
|
||||||
|
float m_vocoderDecoderAudioGain;
|
||||||
|
bool m_vocoderDecoderAutoGain;
|
||||||
|
float m_txAudioGain;
|
||||||
|
float m_vocoderEncoderAudioGain;
|
||||||
|
|
||||||
|
uint8_t m_txMode;
|
||||||
|
|
||||||
|
float m_voxSampleLevel;
|
||||||
|
uint16_t m_dropTimeMS;
|
||||||
|
Timer m_dropTime;
|
||||||
|
|
||||||
|
bool m_detectAnalogMDC1200;
|
||||||
|
|
||||||
|
bool m_preambleLeaderTone;
|
||||||
|
uint16_t m_preambleTone;
|
||||||
|
uint16_t m_preambleLength;
|
||||||
|
|
||||||
|
bool m_grantDemand;
|
||||||
|
|
||||||
|
bool m_localAudio;
|
||||||
|
|
||||||
|
ma_context m_maContext;
|
||||||
|
ma_device_info* m_maPlaybackDevices;
|
||||||
|
ma_device_info* m_maCaptureDevices;
|
||||||
|
ma_device_config m_maDeviceConfig;
|
||||||
|
ma_device m_maDevice;
|
||||||
|
|
||||||
|
ma_waveform m_maSineWaveform;
|
||||||
|
ma_waveform_config m_maSineWaveConfig;
|
||||||
|
|
||||||
|
RingBuffer<short> m_inputAudio;
|
||||||
|
RingBuffer<short> m_outputAudio;
|
||||||
|
|
||||||
|
vocoder::MBEDecoder* m_decoder;
|
||||||
|
vocoder::MBEEncoder* m_encoder;
|
||||||
|
|
||||||
|
mdc_decoder_t* m_mdcDecoder;
|
||||||
|
|
||||||
|
dmr::data::EmbeddedData m_dmrEmbeddedData;
|
||||||
|
dmr::lc::LC m_rxDMRLC;
|
||||||
|
dmr::lc::PrivacyLC m_rxDMRPILC;
|
||||||
|
uint8_t* m_ambeBuffer;
|
||||||
|
uint32_t m_ambeCount;
|
||||||
|
uint32_t m_dmrSeqNo;
|
||||||
|
uint8_t m_dmrN;
|
||||||
|
|
||||||
|
p25::lc::LC m_rxP25LC;
|
||||||
|
uint8_t* m_netLDU1;
|
||||||
|
uint8_t* m_netLDU2;
|
||||||
|
uint32_t m_p25SeqNo;
|
||||||
|
uint8_t m_p25N;
|
||||||
|
|
||||||
|
bool m_audioDetect;
|
||||||
|
bool m_trafficFromUDP;
|
||||||
|
uint32_t m_udpSrcId;
|
||||||
|
uint32_t m_udpDstId;
|
||||||
|
bool m_callInProgress;
|
||||||
|
bool m_ignoreCall;
|
||||||
|
uint8_t m_callAlgoId;
|
||||||
|
uint64_t m_rxStartTime;
|
||||||
|
uint32_t m_rxStreamId;
|
||||||
|
uint32_t m_txStreamId;
|
||||||
|
|
||||||
|
uint8_t m_detectedSampleCnt;
|
||||||
|
bool m_dumpSampleLevel;
|
||||||
|
|
||||||
|
bool m_running;
|
||||||
|
bool m_debug;
|
||||||
|
|
||||||
|
static std::mutex m_audioMutex;
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
void* m_decoderState;
|
||||||
|
uint16_t m_dcMode;
|
||||||
|
void* m_encoderState;
|
||||||
|
uint16_t m_ecMode;
|
||||||
|
|
||||||
|
HINSTANCE m_ambeDLL;
|
||||||
|
bool m_useExternalVocoder;
|
||||||
|
|
||||||
|
int m_frameLengthInBits;
|
||||||
|
int m_frameLengthInBytes;
|
||||||
|
|
||||||
|
typedef void(__cdecl* Tambe_init_dec)(void* state, short mode);
|
||||||
|
/**
|
||||||
|
* @brief Initialize the AMBE decoder.
|
||||||
|
* @param[out] state Buffer containing the decoder state to initialize.
|
||||||
|
* @param mode AMBE mode; FULL (0) or HALF (1).
|
||||||
|
*/
|
||||||
|
Tambe_init_dec ambe_init_dec;
|
||||||
|
|
||||||
|
typedef short(__cdecl* Tambe_get_dec_mode)(void* state);
|
||||||
|
/**
|
||||||
|
* @brief Get the current operating state of the AMBE decoder.
|
||||||
|
* @param[out] state Buffer containing the decoder state.
|
||||||
|
* @returns short Operational mode.
|
||||||
|
*/
|
||||||
|
Tambe_get_dec_mode ambe_get_dec_mode;
|
||||||
|
|
||||||
|
typedef uint32_t(__cdecl* Tambe_voice_dec)(short* samples, short sampleLength, short* packedCodeword, short bitSteal, uint16_t cmode, short n, void* state);
|
||||||
|
/**
|
||||||
|
* @brief Decode AMBE codeword into PCM samples.
|
||||||
|
* @param[out] samples Audio Output (in short samples)
|
||||||
|
* @param[in] sampleLength Length of sample buffer.
|
||||||
|
* @param[in] packedCodeword AMBE codewords.
|
||||||
|
* @param[in] bitSteal
|
||||||
|
* @param[in] cmode
|
||||||
|
* @param[in] n
|
||||||
|
* @param[in] state Buffer containing the decoder state.
|
||||||
|
* @returns uint32_t
|
||||||
|
*/
|
||||||
|
Tambe_voice_dec ambe_voice_dec;
|
||||||
|
|
||||||
|
typedef void(__cdecl* Tambe_init_enc)(void* state, short mode, short initialize);
|
||||||
|
/**
|
||||||
|
* @brief Initialize the AMBE decoder.
|
||||||
|
* @param[out] state Buffer containing the ebncoder state to initialize.
|
||||||
|
* @param mode AMBE mode; FULL (0) or HALF (1).
|
||||||
|
* @param initialize Flag to initialize encoder state fully, 1 to initialize, 0 to not.
|
||||||
|
*/
|
||||||
|
Tambe_init_enc ambe_init_enc;
|
||||||
|
|
||||||
|
typedef short(__cdecl* Tambe_get_enc_mode)(void* state);
|
||||||
|
/**
|
||||||
|
* @brief Get the current operating state of the AMBE encoder.
|
||||||
|
* @param[out] state Buffer containing the decoder state.
|
||||||
|
* @returns short Operational mode.
|
||||||
|
*/
|
||||||
|
Tambe_get_enc_mode ambe_get_enc_mode;
|
||||||
|
|
||||||
|
typedef uint32_t(__cdecl* Tambe_voice_enc)(short* packedCodeword, short bitSteal, short* samples, short sampleLength, uint16_t cmode, short n, short, void* state);
|
||||||
|
/**
|
||||||
|
* @brief Decode AMBE codeword into PCM samples.
|
||||||
|
* @param[out] packedCodeword AMBE codewords.
|
||||||
|
* @param[in] bitSteal
|
||||||
|
* @param[in] samples Audio Output (in short samples)
|
||||||
|
* @param[in] sampleLength Length of sample buffer.
|
||||||
|
* @param[in] cmode
|
||||||
|
* @param[in] n
|
||||||
|
* @param[in]
|
||||||
|
* @param[in] state Buffer containing the decoder state.
|
||||||
|
* @returns uint32_t
|
||||||
|
*/
|
||||||
|
Tambe_voice_enc ambe_voice_enc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to initialize the use of the external AMBE.DLL binary for DVSI USB-3000.
|
||||||
|
*/
|
||||||
|
void initializeAMBEDLL();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to unpack the codeword bytes into codeword bits for use with the AMBE decoder.
|
||||||
|
* @param[out] codewordBits Codeword bits.
|
||||||
|
* @param[in] codeword Codeword bytes.
|
||||||
|
* @param lengthInBytes Length of codeword in bytes.
|
||||||
|
* @param lengthBits Length of codeword in bits.
|
||||||
|
*/
|
||||||
|
void unpackBytesToBits(short* codewordBits, const uint8_t* codeword, int lengthBytes, int lengthBits);
|
||||||
|
/**
|
||||||
|
* @brief Helper to unpack the codeword bytes into codeword bits for use with the AMBE decoder.
|
||||||
|
* @param[out] codewordBits Codeword bits.
|
||||||
|
* @param[in] codeword Codeword bytes.
|
||||||
|
* @param lengthInBytes Length of codeword in bytes.
|
||||||
|
* @param lengthBits Length of codeword in bits.
|
||||||
|
*/
|
||||||
|
void unpackBytesToBits(uint8_t* codewordBits, const uint8_t* codeword, int lengthBytes, int lengthBits);
|
||||||
|
/**
|
||||||
|
* @brief Decodes the given MBE codewords to PCM samples using the decoder mode.
|
||||||
|
* @param[in] codeword
|
||||||
|
* @param codewordLength
|
||||||
|
* @param[out] samples
|
||||||
|
* @returns int
|
||||||
|
*/
|
||||||
|
int ambeDecode(const uint8_t* codeword, uint32_t codewordLength, short* samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to pack the codeword bits into codeword bytes for use with the AMBE encoder.
|
||||||
|
* @param[in] codewordBits Codeword bits.
|
||||||
|
* @param[out] codeword Codeword bytes.
|
||||||
|
* @param lengthInBytes Length of codeword in bytes.
|
||||||
|
* @param lengthBits Length of codeword in bits.
|
||||||
|
*/
|
||||||
|
void packBitsToBytes(const short* codewordBits, uint8_t* codeword, int lengthBytes, int lengthBits);
|
||||||
|
/**
|
||||||
|
* @brief Helper to pack the codeword bits into codeword bytes for use with the AMBE encoder.
|
||||||
|
* @param[in] codewordBits Codeword bits.
|
||||||
|
* @param[out] codeword Codeword bytes.
|
||||||
|
* @param lengthInBytes Length of codeword in bytes.
|
||||||
|
* @param lengthBits Length of codeword in bits.
|
||||||
|
*/
|
||||||
|
void packBitsToBytes(const uint8_t* codewordBits, uint8_t* codeword, int lengthBytes, int lengthBits);
|
||||||
|
/**
|
||||||
|
* @brief Encodes the given PCM samples using the encoder mode to MBE codewords.
|
||||||
|
* @param[in] samples
|
||||||
|
* @param sampleLength
|
||||||
|
* @param[out] codeword
|
||||||
|
* @returns int
|
||||||
|
*/
|
||||||
|
void ambeEncode(const short* samples, uint32_t sampleLength, uint8_t* codeword);
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads basic configuration parameters from the INI.
|
||||||
|
* @returns bool True, if configuration was read successfully, otherwise false.
|
||||||
|
*/
|
||||||
|
bool readParams();
|
||||||
|
/**
|
||||||
|
* @brief Initializes network connectivity.
|
||||||
|
* @returns bool True, if network connectivity was initialized, otherwise false.
|
||||||
|
*/
|
||||||
|
bool createNetwork();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to process UDP audio.
|
||||||
|
*/
|
||||||
|
void processUDPAudio();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to process DMR network traffic.
|
||||||
|
* @param buffer
|
||||||
|
* @param length
|
||||||
|
*/
|
||||||
|
void processDMRNetwork(uint8_t* buffer, uint32_t length);
|
||||||
|
/**
|
||||||
|
* @brief Helper to decode DMR network traffic audio frames.
|
||||||
|
* @param ambe
|
||||||
|
* @param srcId
|
||||||
|
* @param dstId
|
||||||
|
* @param dmrN
|
||||||
|
*/
|
||||||
|
void decodeDMRAudioFrame(uint8_t* ambe, uint32_t srcId, uint32_t dstId, uint8_t dmrN);
|
||||||
|
/**
|
||||||
|
* @brief Helper to encode DMR network traffic audio frames.
|
||||||
|
* @param pcm
|
||||||
|
* @param forcedSrcId
|
||||||
|
* @param forcedDstId
|
||||||
|
*/
|
||||||
|
void encodeDMRAudioFrame(uint8_t* pcm, uint32_t forcedSrcId = 0U, uint32_t forcedDstId = 0U);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to process P25 network traffic.
|
||||||
|
* @param buffer
|
||||||
|
* @param length
|
||||||
|
*/
|
||||||
|
void processP25Network(uint8_t* buffer, uint32_t length);
|
||||||
|
/**
|
||||||
|
* @brief Helper to decode P25 network traffic audio frames.
|
||||||
|
* @param ldu
|
||||||
|
* @param srcId
|
||||||
|
* @param dstId
|
||||||
|
* @param p25N
|
||||||
|
*/
|
||||||
|
void decodeP25AudioFrame(uint8_t* ldu, uint32_t srcId, uint32_t dstId, uint8_t p25N);
|
||||||
|
/**
|
||||||
|
* @brief Helper to encode P25 network traffic audio frames.
|
||||||
|
* @param pcm
|
||||||
|
* @param forcedSrcId
|
||||||
|
* @param forcedDstId
|
||||||
|
*/
|
||||||
|
void encodeP25AudioFrame(uint8_t* pcm, uint32_t forcedSrcId = 0U, uint32_t forcedDstId = 0U);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to generate the preamble tone.
|
||||||
|
*/
|
||||||
|
void generatePreambleTone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Entry point to audio processing thread.
|
||||||
|
* @param arg Instance of the thread_t structure.
|
||||||
|
* @returns void* (Ignore)
|
||||||
|
*/
|
||||||
|
static void* threadAudioProcess(void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Entry point to network processing thread.
|
||||||
|
* @param arg Instance of the thread_t structure.
|
||||||
|
* @returns void* (Ignore)
|
||||||
|
*/
|
||||||
|
static void* threadNetworkProcess(void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Entry point to call lockup handler thread.
|
||||||
|
* @param arg Instance of the thread_t structure.
|
||||||
|
* @returns void* (Ignore)
|
||||||
|
*/
|
||||||
|
static void* threadCallLockup(void* arg);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __HOST_BRIDGE_H__
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file SampleTimeConversion.h
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
#if !defined(__SAMPLE_TIME_CONVERSION_H__)
|
||||||
|
#define __SAMPLE_TIME_CONVERSION_H__
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
class HOST_SW_API SampleTimeConvert {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief (ms) to sample count conversion
|
||||||
|
* @param sampleRate Sample rate.
|
||||||
|
* @param channels Number of audio channels.
|
||||||
|
* @param ms Number of milliseconds.
|
||||||
|
* @returns int Number of samples.
|
||||||
|
*/
|
||||||
|
static int ToSamples(uint32_t sampleRate, uint8_t channels, int ms)
|
||||||
|
{
|
||||||
|
return (int)(((long)ms) * sampleRate * channels / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sample count to (ms) conversion
|
||||||
|
* @param sampleRate Sample rate.
|
||||||
|
* @param channels Number of audio channels.
|
||||||
|
* @param samples Number of samples.
|
||||||
|
* @returns int Number of milliseconds.
|
||||||
|
*/
|
||||||
|
static int ToMS(uint32_t sampleRate, uint8_t channels, int samples)
|
||||||
|
{
|
||||||
|
return (int)(((float)samples / (float)sampleRate / (float)channels) * 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __SAMPLE_TIME_CONVERSION_H__
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,88 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_common.c
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
#include "mdc/mdc_types.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
mdc_u16_t _flip(mdc_u16_t crc, mdc_int_t bitnum)
|
||||||
|
{
|
||||||
|
mdc_u16_t crcout, j;
|
||||||
|
|
||||||
|
j = 1;
|
||||||
|
crcout = 0;
|
||||||
|
|
||||||
|
for (mdc_u16_t i = 1 << (bitnum - 1); i; i >>= 1) {
|
||||||
|
if (crc & i)
|
||||||
|
crcout |= j;
|
||||||
|
j <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crcout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
mdc_u16_t _docrc(mdc_u8_t *p, int len)
|
||||||
|
{
|
||||||
|
mdc_int_t bit;
|
||||||
|
mdc_u16_t crc = 0x0000;
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < len; i++) {
|
||||||
|
mdc_u16_t c = (mdc_u16_t)*p++;
|
||||||
|
c = _flip(c, 8);
|
||||||
|
|
||||||
|
for (mdc_int_t j = 0x80; j; j >>= 1) {
|
||||||
|
bit = crc & 0x8000;
|
||||||
|
crc <<= 1;
|
||||||
|
if (c & j)
|
||||||
|
bit ^= 0x8000;
|
||||||
|
if (bit)
|
||||||
|
crc ^= 0x1021;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = _flip(crc, 16);
|
||||||
|
crc ^= 0xffff;
|
||||||
|
crc &= 0xFFFF;
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
@ -0,0 +1,507 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_decode.c
|
||||||
|
* Decodes a specific format of 1200 BPS XOR-precoded MSK data burst
|
||||||
|
* from input audio samples.
|
||||||
|
*
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "mdc_decode.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Create a new mdc_decoder object. */
|
||||||
|
|
||||||
|
mdc_decoder_t* mdc_decoder_new(int sampleRate)
|
||||||
|
{
|
||||||
|
mdc_decoder_t* decoder;
|
||||||
|
|
||||||
|
decoder = (mdc_decoder_t*)malloc(sizeof(mdc_decoder_t));
|
||||||
|
if(!decoder)
|
||||||
|
return (mdc_decoder_t*)0L;
|
||||||
|
|
||||||
|
if (sampleRate == 8000) {
|
||||||
|
decoder->incru = 644245094;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 16000) {
|
||||||
|
decoder->incru = 322122547;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 22050) {
|
||||||
|
decoder->incru = 233739716;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 32000) {
|
||||||
|
decoder->incru = 161061274;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 44100) {
|
||||||
|
decoder->incru = 116869858;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 48000) {
|
||||||
|
decoder->incru = 107374182;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// WARNING: lower precision than above
|
||||||
|
decoder->incru = 1200 * 2 * (0x80000000 / sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder->good = 0;
|
||||||
|
decoder->indouble = 0;
|
||||||
|
decoder->level = 0;
|
||||||
|
|
||||||
|
for(mdc_int_t i = 0; i < MDC_ND; i++)
|
||||||
|
{
|
||||||
|
decoder->du[i].thu = i * 2 * (0x80000000 / MDC_ND);
|
||||||
|
decoder->du[i].xorb = 0;
|
||||||
|
decoder->du[i].invert = 0;
|
||||||
|
decoder->du[i].shstate = -1;
|
||||||
|
decoder->du[i].shcount = 0;
|
||||||
|
#ifdef MDC_FOURPOINT
|
||||||
|
decoder->du[i].nlstep = i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder->callback = (mdc_decoder_callback_t)0L;
|
||||||
|
|
||||||
|
return decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static void _clearbits(mdc_decoder_t* decoder, mdc_int_t x)
|
||||||
|
{
|
||||||
|
for (mdc_int_t i = 0; i < 112; i++)
|
||||||
|
decoder->du[x].bits[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MDC_ECC
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static void _gofix(mdc_u8_t *data)
|
||||||
|
{
|
||||||
|
int csr[7];
|
||||||
|
int fixi, fixj;
|
||||||
|
|
||||||
|
int syn = 0;
|
||||||
|
for(int i = 0; i < 7; i++)
|
||||||
|
csr[i] = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j <= 7; j++)
|
||||||
|
{
|
||||||
|
for (int k = 6; k > 0; k--)
|
||||||
|
csr[k] = csr[k-1];
|
||||||
|
|
||||||
|
csr[0] = (data[i] >> j) & 0x01;
|
||||||
|
int b = csr[0] + csr[2] + csr[5] + csr[6];
|
||||||
|
syn <<= 1;
|
||||||
|
if ((b & 0x01) ^ ((data[i+7] >> j) & 0x01)) {
|
||||||
|
syn |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ec = 0;
|
||||||
|
if (syn & 0x80) ++ec;
|
||||||
|
if (syn & 0x20) ++ec;
|
||||||
|
if (syn & 0x04) ++ec;
|
||||||
|
if (syn & 0x02) ++ec;
|
||||||
|
if (ec >= 3) {
|
||||||
|
syn ^= 0xa6;
|
||||||
|
fixi = i;
|
||||||
|
fixj = j-7;
|
||||||
|
if(fixj < 0) {
|
||||||
|
--fixi;
|
||||||
|
fixj += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixi >= 0)
|
||||||
|
data[fixi] ^= 1 << fixj; // flip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static void _procbits(mdc_decoder_t* decoder, int x)
|
||||||
|
{
|
||||||
|
mdc_int_t lbits[112];
|
||||||
|
mdc_int_t lbc = 0;
|
||||||
|
mdc_u8_t data[14];
|
||||||
|
mdc_u16_t ccrc;
|
||||||
|
mdc_u16_t rcrc;
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < 16; i++) {
|
||||||
|
for (mdc_int_t j = 0; j < 7; j++) {
|
||||||
|
mdc_int_t k = (j * 16) + i;
|
||||||
|
lbits[lbc] = decoder->du[x].bits[k];
|
||||||
|
++lbc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < 14; i++) {
|
||||||
|
data[i] = 0;
|
||||||
|
for (mdc_int_t j = 0; j < 8; j++) {
|
||||||
|
mdc_int_t k = (i * 8) + j;
|
||||||
|
|
||||||
|
if (lbits[k])
|
||||||
|
data[i] |= 1<<j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MDC_ECC
|
||||||
|
_gofix(data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ccrc = _docrc(data, 4);
|
||||||
|
rcrc = data[5] << 8 | data[4];
|
||||||
|
|
||||||
|
if (ccrc == rcrc) {
|
||||||
|
if (decoder->du[x].shstate == 2) {
|
||||||
|
decoder->extra0 = data[0];
|
||||||
|
decoder->extra1 = data[1];
|
||||||
|
decoder->extra2 = data[2];
|
||||||
|
decoder->extra3 = data[3];
|
||||||
|
|
||||||
|
for(mdc_int_t k = 0; k < MDC_ND; k++)
|
||||||
|
decoder->du[k].shstate = -1;
|
||||||
|
|
||||||
|
decoder->good = 2;
|
||||||
|
decoder->indouble = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!decoder->indouble) {
|
||||||
|
decoder->good = 1;
|
||||||
|
decoder->op = data[0];
|
||||||
|
decoder->arg = data[1];
|
||||||
|
decoder->unitID = (data[2] << 8) | data[3];
|
||||||
|
|
||||||
|
switch (data[0])
|
||||||
|
{
|
||||||
|
/* list of opcode that mean 'double packet' */
|
||||||
|
case OP_DOUBLE_PACKET_TYPE1:
|
||||||
|
case OP_DOUBLE_PACKET_TYPE2:
|
||||||
|
decoder->good = 0;
|
||||||
|
decoder->indouble = 1;
|
||||||
|
decoder->du[x].shstate = 2;
|
||||||
|
decoder->du[x].shcount = 0;
|
||||||
|
_clearbits(decoder, x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
for (mdc_int_t k = 0; k < MDC_ND; k++)
|
||||||
|
decoder->du[k].shstate = -1; // only in the single-packet case, double keeps rest going
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// any subsequent good decoder allowed to attempt second half
|
||||||
|
decoder->du[x].shstate = 2;
|
||||||
|
decoder->du[x].shcount = 0;
|
||||||
|
_clearbits(decoder, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
decoder->du[x].shstate = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoder->good) {
|
||||||
|
if (decoder->callback) {
|
||||||
|
(decoder->callback)((int)decoder->good, (mdc_u8_t)decoder->op, (mdc_u8_t)decoder->arg, (mdc_u16_t)decoder->unitID,
|
||||||
|
(mdc_u8_t)decoder->extra0, (mdc_u8_t)decoder->extra1, (mdc_u8_t)decoder->extra2, (mdc_u8_t)decoder->extra3,
|
||||||
|
decoder->callback_context);
|
||||||
|
decoder->good = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static int _onebits(mdc_u32_t n)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while(n) {
|
||||||
|
++i;
|
||||||
|
n &= (n-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static void _shiftin(mdc_decoder_t* decoder, int x)
|
||||||
|
{
|
||||||
|
int bit = decoder->du[x].xorb;
|
||||||
|
int gcount;
|
||||||
|
|
||||||
|
switch (decoder->du[x].shstate)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
decoder->du[x].synchigh = 0;
|
||||||
|
decoder->du[x].synclow = 0;
|
||||||
|
decoder->du[x].shstate = 0;
|
||||||
|
// deliberately fall through
|
||||||
|
case 0:
|
||||||
|
decoder->du[x].synchigh <<= 1;
|
||||||
|
if (decoder->du[x].synclow & 0x80000000)
|
||||||
|
decoder->du[x].synchigh |= 1;
|
||||||
|
decoder->du[x].synclow <<= 1;
|
||||||
|
if (bit)
|
||||||
|
decoder->du[x].synclow |= 1;
|
||||||
|
|
||||||
|
gcount = _onebits(0x000000ff & (0x00000007 ^ decoder->du[x].synchigh));
|
||||||
|
gcount += _onebits(0x092a446f ^ decoder->du[x].synclow);
|
||||||
|
|
||||||
|
if (gcount <= MDC_GDTHRESH) {
|
||||||
|
decoder->du[x].shstate = 1;
|
||||||
|
decoder->du[x].shcount = 0;
|
||||||
|
_clearbits(decoder, x);
|
||||||
|
}
|
||||||
|
else if (gcount >= (40 - MDC_GDTHRESH)) {
|
||||||
|
decoder->du[x].shstate = 1;
|
||||||
|
decoder->du[x].shcount = 0;
|
||||||
|
decoder->du[x].xorb = !(decoder->du[x].xorb);
|
||||||
|
decoder->du[x].invert = !(decoder->du[x].invert);
|
||||||
|
_clearbits(decoder, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
decoder->du[x].bits[decoder->du[x].shcount] = bit;
|
||||||
|
decoder->du[x].shcount++;
|
||||||
|
if (decoder->du[x].shcount > 111) {
|
||||||
|
_procbits(decoder, x);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MDC_FOURPOINT
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static void _nlproc(mdc_decoder_t* decoder, int x)
|
||||||
|
{
|
||||||
|
mdc_float_t vnow;
|
||||||
|
mdc_float_t vpast;
|
||||||
|
|
||||||
|
switch (decoder->du[x].nlstep)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
vnow = ((-0.60 * decoder->du[x].nlevel[3]) + (.97 * decoder->du[x].nlevel[1]));
|
||||||
|
vpast = ((-0.60 * decoder->du[x].nlevel[7]) + (.97 * decoder->du[x].nlevel[9]));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
vnow = ((-0.60 * decoder->du[x].nlevel[8]) + (.97 * decoder->du[x].nlevel[6]));
|
||||||
|
vpast = ((-0.60 * decoder->du[x].nlevel[2]) + (.97 * decoder->du[x].nlevel[4]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder->du[x].xorb = (vnow > vpast) ? 1 : 0;
|
||||||
|
if (decoder->du[x].invert)
|
||||||
|
decoder->du[x].xorb = !(decoder->du[x].xorb);
|
||||||
|
_shiftin(decoder, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Process incoming samples using an mdc_decoder object. */
|
||||||
|
|
||||||
|
int mdc_decoder_process_samples(mdc_decoder_t* decoder, mdc_sample_t* samples, int numSamples)
|
||||||
|
{
|
||||||
|
mdc_sample_t sample;
|
||||||
|
#ifndef MDC_FIXEDMATH
|
||||||
|
mdc_float_t value;
|
||||||
|
#else
|
||||||
|
mdc_int_t value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!decoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < numSamples; i++) {
|
||||||
|
sample = samples[i];
|
||||||
|
|
||||||
|
#ifdef MDC_FIXEDMATH
|
||||||
|
#if defined(MDC_SAMPLE_FORMAT_U8)
|
||||||
|
value = ((mdc_int_t)sample) - 127;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_U16)
|
||||||
|
value = ((mdc_int_t)sample) - 32767;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_S16)
|
||||||
|
value = (mdc_int_t) sample;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_FLOAT)
|
||||||
|
#error "fixed-point math not allowed with float sample format"
|
||||||
|
#else
|
||||||
|
#error "no known sample format set"
|
||||||
|
#endif // sample format
|
||||||
|
#endif // is MDC_FIXEDMATH
|
||||||
|
|
||||||
|
#ifndef MDC_FIXEDMATH
|
||||||
|
#if defined(MDC_SAMPLE_FORMAT_U8)
|
||||||
|
value = (((mdc_float_t)sample) - 128.0)/256;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_U16)
|
||||||
|
value = (((mdc_float_t)sample) - 32768.0)/65536.0;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_S16)
|
||||||
|
value = ((mdc_float_t)sample) / 65536.0;
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_FLOAT)
|
||||||
|
value = sample;
|
||||||
|
#else
|
||||||
|
#error "no known sample format set"
|
||||||
|
#endif // sample format
|
||||||
|
#endif // not MDC_FIXEDMATH
|
||||||
|
|
||||||
|
#if defined(MDC_ONEPOINT)
|
||||||
|
for (mdc_int_t j = 0; j < MDC_ND; j++) {
|
||||||
|
mdc_u32_t lthu = decoder->du[j].thu;
|
||||||
|
decoder->du[j].thu += decoder->incru;
|
||||||
|
|
||||||
|
// wrapped
|
||||||
|
if (decoder->du[j].thu < lthu) {
|
||||||
|
if (value > 0)
|
||||||
|
decoder->du[j].xorb = 1;
|
||||||
|
else
|
||||||
|
decoder->du[j].xorb = 0;
|
||||||
|
if (decoder->du[j].invert)
|
||||||
|
decoder->du[j].xorb = !(decoder->du[j].xorb);
|
||||||
|
_shiftin(decoder, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(MDC_FOURPOINT)
|
||||||
|
#ifdef MDC_FIXEDMATH
|
||||||
|
#error "fixed-point math not allowed for fourpoint strategy"
|
||||||
|
#endif
|
||||||
|
for (mdc_int_t j = 0; j < MDC_ND; j++)
|
||||||
|
{
|
||||||
|
//decoder->du[j].th += (5.0 * decoder->incr);
|
||||||
|
mdc_u32_t lthu = decoder->du[j].thu;
|
||||||
|
decoder->du[j].thu += 5 * decoder->incru;
|
||||||
|
// if (decoder->du[j].th >= TWOPI)
|
||||||
|
// wrapped
|
||||||
|
if (decoder->du[j].thu < lthu) {
|
||||||
|
decoder->du[j].nlstep++;
|
||||||
|
if(decoder->du[j].nlstep > 9)
|
||||||
|
decoder->du[j].nlstep = 0;
|
||||||
|
decoder->du[j].nlevel[decoder->du[j].nlstep] = value;
|
||||||
|
|
||||||
|
_nlproc(decoder, j);
|
||||||
|
|
||||||
|
//decoder->du[j].th -= TWOPI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "no decode strategy chosen"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoder->good)
|
||||||
|
return decoder->good;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve last successfully decoded data packet from decoder object. */
|
||||||
|
|
||||||
|
int mdc_decoder_get_packet(mdc_decoder_t* decoder, mdc_u8_t* op, mdc_u8_t* arg, mdc_u16_t* unitID)
|
||||||
|
{
|
||||||
|
if (!decoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (decoder->good != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (op)
|
||||||
|
*op = decoder->op;
|
||||||
|
if (arg)
|
||||||
|
*arg = decoder->arg;
|
||||||
|
if (unitID)
|
||||||
|
*unitID = decoder->unitID;
|
||||||
|
|
||||||
|
decoder->good = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve last successfully decoded double-length packet from decoder object. */
|
||||||
|
|
||||||
|
int mdc_decoder_get_double_packet(mdc_decoder_t* decoder, mdc_u8_t* op, mdc_u8_t* arg, mdc_u16_t* unitID,
|
||||||
|
mdc_u8_t* extra0, mdc_u8_t* extra1, mdc_u8_t* extra2, mdc_u8_t* extra3)
|
||||||
|
{
|
||||||
|
if (!decoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (decoder->good != 2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (op)
|
||||||
|
*op = decoder->op;
|
||||||
|
if (arg)
|
||||||
|
*arg = decoder->arg;
|
||||||
|
if (unitID)
|
||||||
|
*unitID = decoder->unitID;
|
||||||
|
|
||||||
|
if (extra0)
|
||||||
|
*extra0 = decoder->extra0;
|
||||||
|
if (extra1)
|
||||||
|
*extra1 = decoder->extra1;
|
||||||
|
if (extra2)
|
||||||
|
*extra2 = decoder->extra2;
|
||||||
|
if (extra3)
|
||||||
|
*extra3 = decoder->extra3;
|
||||||
|
|
||||||
|
decoder->good = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a callback function to be called upon successful decode. */
|
||||||
|
|
||||||
|
int mdc_decoder_set_callback(mdc_decoder_t* decoder, mdc_decoder_callback_t callbackFunction, void* context)
|
||||||
|
{
|
||||||
|
if (!decoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
decoder->callback = callbackFunction;
|
||||||
|
decoder->callback_context = context;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,203 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file mdc_decode.h
|
||||||
|
* @ingroup bridge
|
||||||
|
* @file mdc_decode.c
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_decode.h
|
||||||
|
* header for mdc_decode.c
|
||||||
|
*
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
#if !defined(__MDC_DECODE_H__)
|
||||||
|
#define __MDC_DECODE_H__
|
||||||
|
|
||||||
|
// #define MDC_FIXEDMATH // if you want this, define before mdc_types.h
|
||||||
|
|
||||||
|
#include "mdc_types.h"
|
||||||
|
|
||||||
|
#define MDC_GDTHRESH 5 // "good bits" threshold
|
||||||
|
|
||||||
|
#define MDC_ECC
|
||||||
|
|
||||||
|
#define MDC_FOURPOINT // recommended 4-point method, requires high sample rates (16000 or higher)
|
||||||
|
#undef MDC_ONEPOINT // alternative 1-point method
|
||||||
|
|
||||||
|
#ifdef MDC_FOURPOINT
|
||||||
|
#define MDC_ND 5 // recommended for four-point method
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MDC_ONEPOINT
|
||||||
|
#define MDC_ND 4 // recommended for one-point method
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*mdc_decoder_callback_t)(int frameCount, // 1 or 2 - if 2 then extra0-3 are valid
|
||||||
|
mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID,
|
||||||
|
mdc_u8_t extra0, mdc_u8_t extra1, mdc_u8_t extra2, mdc_u8_t extra3,
|
||||||
|
void *context);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Structure Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// mdc_float_t th;
|
||||||
|
mdc_u32_t thu;
|
||||||
|
// mdc_int_t zc; - deprecated
|
||||||
|
mdc_int_t xorb;
|
||||||
|
mdc_int_t invert;
|
||||||
|
#ifdef MDC_FOURPOINT
|
||||||
|
#ifdef MDC_FIXEDMATH
|
||||||
|
#error "fixed-point math not allowed for fourpoint strategy"
|
||||||
|
#endif // MDC_FIXEDMATH
|
||||||
|
mdc_int_t nlstep;
|
||||||
|
mdc_float_t nlevel[10];
|
||||||
|
#endif // MDC_FOURPOINT
|
||||||
|
#ifdef PLL
|
||||||
|
mdc_u32_t plt;
|
||||||
|
#endif
|
||||||
|
mdc_u32_t synclow;
|
||||||
|
mdc_u32_t synchigh;
|
||||||
|
mdc_int_t shstate;
|
||||||
|
mdc_int_t shcount;
|
||||||
|
mdc_int_t bits[112];
|
||||||
|
} mdc_decode_unit_t;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Structure Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
mdc_decode_unit_t du[MDC_ND];
|
||||||
|
// mdc_float_t hyst;
|
||||||
|
// mdc_float_t incr;
|
||||||
|
mdc_u32_t incru;
|
||||||
|
#ifdef PLL
|
||||||
|
mdc_u32_t zthu;
|
||||||
|
mdc_int_t zprev;
|
||||||
|
mdc_float_t vprev;
|
||||||
|
#endif
|
||||||
|
mdc_int_t level;
|
||||||
|
mdc_int_t good;
|
||||||
|
mdc_int_t indouble;
|
||||||
|
mdc_u8_t op;
|
||||||
|
mdc_u8_t arg;
|
||||||
|
mdc_u16_t unitID;
|
||||||
|
mdc_u8_t extra0;
|
||||||
|
mdc_u8_t extra1;
|
||||||
|
mdc_u8_t extra2;
|
||||||
|
mdc_u8_t extra3;
|
||||||
|
mdc_decoder_callback_t callback;
|
||||||
|
void *callback_context;
|
||||||
|
} mdc_decoder_t;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new mdc_decoder object.
|
||||||
|
* @param sampleRate The sampling rate in Hz.
|
||||||
|
* @returns mdc_decoder_t* An mdc_decoder object or null if failure.
|
||||||
|
*/
|
||||||
|
mdc_decoder_t* mdc_decoder_new(int sampleRate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process incoming samples using an mdc_decoder object.
|
||||||
|
* @param[in] decoder Instance of the mdc_decoder object.
|
||||||
|
* @param[out] samples Samples (in format set in mdc_types.h).
|
||||||
|
* @param[out] numSamples Count of the number of samples in buffer.
|
||||||
|
* @returns int 0 if more samples are needed
|
||||||
|
* -1 if an error occurs
|
||||||
|
* 1 if a decoded single packet is available to read (if no callback set)
|
||||||
|
* 2 if a decoded double packet is available to read (if no callback set)
|
||||||
|
*/
|
||||||
|
int mdc_decoder_process_samples(mdc_decoder_t* decoder, mdc_sample_t* samples, int numSamples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve last successfully decoded data packet from decoder object.
|
||||||
|
* @param[in] decoder Instance of the mdc_decoder object.
|
||||||
|
* @param[out] op MDC Opcode.
|
||||||
|
* @param[out] arg MDC Argument.
|
||||||
|
* @param[out] unitID Unit ID.
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_decoder_get_packet(mdc_decoder_t* decoder, mdc_u8_t* op, mdc_u8_t* arg, mdc_u16_t* unitID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve last successfully decoded double-length packet from decoder object.
|
||||||
|
* @param[in] decoder Instance of the mdc_decoder object.
|
||||||
|
* @param[out] op MDC Opcode.
|
||||||
|
* @param[out] arg MDC Argument.
|
||||||
|
* @param[out] unitID Unit ID.
|
||||||
|
* @param[out] extra0 1st extra byte.
|
||||||
|
* @param[out] extra1 2nd extra byte.
|
||||||
|
* @param[out] extra2 3rd extra byte.
|
||||||
|
* @param[out] extra3 4th extra byte.
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_decoder_get_double_packet(mdc_decoder_t* decoder, mdc_u8_t* op, mdc_u8_t* arg, mdc_u16_t* unitID,
|
||||||
|
mdc_u8_t* extra0, mdc_u8_t* extra1, mdc_u8_t* extra2, mdc_u8_t* extra3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a callback function to be called upon successful decode
|
||||||
|
* if this is set, the functions mdc_decoder_get_packet and mdc_decoder_get_double_packet
|
||||||
|
* will no longer be functional, instead the callback function is called immediately when
|
||||||
|
* a successful decode happens (from within the context of mdc_decoder_process_samples).
|
||||||
|
* @param[in] decoder Instance of the mdc_decoder object.
|
||||||
|
* @param callbackFunction
|
||||||
|
* @param context
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_decoder_set_callback(mdc_decoder_t* decoder, mdc_decoder_callback_t callbackFunction, void* context);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __MDC_DECODE_H__
|
||||||
@ -0,0 +1,574 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_encode.c
|
||||||
|
* Encodes a specific format from 1200 BPS MSK data burst
|
||||||
|
* to output audio samples.
|
||||||
|
*
|
||||||
|
* 9 October 2010 - typedefs for easier porting
|
||||||
|
* 27 July 2016 - additional reduced-amplitude sin tables
|
||||||
|
*
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005, 2010 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "mdc_encode.h"
|
||||||
|
|
||||||
|
#if defined(MDC_SAMPLE_FORMAT_U8)
|
||||||
|
#if defined(MDC_ENCODE_FULL_AMPLITUDE)
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172,
|
||||||
|
175, 178, 180, 183, 186, 189, 191, 194, 196, 199, 201, 204, 206, 209, 211, 213,
|
||||||
|
215, 218, 220, 222, 224, 226, 227, 229, 231, 233, 234, 236, 237, 239, 240, 241,
|
||||||
|
242, 244, 245, 246, 247, 247, 248, 249, 250, 250, 251, 251, 251, 252, 252, 252,
|
||||||
|
252, 252, 252, 252, 251, 251, 251, 250, 250, 249, 248, 247, 247, 246, 245, 244,
|
||||||
|
242, 241, 240, 239, 237, 236, 234, 233, 231, 229, 227, 226, 224, 222, 220, 218,
|
||||||
|
215, 213, 211, 209, 206, 204, 201, 199, 196, 194, 191, 189, 186, 183, 180, 178,
|
||||||
|
175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139, 136, 133, 130,
|
||||||
|
127, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 94, 91, 88, 85, 82,
|
||||||
|
79, 76, 74, 71, 68, 65, 63, 60, 58, 55, 53, 50, 48, 45, 43, 41,
|
||||||
|
39, 36, 34, 32, 30, 28, 27, 25, 23, 21, 20, 18, 17, 15, 14, 13,
|
||||||
|
12, 10, 9, 8, 7, 7, 6, 5, 4, 4, 3, 3, 3, 2, 2, 2,
|
||||||
|
2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10,
|
||||||
|
12, 13, 14, 15, 17, 18, 20, 21, 23, 25, 27, 28, 30, 32, 34, 36,
|
||||||
|
39, 41, 43, 45, 48, 50, 53, 55, 58, 60, 63, 65, 68, 71, 74, 76,
|
||||||
|
79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
|
||||||
|
160, 162, 164, 166, 168, 170, 172, 172, 174, 176, 178, 180, 182, 182, 184, 186,
|
||||||
|
188, 190, 190, 192, 194, 194, 196, 198, 198, 200, 200, 202, 202, 204, 204, 206,
|
||||||
|
206, 206, 208, 208, 208, 210, 210, 210, 212, 212, 212, 212, 212, 212, 212, 212,
|
||||||
|
212, 212, 212, 212, 212, 212, 212, 212, 212, 210, 210, 210, 208, 208, 208, 206,
|
||||||
|
206, 206, 204, 204, 202, 202, 200, 200, 198, 198, 196, 194, 194, 192, 190, 190,
|
||||||
|
188, 186, 184, 182, 182, 180, 178, 176, 174, 172, 172, 170, 168, 166, 164, 162,
|
||||||
|
160, 158, 156, 154, 152, 150, 148, 146, 144, 142, 140, 138, 136, 134, 132, 130,
|
||||||
|
128, 126, 124, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98,
|
||||||
|
96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 76, 74, 72, 70, 68,
|
||||||
|
68, 66, 64, 64, 62, 60, 60, 58, 56, 56, 54, 54, 52, 52, 50, 50,
|
||||||
|
48, 48, 48, 46, 46, 46, 44, 44, 44, 44, 44, 42, 42, 42, 42, 42,
|
||||||
|
42, 42, 42, 42, 42, 42, 44, 44, 44, 44, 44, 46, 46, 46, 48, 48,
|
||||||
|
48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 60, 60, 62, 64, 64, 66,
|
||||||
|
68, 68, 70, 72, 74, 76, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
|
||||||
|
96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_U16)
|
||||||
|
#if defined(MDC_ENCODE_FULL_AMPLITUDE)
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
32768, 33552, 34337, 35120, 35902, 36682, 37460, 38235,
|
||||||
|
39007, 39775, 40538, 41297, 42051, 42799, 43542, 44277,
|
||||||
|
45006, 45728, 46441, 47147, 47843, 48531, 49209, 49877,
|
||||||
|
50535, 51182, 51819, 52443, 53056, 53657, 54245, 54820,
|
||||||
|
55381, 55930, 56464, 56984, 57489, 57980, 58455, 58915,
|
||||||
|
59359, 59787, 60199, 60594, 60972, 61334, 61678, 62005,
|
||||||
|
62314, 62606, 62879, 63134, 63371, 63590, 63790, 63971,
|
||||||
|
64134, 64278, 64402, 64508, 64595, 64662, 64710, 64739,
|
||||||
|
64749, 64739, 64710, 64662, 64595, 64508, 64402, 64278,
|
||||||
|
64134, 63971, 63790, 63590, 63371, 63134, 62879, 62606,
|
||||||
|
62314, 62005, 61678, 61334, 60972, 60594, 60199, 59787,
|
||||||
|
59359, 58915, 58455, 57980, 57489, 56984, 56464, 55930,
|
||||||
|
55381, 54820, 54245, 53657, 53056, 52443, 51819, 51182,
|
||||||
|
50535, 49877, 49209, 48531, 47843, 47147, 46441, 45728,
|
||||||
|
45006, 44277, 43542, 42799, 42051, 41297, 40538, 39775,
|
||||||
|
39007, 38235, 37460, 36682, 35902, 35120, 34337, 33552,
|
||||||
|
32768, 31983, 31198, 30415, 29633, 28853, 28075, 27300,
|
||||||
|
26528, 25760, 24997, 24238, 23484, 22736, 21993, 21258,
|
||||||
|
20529, 19807, 19094, 18388, 17692, 17004, 16326, 15658,
|
||||||
|
15000, 14353, 13716, 13092, 12479, 11878, 11290, 10715,
|
||||||
|
10154, 9605, 9071, 8551, 8046, 7555, 7080, 6620,
|
||||||
|
6176, 5748, 5336, 4941, 4563, 4201, 3857, 3530,
|
||||||
|
3221, 2929, 2656, 2401, 2164, 1945, 1745, 1564,
|
||||||
|
1401, 1257, 1133, 1027, 940, 873, 825, 796,
|
||||||
|
787, 796, 825, 873, 940, 1027, 1133, 1257,
|
||||||
|
1401, 1564, 1745, 1945, 2164, 2401, 2656, 2929,
|
||||||
|
3221, 3530, 3857, 4201, 4563, 4941, 5336, 5748,
|
||||||
|
6176, 6620, 7080, 7555, 8046, 8551, 9071, 9605,
|
||||||
|
10154, 10715, 11290, 11878, 12479, 13092, 13716, 14353,
|
||||||
|
15000, 15658, 16326, 17004, 17692, 18388, 19094, 19807,
|
||||||
|
20529, 21258, 21993, 22736, 23484, 24238, 24997, 25760,
|
||||||
|
26528, 27300, 28075, 28853, 29633, 30415, 31198, 31983 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
32768, 33314, 33861, 34407, 34952, 35495, 36037, 36577, 37115, 37650, 38182, 38710, 39236, 39757, 40274, 40787,
|
||||||
|
41295, 41797, 42294, 42786, 43271, 43750, 44223, 44688, 45147, 45598, 46041, 46476, 46903, 47322, 47731, 48132,
|
||||||
|
48523, 48905, 49278, 49640, 49992, 50334, 50665, 50985, 51295, 51593, 51880, 52155, 52419, 52671, 52910, 53138,
|
||||||
|
53354, 53557, 53747, 53925, 54090, 54243, 54382, 54508, 54622, 54722, 54809, 54882, 54942, 54989, 55023, 55043,
|
||||||
|
55050, 55043, 55023, 54989, 54942, 54882, 54809, 54722, 54622, 54508, 54382, 54243, 54090, 53925, 53747, 53557,
|
||||||
|
53354, 53138, 52910, 52671, 52419, 52155, 51880, 51593, 51295, 50985, 50665, 50334, 49992, 49640, 49278, 48905,
|
||||||
|
48523, 48132, 47731, 47322, 46903, 46476, 46041, 45598, 45147, 44688, 44223, 43750, 43271, 42786, 42294, 41797,
|
||||||
|
41295, 40787, 40274, 39757, 39236, 38710, 38182, 37650, 37115, 36577, 36037, 35495, 34952, 34407, 33861, 33314,
|
||||||
|
32768, 32222, 31675, 31129, 30584, 30041, 29499, 28959, 28421, 27886, 27354, 26826, 26300, 25779, 25262, 24749,
|
||||||
|
24241, 23739, 23242, 22750, 22265, 21786, 21313, 20848, 20389, 19938, 19495, 19060, 18633, 18214, 17805, 17404,
|
||||||
|
17013, 16631, 16258, 15896, 15544, 15202, 14871, 14551, 14241, 13943, 13656, 13381, 13117, 12865, 12626, 12398,
|
||||||
|
12182, 11979, 11789, 11611, 11446, 11293, 11154, 11028, 10914, 10814, 10727, 10654, 10594, 10547, 10513, 10493,
|
||||||
|
10486, 10493, 10513, 10547, 10594, 10654, 10727, 10814, 10914, 11028, 11154, 11293, 11446, 11611, 11789, 11979,
|
||||||
|
12182, 12398, 12626, 12865, 13117, 13381, 13656, 13943, 14241, 14551, 14871, 15202, 15544, 15896, 16258, 16631,
|
||||||
|
17013, 17404, 17805, 18214, 18633, 19060, 19495, 19938, 20389, 20848, 21313, 21786, 22265, 22750, 23242, 23739,
|
||||||
|
24241, 24749, 25262, 25779, 26300, 26826, 27354, 27886, 28421, 28959, 29499, 30041, 30584, 31129, 31675, 32222 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_S16)
|
||||||
|
#if defined(MDC_ENCODE_FULL_AMPLITUDE)
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
0, 784, 1569, 2352, 3134, 3914, 4692, 5467,
|
||||||
|
6239, 7007, 7770, 8529, 9283, 10031, 10774, 11509,
|
||||||
|
12238, 12960, 13673, 14379, 15075, 15763, 16441, 17109,
|
||||||
|
17767, 18414, 19051, 19675, 20288, 20889, 21477, 22052,
|
||||||
|
22613, 23162, 23696, 24216, 24721, 25212, 25687, 26147,
|
||||||
|
26591, 27019, 27431, 27826, 28204, 28566, 28910, 29237,
|
||||||
|
29546, 29838, 30111, 30366, 30603, 30822, 31022, 31203,
|
||||||
|
31366, 31510, 31634, 31740, 31827, 31894, 31942, 31971,
|
||||||
|
31981, 31971, 31942, 31894, 31827, 31740, 31634, 31510,
|
||||||
|
31366, 31203, 31022, 30822, 30603, 30366, 30111, 29838,
|
||||||
|
29546, 29237, 28910, 28566, 28204, 27826, 27431, 27019,
|
||||||
|
26591, 26147, 25687, 25212, 24721, 24216, 23696, 23162,
|
||||||
|
22613, 22052, 21477, 20889, 20288, 19675, 19051, 18414,
|
||||||
|
17767, 17109, 16441, 15763, 15075, 14379, 13673, 12960,
|
||||||
|
12238, 11509, 10774, 10031, 9283, 8529, 7770, 7007,
|
||||||
|
6239, 5467, 4692, 3914, 3134, 2352, 1569, 784,
|
||||||
|
0, -784, -1569, -2352, -3134, -3914, -4692, -5467,
|
||||||
|
-6239, -7007, -7770, -8529, -9283, -10031, -10774, -11509,
|
||||||
|
-12238, -12960, -13673, -14379, -15075, -15763, -16441, -17109,
|
||||||
|
-17767, -18414, -19051, -19675, -20288, -20889, -21477, -22052,
|
||||||
|
-22613, -23162, -23696, -24216, -24721, -25212, -25687, -26147,
|
||||||
|
-26591, -27019, -27431, -27826, -28204, -28566, -28910, -29237,
|
||||||
|
-29546, -29838, -30111, -30366, -30603, -30822, -31022, -31203,
|
||||||
|
-31366, -31510, -31634, -31740, -31827, -31894, -31942, -31971,
|
||||||
|
-31981, -31971, -31942, -31894, -31827, -31740, -31634, -31510,
|
||||||
|
-31366, -31203, -31022, -30822, -30603, -30366, -30111, -29838,
|
||||||
|
-29546, -29237, -28910, -28566, -28204, -27826, -27431, -27019,
|
||||||
|
-26591, -26147, -25687, -25212, -24721, -24216, -23696, -23162,
|
||||||
|
-22613, -22052, -21477, -20889, -20288, -19675, -19051, -18414,
|
||||||
|
-17767, -17109, -16441, -15763, -15075, -14379, -13673, -12960,
|
||||||
|
-12238, -11509, -10774, -10031, -9283, -8529, -7770, -7007,
|
||||||
|
-6239, -5467, -4692, -3914, -3134, -2352, -1569, -784 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
|
||||||
|
0, 546, 1093, 1639, 2184, 2727, 3269, 3809, 4347, 4882, 5414, 5942, 6468, 6989, 7506, 8019,
|
||||||
|
8527, 9029, 9526, 10018, 10503, 10982, 11455, 11920, 12379, 12830, 13273, 13708, 14135, 14554, 14963, 15364,
|
||||||
|
15755, 16137, 16510, 16872, 17224, 17566, 17897, 18217, 18527, 18825, 19112, 19387, 19651, 19903, 20142, 20370,
|
||||||
|
20586, 20789, 20979, 21157, 21322, 21475, 21614, 21740, 21854, 21954, 22041, 22114, 22174, 22221, 22255, 22275,
|
||||||
|
22282, 22275, 22255, 22221, 22174, 22114, 22041, 21954, 21854, 21740, 21614, 21475, 21322, 21157, 20979, 20789,
|
||||||
|
20586, 20370, 20142, 19903, 19651, 19387, 19112, 18825, 18527, 18217, 17897, 17566, 17224, 16872, 16510, 16137,
|
||||||
|
15755, 15364, 14963, 14554, 14135, 13708, 13273, 12830, 12379, 11920, 11455, 10982, 10503, 10018, 9526, 9029,
|
||||||
|
8527, 8019, 7506, 6989, 6468, 5942, 5414, 4882, 4347, 3809, 3269, 2727, 2184, 1639, 1093, 546,
|
||||||
|
0, -546, -1093, -1639, -2184, -2727, -3269, -3809, -4347, -4882, -5414, -5942, -6468, -6989, -7506, -8019,
|
||||||
|
-8527, -9029, -9526, -10018, -10503, -10982, -11455, -11920, -12379, -12830, -13273, -13708, -14135, -14554, -14963, -15364,
|
||||||
|
-15755, -16137, -16510, -16872, -17224, -17566, -17897, -18217, -18527, -18825, -19112, -19387, -19651, -19903, -20142, -20370,
|
||||||
|
-20586, -20789, -20979, -21157, -21322, -21475, -21614, -21740, -21854, -21954, -22041, -22114, -22174, -22221, -22255, -22275,
|
||||||
|
-22282, -22275, -22255, -22221, -22174, -22114, -22041, -21954, -21854, -21740, -21614, -21475, -21322, -21157, -20979, -20789,
|
||||||
|
-20586, -20370, -20142, -19903, -19651, -19387, -19112, -18825, -18527, -18217, -17897, -17566, -17224, -16872, -16510, -16137,
|
||||||
|
-15755, -15364, -14963, -14554, -14135, -13708, -13273, -12830, -12379, -11920, -11455, -10982, -10503, -10018, -9526, -9029,
|
||||||
|
-8527, -8019, -7506, -6989, -6468, -5942, -5414, -4882, -4347, -3809, -3269, -2727, -2184, -1639, -1093, -546 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#elif defined(MDC_SAMPLE_FORMAT_FLOAT)
|
||||||
|
#if defined(MDC_ENCODE_FULL_AMPLITUDE)
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
0.000000, 0.024541, 0.049068, 0.073565, 0.098017, 0.122411, 0.146730, 0.170962,
|
||||||
|
0.195090, 0.219101, 0.242980, 0.266713, 0.290285, 0.313682, 0.336890, 0.359895,
|
||||||
|
0.382683, 0.405241, 0.427555, 0.449611, 0.471397, 0.492898, 0.514103, 0.534998,
|
||||||
|
0.555570, 0.575808, 0.595699, 0.615232, 0.634393, 0.653173, 0.671559, 0.689541,
|
||||||
|
0.707107, 0.724247, 0.740951, 0.757209, 0.773010, 0.788346, 0.803208, 0.817585,
|
||||||
|
0.831470, 0.844854, 0.857729, 0.870087, 0.881921, 0.893224, 0.903989, 0.914210,
|
||||||
|
0.923880, 0.932993, 0.941544, 0.949528, 0.956940, 0.963776, 0.970031, 0.975702,
|
||||||
|
0.980785, 0.985278, 0.989177, 0.992480, 0.995185, 0.997290, 0.998795, 0.999699,
|
||||||
|
1.000000, 0.999699, 0.998795, 0.997290, 0.995185, 0.992480, 0.989177, 0.985278,
|
||||||
|
0.980785, 0.975702, 0.970031, 0.963776, 0.956940, 0.949528, 0.941544, 0.932993,
|
||||||
|
0.923880, 0.914210, 0.903989, 0.893224, 0.881921, 0.870087, 0.857729, 0.844854,
|
||||||
|
0.831470, 0.817585, 0.803208, 0.788346, 0.773010, 0.757209, 0.740951, 0.724247,
|
||||||
|
0.707107, 0.689541, 0.671559, 0.653173, 0.634393, 0.615232, 0.595699, 0.575808,
|
||||||
|
0.555570, 0.534998, 0.514103, 0.492898, 0.471397, 0.449611, 0.427555, 0.405241,
|
||||||
|
0.382683, 0.359895, 0.336890, 0.313682, 0.290285, 0.266713, 0.242980, 0.219101,
|
||||||
|
0.195090, 0.170962, 0.146730, 0.122411, 0.098017, 0.073565, 0.049068, 0.024541,
|
||||||
|
0.000000, -0.024541, -0.049068, -0.073565, -0.098017, -0.122411, -0.146730, -0.170962,
|
||||||
|
-0.195090, -0.219101, -0.242980, -0.266713, -0.290285, -0.313682, -0.336890, -0.359895,
|
||||||
|
-0.382683, -0.405241, -0.427555, -0.449611, -0.471397, -0.492898, -0.514103, -0.534998,
|
||||||
|
-0.555570, -0.575808, -0.595699, -0.615232, -0.634393, -0.653173, -0.671559, -0.689541,
|
||||||
|
-0.707107, -0.724247, -0.740951, -0.757209, -0.773010, -0.788346, -0.803208, -0.817585,
|
||||||
|
-0.831470, -0.844854, -0.857729, -0.870087, -0.881921, -0.893224, -0.903989, -0.914210,
|
||||||
|
-0.923880, -0.932993, -0.941544, -0.949528, -0.956940, -0.963776, -0.970031, -0.975702,
|
||||||
|
-0.980785, -0.985278, -0.989177, -0.992480, -0.995185, -0.997290, -0.998795, -0.999699,
|
||||||
|
-1.000000, -0.999699, -0.998795, -0.997290, -0.995185, -0.992480, -0.989177, -0.985278,
|
||||||
|
-0.980785, -0.975702, -0.970031, -0.963776, -0.956940, -0.949528, -0.941544, -0.932993,
|
||||||
|
-0.923880, -0.914210, -0.903989, -0.893224, -0.881921, -0.870087, -0.857729, -0.844854,
|
||||||
|
-0.831470, -0.817585, -0.803208, -0.788346, -0.773010, -0.757209, -0.740951, -0.724247,
|
||||||
|
-0.707107, -0.689541, -0.671559, -0.653173, -0.634393, -0.615232, -0.595699, -0.575808,
|
||||||
|
-0.555570, -0.534998, -0.514103, -0.492898, -0.471397, -0.449611, -0.427555, -0.405241,
|
||||||
|
-0.382683, -0.359895, -0.336890, -0.313682, -0.290285, -0.266713, -0.242980, -0.219101,
|
||||||
|
-0.195090, -0.170962, -0.146730, -0.122411, -0.098017, -0.073565, -0.049068, -0.024541 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static mdc_sample_t sintable[] = {
|
||||||
|
0.000000, 0.016688, 0.033366, 0.050024, 0.066652, 0.083239, 0.099777, 0.116254,
|
||||||
|
0.132661, 0.148989, 0.165227, 0.181365, 0.197394, 0.213304, 0.229085, 0.244729,
|
||||||
|
0.260225, 0.275564, 0.290737, 0.305736, 0.320550, 0.335171, 0.349590, 0.363798,
|
||||||
|
0.377788, 0.391550, 0.405076, 0.418357, 0.431387, 0.444158, 0.456660, 0.468888,
|
||||||
|
0.480833, 0.492488, 0.503847, 0.514902, 0.525647, 0.536076, 0.546181, 0.555958,
|
||||||
|
0.565399, 0.574500, 0.583255, 0.591659, 0.599706, 0.607393, 0.614713, 0.621663,
|
||||||
|
0.628238, 0.634435, 0.640250, 0.645679, 0.650719, 0.655368, 0.659621, 0.663477,
|
||||||
|
0.666934, 0.669989, 0.672640, 0.674886, 0.676726, 0.678158, 0.679181, 0.679795,
|
||||||
|
0.680000, 0.679795, 0.679181, 0.678158, 0.676726, 0.674886, 0.672640, 0.669989,
|
||||||
|
0.666934, 0.663477, 0.659621, 0.655368, 0.650719, 0.645679, 0.640250, 0.634435,
|
||||||
|
0.628238, 0.621663, 0.614713, 0.607393, 0.599706, 0.591659, 0.583255, 0.574500,
|
||||||
|
0.565399, 0.555958, 0.546181, 0.536076, 0.525647, 0.514902, 0.503847, 0.492488,
|
||||||
|
0.480833, 0.468888, 0.456660, 0.444158, 0.431387, 0.418357, 0.405076, 0.391550,
|
||||||
|
0.377788, 0.363798, 0.349590, 0.335171, 0.320550, 0.305736, 0.290737, 0.275564,
|
||||||
|
0.260225, 0.244729, 0.229085, 0.213304, 0.197394, 0.181365, 0.165227, 0.148989,
|
||||||
|
0.132661, 0.116254, 0.099777, 0.083239, 0.066652, 0.050024, 0.033366, 0.016688,
|
||||||
|
0.000000, -0.016688, -0.033366, -0.050024, -0.066652, -0.083239, -0.099777, -0.116254,
|
||||||
|
-0.132661, -0.148989, -0.165227, -0.181365, -0.197394, -0.213304, -0.229085, -0.244729,
|
||||||
|
-0.260225, -0.275564, -0.290737, -0.305736, -0.320550, -0.335171, -0.349590, -0.363798,
|
||||||
|
-0.377788, -0.391550, -0.405076, -0.418357, -0.431387, -0.444158, -0.456660, -0.468888,
|
||||||
|
-0.480833, -0.492488, -0.503847, -0.514902, -0.525647, -0.536076, -0.546181, -0.555958,
|
||||||
|
-0.565399, -0.574500, -0.583255, -0.591659, -0.599706, -0.607393, -0.614713, -0.621663,
|
||||||
|
-0.628238, -0.634435, -0.640250, -0.645679, -0.650719, -0.655368, -0.659621, -0.663477,
|
||||||
|
-0.666934, -0.669989, -0.672640, -0.674886, -0.676726, -0.678158, -0.679181, -0.679795,
|
||||||
|
-0.680000, -0.679795, -0.679181, -0.678158, -0.676726, -0.674886, -0.672640, -0.669989,
|
||||||
|
-0.666934, -0.663477, -0.659621, -0.655368, -0.650719, -0.645679, -0.640250, -0.634435,
|
||||||
|
-0.628238, -0.621663, -0.614713, -0.607393, -0.599706, -0.591659, -0.583255, -0.574500,
|
||||||
|
-0.565399, -0.555958, -0.546181, -0.536076, -0.525647, -0.514902, -0.503847, -0.492488,
|
||||||
|
-0.480833, -0.468888, -0.456660, -0.444158, -0.431387, -0.418357, -0.405076, -0.391550,
|
||||||
|
-0.377788, -0.363798, -0.349590, -0.335171, -0.320550, -0.305736, -0.290737, -0.275564,
|
||||||
|
-0.260225, -0.244729, -0.229085, -0.213304, -0.197394, -0.181365, -0.165227, -0.148989,
|
||||||
|
-0.132661, -0.116254, -0.099777, -0.083239, -0.066652, -0.050024, -0.033366, -0.016688 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#error "no known sample format defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Create a new mdc_encoder object. */
|
||||||
|
|
||||||
|
mdc_encoder_t* mdc_encoder_new(int sampleRate)
|
||||||
|
{
|
||||||
|
mdc_encoder_t* encoder;
|
||||||
|
|
||||||
|
encoder = (mdc_encoder_t*)malloc(sizeof(mdc_encoder_t));
|
||||||
|
if (!encoder)
|
||||||
|
return (mdc_encoder_t*)0L;
|
||||||
|
|
||||||
|
encoder->loaded = 0;
|
||||||
|
encoder->preamble_set = 0;
|
||||||
|
|
||||||
|
if (sampleRate == 8000) {
|
||||||
|
encoder->incru = 644245094;
|
||||||
|
encoder->incru18 = 966367642;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 16000) {
|
||||||
|
encoder->incru = 322122547;
|
||||||
|
encoder->incru18 = 483183820;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 22050) {
|
||||||
|
encoder->incru = 233739716;
|
||||||
|
encoder->incru18 = 350609575;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 32000) {
|
||||||
|
encoder->incru = 161061274;
|
||||||
|
encoder->incru18 = 241591910;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 44100) {
|
||||||
|
encoder->incru = 116869858;
|
||||||
|
encoder->incru18 = 175304788;
|
||||||
|
}
|
||||||
|
else if (sampleRate == 48000) {
|
||||||
|
encoder->incru = 107374182;
|
||||||
|
encoder->incru18 = 161061274;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// WARNING: lower precision than above
|
||||||
|
encoder->incru = 1200 * 2 * (0x80000000 / sampleRate);
|
||||||
|
encoder->incru18 = 1800 * 2 * (0x80000000 / sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return encoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mdc_encoder_set_preamble(mdc_encoder_t* encoder, int preambleLength)
|
||||||
|
{
|
||||||
|
if (!encoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (preambleLength < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
encoder->preamble_set = preambleLength;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static mdc_u8_t* _enc_leader(mdc_u8_t* data)
|
||||||
|
{
|
||||||
|
data[0] = 0x55;
|
||||||
|
data[1] = 0x55;
|
||||||
|
data[2] = 0x55;
|
||||||
|
data[3] = 0x55;
|
||||||
|
data[4] = 0x55;
|
||||||
|
data[5] = 0x55;
|
||||||
|
data[6] = 0x55;
|
||||||
|
|
||||||
|
data[7] = 0x07;
|
||||||
|
data[8] = 0x09;
|
||||||
|
data[9] = 0x2a;
|
||||||
|
data[10] = 0x44;
|
||||||
|
data[11] = 0x6f;
|
||||||
|
|
||||||
|
return &(data[12]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static mdc_u8_t* _enc_str(mdc_u8_t* data)
|
||||||
|
{
|
||||||
|
mdc_u16_t ccrc;
|
||||||
|
mdc_int_t k, m;
|
||||||
|
mdc_int_t csr[7];
|
||||||
|
mdc_int_t b;
|
||||||
|
mdc_int_t lbits[112];
|
||||||
|
|
||||||
|
ccrc = _docrc(data, 4);
|
||||||
|
|
||||||
|
data[4] = ccrc & 0x00ff;
|
||||||
|
data[5] = (ccrc >> 8) & 0x00ff;
|
||||||
|
|
||||||
|
data[6] = 0;
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < 7; i++)
|
||||||
|
csr[i] = 0;
|
||||||
|
|
||||||
|
for (mdc_int_t i = 0; i < 7; i++) {
|
||||||
|
data[i + 7] = 0;
|
||||||
|
for (mdc_int_t j = 0; j <= 7; j++) {
|
||||||
|
for (k = 6; k > 0; k--)
|
||||||
|
csr[k] = csr[k - 1];
|
||||||
|
csr[0] = (data[i] >> j) & 0x01;
|
||||||
|
b = csr[0] + csr[2] + csr[5] + csr[6];
|
||||||
|
data[i + 7] |= (b & 0x01) << j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
m = 0;
|
||||||
|
for(mdc_int_t i = 0; i < 14; i++) {
|
||||||
|
for(mdc_int_t j = 0; j <= 7; j++) {
|
||||||
|
b = 0x01 & (data[i] >> j);
|
||||||
|
lbits[k] = b;
|
||||||
|
k += 16;
|
||||||
|
if (k > 111)
|
||||||
|
k = ++m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (mdc_int_t i = 0; i < 14; i++) {
|
||||||
|
data[i] = 0;
|
||||||
|
for(mdc_int_t j = 7; j >= 0; j--) {
|
||||||
|
if (lbits[k])
|
||||||
|
data[i] |= 1<<j;
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &(data[14]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a normal-length MDC packet for transmission. */
|
||||||
|
|
||||||
|
int mdc_encoder_set_packet(mdc_encoder_t* encoder, mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID)
|
||||||
|
{
|
||||||
|
mdc_u8_t* dp;
|
||||||
|
|
||||||
|
if (!encoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (encoder->loaded)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
encoder->state = 0;
|
||||||
|
|
||||||
|
dp = _enc_leader(encoder->data);
|
||||||
|
|
||||||
|
dp[0] = op;
|
||||||
|
dp[1] = arg;
|
||||||
|
dp[2] = (unitID >> 8) & 0x00ff;
|
||||||
|
dp[3] = unitID & 0x00ff;
|
||||||
|
|
||||||
|
_enc_str(dp);
|
||||||
|
|
||||||
|
encoder->loaded = 26;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a double-length MDC packet for transmission. */
|
||||||
|
|
||||||
|
int mdc_encoder_set_double_packet(mdc_encoder_t* encoder, mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID,
|
||||||
|
mdc_u8_t extra0, mdc_u8_t extra1, mdc_u8_t extra2, mdc_u8_t extra3)
|
||||||
|
{
|
||||||
|
mdc_u8_t* dp;
|
||||||
|
|
||||||
|
if (!encoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (encoder->loaded)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
encoder->state = 0;
|
||||||
|
|
||||||
|
dp = _enc_leader(encoder->data);
|
||||||
|
|
||||||
|
dp[0] = op;
|
||||||
|
dp[1] = arg;
|
||||||
|
dp[2] = (unitID >> 8) & 0x00ff;
|
||||||
|
dp[3] = unitID & 0x00ff;
|
||||||
|
|
||||||
|
dp = _enc_str(dp);
|
||||||
|
|
||||||
|
dp[0] = extra0;
|
||||||
|
dp[1] = extra1;
|
||||||
|
dp[2] = extra2;
|
||||||
|
dp[3] = extra3;
|
||||||
|
|
||||||
|
_enc_str(dp);
|
||||||
|
|
||||||
|
encoder->loaded = 40;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static mdc_sample_t _enc_get_samp(mdc_encoder_t* encoder)
|
||||||
|
{
|
||||||
|
mdc_int_t b;
|
||||||
|
mdc_int_t ofs;
|
||||||
|
|
||||||
|
mdc_u32_t lthu = encoder->thu;
|
||||||
|
encoder->thu += encoder->incru;
|
||||||
|
|
||||||
|
// wrap
|
||||||
|
if (encoder->thu < lthu) {
|
||||||
|
encoder->ipos++;
|
||||||
|
if (encoder->ipos > 7) {
|
||||||
|
encoder->ipos = 0;
|
||||||
|
if (encoder->preamble_count == 0)
|
||||||
|
encoder->bpos++;
|
||||||
|
else
|
||||||
|
encoder->preamble_count--;
|
||||||
|
|
||||||
|
if (encoder->bpos >= encoder->loaded) {
|
||||||
|
encoder->state = 0;
|
||||||
|
return sintable[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b = 0x01 & (encoder->data[encoder->bpos] >> (7-(encoder->ipos)));
|
||||||
|
|
||||||
|
if (b != encoder->lb) {
|
||||||
|
encoder->xorb = 1;
|
||||||
|
encoder->lb = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
encoder->xorb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder->xorb)
|
||||||
|
encoder->tthu += encoder->incru18;
|
||||||
|
else
|
||||||
|
encoder->tthu += encoder->incru;
|
||||||
|
|
||||||
|
ofs = (int)(encoder->tthu >> 24);
|
||||||
|
|
||||||
|
return sintable[ofs];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get generated output audio samples from encoder. */
|
||||||
|
|
||||||
|
int mdc_encoder_get_samples(mdc_encoder_t* encoder, mdc_sample_t* buffer, int bufferSize)
|
||||||
|
{
|
||||||
|
if (!encoder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(encoder->loaded))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (encoder->state == 0) {
|
||||||
|
encoder->tthu = 0;
|
||||||
|
encoder->thu = 0;
|
||||||
|
encoder->bpos = 0;
|
||||||
|
encoder->ipos = 0;
|
||||||
|
encoder->state = 1;
|
||||||
|
encoder->xorb = 1;
|
||||||
|
encoder->lb = 0;
|
||||||
|
encoder->preamble_count = encoder->preamble_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdc_int_t i = 0;
|
||||||
|
while ((i < bufferSize) && encoder->state) {
|
||||||
|
buffer[i++] = _enc_get_samp(encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FILL_FINAL
|
||||||
|
while (i < bufferSize) {
|
||||||
|
buffer[i++] = sintable[0];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (encoder->state == 0)
|
||||||
|
encoder->loaded = 0;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file mdc_encode.h
|
||||||
|
* @ingroup bridge
|
||||||
|
* @file mdc_encode.c
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_encode.h
|
||||||
|
* header for mdc_encode.c
|
||||||
|
*
|
||||||
|
* 9 October 2010 - typedefs for easier porting
|
||||||
|
*
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
#if !defined(__MDC_ENCODE_H__)
|
||||||
|
#define __MDC_ENCODE_H__
|
||||||
|
|
||||||
|
#include "mdc/mdc_types.h"
|
||||||
|
|
||||||
|
//#define FILL_FINAL // fills the end of the last block with zeros, rather than returning fewer samples than requested
|
||||||
|
//#define MDC_ENCODE_FULL_AMPLITUDE // encode at 100% amplitude (default is 68% amplitude for recommended deviation)
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Structure Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
mdc_int_t loaded;
|
||||||
|
mdc_int_t bpos;
|
||||||
|
mdc_int_t ipos;
|
||||||
|
mdc_int_t preamble_set;
|
||||||
|
mdc_int_t preamble_count;
|
||||||
|
mdc_u32_t thu;
|
||||||
|
mdc_u32_t tthu;
|
||||||
|
mdc_u32_t incru;
|
||||||
|
mdc_u32_t incru18;
|
||||||
|
mdc_int_t state;
|
||||||
|
mdc_int_t lb;
|
||||||
|
mdc_int_t xorb;
|
||||||
|
mdc_u8_t data[14 + 14 + 5 + 7];
|
||||||
|
} mdc_encoder_t;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new mdc_encoder object.
|
||||||
|
* @param sampleRate The sampling rate in Hz.
|
||||||
|
* @returns mdc_encoder_t* An mdc_encoder object or null if failure.
|
||||||
|
*/
|
||||||
|
mdc_encoder_t* mdc_encoder_new(int sampleRate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param[in] encoder Instance of mdc_encoder object.
|
||||||
|
* @param preambleLength length of additional preamble (in bytes) - preamble time is 6.66 msec * preambleLength.
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_encoder_set_preamble(mdc_encoder_t* encoder, int preambleLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set up a normal-length MDC packet for transmission.
|
||||||
|
* @param[in] encoder Instance of mdc_encoder object.
|
||||||
|
* @param op MDC Opcode.
|
||||||
|
* @param arg MDC Argument.
|
||||||
|
* @param unitID Unit ID.
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_encoder_set_packet(mdc_encoder_t* encoder, mdc_u8_t op, mdc_u8_t arg, mdc_u16_t unitID);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set up a double-length MDC packet for transmission.
|
||||||
|
* @param[in] encoder Instance of mdc_encoder object.
|
||||||
|
* @param op MDC Opcode.
|
||||||
|
* @param arg MDC Argument.
|
||||||
|
* @param unitID Unit ID.
|
||||||
|
* @param extra0 1st extra byte.
|
||||||
|
* @param extra1 2nd extra byte.
|
||||||
|
* @param extra2 3rd extra byte.
|
||||||
|
* @param extra3 4th extra byte.
|
||||||
|
* @returns int -1 for error, 0 otherwise
|
||||||
|
*/
|
||||||
|
int mdc_encoder_set_double_packet(mdc_encoder_t* encoder, mdc_u8_t op, mdc_u8_t arg,
|
||||||
|
mdc_u16_t unitID, mdc_u8_t extra0, mdc_u8_t extra1, mdc_u8_t extra2, mdc_u8_t extra3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get generated output audio samples from encoder.
|
||||||
|
* @param[out] buffer Sample buffer to write into.
|
||||||
|
* @param[out] bufferSize The size (in samples) of the sample buffer.
|
||||||
|
* @returns int -1 for error, otherwise returns the number of samples written
|
||||||
|
* into the buffer (will be equal to bufferSize unless the end has
|
||||||
|
* been reached, in which case the last block may be less than
|
||||||
|
* bufferSize and all subsequent calls will return zero, until
|
||||||
|
* a new packet is loaded for transmission
|
||||||
|
*/
|
||||||
|
int mdc_encoder_get_samples(mdc_encoder_t* encoder, mdc_sample_t* buffer, int bufferSize);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __MDC_ENCODE_H__
|
||||||
@ -0,0 +1,511 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file mdc_types.h
|
||||||
|
* @ingroup bridge
|
||||||
|
*/
|
||||||
|
/*-
|
||||||
|
* mdc_types.h
|
||||||
|
* common typedef header for mdc_decode.h, mdc_encode.h
|
||||||
|
*
|
||||||
|
* Author: Matthew Kaufman (matthew@eeph.com)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Matthew Kaufman All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of Matthew Kaufman's MDC Encoder/Decoder Library
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library is free software; you can
|
||||||
|
* redistribute it and/or modify it under the terms of version 2 of
|
||||||
|
* the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation.
|
||||||
|
*
|
||||||
|
* If you cannot comply with the terms of this license, contact
|
||||||
|
* the author for alternative license arrangements or do not use
|
||||||
|
* or redistribute this software.
|
||||||
|
*
|
||||||
|
* The MDC Encoder/Decoder Library 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; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
* USA.
|
||||||
|
*
|
||||||
|
* or see http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
-*/
|
||||||
|
#if !defined(__MDC_TYPES_H__)
|
||||||
|
#define __MDC_TYPES_H__
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Types
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef int mdc_s32;
|
||||||
|
typedef unsigned int mdc_u32_t;
|
||||||
|
typedef short mdc_s16_t;
|
||||||
|
typedef unsigned short mdc_u16_t;
|
||||||
|
typedef char mdc_s8_t;
|
||||||
|
typedef unsigned char mdc_u8_t;
|
||||||
|
typedef int mdc_int_t;
|
||||||
|
|
||||||
|
#ifndef MDC_FIXEDMATH
|
||||||
|
typedef double mdc_float_t;
|
||||||
|
#endif // MDC_FIXEDMATH
|
||||||
|
|
||||||
|
/* to change the data type, set this typedef: */
|
||||||
|
typedef short mdc_sample_t;
|
||||||
|
#define MDC_SAMPLE_FORMAT_S16
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Single Packets
|
||||||
|
*/
|
||||||
|
/// <summary>
|
||||||
|
/// Emergency
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// PTT_PRE (0x80)
|
||||||
|
/// EMERG_UNKNW (0x81)
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_EMERGENCY 0x00U
|
||||||
|
/// <summary>
|
||||||
|
/// Emergency Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Has no arguments, should always have NO_ARG.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_EMERGENCY_ACK 0x20U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PTT ID
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// NO_ARG (0x00) value indicates Post- ID
|
||||||
|
/// PTT_PRE (0x80) value indicated Pre- ID
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_PTT_ID 0x01U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Radio Check
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Always takes the argument RADIO_CHECK (0x85).
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RADIO_CHECK 0x63U
|
||||||
|
/// <summary>
|
||||||
|
/// Radio Check Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Has no arguments, should always have NO_ARG.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RADIO_CHECK_ACK 0x03U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Argument contains the ID of the given message. This opcode
|
||||||
|
/// optionally supports setting of bit 7 for required acknowledgement
|
||||||
|
/// of receipt.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack (or) Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_MESSAGE 0x07U
|
||||||
|
#define OP_MESSAGE_WITH_ACK 0x47U
|
||||||
|
/// <summary>
|
||||||
|
/// Message/Status Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Always takes the argument NO_ARG.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_MESSAGE_ACK 0x23U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Status Request
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Always takes the argument STATUS_REQ (0x06).
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_STATUS_REQUEST 0x22U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Status Response
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Argument contains the ID of the given status.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_STATUS_RESPONSE 0x06U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remote Monitor
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Always takes the argument REMOTE_MONITOR (0x8A).
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_REMOTE_MONITOR 0x11U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selective Radio Inhibit
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// NO_ARG (0x00) value indicates Unit ID to inhibit
|
||||||
|
/// CANCEL_INHIBIT (0x0C) value indicates Unit ID to uninhibit
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RADIO_INHIBIT 0x2BU
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Selective Radio Inhibit Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// NO_ARG (0x00) value indicates the Unit ID acknowledges the inhibit
|
||||||
|
/// CANCEL_INHIBIT (0x0C) value indicates the Unit ID acknowledges is uninhibited
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RADIO_INHIBIT_ACK 0x0BU
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repeater Access Code
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This operand is doubled to 0x41?
|
||||||
|
///
|
||||||
|
/// Always takes the argument RTT (0x01).
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RAC 0x30U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request to Talk
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This operand is doubled to 0x41?
|
||||||
|
///
|
||||||
|
/// Always takes the argument RTT (0x01).
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RTT_1 0x40U
|
||||||
|
#define OP_RTT_2 0x41U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request to Talk Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Has no arguments, should always have NO_ARG.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_RTT_ACK 0x23U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple Status
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Argument contains the ID of the given status.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_SIMPLE_STATUS 0x46U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Double Packets
|
||||||
|
*/
|
||||||
|
/// <summary>
|
||||||
|
/// Double Packet Operation (0x35)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// DOUBLE_PACKET_FROM (0x89) value indicates who transmitted the double packet
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_DOUBLE_PACKET_TYPE1 0x35U
|
||||||
|
/// <summary>
|
||||||
|
/// Double Packet Operation (0x55)
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </summary>
|
||||||
|
#define OP_DOUBLE_PACKET_TYPE2 0x55U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call Alert/Page
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// CALL_ALERT_TO (0x0D) value indicates the intended target of the call
|
||||||
|
///
|
||||||
|
/// The DOUBLE_PACKET_FROM (0x89) of the DOUBLE_PACKET_TYPE1 frame will contain the unit ID that transmitted
|
||||||
|
/// the call alert. This opcode expects an ack, regardless of the bit 7 setting.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Data
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_CALL_ALERT_ACK_EXPECTED 0x83U
|
||||||
|
/// <summary>
|
||||||
|
/// Call Alert/Page
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// CALL_ALERT_TO (0x0D) value indicates the intended target of the call
|
||||||
|
///
|
||||||
|
/// The DOUBLE_PACKET_FROM (0x89) of the DOUBLE_PACKET_TYPE1 frame will contain the unit ID that transmitted
|
||||||
|
/// the call alert. This opcode does not expect an ack, regardless of the bit 7 setting.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Data
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_CALL_ALERT_NOACK_EXPECTED 0x81U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call Alert/Page Acknowledge
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// NO_ARG (0x00) value indicates the unit ID which initiated the call
|
||||||
|
///
|
||||||
|
/// The DOUBLE_PACKET_FROM (0x89) of the DOUBLE_PACKET_TYPE1 frame will contain the unit ID that transmitted
|
||||||
|
/// the acknowledge.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Data
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_CALL_ALERT_ACK 0xA0U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Voice Selective Call
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This opcode is doubled to operand 0x82 as well as 0x80?
|
||||||
|
///
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// SELECTIVE_CALL_TO (0x15) value indicates the intended target of the call
|
||||||
|
///
|
||||||
|
/// The DOUBLE_PACKET_FROM (0x89) of the DOUBLE_PACKET_TYPE1 frame will contain the unit ID that transmitted
|
||||||
|
/// the call alert.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Data
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Inbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_SELECTIVE_CALL_1 0x80U
|
||||||
|
#define OP_SELECTIVE_CALL_2 0x82U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Over-the-Air Rekey
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Supports the following arguments:
|
||||||
|
/// OTAR_UNK1 0x74 ?
|
||||||
|
/// OTAR_UNK2 0x76 ?
|
||||||
|
///
|
||||||
|
/// The DOUBLE_PACKET_FROM (0x89) of the DOUBLE_PACKET_TYPE1 frame will contain the unit ID that transmitted
|
||||||
|
/// the call alert.
|
||||||
|
///
|
||||||
|
/// Opcode Bits:
|
||||||
|
/// 8 = Command/Data Packet = Command
|
||||||
|
/// 7 = Ack/No Ack Required = No Ack
|
||||||
|
/// 6 = Inbound/Outbound Packet = Outbound
|
||||||
|
/// </remarks>
|
||||||
|
#define OP_OTAR 0x86U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// No Argument
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_NO_ARG 0x00U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Single Packets
|
||||||
|
*/
|
||||||
|
/// <summary>
|
||||||
|
/// Emergency Argument (unknown use)
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_EMERG_UNKNW 0x81U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PTT ID Pre-
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_PTT_PRE 0x80U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Radio Check
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_RADIO_CHECK 0x85U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Status Request
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_STATUS_REQ 0x06U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remote Monitor
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_REMOTE_MONITOR 0x8AU
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel Selective Radio Inhibit
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_CANCEL_INHIBIT 0x0CU
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request to Talk
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_RTT 0x01U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Double Packets
|
||||||
|
*/
|
||||||
|
/// <summary>
|
||||||
|
/// Double To Argument
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Unit ID represents what radio ID the call is targeting</remarks>
|
||||||
|
#define ARG_DOUBLE_PACKET_TO 0x89U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call Alert Argument
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Unit ID represents what radio ID the call originated from</remarks>
|
||||||
|
#define ARG_CALL_ALERT 0x0DU
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OTAR Argument Unknown 0xC6
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_OTAR_DOUBLE 0xC6U
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OTAR Argument Unknown 0x74
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_OTAR_UNK1 0x74U
|
||||||
|
/// <summary>
|
||||||
|
/// OTAR Argument Unknown 0x76
|
||||||
|
/// </summary>
|
||||||
|
#define ARG_OTAR_UNK2 0x76U
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param crc
|
||||||
|
* @param bitnum
|
||||||
|
* @returns mdc_u16_t
|
||||||
|
*/
|
||||||
|
mdc_u16_t _flip(mdc_u16_t crc, mdc_int_t bitnum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param p
|
||||||
|
* @param len
|
||||||
|
* @returns mdc_u16_t
|
||||||
|
*/
|
||||||
|
mdc_u16_t _docrc(mdc_u8_t* p, int len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __MDC_TYPES_H__
|
||||||
@ -0,0 +1,360 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "bridge/Defines.h"
|
||||||
|
#include "common/dmr/data/EMB.h"
|
||||||
|
#include "common/dmr/lc/FullLC.h"
|
||||||
|
#include "common/dmr/SlotType.h"
|
||||||
|
#include "common/network/json/json.h"
|
||||||
|
#include "common/p25/dfsi/DFSIDefines.h"
|
||||||
|
#include "common/p25/dfsi/LC.h"
|
||||||
|
#include "common/Utils.h"
|
||||||
|
#include "network/PeerNetwork.h"
|
||||||
|
|
||||||
|
using namespace network;
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Public Class Members
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Initializes a new instance of the PeerNetwork class. */
|
||||||
|
|
||||||
|
PeerNetwork::PeerNetwork(const std::string& address, uint16_t port, uint16_t localPort, uint32_t peerId, const std::string& password,
|
||||||
|
bool duplex, bool debug, bool dmr, bool p25, bool nxdn, bool slot1, bool slot2, bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup) :
|
||||||
|
Network(address, port, localPort, peerId, password, duplex, debug, dmr, p25, nxdn, slot1, slot2, allowActivityTransfer, allowDiagnosticTransfer, updateLookup, saveLookup)
|
||||||
|
{
|
||||||
|
assert(!address.empty());
|
||||||
|
assert(port > 0U);
|
||||||
|
assert(!password.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes P25 LDU1 frame data to the network. */
|
||||||
|
|
||||||
|
bool PeerNetwork::writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data, p25::defines::FrameType::E frameType)
|
||||||
|
{
|
||||||
|
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool resetSeq = false;
|
||||||
|
if (m_p25StreamId == 0U) {
|
||||||
|
resetSeq = true;
|
||||||
|
m_p25StreamId = createStreamId();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t messageLength = 0U;
|
||||||
|
UInt8Array message = createP25_LDU1Message_Raw(messageLength, control, lsd, data, frameType);
|
||||||
|
if (message == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeMaster({ NET_FUNC::PROTOCOL, NET_SUBFUNC::PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, pktSeq(resetSeq), m_p25StreamId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Writes P25 LDU2 frame data to the network. */
|
||||||
|
|
||||||
|
bool PeerNetwork::writeP25LDU2(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data)
|
||||||
|
{
|
||||||
|
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool resetSeq = false;
|
||||||
|
if (m_p25StreamId == 0U) {
|
||||||
|
resetSeq = true;
|
||||||
|
m_p25StreamId = createStreamId();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t messageLength = 0U;
|
||||||
|
UInt8Array message = createP25_LDU2Message_Raw(messageLength, control, lsd, data);
|
||||||
|
if (message == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeMaster({ NET_FUNC::PROTOCOL, NET_SUBFUNC::PROTOCOL_SUBFUNC_P25 }, message.get(), messageLength, pktSeq(resetSeq), m_p25StreamId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to send a DMR terminator with LC message. */
|
||||||
|
|
||||||
|
void PeerNetwork::writeDMRTerminator(dmr::data::NetData& data, uint32_t* seqNo, uint8_t* dmrN, dmr::data::EmbeddedData& embeddedData)
|
||||||
|
{
|
||||||
|
using namespace dmr;
|
||||||
|
using namespace dmr::defines;
|
||||||
|
|
||||||
|
uint8_t n = (uint8_t)((*seqNo - 3U) % 6U);
|
||||||
|
uint32_t fill = 6U - n;
|
||||||
|
|
||||||
|
uint8_t* buffer = nullptr;
|
||||||
|
if (n > 0U) {
|
||||||
|
for (uint32_t i = 0U; i < fill; i++) {
|
||||||
|
// generate DMR AMBE data
|
||||||
|
buffer = new uint8_t[DMR_FRAME_LENGTH_BYTES];
|
||||||
|
::memcpy(buffer, SILENCE_DATA, DMR_FRAME_LENGTH_BYTES);
|
||||||
|
|
||||||
|
uint8_t lcss = embeddedData.getData(buffer, n);
|
||||||
|
|
||||||
|
// generated embedded signalling
|
||||||
|
data::EMB emb = data::EMB();
|
||||||
|
emb.setColorCode(0U);
|
||||||
|
emb.setLCSS(lcss);
|
||||||
|
emb.encode(buffer);
|
||||||
|
|
||||||
|
// generate DMR network frame
|
||||||
|
data.setData(buffer);
|
||||||
|
|
||||||
|
writeDMR(data);
|
||||||
|
|
||||||
|
seqNo++;
|
||||||
|
dmrN++;
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = new uint8_t[DMR_FRAME_LENGTH_BYTES];
|
||||||
|
|
||||||
|
// generate DMR LC
|
||||||
|
lc::LC dmrLC = lc::LC();
|
||||||
|
dmrLC.setFLCO(FLCO::GROUP);
|
||||||
|
dmrLC.setSrcId(data.getSrcId());
|
||||||
|
dmrLC.setDstId(data.getDstId());
|
||||||
|
|
||||||
|
// generate the Slot Type
|
||||||
|
SlotType slotType = SlotType();
|
||||||
|
slotType.setDataType(DataType::TERMINATOR_WITH_LC);
|
||||||
|
slotType.encode(buffer);
|
||||||
|
|
||||||
|
lc::FullLC fullLC = lc::FullLC();
|
||||||
|
fullLC.encode(dmrLC, buffer, DataType::TERMINATOR_WITH_LC);
|
||||||
|
|
||||||
|
// generate DMR network frame
|
||||||
|
data.setData(buffer);
|
||||||
|
|
||||||
|
writeDMR(data);
|
||||||
|
|
||||||
|
seqNo = 0;
|
||||||
|
dmrN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Protected Class Members
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Writes configuration to the network. */
|
||||||
|
|
||||||
|
bool PeerNetwork::writeConfig()
|
||||||
|
{
|
||||||
|
if (m_loginStreamId == 0U) {
|
||||||
|
LogWarning(LOG_NET, "BUGBUG: tried to write network authorisation with no stream ID?");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* software = __NETVER__;
|
||||||
|
|
||||||
|
json::object config = json::object();
|
||||||
|
|
||||||
|
// identity and frequency
|
||||||
|
config["identity"].set<std::string>(m_identity); // Identity
|
||||||
|
config["rxFrequency"].set<uint32_t>(m_rxFrequency); // Rx Frequency
|
||||||
|
config["txFrequency"].set<uint32_t>(m_txFrequency); // Tx Frequency
|
||||||
|
|
||||||
|
// system info
|
||||||
|
json::object sysInfo = json::object();
|
||||||
|
sysInfo["latitude"].set<float>(m_latitude); // Latitude
|
||||||
|
sysInfo["longitude"].set<float>(m_longitude); // Longitude
|
||||||
|
|
||||||
|
sysInfo["height"].set<int>(m_height); // Height
|
||||||
|
sysInfo["location"].set<std::string>(m_location); // Location
|
||||||
|
config["info"].set<json::object>(sysInfo);
|
||||||
|
|
||||||
|
// channel data
|
||||||
|
json::object channel = json::object();
|
||||||
|
channel["txPower"].set<uint32_t>(m_power); // Tx Power
|
||||||
|
channel["txOffsetMhz"].set<float>(m_txOffsetMhz); // Tx Offset (Mhz)
|
||||||
|
channel["chBandwidthKhz"].set<float>(m_chBandwidthKhz); // Ch. Bandwidth (khz)
|
||||||
|
channel["channelId"].set<uint8_t>(m_channelId); // Channel ID
|
||||||
|
channel["channelNo"].set<uint32_t>(m_channelNo); // Channel No
|
||||||
|
config["channel"].set<json::object>(channel);
|
||||||
|
|
||||||
|
// RCON
|
||||||
|
json::object rcon = json::object();
|
||||||
|
rcon["password"].set<std::string>(m_restApiPassword); // REST API Password
|
||||||
|
rcon["port"].set<uint16_t>(m_restApiPort); // REST API Port
|
||||||
|
config["rcon"].set<json::object>(rcon);
|
||||||
|
|
||||||
|
config["software"].set<std::string>(std::string(software)); // Software ID
|
||||||
|
|
||||||
|
json::value v = json::value(config);
|
||||||
|
std::string json = v.serialize();
|
||||||
|
|
||||||
|
CharArray __buffer = std::make_unique<char[]>(json.length() + 9U);
|
||||||
|
char* buffer = __buffer.get();
|
||||||
|
|
||||||
|
::memcpy(buffer + 0U, TAG_REPEATER_CONFIG, 4U);
|
||||||
|
::sprintf(buffer + 8U, "%s", json.c_str());
|
||||||
|
|
||||||
|
if (m_debug) {
|
||||||
|
Utils::dump(1U, "Network Message, Configuration", (uint8_t*)buffer, json.length() + 8U);
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeMaster({ NET_FUNC::RPTC, NET_SUBFUNC::NOP }, (uint8_t*)buffer, json.length() + 8U, pktSeq(), m_loginStreamId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Private Class Members
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Creates an P25 LDU1 frame message. */
|
||||||
|
|
||||||
|
UInt8Array PeerNetwork::createP25_LDU1Message_Raw(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
|
||||||
|
const uint8_t* data, p25::defines::FrameType::E frameType)
|
||||||
|
{
|
||||||
|
using namespace p25::defines;
|
||||||
|
using namespace p25::dfsi::defines;
|
||||||
|
assert(data != nullptr);
|
||||||
|
|
||||||
|
p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd);
|
||||||
|
|
||||||
|
uint8_t* buffer = new uint8_t[P25_LDU1_PACKET_LENGTH + PACKET_PAD];
|
||||||
|
::memset(buffer, 0x00U, P25_LDU1_PACKET_LENGTH + PACKET_PAD);
|
||||||
|
|
||||||
|
// construct P25 message header
|
||||||
|
createP25_MessageHdr(buffer, DUID::LDU1, control, lsd, frameType);
|
||||||
|
|
||||||
|
// pack DFSI data
|
||||||
|
uint32_t count = MSG_HDR_SIZE;
|
||||||
|
uint8_t imbe[RAW_IMBE_LENGTH_BYTES];
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE1);
|
||||||
|
::memcpy(imbe, data + 10U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 24U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE2);
|
||||||
|
::memcpy(imbe, data + 26U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 46U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE3);
|
||||||
|
::memcpy(imbe, data + 55U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 60U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE4);
|
||||||
|
::memcpy(imbe, data + 80U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 77U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE5);
|
||||||
|
::memcpy(imbe, data + 105U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 94U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE6);
|
||||||
|
::memcpy(imbe, data + 130U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 111U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE7);
|
||||||
|
::memcpy(imbe, data + 155U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 128U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE8);
|
||||||
|
::memcpy(imbe, data + 180U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 145U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE9);
|
||||||
|
::memcpy(imbe, data + 204U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU1(buffer + 162U, imbe);
|
||||||
|
count += DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
buffer[23U] = count;
|
||||||
|
|
||||||
|
if (m_debug)
|
||||||
|
Utils::dump(1U, "Network Message, P25 LDU1", buffer, (P25_LDU1_PACKET_LENGTH + PACKET_PAD));
|
||||||
|
|
||||||
|
length = (P25_LDU1_PACKET_LENGTH + PACKET_PAD);
|
||||||
|
return UInt8Array(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates an P25 LDU2 frame message. */
|
||||||
|
|
||||||
|
UInt8Array PeerNetwork::createP25_LDU2Message_Raw(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
|
||||||
|
const uint8_t* data)
|
||||||
|
{
|
||||||
|
using namespace p25::defines;
|
||||||
|
using namespace p25::dfsi::defines;
|
||||||
|
assert(data != nullptr);
|
||||||
|
|
||||||
|
p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd);
|
||||||
|
|
||||||
|
uint8_t* buffer = new uint8_t[P25_LDU2_PACKET_LENGTH + PACKET_PAD];
|
||||||
|
::memset(buffer, 0x00U, P25_LDU2_PACKET_LENGTH + PACKET_PAD);
|
||||||
|
|
||||||
|
// construct P25 message header
|
||||||
|
createP25_MessageHdr(buffer, DUID::LDU2, control, lsd, FrameType::DATA_UNIT);
|
||||||
|
|
||||||
|
// pack DFSI data
|
||||||
|
uint32_t count = MSG_HDR_SIZE;
|
||||||
|
uint8_t imbe[RAW_IMBE_LENGTH_BYTES];
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE10);
|
||||||
|
::memcpy(imbe, data + 10U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 24U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE11);
|
||||||
|
::memcpy(imbe, data + 26U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 46U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE12);
|
||||||
|
::memcpy(imbe, data + 55U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 60U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE13);
|
||||||
|
::memcpy(imbe, data + 80U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 77U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE14);
|
||||||
|
::memcpy(imbe, data + 105U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 94U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE15);
|
||||||
|
::memcpy(imbe, data + 130U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 111U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE16);
|
||||||
|
::memcpy(imbe, data + 155U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 128U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE17);
|
||||||
|
::memcpy(imbe, data + 180U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 145U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE18);
|
||||||
|
::memcpy(imbe, data + 204U, RAW_IMBE_LENGTH_BYTES);
|
||||||
|
dfsiLC.encodeLDU2(buffer + 162U, imbe);
|
||||||
|
count += DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
|
||||||
|
|
||||||
|
buffer[23U] = count;
|
||||||
|
|
||||||
|
if (m_debug)
|
||||||
|
Utils::dump(1U, "Network Message, P25 LDU2", buffer, (P25_LDU2_PACKET_LENGTH + PACKET_PAD));
|
||||||
|
|
||||||
|
length = (P25_LDU2_PACKET_LENGTH + PACKET_PAD);
|
||||||
|
return UInt8Array(buffer);
|
||||||
|
}
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - Bridge
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @defgroup bridge_network Networking
|
||||||
|
* @brief Implementation for the bridge networking.
|
||||||
|
* @ingroup bridge
|
||||||
|
*
|
||||||
|
* @file PeerNetwork.h
|
||||||
|
* @ingroup bridge_network
|
||||||
|
* @file PeerNetwork.cpp
|
||||||
|
* @ingroup bridge_network
|
||||||
|
*/
|
||||||
|
#if !defined(__PEER_NETWORK_H__)
|
||||||
|
#define __PEER_NETWORK_H__
|
||||||
|
|
||||||
|
#include "Defines.h"
|
||||||
|
#include "common/dmr/data/EmbeddedData.h"
|
||||||
|
#include "host/network/Network.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace network
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// Implements the core peer networking logic.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class HOST_SW_API PeerNetwork : public Network {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the PeerNetwork class.
|
||||||
|
* @param address Network Hostname/IP address to connect to.
|
||||||
|
* @param port Network port number.
|
||||||
|
* @param local
|
||||||
|
* @param peerId Unique ID on the network.
|
||||||
|
* @param password Network authentication password.
|
||||||
|
* @param duplex Flag indicating full-duplex operation.
|
||||||
|
* @param debug Flag indicating whether network debug is enabled.
|
||||||
|
* @param dmr Flag indicating whether DMR is enabled.
|
||||||
|
* @param p25 Flag indicating whether P25 is enabled.
|
||||||
|
* @param nxdn Flag indicating whether NXDN is enabled.
|
||||||
|
* @param slot1 Flag indicating whether DMR slot 1 is enabled for network traffic.
|
||||||
|
* @param slot2 Flag indicating whether DMR slot 2 is enabled for network traffic.
|
||||||
|
* @param allowActivityTransfer Flag indicating that the system activity logs will be sent to the network.
|
||||||
|
* @param allowDiagnosticTransfer Flag indicating that the system diagnostic logs will be sent to the network.
|
||||||
|
* @param updateLookup Flag indicating that the system will accept radio ID and talkgroup ID lookups from the network.
|
||||||
|
*/
|
||||||
|
PeerNetwork(const std::string& address, uint16_t port, uint16_t localPort, uint32_t peerId, const std::string& password,
|
||||||
|
bool duplex, bool debug, bool dmr, bool p25, bool nxdn, bool slot1, bool slot2, bool allowActivityTransfer, bool allowDiagnosticTransfer, bool updateLookup, bool saveLookup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes P25 LDU1 frame data to the network.
|
||||||
|
* @param[in] control Instance of p25::lc::LC containing link control data.
|
||||||
|
* @param[in] lsd Instance of p25::data::LowSpeedData containing low speed data.
|
||||||
|
* @param[in] data Buffer containing P25 LDU1 data to send.
|
||||||
|
* @param[in] frameType DVM P25 frame type.
|
||||||
|
* @returns bool True, if message was sent, otherwise false.
|
||||||
|
*/
|
||||||
|
bool writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data,
|
||||||
|
p25::defines::FrameType::E frameType) override;
|
||||||
|
/**
|
||||||
|
* @brief Writes P25 LDU2 frame data to the network.
|
||||||
|
* @param[in] control Instance of p25::lc::LC containing link control data.
|
||||||
|
* @param[in] lsd Instance of p25::data::LowSpeedData containing low speed data.
|
||||||
|
* @param[in] data Buffer containing P25 LDU2 data to send.
|
||||||
|
* @returns bool True, if message was sent, otherwise false.
|
||||||
|
*/
|
||||||
|
bool writeP25LDU2(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to send a DMR terminator with LC message.
|
||||||
|
* @param data
|
||||||
|
* @param seqNo
|
||||||
|
* @param dmrN
|
||||||
|
* @param embeddedData
|
||||||
|
*/
|
||||||
|
void writeDMRTerminator(dmr::data::NetData& data, uint32_t* seqNo, uint8_t* dmrN, dmr::data::EmbeddedData& embeddedData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Writes configuration to the network.
|
||||||
|
* @returns bool True, if configuration was sent, otherwise false.
|
||||||
|
*/
|
||||||
|
bool writeConfig() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Creates an P25 LDU1 frame message.
|
||||||
|
*
|
||||||
|
* The data packed into a P25 LDU1 frame message is near standard DFSI messaging, just instead of
|
||||||
|
* 9 individual frames, they are packed into a single message one right after another.
|
||||||
|
*
|
||||||
|
* @param[out] length Length of network message buffer.
|
||||||
|
* @param[in] control Instance of p25::lc::LC containing link control data.
|
||||||
|
* @param[in] lsd Instance of p25::data::LowSpeedData containing low speed data.
|
||||||
|
* @param[in] data Buffer containing P25 LDU1 data to send.
|
||||||
|
* @param[in] frameType DVM P25 frame type.
|
||||||
|
* @returns UInt8Array Buffer containing the built network message.
|
||||||
|
*/
|
||||||
|
UInt8Array createP25_LDU1Message_Raw(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
|
||||||
|
const uint8_t* data, p25::defines::FrameType::E frameType);
|
||||||
|
/**
|
||||||
|
* @brief Creates an P25 LDU2 frame message.
|
||||||
|
*
|
||||||
|
* The data packed into a P25 LDU2 frame message is near standard DFSI messaging, just instead of
|
||||||
|
* 9 individual frames, they are packed into a single message one right after another.
|
||||||
|
*
|
||||||
|
* @param[out] length Length of network message buffer.
|
||||||
|
* @param[in] control Instance of p25::lc::LC containing link control data.
|
||||||
|
* @param[in] lsd Instance of p25::data::LowSpeedData containing low speed data.
|
||||||
|
* @param[in] data Buffer containing P25 LDU2 data to send.
|
||||||
|
* @returns UInt8Array Buffer containing the built network message.
|
||||||
|
*/
|
||||||
|
UInt8Array createP25_LDU2Message_Raw(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
|
||||||
|
const uint8_t* data);
|
||||||
|
};
|
||||||
|
} // namespace network
|
||||||
|
|
||||||
|
#endif // __PEER_NETWORK_H__
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#/*
|
||||||
|
# * Digital Voice Modem - Remote Command Client
|
||||||
|
# * GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
# * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
# *
|
||||||
|
# * Copyright (C) 2024 Bryan Biedenkapp, N2PLL
|
||||||
|
# *
|
||||||
|
# */
|
||||||
|
file(GLOB vocoder_SRC
|
||||||
|
"src/vocoder/imbe/*.cpp"
|
||||||
|
"src/vocoder/*.cpp"
|
||||||
|
"src/vocoder/*.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
file(GLOB vocoder_INCLUDE
|
||||||
|
"src/vocoder/imbe/*.h"
|
||||||
|
"src/vocoder/*.h"
|
||||||
|
)
|
||||||
@ -0,0 +1,316 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Doug McLain
|
||||||
|
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "common/edac/Golay24128.h"
|
||||||
|
#include "vocoder/MBEDecoder.h"
|
||||||
|
|
||||||
|
using namespace edac;
|
||||||
|
using namespace vocoder;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const int MBEDecoder::dW[72] = { 0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,3,2,1,0,0,3,3, };
|
||||||
|
|
||||||
|
const int MBEDecoder::dX[72] = { 10,22,11,9,10,22,11,23,8,20,9,21,10,8,9,21,8,6,7,19,8,20,9,7,6,18,7,5,6,18,7,19,4,16,5,17,6,4,5,17,4,2,3,15,4,16,5,3,2,14,3,1,2,14,3,15,0,12,1,13,2,0,1,13,0,12,10,11,0,12,1,13, };
|
||||||
|
|
||||||
|
const int MBEDecoder::rW[36] = {
|
||||||
|
0, 1, 0, 1, 0, 1,
|
||||||
|
0, 1, 0, 1, 0, 1,
|
||||||
|
0, 1, 0, 1, 0, 1,
|
||||||
|
0, 1, 0, 1, 0, 2,
|
||||||
|
0, 2, 0, 2, 0, 2,
|
||||||
|
0, 2, 0, 2, 0, 2
|
||||||
|
};
|
||||||
|
|
||||||
|
const int MBEDecoder::rX[36] = {
|
||||||
|
23, 10, 22, 9, 21, 8,
|
||||||
|
20, 7, 19, 6, 18, 5,
|
||||||
|
17, 4, 16, 3, 15, 2,
|
||||||
|
14, 1, 13, 0, 12, 10,
|
||||||
|
11, 9, 10, 8, 9, 7,
|
||||||
|
8, 6, 7, 5, 6, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
// bit 0
|
||||||
|
const int MBEDecoder::rY[36] = {
|
||||||
|
0, 2, 0, 2, 0, 2,
|
||||||
|
0, 2, 0, 3, 0, 3,
|
||||||
|
1, 3, 1, 3, 1, 3,
|
||||||
|
1, 3, 1, 3, 1, 3,
|
||||||
|
1, 3, 1, 3, 1, 3,
|
||||||
|
1, 3, 1, 3, 1, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
const int MBEDecoder::rZ[36] = {
|
||||||
|
5, 3, 4, 2, 3, 1,
|
||||||
|
2, 0, 1, 13, 0, 12,
|
||||||
|
22, 11, 21, 10, 20, 9,
|
||||||
|
19, 8, 18, 7, 17, 6,
|
||||||
|
16, 5, 15, 4, 14, 3,
|
||||||
|
13, 2, 12, 1, 11, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Public Class Members
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Initializes a new instance of the MBEDecoder class. */
|
||||||
|
|
||||||
|
MBEDecoder::MBEDecoder(MBE_DECODER_MODE mode) :
|
||||||
|
m_mbelibParms(NULL),
|
||||||
|
m_mbeMode(mode),
|
||||||
|
m_gainAdjust(1.0f)
|
||||||
|
{
|
||||||
|
m_mbelibParms = new mbelibParms();
|
||||||
|
mbe_initMbeParms(m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced);
|
||||||
|
|
||||||
|
::memset(gainMaxBuf, 0, sizeof(float) * 200);
|
||||||
|
gainMaxBufPtr = gainMaxBuf;
|
||||||
|
gainMaxIdx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalizes a instance of the MBEDecoder class. */
|
||||||
|
|
||||||
|
MBEDecoder::~MBEDecoder()
|
||||||
|
{
|
||||||
|
delete m_mbelibParms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decodes the given MBE codewords to deinterleaved MBE bits using the decoder mode. */
|
||||||
|
|
||||||
|
int32_t MBEDecoder::decodeBits(uint8_t* codeword, char* mbeBits)
|
||||||
|
{
|
||||||
|
int32_t errs = 0;
|
||||||
|
float samples[160U];
|
||||||
|
::memset(samples, 0x00U, 160U * sizeof(float));
|
||||||
|
|
||||||
|
switch (m_mbeMode)
|
||||||
|
{
|
||||||
|
case DECODE_DMR_AMBE:
|
||||||
|
{
|
||||||
|
char ambe_d[49U];
|
||||||
|
char ambe_fr[4][24];
|
||||||
|
::memset(ambe_d, 0x00U, 49U);
|
||||||
|
::memset(ambe_fr, 0x00U, 96U);
|
||||||
|
|
||||||
|
const int* w, *x, *y, *z;
|
||||||
|
|
||||||
|
w = rW;
|
||||||
|
x = rX;
|
||||||
|
y = rY;
|
||||||
|
z = rZ;
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
for (int j = 0; j < 8; j += 2) {
|
||||||
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
||||||
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
||||||
|
w++;
|
||||||
|
x++;
|
||||||
|
y++;
|
||||||
|
z++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = mbe_eccAmbe3600x2450C0(ambe_fr);
|
||||||
|
mbe_demodulateAmbe3600x2450Data(ambe_fr);
|
||||||
|
|
||||||
|
errs += mbe_eccAmbe3600x2450Data(ambe_fr, ambe_d);
|
||||||
|
|
||||||
|
::memcpy(mbeBits, ambe_d, 49U);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DECODE_88BIT_IMBE:
|
||||||
|
{
|
||||||
|
char imbe_d[88U];
|
||||||
|
::memset(imbe_d, 0x00U, 88U);
|
||||||
|
|
||||||
|
for (int i = 0; i < 11; ++i) {
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::memcpy(mbeBits, imbe_d, 88U);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
||||||
|
|
||||||
|
int32_t MBEDecoder::decodeF(uint8_t* codeword, float samples[])
|
||||||
|
{
|
||||||
|
int32_t errs = 0;
|
||||||
|
switch (m_mbeMode)
|
||||||
|
{
|
||||||
|
case DECODE_DMR_AMBE:
|
||||||
|
{
|
||||||
|
char ambe_d[49U];
|
||||||
|
char ambe_fr[4][24];
|
||||||
|
::memset(ambe_d, 0x00U, 49U);
|
||||||
|
::memset(ambe_fr, 0x00U, 96U);
|
||||||
|
|
||||||
|
const int* w, *x, *y, *z;
|
||||||
|
|
||||||
|
w = rW;
|
||||||
|
x = rX;
|
||||||
|
y = rY;
|
||||||
|
z = rZ;
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
for (int j = 0; j < 8; j += 2) {
|
||||||
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
||||||
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
||||||
|
w++;
|
||||||
|
x++;
|
||||||
|
y++;
|
||||||
|
z++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ambeErrs;
|
||||||
|
char ambeErrStr[64U];
|
||||||
|
::memset(ambeErrStr, 0x20U, 64U);
|
||||||
|
|
||||||
|
mbe_processAmbe3600x2450FrameF(samples, &ambeErrs, &errs, ambeErrStr, ambe_fr, ambe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DECODE_88BIT_IMBE:
|
||||||
|
{
|
||||||
|
char imbe_d[88U];
|
||||||
|
::memset(imbe_d, 0x00U, 88U);
|
||||||
|
|
||||||
|
for (int i = 0; i < 11; ++i) {
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ambeErrs;
|
||||||
|
char ambeErrStr[64U];
|
||||||
|
::memset(ambeErrStr, 0x20U, 64U);
|
||||||
|
|
||||||
|
mbe_processImbe4400DataF(samples, &ambeErrs, &errs, ambeErrStr, imbe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
||||||
|
|
||||||
|
int32_t MBEDecoder::decode(uint8_t* codeword, int16_t samples[])
|
||||||
|
{
|
||||||
|
float samplesF[160U];
|
||||||
|
::memset(samplesF, 0x00U, 160U * sizeof(float));
|
||||||
|
int32_t errs = decodeF(codeword, samplesF);
|
||||||
|
|
||||||
|
float* sampleFPtr = samplesF;
|
||||||
|
if (m_autoGain) {
|
||||||
|
// detect max level
|
||||||
|
float max = 0.0f;
|
||||||
|
for (int n = 0; n < 160; n++) {
|
||||||
|
float out = fabsf(*sampleFPtr);
|
||||||
|
if (out > max) {
|
||||||
|
max = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sampleFPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*gainMaxBufPtr = max;
|
||||||
|
gainMaxBufPtr++;
|
||||||
|
gainMaxIdx++;
|
||||||
|
|
||||||
|
if (gainMaxIdx > 24) {
|
||||||
|
gainMaxIdx = 0;
|
||||||
|
gainMaxBufPtr = gainMaxBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup max history
|
||||||
|
for (int i = 0; i < 25; i++) {
|
||||||
|
float a = gainMaxBuf[i];
|
||||||
|
if (a > max) {
|
||||||
|
max = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine optimal gain level
|
||||||
|
float gainFactor = 0.0f, gainDelta = 0.0f;
|
||||||
|
if (max > static_cast<float>(0)) {
|
||||||
|
gainFactor = (static_cast<float>(30000) / max);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gainFactor = static_cast<float>(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gainFactor < m_gainAdjust) {
|
||||||
|
m_gainAdjust = gainFactor;
|
||||||
|
gainDelta = static_cast<float>(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (gainFactor > static_cast<float>(50)) {
|
||||||
|
gainFactor = static_cast<float>(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
gainDelta = gainFactor - m_gainAdjust;
|
||||||
|
|
||||||
|
if (gainDelta > (static_cast<float>(0.05) * m_gainAdjust)) {
|
||||||
|
gainDelta = (static_cast<float>(0.05) * m_gainAdjust);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gainDelta /= static_cast<float>(160);
|
||||||
|
|
||||||
|
// adjust output gain
|
||||||
|
sampleFPtr = samplesF;
|
||||||
|
for (int n = 0; n < 160; n++) {
|
||||||
|
*sampleFPtr = (m_gainAdjust + (static_cast<float>(n) * gainDelta)) * (*sampleFPtr);
|
||||||
|
sampleFPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gainAdjust += (static_cast<float>(160) * gainDelta);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t* samplePtr = samples;
|
||||||
|
sampleFPtr = samplesF;
|
||||||
|
for (int n = 0; n < 160; n++) {
|
||||||
|
float smp = *sampleFPtr;
|
||||||
|
if (!m_autoGain) {
|
||||||
|
smp *= m_gainAdjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
// audio clipping
|
||||||
|
if (smp > 32760) {
|
||||||
|
smp = 32760;
|
||||||
|
}
|
||||||
|
else if (smp < -32760) {
|
||||||
|
smp = -32760;
|
||||||
|
}
|
||||||
|
|
||||||
|
*samplePtr = (int16_t)(smp);
|
||||||
|
|
||||||
|
samplePtr++;
|
||||||
|
sampleFPtr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs;
|
||||||
|
}
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Doug McLain
|
||||||
|
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file MBEDecoder.h
|
||||||
|
* @ingroup vocoder
|
||||||
|
* @file MBEDecoder.cpp
|
||||||
|
* @ingroup vocoder
|
||||||
|
*/
|
||||||
|
#if !defined(__MBE_DECODER_H__)
|
||||||
|
#define __MBE_DECODER_H__
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "mbe.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "common/Defines.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace vocoder
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Structure Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct mbelibParms
|
||||||
|
{
|
||||||
|
mbe_parms* m_cur_mp;
|
||||||
|
mbe_parms* m_prev_mp;
|
||||||
|
mbe_parms* m_prev_mp_enhanced;
|
||||||
|
|
||||||
|
/// <summary></summary>
|
||||||
|
mbelibParms()
|
||||||
|
{
|
||||||
|
m_cur_mp = (mbe_parms*)malloc(sizeof(mbe_parms));
|
||||||
|
m_prev_mp = (mbe_parms*)malloc(sizeof(mbe_parms));
|
||||||
|
m_prev_mp_enhanced = (mbe_parms*)malloc(sizeof(mbe_parms));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary></summary>
|
||||||
|
~mbelibParms()
|
||||||
|
{
|
||||||
|
free(m_prev_mp_enhanced);
|
||||||
|
free(m_prev_mp);
|
||||||
|
free(m_cur_mp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vocoder Decoding Mode
|
||||||
|
*/
|
||||||
|
enum MBE_DECODER_MODE {
|
||||||
|
DECODE_DMR_AMBE, //! DMR AMBE
|
||||||
|
DECODE_88BIT_IMBE //! 88-bit IMBE (P25)
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implements MBE audio decoding.
|
||||||
|
*/
|
||||||
|
class HOST_SW_API MBEDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the MBEDecoder class.
|
||||||
|
* @param mode Decoder mode.
|
||||||
|
*/
|
||||||
|
MBEDecoder(MBE_DECODER_MODE mode);
|
||||||
|
/**
|
||||||
|
* @brief Finalizes a instance of the MBEDecoder class.
|
||||||
|
*/
|
||||||
|
~MBEDecoder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decodes the given MBE codewords to deinterleaved MBE bits using the decoder mode.
|
||||||
|
* @param[in] codeword MBE codeword.
|
||||||
|
* @param[out] mbeBits
|
||||||
|
* @returns int32_t
|
||||||
|
*/
|
||||||
|
int32_t decodeBits(uint8_t* codeword, char* mbeBits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decodes the given MBE codewords to PCM samples using the decoder mode.
|
||||||
|
* @param[in] codeword MBE codeword.
|
||||||
|
* @param[out] samples PCM Samples (in float format).
|
||||||
|
* @returns int32_t
|
||||||
|
*/
|
||||||
|
int32_t decodeF(uint8_t* codeword, float samples[]);
|
||||||
|
/**
|
||||||
|
* @brief Decodes the given MBE codewords to PCM samples using the decoder mode.
|
||||||
|
* @param[in] codeword MBE codeword.
|
||||||
|
* @param[out] samples PCM Samples (in short format).
|
||||||
|
* @returns int32_t
|
||||||
|
*/
|
||||||
|
int32_t decode(uint8_t* codeword, int16_t samples[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mbelibParms* m_mbelibParms;
|
||||||
|
|
||||||
|
MBE_DECODER_MODE m_mbeMode;
|
||||||
|
|
||||||
|
static const int dW[72];
|
||||||
|
static const int dX[72];
|
||||||
|
static const int rW[36];
|
||||||
|
static const int rX[36];
|
||||||
|
static const int rY[36];
|
||||||
|
static const int rZ[36];
|
||||||
|
|
||||||
|
float gainMaxBuf[200];
|
||||||
|
float* gainMaxBufPtr;
|
||||||
|
int gainMaxIdx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Gain adjustment.
|
||||||
|
*/
|
||||||
|
__PROPERTY(float, gainAdjust, GainAdjust);
|
||||||
|
/**
|
||||||
|
* @brief Flag indicating automatic gain adjustment is enabled.
|
||||||
|
*/
|
||||||
|
__PROPERTY(bool, autoGain, AutoGain);
|
||||||
|
};
|
||||||
|
} // namespace vocoder
|
||||||
|
|
||||||
|
#endif // __MBE_DECODER_H__
|
||||||
@ -0,0 +1,718 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Doug McLain
|
||||||
|
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AMBE halfrate encoder - Copyright 2016 Max H. Parke KA1RBI
|
||||||
|
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
|
||||||
|
*
|
||||||
|
* This file is part of OP25 and 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/Defines.h"
|
||||||
|
#include "common/edac/AMBEFEC.h"
|
||||||
|
#include "common/edac/Golay24128.h"
|
||||||
|
#include "common/Utils.h"
|
||||||
|
#include "vocoder/MBEEncoder.h"
|
||||||
|
#include "vocoder/ambe3600x2450_const.h"
|
||||||
|
#include "vocoder/ambe3600x2400_const.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace edac;
|
||||||
|
using namespace vocoder;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4244)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static const short b0_lookup[] = {
|
||||||
|
0, 0, 0, 1, 1, 2, 2, 2,
|
||||||
|
3, 3, 4, 4, 4, 5, 5, 5,
|
||||||
|
6, 6, 7, 7, 7, 8, 8, 8,
|
||||||
|
9, 9, 9, 10, 10, 11, 11, 11,
|
||||||
|
12, 12, 12, 13, 13, 13, 14, 14,
|
||||||
|
14, 15, 15, 15, 16, 16, 16, 17,
|
||||||
|
17, 17, 17, 18, 18, 18, 19, 19,
|
||||||
|
19, 20, 20, 20, 21, 21, 21, 21,
|
||||||
|
22, 22, 22, 23, 23, 23, 24, 24,
|
||||||
|
24, 24, 25, 25, 25, 25, 26, 26,
|
||||||
|
26, 27, 27, 27, 27, 28, 28, 28,
|
||||||
|
29, 29, 29, 29, 30, 30, 30, 30,
|
||||||
|
31, 31, 31, 31, 31, 32, 32, 32,
|
||||||
|
32, 33, 33, 33, 33, 34, 34, 34,
|
||||||
|
34, 35, 35, 35, 35, 36, 36, 36,
|
||||||
|
36, 37, 37, 37, 37, 38, 38, 38,
|
||||||
|
38, 38, 39, 39, 39, 39, 40, 40,
|
||||||
|
40, 40, 40, 41, 41, 41, 41, 42,
|
||||||
|
42, 42, 42, 42, 43, 43, 43, 43,
|
||||||
|
43, 44, 44, 44, 44, 45, 45, 45,
|
||||||
|
45, 45, 46, 46, 46, 46, 46, 47,
|
||||||
|
47, 47, 47, 47, 48, 48, 48, 48,
|
||||||
|
48, 49, 49, 49, 49, 49, 49, 50,
|
||||||
|
50, 50, 50, 50, 51, 51, 51, 51,
|
||||||
|
51, 52, 52, 52, 52, 52, 52, 53,
|
||||||
|
53, 53, 53, 53, 54, 54, 54, 54,
|
||||||
|
54, 54, 55, 55, 55, 55, 55, 56,
|
||||||
|
56, 56, 56, 56, 56, 57, 57, 57,
|
||||||
|
57, 57, 57, 58, 58, 58, 58, 58,
|
||||||
|
58, 59, 59, 59, 59, 59, 59, 60,
|
||||||
|
60, 60, 60, 60, 60, 61, 61, 61,
|
||||||
|
61, 61, 61, 62, 62, 62, 62, 62,
|
||||||
|
62, 63, 63, 63, 63, 63, 63, 63,
|
||||||
|
64, 64, 64, 64, 64, 64, 65, 65,
|
||||||
|
65, 65, 65, 65, 65, 66, 66, 66,
|
||||||
|
66, 66, 66, 67, 67, 67, 67, 67,
|
||||||
|
67, 67, 68, 68, 68, 68, 68, 68,
|
||||||
|
68, 69, 69, 69, 69, 69, 69, 69,
|
||||||
|
70, 70, 70, 70, 70, 70, 70, 71,
|
||||||
|
71, 71, 71, 71, 71, 71, 72, 72,
|
||||||
|
72, 72, 72, 72, 72, 73, 73, 73,
|
||||||
|
73, 73, 73, 73, 73, 74, 74, 74,
|
||||||
|
74, 74, 74, 74, 75, 75, 75, 75,
|
||||||
|
75, 75, 75, 75, 76, 76, 76, 76,
|
||||||
|
76, 76, 76, 76, 77, 77, 77, 77,
|
||||||
|
77, 77, 77, 77, 77, 78, 78, 78,
|
||||||
|
78, 78, 78, 78, 78, 79, 79, 79,
|
||||||
|
79, 79, 79, 79, 79, 80, 80, 80,
|
||||||
|
80, 80, 80, 80, 80, 81, 81, 81,
|
||||||
|
81, 81, 81, 81, 81, 81, 82, 82,
|
||||||
|
82, 82, 82, 82, 82, 82, 83, 83,
|
||||||
|
83, 83, 83, 83, 83, 83, 83, 84,
|
||||||
|
84, 84, 84, 84, 84, 84, 84, 84,
|
||||||
|
85, 85, 85, 85, 85, 85, 85, 85,
|
||||||
|
85, 86, 86, 86, 86, 86, 86, 86,
|
||||||
|
86, 86, 87, 87, 87, 87, 87, 87,
|
||||||
|
87, 87, 87, 88, 88, 88, 88, 88,
|
||||||
|
88, 88, 88, 88, 89, 89, 89, 89,
|
||||||
|
89, 89, 89, 89, 89, 89, 90, 90,
|
||||||
|
90, 90, 90, 90, 90, 90, 90, 90,
|
||||||
|
91, 91, 91, 91, 91, 91, 91, 91,
|
||||||
|
91, 92, 92, 92, 92, 92, 92, 92,
|
||||||
|
92, 92, 92, 93, 93, 93, 93, 93,
|
||||||
|
93, 93, 93, 93, 93, 94, 94, 94,
|
||||||
|
94, 94, 94, 94, 94, 94, 94, 94,
|
||||||
|
95, 95, 95, 95, 95, 95, 95, 95,
|
||||||
|
95, 95, 96, 96, 96, 96, 96, 96,
|
||||||
|
96, 96, 96, 96, 96, 97, 97, 97,
|
||||||
|
97, 97, 97, 97, 97, 97, 97, 98,
|
||||||
|
98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
|
98, 98, 99, 99, 99, 99, 99, 99,
|
||||||
|
99, 99, 99, 99, 99, 99, 100, 100,
|
||||||
|
100, 100, 100, 100, 100, 100, 100, 100,
|
||||||
|
100, 101, 101, 101, 101, 101, 101, 101,
|
||||||
|
101, 101, 101, 101, 102, 102, 102, 102,
|
||||||
|
102, 102, 102, 102, 102, 102, 102, 102,
|
||||||
|
103, 103, 103, 103, 103, 103, 103, 103,
|
||||||
|
103, 103, 103, 103, 104, 104, 104, 104,
|
||||||
|
104, 104, 104, 104, 104, 104, 104, 104,
|
||||||
|
105, 105, 105, 105, 105, 105, 105, 105,
|
||||||
|
105, 105, 105, 105, 106, 106, 106, 106,
|
||||||
|
106, 106, 106, 106, 106, 106, 106, 106,
|
||||||
|
107, 107, 107, 107, 107, 107, 107, 107,
|
||||||
|
107, 107, 107, 107, 107, 108, 108, 108,
|
||||||
|
108, 108, 108, 108, 108, 108, 108, 108,
|
||||||
|
108, 109, 109, 109, 109, 109, 109, 109,
|
||||||
|
109, 109, 109, 109, 109, 109, 110, 110,
|
||||||
|
110, 110, 110, 110, 110, 110, 110, 110,
|
||||||
|
110, 110, 110, 111, 111, 111, 111, 111,
|
||||||
|
111, 111, 111, 111, 111, 111, 111, 111,
|
||||||
|
112, 112, 112, 112, 112, 112, 112, 112,
|
||||||
|
112, 112, 112, 112, 112, 112, 113, 113,
|
||||||
|
113, 113, 113, 113, 113, 113, 113, 113,
|
||||||
|
113, 113, 113, 113, 114, 114, 114, 114,
|
||||||
|
114, 114, 114, 114, 114, 114, 114, 114,
|
||||||
|
114, 115, 115, 115, 115, 115, 115, 115,
|
||||||
|
115, 115, 115, 115, 115, 115, 115, 116,
|
||||||
|
116, 116, 116, 116, 116, 116, 116, 116,
|
||||||
|
116, 116, 116, 116, 116, 116, 117, 117,
|
||||||
|
117, 117, 117, 117, 117, 117, 117, 117,
|
||||||
|
117, 117, 117, 117, 118, 118, 118, 118,
|
||||||
|
118, 118, 118, 118, 118, 118, 118, 118,
|
||||||
|
118, 118, 118, 119, 119, 119, 119, 119,
|
||||||
|
119, 119, 119
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param[in] imbe_param
|
||||||
|
* @param b
|
||||||
|
* @param cur_mp Current MBE parameters.
|
||||||
|
* @param prev_mp Previous MBE parameters.
|
||||||
|
* @param gainAdjust Gain adjustment.
|
||||||
|
*/
|
||||||
|
static void encodeAMBE(const IMBE_PARAM* imbe_param, int b[], mbe_parms* cur_mp, mbe_parms* prev_mp, float gainAdjust)
|
||||||
|
{
|
||||||
|
static const float SQRT_2 = sqrtf(2.0);
|
||||||
|
static const int b0_lmax = sizeof(b0_lookup) / sizeof(b0_lookup[0]);
|
||||||
|
// int b[9];
|
||||||
|
|
||||||
|
// ref_pitch is Q8_8 in range 19.875 - 123.125
|
||||||
|
int b0_i = (imbe_param->ref_pitch >> 5) - 159;
|
||||||
|
if (b0_i < 0 || b0_i > b0_lmax) {
|
||||||
|
fprintf(stderr, "encode error b0_i %d\n", b0_i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
b[0] = b0_lookup[b0_i];
|
||||||
|
int L = (int)AmbeLtable[b[0]];
|
||||||
|
|
||||||
|
// adjust b0 until L agrees
|
||||||
|
while (L != imbe_param->num_harms) {
|
||||||
|
if (L < imbe_param->num_harms)
|
||||||
|
b0_i++;
|
||||||
|
else if (L > imbe_param->num_harms)
|
||||||
|
b0_i--;
|
||||||
|
if (b0_i < 0 || b0_i > b0_lmax) {
|
||||||
|
fprintf(stderr, "encode error2 b0_i %d\n", b0_i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
b[0] = b0_lookup[b0_i];
|
||||||
|
L = (int)AmbeLtable[b[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
float m_float2[NUM_HARMS_MAX];
|
||||||
|
for (int l = 1; l <= L; l++) {
|
||||||
|
m_float2[l - 1] = (float)imbe_param->sa[l - 1];
|
||||||
|
m_float2[l - 1] = m_float2[l - 1] * m_float2[l - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
float en_min = 0;
|
||||||
|
b[1] = 0;
|
||||||
|
int vuv_max = 17;
|
||||||
|
for (int n = 0; n < vuv_max; n++) {
|
||||||
|
float En = 0;
|
||||||
|
for (int l = 1; l <= L; l++) {
|
||||||
|
int jl = (int)((float)l * (float)16.0 * AmbeW0table[b[0]]);
|
||||||
|
int kl = 12;
|
||||||
|
if (l <= 36)
|
||||||
|
kl = (l + 2) / 3;
|
||||||
|
|
||||||
|
if (imbe_param->v_uv_dsn[(kl - 1) * 3] != AmbeVuv[n][jl])
|
||||||
|
En += m_float2[l - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
en_min = En;
|
||||||
|
else if (En < en_min) {
|
||||||
|
b[1] = n;
|
||||||
|
en_min = En;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// log spectral amplitudes
|
||||||
|
float num_harms_f = (float)imbe_param->num_harms;
|
||||||
|
float log_l_2 = 0.5 * log2f(num_harms_f); // fixme: table lookup
|
||||||
|
float log_l_w0 = 0.5 * log2f(num_harms_f * AmbeW0table[b[0]] * 2.0 * M_PI) + 2.289;
|
||||||
|
float lsa[NUM_HARMS_MAX];
|
||||||
|
float lsa_sum = 0.0;
|
||||||
|
|
||||||
|
for (int i1 = 0; i1 < imbe_param->num_harms; i1++) {
|
||||||
|
float sa = (float)imbe_param->sa[i1];
|
||||||
|
if (sa < 1) sa = 1.0;
|
||||||
|
if (imbe_param->v_uv_dsn[i1])
|
||||||
|
lsa[i1] = log_l_2 + log2f(sa);
|
||||||
|
else
|
||||||
|
lsa[i1] = log_l_w0 + log2f(sa);
|
||||||
|
lsa_sum += lsa[i1];
|
||||||
|
}
|
||||||
|
|
||||||
|
float gain = lsa_sum / num_harms_f;
|
||||||
|
float diff_gain = gain - 0.5 * prev_mp->gamma;
|
||||||
|
|
||||||
|
diff_gain -= gainAdjust;
|
||||||
|
|
||||||
|
float error;
|
||||||
|
int error_index;
|
||||||
|
int max_dg = 32;
|
||||||
|
for (int i1 = 0; i1 < max_dg; i1++) {
|
||||||
|
float diff = fabsf(diff_gain - AmbeDg[i1]);
|
||||||
|
if ((i1 == 0) || (diff < error)) {
|
||||||
|
error = diff;
|
||||||
|
error_index = i1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b[2] = error_index;
|
||||||
|
|
||||||
|
// prediction residuals
|
||||||
|
float l_prev_l = (float)(prev_mp->L) / num_harms_f;
|
||||||
|
float tmp_s = 0.0;
|
||||||
|
prev_mp->log2Ml[0] = prev_mp->log2Ml[1];
|
||||||
|
for (int i1 = 0; i1 < imbe_param->num_harms; i1++) {
|
||||||
|
float kl = l_prev_l * (float)(i1 + 1);
|
||||||
|
int kl_floor = (int)kl;
|
||||||
|
float kl_frac = kl - kl_floor;
|
||||||
|
tmp_s += (1.0 - kl_frac) * prev_mp->log2Ml[kl_floor + 0] + kl_frac * prev_mp->log2Ml[kl_floor + 1 + 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
float T[NUM_HARMS_MAX];
|
||||||
|
for (int i1 = 0; i1 < imbe_param->num_harms; i1++) {
|
||||||
|
float kl = l_prev_l * (float)(i1 + 1);
|
||||||
|
int kl_floor = (int)kl;
|
||||||
|
float kl_frac = kl - kl_floor;
|
||||||
|
T[i1] = lsa[i1] - 0.65 * (1.0 - kl_frac) * prev_mp->log2Ml[kl_floor + 0] \
|
||||||
|
- 0.65 * kl_frac * prev_mp->log2Ml[kl_floor + 1 + 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// DCT
|
||||||
|
const int* J = AmbeLmprbl[imbe_param->num_harms];
|
||||||
|
float* c[4];
|
||||||
|
int acc = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
c[i] = &T[acc];
|
||||||
|
acc += J[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
float C[4][17];
|
||||||
|
for (int i = 1; i <= 4; i++) {
|
||||||
|
for (int k = 1; k <= J[i - 1]; k++) {
|
||||||
|
float s = 0.0;
|
||||||
|
for (int j = 1; j <= J[i - 1]; j++) {
|
||||||
|
//fixme: lut?
|
||||||
|
s += (c[i - 1][j - 1] * cosf((M_PI * (((float)k) - 1.0) * (((float)j) - 0.5)) / (float)J[i - 1]));
|
||||||
|
}
|
||||||
|
C[i - 1][k - 1] = s / (float)J[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float R[8];
|
||||||
|
R[0] = C[0][0] + SQRT_2 * C[0][1];
|
||||||
|
R[1] = C[0][0] - SQRT_2 * C[0][1];
|
||||||
|
R[2] = C[1][0] + SQRT_2 * C[1][1];
|
||||||
|
R[3] = C[1][0] - SQRT_2 * C[1][1];
|
||||||
|
R[4] = C[2][0] + SQRT_2 * C[2][1];
|
||||||
|
R[5] = C[2][0] - SQRT_2 * C[2][1];
|
||||||
|
R[6] = C[3][0] + SQRT_2 * C[3][1];
|
||||||
|
R[7] = C[3][0] - SQRT_2 * C[3][1];
|
||||||
|
|
||||||
|
// encode PRBA
|
||||||
|
float G[8];
|
||||||
|
for (int m = 1; m <= 8; m++) {
|
||||||
|
G[m - 1] = 0.0;
|
||||||
|
for (int i = 1; i <= 8; i++) {
|
||||||
|
//fixme: lut?
|
||||||
|
G[m - 1] += (R[i - 1] * cosf((M_PI * (((float)m) - 1.0) * (((float)i) - 0.5)) / 8.0));
|
||||||
|
}
|
||||||
|
G[m - 1] /= 8.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 512; i++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
|
||||||
|
diff = G[1] - AmbePRBA24[i][0];
|
||||||
|
err += (diff * diff);
|
||||||
|
diff = G[2] - AmbePRBA24[i][1];
|
||||||
|
err += (diff * diff);
|
||||||
|
diff = G[3] - AmbePRBA24[i][2];
|
||||||
|
err += (diff * diff);
|
||||||
|
|
||||||
|
if (i == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b[3] = error_index;
|
||||||
|
|
||||||
|
// PRBA58
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
|
||||||
|
diff = G[4] - AmbePRBA58[i][0];
|
||||||
|
err += (diff * diff);
|
||||||
|
diff = G[5] - AmbePRBA58[i][1];
|
||||||
|
err += (diff * diff);
|
||||||
|
diff = G[6] - AmbePRBA58[i][2];
|
||||||
|
err += (diff * diff);
|
||||||
|
diff = G[7] - AmbePRBA58[i][3];
|
||||||
|
err += (diff * diff);
|
||||||
|
|
||||||
|
if (i == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b[4] = error_index;
|
||||||
|
|
||||||
|
// higher order coeffs b5
|
||||||
|
int ii = 1;
|
||||||
|
if (J[ii - 1] <= 2) {
|
||||||
|
b[4 + ii] = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int max_5 = 32;
|
||||||
|
for (int n = 0; n < max_5; n++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
for (int j = 1; j <= J[ii - 1] - 2 && j <= 4; j++) {
|
||||||
|
diff = AmbeHOCb5[n][j - 1] - C[ii - 1][j + 2 - 1];
|
||||||
|
err += (diff * diff);
|
||||||
|
}
|
||||||
|
if (n == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b[4 + ii] = error_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// higher order coeffs b6
|
||||||
|
ii = 2;
|
||||||
|
if (J[ii - 1] <= 2) {
|
||||||
|
b[4 + ii] = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int n = 0; n < 16; n++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
for (int j = 1; j <= J[ii - 1] - 2 && j <= 4; j++) {
|
||||||
|
diff = AmbeHOCb6[n][j - 1] - C[ii - 1][j + 2 - 1];
|
||||||
|
err += (diff * diff);
|
||||||
|
}
|
||||||
|
if (n == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b[4 + ii] = error_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// higher order coeffs b7
|
||||||
|
ii = 3;
|
||||||
|
if (J[ii - 1] <= 2) {
|
||||||
|
b[4 + ii] = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int n = 0; n < 16; n++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
for (int j = 1; j <= J[ii - 1] - 2 && j <= 4; j++) {
|
||||||
|
diff = AmbeHOCb7[n][j - 1] - C[ii - 1][j + 2 - 1];
|
||||||
|
err += (diff * diff);
|
||||||
|
}
|
||||||
|
if (n == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b[4 + ii] = error_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// higher order coeffs b8
|
||||||
|
ii = 4;
|
||||||
|
if (J[ii - 1] <= 2) {
|
||||||
|
b[4 + ii] = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int max_8 = 8;
|
||||||
|
for (int n = 0; n < max_8; n++) {
|
||||||
|
float err = 0.0;
|
||||||
|
float diff;
|
||||||
|
for (int j = 1; j <= J[ii - 1] - 2 && j <= 4; j++) {
|
||||||
|
diff = AmbeHOCb8[n][j - 1] - C[ii - 1][j + 2 - 1];
|
||||||
|
err += (diff * diff);
|
||||||
|
}
|
||||||
|
if (n == 0 || err < error) {
|
||||||
|
error = err;
|
||||||
|
error_index = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b[4 + ii] = error_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbe_dequantizeAmbe2250Parms(cur_mp, prev_mp, b);
|
||||||
|
mbe_moveMbeParms(cur_mp, prev_mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param bits
|
||||||
|
* @param b
|
||||||
|
*/
|
||||||
|
static void encode49bit(uint8_t bits[49], const int b[9])
|
||||||
|
{
|
||||||
|
bits[0] = (b[0] >> 6) & 1;
|
||||||
|
bits[1] = (b[0] >> 5) & 1;
|
||||||
|
bits[2] = (b[0] >> 4) & 1;
|
||||||
|
bits[3] = (b[0] >> 3) & 1;
|
||||||
|
bits[4] = (b[1] >> 4) & 1;
|
||||||
|
bits[5] = (b[1] >> 3) & 1;
|
||||||
|
bits[6] = (b[1] >> 2) & 1;
|
||||||
|
bits[7] = (b[1] >> 1) & 1;
|
||||||
|
bits[8] = (b[2] >> 4) & 1;
|
||||||
|
bits[9] = (b[2] >> 3) & 1;
|
||||||
|
bits[10] = (b[2] >> 2) & 1;
|
||||||
|
bits[11] = (b[2] >> 1) & 1;
|
||||||
|
bits[12] = (b[3] >> 8) & 1;
|
||||||
|
bits[13] = (b[3] >> 7) & 1;
|
||||||
|
bits[14] = (b[3] >> 6) & 1;
|
||||||
|
bits[15] = (b[3] >> 5) & 1;
|
||||||
|
bits[16] = (b[3] >> 4) & 1;
|
||||||
|
bits[17] = (b[3] >> 3) & 1;
|
||||||
|
bits[18] = (b[3] >> 2) & 1;
|
||||||
|
bits[19] = (b[3] >> 1) & 1;
|
||||||
|
bits[20] = (b[4] >> 6) & 1;
|
||||||
|
bits[21] = (b[4] >> 5) & 1;
|
||||||
|
bits[22] = (b[4] >> 4) & 1;
|
||||||
|
bits[23] = (b[4] >> 3) & 1;
|
||||||
|
bits[24] = (b[5] >> 4) & 1;
|
||||||
|
bits[25] = (b[5] >> 3) & 1;
|
||||||
|
bits[26] = (b[5] >> 2) & 1;
|
||||||
|
bits[27] = (b[5] >> 1) & 1;
|
||||||
|
bits[28] = (b[6] >> 3) & 1;
|
||||||
|
bits[29] = (b[6] >> 2) & 1;
|
||||||
|
bits[30] = (b[6] >> 1) & 1;
|
||||||
|
bits[31] = (b[7] >> 3) & 1;
|
||||||
|
bits[32] = (b[7] >> 2) & 1;
|
||||||
|
bits[33] = (b[7] >> 1) & 1;
|
||||||
|
bits[34] = (b[8] >> 2) & 1;
|
||||||
|
bits[35] = b[1] & 1;
|
||||||
|
bits[36] = b[2] & 1;
|
||||||
|
bits[37] = (b[0] >> 2) & 1;
|
||||||
|
bits[38] = (b[0] >> 1) & 1;
|
||||||
|
bits[39] = b[0] & 1;
|
||||||
|
bits[40] = b[3] & 1;
|
||||||
|
bits[41] = (b[4] >> 2) & 1;
|
||||||
|
bits[42] = (b[4] >> 1) & 1;
|
||||||
|
bits[43] = b[4] & 1;
|
||||||
|
bits[44] = b[5] & 1;
|
||||||
|
bits[45] = b[6] & 1;
|
||||||
|
bits[46] = b[7] & 1;
|
||||||
|
bits[47] = (b[8] >> 1) & 1;
|
||||||
|
bits[48] = b[8] & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* @param[in] in
|
||||||
|
* @param out
|
||||||
|
*/
|
||||||
|
static void encodeDmrAMBE(const uint8_t* in, uint8_t* out)
|
||||||
|
{
|
||||||
|
unsigned int aOrig = 0U;
|
||||||
|
unsigned int bOrig = 0U;
|
||||||
|
unsigned int cOrig = 0U;
|
||||||
|
|
||||||
|
unsigned int MASK = 0x000800U;
|
||||||
|
for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) {
|
||||||
|
unsigned int n1 = i;
|
||||||
|
unsigned int n2 = i + 12U;
|
||||||
|
if (READ_BIT(in, n1))
|
||||||
|
aOrig |= MASK;
|
||||||
|
if (READ_BIT(in, n2))
|
||||||
|
bOrig |= MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
MASK = 0x1000000U;
|
||||||
|
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int n = i + 24U;
|
||||||
|
if (READ_BIT(in, n))
|
||||||
|
cOrig |= MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int a = Golay24128::encode24128(aOrig);
|
||||||
|
|
||||||
|
// The PRNG
|
||||||
|
unsigned int p = PRNG_TABLE[aOrig] >> 1;
|
||||||
|
|
||||||
|
unsigned int b = Golay24128::encode23127(bOrig) >> 1;
|
||||||
|
b ^= p;
|
||||||
|
|
||||||
|
MASK = 0x800000U;
|
||||||
|
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||||
|
unsigned int aPos = AMBE_A_TABLE[i];
|
||||||
|
WRITE_BIT(out, aPos, a & MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
MASK = 0x400000U;
|
||||||
|
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||||
|
unsigned int bPos = AMBE_B_TABLE[i];
|
||||||
|
WRITE_BIT(out, bPos, b & MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
MASK = 0x1000000U;
|
||||||
|
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||||
|
unsigned int cPos = AMBE_C_TABLE[i];
|
||||||
|
WRITE_BIT(out, cPos, cOrig & MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Public Class Members
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* Initializes a new instance of the MBEEncoder class. */
|
||||||
|
MBEEncoder::MBEEncoder(MBE_ENCODER_MODE mode) :
|
||||||
|
m_mbeMode(mode),
|
||||||
|
m_gainAdjust(0.0f)
|
||||||
|
{
|
||||||
|
mbe_parms enh_mp;
|
||||||
|
mbe_initMbeParms(&m_curMBEParms, &m_prevMBEParms, &enh_mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encodes the given MBE bits to deinterleaved MBE bits using the decoder mode. */
|
||||||
|
|
||||||
|
void MBEEncoder::encodeBits(uint8_t* bits, uint8_t* codeword)
|
||||||
|
{
|
||||||
|
assert(bits != nullptr);
|
||||||
|
assert(codeword != nullptr);
|
||||||
|
|
||||||
|
int32_t errs = 0;
|
||||||
|
float samples[160U];
|
||||||
|
::memset(samples, 0x00U, 160U * sizeof(float));
|
||||||
|
|
||||||
|
switch (m_mbeMode)
|
||||||
|
{
|
||||||
|
case ENCODE_DMR_AMBE:
|
||||||
|
{
|
||||||
|
// build 49-bit AMBE bytes
|
||||||
|
uint8_t rawAmbe[9U];
|
||||||
|
::memset(rawAmbe, 0x00U, 9U);
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
rawAmbe[i] |= (bits[(i * 8) + j] << (7 - j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build DMR AMBE bytes
|
||||||
|
uint8_t dmrAMBE[9U];
|
||||||
|
::memset(dmrAMBE, 0x00U, 9U);
|
||||||
|
|
||||||
|
encodeDmrAMBE(rawAmbe, dmrAMBE);
|
||||||
|
::memcpy(codeword, dmrAMBE, 9U);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ENCODE_88BIT_IMBE:
|
||||||
|
{
|
||||||
|
uint8_t rawImbe[11U];
|
||||||
|
::memset(rawImbe, 0x00U, 11U);
|
||||||
|
|
||||||
|
for (int i = 0; i < 11; ++i) {
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
rawImbe[i] |= (bits[(i * 8) + j] << (7 - j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::memcpy(codeword, rawImbe, 11U);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encodes the given PCM samples using the encoder mode to MBE codewords. */
|
||||||
|
|
||||||
|
void MBEEncoder::encode(int16_t* samples, uint8_t* codeword)
|
||||||
|
{
|
||||||
|
assert(samples != nullptr);
|
||||||
|
assert(codeword != nullptr);
|
||||||
|
|
||||||
|
int16_t frame_vector[8]; // result ignored
|
||||||
|
|
||||||
|
// first do speech analysis to generate mbe model parameters
|
||||||
|
m_vocoder.imbe_encode(frame_vector, samples);
|
||||||
|
if (m_mbeMode == ENCODE_88BIT_IMBE) {
|
||||||
|
if (m_gainAdjust >= 1.0f) {
|
||||||
|
m_vocoder.set_gain_adjust(m_gainAdjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 0U;
|
||||||
|
int16_t mask = 0x0800;
|
||||||
|
|
||||||
|
for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[0U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0800;
|
||||||
|
for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[1U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0800;
|
||||||
|
for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[2U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0800;
|
||||||
|
for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[3U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0400;
|
||||||
|
for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[4U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0400;
|
||||||
|
for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[5U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0400;
|
||||||
|
for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[6U] & mask) != 0);
|
||||||
|
|
||||||
|
mask = 0x0040;
|
||||||
|
for (uint32_t i = 0U; i < 7U; i++, mask >>= 1, offset++)
|
||||||
|
WRITE_BIT(codeword, offset, (frame_vector[7U] & mask) != 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int b[9];
|
||||||
|
|
||||||
|
// halfrate audio encoding - output rate is 2450 (49 bits)
|
||||||
|
encodeAMBE(m_vocoder.param(), b, &m_curMBEParms, &m_prevMBEParms, m_gainAdjust);
|
||||||
|
|
||||||
|
uint8_t bits[49U];
|
||||||
|
::memset(bits, 0x00U, 49U);
|
||||||
|
|
||||||
|
encode49bit(bits, b);
|
||||||
|
|
||||||
|
// build 49-bit AMBE bytes
|
||||||
|
uint8_t rawAmbe[9U];
|
||||||
|
::memset(rawAmbe, 0x00U, 9U);
|
||||||
|
|
||||||
|
for (int i = 0; i < 9; ++i) {
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
rawAmbe[i] |= (bits[(i * 8) + j] << (7 - j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build DMR AMBE bytes
|
||||||
|
uint8_t dmrAMBE[9U];
|
||||||
|
::memset(dmrAMBE, 0x00U, 9U);
|
||||||
|
|
||||||
|
encodeDmrAMBE(rawAmbe, dmrAMBE);
|
||||||
|
::memcpy(codeword, dmrAMBE, 9U);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Doug McLain
|
||||||
|
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file MBEEncoder.h
|
||||||
|
* @ingroup vocoder
|
||||||
|
* @file MBEEncoder.cpp
|
||||||
|
* @ingroup vocoder
|
||||||
|
*/
|
||||||
|
#if !defined(__MBE_ENCODER_H__)
|
||||||
|
#define __MBE_ENCODER_H__
|
||||||
|
|
||||||
|
#include "common/Defines.h"
|
||||||
|
#include "mbe.h"
|
||||||
|
#include "imbe/imbe_vocoder.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace vocoder
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vocoder Encoding Mode
|
||||||
|
*/
|
||||||
|
enum MBE_ENCODER_MODE {
|
||||||
|
ENCODE_DMR_AMBE, //! DMR AMBE
|
||||||
|
ENCODE_88BIT_IMBE, //! 88-bit IMBE (P25)
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Class Declaration
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implements MBE audio encoding.
|
||||||
|
*/
|
||||||
|
class HOST_SW_API MBEEncoder {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initializes a new instance of the MBEEncoder class.
|
||||||
|
* @param mode Encoder mode.
|
||||||
|
*/
|
||||||
|
MBEEncoder(MBE_ENCODER_MODE mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encodes the given MBE bits to deinterleaved MBE bits using the encoder mode.
|
||||||
|
* @param[in] bits
|
||||||
|
* @param[out] codeword
|
||||||
|
*/
|
||||||
|
void encodeBits(uint8_t* bits, uint8_t* codeword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encodes the given PCM samples using the encoder mode to MBE codewords.
|
||||||
|
* @param[in] samples PCM samples (in short format)
|
||||||
|
* @param[out] codeword MBE codewords.
|
||||||
|
*/
|
||||||
|
void encode(int16_t* samples, uint8_t* codeword);
|
||||||
|
|
||||||
|
private:
|
||||||
|
imbe_vocoder m_vocoder;
|
||||||
|
mbe_parms m_curMBEParms;
|
||||||
|
mbe_parms m_prevMBEParms;
|
||||||
|
|
||||||
|
MBE_ENCODER_MODE m_mbeMode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Gain adjustment.
|
||||||
|
*/
|
||||||
|
__PROPERTY(float, gainAdjust, GainAdjust);
|
||||||
|
};
|
||||||
|
} // namespace vocoder
|
||||||
|
|
||||||
|
#endif // __MBE_ENCODER_H__
|
||||||
@ -0,0 +1,404 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "vocoder/mbe.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4244)
|
||||||
|
#pragma warning(disable: 4305)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Externs
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
** these are all declared by include in ambe3600x2450.c
|
||||||
|
*/
|
||||||
|
extern const float AmbeW0table[120];
|
||||||
|
extern const float AmbeLtable[120];
|
||||||
|
extern const int AmbeVuv[32][8];
|
||||||
|
extern const int AmbeLmprbl[57][4];
|
||||||
|
extern const float AmbeDg[32];
|
||||||
|
extern const float AmbePRBA24[512][3];
|
||||||
|
extern const float AmbePRBA58[128][4];
|
||||||
|
extern const float AmbeHOCb5[32][4];
|
||||||
|
extern const float AmbeHOCb6[16][4];
|
||||||
|
extern const float AmbeHOCb7[16][4];
|
||||||
|
extern const float AmbeHOCb8[8][4];
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_dequantizeAmbe2250Parms(mbe_parms* cur_mp, mbe_parms* prev_mp, const int* b)
|
||||||
|
{
|
||||||
|
int ji, i, j, k, l, L, m, am, ak;
|
||||||
|
int intkl[57];
|
||||||
|
int b0, b1, b2, b3, b4, b5, b6, b7, b8;
|
||||||
|
float f0, Cik[5][18], flokl[57], deltal[57];
|
||||||
|
float Sum42, Sum43, Tl[57], Gm[9], Ri[9], sum, c1, c2;
|
||||||
|
//char tmpstr[13];
|
||||||
|
int silence;
|
||||||
|
int Ji[5], jl;
|
||||||
|
float deltaGamma, BigGamma;
|
||||||
|
float unvc, rconst;
|
||||||
|
|
||||||
|
b0 = b[0];
|
||||||
|
b1 = b[1];
|
||||||
|
b2 = b[2];
|
||||||
|
b3 = b[3];
|
||||||
|
b4 = b[4];
|
||||||
|
b5 = b[5];
|
||||||
|
b6 = b[6];
|
||||||
|
b7 = b[7];
|
||||||
|
b8 = b[8];
|
||||||
|
|
||||||
|
silence = 0;
|
||||||
|
|
||||||
|
// copy repeat from prev_mp
|
||||||
|
cur_mp->repeat = prev_mp->repeat;
|
||||||
|
|
||||||
|
if ((b0 >= 120) && (b0 <= 123)) {
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Erasure Frame");
|
||||||
|
#endif
|
||||||
|
return (2);
|
||||||
|
}
|
||||||
|
else if ((b0 == 124) || (b0 == 125)) {
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Silence Frame");
|
||||||
|
#endif
|
||||||
|
silence = 1;
|
||||||
|
cur_mp->w0 = ((float)2 * M_PI) / (float)32;
|
||||||
|
f0 = (float)1 / (float)32;
|
||||||
|
L = 14;
|
||||||
|
cur_mp->L = 14;
|
||||||
|
for (l = 1; l <= L; l++)
|
||||||
|
{
|
||||||
|
cur_mp->Vl[l] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((b0 == 126) || (b0 == 127)) {
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tone Frame");
|
||||||
|
#endif
|
||||||
|
return (3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (silence == 0) {
|
||||||
|
// w0 from specification document
|
||||||
|
f0 = AmbeW0table[b0];
|
||||||
|
cur_mp->w0 = f0 * (float)2 * M_PI;
|
||||||
|
// w0 from patent filings
|
||||||
|
//f0 = powf (2, ((float) b0 + (float) 195.626) / -(float) 45.368);
|
||||||
|
//cur_mp->w0 = f0 * (float) 2 *M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
unvc = (float)0.2046 / sqrtf(cur_mp->w0);
|
||||||
|
//unvc = (float) 1;
|
||||||
|
//unvc = (float) 0.2046 / sqrtf (f0);
|
||||||
|
|
||||||
|
// decode L
|
||||||
|
if (silence == 0) {
|
||||||
|
// L from specification document
|
||||||
|
// lookup L in tabl3
|
||||||
|
L = AmbeLtable[b0];
|
||||||
|
// L formula form patent filings
|
||||||
|
//L=(int)((float)0.4627 / f0);
|
||||||
|
cur_mp->L = L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode V/UV parameters
|
||||||
|
for (l = 1; l <= L; l++) {
|
||||||
|
// jl from specification document
|
||||||
|
jl = (int)((float)l * (float)16.0 * f0);
|
||||||
|
// jl from patent filings?
|
||||||
|
//jl = (int)(((float)l * (float)16.0 * f0) + 0.25);
|
||||||
|
|
||||||
|
if (silence == 0) {
|
||||||
|
cur_mp->Vl[l] = AmbeVuv[b1][jl];
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: jl[%i]:%i Vl[%i]:%i", l, jl, l, cur_mp->Vl[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b0:%i w0:%f L:%i b1:%i", b0, cur_mp->w0, L, b1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
deltaGamma = AmbeDg[b2];
|
||||||
|
cur_mp->gamma = deltaGamma + ((float)0.5 * prev_mp->gamma);
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b2: %i, deltaGamma: %f gamma: %f gamma-1: %f", b2, deltaGamma, cur_mp->gamma, prev_mp->gamma);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decode PRBA vectors
|
||||||
|
Gm[1] = 0;
|
||||||
|
Gm[2] = AmbePRBA24[b3][0];
|
||||||
|
Gm[3] = AmbePRBA24[b3][1];
|
||||||
|
Gm[4] = AmbePRBA24[b3][2];
|
||||||
|
|
||||||
|
Gm[5] = AmbePRBA58[b4][0];
|
||||||
|
Gm[6] = AmbePRBA58[b4][1];
|
||||||
|
Gm[7] = AmbePRBA58[b4][2];
|
||||||
|
Gm[8] = AmbePRBA58[b4][3];
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b3: %i Gm[2]: %f Gm[3]: %f Gm[4]: %f b4: %i Gm[5]: %f Gm[6]: %f Gm[7]: %f Gm[8]: %f", b3, Gm[2], Gm[3], Gm[4], b4, Gm[5], Gm[6], Gm[7], Gm[8]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// compute Ri
|
||||||
|
for (i = 1; i <= 8; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (m = 1; m <= 8; m++) {
|
||||||
|
if (m == 1) {
|
||||||
|
am = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
am = 2;
|
||||||
|
}
|
||||||
|
sum = sum + ((float)am * Gm[m] * cosf((M_PI * (float)(m - 1) * ((float)i - (float)0.5)) / (float)8));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ri[i] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: R%i: %f", i, Ri[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate first to elements of each Ci,k block from PRBA vector
|
||||||
|
rconst = ((float)1 / ((float)2 * M_SQRT2));
|
||||||
|
Cik[1][1] = (float)0.5 * (Ri[1] + Ri[2]);
|
||||||
|
Cik[1][2] = rconst * (Ri[1] - Ri[2]);
|
||||||
|
Cik[2][1] = (float)0.5 * (Ri[3] + Ri[4]);
|
||||||
|
Cik[2][2] = rconst * (Ri[3] - Ri[4]);
|
||||||
|
Cik[3][1] = (float)0.5 * (Ri[5] + Ri[6]);
|
||||||
|
Cik[3][2] = rconst * (Ri[5] - Ri[6]);
|
||||||
|
Cik[4][1] = (float)0.5 * (Ri[7] + Ri[8]);
|
||||||
|
Cik[4][2] = rconst * (Ri[7] - Ri[8]);
|
||||||
|
|
||||||
|
// decode HOC
|
||||||
|
|
||||||
|
// lookup Ji
|
||||||
|
Ji[1] = AmbeLmprbl[L][0];
|
||||||
|
Ji[2] = AmbeLmprbl[L][1];
|
||||||
|
Ji[3] = AmbeLmprbl[L][2];
|
||||||
|
Ji[4] = AmbeLmprbl[L][3];
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i", Ji[1], Ji[2], Ji[3], Ji[4]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: b5: %i b6: %i b7: %i b8: %i", b5, b6, b7, b8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Load Ci,k with the values from the HOC tables
|
||||||
|
// there appear to be a couple typos in eq. 37 so we will just do what makes sense
|
||||||
|
// (3 <= k <= Ji and k<=6)
|
||||||
|
for (k = 3; k <= Ji[1]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[1][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[1][k] = AmbeHOCb5[b5][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C1,%i: %f", k, Cik[1][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[2]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[2][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[2][k] = AmbeHOCb6[b6][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C2,%i: %f", k, Cik[2][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[3]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[3][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[3][k] = AmbeHOCb7[b7][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C3,%i: %f", k, Cik[3][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[4]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[4][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[4][k] = AmbeHOCb8[b8][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C4,%i: %f", k, Cik[4][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inverse DCT each Ci,k to give ci,j (Tl)
|
||||||
|
l = 1;
|
||||||
|
for (i = 1; i <= 4; i++) {
|
||||||
|
ji = Ji[i];
|
||||||
|
for (j = 1; j <= ji; j++) {
|
||||||
|
sum = 0;
|
||||||
|
for (k = 1; k <= ji; k++) {
|
||||||
|
if (k == 1) {
|
||||||
|
ak = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ak = 2;
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: %i Cik[%i][%i]: %f", j, i, k, Cik[i][k]);
|
||||||
|
#endif
|
||||||
|
sum = sum + ((float)ak * Cik[i][k] * cosf((M_PI * (float)(k - 1) * ((float)j - (float)0.5)) / (float)ji));
|
||||||
|
}
|
||||||
|
Tl[l] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tl[%i]: %f", l, Tl[l]);
|
||||||
|
#endif
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine log2Ml by applying ci,j to previous log2Ml
|
||||||
|
|
||||||
|
// fix for when L > L(-1)
|
||||||
|
if (cur_mp->L > prev_mp->L) {
|
||||||
|
for (l = (prev_mp->L) + 1; l <= cur_mp->L; l++) {
|
||||||
|
prev_mp->Ml[l] = prev_mp->Ml[prev_mp->L];
|
||||||
|
prev_mp->log2Ml[l] = prev_mp->log2Ml[prev_mp->L];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_mp->log2Ml[0] = prev_mp->log2Ml[1];
|
||||||
|
prev_mp->Ml[0] = prev_mp->Ml[1];
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
Sum43 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
// eq. 40
|
||||||
|
flokl[l] = ((float)prev_mp->L / (float)cur_mp->L) * (float)l;
|
||||||
|
intkl[l] = (int)(flokl[l]);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flok%i: %f, intk%i: %i", l, flokl[l], l, intkl[l]);
|
||||||
|
#endif
|
||||||
|
// eq. 41
|
||||||
|
deltal[l] = flokl[l] - (float)intkl[l];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: delta%i: %f", l, deltal[l]);
|
||||||
|
#endif
|
||||||
|
// eq 43
|
||||||
|
Sum43 = Sum43 + ((((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]) + (deltal[l] * prev_mp->log2Ml[intkl[l] + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum43 = (((float)0.65 / (float)cur_mp->L) * Sum43);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Sum43: %f", Sum43);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
Sum42 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
Sum42 += Tl[l];
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum42 = Sum42 / (float)cur_mp->L;
|
||||||
|
BigGamma = cur_mp->gamma - ((float)0.5 * (log((float)cur_mp->L) / log((float)2))) - Sum42;
|
||||||
|
//BigGamma=cur_mp->gamma - ((float)0.5 * log((float)cur_mp->L)) - Sum42;
|
||||||
|
|
||||||
|
// Part 3
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
c1 = ((float)0.65 * ((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]);
|
||||||
|
c2 = ((float)0.65 * deltal[l] * prev_mp->log2Ml[intkl[l] + 1]);
|
||||||
|
cur_mp->log2Ml[l] = Tl[l] + c1 + c2 - Sum43 + BigGamma;
|
||||||
|
// inverse log to generate spectral amplitudes
|
||||||
|
if (cur_mp->Vl[l] == 1) {
|
||||||
|
cur_mp->Ml[l] = exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur_mp->Ml[l] = unvc * exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flokl[%i]: %f, intkl[%i]: %i", l, flokl[l], l, intkl[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: deltal[%i]: %f", l, deltal[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: prev_mp->log2Ml[%i]: %f", l, prev_mp->log2Ml[intkl[l]]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f", BigGamma, c1, c2, Sum43, l, Tl[l], l, cur_mp->log2Ml[l], l, cur_mp->Ml[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_dequantizeAmbeTone(mbe_tone* tone, const int* u)
|
||||||
|
{
|
||||||
|
int bitchk1, bitchk2;
|
||||||
|
int AD, ID1, ID2, ID3, ID4;
|
||||||
|
bitchk1 = (u[0] >> 6) & 0x3f;
|
||||||
|
bitchk2 = (u[3] & 0xf);
|
||||||
|
|
||||||
|
if ((bitchk1 != 63) || (bitchk2 != 0))
|
||||||
|
return -1; // Not a valid tone frame
|
||||||
|
|
||||||
|
AD = ((u[0] & 0x3f) << 1) + ((u[3] >> 4) & 0x1);
|
||||||
|
ID1 = ((u[1] & 0xfff) >> 4);
|
||||||
|
ID2 = ((u[1] & 0xf) << 4) + ((u[2] >> 7) & 0xf);
|
||||||
|
ID3 = ((u[2] & 0x7f) << 1) + ((u[3] >> 13) & 0x1);
|
||||||
|
ID4 = ((u[3] & 0x1fe0) >> 5);
|
||||||
|
|
||||||
|
if ((ID1 == ID2) && (ID1 == ID3) && (ID1 == ID4) &&
|
||||||
|
(((ID1 >= 5) && (ID1 <= 122)) || ((ID1 >= 128) && (ID1 <= 163)) || (ID1 == 255))) {
|
||||||
|
if (tone->ID == ID1) {
|
||||||
|
tone->AD = AD;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tone->n = 0;
|
||||||
|
tone->ID = ID1;
|
||||||
|
tone->AD = AD;
|
||||||
|
}
|
||||||
|
return 0; // valid in-range tone frequency
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
@ -0,0 +1,656 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "vocoder/mbe.h"
|
||||||
|
#include "vocoder/ambe3600x2400_const.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4244)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_eccAmbe3600x2400C0(char ambe_fr[4][24])
|
||||||
|
{
|
||||||
|
int j, errs;
|
||||||
|
char in[23], out[23];
|
||||||
|
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
in[j] = ambe_fr[0][j + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = mbe_golay2312(in, out);
|
||||||
|
// ambe_fr[0][0] should be the C0 golay24 parity bit.
|
||||||
|
// TODO: actually test that here...
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
ambe_fr[0][j + 1] = out[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_eccAmbe3600x2400Data(char ambe_fr[4][24], char* ambe_d)
|
||||||
|
{
|
||||||
|
int j, errs;
|
||||||
|
char* ambe, gin[24], gout[24];
|
||||||
|
|
||||||
|
ambe = ambe_d;
|
||||||
|
// just copy C0
|
||||||
|
for (j = 23; j > 11; j--) {
|
||||||
|
*ambe = ambe_fr[0][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ecc and copy C1
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
gin[j] = ambe_fr[1][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = mbe_golay2312(gin, gout);
|
||||||
|
for (j = 22; j > 10; j--) {
|
||||||
|
*ambe = gout[j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just copy C2
|
||||||
|
for (j = 10; j >= 0; j--) {
|
||||||
|
*ambe = ambe_fr[2][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just copy C3
|
||||||
|
for (j = 13; j >= 0; j--) {
|
||||||
|
*ambe = ambe_fr[3][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_decodeAmbe2400Parms(char* ambe_d, mbe_parms* cur_mp, mbe_parms* prev_mp)
|
||||||
|
{
|
||||||
|
int ji, i, j, k, l, L, L9, m, am, ak;
|
||||||
|
int intkl[57];
|
||||||
|
int b0, b1, b2, b3, b4, b5, b6, b7, b8;
|
||||||
|
float f0, Cik[5][18], flokl[57], deltal[57];
|
||||||
|
float Sum42, Sum43, Tl[57], Gm[9], Ri[9], sum, c1, c2;
|
||||||
|
int silence;
|
||||||
|
int Ji[5], jl;
|
||||||
|
float deltaGamma, BigGamma;
|
||||||
|
float unvc, rconst;
|
||||||
|
|
||||||
|
silence = 0;
|
||||||
|
|
||||||
|
// copy repeat from prev_mp
|
||||||
|
cur_mp->repeat = prev_mp->repeat;
|
||||||
|
|
||||||
|
// check if frame is tone or other; this matches section 7.2 on the P25 Half rate vocoder annex doc
|
||||||
|
b0 = 0;
|
||||||
|
b0 |= ambe_d[0] << 6;
|
||||||
|
b0 |= ambe_d[1] << 5;
|
||||||
|
b0 |= ambe_d[2] << 4;
|
||||||
|
b0 |= ambe_d[3] << 3;
|
||||||
|
b0 |= ambe_d[4] << 2;
|
||||||
|
b0 |= ambe_d[5] << 1;
|
||||||
|
b0 |= ambe_d[48];
|
||||||
|
|
||||||
|
if ((b0 & 0x7E) == 0x7E) {
|
||||||
|
// frame is tone
|
||||||
|
// find tone index
|
||||||
|
// Cx# 0000000000001111111111112222222222233333333333333
|
||||||
|
//
|
||||||
|
// IDX 0000000000111111111122222222223333333333444444444
|
||||||
|
// idx 0123456789012345678901234567890123456789012345678
|
||||||
|
// exm 1111110101001110100000001000000000000000001100000 : t=0111100
|
||||||
|
// ex2 1111110110101110100000000000000000000000000000000 : t=1100010
|
||||||
|
// ex3 1111110010101110110000001000000000000000000110000 : t=0000110
|
||||||
|
// tt1 1111110010011110100000001000000000000000000101000 : t=0000101
|
||||||
|
// tt3 1111110010011110000000001000000000000000000101000
|
||||||
|
// ton HHHHHHDEF410======......P.................32==...
|
||||||
|
// vol 765430 21
|
||||||
|
//DEF indexes the following tables for tone bits 5-7
|
||||||
|
int t7tab[8] = { 1,0,0,0,0,1,1,1 };
|
||||||
|
int t6tab[8] = { 0,0,0,1,1,1,1,0 };
|
||||||
|
int t5tab[8] = { 0,0,1,0,1,1,0,1 };
|
||||||
|
// V V V V V G G G V = verified, G = guessed (and unused by all normal tone indices)
|
||||||
|
b1 = 0;
|
||||||
|
b1 |= t7tab[((ambe_d[6] << 2) | (ambe_d[7] << 1) | ambe_d[8])] << 7; //t7 128
|
||||||
|
b1 |= t6tab[((ambe_d[6] << 2) | (ambe_d[7] << 1) | ambe_d[8])] << 6; //t6 64
|
||||||
|
b1 |= t5tab[((ambe_d[6] << 2) | (ambe_d[7] << 1) | ambe_d[8])] << 5; //t5 32
|
||||||
|
b1 |= ambe_d[9] << 4; //t4 16 e verified
|
||||||
|
b1 |= ambe_d[42] << 3; //t3 8 d verified
|
||||||
|
b1 |= ambe_d[43] << 2; //t2 4 c verified
|
||||||
|
b1 |= ambe_d[10] << 1; //t1 2 b verified
|
||||||
|
b1 |= ambe_d[11]; //t0 1 a verified
|
||||||
|
|
||||||
|
b2 = 0;
|
||||||
|
b2 |= ambe_d[12] << 7; //v7 128 h verified
|
||||||
|
b2 |= ambe_d[13] << 6; //v6 64 g verified
|
||||||
|
b2 |= ambe_d[14] << 5; //v5 32 f verified
|
||||||
|
b2 |= ambe_d[15] << 4; //v4 16 e guess based on data
|
||||||
|
b2 |= ambe_d[16] << 3; //v3 8 d guess based on data
|
||||||
|
b2 |= ambe_d[44] << 2; //v2 4 c guess based on data
|
||||||
|
b2 |= ambe_d[45] << 1; //v1 2 b guess based on data
|
||||||
|
b2 |= ambe_d[17]; //v0 1 a guess based on data
|
||||||
|
// the order of the last 3 bits may really be 17,44,45 not 44,45,17 as above
|
||||||
|
|
||||||
|
//fprintf(stderr, "Tone volume: %d; ", b2);
|
||||||
|
if (b1 < 5) {
|
||||||
|
fprintf(stderr, "MBE: AMBE: index: %d, was <5, invalid!", b1);
|
||||||
|
silence = 1;
|
||||||
|
}
|
||||||
|
else if ((b1 >= 5) && (b1 <= 122)) {
|
||||||
|
fprintf(stderr, "MBE: AMBE: index: %d, Single tone hz: %f", b1, (float)b1 * 31.25);
|
||||||
|
}
|
||||||
|
else if ((b1 > 122) && (b1 < 128)) {
|
||||||
|
fprintf(stderr, "MBE: AMBE: index: %d, was >122 and <128, invalid!", b1);
|
||||||
|
silence = 1;
|
||||||
|
}
|
||||||
|
else if ((b1 >= 128) && (b1 <= 163)) {
|
||||||
|
fprintf(stderr, "MBE: AMBE: index: %d, Dual tone?", b1);
|
||||||
|
// note: dual tone index is different on ambe(dstar) and ambe2+
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "MBE: AMBE: index: %d, was >163, invalid!", b1);
|
||||||
|
silence = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (silence == 1) {
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Silence Frame");
|
||||||
|
#endif
|
||||||
|
cur_mp->w0 = ((float)2 * M_PI) / (float)32;
|
||||||
|
f0 = (float)1 / (float)32;
|
||||||
|
L = 14;
|
||||||
|
cur_mp->L = 14;
|
||||||
|
for (l = 1; l <= L; l++) {
|
||||||
|
cur_mp->Vl[l] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tone Frame");
|
||||||
|
#endif
|
||||||
|
return (3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode fundamental frequency w0 from b0 is already done
|
||||||
|
if (silence == 0) {
|
||||||
|
// w0 from specification document
|
||||||
|
//f0 = AmbeW0table[b0];
|
||||||
|
//cur_mp->w0 = f0 * (float) 2 *M_PI;
|
||||||
|
// w0 from patent filings
|
||||||
|
//f0 = powf (2, ((float) b0 + (float) 195.626) / -(float) 46.368); // was 45.368
|
||||||
|
// w0 guess
|
||||||
|
f0 = powf(2, (-4.311767578125 - (2.1336e-2 * ((float)b0 + 0.5))));
|
||||||
|
cur_mp->w0 = f0 * (float)2 * M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
unvc = (float)0.2046 / sqrtf(cur_mp->w0);
|
||||||
|
//unvc = (float) 1;
|
||||||
|
//unvc = (float) 0.2046 / sqrtf (f0);
|
||||||
|
|
||||||
|
// decode L
|
||||||
|
if (silence == 0) {
|
||||||
|
// L from specification document
|
||||||
|
// lookup L in tabl3
|
||||||
|
L = AmbePlusLtable[b0];
|
||||||
|
// L formula from patent filings
|
||||||
|
//L=(int)((float)0.4627 / f0);
|
||||||
|
cur_mp->L = L;
|
||||||
|
}
|
||||||
|
L9 = L - 9;
|
||||||
|
|
||||||
|
// decode V/UV parameters
|
||||||
|
// load b1 from ambe_d
|
||||||
|
//TODO: use correct table (i.e. 0x0000 0x0005 0x0050 0x0055 etc)
|
||||||
|
b1 = 0;
|
||||||
|
b1 |= ambe_d[38] << 3;
|
||||||
|
b1 |= ambe_d[39] << 2;
|
||||||
|
b1 |= ambe_d[40] << 1;
|
||||||
|
b1 |= ambe_d[41];
|
||||||
|
|
||||||
|
for (l = 1; l <= L; l++) {
|
||||||
|
// jl from specification document
|
||||||
|
jl = (int)((float)l * (float)16.0 * f0);
|
||||||
|
// jl from patent filings?
|
||||||
|
//jl = (int)(((float)l * (float)16.0 * f0) + 0.25);
|
||||||
|
|
||||||
|
if (silence == 0)
|
||||||
|
{
|
||||||
|
cur_mp->Vl[l] = AmbePlusVuv[b1][jl];
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: jl[%i]:%i Vl[%i]:%i", l, jl, l, cur_mp->Vl[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b0:%i w0:%f L:%i b1:%i", b0, cur_mp->w0, L, b1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decode gain vector
|
||||||
|
// load b2 from ambe_d
|
||||||
|
b2 = 0;
|
||||||
|
b2 |= ambe_d[6] << 5;
|
||||||
|
b2 |= ambe_d[7] << 4;
|
||||||
|
b2 |= ambe_d[8] << 3;
|
||||||
|
b2 |= ambe_d[9] << 2;
|
||||||
|
b2 |= ambe_d[42] << 1;
|
||||||
|
b2 |= ambe_d[43];
|
||||||
|
|
||||||
|
deltaGamma = AmbePlusDg[b2];
|
||||||
|
cur_mp->gamma = deltaGamma + ((float)0.5 * prev_mp->gamma);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b2: %i, deltaGamma: %f gamma: %f gamma-1: %f", b2, deltaGamma, cur_mp->gamma, prev_mp->gamma);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decode PRBA vectors
|
||||||
|
Gm[1] = 0;
|
||||||
|
|
||||||
|
// load b3 from ambe_d
|
||||||
|
b3 = 0;
|
||||||
|
b3 |= ambe_d[10] << 8;
|
||||||
|
b3 |= ambe_d[11] << 7;
|
||||||
|
b3 |= ambe_d[12] << 6;
|
||||||
|
b3 |= ambe_d[13] << 5;
|
||||||
|
b3 |= ambe_d[14] << 4;
|
||||||
|
b3 |= ambe_d[15] << 3;
|
||||||
|
b3 |= ambe_d[16] << 2;
|
||||||
|
b3 |= ambe_d[44] << 1;
|
||||||
|
b3 |= ambe_d[45];
|
||||||
|
Gm[2] = AmbePlusPRBA24[b3][0];
|
||||||
|
Gm[3] = AmbePlusPRBA24[b3][1];
|
||||||
|
Gm[4] = AmbePlusPRBA24[b3][2];
|
||||||
|
|
||||||
|
// load b4 from ambe_d
|
||||||
|
b4 = 0;
|
||||||
|
b4 |= ambe_d[17] << 6;
|
||||||
|
b4 |= ambe_d[18] << 5;
|
||||||
|
b4 |= ambe_d[19] << 4;
|
||||||
|
b4 |= ambe_d[20] << 3;
|
||||||
|
b4 |= ambe_d[21] << 2;
|
||||||
|
b4 |= ambe_d[46] << 1;
|
||||||
|
b4 |= ambe_d[47];
|
||||||
|
Gm[5] = AmbePlusPRBA58[b4][0];
|
||||||
|
Gm[6] = AmbePlusPRBA58[b4][1];
|
||||||
|
Gm[7] = AmbePlusPRBA58[b4][2];
|
||||||
|
Gm[8] = AmbePlusPRBA58[b4][3];
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b3: %i Gm[2]: %f Gm[3]: %f Gm[4]: %f b4: %i Gm[5]: %f Gm[6]: %f Gm[7]: %f Gm[8]: %f", b3, Gm[2], Gm[3], Gm[4], b4, Gm[5], Gm[6], Gm[7], Gm[8]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// compute Ri
|
||||||
|
for (i = 1; i <= 8; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (m = 1; m <= 8; m++) {
|
||||||
|
if (m == 1) {
|
||||||
|
am = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
am = 2;
|
||||||
|
}
|
||||||
|
sum = sum + ((float)am * Gm[m] * cosf((M_PI * (float)(m - 1) * ((float)i - (float)0.5)) / (float)8));
|
||||||
|
}
|
||||||
|
Ri[i] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: R%i: %f ", i, Ri[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate first to elements of each Ci,k block from PRBA vector
|
||||||
|
rconst = ((float)1 / ((float)2 * M_SQRT2));
|
||||||
|
Cik[1][1] = (float)0.5 * (Ri[1] + Ri[2]);
|
||||||
|
Cik[1][2] = rconst * (Ri[1] - Ri[2]);
|
||||||
|
Cik[2][1] = (float)0.5 * (Ri[3] + Ri[4]);
|
||||||
|
Cik[2][2] = rconst * (Ri[3] - Ri[4]);
|
||||||
|
Cik[3][1] = (float)0.5 * (Ri[5] + Ri[6]);
|
||||||
|
Cik[3][2] = rconst * (Ri[5] - Ri[6]);
|
||||||
|
Cik[4][1] = (float)0.5 * (Ri[7] + Ri[8]);
|
||||||
|
Cik[4][2] = rconst * (Ri[7] - Ri[8]);
|
||||||
|
|
||||||
|
// decode HOC
|
||||||
|
|
||||||
|
// load b5 from ambe_d
|
||||||
|
b5 = 0;
|
||||||
|
b5 |= ambe_d[22] << 3;
|
||||||
|
b5 |= ambe_d[23] << 2;
|
||||||
|
b5 |= ambe_d[25] << 1;
|
||||||
|
b5 |= ambe_d[26];
|
||||||
|
|
||||||
|
// load b6 from ambe_d
|
||||||
|
b6 = 0;
|
||||||
|
b6 |= ambe_d[27] << 3;
|
||||||
|
b6 |= ambe_d[28] << 2;
|
||||||
|
b6 |= ambe_d[29] << 1;
|
||||||
|
b6 |= ambe_d[30];
|
||||||
|
|
||||||
|
// load b7 from ambe_d
|
||||||
|
b7 = 0;
|
||||||
|
b7 |= ambe_d[31] << 3;
|
||||||
|
b7 |= ambe_d[32] << 2;
|
||||||
|
b7 |= ambe_d[33] << 1;
|
||||||
|
b7 |= ambe_d[34];
|
||||||
|
|
||||||
|
// load b8 from ambe_d
|
||||||
|
b8 = 0;
|
||||||
|
b8 |= ambe_d[35] << 3;
|
||||||
|
b8 |= ambe_d[36] << 2;
|
||||||
|
b8 |= ambe_d[37] << 1;
|
||||||
|
//b8 |= 0; // least significant bit of hoc3 unused here, and according to the patent is forced to 0 when not used
|
||||||
|
|
||||||
|
// lookup Ji
|
||||||
|
Ji[1] = AmbePlusLmprbl[L][0];
|
||||||
|
Ji[2] = AmbePlusLmprbl[L][1];
|
||||||
|
Ji[3] = AmbePlusLmprbl[L][2];
|
||||||
|
Ji[4] = AmbePlusLmprbl[L][3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i", Ji[1], Ji[2], Ji[3], Ji[4]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: b5: %i b6: %i b7: %i b8: %i", b5, b6, b7, b8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Load Ci,k with the values from the HOC tables
|
||||||
|
// there appear to be a couple typos in eq. 37 so we will just do what makes sense
|
||||||
|
// (3 <= k <= Ji and k<=6)
|
||||||
|
for (k = 3; k <= Ji[1]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[1][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[1][k] = AmbePlusHOCb5[b5][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C1,%i: %f ", k, Cik[1][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[2]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[2][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[2][k] = AmbePlusHOCb6[b6][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C2,%i: %f ", k, Cik[2][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[3]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[3][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[3][k] = AmbePlusHOCb7[b7][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C3,%i: %f ", k, Cik[3][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[4]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[4][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[4][k] = AmbePlusHOCb8[b8][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C4,%i: %f ", k, Cik[4][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inverse DCT each Ci,k to give ci,j (Tl)
|
||||||
|
l = 1;
|
||||||
|
for (i = 1; i <= 4; i++) {
|
||||||
|
ji = Ji[i];
|
||||||
|
for (j = 1; j <= ji; j++) {
|
||||||
|
sum = 0;
|
||||||
|
for (k = 1; k <= ji; k++) {
|
||||||
|
if (k == 1) {
|
||||||
|
ak = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ak = 2;
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: j: %i Cik[%i][%i]: %f ", j, i, k, Cik[i][k]);
|
||||||
|
#endif
|
||||||
|
sum = sum + ((float)ak * Cik[i][k] * cosf((M_PI * (float)(k - 1) * ((float)j - (float)0.5)) / (float)ji));
|
||||||
|
}
|
||||||
|
Tl[l] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tl[%i]: %f", l, Tl[l]);
|
||||||
|
#endif
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine log2Ml by applying ci,j to previous log2Ml
|
||||||
|
|
||||||
|
// fix for when L > L(-1)
|
||||||
|
if (cur_mp->L > prev_mp->L) {
|
||||||
|
for (l = (prev_mp->L) + 1; l <= cur_mp->L; l++) {
|
||||||
|
prev_mp->Ml[l] = prev_mp->Ml[prev_mp->L];
|
||||||
|
prev_mp->log2Ml[l] = prev_mp->log2Ml[prev_mp->L];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_mp->log2Ml[0] = prev_mp->log2Ml[1];
|
||||||
|
prev_mp->Ml[0] = prev_mp->Ml[1];
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
Sum43 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
// eq. 40
|
||||||
|
flokl[l] = ((float)prev_mp->L / (float)cur_mp->L) * (float)l;
|
||||||
|
intkl[l] = (int)(flokl[l]);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flok%i: %f, intk%i: %i ", l, flokl[l], l, intkl[l]);
|
||||||
|
#endif
|
||||||
|
// eq. 41
|
||||||
|
deltal[l] = flokl[l] - (float)intkl[l];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: delta%i: %f ", l, deltal[l]);
|
||||||
|
#endif
|
||||||
|
// eq 43
|
||||||
|
Sum43 = Sum43 + ((((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]) + (deltal[l] * prev_mp->log2Ml[intkl[l] + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum43 = (((float)0.65 / (float)cur_mp->L) * Sum43);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Sum43: %f", Sum43);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
Sum42 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
Sum42 += Tl[l];
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum42 = Sum42 / (float)cur_mp->L;
|
||||||
|
BigGamma = cur_mp->gamma - ((float)0.5 * (log((float)cur_mp->L) / log((float)2))) - Sum42;
|
||||||
|
//BigGamma=cur_mp->gamma - ((float)0.5 * log((float)cur_mp->L)) - Sum42;
|
||||||
|
|
||||||
|
// Part 3
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
c1 = ((float)0.65 * ((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]);
|
||||||
|
c2 = ((float)0.65 * deltal[l] * prev_mp->log2Ml[intkl[l] + 1]);
|
||||||
|
cur_mp->log2Ml[l] = Tl[l] + c1 + c2 - Sum43 + BigGamma;
|
||||||
|
// inverse log to generate spectral amplitudes
|
||||||
|
if (cur_mp->Vl[l] == 1)
|
||||||
|
{
|
||||||
|
cur_mp->Ml[l] = exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur_mp->Ml[l] = unvc * exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flokl[%i]: %f, intkl[%i]: %i", l, flokl[l], l, intkl[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: deltal[%i]: %f", l, deltal[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: prev_mp->log2Ml[%i]: %f", l, prev_mp->log2Ml[intkl[l]]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f", BigGamma, c1, c2, Sum43, l, Tl[l], l, cur_mp->log2Ml[l], l, cur_mp->Ml[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_demodulateAmbe3600x2400Data(char ambe_fr[4][24])
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
unsigned short pr[115];
|
||||||
|
unsigned short foo = 0;
|
||||||
|
|
||||||
|
// create pseudo-random modulator
|
||||||
|
for (i = 23; i >= 12; i--) {
|
||||||
|
foo <<= 1;
|
||||||
|
foo |= ambe_fr[0][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pr[0] = (16 * foo);
|
||||||
|
for (i = 1; i < 24; i++) {
|
||||||
|
pr[i] = (173 * pr[i - 1]) + 13849 - (65536 * (((173 * pr[i - 1]) + 13849) / 65536));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < 24; i++) {
|
||||||
|
pr[i] = pr[i] / 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
// demodulate ambe_fr with pr
|
||||||
|
k = 1;
|
||||||
|
for (j = 22; j >= 0; j--) {
|
||||||
|
ambe_fr[1][j] = ((ambe_fr[1][j]) ^ pr[k]);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe2400DataF(float* aout_buf, int* errs, int* errs2, char* err_str, char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
int i, bad;
|
||||||
|
|
||||||
|
for (i = 0; i < *errs2; i++) {
|
||||||
|
*err_str = '=';
|
||||||
|
err_str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bad = mbe_decodeAmbe2400Parms(ambe_d, cur_mp, prev_mp);
|
||||||
|
if (bad == 2) {
|
||||||
|
// Erasure frame
|
||||||
|
*err_str = 'E';
|
||||||
|
err_str++;
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
else if (bad == 3) {
|
||||||
|
// Tone Frame
|
||||||
|
*err_str = 'T';
|
||||||
|
err_str++;
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
else if (*errs2 > 3) {
|
||||||
|
mbe_useLastMbeParms(cur_mp, prev_mp);
|
||||||
|
cur_mp->repeat++;
|
||||||
|
*err_str = 'R';
|
||||||
|
err_str++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bad == 0) {
|
||||||
|
if (cur_mp->repeat <= 3) {
|
||||||
|
mbe_moveMbeParms(cur_mp, prev_mp);
|
||||||
|
mbe_spectralAmpEnhance(cur_mp);
|
||||||
|
mbe_synthesizeSpeechF(aout_buf, cur_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_moveMbeParms(cur_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*err_str = 'M';
|
||||||
|
err_str++;
|
||||||
|
mbe_synthesizeSilenceF(aout_buf);
|
||||||
|
mbe_initMbeParms(cur_mp, prev_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mbe_synthesizeSilenceF(aout_buf);
|
||||||
|
mbe_initMbeParms(cur_mp, prev_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
|
||||||
|
*err_str = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe2400Data(short* aout_buf, int* errs, int* errs2, char* err_str, char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
float float_buf[160];
|
||||||
|
mbe_processAmbe2400DataF(float_buf, errs, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_floatToShort(float_buf, aout_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe3600x2400FrameF(float* aout_buf, int* errs, int* errs2, char* err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
*errs = 0;
|
||||||
|
*errs2 = 0;
|
||||||
|
*errs = mbe_eccAmbe3600x2400C0(ambe_fr);
|
||||||
|
mbe_demodulateAmbe3600x2400Data(ambe_fr);
|
||||||
|
|
||||||
|
*errs2 = *errs;
|
||||||
|
*errs2 += mbe_eccAmbe3600x2400Data(ambe_fr, ambe_d);
|
||||||
|
|
||||||
|
mbe_processAmbe2400DataF(aout_buf, errs, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe3600x2400Frame(short* aout_buf, int* errs, int* errs2, char* err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
float float_buf[160];
|
||||||
|
mbe_processAmbe3600x2400FrameF(float_buf, errs, errs2, err_str, ambe_fr, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_floatToShort(float_buf, aout_buf);
|
||||||
|
}
|
||||||
@ -0,0 +1,903 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file ambe3600x2400_const.h
|
||||||
|
* @ingroup vocoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#if !defined(__AMBE3600x2400_CONST_H__)
|
||||||
|
#define __AMBE3600x2400_CONST_H__
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4305)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const float AmbePlusLtable[126] = {
|
||||||
|
9, 9, 9, 9, 9, 9,
|
||||||
|
10, 10, 10, 10, 10, 10,
|
||||||
|
11, 11, 11, 11, 11, 11,
|
||||||
|
12, 12, 12, 12, 12, 13,
|
||||||
|
13, 13, 13, 13, 14, 14,
|
||||||
|
14, 14, 15, 15, 15, 15,
|
||||||
|
16, 16, 16, 16, 17, 17,
|
||||||
|
17, 17, 18, 18, 18, 18,
|
||||||
|
19, 19, 19, 20, 20, 20,
|
||||||
|
21, 21, 21, 22, 22, 22,
|
||||||
|
23, 23, 23, 24, 24, 24,
|
||||||
|
25, 25, 26, 26, 26, 27,
|
||||||
|
27, 28, 28, 29, 29, 30,
|
||||||
|
30, 30, 31, 31, 32, 32,
|
||||||
|
33, 33, 34, 34, 35, 36,
|
||||||
|
36, 37, 37, 38, 38, 39,
|
||||||
|
40, 40, 41, 42, 42, 43,
|
||||||
|
43, 44, 45, 46, 46, 47,
|
||||||
|
48, 48, 49, 50, 51, 52,
|
||||||
|
52, 53, 54, 55, 56, 56,
|
||||||
|
56, 56, 56, 56, 56, 56 // last line is padded
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V/UV Quantization Vectors
|
||||||
|
*/
|
||||||
|
const int AmbePlusVuv[16][8] = {
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0, 0, 0, 1, 1},
|
||||||
|
{0, 0, 0, 0, 1, 1, 0, 0},
|
||||||
|
{0, 0, 0, 0, 1, 1, 1, 1},
|
||||||
|
{0, 0, 1, 1, 0, 0, 0, 0},
|
||||||
|
{0, 0, 1, 1, 0, 0, 1, 1},
|
||||||
|
{0, 0, 1, 1, 1, 1, 0, 0},
|
||||||
|
{0, 0, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 0, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 0, 0, 0, 0, 1, 1},
|
||||||
|
{1, 1, 0, 0, 1, 1, 0, 0},
|
||||||
|
{1, 1, 0, 0, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 1, 0, 0, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 0, 0},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log Magnitude Prediction Residual Block Lengths
|
||||||
|
*/
|
||||||
|
const int AmbePlusLmprbl[57][4] = {
|
||||||
|
{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,},
|
||||||
|
{2, 2, 2, 3,},
|
||||||
|
{2, 2, 3, 3,},
|
||||||
|
{2, 3, 3, 3,},
|
||||||
|
{2, 3, 3, 4,},
|
||||||
|
{3, 3, 3, 4,},
|
||||||
|
{3, 3, 4, 4,},
|
||||||
|
{3, 3, 4, 5,},
|
||||||
|
{3, 4, 4, 5,},
|
||||||
|
{3, 4, 5, 5,},
|
||||||
|
{4, 4, 5, 5,},
|
||||||
|
{4, 4, 5, 6,},
|
||||||
|
{4, 4, 6, 6,},
|
||||||
|
{4, 5, 6, 6,},
|
||||||
|
{4, 5, 6, 7,},
|
||||||
|
{5, 5, 6, 7,},
|
||||||
|
{5, 5, 7, 7,},
|
||||||
|
{5, 6, 7, 7,},
|
||||||
|
{5, 6, 7, 8,},
|
||||||
|
{5, 6, 8, 8,},
|
||||||
|
{6, 6, 8, 8,},
|
||||||
|
{6, 6, 8, 9,},
|
||||||
|
{6, 7, 8, 9,},
|
||||||
|
{6, 7, 9, 9,},
|
||||||
|
{6, 7, 9, 10,},
|
||||||
|
{7, 7, 9, 10,},
|
||||||
|
{7, 8, 9, 10,},
|
||||||
|
{7, 8, 10, 10,},
|
||||||
|
{7, 8, 10, 11,},
|
||||||
|
{8, 8, 10, 11,},
|
||||||
|
{8, 9, 10, 11,},
|
||||||
|
{8, 9, 11, 11,},
|
||||||
|
{8, 9, 11, 12,},
|
||||||
|
{8, 9, 11, 13,},
|
||||||
|
{8, 9, 12, 13,},
|
||||||
|
{8, 10, 12, 13,},
|
||||||
|
{9, 10, 12, 13,},
|
||||||
|
{9, 10, 12, 14,},
|
||||||
|
{9, 10, 13, 14,},
|
||||||
|
{9, 11, 13, 14,},
|
||||||
|
{10, 11, 13, 14,},
|
||||||
|
{10, 11, 13, 15,},
|
||||||
|
{10, 11, 14, 15,},
|
||||||
|
{10, 12, 14, 15,},
|
||||||
|
{10, 12, 14, 16,},
|
||||||
|
{11, 12, 14, 16,},
|
||||||
|
{11, 12, 15, 16,},
|
||||||
|
{11, 12, 15, 17,},
|
||||||
|
{11, 13, 15, 17}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gain Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbePlusDg[64] = {
|
||||||
|
0.000000, 0.118200, 0.215088, 0.421167, 0.590088, 0.749075, 0.879395, 0.996388,
|
||||||
|
1.092285, 1.171577, 1.236572, 1.313450, 1.376465, 1.453342, 1.516357, 1.600346,
|
||||||
|
1.669189, 1.742847, 1.803223, 1.880234, 1.943359, 2.025067, 2.092041, 2.178042,
|
||||||
|
2.248535, 2.331718, 2.399902, 2.492343, 2.568115, 2.658677, 2.732910, 2.816496,
|
||||||
|
2.885010, 2.956386, 3.014893, 3.078890, 3.131348, 3.206615, 3.268311, 3.344785,
|
||||||
|
3.407471, 3.484885, 3.548340, 3.623339, 3.684814, 3.764509, 3.829834, 3.915298,
|
||||||
|
3.985352, 4.072560, 4.144043, 4.231251, 4.302734, 4.399066, 4.478027, 4.572883,
|
||||||
|
4.650635, 4.760785, 4.851074, 4.972361, 5.071777, 5.226203, 5.352783, 5.352783
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRBA24 Vector Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbePlusPRBA24[512][3] = {
|
||||||
|
{-1.250000, -0.312500, -0.625000},
|
||||||
|
{-0.750000, -0.437500, -0.437500},
|
||||||
|
{-0.437500, -0.375000, -0.312500},
|
||||||
|
{-0.437500, -0.625000, -0.500000},
|
||||||
|
{-1.000000, -0.187500, -0.187500},
|
||||||
|
{-0.625000, -0.625000, -0.125000},
|
||||||
|
{-0.500000, -0.187500, -0.187500},
|
||||||
|
{-0.375000, -0.437500, -0.187500},
|
||||||
|
{-1.062500, -0.750000, -0.125000},
|
||||||
|
{-0.625000, -0.312500, -0.062500},
|
||||||
|
{-0.500000, -1.000000, -0.062500},
|
||||||
|
{-0.375000, -0.312500, -0.062500},
|
||||||
|
{-0.687500, -0.250000, 0.187500},
|
||||||
|
{-0.437500, -0.500000, 0.375000},
|
||||||
|
{-0.375000, -0.375000, 0.062500},
|
||||||
|
{-0.312500, -0.187500, 0.000000},
|
||||||
|
{-0.625000, -0.187500, -0.187500},
|
||||||
|
{-0.500000, -0.062500, -0.250000},
|
||||||
|
{-0.500000, -0.125000, -0.437500},
|
||||||
|
{-0.312500, -0.062500, -0.312500},
|
||||||
|
{-0.562500, -0.187500, -0.062500},
|
||||||
|
{-0.375000, -0.187500, -0.062500},
|
||||||
|
{-0.375000, -0.125000, -0.187500},
|
||||||
|
{-0.312500, -0.187500, -0.125000},
|
||||||
|
{-0.562500, 0.000000, 0.125000},
|
||||||
|
{-0.437500, 0.000000, 0.062500},
|
||||||
|
{-0.312500, -0.125000, 0.125000},
|
||||||
|
{-0.312500, -0.062500, 0.000000},
|
||||||
|
{-0.937500, -0.062500, 0.125000},
|
||||||
|
{-0.750000, -0.125000, 0.375000},
|
||||||
|
{-0.437500, -0.062500, 0.250000},
|
||||||
|
{-0.375000, -0.062500, 0.625000},
|
||||||
|
{-0.875000, 0.062500, -0.312500},
|
||||||
|
{-0.500000, 0.125000, -0.375000},
|
||||||
|
{-0.312500, 0.062500, -0.250000},
|
||||||
|
{-0.312500, 0.000000, -0.312500},
|
||||||
|
{-0.687500, 0.125000, -0.187500},
|
||||||
|
{-0.437500, 0.062500, -0.062500},
|
||||||
|
{-0.375000, 0.125000, -0.125000},
|
||||||
|
{-0.312500, 0.062500, -0.125000},
|
||||||
|
{-0.687500, 0.062500, -0.062500},
|
||||||
|
{-0.437500, 0.187500, 0.062500},
|
||||||
|
{-0.312500, 0.062500, 0.000000},
|
||||||
|
{-0.250000, 0.000000, 0.125000},
|
||||||
|
{-1.312500, 0.062500, 0.312500},
|
||||||
|
{-0.562500, 0.125000, 0.250000},
|
||||||
|
{-0.375000, 0.062500, 0.375000},
|
||||||
|
{-0.312500, 0.125000, 0.125000},
|
||||||
|
{-1.250000, 0.187500, -0.250000},
|
||||||
|
{-0.687500, 0.437500, -0.375000},
|
||||||
|
{-0.562500, 0.250000, -0.250000},
|
||||||
|
{-0.312500, 0.375000, -0.562500},
|
||||||
|
{-0.812500, 0.437500, -0.062500},
|
||||||
|
{-0.625000, 0.187500, -0.062500},
|
||||||
|
{-0.500000, 0.375000, -0.062500},
|
||||||
|
{-0.375000, 0.375000, -0.250000},
|
||||||
|
{-0.812500, 0.187500, 0.187500},
|
||||||
|
{-0.562500, 0.625000, 0.062500},
|
||||||
|
{-0.500000, 0.312500, 0.125000},
|
||||||
|
{-0.312500, 0.312500, 0.062500},
|
||||||
|
{-0.500000, 0.250000, 0.625000},
|
||||||
|
{-0.375000, 0.250000, 0.312500},
|
||||||
|
{-0.312500, 0.500000, 0.500000},
|
||||||
|
{-0.312500, 0.500000, 0.250000},
|
||||||
|
{-0.250000, -0.437500, -0.375000},
|
||||||
|
{-0.250000, -0.250000, -0.312500},
|
||||||
|
{-0.250000, -0.687500, -0.312500},
|
||||||
|
{-0.125000, -0.500000, -0.250000},
|
||||||
|
{-0.250000, -0.375000, -0.125000},
|
||||||
|
{-0.125000, -0.312500, -0.187500},
|
||||||
|
{-0.125000, -0.250000, -0.250000},
|
||||||
|
{-0.062500, -0.187500, -0.125000},
|
||||||
|
{-0.187500, -0.187500, -0.062500},
|
||||||
|
{-0.187500, -0.500000, 0.000000},
|
||||||
|
{-0.125000, -0.375000, -0.062500},
|
||||||
|
{-0.062500, -0.250000, 0.000000},
|
||||||
|
{-0.250000, -0.312500, 0.250000},
|
||||||
|
{-0.187500, -0.250000, 0.125000},
|
||||||
|
{-0.187500, -0.250000, 0.000000},
|
||||||
|
{-0.125000, -0.625000, 0.187500},
|
||||||
|
{-0.187500, -0.062500, -0.250000},
|
||||||
|
{-0.125000, -0.062500, -0.187500},
|
||||||
|
{-0.062500, 0.000000, -0.312500},
|
||||||
|
{-0.062500, 0.000000, -0.812500},
|
||||||
|
{-0.250000, -0.125000, -0.062500},
|
||||||
|
{-0.250000, -0.062500, -0.125000},
|
||||||
|
{-0.187500, 0.000000, -0.062500},
|
||||||
|
{-0.125000, -0.062500, -0.062500},
|
||||||
|
{-0.187500, 0.000000, 0.125000},
|
||||||
|
{-0.187500, -0.062500, 0.062500},
|
||||||
|
{-0.125000, -0.125000, 0.125000},
|
||||||
|
{-0.125000, -0.187500, 0.062500},
|
||||||
|
{-0.187500, -0.062500, 0.437500},
|
||||||
|
{-0.187500, -0.125000, 0.187500},
|
||||||
|
{-0.125000, 0.000000, 0.187500},
|
||||||
|
{-0.062500, 0.000000, 0.375000},
|
||||||
|
{-0.187500, 0.000000, -0.187500},
|
||||||
|
{-0.187500, 0.125000, -0.125000},
|
||||||
|
{-0.187500, 0.125000, -0.187500},
|
||||||
|
{-0.125000, 0.125000, -0.375000},
|
||||||
|
{-0.250000, 0.187500, 0.000000},
|
||||||
|
{-0.125000, 0.000000, -0.125000},
|
||||||
|
{-0.062500, 0.000000, -0.062500},
|
||||||
|
{-0.062500, 0.125000, -0.062500},
|
||||||
|
{-0.187500, 0.125000, 0.125000},
|
||||||
|
{-0.187500, 0.062500, 0.000000},
|
||||||
|
{-0.125000, 0.125000, 0.062500},
|
||||||
|
{-0.062500, 0.000000, 0.000000},
|
||||||
|
{-0.250000, 0.062500, 0.250000},
|
||||||
|
{-0.125000, 0.125000, 0.312500},
|
||||||
|
{-0.125000, 0.125000, 0.125000},
|
||||||
|
{-0.062500, 0.000000, 0.125000},
|
||||||
|
{-0.250000, 0.250000, -0.187500},
|
||||||
|
{-0.187500, 0.687500, -0.187500},
|
||||||
|
{-0.125000, 0.250000, -0.125000},
|
||||||
|
{-0.062500, 0.375000, -0.312500},
|
||||||
|
{-0.187500, 0.187500, -0.062500},
|
||||||
|
{-0.187500, 0.437500, -0.062500},
|
||||||
|
{-0.125000, 0.375000, 0.062500},
|
||||||
|
{-0.062500, 0.500000, 0.000000},
|
||||||
|
{-0.250000, 0.250000, 0.187500},
|
||||||
|
{-0.125000, 0.562500, 0.250000},
|
||||||
|
{-0.125000, 0.437500, 0.125000},
|
||||||
|
{-0.062500, 0.312500, 0.125000},
|
||||||
|
{-0.250000, 0.187500, 0.437500},
|
||||||
|
{-0.187500, 0.250000, 0.312500},
|
||||||
|
{-0.062500, 0.312500, 0.250000},
|
||||||
|
{-0.062500, 0.437500, 0.562500},
|
||||||
|
{-0.062500, -0.375000, -0.250000},
|
||||||
|
{0.000000, -0.250000, -0.375000},
|
||||||
|
{0.062500, -0.250000, -0.312500},
|
||||||
|
{0.062500, -0.375000, -0.312500},
|
||||||
|
{0.000000, -0.312500, -0.125000},
|
||||||
|
{0.000000, -0.250000, -0.062500},
|
||||||
|
{0.062500, -0.500000, -0.125000},
|
||||||
|
{0.062500, -0.250000, -0.187500},
|
||||||
|
{0.000000, -0.437500, 0.000000},
|
||||||
|
{0.000000, -0.250000, 0.000000},
|
||||||
|
{0.000000, -0.187500, 0.062500},
|
||||||
|
{0.062500, -0.375000, 0.000000},
|
||||||
|
{-0.062500, -0.187500, 0.125000},
|
||||||
|
{-0.062500, -0.375000, 0.062500},
|
||||||
|
{0.000000, -0.250000, 0.187500},
|
||||||
|
{0.000000, -0.312500, 0.125000},
|
||||||
|
{-0.062500, -0.125000, -0.250000},
|
||||||
|
{0.000000, -0.125000, -0.500000},
|
||||||
|
{0.000000, -0.062500, -0.250000},
|
||||||
|
{0.062500, -0.187500, -0.187500},
|
||||||
|
{-0.062500, -0.125000, -0.062500},
|
||||||
|
{-0.062500, -0.187500, 0.000000},
|
||||||
|
{0.000000, -0.125000, -0.125000},
|
||||||
|
{0.000000, -0.187500, -0.125000},
|
||||||
|
{-0.062500, -0.062500, 0.125000},
|
||||||
|
{0.000000, -0.125000, 0.000000},
|
||||||
|
{0.062500, -0.062500, 0.000000},
|
||||||
|
{0.062500, -0.125000, 0.000000},
|
||||||
|
{-0.062500, -0.125000, 0.437500},
|
||||||
|
{0.000000, -0.062500, 0.250000},
|
||||||
|
{0.000000, -0.125000, 0.187500},
|
||||||
|
{0.062500, -0.187500, 0.312500},
|
||||||
|
{-0.062500, 0.062500, -0.187500},
|
||||||
|
{-0.062500, 0.000000, -0.125000},
|
||||||
|
{0.062500, 0.062500, -0.125000},
|
||||||
|
{0.062500, 0.062500, -0.312500},
|
||||||
|
{0.000000, 0.062500, -0.062500},
|
||||||
|
{0.000000, 0.000000, 0.000000},
|
||||||
|
{0.062500, 0.000000, -0.125000},
|
||||||
|
{0.062500, 0.125000, -0.125000},
|
||||||
|
{0.000000, 0.062500, 0.125000},
|
||||||
|
{0.000000, 0.125000, 0.062500},
|
||||||
|
{0.062500, 0.000000, 0.125000},
|
||||||
|
{0.062500, 0.062500, 0.000000},
|
||||||
|
{-0.062500, 0.062500, 0.187500},
|
||||||
|
{-0.062500, 0.062500, 0.437500},
|
||||||
|
{0.000000, 0.062500, 0.250000},
|
||||||
|
{0.062500, 0.125000, 0.187500},
|
||||||
|
{0.000000, 0.250000, -0.250000},
|
||||||
|
{0.000000, 0.375000, -0.062500},
|
||||||
|
{0.000000, 0.187500, -0.125000},
|
||||||
|
{0.062500, 0.500000, -0.187500},
|
||||||
|
{0.000000, 0.250000, 0.000000},
|
||||||
|
{0.000000, 0.187500, 0.062500},
|
||||||
|
{0.062500, 0.312500, 0.062500},
|
||||||
|
{0.062500, 0.187500, 0.000000},
|
||||||
|
{-0.062500, 0.187500, 0.187500},
|
||||||
|
{0.000000, 0.250000, 0.125000},
|
||||||
|
{0.062500, 0.375000, 0.187500},
|
||||||
|
{0.062500, 0.250000, 0.250000},
|
||||||
|
{-0.062500, 0.187500, 0.500000},
|
||||||
|
{0.000000, 0.312500, 0.375000},
|
||||||
|
{0.000000, 0.125000, 0.312500},
|
||||||
|
{0.062500, 0.187500, 0.250000},
|
||||||
|
{0.125000, -0.125000, -0.312500},
|
||||||
|
{0.125000, -0.312500, -0.187500},
|
||||||
|
{0.187500, -0.375000, -0.250000},
|
||||||
|
{0.187500, -0.187500, -0.125000},
|
||||||
|
{0.125000, -0.187500, -0.062500},
|
||||||
|
{0.125000, -0.687500, -0.062500},
|
||||||
|
{0.125000, -0.187500, -0.062500},
|
||||||
|
{0.187500, -0.375000, -0.062500},
|
||||||
|
{0.062500, -0.250000, 0.062500},
|
||||||
|
{0.125000, -0.187500, 0.000000},
|
||||||
|
{0.125000, -0.187500, 0.125000},
|
||||||
|
{0.187500, -0.250000, 0.125000},
|
||||||
|
{0.062500, -0.187500, 0.187500},
|
||||||
|
{0.125000, -0.312500, 0.250000},
|
||||||
|
{0.125000, -0.375000, 0.125000},
|
||||||
|
{0.187500, -0.187500, 0.187500},
|
||||||
|
{0.062500, -0.125000, -0.125000},
|
||||||
|
{0.062500, 0.000000, -0.187500},
|
||||||
|
{0.125000, -0.062500, -0.187500},
|
||||||
|
{0.125000, -0.125000, -0.062500},
|
||||||
|
{0.062500, -0.062500, 0.062500},
|
||||||
|
{0.125000, -0.062500, 0.000000},
|
||||||
|
{0.125000, -0.125000, 0.000000},
|
||||||
|
{0.187500, -0.062500, 0.000000},
|
||||||
|
{0.062500, 0.000000, 0.187500},
|
||||||
|
{0.125000, -0.125000, 0.125000},
|
||||||
|
{0.125000, -0.062500, 0.125000},
|
||||||
|
{0.187500, -0.125000, 0.125000},
|
||||||
|
{0.062500, -0.062500, 0.250000},
|
||||||
|
{0.062500, 0.000000, 0.437500},
|
||||||
|
{0.187500, -0.125000, 0.375000},
|
||||||
|
{0.187500, -0.125000, 0.250000},
|
||||||
|
{0.062500, 0.125000, -0.500000},
|
||||||
|
{0.125000, 0.125000, -0.125000},
|
||||||
|
{0.125000, 0.000000, -0.125000},
|
||||||
|
{0.187500, 0.000000, -0.312500},
|
||||||
|
{0.062500, 0.062500, 0.062500},
|
||||||
|
{0.062500, 0.125000, 0.000000},
|
||||||
|
{0.187500, 0.062500, -0.062500},
|
||||||
|
{0.187500, 0.125000, 0.062500},
|
||||||
|
{0.125000, 0.125000, 0.125000},
|
||||||
|
{0.125000, 0.000000, 0.125000},
|
||||||
|
{0.187500, 0.000000, 0.062500},
|
||||||
|
{0.187500, 0.125000, 0.125000},
|
||||||
|
{0.062500, 0.125000, 0.375000},
|
||||||
|
{0.125000, 0.062500, 0.687500},
|
||||||
|
{0.125000, 0.062500, 0.187500},
|
||||||
|
{0.125000, 0.000000, 0.250000},
|
||||||
|
{0.062500, 0.187500, -0.125000},
|
||||||
|
{0.125000, 0.187500, -0.250000},
|
||||||
|
{0.187500, 0.312500, -0.312500},
|
||||||
|
{0.187500, 0.250000, -0.125000},
|
||||||
|
{0.062500, 0.437500, 0.000000},
|
||||||
|
{0.125000, 0.250000, 0.000000},
|
||||||
|
{0.187500, 0.187500, 0.062500},
|
||||||
|
{0.187500, 0.187500, -0.062500},
|
||||||
|
{0.062500, 0.187500, 0.187500},
|
||||||
|
{0.125000, 0.375000, 0.062500},
|
||||||
|
{0.187500, 0.250000, 0.125000},
|
||||||
|
{0.187500, 0.250000, 0.187500},
|
||||||
|
{0.125000, 0.312500, 0.375000},
|
||||||
|
{0.187500, 0.687500, 0.312500},
|
||||||
|
{0.187500, 0.187500, 0.250000},
|
||||||
|
{0.187500, 0.312500, 0.250000},
|
||||||
|
{0.187500, -0.562500, -0.250000},
|
||||||
|
{0.187500, -0.937500, -0.687500},
|
||||||
|
{0.312500, -0.312500, -0.375000},
|
||||||
|
{0.312500, -0.500000, -0.625000},
|
||||||
|
{0.187500, -0.312500, 0.000000},
|
||||||
|
{0.187500, -0.250000, -0.250000},
|
||||||
|
{0.250000, -0.312500, -0.125000},
|
||||||
|
{0.312500, -0.187500, 0.000000},
|
||||||
|
{0.187500, -0.437500, 0.062500},
|
||||||
|
{0.250000, -0.250000, 0.000000},
|
||||||
|
{0.250000, -0.312500, 0.125000},
|
||||||
|
{0.250000, -1.000000, 0.125000},
|
||||||
|
{0.187500, -0.312500, 0.437500},
|
||||||
|
{0.187500, -0.625000, 0.187500},
|
||||||
|
{0.187500, -0.250000, 0.187500},
|
||||||
|
{0.312500, -0.312500, 0.250000},
|
||||||
|
{0.187500, -0.062500, -0.187500},
|
||||||
|
{0.187500, -0.125000, -0.437500},
|
||||||
|
{0.250000, -0.187500, -0.125000},
|
||||||
|
{0.250000, -0.125000, -0.250000},
|
||||||
|
{0.250000, -0.187500, -0.062500},
|
||||||
|
{0.250000, -0.062500, -0.062500},
|
||||||
|
{0.250000, -0.062500, -0.125000},
|
||||||
|
{0.312500, -0.125000, -0.062500},
|
||||||
|
{0.187500, -0.187500, 0.062500},
|
||||||
|
{0.250000, -0.062500, 0.000000},
|
||||||
|
{0.250000, -0.125000, 0.000000},
|
||||||
|
{0.250000, -0.125000, 0.125000},
|
||||||
|
{0.250000, -0.062500, 0.312500},
|
||||||
|
{0.250000, -0.187500, 0.312500},
|
||||||
|
{0.250000, -0.062500, 0.250000},
|
||||||
|
{0.312500, -0.187500, 0.187500},
|
||||||
|
{0.187500, 0.125000, -0.187500},
|
||||||
|
{0.187500, 0.062500, -0.125000},
|
||||||
|
{0.312500, 0.062500, -0.312500},
|
||||||
|
{0.312500, 0.062500, -0.187500},
|
||||||
|
{0.250000, -0.062500, 0.062500},
|
||||||
|
{0.250000, 0.000000, -0.062500},
|
||||||
|
{0.250000, 0.062500, 0.000000},
|
||||||
|
{0.312500, 0.000000, 0.000000},
|
||||||
|
{0.187500, 0.000000, 0.187500},
|
||||||
|
{0.187500, 0.062500, 0.125000},
|
||||||
|
{0.312500, 0.000000, 0.125000},
|
||||||
|
{0.312500, 0.062500, 0.187500},
|
||||||
|
{0.187500, 0.062500, 0.187500},
|
||||||
|
{0.250000, 0.062500, 0.312500},
|
||||||
|
{0.250000, 0.000000, 0.250000},
|
||||||
|
{0.250000, 0.062500, 0.437500},
|
||||||
|
{0.250000, 0.250000, -0.187500},
|
||||||
|
{0.250000, 0.250000, -0.062500},
|
||||||
|
{0.250000, 0.125000, -0.062500},
|
||||||
|
{0.312500, 0.625000, -0.062500},
|
||||||
|
{0.187500, 0.312500, 0.062500},
|
||||||
|
{0.250000, 0.375000, -0.062500},
|
||||||
|
{0.250000, 0.125000, 0.062500},
|
||||||
|
{0.312500, 0.187500, -0.062500},
|
||||||
|
{0.250000, 0.437500, 0.125000},
|
||||||
|
{0.250000, 0.187500, 0.187500},
|
||||||
|
{0.250000, 0.187500, 0.062500},
|
||||||
|
{0.312500, 0.250000, 0.187500},
|
||||||
|
{0.187500, 0.187500, 0.375000},
|
||||||
|
{0.250000, 0.187500, 0.250000},
|
||||||
|
{0.250000, 0.312500, 0.437500},
|
||||||
|
{0.250000, 0.375000, 0.625000},
|
||||||
|
{0.312500, -0.250000, -0.125000},
|
||||||
|
{0.312500, -0.312500, -0.187500},
|
||||||
|
{0.312500, -0.187500, -0.062500},
|
||||||
|
{0.437500, -0.625000, -0.250000},
|
||||||
|
{0.312500, -0.312500, 0.062500},
|
||||||
|
{0.312500, -0.312500, 0.000000},
|
||||||
|
{0.312500, -0.375000, -0.062500},
|
||||||
|
{0.375000, -0.250000, 0.062500},
|
||||||
|
{0.312500, -0.437500, 0.187500},
|
||||||
|
{0.312500, -0.187500, 0.062500},
|
||||||
|
{0.312500, -0.312500, 0.125000},
|
||||||
|
{0.375000, -0.250000, 0.125000},
|
||||||
|
{0.375000, -0.375000, 0.375000},
|
||||||
|
{0.375000, -0.250000, 0.437500},
|
||||||
|
{0.375000, -0.250000, 0.250000},
|
||||||
|
{0.375000, -0.312500, 0.625000},
|
||||||
|
{0.375000, -0.125000, -0.062500},
|
||||||
|
{0.375000, -0.125000, -0.125000},
|
||||||
|
{0.375000, -0.062500, -0.125000},
|
||||||
|
{0.437500, 0.000000, -0.312500},
|
||||||
|
{0.312500, -0.125000, 0.062500},
|
||||||
|
{0.312500, 0.000000, 0.000000},
|
||||||
|
{0.375000, -0.062500, 0.000000},
|
||||||
|
{0.375000, -0.187500, 0.000000},
|
||||||
|
{0.312500, -0.062500, 0.062500},
|
||||||
|
{0.375000, -0.062500, 0.187500},
|
||||||
|
{0.375000, -0.125000, 0.125000},
|
||||||
|
{0.437500, -0.062500, 0.062500},
|
||||||
|
{0.312500, -0.125000, 0.312500},
|
||||||
|
{0.375000, -0.062500, 0.562500},
|
||||||
|
{0.375000, -0.187500, 0.250000},
|
||||||
|
{0.437500, -0.062500, 0.187500},
|
||||||
|
{0.312500, 0.000000, -0.187500},
|
||||||
|
{0.312500, 0.000000, -0.062500},
|
||||||
|
{0.375000, 0.062500, -0.187500},
|
||||||
|
{0.375000, 0.125000, -0.250000},
|
||||||
|
{0.312500, 0.062500, -0.062500},
|
||||||
|
{0.375000, 0.062500, 0.000000},
|
||||||
|
{0.375000, 0.125000, 0.000000},
|
||||||
|
{0.437500, 0.000000, 0.000000},
|
||||||
|
{0.312500, 0.062500, 0.062500},
|
||||||
|
{0.312500, 0.125000, 0.125000},
|
||||||
|
{0.375000, 0.000000, 0.062500},
|
||||||
|
{0.437500, 0.125000, 0.062500},
|
||||||
|
{0.312500, 0.062500, 0.250000},
|
||||||
|
{0.375000, 0.000000, 0.312500},
|
||||||
|
{0.375000, 0.000000, 0.187500},
|
||||||
|
{0.375000, 0.125000, 0.187500},
|
||||||
|
{0.312500, 0.187500, -0.437500},
|
||||||
|
{0.312500, 0.187500, -0.250000},
|
||||||
|
{0.437500, 0.500000, -0.375000},
|
||||||
|
{0.437500, 0.250000, -0.187500},
|
||||||
|
{0.312500, 0.250000, -0.125000},
|
||||||
|
{0.312500, 0.187500, 0.062500},
|
||||||
|
{0.312500, 0.312500, 0.000000},
|
||||||
|
{0.375000, 0.125000, -0.125000},
|
||||||
|
{0.312500, 0.250000, 0.062500},
|
||||||
|
{0.375000, 0.312500, 0.125000},
|
||||||
|
{0.375000, 0.187500, 0.125000},
|
||||||
|
{0.437500, 0.312500, 0.250000},
|
||||||
|
{0.312500, 0.437500, 0.312500},
|
||||||
|
{0.375000, 0.125000, 0.375000},
|
||||||
|
{0.375000, 0.750000, 0.687500},
|
||||||
|
{0.437500, 0.125000, 0.625000},
|
||||||
|
{0.437500, -0.250000, -0.312500},
|
||||||
|
{0.437500, -0.250000, -0.187500},
|
||||||
|
{0.500000, -0.375000, -0.312500},
|
||||||
|
{0.562500, -0.250000, -0.125000},
|
||||||
|
{0.437500, -0.250000, 0.000000},
|
||||||
|
{0.500000, -0.500000, -0.062500},
|
||||||
|
{0.500000, -0.312500, -0.125000},
|
||||||
|
{0.562500, -0.375000, 0.000000},
|
||||||
|
{0.437500, -0.312500, 0.187500},
|
||||||
|
{0.437500, -0.375000, 0.125000},
|
||||||
|
{0.500000, -0.187500, 0.062500},
|
||||||
|
{0.625000, -0.250000, 0.187500},
|
||||||
|
{0.437500, -0.375000, 0.312500},
|
||||||
|
{0.500000, -0.250000, 0.375000},
|
||||||
|
{0.562500, -0.562500, 0.312500},
|
||||||
|
{0.625000, -0.437500, 0.187500},
|
||||||
|
{0.437500, -0.187500, -0.250000},
|
||||||
|
{0.437500, -0.187500, -0.062500},
|
||||||
|
{0.437500, -0.062500, -0.125000},
|
||||||
|
{0.625000, -0.187500, -0.125000},
|
||||||
|
{0.437500, -0.125000, 0.000000},
|
||||||
|
{0.500000, -0.125000, -0.062500},
|
||||||
|
{0.562500, -0.125000, 0.000000},
|
||||||
|
{0.562500, -0.062500, -0.062500},
|
||||||
|
{0.437500, -0.062500, 0.125000},
|
||||||
|
{0.500000, -0.187500, 0.125000},
|
||||||
|
{0.562500, -0.062500, 0.125000},
|
||||||
|
{0.625000, -0.187500, 0.187500},
|
||||||
|
{0.437500, -0.062500, 0.375000},
|
||||||
|
{0.500000, -0.125000, 0.187500},
|
||||||
|
{0.562500, -0.125000, 0.562500},
|
||||||
|
{0.562500, -0.125000, 0.250000},
|
||||||
|
{0.437500, 0.062500, -0.187500},
|
||||||
|
{0.500000, 0.125000, -0.187500},
|
||||||
|
{0.562500, 0.000000, -0.187500},
|
||||||
|
{0.625000, 0.000000, -0.312500},
|
||||||
|
{0.437500, 0.062500, -0.062500},
|
||||||
|
{0.500000, 0.062500, 0.000000},
|
||||||
|
{0.500000, 0.125000, -0.062500},
|
||||||
|
{0.500000, -0.062500, 0.000000},
|
||||||
|
{0.437500, 0.062500, 0.187500},
|
||||||
|
{0.500000, 0.000000, 0.125000},
|
||||||
|
{0.500000, 0.062500, 0.125000},
|
||||||
|
{0.562500, 0.125000, 0.000000},
|
||||||
|
{0.437500, 0.062500, 0.500000},
|
||||||
|
{0.500000, -0.062500, 0.312500},
|
||||||
|
{0.562500, 0.000000, 0.250000},
|
||||||
|
{0.562500, 0.062500, 0.375000},
|
||||||
|
{0.437500, 0.312500, -0.125000},
|
||||||
|
{0.437500, 0.187500, -0.125000},
|
||||||
|
{0.562500, 0.500000, -0.125000},
|
||||||
|
{0.562500, 0.312500, -0.125000},
|
||||||
|
{0.437500, 0.250000, -0.062500},
|
||||||
|
{0.437500, 0.250000, 0.062500},
|
||||||
|
{0.500000, 0.250000, -0.062500},
|
||||||
|
{0.625000, 0.125000, -0.125000},
|
||||||
|
{0.500000, 0.375000, 0.062500},
|
||||||
|
{0.500000, 0.125000, 0.125000},
|
||||||
|
{0.500000, 0.562500, 0.125000},
|
||||||
|
{0.562500, 0.187500, 0.125000},
|
||||||
|
{0.500000, 0.187500, 0.250000},
|
||||||
|
{0.500000, 0.625000, 0.375000},
|
||||||
|
{0.500000, 0.250000, 0.187500},
|
||||||
|
{0.562500, 0.312500, 0.375000},
|
||||||
|
{0.625000, -0.312500, -0.187500},
|
||||||
|
{0.625000, -0.187500, -0.312500},
|
||||||
|
{0.812500, -0.437500, -0.437500},
|
||||||
|
{1.375000, -0.187500, -0.375000},
|
||||||
|
{0.687500, -0.312500, -0.062500},
|
||||||
|
{0.875000, -0.250000, -0.062500},
|
||||||
|
{1.062500, -0.187500, 0.062500},
|
||||||
|
{1.062500, -0.437500, -0.062500},
|
||||||
|
{0.625000, -0.250000, 0.125000},
|
||||||
|
{0.750000, -0.125000, 0.062500},
|
||||||
|
{0.812500, -0.312500, 0.125000},
|
||||||
|
{1.187500, -0.125000, 0.312500},
|
||||||
|
{0.625000, -0.312500, 0.562500},
|
||||||
|
{0.812500, -0.250000, 0.312500},
|
||||||
|
{0.875000, -0.500000, 0.312500},
|
||||||
|
{1.000000, -0.312500, 0.500000},
|
||||||
|
{0.625000, -0.062500, -0.187500},
|
||||||
|
{0.687500, 0.062500, -0.187500},
|
||||||
|
{0.812500, -0.062500, -0.187500},
|
||||||
|
{1.062500, -0.125000, -0.187500},
|
||||||
|
{0.625000, 0.062500, -0.062500},
|
||||||
|
{0.687500, -0.125000, -0.062500},
|
||||||
|
{0.875000, -0.125000, 0.000000},
|
||||||
|
{1.437500, 0.000000, 0.000000},
|
||||||
|
{0.625000, 0.000000, 0.062500},
|
||||||
|
{0.687500, -0.062500, 0.187500},
|
||||||
|
{0.750000, 0.062500, 0.000000},
|
||||||
|
{0.812500, 0.000000, 0.125000},
|
||||||
|
{0.625000, 0.062500, 0.250000},
|
||||||
|
{0.687500, -0.062500, 0.375000},
|
||||||
|
{0.687500, 0.000000, 0.500000},
|
||||||
|
{0.937500, -0.062500, 0.250000},
|
||||||
|
{0.687500, 0.187500, -0.312500},
|
||||||
|
{0.750000, 0.187500, -0.500000},
|
||||||
|
{1.000000, 0.187500, -0.312500},
|
||||||
|
{1.750000, 0.125000, -0.250000},
|
||||||
|
{0.750000, 0.187500, -0.125000},
|
||||||
|
{0.875000, 0.187500, -0.062500},
|
||||||
|
{0.937500, 0.125000, 0.000000},
|
||||||
|
{1.187500, 0.187500, -0.187500},
|
||||||
|
{0.625000, 0.187500, 0.250000},
|
||||||
|
{0.625000, 0.187500, 0.125000},
|
||||||
|
{0.687500, 0.187500, 0.000000},
|
||||||
|
{0.937500, 0.250000, 0.250000},
|
||||||
|
{0.687500, 0.187500, 0.437500},
|
||||||
|
{0.750000, 0.062500, 0.312500},
|
||||||
|
{0.937500, 0.125000, 0.437500},
|
||||||
|
{1.437500, 0.187500, 0.437500},
|
||||||
|
{0.625000, 0.250000, -0.062500},
|
||||||
|
{0.687500, 0.375000, 0.000000},
|
||||||
|
{1.062500, 0.937500, -0.250000},
|
||||||
|
{1.375000, 0.375000, -0.250000},
|
||||||
|
{0.812500, 0.312500, 0.125000},
|
||||||
|
{0.875000, 0.500000, 0.000000},
|
||||||
|
{1.062500, 0.375000, 0.062500},
|
||||||
|
{1.500000, 0.437500, 0.125000},
|
||||||
|
{0.625000, 0.375000, 0.250000},
|
||||||
|
{0.875000, 0.375000, 0.312500},
|
||||||
|
{1.125000, 0.625000, 0.187500},
|
||||||
|
{1.187500, 0.250000, 0.187500},
|
||||||
|
{0.687500, 0.437500, 0.437500},
|
||||||
|
{0.750000, 0.375000, 0.687500},
|
||||||
|
{0.937500, 0.750000, 0.500000},
|
||||||
|
{1.312500, 0.687500, 0.625000}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRBA58 Vector Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbePlusPRBA58[128][4] = {
|
||||||
|
{-0.460938, -0.265625, -0.281250, -0.062500},
|
||||||
|
{-0.367188, -0.117188, -0.078125, -0.054688},
|
||||||
|
{-0.250000, -0.312500, -0.164063, -0.101563},
|
||||||
|
{-0.156250, -0.078125, -0.085938, -0.203125},
|
||||||
|
{-0.468750, -0.085938, -0.171875, 0.164063},
|
||||||
|
{-0.210938, -0.039063, -0.117188, 0.085938},
|
||||||
|
{-0.187500, -0.156250, -0.289063, 0.070313},
|
||||||
|
{-0.179688, -0.117188, -0.148438, -0.046875},
|
||||||
|
{-0.320313, -0.031250, 0.140625, -0.132813},
|
||||||
|
{-0.289063, -0.140625, 0.179688, 0.015625},
|
||||||
|
{-0.179688, -0.226563, -0.007813, -0.101563},
|
||||||
|
{-0.156250, -0.031250, 0.015625, -0.093750},
|
||||||
|
{-0.390625, -0.273438, 0.046875, 0.031250},
|
||||||
|
{-0.195313, -0.203125, -0.070313, 0.039063},
|
||||||
|
{-0.171875, -0.156250, -0.039063, 0.171875},
|
||||||
|
{-0.156250, -0.085938, 0.085938, 0.125000},
|
||||||
|
{-0.304688, 0.054688, -0.210938, -0.085938},
|
||||||
|
{-0.265625, 0.140625, -0.031250, -0.132813},
|
||||||
|
{-0.242188, 0.078125, -0.031250, 0.015625},
|
||||||
|
{-0.203125, 0.000000, -0.085938, -0.070313},
|
||||||
|
{-0.453125, 0.171875, -0.062500, 0.031250},
|
||||||
|
{-0.289063, 0.125000, -0.156250, 0.093750},
|
||||||
|
{-0.179688, 0.257813, -0.054688, 0.273438},
|
||||||
|
{-0.171875, 0.226563, -0.109375, 0.015625},
|
||||||
|
{-0.312500, -0.007813, 0.000000, 0.085938},
|
||||||
|
{-0.265625, 0.265625, 0.046875, 0.101563},
|
||||||
|
{-0.234375, 0.109375, 0.125000, -0.046875},
|
||||||
|
{-0.171875, -0.015625, 0.093750, 0.007813},
|
||||||
|
{-0.414063, 0.046875, 0.101563, 0.203125},
|
||||||
|
{-0.179688, 0.093750, 0.210938, 0.125000},
|
||||||
|
{-0.179688, -0.007813, 0.007813, 0.273438},
|
||||||
|
{-0.171875, 0.085938, 0.007813, 0.132813},
|
||||||
|
{-0.062500, -0.117188, -0.257813, -0.156250},
|
||||||
|
{-0.054688, -0.226563, -0.109375, -0.015625},
|
||||||
|
{-0.046875, -0.164063, -0.070313, -0.117188},
|
||||||
|
{-0.039063, -0.031250, -0.093750, -0.085938},
|
||||||
|
{-0.156250, -0.031250, -0.015625, 0.039063},
|
||||||
|
{-0.085938, 0.015625, -0.179688, 0.164063},
|
||||||
|
{-0.078125, -0.078125, -0.070313, 0.046875},
|
||||||
|
{-0.046875, -0.195313, -0.062500, 0.109375},
|
||||||
|
{-0.093750, -0.046875, 0.109375, -0.101563},
|
||||||
|
{-0.054688, -0.007813, 0.007813, -0.007813},
|
||||||
|
{-0.039063, -0.132813, 0.031250, -0.031250},
|
||||||
|
{-0.023438, -0.148438, 0.195313, -0.085938},
|
||||||
|
{-0.148438, -0.109375, 0.023438, 0.000000},
|
||||||
|
{-0.039063, -0.085938, 0.031250, 0.085938},
|
||||||
|
{-0.039063, -0.226563, 0.117188, 0.070313},
|
||||||
|
{-0.015625, -0.015625, 0.156250, 0.156250},
|
||||||
|
{-0.109375, 0.132813, -0.109375, -0.140625},
|
||||||
|
{-0.093750, 0.023438, -0.187500, -0.007813},
|
||||||
|
{-0.093750, 0.382813, -0.062500, -0.101563},
|
||||||
|
{-0.023438, 0.101563, -0.062500, -0.007813},
|
||||||
|
{-0.140625, 0.195313, -0.273438, 0.132813},
|
||||||
|
{-0.109375, 0.125000, -0.117188, 0.062500},
|
||||||
|
{-0.085938, 0.015625, -0.078125, 0.031250},
|
||||||
|
{-0.031250, 0.203125, -0.023438, 0.125000},
|
||||||
|
{-0.125000, 0.156250, 0.078125, -0.140625},
|
||||||
|
{-0.117188, 0.085938, 0.312500, -0.101563},
|
||||||
|
{-0.093750, 0.062500, 0.007813, -0.078125},
|
||||||
|
{-0.046875, 0.046875, 0.148438, -0.023438},
|
||||||
|
{-0.125000, 0.148438, 0.007813, 0.015625},
|
||||||
|
{-0.085938, 0.046875, 0.054688, 0.039063},
|
||||||
|
{-0.054688, 0.140625, 0.117188, 0.101563},
|
||||||
|
{-0.054688, 0.039063, -0.015625, 0.109375},
|
||||||
|
{0.046875, -0.062500, -0.054688, -0.226563},
|
||||||
|
{0.062500, -0.132813, -0.093750, -0.101563},
|
||||||
|
{0.078125, -0.015625, -0.132813, -0.023438},
|
||||||
|
{0.085938, -0.421875, -0.140625, -0.062500},
|
||||||
|
{-0.007813, -0.054688, -0.054688, 0.179688},
|
||||||
|
{0.015625, -0.078125, -0.203125, 0.054688},
|
||||||
|
{0.015625, -0.093750, -0.078125, 0.023438},
|
||||||
|
{0.062500, -0.179688, -0.187500, 0.148438},
|
||||||
|
{0.007813, -0.039063, 0.046875, -0.093750},
|
||||||
|
{0.023438, 0.031250, 0.117188, -0.179688},
|
||||||
|
{0.101563, -0.171875, 0.093750, -0.171875},
|
||||||
|
{0.101563, -0.023438, -0.023438, -0.125000},
|
||||||
|
{-0.007813, -0.039063, 0.109375, 0.023438},
|
||||||
|
{0.046875, -0.015625, 0.015625, 0.078125},
|
||||||
|
{0.054688, -0.046875, -0.023438, -0.023438},
|
||||||
|
{0.070313, -0.140625, 0.062500, -0.015625},
|
||||||
|
{0.007813, 0.070313, -0.031250, -0.210938},
|
||||||
|
{0.015625, 0.140625, -0.179688, -0.046875},
|
||||||
|
{0.023438, 0.039063, -0.039063, -0.039063},
|
||||||
|
{0.054688, 0.117188, -0.007813, -0.101563},
|
||||||
|
{0.015625, 0.046875, -0.117188, 0.078125},
|
||||||
|
{0.054688, 0.054688, -0.281250, 0.164063},
|
||||||
|
{0.062500, 0.273438, -0.125000, 0.085938},
|
||||||
|
{0.093750, 0.101563, -0.070313, 0.046875},
|
||||||
|
{-0.015625, 0.125000, 0.046875, -0.031250},
|
||||||
|
{-0.007813, 0.273438, 0.054688, 0.000000},
|
||||||
|
{0.070313, 0.039063, 0.070313, -0.023438},
|
||||||
|
{0.109375, 0.195313, 0.093750, -0.218750},
|
||||||
|
{0.046875, 0.078125, 0.039063, 0.070313},
|
||||||
|
{0.054688, 0.101563, 0.023438, 0.265625},
|
||||||
|
{0.070313, 0.125000, 0.273438, 0.031250},
|
||||||
|
{0.093750, 0.335938, 0.164063, 0.132813},
|
||||||
|
{0.195313, -0.101563, 0.015625, -0.046875},
|
||||||
|
{0.234375, -0.171875, -0.164063, -0.125000},
|
||||||
|
{0.296875, -0.085938, -0.117188, 0.031250},
|
||||||
|
{0.507813, -0.179688, -0.117188, 0.015625},
|
||||||
|
{0.109375, -0.179688, -0.046875, 0.046875},
|
||||||
|
{0.132813, -0.054688, -0.039063, 0.070313},
|
||||||
|
{0.171875, 0.007813, -0.117188, 0.179688},
|
||||||
|
{0.429688, 0.015625, -0.039063, 0.218750},
|
||||||
|
{0.132813, -0.015625, 0.156250, -0.085938},
|
||||||
|
{0.140625, -0.125000, 0.218750, 0.000000},
|
||||||
|
{0.265625, -0.250000, 0.101563, -0.085938},
|
||||||
|
{0.382813, -0.109375, 0.101563, -0.125000},
|
||||||
|
{0.117188, -0.078125, 0.085938, 0.195313},
|
||||||
|
{0.218750, -0.210938, 0.054688, 0.140625},
|
||||||
|
{0.265625, -0.031250, 0.054688, 0.148438},
|
||||||
|
{0.304688, 0.007813, 0.250000, 0.023438},
|
||||||
|
{0.117188, 0.289063, -0.226563, -0.109375},
|
||||||
|
{0.132813, 0.023438, -0.195313, -0.132813},
|
||||||
|
{0.164063, 0.187500, -0.070313, -0.078125},
|
||||||
|
{0.281250, 0.046875, -0.101563, -0.250000},
|
||||||
|
{0.164063, 0.023438, -0.023438, -0.039063},
|
||||||
|
{0.171875, 0.148438, -0.265625, 0.046875},
|
||||||
|
{0.210938, 0.031250, -0.156250, 0.000000},
|
||||||
|
{0.390625, 0.179688, -0.101563, -0.031250},
|
||||||
|
{0.234375, 0.085938, 0.031250, -0.148438},
|
||||||
|
{0.250000, 0.265625, 0.156250, -0.070313},
|
||||||
|
{0.312500, 0.054688, 0.093750, -0.007813},
|
||||||
|
{0.531250, 0.210938, 0.085938, -0.015625},
|
||||||
|
{0.117188, 0.179688, 0.054688, 0.031250},
|
||||||
|
{0.132813, 0.039063, 0.140625, 0.070313},
|
||||||
|
{0.218750, 0.070313, 0.007813, 0.039063},
|
||||||
|
{0.226563, 0.242188, 0.007813, 0.148438}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbePlusHOCb5[16][4] = {
|
||||||
|
{-0.617188, -0.015625, 0.015625, -0.023438},
|
||||||
|
{-0.507813, -0.382813, -0.312500, -0.117188},
|
||||||
|
{-0.328125, 0.046875, 0.007813, -0.015625},
|
||||||
|
{-0.320313, -0.281250, -0.023438, -0.023438},
|
||||||
|
{-0.171875, 0.140625, -0.179688, -0.007813},
|
||||||
|
{-0.148438, 0.226563, 0.039063, -0.039063},
|
||||||
|
{-0.140625, -0.007813, -0.007813, -0.015625},
|
||||||
|
{-0.109375, -0.101563, 0.179688, -0.062500},
|
||||||
|
{-0.109375, -0.109375, -0.031250, 0.187500},
|
||||||
|
{-0.109375, -0.218750, -0.273438, -0.140625},
|
||||||
|
{0.007813, -0.007813, -0.015625, -0.015625},
|
||||||
|
{0.078125, -0.265625, -0.007813, 0.007813},
|
||||||
|
{0.101563, 0.054688, -0.210938, -0.007813},
|
||||||
|
{0.164063, 0.242188, 0.093750, 0.039063},
|
||||||
|
{0.179688, -0.023438, 0.007813, -0.007813},
|
||||||
|
{0.460938, 0.015625, -0.015625, 0.007813}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbePlusHOCb6[16][4] = {
|
||||||
|
{-0.429688, -0.046875, 0.039063, 0.000000},
|
||||||
|
{-0.296875, 0.187500, 0.125000, 0.015625},
|
||||||
|
{-0.203125, -0.218750, -0.039063, -0.007813},
|
||||||
|
{-0.179688, 0.007813, -0.007813, 0.000000},
|
||||||
|
{-0.171875, 0.265625, -0.085938, -0.039063},
|
||||||
|
{-0.046875, -0.070313, 0.203125, -0.023438},
|
||||||
|
{-0.023438, 0.125000, 0.031250, -0.023438},
|
||||||
|
{-0.007813, 0.000000, -0.195313, -0.007813},
|
||||||
|
{0.007813, -0.046875, -0.007813, -0.015625},
|
||||||
|
{0.015625, -0.031250, 0.039063, 0.195313},
|
||||||
|
{0.031250, -0.273438, -0.015625, -0.007813},
|
||||||
|
{0.140625, 0.257813, 0.015625, 0.007813},
|
||||||
|
{0.164063, 0.015625, 0.007813, -0.023438},
|
||||||
|
{0.210938, -0.148438, -0.187500, 0.039063},
|
||||||
|
{0.273438, -0.179688, 0.054688, -0.007813},
|
||||||
|
{0.421875, 0.054688, -0.039063, 0.000000}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbePlusHOCb7[16][4] = {
|
||||||
|
{-0.382813, -0.101563, 0.007813, 0.015625},
|
||||||
|
{-0.335938, 0.226563, 0.015625, -0.007813},
|
||||||
|
{-0.156250, 0.031250, -0.039063, -0.054688},
|
||||||
|
{-0.156250, -0.015625, 0.187500, -0.015625},
|
||||||
|
{-0.085938, -0.257813, 0.023438, -0.007813},
|
||||||
|
{-0.070313, -0.148438, -0.203125, -0.023438},
|
||||||
|
{-0.031250, 0.187500, -0.156250, 0.007813},
|
||||||
|
{-0.023438, -0.007813, -0.015625, 0.179688},
|
||||||
|
{-0.015625, 0.203125, 0.070313, -0.023438},
|
||||||
|
{0.000000, -0.039063, -0.007813, -0.023438},
|
||||||
|
{0.140625, -0.078125, 0.179688, -0.007813},
|
||||||
|
{0.164063, 0.023438, -0.007813, -0.015625},
|
||||||
|
{0.187500, -0.007813, -0.218750, -0.007813},
|
||||||
|
{0.218750, 0.242188, 0.023438, 0.031250},
|
||||||
|
{0.234375, -0.234375, -0.039063, 0.007813},
|
||||||
|
{0.445313, 0.054688, -0.007813, 0.000000}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbePlusHOCb8[16][4] = {
|
||||||
|
{-0.453125, 0.179688, 0.078125, -0.015625},
|
||||||
|
{-0.414063, -0.179688, -0.031250, 0.015625},
|
||||||
|
{-0.281250, 0.187500, -0.203125, 0.046875},
|
||||||
|
{-0.210938, -0.007813, -0.031250, -0.031250},
|
||||||
|
{-0.148438, -0.031250, 0.218750, -0.054688},
|
||||||
|
{-0.140625, -0.085938, 0.039063, 0.187500},
|
||||||
|
{-0.117188, 0.234375, 0.031250, -0.054688},
|
||||||
|
{-0.062500, -0.273438, -0.007813, -0.015625},
|
||||||
|
{-0.054688, 0.093750, -0.078125, 0.078125},
|
||||||
|
{-0.023438, -0.062500, -0.210938, -0.054688},
|
||||||
|
{0.023438, 0.000000, 0.023438, -0.046875},
|
||||||
|
{0.125000, 0.234375, -0.187500, -0.015625},
|
||||||
|
{0.164063, -0.054688, -0.093750, 0.070313},
|
||||||
|
{0.187500, 0.179688, 0.093750, 0.015625},
|
||||||
|
{0.203125, -0.171875, 0.140625, -0.015625},
|
||||||
|
{0.421875, -0.039063, -0.046875, -0.007813}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __AMBE3600x2400_CONST_H__
|
||||||
@ -0,0 +1,600 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "vocoder/mbe.h"
|
||||||
|
#include "vocoder/ambe3600x2450_const.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4244)
|
||||||
|
#endif
|
||||||
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_eccAmbe3600x2450C0(char ambe_fr[4][24])
|
||||||
|
{
|
||||||
|
int j, errs;
|
||||||
|
char in[23], out[23];
|
||||||
|
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
in[j] = ambe_fr[0][j + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = mbe_golay2312(in, out);
|
||||||
|
// ambe_fr[0][0] should be the C0 golay24 parity bit.
|
||||||
|
// TODO: actually test that here...
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
ambe_fr[0][j + 1] = out[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_eccAmbe3600x2450Data(char ambe_fr[4][24], char* ambe_d)
|
||||||
|
{
|
||||||
|
int j, errs;
|
||||||
|
char* ambe, gin[24], gout[24];
|
||||||
|
|
||||||
|
ambe = ambe_d;
|
||||||
|
|
||||||
|
// just copy C0
|
||||||
|
for (j = 23; j > 11; j--) {
|
||||||
|
*ambe = ambe_fr[0][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ecc and copy C1
|
||||||
|
for (j = 0; j < 23; j++) {
|
||||||
|
gin[j] = ambe_fr[1][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = mbe_golay2312(gin, gout);
|
||||||
|
for (j = 22; j > 10; j--) {
|
||||||
|
*ambe = gout[j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just copy C2
|
||||||
|
for (j = 10; j >= 0; j--) {
|
||||||
|
*ambe = ambe_fr[2][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just copy C3
|
||||||
|
for (j = 13; j >= 0; j--) {
|
||||||
|
*ambe = ambe_fr[3][j];
|
||||||
|
ambe++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_decodeAmbe2450Parms(char* ambe_d, mbe_parms* cur_mp, mbe_parms* prev_mp)
|
||||||
|
{
|
||||||
|
int ji, i, j, k, l, L, L9, m, am, ak;
|
||||||
|
int intkl[57];
|
||||||
|
int b0, b1, b2, b3, b4, b5, b6, b7, b8;
|
||||||
|
float f0, Cik[5][18], flokl[57], deltal[57];
|
||||||
|
float Sum42, Sum43, Tl[57], Gm[9], Ri[9], sum, c1, c2;
|
||||||
|
int silence;
|
||||||
|
int Ji[5], jl;
|
||||||
|
float deltaGamma, BigGamma;
|
||||||
|
float unvc, rconst;
|
||||||
|
|
||||||
|
silence = 0;
|
||||||
|
|
||||||
|
// copy repeat from prev_mp
|
||||||
|
cur_mp->repeat = prev_mp->repeat;
|
||||||
|
|
||||||
|
// decode fundamental frequency w0 from b0
|
||||||
|
b0 = 0;
|
||||||
|
b0 |= ambe_d[0] << 6;
|
||||||
|
b0 |= ambe_d[1] << 5;
|
||||||
|
b0 |= ambe_d[2] << 4;
|
||||||
|
b0 |= ambe_d[3] << 3;
|
||||||
|
b0 |= ambe_d[37] << 2;
|
||||||
|
b0 |= ambe_d[38] << 1;
|
||||||
|
b0 |= ambe_d[39];
|
||||||
|
if ((b0 >= 120) && (b0 <= 123)) {
|
||||||
|
// if w0 bits are 1111000, 1111001, 1111010 or 1111011, frame is erasure
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Erasure Frame");
|
||||||
|
#endif
|
||||||
|
return (2);
|
||||||
|
}
|
||||||
|
else if ((b0 == 124) || (b0 == 125)) {
|
||||||
|
// if w0 bits are 1111100 or 1111101, frame is silence
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Silence Frame");
|
||||||
|
#endif
|
||||||
|
silence = 1;
|
||||||
|
cur_mp->w0 = ((float)2 * M_PI) / (float)32;
|
||||||
|
f0 = (float)1 / (float)32;
|
||||||
|
L = 14;
|
||||||
|
cur_mp->L = 14;
|
||||||
|
for (l = 1; l <= L; l++) {
|
||||||
|
cur_mp->Vl[l] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((b0 == 126) || (b0 == 127)) {
|
||||||
|
// if w0 bits are 1111110 or 1111111, frame is tone
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tone Frame");
|
||||||
|
#endif
|
||||||
|
return (3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (silence == 0) {
|
||||||
|
// w0 from specification document
|
||||||
|
f0 = AmbeW0table[b0];
|
||||||
|
cur_mp->w0 = f0 * (float)2 * M_PI;
|
||||||
|
// w0 from patent filings
|
||||||
|
//f0 = powf (2, ((float) b0 + (float) 195.626) / -(float) 45.368);
|
||||||
|
//cur_mp->w0 = f0 * (float) 2 *M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
unvc = (float)0.2046 / sqrtf(cur_mp->w0);
|
||||||
|
//unvc = (float) 1;
|
||||||
|
//unvc = (float) 0.2046 / sqrtf (f0);
|
||||||
|
|
||||||
|
// decode L
|
||||||
|
if (silence == 0) {
|
||||||
|
// L from specification document
|
||||||
|
// lookup L in tabl3
|
||||||
|
L = AmbeLtable[b0];
|
||||||
|
// L formula from patent filings
|
||||||
|
//L=(int)((float)0.4627 / f0);
|
||||||
|
cur_mp->L = L;
|
||||||
|
}
|
||||||
|
L9 = L - 9;
|
||||||
|
|
||||||
|
// decode V/UV parameters
|
||||||
|
// load b1 from ambe_d
|
||||||
|
b1 = 0;
|
||||||
|
b1 |= ambe_d[4] << 4;
|
||||||
|
b1 |= ambe_d[5] << 3;
|
||||||
|
b1 |= ambe_d[6] << 2;
|
||||||
|
b1 |= ambe_d[7] << 1;
|
||||||
|
b1 |= ambe_d[35];
|
||||||
|
|
||||||
|
for (l = 1; l <= L; l++) {
|
||||||
|
// jl from specification document
|
||||||
|
jl = (int)((float)l * (float)16.0 * f0);
|
||||||
|
// jl from patent filings?
|
||||||
|
//jl = (int)(((float)l * (float)16.0 * f0) + 0.25);
|
||||||
|
|
||||||
|
if (silence == 0)
|
||||||
|
{
|
||||||
|
cur_mp->Vl[l] = AmbeVuv[b1][jl];
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: jl[%i]:%i Vl[%i]:%i", l, jl, l, cur_mp->Vl[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b0:%i w0:%f L:%i b1:%i\n", b0, cur_mp->w0, L, b1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decode gain vector
|
||||||
|
// load b2 from ambe_d
|
||||||
|
b2 = 0;
|
||||||
|
b2 |= ambe_d[8] << 4;
|
||||||
|
b2 |= ambe_d[9] << 3;
|
||||||
|
b2 |= ambe_d[10] << 2;
|
||||||
|
b2 |= ambe_d[11] << 1;
|
||||||
|
b2 |= ambe_d[36];
|
||||||
|
|
||||||
|
deltaGamma = AmbeDg[b2];
|
||||||
|
cur_mp->gamma = deltaGamma + ((float)0.5 * prev_mp->gamma);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b2: %i, deltaGamma: %f gamma: %f gamma-1: %f\n", b2, deltaGamma, cur_mp->gamma, prev_mp->gamma);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decode PRBA vectors
|
||||||
|
Gm[1] = 0;
|
||||||
|
|
||||||
|
// load b3 from ambe_d
|
||||||
|
b3 = 0;
|
||||||
|
b3 |= ambe_d[12] << 8;
|
||||||
|
b3 |= ambe_d[13] << 7;
|
||||||
|
b3 |= ambe_d[14] << 6;
|
||||||
|
b3 |= ambe_d[15] << 5;
|
||||||
|
b3 |= ambe_d[16] << 4;
|
||||||
|
b3 |= ambe_d[17] << 3;
|
||||||
|
b3 |= ambe_d[18] << 2;
|
||||||
|
b3 |= ambe_d[19] << 1;
|
||||||
|
b3 |= ambe_d[40];
|
||||||
|
Gm[2] = AmbePRBA24[b3][0];
|
||||||
|
Gm[3] = AmbePRBA24[b3][1];
|
||||||
|
Gm[4] = AmbePRBA24[b3][2];
|
||||||
|
|
||||||
|
// load b4 from ambe_d
|
||||||
|
b4 = 0;
|
||||||
|
b4 |= ambe_d[20] << 6;
|
||||||
|
b4 |= ambe_d[21] << 5;
|
||||||
|
b4 |= ambe_d[22] << 4;
|
||||||
|
b4 |= ambe_d[23] << 3;
|
||||||
|
b4 |= ambe_d[41] << 2;
|
||||||
|
b4 |= ambe_d[42] << 1;
|
||||||
|
b4 |= ambe_d[43];
|
||||||
|
Gm[5] = AmbePRBA58[b4][0];
|
||||||
|
Gm[6] = AmbePRBA58[b4][1];
|
||||||
|
Gm[7] = AmbePRBA58[b4][2];
|
||||||
|
Gm[8] = AmbePRBA58[b4][3];
|
||||||
|
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: b3: %i Gm[2]: %f Gm[3]: %f Gm[4]: %f b4: %i Gm[5]: %f Gm[6]: %f Gm[7]: %f Gm[8]: %f\n", b3, Gm[2], Gm[3], Gm[4], b4, Gm[5], Gm[6], Gm[7], Gm[8]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// compute Ri
|
||||||
|
for (i = 1; i <= 8; i++) {
|
||||||
|
sum = 0;
|
||||||
|
for (m = 1; m <= 8; m++) {
|
||||||
|
if (m == 1) {
|
||||||
|
am = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
am = 2;
|
||||||
|
}
|
||||||
|
sum = sum + ((float)am * Gm[m] * cosf((M_PI * (float)(m - 1) * ((float)i - (float)0.5)) / (float)8));
|
||||||
|
}
|
||||||
|
Ri[i] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: R%i: %f ", i, Ri[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate first to elements of each Ci,k block from PRBA vector
|
||||||
|
rconst = ((float)1 / ((float)2 * M_SQRT2));
|
||||||
|
Cik[1][1] = (float)0.5 * (Ri[1] + Ri[2]);
|
||||||
|
Cik[1][2] = rconst * (Ri[1] - Ri[2]);
|
||||||
|
Cik[2][1] = (float)0.5 * (Ri[3] + Ri[4]);
|
||||||
|
Cik[2][2] = rconst * (Ri[3] - Ri[4]);
|
||||||
|
Cik[3][1] = (float)0.5 * (Ri[5] + Ri[6]);
|
||||||
|
Cik[3][2] = rconst * (Ri[5] - Ri[6]);
|
||||||
|
Cik[4][1] = (float)0.5 * (Ri[7] + Ri[8]);
|
||||||
|
Cik[4][2] = rconst * (Ri[7] - Ri[8]);
|
||||||
|
|
||||||
|
// decode HOC
|
||||||
|
|
||||||
|
// load b5 from ambe_d
|
||||||
|
b5 = 0;
|
||||||
|
b5 |= ambe_d[24] << 4;
|
||||||
|
b5 |= ambe_d[25] << 3;
|
||||||
|
b5 |= ambe_d[26] << 2;
|
||||||
|
b5 |= ambe_d[27] << 1;
|
||||||
|
b5 |= ambe_d[44];
|
||||||
|
|
||||||
|
// load b6 from ambe_d
|
||||||
|
b6 = 0;
|
||||||
|
b6 |= ambe_d[28] << 3;
|
||||||
|
b6 |= ambe_d[29] << 2;
|
||||||
|
b6 |= ambe_d[30] << 1;
|
||||||
|
b6 |= ambe_d[45];
|
||||||
|
|
||||||
|
// load b7 from ambe_d
|
||||||
|
b7 = 0;
|
||||||
|
b7 |= ambe_d[31] << 3;
|
||||||
|
b7 |= ambe_d[32] << 2;
|
||||||
|
b7 |= ambe_d[33] << 1;
|
||||||
|
b7 |= ambe_d[46];
|
||||||
|
|
||||||
|
// load b8 from ambe_d
|
||||||
|
b8 = 0;
|
||||||
|
b8 |= ambe_d[34] << 2;
|
||||||
|
b8 |= ambe_d[47] << 1;
|
||||||
|
b8 |= ambe_d[48];
|
||||||
|
|
||||||
|
// lookup Ji
|
||||||
|
Ji[1] = AmbeLmprbl[L][0];
|
||||||
|
Ji[2] = AmbeLmprbl[L][1];
|
||||||
|
Ji[3] = AmbeLmprbl[L][2];
|
||||||
|
Ji[4] = AmbeLmprbl[L][3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i", Ji[1], Ji[2], Ji[3], Ji[4]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: b5: %i b6: %i b7: %i b8: %i", b5, b6, b7, b8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Load Ci,k with the values from the HOC tables
|
||||||
|
// there appear to be a couple typos in eq. 37 so we will just do what makes sense
|
||||||
|
// (3 <= k <= Ji and k<=6)
|
||||||
|
for (k = 3; k <= Ji[1]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[1][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[1][k] = AmbeHOCb5[b5][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C1,%i: %f ", k, Cik[1][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[2]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[2][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[2][k] = AmbeHOCb6[b6][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C2,%i: %f ", k, Cik[2][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[3]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[3][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[3][k] = AmbeHOCb7[b7][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C3,%i: %f ", k, Cik[3][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (k = 3; k <= Ji[4]; k++) {
|
||||||
|
if (k > 6) {
|
||||||
|
Cik[4][k] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cik[4][k] = AmbeHOCb8[b8][k - 3];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: C4,%i: %f ", k, Cik[4][k]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// inverse DCT each Ci,k to give ci,j (Tl)
|
||||||
|
l = 1;
|
||||||
|
for (i = 1; i <= 4; i++) {
|
||||||
|
ji = Ji[i];
|
||||||
|
for (j = 1; j <= ji; j++) {
|
||||||
|
sum = 0;
|
||||||
|
for (k = 1; k <= ji; k++) {
|
||||||
|
if (k == 1) {
|
||||||
|
ak = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ak = 2;
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: j: %i Cik[%i][%i]: %f ", j, i, k, Cik[i][k]);
|
||||||
|
#endif
|
||||||
|
sum = sum + ((float)ak * Cik[i][k] * cosf((M_PI * (float)(k - 1) * ((float)j - (float)0.5)) / (float)ji));
|
||||||
|
}
|
||||||
|
Tl[l] = sum;
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Tl[%i]: %f", l, Tl[l]);
|
||||||
|
#endif
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine log2Ml by applying ci,j to previous log2Ml
|
||||||
|
|
||||||
|
// fix for when L > L(-1)
|
||||||
|
if (cur_mp->L > prev_mp->L) {
|
||||||
|
for (l = (prev_mp->L) + 1; l <= cur_mp->L; l++) {
|
||||||
|
prev_mp->Ml[l] = prev_mp->Ml[prev_mp->L];
|
||||||
|
prev_mp->log2Ml[l] = prev_mp->log2Ml[prev_mp->L];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_mp->log2Ml[0] = prev_mp->log2Ml[1];
|
||||||
|
prev_mp->Ml[0] = prev_mp->Ml[1];
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
Sum43 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
// eq. 40
|
||||||
|
flokl[l] = ((float)prev_mp->L / (float)cur_mp->L) * (float)l;
|
||||||
|
intkl[l] = (int)(flokl[l]);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flok%i: %f, intk%i: %i ", l, flokl[l], l, intkl[l]);
|
||||||
|
#endif
|
||||||
|
// eq. 41
|
||||||
|
deltal[l] = flokl[l] - (float)intkl[l];
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: delta%i: %f ", l, deltal[l]);
|
||||||
|
#endif
|
||||||
|
// eq 43
|
||||||
|
Sum43 = Sum43 + ((((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]) + (deltal[l] * prev_mp->log2Ml[intkl[l] + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum43 = (((float)0.65 / (float)cur_mp->L) * Sum43);
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: Sum43: %f", Sum43);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Part 2
|
||||||
|
Sum42 = 0;
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
Sum42 += Tl[l];
|
||||||
|
}
|
||||||
|
|
||||||
|
Sum42 = Sum42 / (float)cur_mp->L;
|
||||||
|
BigGamma = cur_mp->gamma - ((float)0.5 * (log((float)cur_mp->L) / log((float)2))) - Sum42;
|
||||||
|
//BigGamma=cur_mp->gamma - ((float)0.5 * log((float)cur_mp->L)) - Sum42;
|
||||||
|
|
||||||
|
// Part 3
|
||||||
|
for (l = 1; l <= cur_mp->L; l++) {
|
||||||
|
c1 = ((float)0.65 * ((float)1 - deltal[l]) * prev_mp->log2Ml[intkl[l]]);
|
||||||
|
c2 = ((float)0.65 * deltal[l] * prev_mp->log2Ml[intkl[l] + 1]);
|
||||||
|
cur_mp->log2Ml[l] = Tl[l] + c1 + c2 - Sum43 + BigGamma;
|
||||||
|
// inverse log to generate spectral amplitudes
|
||||||
|
if (cur_mp->Vl[l] == 1) {
|
||||||
|
cur_mp->Ml[l] = exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur_mp->Ml[l] = unvc * exp((float)0.693 * cur_mp->log2Ml[l]);
|
||||||
|
}
|
||||||
|
#ifdef AMBE_DEBUG
|
||||||
|
fprintf(stderr, "MBE: AMBE: flokl[%i]: %f, intkl[%i]: %i", l, flokl[l], l, intkl[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: deltal[%i]: %f", l, deltal[l]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: prev_mp->log2Ml[%i]: %f", l, prev_mp->log2Ml[intkl[l]]);
|
||||||
|
fprintf(stderr, "MBE: AMBE: BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f", BigGamma, c1, c2, Sum43, l, Tl[l], l, cur_mp->log2Ml[l], l, cur_mp->Ml[l]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_demodulateAmbe3600x2450Data(char ambe_fr[4][24])
|
||||||
|
{
|
||||||
|
int i, j, k;
|
||||||
|
unsigned short pr[115];
|
||||||
|
unsigned short foo = 0;
|
||||||
|
|
||||||
|
// create pseudo-random modulator
|
||||||
|
for (i = 23; i >= 12; i--) {
|
||||||
|
foo <<= 1;
|
||||||
|
foo |= ambe_fr[0][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pr[0] = (16 * foo);
|
||||||
|
for (i = 1; i < 24; i++) {
|
||||||
|
pr[i] = (173 * pr[i - 1]) + 13849 - (65536 * (((173 * pr[i - 1]) + 13849) / 65536));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 1; i < 24; i++) {
|
||||||
|
pr[i] = pr[i] / 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
// demodulate ambe_fr with pr
|
||||||
|
k = 1;
|
||||||
|
for (j = 22; j >= 0; j--) {
|
||||||
|
ambe_fr[1][j] = ((ambe_fr[1][j]) ^ pr[k]);
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe2450DataF(float* aout_buf, int* errs, int* errs2, char* err_str, char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
int i, bad;
|
||||||
|
|
||||||
|
for (i = 0; i < *errs2; i++) {
|
||||||
|
*err_str = '=';
|
||||||
|
err_str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bad = mbe_decodeAmbe2450Parms(ambe_d, cur_mp, prev_mp);
|
||||||
|
if (bad == 2) {
|
||||||
|
// Erasure frame
|
||||||
|
*err_str = 'E';
|
||||||
|
err_str++;
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
else if (bad == 3) {
|
||||||
|
// Tone Frame
|
||||||
|
*err_str = 'T';
|
||||||
|
err_str++;
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
else if (*errs2 > 3) {
|
||||||
|
mbe_useLastMbeParms(cur_mp, prev_mp);
|
||||||
|
cur_mp->repeat++;
|
||||||
|
*err_str = 'R';
|
||||||
|
err_str++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur_mp->repeat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bad == 0) {
|
||||||
|
if (cur_mp->repeat <= 3) {
|
||||||
|
mbe_moveMbeParms(cur_mp, prev_mp);
|
||||||
|
mbe_spectralAmpEnhance(cur_mp);
|
||||||
|
mbe_synthesizeSpeechF(aout_buf, cur_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_moveMbeParms(cur_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*err_str = 'M';
|
||||||
|
err_str++;
|
||||||
|
mbe_synthesizeSilenceF(aout_buf);
|
||||||
|
mbe_initMbeParms(cur_mp, prev_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mbe_synthesizeSilenceF(aout_buf);
|
||||||
|
mbe_initMbeParms(cur_mp, prev_mp, prev_mp_enhanced);
|
||||||
|
}
|
||||||
|
|
||||||
|
*err_str = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe2450Data(short* aout_buf, int* errs, int* errs2, char* err_str, char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
float float_buf[160];
|
||||||
|
mbe_processAmbe2450DataF(float_buf, errs, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_floatToShort(float_buf, aout_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe3600x2450FrameF(float* aout_buf, int* errs, int* errs2, char* err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
*errs = 0;
|
||||||
|
*errs2 = 0;
|
||||||
|
*errs = mbe_eccAmbe3600x2450C0(ambe_fr);
|
||||||
|
mbe_demodulateAmbe3600x2450Data(ambe_fr);
|
||||||
|
|
||||||
|
*errs2 = *errs;
|
||||||
|
*errs2 += mbe_eccAmbe3600x2450Data(ambe_fr, ambe_d);
|
||||||
|
|
||||||
|
mbe_processAmbe2450DataF(aout_buf, errs, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_processAmbe3600x2450Frame(short* aout_buf, int* errs, int* errs2, char* err_str, char ambe_fr[4][24], char ambe_d[49], mbe_parms* cur_mp, mbe_parms* prev_mp, mbe_parms* prev_mp_enhanced, int uvquality)
|
||||||
|
{
|
||||||
|
float float_buf[160];
|
||||||
|
mbe_processAmbe3600x2450FrameF(float_buf, errs, errs2, err_str, ambe_fr, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality);
|
||||||
|
mbe_floatToShort(float_buf, aout_buf);
|
||||||
|
}
|
||||||
@ -0,0 +1,991 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file ambe3600x2450_const.h
|
||||||
|
* @ingroup vocoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#if !defined(__AMBE3600x2450_CONST_H__)
|
||||||
|
#define __AMBE3600x2450_CONST_H__
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4305)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fundamental Frequency Quanitization Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
const float AmbeW0table[120] = {
|
||||||
|
0.049971, 0.049215, 0.048471, 0.047739, 0.047010, 0.046299,
|
||||||
|
0.045601, 0.044905, 0.044226, 0.043558, 0.042900, 0.042246,
|
||||||
|
0.041609, 0.040979, 0.040356, 0.039747, 0.039148, 0.038559,
|
||||||
|
0.037971, 0.037399, 0.036839, 0.036278, 0.035732, 0.035198,
|
||||||
|
0.034672, 0.034145, 0.033636, 0.033133, 0.032635, 0.032148,
|
||||||
|
0.031670, 0.031122, 0.030647, 0.030184, 0.029728, 0.029272,
|
||||||
|
0.028831, 0.028395, 0.027966, 0.027538,
|
||||||
|
0.027122, 0.026712, 0.026304, 0.025906, 0.025515, 0.025129,
|
||||||
|
0.024746, 0.024372, 0.024002, 0.023636, 0.023279, 0.022926,
|
||||||
|
0.022581, 0.022236, 0.021900, 0.021570, 0.021240, 0.020920,
|
||||||
|
0.020605, 0.020294, 0.019983, 0.019684, 0.019386, 0.019094,
|
||||||
|
0.018805, 0.018520, 0.018242, 0.017965, 0.017696, 0.017431,
|
||||||
|
0.017170, 0.016911, 0.016657, 0.016409, 0.016163, 0.015923,
|
||||||
|
0.015686, 0.015411, 0.015177, 0.014946,
|
||||||
|
0.014721, 0.014496, 0.014277, 0.014061, 0.013847, 0.013636,
|
||||||
|
0.013430, 0.013227, 0.013025, 0.012829, 0.012634, 0.012444,
|
||||||
|
0.012253, 0.012068, 0.011887, 0.011703, 0.011528, 0.011353,
|
||||||
|
0.011183, 0.011011, 0.010845, 0.010681, 0.010517, 0.010359,
|
||||||
|
0.010202, 0.010050, 0.009895, 0.009747, 0.009600, 0.009453,
|
||||||
|
0.009312, 0.009172, 0.009033, 0.008896, 0.008762, 0.008633,
|
||||||
|
0.008501, 0.008375, 0.008249, 0.008125
|
||||||
|
};
|
||||||
|
|
||||||
|
const float AmbeLtable[120] = {
|
||||||
|
9, 9, 9, 9, 9, 9,
|
||||||
|
10, 10, 10, 10, 10, 10,
|
||||||
|
11, 11, 11, 11, 11, 11,
|
||||||
|
12, 12, 12, 12, 12, 13,
|
||||||
|
13, 13, 13, 13, 14, 14,
|
||||||
|
14, 14, 15, 15, 15, 15,
|
||||||
|
16, 16, 16, 16, 17, 17,
|
||||||
|
17, 17, 18, 18, 18, 18,
|
||||||
|
19, 19, 19, 20, 20, 20,
|
||||||
|
21, 21, 21, 22, 22, 22,
|
||||||
|
23, 23, 23, 24, 24, 24,
|
||||||
|
25, 25, 26, 26, 26, 27,
|
||||||
|
27, 28, 28, 29, 29, 30,
|
||||||
|
30, 30, 31, 31, 32, 32,
|
||||||
|
33, 33, 34, 34, 35, 36,
|
||||||
|
36, 37, 37, 38, 38, 39,
|
||||||
|
40, 40, 41, 42, 42, 43,
|
||||||
|
43, 44, 45, 46, 46, 47,
|
||||||
|
48, 48, 49, 50, 51, 52,
|
||||||
|
52, 53, 54, 55, 56, 56
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V/UV Quantization Vectors
|
||||||
|
*/
|
||||||
|
const int AmbeVuv[32][8] = {
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 0},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 0, 0},
|
||||||
|
{1, 1, 0, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 0, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 0, 1, 1},
|
||||||
|
{1, 1, 1, 1, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 1, 1, 0, 0, 0},
|
||||||
|
{1, 1, 1, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 0, 0, 0, 0, 1},
|
||||||
|
{1, 1, 0, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 0, 0, 0, 0, 0},
|
||||||
|
{1, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 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, 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, 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, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* V/UV Quantization Vectors
|
||||||
|
* alternate version
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
const int AmbeVuv[32][8] = {
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 0},
|
||||||
|
{1, 1, 1, 1, 1, 1, 1, 0},
|
||||||
|
{1, 1, 1, 1, 1, 1, 0, 0},
|
||||||
|
{1, 1, 0, 1, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 0, 1, 1, 1, 1},
|
||||||
|
{1, 1, 1, 1, 1, 0, 1, 1},
|
||||||
|
{1, 1, 1, 1, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 1, 1, 0, 0, 0},
|
||||||
|
{1, 1, 1, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 1, 0, 0, 0, 0, 1},
|
||||||
|
{1, 1, 0, 0, 0, 0, 0, 0},
|
||||||
|
{1, 1, 0, 0, 0, 0, 0, 0},
|
||||||
|
{1, 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, 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, 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, 0, 0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
{0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Log Magnitude Prediction Residual Block Lengths
|
||||||
|
*/
|
||||||
|
const int AmbeLmprbl[57][4] = {
|
||||||
|
{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,},
|
||||||
|
{2, 2, 2, 3,},
|
||||||
|
{2, 2, 3, 3,},
|
||||||
|
{2, 3, 3, 3,},
|
||||||
|
{2, 3, 3, 4,},
|
||||||
|
{3, 3, 3, 4,},
|
||||||
|
{3, 3, 4, 4,},
|
||||||
|
{3, 3, 4, 5,},
|
||||||
|
{3, 4, 4, 5,},
|
||||||
|
{3, 4, 5, 5,},
|
||||||
|
{4, 4, 5, 5,},
|
||||||
|
{4, 4, 5, 6,},
|
||||||
|
{4, 4, 6, 6,},
|
||||||
|
{4, 5, 6, 6,},
|
||||||
|
{4, 5, 6, 7,},
|
||||||
|
{5, 5, 6, 7,},
|
||||||
|
{5, 5, 7, 7,},
|
||||||
|
{5, 6, 7, 7,},
|
||||||
|
{5, 6, 7, 8,},
|
||||||
|
{5, 6, 8, 8,},
|
||||||
|
{6, 6, 8, 8,},
|
||||||
|
{6, 6, 8, 9,},
|
||||||
|
{6, 7, 8, 9,},
|
||||||
|
{6, 7, 9, 9,},
|
||||||
|
{6, 7, 9, 10,},
|
||||||
|
{7, 7, 9, 10,},
|
||||||
|
{7, 8, 9, 10,},
|
||||||
|
{7, 8, 10, 10,},
|
||||||
|
{7, 8, 10, 11,},
|
||||||
|
{8, 8, 10, 11,},
|
||||||
|
{8, 9, 10, 11,},
|
||||||
|
{8, 9, 11, 11,},
|
||||||
|
{8, 9, 11, 12,},
|
||||||
|
{8, 9, 11, 13,},
|
||||||
|
{8, 9, 12, 13,},
|
||||||
|
{8, 10, 12, 13,},
|
||||||
|
{9, 10, 12, 13,},
|
||||||
|
{9, 10, 12, 14,},
|
||||||
|
{9, 10, 13, 14,},
|
||||||
|
{9, 11, 13, 14,},
|
||||||
|
{10, 11, 13, 14,},
|
||||||
|
{10, 11, 13, 15,},
|
||||||
|
{10, 11, 14, 15,},
|
||||||
|
{10, 12, 14, 15,},
|
||||||
|
{10, 12, 14, 16,},
|
||||||
|
{11, 12, 14, 16,},
|
||||||
|
{11, 12, 15, 16,},
|
||||||
|
{11, 12, 15, 17,},
|
||||||
|
{11, 13, 15, 17}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gain Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbeDg[32] = {
|
||||||
|
-2.0, -0.67, 0.297941, 0.663728, 1.036829, 1.438136, 1.890077, 2.227970,
|
||||||
|
2.478289, 2.667544, 2.793619, 2.893261, 3.020630, 3.138586, 3.237579, 3.322570,
|
||||||
|
3.432367, 3.571863, 3.696650, 3.814917, 3.920932, 4.022503, 4.123569, 4.228291,
|
||||||
|
4.370569, 4.543700, 4.707695, 4.848879, 5.056757, 5.326468, 5.777581, 6.874496
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRBA24 Vector Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbePRBA24[512][3] = {
|
||||||
|
{0.526055, -0.328567, -0.304727},
|
||||||
|
{0.441044, -0.303127, -0.201114},
|
||||||
|
{1.030896, -0.324730, -0.397204},
|
||||||
|
{0.839696, -0.351933, -0.224909},
|
||||||
|
{0.272958, -0.176118, -0.098893},
|
||||||
|
{0.221466, -0.160045, -0.061026},
|
||||||
|
{0.496555, -0.211499, 0.047305},
|
||||||
|
{0.424376, -0.223752, 0.069911},
|
||||||
|
{0.264531, -0.353355, -0.330505},
|
||||||
|
{0.273650, -0.253004, -0.250241},
|
||||||
|
{0.484531, -0.297627, -0.071051},
|
||||||
|
{0.410814, -0.224961, -0.084998},
|
||||||
|
{0.039519, -0.252904, -0.115128},
|
||||||
|
{0.017423, -0.296519, -0.045921},
|
||||||
|
{0.225113, -0.224371, 0.037882},
|
||||||
|
{0.183424, -0.260492, 0.050491},
|
||||||
|
{0.308704, -0.073205, -0.405880},
|
||||||
|
{0.213125, -0.101632, -0.333208},
|
||||||
|
{0.617735, -0.137299, -0.213670},
|
||||||
|
{0.514382, -0.126485, -0.170204},
|
||||||
|
{0.130009, -0.076955, -0.229303},
|
||||||
|
{0.061740, -0.108259, -0.203887},
|
||||||
|
{0.244473, -0.110094, -0.051689},
|
||||||
|
{0.230452, -0.076147, -0.028190},
|
||||||
|
{0.059837, -0.254595, -0.562704},
|
||||||
|
{0.011630, -0.135223, -0.432791},
|
||||||
|
{0.207077, -0.152248, -0.148391},
|
||||||
|
{0.158078, -0.128800, -0.122150},
|
||||||
|
{-0.265982, -0.144742, -0.199894},
|
||||||
|
{-0.356479, -0.204740, -0.156465},
|
||||||
|
{0.000324, -0.139549, -0.066471},
|
||||||
|
{0.001888, -0.170557, -0.025025},
|
||||||
|
{0.402913, -0.581478, -0.274626},
|
||||||
|
{0.191289, -0.540335, -0.193040},
|
||||||
|
{0.632914, -0.401410, -0.006636},
|
||||||
|
{0.471086, -0.463144, 0.061489},
|
||||||
|
{0.044829, -0.438487, 0.033433},
|
||||||
|
{0.015513, -0.539475, -0.006719},
|
||||||
|
{0.336218, -0.351311, 0.214087},
|
||||||
|
{0.239967, -0.380836, 0.157681},
|
||||||
|
{0.347609, -0.901619, -0.688432},
|
||||||
|
{0.064067, -0.826753, -0.492089},
|
||||||
|
{0.303089, -0.396757, -0.108446},
|
||||||
|
{0.235590, -0.446122, 0.006437},
|
||||||
|
{-0.236964, -0.652532, -0.135520},
|
||||||
|
{-0.418285, -0.793014, -0.034730},
|
||||||
|
{-0.038262, -0.516984, 0.273681},
|
||||||
|
{-0.037419, -0.958198, 0.214749},
|
||||||
|
{0.061624, -0.238233, -0.237184},
|
||||||
|
{-0.013944, -0.235704, -0.204811},
|
||||||
|
{0.286428, -0.210542, -0.029587},
|
||||||
|
{0.257656, -0.261837, -0.056566},
|
||||||
|
{-0.235852, -0.310760, -0.165147},
|
||||||
|
{-0.334949, -0.385870, -0.197362},
|
||||||
|
{0.094870, -0.241144, 0.059122},
|
||||||
|
{0.060177, -0.225884, 0.031140},
|
||||||
|
{-0.301184, -0.306545, -0.446189},
|
||||||
|
{-0.293528, -0.504146, -0.429844},
|
||||||
|
{-0.055084, -0.379015, -0.125887},
|
||||||
|
{-0.115434, -0.375008, -0.059939},
|
||||||
|
{-0.777425, -0.592163, -0.107585},
|
||||||
|
{-0.950500, -0.893847, -0.181762},
|
||||||
|
{-0.259402, -0.396726, 0.010357},
|
||||||
|
{-0.368905, -0.449026, 0.038299},
|
||||||
|
{0.279719, -0.063196, -0.184628},
|
||||||
|
{0.255265, -0.067248, -0.121124},
|
||||||
|
{0.458433, -0.103777, 0.010074},
|
||||||
|
{0.437231, -0.092496, -0.031028},
|
||||||
|
{0.082265, -0.028050, -0.041262},
|
||||||
|
{0.045920, -0.051719, -0.030155},
|
||||||
|
{0.271149, -0.043613, 0.112085},
|
||||||
|
{0.246881, -0.065274, 0.105436},
|
||||||
|
{0.056590, -0.117773, -0.142283},
|
||||||
|
{0.058824, -0.104418, -0.099608},
|
||||||
|
{0.213781, -0.111974, 0.031269},
|
||||||
|
{0.187554, -0.070340, 0.011834},
|
||||||
|
{-0.185701, -0.081106, -0.073803},
|
||||||
|
{-0.266112, -0.074133, -0.085370},
|
||||||
|
{-0.029368, -0.046490, 0.124679},
|
||||||
|
{-0.017378, -0.102882, 0.140482},
|
||||||
|
{0.114700, 0.092738, -0.244271},
|
||||||
|
{0.072922, 0.007863, -0.231476},
|
||||||
|
{0.270022, 0.031819, -0.094208},
|
||||||
|
{0.254403, 0.024805, -0.050389},
|
||||||
|
{-0.182905, 0.021629, -0.168481},
|
||||||
|
{-0.225864, -0.010109, -0.130374},
|
||||||
|
{0.040089, 0.013969, 0.016028},
|
||||||
|
{0.001442, 0.010551, 0.032942},
|
||||||
|
{-0.287472, -0.036130, -0.296798},
|
||||||
|
{-0.332344, -0.108862, -0.342196},
|
||||||
|
{0.012700, 0.022917, -0.052501},
|
||||||
|
{-0.040681, -0.001805, -0.050548},
|
||||||
|
{-0.718522, -0.061234, -0.278820},
|
||||||
|
{-0.879205, -0.213588, -0.303508},
|
||||||
|
{-0.234102, -0.065407, 0.013686},
|
||||||
|
{-0.281223, -0.076139, 0.046830},
|
||||||
|
{0.141967, -0.193679, -0.055697},
|
||||||
|
{0.100318, -0.161222, -0.063062},
|
||||||
|
{0.265859, -0.132747, 0.078209},
|
||||||
|
{0.244805, -0.139776, 0.122123},
|
||||||
|
{-0.121802, -0.179976, 0.031732},
|
||||||
|
{-0.185318, -0.214011, 0.018117},
|
||||||
|
{0.047014, -0.153961, 0.218068},
|
||||||
|
{0.047305, -0.187402, 0.282114},
|
||||||
|
{-0.027533, -0.415868, -0.333841},
|
||||||
|
{-0.125886, -0.334492, -0.290317},
|
||||||
|
{-0.030602, -0.190918, 0.097454},
|
||||||
|
{-0.054936, -0.209948, 0.158977},
|
||||||
|
{-0.507223, -0.295876, -0.217183},
|
||||||
|
{-0.581733, -0.403194, -0.208936},
|
||||||
|
{-0.299719, -0.289679, 0.297101},
|
||||||
|
{-0.363169, -0.362718, 0.436529},
|
||||||
|
{-0.124627, -0.042100, -0.157011},
|
||||||
|
{-0.161571, -0.092846, -0.183636},
|
||||||
|
{0.084520, -0.100217, -0.000901},
|
||||||
|
{0.055655, -0.136381, 0.032764},
|
||||||
|
{-0.545087, -0.197713, -0.026888},
|
||||||
|
{-0.662772, -0.179815, 0.026419},
|
||||||
|
{-0.165583, -0.148913, 0.090382},
|
||||||
|
{-0.240772, -0.182830, 0.105474},
|
||||||
|
{-0.576315, -0.359473, -0.456844},
|
||||||
|
{-0.713430, -0.554156, -0.476739},
|
||||||
|
{-0.275628, -0.223640, -0.051584},
|
||||||
|
{-0.359501, -0.230758, -0.027006},
|
||||||
|
{-1.282559, -0.284807, -0.233743},
|
||||||
|
{-1.060476, -0.399911, -0.562698},
|
||||||
|
{-0.871952, -0.272197, 0.016126},
|
||||||
|
{-0.747922, -0.329404, 0.276696},
|
||||||
|
{0.643086, 0.046175, -0.660078},
|
||||||
|
{0.738204, -0.127844, -0.433708},
|
||||||
|
{1.158072, 0.025571, -0.177856},
|
||||||
|
{0.974840, -0.009417, -0.112337},
|
||||||
|
{0.418014, 0.032741, -0.124545},
|
||||||
|
{0.381422, -0.001557, -0.085504},
|
||||||
|
{0.768280, 0.056085, 0.095375},
|
||||||
|
{0.680004, 0.052035, 0.152318},
|
||||||
|
{0.473182, 0.012560, -0.264221},
|
||||||
|
{0.345153, 0.036627, -0.248756},
|
||||||
|
{0.746238, -0.025880, -0.106050},
|
||||||
|
{0.644319, -0.058256, -0.095133},
|
||||||
|
{0.185924, -0.022230, -0.070540},
|
||||||
|
{0.146068, -0.009550, -0.057871},
|
||||||
|
{0.338488, 0.013022, 0.069961},
|
||||||
|
{0.298969, 0.047403, 0.052598},
|
||||||
|
{0.346002, 0.256253, -0.380261},
|
||||||
|
{0.313092, 0.163821, -0.314004},
|
||||||
|
{0.719154, 0.103108, -0.252648},
|
||||||
|
{0.621429, 0.172423, -0.265180},
|
||||||
|
{0.240461, 0.104684, -0.202582},
|
||||||
|
{0.206946, 0.139642, -0.138016},
|
||||||
|
{0.359915, 0.101273, -0.052997},
|
||||||
|
{0.318117, 0.125888, -0.003486},
|
||||||
|
{0.150452, 0.050219, -0.409155},
|
||||||
|
{0.188753, 0.091894, -0.325733},
|
||||||
|
{0.334922, 0.029098, -0.098587},
|
||||||
|
{0.324508, 0.015809, -0.135408},
|
||||||
|
{-0.042506, 0.038667, -0.208535},
|
||||||
|
{-0.083003, 0.094758, -0.174054},
|
||||||
|
{0.094773, 0.102653, -0.025701},
|
||||||
|
{0.063284, 0.118703, -0.000071},
|
||||||
|
{0.355965, -0.139239, -0.191705},
|
||||||
|
{0.392742, -0.105496, -0.132103},
|
||||||
|
{0.663678, -0.204627, -0.031242},
|
||||||
|
{0.609381, -0.146914, 0.079610},
|
||||||
|
{0.151855, -0.132843, -0.007125},
|
||||||
|
{0.146404, -0.161917, 0.024842},
|
||||||
|
{0.400524, -0.135221, 0.232289},
|
||||||
|
{0.324931, -0.116605, 0.253458},
|
||||||
|
{0.169066, -0.215132, -0.185604},
|
||||||
|
{0.128681, -0.189394, -0.160279},
|
||||||
|
{0.356194, -0.116992, -0.038381},
|
||||||
|
{0.342866, -0.144687, 0.020265},
|
||||||
|
{-0.065545, -0.202593, -0.043688},
|
||||||
|
{-0.124296, -0.260225, -0.035370},
|
||||||
|
{0.083224, -0.235149, 0.153301},
|
||||||
|
{0.046256, -0.309608, 0.190944},
|
||||||
|
{0.187385, -0.008168, -0.198575},
|
||||||
|
{0.190401, -0.018699, -0.136858},
|
||||||
|
{0.398009, -0.025700, -0.007458},
|
||||||
|
{0.346948, -0.022258, -0.020905},
|
||||||
|
{-0.047064, -0.085629, -0.080677},
|
||||||
|
{-0.067523, -0.128972, -0.119538},
|
||||||
|
{0.186086, -0.016828, 0.070014},
|
||||||
|
{0.187364, 0.017133, 0.075949},
|
||||||
|
{-0.112669, -0.037433, -0.298944},
|
||||||
|
{-0.068276, -0.114504, -0.265795},
|
||||||
|
{0.147510, -0.040616, -0.013687},
|
||||||
|
{0.133084, -0.062849, -0.032637},
|
||||||
|
{-0.416571, -0.041544, -0.125088},
|
||||||
|
{-0.505337, -0.044193, -0.157651},
|
||||||
|
{-0.154132, -0.075106, 0.050466},
|
||||||
|
{-0.148036, -0.059719, 0.121516},
|
||||||
|
{0.490555, 0.157659, -0.222208},
|
||||||
|
{0.436700, 0.120500, -0.205869},
|
||||||
|
{0.754525, 0.269323, 0.045810},
|
||||||
|
{0.645077, 0.271923, 0.013942},
|
||||||
|
{0.237023, 0.115337, -0.026429},
|
||||||
|
{0.204895, 0.121020, -0.008541},
|
||||||
|
{0.383999, 0.153963, 0.171763},
|
||||||
|
{0.385026, 0.222074, 0.239731},
|
||||||
|
{0.198232, 0.072972, -0.108179},
|
||||||
|
{0.147882, 0.074743, -0.123341},
|
||||||
|
{0.390929, 0.075205, 0.081828},
|
||||||
|
{0.341623, 0.089405, 0.069389},
|
||||||
|
{-0.003381, 0.159694, -0.016026},
|
||||||
|
{-0.043653, 0.206860, -0.040729},
|
||||||
|
{0.135515, 0.107824, 0.179310},
|
||||||
|
{0.081086, 0.119673, 0.174282},
|
||||||
|
{0.192637, 0.400335, -0.341906},
|
||||||
|
{0.171196, 0.284921, -0.221516},
|
||||||
|
{0.377807, 0.359087, -0.151523},
|
||||||
|
{0.411052, 0.297925, -0.099774},
|
||||||
|
{-0.010060, 0.261887, -0.149567},
|
||||||
|
{-0.107877, 0.287756, -0.116982},
|
||||||
|
{0.158003, 0.209727, 0.077988},
|
||||||
|
{0.109710, 0.232272, 0.088135},
|
||||||
|
{0.000698, 0.209353, -0.395208},
|
||||||
|
{-0.094015, 0.230322, -0.279928},
|
||||||
|
{0.137355, 0.230881, -0.124115},
|
||||||
|
{0.103058, 0.166855, -0.100386},
|
||||||
|
{-0.305058, 0.305422, -0.176026},
|
||||||
|
{-0.422049, 0.337137, -0.293297},
|
||||||
|
{-0.121744, 0.185124, 0.048115},
|
||||||
|
{-0.171052, 0.200312, 0.052812},
|
||||||
|
{0.224091, -0.010673, -0.019727},
|
||||||
|
{0.200266, -0.020167, 0.001798},
|
||||||
|
{0.382742, 0.032362, 0.161665},
|
||||||
|
{0.345631, -0.019705, 0.164451},
|
||||||
|
{0.029431, 0.045010, 0.071518},
|
||||||
|
{0.031940, 0.010876, 0.087037},
|
||||||
|
{0.181935, 0.039112, 0.202316},
|
||||||
|
{0.181810, 0.033189, 0.253435},
|
||||||
|
{-0.008677, -0.066679, -0.144737},
|
||||||
|
{-0.021768, -0.021288, -0.125903},
|
||||||
|
{0.136766, 0.000100, 0.059449},
|
||||||
|
{0.135405, -0.020446, 0.103793},
|
||||||
|
{-0.289115, 0.039747, -0.012256},
|
||||||
|
{-0.338683, 0.025909, -0.034058},
|
||||||
|
{-0.016515, 0.048584, 0.197981},
|
||||||
|
{-0.046790, 0.011816, 0.199964},
|
||||||
|
{0.094214, 0.127422, -0.169936},
|
||||||
|
{0.048279, 0.096189, -0.148153},
|
||||||
|
{0.217391, 0.081732, 0.013677},
|
||||||
|
{0.179656, 0.084671, 0.031434},
|
||||||
|
{-0.227367, 0.118176, -0.039803},
|
||||||
|
{-0.327096, 0.159747, -0.018931},
|
||||||
|
{0.000834, 0.113118, 0.125325},
|
||||||
|
{-0.014617, 0.128924, 0.163776},
|
||||||
|
{-0.254570, 0.154329, -0.232018},
|
||||||
|
{-0.353068, 0.124341, -0.174409},
|
||||||
|
{-0.061004, 0.107744, 0.037257},
|
||||||
|
{-0.100991, 0.080302, 0.062701},
|
||||||
|
{-0.927022, 0.285660, -0.240549},
|
||||||
|
{-1.153224, 0.277232, -0.322538},
|
||||||
|
{-0.569012, 0.108135, 0.172634},
|
||||||
|
{-0.555273, 0.131461, 0.325930},
|
||||||
|
{0.518847, 0.065683, -0.132877},
|
||||||
|
{0.501324, -0.006585, -0.094884},
|
||||||
|
{1.066190, -0.150380, 0.201791},
|
||||||
|
{0.858377, -0.166415, 0.081686},
|
||||||
|
{0.320584, -0.031499, 0.039534},
|
||||||
|
{0.311442, -0.075120, 0.026013},
|
||||||
|
{0.625829, -0.019856, 0.346041},
|
||||||
|
{0.525271, -0.003948, 0.284868},
|
||||||
|
{0.312594, -0.075673, -0.066642},
|
||||||
|
{0.295732, -0.057895, -0.042207},
|
||||||
|
{0.550446, -0.029110, 0.046850},
|
||||||
|
{0.465467, -0.068987, 0.096167},
|
||||||
|
{0.122669, -0.051786, 0.044283},
|
||||||
|
{0.079669, -0.044145, 0.045805},
|
||||||
|
{0.238778, -0.031835, 0.171694},
|
||||||
|
{0.200734, -0.072619, 0.178726},
|
||||||
|
{0.342512, 0.131270, -0.163021},
|
||||||
|
{0.294028, 0.111759, -0.125793},
|
||||||
|
{0.589523, 0.121808, -0.049372},
|
||||||
|
{0.550506, 0.132318, 0.017485},
|
||||||
|
{0.164280, 0.047560, -0.058383},
|
||||||
|
{0.120110, 0.049242, -0.052403},
|
||||||
|
{0.269181, 0.035000, 0.103494},
|
||||||
|
{0.297466, 0.038517, 0.139289},
|
||||||
|
{0.094549, -0.030880, -0.153376},
|
||||||
|
{0.080363, 0.024359, -0.127578},
|
||||||
|
{0.281351, 0.055178, 0.000155},
|
||||||
|
{0.234900, 0.039477, 0.013957},
|
||||||
|
{-0.118161, 0.011976, -0.034270},
|
||||||
|
{-0.157654, 0.027765, -0.005010},
|
||||||
|
{0.102631, 0.027283, 0.099723},
|
||||||
|
{0.077285, 0.052532, 0.115583},
|
||||||
|
{0.329398, -0.278552, 0.016316},
|
||||||
|
{0.305993, -0.267896, 0.094952},
|
||||||
|
{0.775270, -0.394995, 0.290748},
|
||||||
|
{0.583180, -0.252159, 0.285391},
|
||||||
|
{0.192226, -0.182242, 0.126859},
|
||||||
|
{0.185908, -0.245779, 0.159940},
|
||||||
|
{0.346293, -0.250404, 0.355682},
|
||||||
|
{0.354160, -0.364521, 0.472337},
|
||||||
|
{0.134942, -0.313666, -0.115181},
|
||||||
|
{0.126077, -0.286568, -0.039927},
|
||||||
|
{0.405618, -0.211792, 0.199095},
|
||||||
|
{0.312099, -0.213642, 0.190972},
|
||||||
|
{-0.071392, -0.297366, 0.081426},
|
||||||
|
{-0.165839, -0.301986, 0.160640},
|
||||||
|
{0.147808, -0.290712, 0.298198},
|
||||||
|
{0.063302, -0.310149, 0.396302},
|
||||||
|
{0.141444, -0.081377, -0.076621},
|
||||||
|
{0.115936, -0.104440, -0.039885},
|
||||||
|
{0.367023, -0.087281, 0.096390},
|
||||||
|
{0.330038, -0.117958, 0.127050},
|
||||||
|
{0.002897, -0.062454, 0.025151},
|
||||||
|
{-0.052404, -0.082200, 0.041975},
|
||||||
|
{0.181553, -0.137004, 0.230489},
|
||||||
|
{0.140768, -0.094604, 0.265928},
|
||||||
|
{-0.101763, -0.209566, -0.135964},
|
||||||
|
{-0.159056, -0.191005, -0.095509},
|
||||||
|
{0.045016, -0.081562, 0.075942},
|
||||||
|
{0.016808, -0.112482, 0.068593},
|
||||||
|
{-0.408578, -0.132377, 0.079163},
|
||||||
|
{-0.431534, -0.214646, 0.157714},
|
||||||
|
{-0.096931, -0.101938, 0.200304},
|
||||||
|
{-0.167867, -0.114851, 0.262964},
|
||||||
|
{0.393882, 0.086002, 0.008961},
|
||||||
|
{0.338747, 0.048405, -0.004187},
|
||||||
|
{0.877844, 0.374373, 0.171008},
|
||||||
|
{0.740790, 0.324525, 0.242248},
|
||||||
|
{0.200218, 0.070150, 0.085891},
|
||||||
|
{0.171760, 0.090531, 0.102579},
|
||||||
|
{0.314263, 0.126417, 0.322833},
|
||||||
|
{0.313523, 0.065445, 0.403855},
|
||||||
|
{0.164261, 0.057745, -0.005490},
|
||||||
|
{0.122141, 0.024122, 0.009190},
|
||||||
|
{0.308248, 0.078401, 0.180577},
|
||||||
|
{0.251222, 0.073868, 0.160457},
|
||||||
|
{-0.047526, 0.023725, 0.086336},
|
||||||
|
{-0.091643, 0.005539, 0.093179},
|
||||||
|
{0.079339, 0.044135, 0.206697},
|
||||||
|
{0.104213, 0.011277, 0.240060},
|
||||||
|
{0.226607, 0.186234, -0.056881},
|
||||||
|
{0.173281, 0.158131, -0.059413},
|
||||||
|
{0.339400, 0.214501, 0.052905},
|
||||||
|
{0.309166, 0.188181, 0.058028},
|
||||||
|
{0.014442, 0.194715, 0.048945},
|
||||||
|
{-0.028793, 0.194766, 0.089078},
|
||||||
|
{0.069564, 0.206743, 0.193568},
|
||||||
|
{0.091532, 0.202786, 0.269680},
|
||||||
|
{-0.071196, 0.135604, -0.103744},
|
||||||
|
{-0.118288, 0.152837, -0.060151},
|
||||||
|
{0.146856, 0.143174, 0.061789},
|
||||||
|
{0.104379, 0.143672, 0.056797},
|
||||||
|
{-0.541832, 0.250034, -0.017602},
|
||||||
|
{-0.641583, 0.278411, -0.111909},
|
||||||
|
{-0.094447, 0.159393, 0.164848},
|
||||||
|
{-0.113612, 0.120702, 0.221656},
|
||||||
|
{0.204918, -0.078894, 0.075524},
|
||||||
|
{0.161232, -0.090256, 0.088701},
|
||||||
|
{0.378460, -0.033687, 0.309964},
|
||||||
|
{0.311701, -0.049984, 0.316881},
|
||||||
|
{0.019311, -0.050048, 0.212387},
|
||||||
|
{0.002473, -0.062855, 0.278462},
|
||||||
|
{0.151448, -0.090652, 0.410031},
|
||||||
|
{0.162778, -0.071291, 0.531252},
|
||||||
|
{-0.083704, -0.076839, -0.020798},
|
||||||
|
{-0.092832, -0.043492, 0.029202},
|
||||||
|
{0.136844, -0.077791, 0.186493},
|
||||||
|
{0.089536, -0.086826, 0.184711},
|
||||||
|
{-0.270255, -0.058858, 0.173048},
|
||||||
|
{-0.350416, -0.009219, 0.273260},
|
||||||
|
{-0.105248, -0.205534, 0.425159},
|
||||||
|
{-0.135030, -0.197464, 0.623550},
|
||||||
|
{-0.051717, 0.069756, -0.043829},
|
||||||
|
{-0.081050, 0.056947, -0.000205},
|
||||||
|
{0.190388, 0.016366, 0.145922},
|
||||||
|
{0.142662, 0.002575, 0.159182},
|
||||||
|
{-0.352890, 0.011117, 0.091040},
|
||||||
|
{-0.367374, 0.056547, 0.147209},
|
||||||
|
{-0.003179, 0.026570, 0.282541},
|
||||||
|
{-0.069934, -0.005171, 0.337678},
|
||||||
|
{-0.496181, 0.026464, 0.019432},
|
||||||
|
{-0.690384, 0.069313, -0.004175},
|
||||||
|
{-0.146138, 0.046372, 0.161839},
|
||||||
|
{-0.197581, 0.034093, 0.241003},
|
||||||
|
{-0.989567, 0.040993, 0.049384},
|
||||||
|
{-1.151075, 0.210556, 0.237374},
|
||||||
|
{-0.335366, -0.058208, 0.480168},
|
||||||
|
{-0.502419, -0.093761, 0.675240},
|
||||||
|
{0.862548, 0.264137, -0.294905},
|
||||||
|
{0.782668, 0.251324, -0.122108},
|
||||||
|
{1.597797, 0.463818, -0.133153},
|
||||||
|
{1.615756, 0.060653, 0.084764},
|
||||||
|
{0.435588, 0.209832, 0.095050},
|
||||||
|
{0.431013, 0.165328, 0.047909},
|
||||||
|
{1.248164, 0.265923, 0.488086},
|
||||||
|
{1.009933, 0.345440, 0.473702},
|
||||||
|
{0.477017, 0.194237, -0.058012},
|
||||||
|
{0.401362, 0.186915, -0.054137},
|
||||||
|
{1.202158, 0.284782, -0.066531},
|
||||||
|
{1.064907, 0.203766, 0.046383},
|
||||||
|
{0.255848, 0.133398, 0.046049},
|
||||||
|
{0.218680, 0.128833, 0.065326},
|
||||||
|
{0.490817, 0.182041, 0.286583},
|
||||||
|
{0.440714, 0.106576, 0.301120},
|
||||||
|
{0.604263, 0.522925, -0.238629},
|
||||||
|
{0.526329, 0.377577, -0.198100},
|
||||||
|
{1.038632, 0.606242, -0.121253},
|
||||||
|
{0.995283, 0.552202, 0.110700},
|
||||||
|
{0.262232, 0.313664, -0.086909},
|
||||||
|
{0.230835, 0.273385, -0.054268},
|
||||||
|
{0.548466, 0.490721, 0.278201},
|
||||||
|
{0.466984, 0.355859, 0.289160},
|
||||||
|
{0.367137, 0.236160, -0.228114},
|
||||||
|
{0.309359, 0.233843, -0.171325},
|
||||||
|
{0.465268, 0.276569, 0.010951},
|
||||||
|
{0.378124, 0.250237, 0.011131},
|
||||||
|
{0.061885, 0.296810, -0.011420},
|
||||||
|
{0.000125, 0.350029, -0.011277},
|
||||||
|
{0.163815, 0.261191, 0.175863},
|
||||||
|
{0.165132, 0.308797, 0.227800},
|
||||||
|
{0.461418, 0.052075, -0.016543},
|
||||||
|
{0.472372, 0.046962, 0.045746},
|
||||||
|
{0.856406, 0.136415, 0.245074},
|
||||||
|
{0.834616, 0.003254, 0.372643},
|
||||||
|
{0.337869, 0.036994, 0.232513},
|
||||||
|
{0.267414, 0.027593, 0.252779},
|
||||||
|
{0.584983, 0.113046, 0.583119},
|
||||||
|
{0.475406, -0.024234, 0.655070},
|
||||||
|
{0.264823, -0.029292, 0.004270},
|
||||||
|
{0.246071, -0.019109, 0.030048},
|
||||||
|
{0.477401, 0.021039, 0.155448},
|
||||||
|
{0.458453, -0.043959, 0.187850},
|
||||||
|
{0.067059, -0.061227, 0.126904},
|
||||||
|
{0.044608, -0.034575, 0.150205},
|
||||||
|
{0.191304, -0.003810, 0.316776},
|
||||||
|
{0.153078, 0.029915, 0.361303},
|
||||||
|
{0.320704, 0.178950, -0.088835},
|
||||||
|
{0.300866, 0.137645, -0.056893},
|
||||||
|
{0.553442, 0.162339, 0.131987},
|
||||||
|
{0.490083, 0.123682, 0.146163},
|
||||||
|
{0.118950, 0.083109, 0.034052},
|
||||||
|
{0.099344, 0.066212, 0.054329},
|
||||||
|
{0.228325, 0.122445, 0.309219},
|
||||||
|
{0.172093, 0.135754, 0.323361},
|
||||||
|
{0.064213, 0.063405, -0.058243},
|
||||||
|
{0.011906, 0.088795, -0.069678},
|
||||||
|
{0.194232, 0.129185, 0.125708},
|
||||||
|
{0.155182, 0.174013, 0.144099},
|
||||||
|
{-0.217068, 0.112731, 0.093497},
|
||||||
|
{-0.307590, 0.171146, 0.110735},
|
||||||
|
{-0.014897, 0.138094, 0.232455},
|
||||||
|
{-0.036936, 0.170135, 0.279166},
|
||||||
|
{0.681886, 0.437121, 0.078458},
|
||||||
|
{0.548559, 0.376914, 0.092485},
|
||||||
|
{1.259194, 0.901494, 0.256085},
|
||||||
|
{1.296139, 0.607949, 0.302184},
|
||||||
|
{0.319619, 0.307231, 0.099647},
|
||||||
|
{0.287232, 0.359355, 0.186844},
|
||||||
|
{0.751306, 0.676688, 0.499386},
|
||||||
|
{0.479609, 0.553030, 0.560447},
|
||||||
|
{0.276377, 0.214032, -0.003661},
|
||||||
|
{0.238146, 0.223595, 0.028806},
|
||||||
|
{0.542688, 0.266205, 0.171393},
|
||||||
|
{0.460188, 0.283979, 0.158288},
|
||||||
|
{0.057385, 0.309853, 0.144517},
|
||||||
|
{-0.006881, 0.348152, 0.097310},
|
||||||
|
{0.244434, 0.247298, 0.322601},
|
||||||
|
{0.253992, 0.335420, 0.402241},
|
||||||
|
{0.354006, 0.579776, -0.130176},
|
||||||
|
{0.267043, 0.461976, -0.058178},
|
||||||
|
{0.534049, 0.626549, 0.046747},
|
||||||
|
{0.441835, 0.468260, 0.057556},
|
||||||
|
{0.110477, 0.628795, 0.102950},
|
||||||
|
{0.031409, 0.489068, 0.090605},
|
||||||
|
{0.229564, 0.525640, 0.325454},
|
||||||
|
{0.105570, 0.582151, 0.509738},
|
||||||
|
{0.005690, 0.521474, -0.157885},
|
||||||
|
{0.104463, 0.424022, -0.080647},
|
||||||
|
{0.223784, 0.389860, 0.060904},
|
||||||
|
{0.159806, 0.340571, 0.062061},
|
||||||
|
{-0.173976, 0.573425, 0.027383},
|
||||||
|
{-0.376008, 0.587868, 0.133042},
|
||||||
|
{-0.051773, 0.348339, 0.231923},
|
||||||
|
{-0.122571, 0.473049, 0.251159},
|
||||||
|
{0.324321, 0.148510, 0.116006},
|
||||||
|
{0.282263, 0.121730, 0.114016},
|
||||||
|
{0.690108, 0.256346, 0.418128},
|
||||||
|
{0.542523, 0.294427, 0.461973},
|
||||||
|
{0.056944, 0.107667, 0.281797},
|
||||||
|
{0.027844, 0.106858, 0.355071},
|
||||||
|
{0.160456, 0.177656, 0.528819},
|
||||||
|
{0.227537, 0.177976, 0.689465},
|
||||||
|
{0.111585, 0.097896, 0.109244},
|
||||||
|
{0.083994, 0.133245, 0.115789},
|
||||||
|
{0.208740, 0.142084, 0.208953},
|
||||||
|
{0.156072, 0.143303, 0.231368},
|
||||||
|
{-0.185830, 0.214347, 0.309774},
|
||||||
|
{-0.311053, 0.240517, 0.328512},
|
||||||
|
{-0.041749, 0.090901, 0.511373},
|
||||||
|
{-0.156164, 0.098486, 0.478020},
|
||||||
|
{0.151543, 0.263073, -0.033471},
|
||||||
|
{0.126322, 0.213004, -0.007014},
|
||||||
|
{0.245313, 0.217564, 0.120210},
|
||||||
|
{0.259136, 0.225542, 0.176601},
|
||||||
|
{-0.190632, 0.260214, 0.141755},
|
||||||
|
{-0.189271, 0.331768, 0.170606},
|
||||||
|
{0.054763, 0.294766, 0.357775},
|
||||||
|
{-0.033724, 0.257645, 0.365069},
|
||||||
|
{-0.184971, 0.396532, 0.057728},
|
||||||
|
{-0.293313, 0.400259, 0.001123},
|
||||||
|
{-0.015219, 0.232287, 0.177913},
|
||||||
|
{-0.022524, 0.244724, 0.240753},
|
||||||
|
{-0.520342, 0.347950, 0.249265},
|
||||||
|
{-0.671997, 0.410782, 0.153434},
|
||||||
|
{-0.253089, 0.412356, 0.489854},
|
||||||
|
{-0.410922, 0.562454, 0.543891}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRBA58 Vector Quantizer Levels
|
||||||
|
*/
|
||||||
|
const float AmbePRBA58[128][4] = {
|
||||||
|
{-0.103660, 0.094597, -0.013149, 0.081501},
|
||||||
|
{-0.170709, 0.129958, -0.057316, 0.112324},
|
||||||
|
{-0.095113, 0.080892, -0.027554, 0.003371},
|
||||||
|
{-0.154153, 0.113437, -0.074522, 0.003446},
|
||||||
|
{-0.109553, 0.153519, 0.006858, 0.040930},
|
||||||
|
{-0.181931, 0.217882, -0.019042, 0.040049},
|
||||||
|
{-0.096246, 0.144191, -0.024147, -0.035120},
|
||||||
|
{-0.174811, 0.193357, -0.054261, -0.071700},
|
||||||
|
{-0.183241, -0.052840, 0.117923, 0.030960},
|
||||||
|
{-0.242634, 0.009075, 0.098007, 0.091643},
|
||||||
|
{-0.143847, -0.028529, 0.040171, -0.002812},
|
||||||
|
{-0.198809, 0.006990, 0.020668, 0.026641},
|
||||||
|
{-0.233172, -0.028793, 0.140130, -0.071927},
|
||||||
|
{-0.309313, 0.056873, 0.108262, -0.018930},
|
||||||
|
{-0.172782, -0.002037, 0.048755, -0.087065},
|
||||||
|
{-0.242901, 0.036076, 0.015064, -0.064366},
|
||||||
|
{0.077107, 0.172685, 0.159939, 0.097456},
|
||||||
|
{0.024820, 0.209676, 0.087347, 0.105204},
|
||||||
|
{0.085113, 0.151639, 0.084272, 0.022747},
|
||||||
|
{0.047975, 0.196695, 0.038770, 0.029953},
|
||||||
|
{0.113925, 0.236813, 0.176121, 0.016635},
|
||||||
|
{0.009708, 0.267969, 0.127660, 0.015872},
|
||||||
|
{0.114044, 0.202311, 0.096892, -0.043071},
|
||||||
|
{0.047219, 0.260395, 0.050952, -0.046996},
|
||||||
|
{-0.055095, 0.034041, 0.200464, 0.039050},
|
||||||
|
{-0.061582, 0.069566, 0.113048, 0.027511},
|
||||||
|
{-0.025469, 0.040440, 0.132777, -0.039098},
|
||||||
|
{-0.031388, 0.064010, 0.067559, -0.017117},
|
||||||
|
{-0.074386, 0.086579, 0.228232, -0.055461},
|
||||||
|
{-0.107352, 0.120874, 0.137364, -0.030252},
|
||||||
|
{-0.036897, 0.089972, 0.155831, -0.128475},
|
||||||
|
{-0.059070, 0.097879, 0.084489, -0.075821},
|
||||||
|
{-0.050865, -0.025167, -0.086636, 0.011256},
|
||||||
|
{-0.051426, 0.013301, -0.144665, 0.038541},
|
||||||
|
{-0.073831, -0.028917, -0.142416, -0.025268},
|
||||||
|
{-0.083910, 0.015004, -0.227113, -0.002808},
|
||||||
|
{-0.030840, -0.009326, -0.070517, -0.041304},
|
||||||
|
{-0.022018, 0.029381, -0.124961, -0.031624},
|
||||||
|
{-0.064222, -0.014640, -0.108798, -0.092342},
|
||||||
|
{-0.038801, 0.038133, -0.188992, -0.094221},
|
||||||
|
{-0.154059, -0.183932, -0.019894, 0.082105},
|
||||||
|
{-0.188022, -0.113072, -0.117380, 0.090911},
|
||||||
|
{-0.243301, -0.207086, -0.053735, -0.001975},
|
||||||
|
{-0.275931, -0.121035, -0.161261, 0.004231},
|
||||||
|
{-0.118142, -0.157537, -0.036594, -0.008679},
|
||||||
|
{-0.153627, -0.111372, -0.103095, -0.009460},
|
||||||
|
{-0.173458, -0.180158, -0.057130, -0.103198},
|
||||||
|
{-0.208509, -0.127679, -0.149336, -0.109289},
|
||||||
|
{0.096310, 0.047927, -0.024094, -0.057018},
|
||||||
|
{0.044289, 0.075486, -0.008505, -0.067635},
|
||||||
|
{0.076751, 0.025560, -0.066428, -0.102991},
|
||||||
|
{0.025215, 0.090417, -0.058616, -0.114284},
|
||||||
|
{0.125980, 0.070078, 0.016282, -0.112355},
|
||||||
|
{0.070859, 0.118988, 0.001180, -0.116359},
|
||||||
|
{0.097520, 0.059219, -0.026821, -0.172850},
|
||||||
|
{0.048226, 0.145459, -0.050093, -0.188853},
|
||||||
|
{0.007242, -0.135796, 0.147832, -0.034080},
|
||||||
|
{0.012843, -0.069616, 0.077139, -0.047909},
|
||||||
|
{-0.050911, -0.116323, 0.082521, -0.056362},
|
||||||
|
{-0.039630, -0.055678, 0.036066, -0.067992},
|
||||||
|
{0.042694, -0.091527, 0.150940, -0.124225},
|
||||||
|
{0.029225, -0.039401, 0.071664, -0.113665},
|
||||||
|
{-0.025085, -0.099013, 0.074622, -0.138674},
|
||||||
|
{-0.031220, -0.035717, 0.020870, -0.143376},
|
||||||
|
{0.040638, 0.087903, -0.049500, 0.094607},
|
||||||
|
{0.026860, 0.125924, -0.103449, 0.140882},
|
||||||
|
{0.075166, 0.110186, -0.115173, 0.067330},
|
||||||
|
{0.036642, 0.163193, -0.188762, 0.103724},
|
||||||
|
{0.028179, 0.095124, -0.053258, 0.028900},
|
||||||
|
{0.002307, 0.148211, -0.096037, 0.046189},
|
||||||
|
{0.072227, 0.137595, -0.095629, 0.001339},
|
||||||
|
{0.033308, 0.221480, -0.152201, 0.012125},
|
||||||
|
{0.003458, -0.085112, 0.041850, 0.113836},
|
||||||
|
{-0.040610, -0.044880, 0.029732, 0.177011},
|
||||||
|
{0.011404, -0.054324, -0.012426, 0.077815},
|
||||||
|
{-0.042413, -0.030930, -0.034844, 0.122946},
|
||||||
|
{-0.002206, -0.045698, 0.050651, 0.054886},
|
||||||
|
{-0.041729, -0.016110, 0.048005, 0.102125},
|
||||||
|
{0.013963, -0.022204, 0.001613, 0.028997},
|
||||||
|
{-0.030218, -0.002052, -0.004365, 0.065343},
|
||||||
|
{0.299049, 0.046260, 0.076320, 0.070784},
|
||||||
|
{0.250160, 0.098440, 0.012590, 0.137479},
|
||||||
|
{0.254170, 0.095310, 0.018749, 0.004288},
|
||||||
|
{0.218892, 0.145554, -0.035161, 0.069784},
|
||||||
|
{0.303486, 0.101424, 0.135996, -0.013096},
|
||||||
|
{0.262919, 0.165133, 0.077237, 0.071721},
|
||||||
|
{0.319358, 0.170283, 0.054554, -0.072210},
|
||||||
|
{0.272983, 0.231181, -0.014471, 0.011689},
|
||||||
|
{0.134116, -0.026693, 0.161400, 0.110292},
|
||||||
|
{0.100379, 0.026517, 0.086236, 0.130478},
|
||||||
|
{0.144718, -0.000895, 0.093767, 0.044514},
|
||||||
|
{0.114943, 0.022145, 0.035871, 0.069193},
|
||||||
|
{0.122051, 0.011043, 0.192803, 0.022796},
|
||||||
|
{0.079482, 0.026156, 0.117725, 0.056565},
|
||||||
|
{0.124641, 0.027387, 0.122956, -0.025369},
|
||||||
|
{0.090708, 0.027357, 0.064450, 0.013058},
|
||||||
|
{0.159781, -0.055202, -0.090597, 0.151598},
|
||||||
|
{0.084577, -0.037203, -0.126698, 0.119739},
|
||||||
|
{0.192484, -0.100195, -0.162066, 0.104148},
|
||||||
|
{0.114579, -0.046270, -0.219547, 0.100067},
|
||||||
|
{0.153083, -0.010127, -0.086266, 0.068648},
|
||||||
|
{0.088202, -0.010515, -0.102196, 0.046281},
|
||||||
|
{0.164494, -0.057325, -0.132860, 0.024093},
|
||||||
|
{0.109419, -0.013999, -0.169596, 0.020412},
|
||||||
|
{0.039180, -0.209168, -0.035872, 0.087949},
|
||||||
|
{0.012790, -0.177723, -0.129986, 0.073364},
|
||||||
|
{0.045261, -0.256694, -0.088186, 0.004212},
|
||||||
|
{-0.005314, -0.231202, -0.191671, -0.002628},
|
||||||
|
{0.037963, -0.153227, -0.045364, 0.003322},
|
||||||
|
{0.030800, -0.126452, -0.114266, -0.010414},
|
||||||
|
{0.044125, -0.184146, -0.081400, -0.077341},
|
||||||
|
{0.029204, -0.157393, -0.172017, -0.089814},
|
||||||
|
{0.393519, -0.043228, -0.111365, -0.000740},
|
||||||
|
{0.289581, 0.018928, -0.123140, 0.000713},
|
||||||
|
{0.311229, -0.059735, -0.198982, -0.081664},
|
||||||
|
{0.258659, 0.052505, -0.211913, -0.034928},
|
||||||
|
{0.300693, 0.011381, -0.083545, -0.086683},
|
||||||
|
{0.214523, 0.053878, -0.101199, -0.061018},
|
||||||
|
{0.253422, 0.028496, -0.156752, -0.163342},
|
||||||
|
{0.199123, 0.113877, -0.166220, -0.102584},
|
||||||
|
{0.249134, -0.165135, 0.028917, 0.051838},
|
||||||
|
{0.156434, -0.123708, 0.017053, 0.043043},
|
||||||
|
{0.214763, -0.101243, -0.005581, -0.020703},
|
||||||
|
{0.140554, -0.072067, -0.015063, -0.011165},
|
||||||
|
{0.241791, -0.152048, 0.106403, -0.046857},
|
||||||
|
{0.142316, -0.131899, 0.054076, -0.026485},
|
||||||
|
{0.206535, -0.086116, 0.046640, -0.097615},
|
||||||
|
{0.129759, -0.081874, 0.004693, -0.073169}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbeHOCb5[32][4] = {
|
||||||
|
{0.264108, 0.045976, -0.200999, -0.122344},
|
||||||
|
{0.479006, 0.227924, -0.016114, -0.006835},
|
||||||
|
{0.077297, 0.080775, -0.068936, 0.041733},
|
||||||
|
{0.185486, 0.231840, 0.182410, 0.101613},
|
||||||
|
{-0.012442, 0.223718, -0.277803, -0.034370},
|
||||||
|
{-0.059507, 0.139621, -0.024708, -0.104205},
|
||||||
|
{-0.248676, 0.255502, -0.134894, -0.058338},
|
||||||
|
{-0.055122, 0.427253, 0.025059, -0.045051},
|
||||||
|
{-0.058898, -0.061945, 0.028030, -0.022242},
|
||||||
|
{0.084153, 0.025327, 0.066780, -0.180839},
|
||||||
|
{-0.193125, -0.082632, 0.140899, -0.089559},
|
||||||
|
{0.000000, 0.033758, 0.276623, 0.002493},
|
||||||
|
{-0.396582, -0.049543, -0.118100, -0.208305},
|
||||||
|
{-0.287112, 0.096620, 0.049650, -0.079312},
|
||||||
|
{-0.543760, 0.171107, -0.062173, -0.010483},
|
||||||
|
{-0.353572, 0.227440, 0.230128, -0.032089},
|
||||||
|
{0.248579, -0.279824, -0.209589, 0.070903},
|
||||||
|
{0.377604, -0.119639, 0.008463, -0.005589},
|
||||||
|
{0.102127, -0.093666, -0.061325, 0.052082},
|
||||||
|
{0.154134, -0.105724, 0.099317, 0.187972},
|
||||||
|
{-0.139232, -0.091146, -0.275479, -0.038435},
|
||||||
|
{-0.144169, 0.034314, -0.030840, 0.022207},
|
||||||
|
{-0.143985, 0.079414, -0.194701, 0.175312},
|
||||||
|
{-0.195329, 0.087467, 0.067711, 0.186783},
|
||||||
|
{-0.123515, -0.377873, -0.209929, -0.212677},
|
||||||
|
{0.068698, -0.255933, 0.120463, -0.095629},
|
||||||
|
{-0.106810, -0.319964, -0.089322, 0.106947},
|
||||||
|
{-0.158605, -0.309606, 0.190900, 0.089340},
|
||||||
|
{-0.489162, -0.432784, -0.151215, -0.005786},
|
||||||
|
{-0.370883, -0.154342, -0.022545, 0.114054},
|
||||||
|
{-0.742866, -0.204364, -0.123865, -0.038888},
|
||||||
|
{-0.573077, -0.115287, 0.208879, -0.027698}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbeHOCb6[16][4] = {
|
||||||
|
{-0.143886, 0.235528, -0.116707, 0.025541},
|
||||||
|
{-0.170182, -0.063822, -0.096934, 0.109704},
|
||||||
|
{0.232915, 0.269793, 0.047064, -0.032761},
|
||||||
|
{0.153458, 0.068130, -0.033513, 0.126553},
|
||||||
|
{-0.440712, 0.132952, 0.081378, -0.013210},
|
||||||
|
{-0.480433, -0.249687, -0.012280, 0.007112},
|
||||||
|
{-0.088001, 0.167609, 0.148323, -0.119892},
|
||||||
|
{-0.104628, 0.102639, 0.183560, 0.121674},
|
||||||
|
{0.047408, -0.000908, -0.214196, -0.109372},
|
||||||
|
{0.113418, -0.240340, -0.121420, 0.041117},
|
||||||
|
{0.385609, 0.042913, -0.184584, -0.017851},
|
||||||
|
{0.453830, -0.180745, 0.050455, 0.030984},
|
||||||
|
{-0.155984, -0.144212, 0.018226, -0.146356},
|
||||||
|
{-0.104028, -0.260377, 0.146472, 0.101389},
|
||||||
|
{0.012376, -0.000267, 0.006657, -0.013941},
|
||||||
|
{0.165852, -0.103467, 0.119713, -0.075455}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbeHOCb7[16][4] = {
|
||||||
|
{0.182478, 0.271794, -0.057639, 0.026115},
|
||||||
|
{0.110795, 0.092854, 0.078125, -0.082726},
|
||||||
|
{0.057964, 0.000833, 0.176048, 0.135404},
|
||||||
|
{-0.027315, 0.098668, -0.065801, 0.116421},
|
||||||
|
{-0.222796, 0.062967, 0.201740, -0.089975},
|
||||||
|
{-0.193571, 0.309225, -0.014101, -0.034574},
|
||||||
|
{-0.389053, -0.181476, 0.107682, 0.050169},
|
||||||
|
{-0.345604, 0.064900, -0.065014, 0.065642},
|
||||||
|
{0.319393, -0.055491, -0.220727, -0.067499},
|
||||||
|
{0.460572, 0.084686, 0.048453, -0.011050},
|
||||||
|
{0.201623, -0.068994, -0.067101, 0.108320},
|
||||||
|
{0.227528, -0.173900, 0.092417, -0.066515},
|
||||||
|
{-0.016927, 0.047757, -0.177686, -0.102163},
|
||||||
|
{-0.052553, -0.065689, 0.019328, -0.033060},
|
||||||
|
{-0.144910, -0.238617, -0.195206, -0.063917},
|
||||||
|
{-0.024159, -0.338822, 0.003581, 0.060995}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Higher Order Coefficients
|
||||||
|
*/
|
||||||
|
const float AmbeHOCb8[8][4] = {
|
||||||
|
{0.323968, 0.008964, -0.063117, 0.027909},
|
||||||
|
{0.010900, -0.004030, -0.125016, -0.080818},
|
||||||
|
{0.109969, 0.256272, 0.042470, 0.000749},
|
||||||
|
{-0.135446, 0.201769, -0.083426, 0.093888},
|
||||||
|
{-0.441995, 0.038159, 0.022784, 0.003943},
|
||||||
|
{-0.155951, 0.032467, 0.145309, -0.041725},
|
||||||
|
{-0.149182, -0.223356, -0.065793, 0.075016},
|
||||||
|
{0.096949, -0.096400, 0.083194, 0.049306}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __AMBE3600x2450_CONST_H__
|
||||||
@ -0,0 +1,179 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "vocoder/ecc_const.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
void mbe_checkGolayBlock(long int* block)
|
||||||
|
{
|
||||||
|
static int i, syndrome, eccexpected, eccbits, databits;
|
||||||
|
long int mask, block_l;
|
||||||
|
|
||||||
|
block_l = *block;
|
||||||
|
|
||||||
|
mask = 0x400000l;
|
||||||
|
eccexpected = 0;
|
||||||
|
for (i = 0; i < 12; i++) {
|
||||||
|
if ((block_l & mask) != 0l) {
|
||||||
|
eccexpected ^= golayGenerator[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mask = mask >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eccbits = (int)(block_l & 0x7ffl);
|
||||||
|
syndrome = eccexpected ^ eccbits;
|
||||||
|
|
||||||
|
databits = (int)(block_l >> 11);
|
||||||
|
databits = databits ^ golayMatrix[syndrome];
|
||||||
|
|
||||||
|
*block = (long)databits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_golay2312(char* in, char* out)
|
||||||
|
{
|
||||||
|
int i, errs;
|
||||||
|
long block;
|
||||||
|
|
||||||
|
block = 0;
|
||||||
|
for (i = 22; i >= 0; i--) {
|
||||||
|
block = block << 1;
|
||||||
|
block = block + in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
mbe_checkGolayBlock(&block);
|
||||||
|
|
||||||
|
for (i = 22; i >= 11; i--) {
|
||||||
|
out[i] = (block & 2048) >> 11;
|
||||||
|
block = block << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 10; i >= 0; i--) {
|
||||||
|
out[i] = in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = 0;
|
||||||
|
for (i = 22; i >= 11; i--) {
|
||||||
|
if (out[i] != in[i]) {
|
||||||
|
errs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_hamming1511(char* in, char* out)
|
||||||
|
{
|
||||||
|
int i, j, errs, block, syndrome, stmp, stmp2;
|
||||||
|
|
||||||
|
errs = 0;
|
||||||
|
|
||||||
|
block = 0;
|
||||||
|
for (i = 14; i >= 0; i--) {
|
||||||
|
block <<= 1;
|
||||||
|
block |= in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
syndrome = 0;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
syndrome <<= 1;
|
||||||
|
stmp = block;
|
||||||
|
stmp &= hammingGenerator[i];
|
||||||
|
|
||||||
|
stmp2 = (stmp % 2);
|
||||||
|
for (j = 0; j < 14; j++)
|
||||||
|
{
|
||||||
|
stmp >>= 1;
|
||||||
|
stmp2 ^= (stmp % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
syndrome |= stmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syndrome > 0) {
|
||||||
|
errs++;
|
||||||
|
block ^= hammingMatrix[syndrome];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 14; i >= 0; i--) {
|
||||||
|
out[i] = (block & 0x4000) >> 14;
|
||||||
|
block = block << 1;
|
||||||
|
}
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
int mbe_7100x4400Hamming1511(char* in, char* out)
|
||||||
|
{
|
||||||
|
int i, j, errs, block, syndrome, stmp, stmp2;
|
||||||
|
|
||||||
|
errs = 0;
|
||||||
|
|
||||||
|
block = 0;
|
||||||
|
for (i = 14; i >= 0; i--) {
|
||||||
|
block <<= 1;
|
||||||
|
block |= in[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
syndrome = 0;
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
syndrome <<= 1;
|
||||||
|
stmp = block;
|
||||||
|
stmp &= imbe7100x4400hammingGenerator[i];
|
||||||
|
|
||||||
|
stmp2 = (stmp % 2);
|
||||||
|
for (j = 0; j < 14; j++)
|
||||||
|
{
|
||||||
|
stmp >>= 1;
|
||||||
|
stmp2 ^= (stmp % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
syndrome |= stmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syndrome > 0) {
|
||||||
|
errs++;
|
||||||
|
block ^= hammingMatrix[syndrome];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 14; i >= 0; i--) {
|
||||||
|
out[i] = (block & 0x4000) >> 14;
|
||||||
|
block = block << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (errs);
|
||||||
|
}
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Digital Voice Modem - MBE Vocoder
|
||||||
|
* GPLv2 Open Source. Use is subject to license terms.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file ecc_const.h
|
||||||
|
* @ingroup vocoder
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 mbelib Author
|
||||||
|
* GPG Key ID: 0xEA5EFE2C (9E7A 5527 9CDC EBF7 BF1B D772 4F98 E863 EA5E FE2C)
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||||
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
#if !defined(__ECC_CONST_H__)
|
||||||
|
#define __ECC_CONST_H__
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const int hammingGenerator[4] = {
|
||||||
|
0x7f08, 0x78e4, 0x66d2, 0x55b1
|
||||||
|
};
|
||||||
|
|
||||||
|
const int imbe7100x4400hammingGenerator[4] = {
|
||||||
|
0x7ac8, 0x3d64, 0x1eb2, 0x7591
|
||||||
|
};
|
||||||
|
|
||||||
|
const int hammingMatrix[16] = {
|
||||||
|
0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000
|
||||||
|
};
|
||||||
|
|
||||||
|
const int golayGenerator[12] = {
|
||||||
|
0x63a, 0x31d, 0x7b4, 0x3da, 0x1ed, 0x6cc, 0x366, 0x1b3, 0x6e3, 0x54b, 0x49f, 0x475
|
||||||
|
};
|
||||||
|
|
||||||
|
const int golayMatrix[2048] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 2084, 0, 0, 0, 769, 0, 1024, 144,
|
||||||
|
2, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 72, 0, 72, 72, 72, 0, 0, 0, 16, 0, 1, 1538, 384, 0, 134, 2048, 1056, 288,
|
||||||
|
2576, 5, 72, 0, 0, 0, 0, 0, 0, 0, 1280, 0, 0, 0, 4, 0, 546, 144, 2049, 0, 0, 0, 66, 0, 1, 144, 520, 0, 2056, 144,
|
||||||
|
1056, 144, 324, 144, 144, 0, 0, 0, 2688, 0, 1, 32, 22, 0, 272, 3, 1056, 3076, 128, 768, 72, 0, 1, 268, 1056, 1, 1, 2112, 1, 576,
|
||||||
|
1056, 1056, 1056, 10, 1, 144, 1056, 0, 0, 0, 0, 0, 0, 0, 1280, 0, 0, 0, 160, 0, 21, 2560, 2, 0, 0, 0, 16, 0, 704, 9,
|
||||||
|
2, 0, 2056, 1092, 2, 288, 2, 2, 2, 0, 0, 0, 16, 0, 2050, 132, 545, 0, 1536, 3, 2308, 288, 128, 1040, 72, 0, 16, 16, 16, 288,
|
||||||
|
1036, 2112, 16, 288, 65, 648, 16, 288, 288, 288, 2, 0, 0, 0, 1280, 0, 1280, 1280, 1280, 0, 2056, 3, 592, 64, 128, 44, 1280, 0, 2056, 544,
|
||||||
|
133, 6, 48, 2112, 1280, 2056, 2056, 256, 2056, 1537, 2056, 144, 2, 0, 100, 3, 8, 536, 128, 2112, 1280, 3, 128, 3, 3, 128, 128, 3, 128, 1152,
|
||||||
|
770, 2112, 16, 2112, 1, 2112, 2112, 20, 2056, 3, 1056, 288, 128, 2112, 516, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 4, 0, 1024, 2560,
|
||||||
|
304, 0, 0, 0, 16, 0, 1024, 320, 520, 0, 1024, 42, 2240, 1024, 1024, 5, 1024, 0, 0, 0, 16, 0, 772, 32, 3072, 0, 2081, 1408, 514, 18,
|
||||||
|
128, 5, 72, 0, 16, 16, 16, 2184, 98, 5, 16, 576, 264, 5, 16, 5, 1024, 5, 5, 0, 0, 0, 4, 0, 2128, 32, 520, 0, 4, 4,
|
||||||
|
4, 265, 128, 1090, 4, 0, 416, 3073, 520, 6, 520, 520, 520, 576, 19, 256, 4, 2080, 1024, 144, 520, 0, 1034, 32, 321, 32, 128, 32, 32, 576,
|
||||||
|
128, 2072, 4, 128, 128, 32, 128, 576, 2052, 130, 16, 1296, 1, 32, 520, 576, 576, 576, 1056, 576, 128, 5, 2306, 0, 0, 0, 16, 0, 40, 2560,
|
||||||
|
68, 0, 322, 2560, 1033, 2560, 128, 2560, 2560, 0, 16, 16, 16, 6, 2305, 1184, 16, 129, 548, 256, 16, 88, 1024, 2560, 2, 0, 16, 16, 16, 1089,
|
||||||
|
128, 266, 16, 12, 128, 96, 16, 128, 128, 2560, 128, 16, 16, 16, 16, 512, 16, 16, 16, 3074, 16, 16, 16, 288, 128, 5, 16, 0, 513, 200,
|
||||||
|
2082, 6, 128, 17, 1280, 1072, 128, 256, 4, 128, 128, 2560, 128, 6, 1088, 256, 16, 6, 6, 6, 520, 256, 2056, 256, 256, 6, 128, 256, 97, 2304,
|
||||||
|
128, 1540, 16, 128, 128, 32, 128, 128, 128, 3, 128, 128, 128, 128, 128, 41, 16, 16, 16, 6, 128, 2112, 16, 576, 128, 256, 16, 128, 128, 1032,
|
||||||
|
128, 0, 0, 0, 0, 0, 0, 0, 528, 0, 0, 0, 160, 0, 1024, 262, 2049, 0, 0, 0, 66, 0, 1024, 9, 384, 0, 1024, 2048, 28, 1024,
|
||||||
|
1024, 608, 1024, 0, 0, 0, 1029, 0, 2050, 32, 384, 0, 272, 2048, 514, 641, 36, 1040, 72, 0, 552, 2048, 384, 84, 384, 384, 384, 2048, 65, 2048,
|
||||||
|
2048, 10, 1024, 2048, 384, 0, 0, 0, 66, 0, 140, 32, 2049, 0, 272, 1544, 2049, 64, 2049, 2049, 2049, 0, 66, 66, 66, 2816, 48, 1028, 66, 37,
|
||||||
|
640, 256, 66, 10, 1024, 144, 2049, 0, 272, 32, 8, 32, 1600, 32, 32, 272, 272, 196, 272, 10, 272, 32, 2049, 1152, 2052, 529, 66, 10, 1, 32,
|
||||||
|
384, 10, 272, 2048, 1056, 10, 10, 10, 516, 0, 0, 0, 160, 0, 2050, 9, 68, 0, 160, 160, 160, 64, 776, 1040, 160, 0, 260, 9, 3584, 9,
|
||||||
|
48, 9, 9, 530, 65, 256, 160, 2180, 1024, 9, 2, 0, 2050, 832, 8, 2050, 2050, 1040, 2050, 12, 65, 1040, 160, 1040, 2050, 1040, 1040, 1152, 65, 38,
|
||||||
|
16, 512, 2050, 9, 384, 65, 65, 2048, 65, 288, 65, 1040, 516, 0, 513, 2068, 8, 64, 48, 642, 1280, 64, 1030, 256, 160, 64, 64, 64, 2049, 1152,
|
||||||
|
48, 256, 66, 48, 48, 9, 48, 256, 2056, 256, 256, 64, 48, 256, 516, 1152, 8, 8, 8, 261, 2050, 32, 8, 2592, 272, 3, 8, 64, 128, 1040,
|
||||||
|
516, 1152, 1152, 1152, 8, 1152, 48, 2112, 516, 1152, 65, 256, 516, 10, 516, 516, 516, 0, 0, 0, 2312, 0, 1024, 32, 68, 0, 1024, 81, 514, 1024,
|
||||||
|
1024, 136, 1024, 0, 1024, 644, 33, 1024, 1024, 2066, 1024, 1024, 1024, 256, 1024, 1024, 1024, 1024, 1024, 0, 192, 32, 514, 32, 25, 32, 32, 12, 514, 514,
|
||||||
|
514, 2368, 1024, 32, 514, 259, 2052, 1096, 16, 512, 1024, 32, 384, 176, 1024, 2048, 514, 1024, 1024, 5, 1024, 0, 513, 32, 1168, 32, 258, 32, 32, 2178,
|
||||||
|
104, 256, 4, 532, 1024, 32, 2049, 24, 2052, 256, 66, 193, 1024, 32, 520, 256, 1024, 256, 256, 1024, 1024, 256, 1024, 32, 2052, 32, 32, 32, 32, 32,
|
||||||
|
32, 1025, 272, 32, 514, 32, 128, 32, 32, 2052, 2052, 32, 2052, 32, 2052, 32, 32, 576, 2052, 256, 137, 10, 1024, 32, 80, 0, 513, 1026, 68, 400,
|
||||||
|
68, 68, 68, 12, 2064, 256, 160, 35, 1024, 2560, 68, 2144, 138, 256, 16, 512, 1024, 9, 68, 256, 1024, 256, 256, 1024, 1024, 256, 1024, 12, 1312, 2177,
|
||||||
|
16, 512, 2050, 32, 68, 12, 12, 12, 514, 12, 128, 1040, 257, 512, 16, 16, 16, 512, 512, 512, 16, 12, 65, 256, 16, 512, 1024, 194, 2088, 513,
|
||||||
|
513, 256, 513, 3080, 513, 32, 68, 256, 513, 256, 256, 64, 128, 256, 26, 256, 513, 256, 256, 6, 48, 256, 2176, 256, 256, 256, 256, 256, 1024, 256,
|
||||||
|
256, 82, 513, 32, 8, 32, 128, 32, 32, 12, 128, 256, 3136, 128, 128, 32, 128, 1152, 2052, 256, 16, 512, 328, 32, 1027, 256, 34, 256, 256, 2065,
|
||||||
|
128, 256, 516, 0, 0, 0, 0, 0, 0, 0, 528, 0, 0, 0, 4, 0, 2432, 1057, 2, 0, 0, 0, 1160, 0, 1, 320, 2, 0, 112, 2048,
|
||||||
|
2, 524, 2, 2, 2, 0, 0, 0, 290, 0, 1, 132, 3072, 0, 1536, 2048, 145, 18, 36, 768, 72, 0, 1, 2048, 580, 1, 1, 56, 1, 2048,
|
||||||
|
264, 2048, 2048, 1216, 1, 2048, 2, 0, 0, 0, 4, 0, 1, 2058, 224, 0, 4, 4, 4, 64, 1048, 768, 4, 0, 1, 544, 2320, 1, 1, 1028,
|
||||||
|
1, 1282, 640, 73, 4, 2080, 1, 144, 2, 0, 1, 1104, 8, 1, 1, 768, 1, 168, 2114, 768, 4, 768, 1, 768, 768, 1, 1, 130, 1, 1,
|
||||||
|
1, 1, 1, 20, 1, 2048, 1056, 1, 1, 768, 1, 0, 0, 0, 2113, 0, 40, 132, 2, 0, 1536, 280, 2, 64, 2, 2, 2, 0, 260, 544,
|
||||||
|
2, 3088, 2, 2, 2, 129, 2, 2, 2, 2, 2, 2, 2, 0, 1536, 132, 8, 132, 336, 132, 132, 1536, 1536, 96, 1536, 2057, 1536, 132, 2, 74,
|
||||||
|
2208, 1281, 16, 512, 1, 132, 2, 20, 1536, 2048, 2, 288, 2, 2, 2, 0, 146, 544, 8, 64, 2564, 17, 1280, 64, 289, 3200, 4, 64, 64, 64,
|
||||||
|
2, 544, 1088, 544, 544, 392, 1, 544, 2, 20, 2056, 544, 2, 64, 2, 2, 2, 2304, 8, 8, 8, 1058, 1, 132, 8, 20, 1536, 3, 8, 64,
|
||||||
|
128, 768, 2096, 20, 1, 544, 8, 1, 1, 2112, 1, 20, 20, 20, 448, 20, 1, 1032, 2, 0, 0, 0, 4, 0, 40, 320, 3072, 0, 4, 4,
|
||||||
|
4, 18, 577, 136, 4, 0, 2562, 320, 33, 320, 148, 320, 320, 129, 264, 1552, 4, 2080, 1024, 320, 2, 0, 192, 521, 3072, 18, 3072, 3072, 3072, 18,
|
||||||
|
264, 96, 4, 18, 18, 18, 3072, 1060, 264, 130, 16, 512, 1, 320, 3072, 264, 264, 2048, 264, 18, 264, 5, 672, 0, 4, 4, 4, 1664, 258, 17,
|
||||||
|
4, 4, 4, 4, 4, 2080, 4, 4, 4, 24, 1088, 130, 4, 2080, 1, 320, 520, 2080, 4, 4, 4, 2080, 2080, 2080, 4, 2304, 560, 130, 4, 76,
|
||||||
|
1, 32, 3072, 1025, 4, 4, 4, 18, 128, 768, 4, 130, 1, 130, 130, 1, 1, 130, 1, 576, 264, 130, 4, 2080, 1, 1032, 80, 0, 40, 1026,
|
||||||
|
896, 40, 40, 17, 40, 129, 2064, 96, 4, 1284, 40, 2560, 2, 129, 1088, 2060, 16, 512, 40, 320, 2, 129, 129, 129, 2, 129, 2, 2, 2, 2304,
|
||||||
|
7, 96, 16, 512, 40, 132, 3072, 96, 1536, 96, 96, 18, 128, 96, 257, 512, 16, 16, 16, 512, 512, 512, 16, 129, 264, 96, 16, 512, 2116, 1032,
|
||||||
|
2, 2304, 1088, 17, 4, 17, 40, 17, 17, 522, 4, 4, 4, 64, 128, 17, 4, 1088, 1088, 544, 1088, 6, 1088, 17, 2176, 129, 1088, 256, 4, 2080,
|
||||||
|
784, 1032, 2, 2304, 2304, 2304, 8, 2304, 128, 17, 578, 2304, 128, 96, 4, 128, 128, 1032, 128, 2304, 1088, 130, 16, 512, 1, 1032, 292, 20, 34, 1032,
|
||||||
|
2561, 1032, 128, 1032, 1032, 0, 0, 0, 528, 0, 528, 528, 528, 0, 11, 2048, 1344, 64, 36, 136, 528, 0, 260, 2048, 33, 162, 2120, 1028, 528, 2048,
|
||||||
|
640, 2048, 2048, 273, 1024, 2048, 2, 0, 192, 2048, 8, 1288, 36, 67, 528, 2048, 36, 2048, 2048, 36, 36, 2048, 36, 2048, 1042, 2048, 2048, 512, 1, 2048,
|
||||||
|
384, 2048, 2048, 2048, 2048, 2048, 36, 2048, 2048, 0, 3104, 385, 8, 64, 258, 1028, 528, 64, 640, 50, 4, 64, 64, 64, 2049, 24, 640, 1028, 66, 1028,
|
||||||
|
1, 1028, 1028, 640, 640, 2048, 640, 64, 640, 1028, 296, 518, 8, 8, 8, 2192, 1, 32, 8, 1025, 272, 2048, 8, 64, 36, 768, 1154, 352, 1, 2048,
|
||||||
|
8, 1, 1, 1028, 1, 2048, 640, 2048, 2048, 10, 1, 2048, 80, 0, 260, 1026, 8, 64, 1153, 2336, 528, 64, 2064, 517, 160, 64, 64, 64, 2, 260,
|
||||||
|
260, 208, 260, 512, 260, 9, 2, 1064, 260, 2048, 2, 64, 2, 2, 2, 49, 8, 8, 8, 512, 2050, 132, 8, 386, 1536, 2048, 8, 64, 36, 1040,
|
||||||
|
257, 512, 260, 2048, 8, 512, 512, 512, 1120, 2048, 65, 2048, 2048, 512, 152, 2048, 2, 64, 8, 8, 8, 64, 64, 64, 8, 64, 64, 64, 8, 64,
|
||||||
|
64, 64, 64, 2051, 260, 544, 8, 64, 48, 1028, 2176, 64, 640, 256, 1041, 64, 64, 64, 2, 8, 8, 8, 8, 64, 8, 8, 8, 64, 8, 8,
|
||||||
|
8, 64, 64, 64, 8, 1152, 8, 8, 8, 512, 1, 274, 8, 20, 34, 2048, 8, 64, 3328, 161, 516, 0, 192, 1026, 33, 2053, 258, 136, 528, 800,
|
||||||
|
2064, 136, 4, 136, 1024, 136, 136, 24, 33, 33, 33, 512, 1024, 320, 33, 70, 1024, 2048, 33, 1024, 1024, 136, 1024, 192, 192, 276, 192, 512, 192, 32,
|
||||||
|
3072, 1025, 192, 2048, 514, 18, 36, 136, 257, 512, 192, 2048, 33, 512, 512, 512, 14, 2048, 264, 2048, 2048, 512, 1024, 2048, 80, 24, 258, 2624, 4, 258,
|
||||||
|
258, 32, 258, 1025, 4, 4, 4, 64, 258, 136, 4, 24, 24, 24, 33, 24, 258, 1028, 2176, 24, 640, 256, 4, 2080, 1024, 515, 80, 1025, 192, 32,
|
||||||
|
8, 32, 258, 32, 32, 1025, 1025, 1025, 4, 1025, 2568, 32, 80, 24, 2052, 130, 1792, 512, 1, 32, 80, 1025, 34, 2048, 80, 388, 80, 80, 80, 1026,
|
||||||
|
2064, 1026, 1026, 512, 40, 1026, 68, 2064, 2064, 1026, 2064, 64, 2064, 136, 257, 512, 260, 1026, 33, 512, 512, 512, 2176, 129, 2064, 256, 584, 512, 1024, 52,
|
||||||
|
2, 512, 192, 1026, 8, 512, 512, 512, 257, 12, 2064, 96, 257, 512, 257, 257, 257, 512, 512, 512, 16, 512, 512, 512, 512, 512, 34, 2048, 1156, 512,
|
||||||
|
512, 512, 257, 164, 513, 1026, 8, 64, 258, 17, 2176, 64, 2064, 256, 4, 64, 64, 64, 1568, 24, 1088, 256, 2176, 512, 2176, 2176, 2176, 256, 34, 256,
|
||||||
|
256, 64, 13, 256, 2176, 2304, 8, 8, 8, 512, 1044, 32, 8, 1025, 34, 656, 8, 64, 128, 2054, 257, 512, 34, 69, 8, 512, 512, 512, 2176, 34,
|
||||||
|
34, 256, 34, 512, 34, 1032, 80
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __ECC_CONST_H__
|
||||||
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Project 25 IMBE Encoder/Decoder Fixed-Point implementation
|
||||||
|
* Developed by Pavel Yazev E-mail: pyazev@gmail.com
|
||||||
|
* Version 1.0 (c) Copyright 2009
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The 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; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vocoder/imbe/typedef.h"
|
||||||
|
#include "vocoder/imbe/basic_op.h"
|
||||||
|
#include "vocoder/imbe/imbe.h"
|
||||||
|
#include "vocoder/imbe/aux_sub.h"
|
||||||
|
#include "vocoder/imbe/tbls.h"
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Return pointer to bit allocation array
|
||||||
|
// according to the number of harmonics
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// num_harms - The number of harmonics
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// Pointer to bits allocation array
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
const UWord16* get_bit_allocation_arr(Word16 num_harms)
|
||||||
|
{
|
||||||
|
Word16 offset_in_word, index;
|
||||||
|
|
||||||
|
if (num_harms == NUM_HARMS_MIN)
|
||||||
|
return &bit_allocation_tbl[0];
|
||||||
|
else {
|
||||||
|
index = num_harms - NUM_HARMS_MIN - 1;
|
||||||
|
offset_in_word = bit_allocation_offset_tbl[index >> 2] + ((3 + (index >> 2)) * (index & 0x3));
|
||||||
|
return &bit_allocation_tbl[offset_in_word];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Unpack bit allocation table's item
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// num_harms - The number of harmonics
|
||||||
|
// ptr - Pointer to buffer to place bit allocation data
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Unpacked bit allocation table
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void get_bit_allocation(Word16 num_harms, Word16* ptr)
|
||||||
|
{
|
||||||
|
const UWord16* bat_ptr;
|
||||||
|
Word16 i, tmp;
|
||||||
|
|
||||||
|
bat_ptr = get_bit_allocation_arr(num_harms);
|
||||||
|
|
||||||
|
for (i = 0; i < num_harms - 1; i += 4) {
|
||||||
|
tmp = *bat_ptr++;
|
||||||
|
ptr[3] = tmp & 0xF; tmp >>= 4;
|
||||||
|
ptr[2] = tmp & 0xF; tmp >>= 4;
|
||||||
|
ptr[1] = tmp & 0xF; tmp >>= 4;
|
||||||
|
ptr[0] = tmp & 0xF;
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Set the elements of a 16 bit input vector to zero.
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec - Pointer to vector
|
||||||
|
// n - size of vec
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_zap(Word16* vec, Word16 n)
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
*vec++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Copy the contents of one 16 bit input vector to another
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec1 - Pointer to the destination vector
|
||||||
|
// vec2 - Pointer to the source vector
|
||||||
|
// n - size of data should be copied
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Copy of the source vector
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_equ(Word16* vec1, Word16* vec2, Word16 n)
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
*vec1++ = *vec2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Compute the sum of square magnitude of a 16 bit input vector
|
||||||
|
// with saturation and truncation. Output is a 32 bit number.
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec - Pointer to the vector
|
||||||
|
// n - size of input vectors
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// none
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// 32 bit long signed integer result
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
Word32 L_v_magsq(Word16* vec, Word16 n)
|
||||||
|
{
|
||||||
|
Word32 L_magsq = 0;
|
||||||
|
|
||||||
|
while (n--) {
|
||||||
|
L_magsq = L_mac(L_magsq, *vec, *vec);
|
||||||
|
vec++;
|
||||||
|
}
|
||||||
|
return L_magsq;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Copy the contents of one 16 bit input vector to another with shift
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec1 - Pointer to the destination vector
|
||||||
|
// vec2 - Pointer to the source vector
|
||||||
|
// scale - right shift factor
|
||||||
|
// n - size of data should be copied
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Copy of the source vector
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_equ_shr(Word16* vec1, Word16* vec2, Word16 scale, Word16 n)
|
||||||
|
{
|
||||||
|
while (n--)
|
||||||
|
*vec1++ = shr(*vec2++, scale);
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Project 25 IMBE Encoder/Decoder Fixed-Point implementation
|
||||||
|
* Developed by Pavel Yazev E-mail: pyazev@gmail.com
|
||||||
|
* Version 1.0 (c) Copyright 2009
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The 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; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __AUX_SUB_H__
|
||||||
|
#define __AUX_SUB_H__
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Return pointer to bit allocation array
|
||||||
|
// according to the number of harmonics
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// num_harms - The number of harmonics
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// Pointer to bits allocation array
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
const UWord16 *get_bit_allocation_arr(Word16 num_harms);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Unpack bit allocation table's item
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// num_harms - The number of harmonics
|
||||||
|
// ptr - Pointer to buffer to place bit allocation data
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Unpacked bit allocation table
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void get_bit_allocation(Word16 num_harms, Word16 *ptr);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Set the elements of a 16 bit input vector to zero.
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec - Pointer to vector
|
||||||
|
// n - size of vec
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_zap(Word16 *vec, Word16 n);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Copy the contents of one 16 bit input vector to another
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec1 - Pointer to the destination vector
|
||||||
|
// vec2 - Pointer to the source vector
|
||||||
|
// n - size of data should be copied
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Copy of the source vector
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_equ(Word16 *vec1, Word16 *vec2, Word16 n);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Compute the sum of square magnitude of a 16 bit input vector
|
||||||
|
// with saturation and truncation. Output is a 32 bit number.
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec - Pointer to the vector
|
||||||
|
// n - size of input vectors
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// none
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// 32 bit long signed integer result
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
Word32 L_v_magsq(Word16 *vec, Word16 n);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// PURPOSE:
|
||||||
|
// Copy the contents of one 16 bit input vector to another with shift
|
||||||
|
//
|
||||||
|
// INPUT:
|
||||||
|
// vec1 - Pointer to the destination vector
|
||||||
|
// vec2 - Pointer to the source vector
|
||||||
|
// scale - right shift factor
|
||||||
|
// n - size of data should be copied
|
||||||
|
//
|
||||||
|
// OUTPUT:
|
||||||
|
// Copy of the source vector
|
||||||
|
//
|
||||||
|
// RETURN:
|
||||||
|
// None
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void v_equ_shr(Word16 *vec1, Word16 *vec2, Word16 scale, Word16 n);
|
||||||
|
|
||||||
|
#endif // __AUX_SUB_H__
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Project 25 IMBE Encoder/Decoder Fixed-Point implementation
|
||||||
|
* Developed by Pavel Yazev E-mail: pyazev@gmail.com
|
||||||
|
* Version 1.0 (c) Copyright 2009
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The 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; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, Inc., 51 Franklin Street, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
#ifndef __BASIC_OP_H__
|
||||||
|
#define __BASIC_OP_H__
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Constants and Globals
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
extern Flag Overflow;
|
||||||
|
extern Flag Carry;
|
||||||
|
|
||||||
|
#define MAX_32 (Word32)0x7fffffffL
|
||||||
|
#define MIN_32 (Word32)0x80000000L
|
||||||
|
|
||||||
|
#define MAX_16 (Word16)0x7fff
|
||||||
|
#define MIN_16 (Word16)0x8000
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Word16 add(Word16 var1, Word16 var2); /* Short add, 1 */
|
||||||
|
Word16 sub(Word16 var1, Word16 var2); /* Short sub, 1 */
|
||||||
|
Word16 abs_s(Word16 var1); /* Short abs, 1 */
|
||||||
|
Word16 shl(Word16 var1, Word16 var2); /* Short shift left, 1 */
|
||||||
|
Word16 shr(Word16 var1, Word16 var2); /* Short shift right, 1 */
|
||||||
|
Word16 mult(Word16 var1, Word16 var2); /* Short mult, 1 */
|
||||||
|
Word32 L_mult(Word16 var1, Word16 var2); /* Long mult, 1 */
|
||||||
|
Word16 negate(Word16 var1); /* Short negate, 1 */
|
||||||
|
Word16 extract_h(Word32 L_var1); /* Extract high, 1 */
|
||||||
|
Word16 extract_l(Word32 L_var1); /* Extract low, 1 */
|
||||||
|
Word16 L_round(Word32 L_var1); /* Round, 1 */
|
||||||
|
Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */
|
||||||
|
Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */
|
||||||
|
Word32 L_macNs(Word32 L_var3, Word16 var1, Word16 var2); /* Mac without
|
||||||
|
sat, 1 */
|
||||||
|
Word32 L_msuNs(Word32 L_var3, Word16 var1, Word16 var2); /* Msu without
|
||||||
|
sat, 1 */
|
||||||
|
Word32 L_add(Word32 L_var1, Word32 L_var2); /* Long add, 2 */
|
||||||
|
Word32 L_sub(Word32 L_var1, Word32 L_var2); /* Long sub, 2 */
|
||||||
|
Word32 L_add_c(Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */
|
||||||
|
Word32 L_sub_c(Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */
|
||||||
|
Word32 L_negate(Word32 L_var1); /* Long negate, 2 */
|
||||||
|
Word16 mult_r(Word16 var1, Word16 var2); /* Mult with round, 2 */
|
||||||
|
Word32 L_shl(Word32 L_var1, Word16 var2); /* Long shift left, 2 */
|
||||||
|
Word32 L_shr(Word32 L_var1, Word16 var2); /* Long shift right, 2*/
|
||||||
|
Word16 shr_r(Word16 var1, Word16 var2); /* Shift right with
|
||||||
|
round, 2 */
|
||||||
|
Word16 mac_r(Word32 L_var3, Word16 var1, Word16 var2); /* Mac with
|
||||||
|
rounding,2 */
|
||||||
|
Word16 msu_r(Word32 L_var3, Word16 var1, Word16 var2); /* Msu with
|
||||||
|
rounding,2 */
|
||||||
|
Word32 L_deposit_h(Word16 var1); /* 16 bit var1 -> MSB, 2 */
|
||||||
|
Word32 L_deposit_l(Word16 var1); /* 16 bit var1 -> LSB, 2 */
|
||||||
|
|
||||||
|
Word32 L_shr_r(Word32 L_var1, Word16 var2); /* Long shift right with
|
||||||
|
round, 3 */
|
||||||
|
Word32 L_abs(Word32 L_var1); /* Long abs, 3 */
|
||||||
|
Word32 L_sat(Word32 L_var1); /* Long saturation, 4 */
|
||||||
|
Word16 norm_s(Word16 var1); /* Short norm, 15 */
|
||||||
|
Word16 div_s(Word16 var1, Word16 var2); /* Short division, 18 */
|
||||||
|
Word16 norm_l(Word32 L_var1); /* Long norm, 30 */
|
||||||
|
|
||||||
|
#endif // __BASIC_OP_H__
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue