From f0a60f3134f1a83de74c69d673e964e2454f15da Mon Sep 17 00:00:00 2001 From: Doug McLain Date: Mon, 16 Oct 2023 20:16:33 -0400 Subject: [PATCH] Add external dependencies to source --- DroidStar.pro | 82 +- README.md | 8 +- imbe_vocoder/aux_sub.cc | 184 +++ imbe_vocoder/aux_sub.h | 133 ++ imbe_vocoder/basic_op.h | 85 ++ imbe_vocoder/basicop2.cc | 2157 +++++++++++++++++++++++++++++ imbe_vocoder/ch_decode.cc | 185 +++ imbe_vocoder/ch_decode.h | 32 + imbe_vocoder/ch_encode.cc | 110 ++ imbe_vocoder/ch_encode.h | 32 + imbe_vocoder/dc_rmv.cc | 66 + imbe_vocoder/dc_rmv.h | 46 + imbe_vocoder/decode.cc | 112 ++ imbe_vocoder/decode.h | 31 + imbe_vocoder/dsp_sub.cc | 278 ++++ imbe_vocoder/dsp_sub.h | 81 ++ imbe_vocoder/encode.cc | 142 ++ imbe_vocoder/encode.h | 33 + imbe_vocoder/globals.h | 62 + imbe_vocoder/imbe.h | 69 + imbe_vocoder/imbe_vocoder.cc | 37 + imbe_vocoder/imbe_vocoder.h | 32 + imbe_vocoder/imbe_vocoder_api.h | 68 + imbe_vocoder/imbe_vocoder_impl.cc | 42 + imbe_vocoder/imbe_vocoder_impl.h | 92 ++ imbe_vocoder/math_sub.cc | 355 +++++ imbe_vocoder/math_sub.h | 130 ++ imbe_vocoder/pe_lpf.cc | 74 + imbe_vocoder/pe_lpf.h | 47 + imbe_vocoder/pitch_est.cc | 350 +++++ imbe_vocoder/pitch_est.h | 29 + imbe_vocoder/pitch_ref.cc | 167 +++ imbe_vocoder/pitch_ref.h | 28 + imbe_vocoder/qnt_sub.cc | 144 ++ imbe_vocoder/qnt_sub.h | 86 ++ imbe_vocoder/rand_gen.cc | 61 + imbe_vocoder/rand_gen.h | 44 + imbe_vocoder/sa_decode.cc | 200 +++ imbe_vocoder/sa_decode.h | 64 + imbe_vocoder/sa_encode.cc | 296 ++++ imbe_vocoder/sa_encode.h | 30 + imbe_vocoder/sa_enh.cc | 202 +++ imbe_vocoder/sa_enh.h | 50 + imbe_vocoder/tbls.cc | 368 +++++ imbe_vocoder/tbls.h | 99 ++ imbe_vocoder/typedef.h | 74 + imbe_vocoder/typedefs.h | 201 +++ imbe_vocoder/uv_synt.cc | 147 ++ imbe_vocoder/uv_synt.h | 29 + imbe_vocoder/v_synt.cc | 248 ++++ imbe_vocoder/v_synt.h | 30 + imbe_vocoder/v_uv_det.cc | 373 +++++ imbe_vocoder/v_uv_det.h | 28 + mbe/ambe3600x2400.c | 746 ++++++++++ mbe/ambe3600x2400_const.h | 884 ++++++++++++ mbe/ambe3600x2450.c | 681 +++++++++ mbe/ambe3600x2450_const.h | 971 +++++++++++++ mbe/ecc.c | 172 +++ mbe/ecc_const.h | 112 ++ mbe/mbelib.c | 501 +++++++ mbe/mbelib.h | 113 ++ mbe/mbelib_const.h | 371 +++++ mbe/mbelib_parms.h | 44 + mbe/vocoder_plugin.cpp | 1299 +++++++++++++++++ mbe/vocoder_plugin.h | 62 + mbe/vocoder_plugin_api.h | 104 ++ mbe/vocoder_tables.h | 489 +++++++ mode.h | 4 +- 68 files changed, 14693 insertions(+), 13 deletions(-) create mode 100644 imbe_vocoder/aux_sub.cc create mode 100644 imbe_vocoder/aux_sub.h create mode 100644 imbe_vocoder/basic_op.h create mode 100644 imbe_vocoder/basicop2.cc create mode 100644 imbe_vocoder/ch_decode.cc create mode 100644 imbe_vocoder/ch_decode.h create mode 100644 imbe_vocoder/ch_encode.cc create mode 100644 imbe_vocoder/ch_encode.h create mode 100644 imbe_vocoder/dc_rmv.cc create mode 100644 imbe_vocoder/dc_rmv.h create mode 100644 imbe_vocoder/decode.cc create mode 100644 imbe_vocoder/decode.h create mode 100644 imbe_vocoder/dsp_sub.cc create mode 100644 imbe_vocoder/dsp_sub.h create mode 100644 imbe_vocoder/encode.cc create mode 100644 imbe_vocoder/encode.h create mode 100644 imbe_vocoder/globals.h create mode 100644 imbe_vocoder/imbe.h create mode 100644 imbe_vocoder/imbe_vocoder.cc create mode 100644 imbe_vocoder/imbe_vocoder.h create mode 100644 imbe_vocoder/imbe_vocoder_api.h create mode 100644 imbe_vocoder/imbe_vocoder_impl.cc create mode 100644 imbe_vocoder/imbe_vocoder_impl.h create mode 100644 imbe_vocoder/math_sub.cc create mode 100644 imbe_vocoder/math_sub.h create mode 100644 imbe_vocoder/pe_lpf.cc create mode 100644 imbe_vocoder/pe_lpf.h create mode 100644 imbe_vocoder/pitch_est.cc create mode 100644 imbe_vocoder/pitch_est.h create mode 100644 imbe_vocoder/pitch_ref.cc create mode 100644 imbe_vocoder/pitch_ref.h create mode 100644 imbe_vocoder/qnt_sub.cc create mode 100644 imbe_vocoder/qnt_sub.h create mode 100644 imbe_vocoder/rand_gen.cc create mode 100644 imbe_vocoder/rand_gen.h create mode 100644 imbe_vocoder/sa_decode.cc create mode 100644 imbe_vocoder/sa_decode.h create mode 100644 imbe_vocoder/sa_encode.cc create mode 100644 imbe_vocoder/sa_encode.h create mode 100644 imbe_vocoder/sa_enh.cc create mode 100644 imbe_vocoder/sa_enh.h create mode 100644 imbe_vocoder/tbls.cc create mode 100644 imbe_vocoder/tbls.h create mode 100644 imbe_vocoder/typedef.h create mode 100644 imbe_vocoder/typedefs.h create mode 100644 imbe_vocoder/uv_synt.cc create mode 100644 imbe_vocoder/uv_synt.h create mode 100644 imbe_vocoder/v_synt.cc create mode 100644 imbe_vocoder/v_synt.h create mode 100644 imbe_vocoder/v_uv_det.cc create mode 100644 imbe_vocoder/v_uv_det.h create mode 100644 mbe/ambe3600x2400.c create mode 100644 mbe/ambe3600x2400_const.h create mode 100644 mbe/ambe3600x2450.c create mode 100644 mbe/ambe3600x2450_const.h create mode 100644 mbe/ecc.c create mode 100644 mbe/ecc_const.h create mode 100644 mbe/mbelib.c create mode 100644 mbe/mbelib.h create mode 100644 mbe/mbelib_const.h create mode 100644 mbe/mbelib_parms.h create mode 100644 mbe/vocoder_plugin.cpp create mode 100644 mbe/vocoder_plugin.h create mode 100644 mbe/vocoder_plugin_api.h create mode 100644 mbe/vocoder_tables.h diff --git a/DroidStar.pro b/DroidStar.pro index f6df2de..67f3791 100644 --- a/DroidStar.pro +++ b/DroidStar.pro @@ -7,22 +7,17 @@ equals(QT_MAJOR_VERSION, 5){ unix:!ios:QT += serialport CONFIG += c++17 LFLAGS += -android:INCLUDEPATH += $$(HOME)/Android/local/include -LIBS += -limbe_vocoder # -lvocoder !win32:LIBS += -ldl win32:QT += serialport -win32:INCLUDEPATH += /mnt/data/src/winlibs/include -win32:LIBS += -L/mnt/data/src/winlibs/lib64 -#win32:LIBS += -L/mnt/data/src/winlibs/lib -lws2_32 +#win32:LIBS += -lws2_32 win32:QMAKE_LFLAGS += -static QMAKE_LFLAGS_WINDOWS += --enable-stdcall-fixup RC_ICONS = images/droidstar.ico ICON = images/droidstar.icns -macx::INCLUDEPATH += /usr/local/include -macx:LIBS += -L/usr/local/lib -framework AVFoundation +macx:LIBS += -framework AVFoundation macx:QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14 macx:QMAKE_INFO_PLIST = Info.plist.mac -ios:LIBS += -lvocoder -framework AVFoundation +ios:LIBS += -framework AVFoundation ios:QMAKE_IOS_DEPLOYMENT_TARGET=14.0 ios:QMAKE_TARGET_BUNDLE_PREFIX = org.dudetronics ios:QMAKE_BUNDLE = droidstar @@ -37,7 +32,7 @@ DEFINES += VERSION_NUMBER=\"\\\"$${VERSION_BUILD}\\\"\" DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DEBUG_PLUGINS=1 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 -DEFINES += VOCODER_PLUGIN +#DEFINES += VOCODER_PLUGIN #DEFINES += USE_FLITE #DEFINES += USE_EXTERNAL_CODEC2 @@ -62,6 +57,34 @@ HEADERS += \ httpmanager.h \ iax.h \ iaxdefines.h \ + imbe_vocoder/aux_sub.h \ + imbe_vocoder/basic_op.h \ + imbe_vocoder/ch_decode.h \ + imbe_vocoder/ch_encode.h \ + imbe_vocoder/dc_rmv.h \ + imbe_vocoder/decode.h \ + imbe_vocoder/dsp_sub.h \ + imbe_vocoder/encode.h \ + imbe_vocoder/globals.h \ + imbe_vocoder/imbe.h \ + imbe_vocoder/imbe_vocoder.h \ + imbe_vocoder/imbe_vocoder_api.h \ + imbe_vocoder/imbe_vocoder_impl.h \ + imbe_vocoder/math_sub.h \ + imbe_vocoder/pe_lpf.h \ + imbe_vocoder/pitch_est.h \ + imbe_vocoder/pitch_ref.h \ + imbe_vocoder/qnt_sub.h \ + imbe_vocoder/rand_gen.h \ + imbe_vocoder/sa_decode.h \ + imbe_vocoder/sa_encode.h \ + imbe_vocoder/sa_enh.h \ + imbe_vocoder/tbls.h \ + imbe_vocoder/typedef.h \ + imbe_vocoder/typedefs.h \ + imbe_vocoder/uv_synt.h \ + imbe_vocoder/v_synt.h \ + imbe_vocoder/v_uv_det.h \ m17.h \ mode.h \ nxdn.h \ @@ -91,6 +114,29 @@ SOURCES += \ droidstar.cpp \ httpmanager.cpp \ iax.cpp \ + imbe_vocoder/aux_sub.cc \ + imbe_vocoder/basicop2.cc \ + imbe_vocoder/ch_decode.cc \ + imbe_vocoder/ch_encode.cc \ + imbe_vocoder/dc_rmv.cc \ + imbe_vocoder/decode.cc \ + imbe_vocoder/dsp_sub.cc \ + imbe_vocoder/encode.cc \ + imbe_vocoder/imbe_vocoder.cc \ + imbe_vocoder/imbe_vocoder_impl.cc \ + imbe_vocoder/math_sub.cc \ + imbe_vocoder/pe_lpf.cc \ + imbe_vocoder/pitch_est.cc \ + imbe_vocoder/pitch_ref.cc \ + imbe_vocoder/qnt_sub.cc \ + imbe_vocoder/rand_gen.cc \ + imbe_vocoder/sa_decode.cc \ + imbe_vocoder/sa_encode.cc \ + imbe_vocoder/sa_enh.cc \ + imbe_vocoder/tbls.cc \ + imbe_vocoder/uv_synt.cc \ + imbe_vocoder/v_synt.cc \ + imbe_vocoder/v_uv_det.cc \ m17.cpp \ main.cpp \ mode.cpp \ @@ -124,6 +170,24 @@ SOURCES += \ contains(DEFINES, USE_EXTERNAL_CODEC2){ LIBS += -lcodec2 } +!contains(DEFINES, VOCODER_PLUGIN){ +HEADERS += \ + mbe/ambe3600x2400_const.h \ + mbe/ambe3600x2450_const.h \ + mbe/ecc_const.h \ + mbe/mbelib.h \ + mbe/mbelib_const.h \ + mbe/mbelib_parms.h \ + mbe/vocoder_plugin.h \ + mbe/vocoder_plugin_api.h \ + mbe/vocoder_tables.h +SOURCES += \ + mbe/ambe3600x2400.c \ + mbe/ambe3600x2450.c \ + mbe/ecc.c \ + mbe/mbelib.c \ + mbe/vocoder_plugin.cpp +} macx:OBJECTIVE_SOURCES += micpermission.mm ios:OBJECTIVE_SOURCES += micpermission.mm diff --git a/README.md b/README.md index 72a7baa..6d7f0c2 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,13 @@ Port: UDP port of node, usually 4569. Add DTMF commands like \*3node, \*1node, \*70, etc in the IAX DTMF box and hit send to send the DTMF string. Details on various commands can be found at the AllStar wiki and others. # General building instructions -This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15 or Qt6 >= Qt6.3, and natually the devel packages to build. The imbe_vocoder library is also required. Java, QML (Javascript based), and C# code is also used where necessary. The preferred way to obtain Qt 5.15 is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt. +This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15 or Qt6 >= Qt6.3, and natually the devel packages to build. Java, QML (Javascript based), and C# code is also used where necessary. The preferred way to obtain Qt is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt. -The imbe_vocoder library is a prerequisite: https://github.com/nostar/imbe_vocoder +In an effort to encourage others to build from source on multiple platforms, there are no longer any external build dependencies. In order to build DroidStar with no internal AMBE vocider, uncomment the the following line in the DroidStar.pro file: +``` +DEFINES+=VOCODER_PLUGIN +``` +Building DroidStar with this line commented out will build with internal AMBE support. If you choose to do this, it is your responsibility to determine if you will violate any patents in your area. ## Note for building on Raspbian/RaspiOS The Qt online installer does not support RPi, but fortunately there is a great Qt 5.15.2 installer for RaspiOS: diff --git a/imbe_vocoder/aux_sub.cc b/imbe_vocoder/aux_sub.cc new file mode 100644 index 0000000..b5bfec9 --- /dev/null +++ b/imbe_vocoder/aux_sub.cc @@ -0,0 +1,184 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "imbe.h" +#include "aux_sub.h" +#include "tbls.h" + +//----------------------------------------------------------------------------- +// 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) +{ + UWord16 offset_in_word; + Word16 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; + UWord16 tmp; + Word16 i; + + 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); +} + diff --git a/imbe_vocoder/aux_sub.h b/imbe_vocoder/aux_sub.h new file mode 100644 index 0000000..ada0cd2 --- /dev/null +++ b/imbe_vocoder/aux_sub.h @@ -0,0 +1,133 @@ +/* + * 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 +#define _AUX_SUB + + +//----------------------------------------------------------------------------- +// 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 diff --git a/imbe_vocoder/basic_op.h b/imbe_vocoder/basic_op.h new file mode 100644 index 0000000..9132ba1 --- /dev/null +++ b/imbe_vocoder/basic_op.h @@ -0,0 +1,85 @@ +/* + * 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. + */ +/*___________________________________________________________________________ + | | + | Constants and Globals | + | | + | $Id $ + |___________________________________________________________________________| +*/ +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 + +/*___________________________________________________________________________ + | | + | Prototypes for basic arithmetic operators | + |___________________________________________________________________________| +*/ + +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 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 */ + + diff --git a/imbe_vocoder/basicop2.cc b/imbe_vocoder/basicop2.cc new file mode 100644 index 0000000..25a795e --- /dev/null +++ b/imbe_vocoder/basicop2.cc @@ -0,0 +1,2157 @@ +/* + * 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. + */ +/*___________________________________________________________________________ + | | + | Basic arithmetic operators. | + | | + | $Id $ + |___________________________________________________________________________| +*/ + +/*___________________________________________________________________________ + | | + | Include-Files | + |___________________________________________________________________________| +*/ + +#include +#include +#include "typedef.h" +#include "basic_op.h" + +#if (WMOPS) +#include "count.h" +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; + +#endif + +/*___________________________________________________________________________ + | | + | Local Functions | + |___________________________________________________________________________| +*/ +Word16 saturate (Word32 L_var1); + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +Flag Overflow = 0; +Flag Carry = 0; + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +/*___________________________________________________________________________ + | | + | Function Name : saturate | + | | + | Purpose : | + | | + | Limit the 32 bit input to the range of a 16 bit word. | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 +saturate (Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 > 0X00007fffL) + { + Overflow = 1; + var_out = MAX_16; + } + else if (L_var1 < (Word32) 0xffff8000L) + { + Overflow = 1; + var_out = MIN_16; + } + else + { + var_out = extract_l (L_var1); +#if (WMOPS) + multiCounter[currCounter].extract_l--; +#endif + } + + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : add | + | | + | Purpose : | + | | + | Performs the addition (var1+var2) with overflow control and saturation;| + | the 16 bit result is set at +32767 when overflow occurs or at -32768 | + | when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 add (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate (L_sum); +#if (WMOPS) + multiCounter[currCounter].add++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : sub | + | | + | Purpose : | + | | + | Performs the subtraction (var1+var2) with overflow control and satu- | + | ration; the 16 bit result is set at +32767 when overflow occurs or at | + | -32768 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 sub (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate (L_diff); +#if (WMOPS) + multiCounter[currCounter].sub++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : abs_s | + | | + | Purpose : | + | | + | Absolute value of var1; abs_s(-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 abs_s (Word16 var1) +{ + Word16 var_out; + + if (var1 == (Word16) 0X8000) + { + var_out = MAX_16; + } + else + { + if (var1 < 0) + { + var_out = -var1; + } + else + { + var_out = var1; + } + } +#if (WMOPS) + multiCounter[currCounter].abs_s++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : shl | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| + | the var2 LSB of the result. If var2 is negative, arithmetically shift | + | var1 right by -var2 with sign extension. Saturate the result in case of | + | underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 shl (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 result; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shr (var1, -var2); +#if (WMOPS) + multiCounter[currCounter].shr--; +#endif + } + else + { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) + { + Overflow = 1; + var_out = (var1 > 0) ? MAX_16 : MIN_16; + } + else + { + var_out = extract_l (result); +#if (WMOPS) + multiCounter[currCounter].extract_l--; +#endif + } + } +#if (WMOPS) + multiCounter[currCounter].shl++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : shr | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift var1 left by | + | -var2 with sign extension. Saturate the result in case of underflows or | + | overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 shr (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 < 0) + { + if (var2 < -16) + var2 = -16; + var_out = shl (var1, -var2); +#if (WMOPS) + multiCounter[currCounter].shl--; +#endif + } + else + { + if (var2 >= 15) + { + var_out = (var1 < 0) ? -1 : 0; + } + else + { + if (var1 < 0) + { + var_out = ~((~var1) >> var2); + } + else + { + var_out = var1 >> var2; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].shr++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : mult | + | | + | Purpose : | + | | + | Performs the multiplication of var1 by var2 and gives a 16 bit result | + | which is scaled i.e.: | + | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | + | mult(-32768,-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 mult (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + + var_out = saturate (L_product); +#if (WMOPS) + multiCounter[currCounter].mult++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_mult | + | | + | Purpose : | + | | + | L_mult is the 32 bit result of the multiplication of var1 times var2 | + | with one shift left i.e.: | + | L_mult(var1,var2) = L_shl((var1 times var2),1) and | + | L_mult(-32768,-32768) = 2147483647. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_mult (Word16 var1, Word16 var2) +{ + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) + { + L_var_out *= 2; + } + else + { + Overflow = 1; + L_var_out = MAX_32; + } + +#if (WMOPS) + multiCounter[currCounter].L_mult++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : negate | + | | + | Purpose : | + | | + | Negate var1 with saturation, saturate in the case where input is -32768:| + | negate(var1) = sub(0,var1). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 negate (Word16 var1) +{ + Word16 var_out; + + var_out = (var1 == MIN_16) ? MAX_16 : -var1; +#if (WMOPS) + multiCounter[currCounter].negate++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : extract_h | + | | + | Purpose : | + | | + | Return the 16 MSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 extract_h (Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) (L_var1 >> 16); +#if (WMOPS) + multiCounter[currCounter].extract_h++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : extract_l | + | | + | Purpose : | + | | + | Return the 16 LSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 extract_l (Word32 L_var1) +{ + Word16 var_out; + + var_out = (Word16) L_var1; +#if (WMOPS) + multiCounter[currCounter].extract_l++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : round | + | | + | Purpose : | + | | + | Round the lower 16 bits of the 32 bit input number into the MS 16 bits | + | with saturation. Shift the resulting bits right by 16 and return the 16 | + | bit number: | + | round(L_var1) = extract_h(L_add(L_var1,32768)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 round (Word32 L_var1) +{ + Word16 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); +#if (WMOPS) + multiCounter[currCounter].L_add--; +#endif + var_out = extract_h (L_rounded); +#if (WMOPS) + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_mac | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation, return a 32 bit result: | + | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult (var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_mult--; +#endif + L_var_out = L_add (L_var3, L_product); +#if (WMOPS) + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_mac++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_msu | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation, return a 32 bit result: | + | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult (var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_mult--; +#endif + L_var_out = L_sub (L_var3, L_product); +#if (WMOPS) + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_msu++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_macNs | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 without saturation, return a 32 bit result. Generate | + | carry and overflow values : | + | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ + +Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + + L_var_out = L_mult (var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_mult--; +#endif + L_var_out = L_add_c (L_var3, L_var_out); +#if (WMOPS) + multiCounter[currCounter].L_add_c--; + multiCounter[currCounter].L_macNs++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_msuNs | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result from L_var3 without saturation, return a 32 bit result. Ge- | + | nerate carry and overflow values : | + | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ + +Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word32 L_var_out; + + L_var_out = L_mult (var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_mult--; +#endif + L_var_out = L_sub_c (L_var3, L_var_out); +#if (WMOPS) + multiCounter[currCounter].L_sub_c--; + multiCounter[currCounter].L_msuNs++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_add | + | | + | Purpose : | + | | + | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_add (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) == 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + Overflow = 1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_add++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_sub | + | | + | Purpose : | + | | + | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_sub (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) + { + if ((L_var_out ^ L_var1) & MIN_32) + { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + Overflow = 1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_sub++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_add_c | + | | + | Purpose : | + | | + | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)| + | with carry. No saturation. Generate carry and Overflow values. The car- | + | ry and overflow values are binary variables which can be tested and as- | + | signed values. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +Word32 L_add_c (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + + L_var_out = L_var1 + L_var2 + Carry; + + L_test = L_var1 + L_var2; + + if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0)) + { + Overflow = 1; + carry_int = 0; + } + else + { + if ((L_var1 < 0) && (L_var2 < 0)) + { + if (L_test >= 0) + { + Overflow = 1; + carry_int = 1; + } + else + { + Overflow = 0; + carry_int = 1; + } + } + else + { + if (((L_var1 ^ L_var2) < 0) && (L_test >= 0)) + { + Overflow = 0; + carry_int = 1; + } + else + { + Overflow = 0; + carry_int = 0; + } + } + } + + if (Carry) + { + if (L_test == MAX_32) + { + Overflow = 1; + Carry = carry_int; + } + else + { + if (L_test == (Word32) 0xFFFFFFFFL) + { + Carry = 1; + } + else + { + Carry = carry_int; + } + } + } + else + { + Carry = carry_int; + } + +#if (WMOPS) + multiCounter[currCounter].L_add_c++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_sub_c | + | | + | Purpose : | + | | + | Performs 32 bits subtraction of the two 32 bits variables with carry | + | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow | + | values. The carry and overflow values are binary variables which can | + | be tested and assigned values. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ + +Word32 L_sub_c (Word32 L_var1, Word32 L_var2) +{ + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + + if (Carry) + { + Carry = 0; + if (L_var2 != MIN_32) + { + L_var_out = L_add_c (L_var1, -L_var2); +#if (WMOPS) + multiCounter[currCounter].L_add_c--; +#endif + } + else + { + L_var_out = L_var1 - L_var2; + if (L_var1 > 0L) + { + Overflow = 1; + Carry = 0; + } + } + } + else + { + L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L; + L_test = L_var1 - L_var2; + + if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0)) + { + Overflow = 1; + carry_int = 0; + } + else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0)) + { + Overflow = 1; + carry_int = 1; + } + else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0)) + { + Overflow = 0; + carry_int = 1; + } + if (L_test == MIN_32) + { + Overflow = 1; + Carry = carry_int; + } + else + { + Carry = carry_int; + } + } + +#if (WMOPS) + multiCounter[currCounter].L_sub_c++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_negate | + | | + | Purpose : | + | | + | Negate the 32 bit variable L_var1 with saturation; saturate in the case | + | where input is -2147483648 (0x8000 0000). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_negate (Word32 L_var1) +{ + Word32 L_var_out; + + L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1; +#if (WMOPS) + multiCounter[currCounter].L_negate++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : mult_r | + | | + | Purpose : | + | | + | Same as mult with rounding, i.e.: | + | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | + | mult_r(-32768,-32768) = 32767. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 mult_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32) var1 *(Word32) var2; /* product */ + L_product_arr += (Word32) 0x00004000L; /* round */ + L_product_arr &= (Word32) 0xffff8000L; + L_product_arr >>= 15; /* shift */ + + if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */ + { + L_product_arr |= (Word32) 0xffff0000L; + } + var_out = saturate (L_product_arr); +#if (WMOPS) + multiCounter[currCounter].mult_r++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_shl | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | + | fill the var2 LSB of the result. If var2 is negative, arithmetically | + | shift L_var1 right by -var2 with sign extension. Saturate the result in | + | case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_shl (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out=0; + + if (var2 <= 0) + { + if (var2 < -32) + var2 = -32; + L_var_out = L_shr (L_var1, -var2); +#if (WMOPS) + multiCounter[currCounter].L_shr--; +#endif + } + else + { + for (; var2 > 0; var2--) + { + if (L_var1 > (Word32) 0X3fffffffL) + { + Overflow = 1; + L_var_out = MAX_32; + break; + } + else + { + if (L_var1 < (Word32) 0xc0000000L) + { + Overflow = 1; + L_var_out = MIN_32; + break; + } + } + L_var1 *= 2; + L_var_out = L_var1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_shl++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_shr | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift L_var1 left | + | by -var2 and zero fill the -var2 LSB of the result. Saturate the result | + | in case of underflows or overflows. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_shr (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 < 0) + { + if (var2 < -32) + var2 = -32; + L_var_out = L_shl (L_var1, -var2); +#if (WMOPS) + multiCounter[currCounter].L_shl--; +#endif + } + else + { + if (var2 >= 31) + { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } + else + { + if (L_var1 < 0) + { + L_var_out = ~((~L_var1) >> var2); + } + else + { + L_var_out = L_var1 >> var2; + } + } + } +#if (WMOPS) + multiCounter[currCounter].L_shr++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : shr_r | + | | + | Purpose : | + | | + | Same as shr(var1,var2) but with rounding. Saturate the result in case of| + | underflows or overflows : | + | - If var2 is greater than zero : | + | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) | + | is equal to zero | + | then | + | shr_r(var1,var2) = shr(var1,var2) | + | else | + | shr_r(var1,var2) = add(shr(var1,var2),1) | + | - If var2 is less than or equal to zero : | + | shr_r(var1,var2) = shr(var1,var2). | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 shr_r (Word16 var1, Word16 var2) +{ + Word16 var_out; + + if (var2 > 15) + { + var_out = 0; + } + else + { + var_out = shr (var1, var2); +#if (WMOPS) + multiCounter[currCounter].shr--; +#endif + + if (var2 > 0) + { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) + { + var_out++; + } + } + } +#if (WMOPS) + multiCounter[currCounter].shr_r++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : mac_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation. Round the LS 16 bits of the result | + | into the MS 16 bits with saturation and shift the result right by 16. | + | Return a 16 bit result. | + | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_mac (L_var3, var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_mac--; +#endif + L_var3 = L_add (L_var3, (Word32) 0x00008000L); +#if (WMOPS) + multiCounter[currCounter].L_add--; +#endif + var_out = extract_h (L_var3); +#if (WMOPS) + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].mac_r++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : msu_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result to L_var3 with saturation. Round the LS 16 bits of the res- | + | ult into the MS 16 bits with saturation and shift the result right by | + | 16. Return a 16 bit result. | + | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2) +{ + Word16 var_out; + + L_var3 = L_msu (L_var3, var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_msu--; +#endif + L_var3 = L_add (L_var3, (Word32) 0x00008000L); +#if (WMOPS) + multiCounter[currCounter].L_add--; +#endif + var_out = extract_h (L_var3); +#if (WMOPS) + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].msu_r++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_h | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The | + | 16 LS bits of the output are zeroed. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff 0000. | + |___________________________________________________________________________| +*/ + +Word32 L_deposit_h (Word16 var1) +{ + Word32 L_var_out; + + L_var_out = (Word32) var1 << 16; +#if (WMOPS) + multiCounter[currCounter].L_deposit_h++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_l | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | + | 16 MS bits of the output are sign extended. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ + +Word32 L_deposit_l (Word16 var1) +{ + Word32 L_var_out; + + L_var_out = (Word32) var1; +#if (WMOPS) + multiCounter[currCounter].L_deposit_l++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_shr_r | + | | + | Purpose : | + | | + | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in | + | case of underflows or overflows : | + | - If var2 is greater than zero : | + | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))| + | is equal to zero | + | then | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) | + | else | + | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) | + | - If var2 is less than or equal to zero : | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_shr_r (Word32 L_var1, Word16 var2) +{ + Word32 L_var_out; + + if (var2 > 31) + { + L_var_out = 0; + } + else + { + L_var_out = L_shr (L_var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_shr--; +#endif + if (var2 > 0) + { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) + { + L_var_out++; + } + } + } +#if (WMOPS) + multiCounter[currCounter].L_shr_r++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_abs | + | | + | Purpose : | + | | + | Absolute value of L_var1; Saturate in case where the input is | + | -214783648 | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_abs (Word32 L_var1) +{ + Word32 L_var_out; + + if (L_var1 == MIN_32) + { + L_var_out = MAX_32; + } + else + { + if (L_var1 < 0) + { + L_var_out = -L_var1; + } + else + { + L_var_out = L_var1; + } + } + +#if (WMOPS) + multiCounter[currCounter].L_abs++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : L_sat | + | | + | Purpose : | + | | + | 32 bit L_var1 is set to 2147483647 if an overflow occured or to | + | -2147483648 if an underflow occured on the most recent L_add_c, | + | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values | + | are binary values which can be tested and assigned values. | + | | + | Complexity weight : 4 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ + +Word32 L_sat (Word32 L_var1) +{ + Word32 L_var_out; + + L_var_out = L_var1; + + if (Overflow) + { + + if (Carry) + { + L_var_out = MIN_32; + } + else + { + L_var_out = MAX_32; + } + + Carry = 0; + Overflow = 0; + } +#if (WMOPS) + multiCounter[currCounter].L_sat++; +#endif + return (L_var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : norm_s | + | | + | Purpose : | + | | + | Produces the number of left shift needed to normalize the 16 bit varia- | + | ble var1 for positive values on the interval with minimum of 16384 and | + | maximum of 32767, and for negative values on the interval with minimum | + | of -32768 and maximum of -16384; in order to normalize the result, the | + | following operation must be done : | + | norm_var1 = shl(var1,norm_s(var1)). | + | | + | Complexity weight : 15 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 000f. | + |___________________________________________________________________________| +*/ + +Word16 norm_s (Word16 var1) +{ + Word16 var_out; + + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == (Word16) 0xffff) + { + var_out = 15; + } + else + { + if (var1 < 0) + { + var1 = ~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) + { + var1 <<= 1; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].norm_s++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : div_s | + | | + | Purpose : | + | | + | Produces a result which is the fractional integer division of var1 by | + | var2; var1 and var2 must be positive and var2 must be greater or equal | + | to var1; the result is positive (leading bit equal to 0) and truncated | + | to 16 bits. | + | If var1 = var2 then div(var1,var2) = 32767. | + | | + | Complexity weight : 18 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + | It's a Q15 value (point between b15 and b14). | + |___________________________________________________________________________| +*/ + +Word16 div_s (Word16 var1, Word16 var2) +{ + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + + if ((var1 > var2) || (var1 < 0) || (var2 < 0)) + { + printf ("Division Error var1=%d var2=%d\n", var1, var2); + abort(); /* exit (0); */ + } + if (var2 == 0) + { + printf ("Division by 0, Fatal error \n"); + abort(); /* exit (0); */ + } + if (var1 == 0) + { + var_out = 0; + } + else + { + if (var1 == var2) + { + var_out = MAX_16; + } + else + { + L_num = L_deposit_l (var1); +#if (WMOPS) + multiCounter[currCounter].L_deposit_l--; +#endif + L_denom = L_deposit_l (var2); +#if (WMOPS) + multiCounter[currCounter].L_deposit_l--; +#endif + + for (iteration = 0; iteration < 15; iteration++) + { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) + { + L_num = L_sub (L_num, L_denom); +#if (WMOPS) + multiCounter[currCounter].L_sub--; +#endif + var_out = add (var_out, 1); +#if (WMOPS) + multiCounter[currCounter].add--; +#endif + } + } + } + } + +#if (WMOPS) + multiCounter[currCounter].div_s++; +#endif + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : norm_l | + | | + | Purpose : | + | | + | Produces the number of left shifts needed to normalize the 32 bit varia-| + | ble L_var1 for positive values on the interval with minimum of | + | 1073741824 and maximum of 2147483647, and for negative values on the in-| + | terval with minimum of -2147483648 and maximum of -1073741824; in order | + | to normalize the result, the following operation must be done : | + | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | + | | + | Complexity weight : 30 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 001f. | + |___________________________________________________________________________| +*/ + +Word16 norm_l (Word32 L_var1) +{ + Word16 var_out; + + if (L_var1 == 0) + { + var_out = 0; + } + else + { + if (L_var1 == (Word32) 0xffffffffL) + { + var_out = 31; + } + else + { + if (L_var1 < 0) + { + L_var1 = ~L_var1; + } + for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) + { + L_var1 <<= 1; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].norm_l++; +#endif + return (var_out); +} + diff --git a/imbe_vocoder/ch_decode.cc b/imbe_vocoder/ch_decode.cc new file mode 100644 index 0000000..da0b6cc --- /dev/null +++ b/imbe_vocoder/ch_decode.cc @@ -0,0 +1,185 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "ch_decode.h" +#include "aux_sub.h" + + +void decode_frame_vector(IMBE_PARAM *imbe_param, Word16 *frame_vector) +{ + Word16 bit_stream[BIT_STREAM_LEN]; + Word16 i, vec_num, tmp, tmp1, tmp2, bit_thr, shift; + Word16 *b_ptr, *ba_ptr, index0; + Word32 L_tmp; + + imbe_param->b_vec[0] = (shr(frame_vector[0], 4) & 0xFC) | (shr(frame_vector[7], 1) & 0x3); + + if (imbe_param->b_vec[0] < 0 || imbe_param->b_vec[0] > 207) + return; // If we return here IMBE parameters from previous frame will be used (frame repeating) + + tmp = ((imbe_param->b_vec[0] & 0xFF) << 1) + 0x4F; // Convert b_vec[0] to unsigned Q15.1 format and add 39.5 + + //imbe_param->ff = 4./((double)imbe_param->b_vec[0] + 39.5); + + // Calculate fundamental frequency with higher precession + shift = norm_s(tmp); + tmp1 = tmp << shift; + + tmp2 = div_s(0x4000, tmp1); + imbe_param->fund_freq = L_shr(L_deposit_h(tmp2), 11 - shift); + + L_tmp = L_sub(0x40000000, L_mult(tmp1, tmp2)); + tmp2 = div_s(extract_l(L_shr(L_tmp, 2)), tmp1); + L_tmp = L_shr(L_deposit_l(tmp2), 11 - shift - 2); + imbe_param->fund_freq = L_add(imbe_param->fund_freq, L_tmp); + + //printf("%X %X \n", imbe_param->fund_freq, (Word32)(imbe_param->ff * (double)((UWord32)1<<31))); + + tmp = (tmp + 0x2) >> 3; // Calculate (b0 + 39.5 + 1)/4 + imbe_param->num_harms = ((UWord32)CNST_0_9254_Q0_16 * tmp) >> 16; + + if(imbe_param->num_harms <= 36) + imbe_param->num_bands = extract_h((UWord32)(imbe_param->num_harms + 2) * CNST_0_33_Q0_16); // fix((L+2)/3) + else + imbe_param->num_bands = NUM_BANDS_MAX; + + // Convert input vector (from b_3 to b_L+1) to bit stream + bit_stream[0] = (frame_vector[0] & 0x4)?1:0; + bit_stream[1] = (frame_vector[0] & 0x2)?1:0; + bit_stream[2] = (frame_vector[0] & 0x1)?1:0; + + bit_stream[BIT_STREAM_LEN - 3] = (frame_vector[7] & 0x40)?1:0; + bit_stream[BIT_STREAM_LEN - 2] = (frame_vector[7] & 0x20)?1:0; + bit_stream[BIT_STREAM_LEN - 1] = (frame_vector[7] & 0x10)?1:0; + + + index0 = 3 + 3 * 12 - 1; + for(vec_num = 3; vec_num >= 1; vec_num--) + { + tmp = frame_vector[vec_num]; + for(i = 0; i < 12; i++) + { + bit_stream[index0] = (tmp & 0x1)?1:0; + tmp >>= 1; + index0--; + } + } + + index0 = 3 + 3 * 12 + 3 * 11 - 1; + for(vec_num = 6; vec_num >= 4; vec_num--) + { + tmp = frame_vector[vec_num]; + for(i = 0; i < 11; i++) + { + bit_stream[index0] = (tmp & 0x1)?1:0; + tmp >>= 1; + index0--; + } + } + + // Rebuild b1 + index0 = 3 + 3 * 12; + tmp = 0; + for(i = 0; i < imbe_param->num_bands; i++) + tmp = (tmp << 1) | bit_stream[index0++]; + + imbe_param->b_vec[1] = tmp; + + // Rebuild b2 + tmp = 0; + tmp |= bit_stream[index0++] << 1; + tmp |= bit_stream[index0++]; + imbe_param->b_vec[2] = (frame_vector[0] & 0x38) | (tmp << 1) | (shr(frame_vector[7], 3) & 0x01); + + // Shift the rest of sequence + tmp = imbe_param->num_bands + 2; // shift + for(; index0 < BIT_STREAM_LEN; index0++) + bit_stream[index0 - tmp] = bit_stream[index0]; + + // Priority ReScanning + b_ptr = &imbe_param->b_vec[3]; + ba_ptr = imbe_param->bit_alloc; + for(i = 0; i < B_NUM; i++) + ba_ptr[i] = b_ptr[i] = 0; + + + // Unpack bit allocation table's item + get_bit_allocation(imbe_param->num_harms, imbe_param->bit_alloc); + + index0 = 0; + bit_thr = (imbe_param->num_harms == 0xb)?9:ba_ptr[0]; + + while(index0 < BIT_STREAM_LEN - imbe_param->num_bands - 2) + { + for(i = 0; i < imbe_param->num_harms - 1; i++) + if(bit_thr && bit_thr <= ba_ptr[i]) + b_ptr[i] = (b_ptr[i] << 1) | bit_stream[index0++]; + bit_thr--; + } + + // Synchronization Bit Decoding + imbe_param->b_vec[imbe_param->num_harms + 2] = frame_vector[7] & 1; +} + + +void v_uv_decode(IMBE_PARAM *imbe_param) +{ + Word16 num_harms; + Word16 num_bands; + Word16 vu_vec, *p_v_uv_dsn, mask, i, uv_cnt; + + num_harms = imbe_param->num_harms; + num_bands = imbe_param->num_bands; + vu_vec = imbe_param->b_vec[1]; + + p_v_uv_dsn = imbe_param->v_uv_dsn; + + mask = 1 << (num_bands - 1); + + v_zap(p_v_uv_dsn, NUM_HARMS_MAX); + + i = 0; uv_cnt = 0; + while(num_harms--) + { + if(vu_vec & mask) + *p_v_uv_dsn++ = 1; + else + { + *p_v_uv_dsn++ = 0; + uv_cnt++; + } + + if(++i == 3) + { + if(num_bands > 1) + { + num_bands--; + mask >>= 1; + } + i = 0; + } + } + imbe_param->l_uv = uv_cnt; +} diff --git a/imbe_vocoder/ch_decode.h b/imbe_vocoder/ch_decode.h new file mode 100644 index 0000000..027ab11 --- /dev/null +++ b/imbe_vocoder/ch_decode.h @@ -0,0 +1,32 @@ +/* + * 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 _CH_DECODE +#define _CH_DECODE + +#include "typedef.h" + +#define BIT_STREAM_LEN (3 + 3*12 + 3*11 + 3) + +void decode_frame_vector(IMBE_PARAM *imbe_param, Word16 *frame_vector); +void v_uv_decode(IMBE_PARAM *imbe_param); + +#endif diff --git a/imbe_vocoder/ch_encode.cc b/imbe_vocoder/ch_encode.cc new file mode 100644 index 0000000..6d12083 --- /dev/null +++ b/imbe_vocoder/ch_encode.cc @@ -0,0 +1,110 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "ch_encode.h" +#include "aux_sub.h" + + +void encode_frame_vector(IMBE_PARAM *imbe_param, Word16 *frame_vector) +{ + Word16 bit_stream[EN_BIT_STREAM_LEN], index0, bit_thr, bit_mask, i; + Word16 vec_num, num_harms, num_bands, tmp; + Word16 *ba_ptr, *b_ptr; + + num_harms = imbe_param->num_harms; + num_bands = imbe_param->num_bands; + + v_zap(frame_vector, 8); + + // Unpack bit allocation table's item + get_bit_allocation(num_harms, imbe_param->bit_alloc); + + // Priority Scanning + index0 = 0; + ba_ptr = imbe_param->bit_alloc; + bit_thr = (num_harms == 0xb)?9:ba_ptr[0]; + bit_mask = shl(1, bit_thr - 1); + + while(index0 < EN_BIT_STREAM_LEN - (num_bands - 3)) + { + b_ptr = &imbe_param->b_vec[3]; + for(i = 0; i < num_harms - 1; i++) + if(bit_thr && bit_thr <= ba_ptr[i]) + bit_stream[index0++] = (b_ptr[i] & bit_mask)?1:0; + + bit_thr--; + bit_mask = shr(bit_mask, 1); + } + + frame_vector[0] = shl(imbe_param->b_vec[0] & 0xFC, 4) | (imbe_param->b_vec[2] & 0x38); + + index0 = 0; + frame_vector[0] |= (bit_stream[index0++])?4:0; + frame_vector[0] |= (bit_stream[index0++])?2:0; + frame_vector[0] |= (bit_stream[index0++])?1:0; + + for(vec_num = 1; vec_num <= 3; vec_num++) + { + tmp = 0; + for(i = 0; i < 12; i++) + { + tmp <<= 1; + tmp |= bit_stream[index0++]; + } + frame_vector[vec_num] = tmp; + } + + index0 -= num_bands + 2; + + bit_mask = shl(1, num_bands - 1); + for(i = 0; i < num_bands; i++) + { + bit_stream[index0++] = (imbe_param->b_vec[1] & bit_mask)?1:0; + bit_mask >>= 1; + } + + bit_stream[index0++] = (imbe_param->b_vec[2] & 0x04)?1:0; + bit_stream[index0++] = (imbe_param->b_vec[2] & 0x02)?1:0; + + index0 -= num_bands + 2; + + for(vec_num = 4; vec_num <= 6; vec_num++) + { + tmp = 0; + for(i = 0; i < 11; i++) + { + tmp <<= 1; + tmp |= bit_stream[index0++]; + } + frame_vector[vec_num] = tmp; + } + + frame_vector[7] = shl(imbe_param->b_vec[0] & 0x03, 1) | shl(imbe_param->b_vec[2] & 0x01, 3); + frame_vector[7] |= (bit_stream[index0++])?0x40:0; + frame_vector[7] |= (bit_stream[index0++])?0x20:0; + frame_vector[7] |= (bit_stream[index0++])?0x10:0; + frame_vector[7] |= (imbe_param->b_vec[num_harms + 2])?0x01:0; +} diff --git a/imbe_vocoder/ch_encode.h b/imbe_vocoder/ch_encode.h new file mode 100644 index 0000000..0a9b8de --- /dev/null +++ b/imbe_vocoder/ch_encode.h @@ -0,0 +1,32 @@ +/* + * 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 _CH_ENCODE +#define _CH_ENCODE + +#define EN_BIT_STREAM_LEN (3 + 3*12 + 6 + 2*11 + 3) + + +void encode_frame_vector(IMBE_PARAM *imbe_param, Word16 *frame_vector); + + +#endif diff --git a/imbe_vocoder/dc_rmv.cc b/imbe_vocoder/dc_rmv.cc new file mode 100644 index 0000000..946174c --- /dev/null +++ b/imbe_vocoder/dc_rmv.cc @@ -0,0 +1,66 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "aux_sub.h" +#include "basic_op.h" +#include "math_sub.h" +#include "dc_rmv.h" + + +#define CNST_0_99_Q1_15 0x7EB8 + + +//----------------------------------------------------------------------------- +// PURPOSE: +// High-pass filter to remove DC +// +// +// INPUT: +// *sigin - pointer to input signal buffer +// *sigout - pointer to output signal buffer +// *mem - pointer to filter's memory element +// len - number of input signal samples +// +// OUTPUT: +// None +// +// RETURN: +// Saved filter state in mem +// +//----------------------------------------------------------------------------- +void dc_rmv(Word16 *sigin, Word16 *sigout, Word32 *mem, Word16 len) +{ + Word32 L_tmp, L_mem; + + L_mem = *mem; + while(len--) + { + L_tmp = L_deposit_h(*sigin++); + L_mem = L_add(L_mem, L_tmp); + *sigout++ = round(L_mem); + L_mem = L_mpy_ls(L_mem, CNST_0_99_Q1_15); + L_mem = L_sub(L_mem, L_tmp); + } + *mem = L_mem; +} diff --git a/imbe_vocoder/dc_rmv.h b/imbe_vocoder/dc_rmv.h new file mode 100644 index 0000000..d36393b --- /dev/null +++ b/imbe_vocoder/dc_rmv.h @@ -0,0 +1,46 @@ +/* + * 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 _DC_RMV +#define _DC_RMV + +//----------------------------------------------------------------------------- +// PURPOSE: +// High-pass filter to remove DC +// +// +// INPUT: +// *sigin - pointer to input signal buffer +// *sigout - pointer to output signal buffer +// *mem - pointer to filter's memory element +// len - number of input signal samples +// +// OUTPUT: +// None +// +// RETURN: +// Saved filter state in mem +// +//----------------------------------------------------------------------------- +void dc_rmv(Word16 *sigin, Word16 *sigout, Word32 *mem, Word16 len); + +#endif diff --git a/imbe_vocoder/decode.cc b/imbe_vocoder/decode.cc new file mode 100644 index 0000000..5481697 --- /dev/null +++ b/imbe_vocoder/decode.cc @@ -0,0 +1,112 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "ch_decode.h" +#include "sa_decode.h" +#include "sa_enh.h" +#include "v_synt.h" +#include "uv_synt.h" +#include "basic_op.h" +#include "aux_sub.h" +#include "encode.h" +#include "dsp_sub.h" +#include "imbe_vocoder_impl.h" + +#include + +const uint8_t BIT_MASK_TABLE8[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; +#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE8[(i)&7]) + + +void imbe_vocoder_impl::decode_init(IMBE_PARAM *imbe_param) +{ + v_synt_init(); + uv_synt_init(); + sa_decode_init(); + + // Make previous frame for the first frame + memset((char *)imbe_param, 0, sizeof(IMBE_PARAM)); + imbe_param->fund_freq = 0x0cf6474a; + imbe_param->num_harms = 9; + imbe_param->num_bands = 3; + +} + + +void imbe_vocoder_impl::decode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd) +{ + Word16 snd_tmp[FRAME]; + Word16 j; + + decode_frame_vector(imbe_param, frame_vector); + v_uv_decode(imbe_param); + sa_decode(imbe_param); + sa_enh(imbe_param); + v_synt(imbe_param, snd); + uv_synt(imbe_param, snd_tmp); + + for(j = 0; j < FRAME; j++) + snd[j] = add(snd[j], snd_tmp[j]); +} + +void imbe_vocoder_impl::decode_4400(int16_t *snd, uint8_t *imbe) +{ + int16_t frame[8U] = {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; + unsigned int offset = 0U; + + int16_t mask = 0x0800; + for (unsigned int i = 0U; i < 12U; i++, mask >>= 1, offset++) + frame[0U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0800; + for (unsigned int i = 0U; i < 12U; i++, mask >>= 1, offset++) + frame[1U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0800; + for (unsigned int i = 0U; i < 12U; i++, mask >>= 1, offset++) + frame[2U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0800; + for (unsigned int i = 0U; i < 12U; i++, mask >>= 1, offset++) + frame[3U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0400; + for (unsigned int i = 0U; i < 11U; i++, mask >>= 1, offset++) + frame[4U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0400; + for (unsigned int i = 0U; i < 11U; i++, mask >>= 1, offset++) + frame[5U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0400; + for (unsigned int i = 0U; i < 11U; i++, mask >>= 1, offset++) + frame[6U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + mask = 0x0040; + for (unsigned int i = 0U; i < 7U; i++, mask >>= 1, offset++) + frame[7U] |= READ_BIT(imbe, offset) != 0x00U ? mask : 0x0000; + + imbe_decode(frame, snd); +} + diff --git a/imbe_vocoder/decode.h b/imbe_vocoder/decode.h new file mode 100644 index 0000000..962be53 --- /dev/null +++ b/imbe_vocoder/decode.h @@ -0,0 +1,31 @@ +/* + * 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 _DECODE +#define _DECODE +#if 0 +void decode_init(IMBE_PARAM *imbe_param); +void decode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd); +void decode_4400(int16_t *pcm, uint8_t *imbe); +#endif +#endif + diff --git a/imbe_vocoder/dsp_sub.cc b/imbe_vocoder/dsp_sub.cc new file mode 100644 index 0000000..2a02051 --- /dev/null +++ b/imbe_vocoder/dsp_sub.cc @@ -0,0 +1,278 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "imbe.h" +#include "tbls.h" +#include "dsp_sub.h" +#include "math_sub.h" +#include "encode.h" +#include "imbe_vocoder_impl.h" + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform inverse DCT +// +// +// INPUT: +// in - pointer to input data +// m_lim - input data's size +// i_lim - result's size +// out - pointer to save result +// +// OUTPUT: +// None +// +// RETURN: +// Saved in out result of conversion +// +//----------------------------------------------------------------------------- +void imbe_vocoder_impl::idct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out) +{ + UWord16 angl_step, angl_intl, angl_intl_2; + UWord16 angl_acc; + Word32 sum; + Word16 i, m; + + if(m_lim == 1) + { + angl_intl = CNST_0_5_Q1_15; + angl_intl_2 = CNST_1_0_Q1_15; + } + else + { + angl_intl = div_s ((Word16) CNST_0_5_Q5_11, m_lim << 11); // calculate 0.5/m_lim + angl_intl_2 = shl(angl_intl, 1); + } + + angl_step = angl_intl; + for(i = 0; i < i_lim; i++) + { + sum = 0; + angl_acc = angl_step; + for(m = 1; m < m_lim; m++) + { + sum = L_add(sum, L_shr( L_mult(in[m], cos_fxp(angl_acc)), 7)); + angl_acc += angl_step; + } + sum = L_add(sum, L_shr( L_deposit_h(in[0]), 8)); + out[i] = extract_l(L_shr_r (sum, 8)); + angl_step += angl_intl_2; + } +} + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform DCT +// +// +// INPUT: +// in - pointer to input data +// m_lim - input data's size +// i_lim - result's size +// out - pointer to save result +// +// OUTPUT: +// None +// +// RETURN: +// Saved in out result of conversion +// +//----------------------------------------------------------------------------- +void imbe_vocoder_impl::dct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out) +{ + UWord16 angl_step, angl_intl, angl_intl_2, angl_begin; + UWord16 angl_acc; + Word32 sum; + Word16 i, m; + + if(m_lim == 1) + { + angl_intl = CNST_0_5_Q1_15; + angl_intl_2 = CNST_1_0_Q1_15; + } + else + { + angl_intl = div_s ((Word16) CNST_0_5_Q5_11, m_lim << 11); // calculate 0.5/m_lim + angl_intl_2 = shl(angl_intl, 1); + } + + // Calculate first coefficient + sum = 0; + for(m = 0; m < m_lim; m++) + sum = L_add(sum, L_deposit_l(in[m])); + out[0] = extract_l(L_mpy_ls(sum, angl_intl_2)); + + // Calculate the others coefficients + angl_begin = angl_intl; + angl_step = angl_intl_2; + for(i = 1; i < i_lim; i++) + { + sum = 0; + angl_acc = angl_begin; + for(m = 0; m < m_lim; m++) + { + sum = L_add(sum, L_deposit_l(mult(in[m], cos_fxp(angl_acc)))); + angl_acc += angl_step; + } + out[i] = extract_l(L_mpy_ls(sum, angl_intl_2)); + + angl_step += angl_intl_2; + angl_begin += angl_intl; + } +} + + + + +void imbe_vocoder_impl::fft_init(void) +{ + Word16 i, fft_len2, shift, step, theta; + + fft_len2 = shr(FFTLENGTH, 1); + shift = norm_s(fft_len2); + step = shl(2, shift); + theta = 0; + + for(i = 0; i <= fft_len2; i++) + { + wr_array[i] = cos_fxp(theta); + wi_array[i] = sin_fxp(theta); + if(i >= (fft_len2 - 1)) + theta = ONE_Q15; + else + theta = add(theta, step); + } +} + + +// Subroutine FFT: Fast Fourier Transform +// *************************************************************** +// * Replaces data by its DFT, if isign is 1, or replaces data * +// * by inverse DFT times nn if isign is -1. data is a complex * +// * array of length nn, input as a real array of length 2*nn. * +// * nn MUST be an integer power of two. This is not checked * +// * The real part of the number should be in the zeroeth * +// * of data , and the imaginary part should be in the next * +// * element. Hence all the real parts should have even indeces * +// * and the imaginary parts, odd indeces. * +// * * +// * Data is passed in an array starting in position 0, but the * +// * code is copied from Fortran so uses an internal pointer * +// * which accesses position 0 as position 1, etc. * +// * * +// * This code uses e+jwt sign convention, so isign should be * +// * reversed for e-jwt. * +// *************************************************************** +// +// Q values: +// datam1 - Q14 +// isign - Q15 + +#define SWAP(a,b) temp1 = (a);(a) = (b); (b) = temp1 + +void imbe_vocoder_impl::fft(Word16 *datam1, Word16 nn, Word16 isign) +{ + Word16 n, mmax, m, j, istep, i; + Word16 wr, wi, temp1; + Word32 L_tempr, L_tempi; + Word16 *data; + Word32 L_temp1, L_temp2; + Word16 index, index_step; + + // Use pointer indexed from 1 instead of 0 + data = &datam1[-1]; + + n = shl(nn,1); + j = 1; + for( i = 1; i < n; i+=2 ) + { + if ( j > i) + { + SWAP(data[j],data[i]); + SWAP(data[j+1],data[i+1]); + } + m = nn; + while ( m >= 2 && j > m ) + { + j = sub(j,m); + m = shr(m,1); + } + j = add(j,m); + } + mmax = 2; + + // initialize index step + index_step = nn; + + while ( n > mmax) + { + istep = shl(mmax,1); // istep = 2 * mmax + + index = 0; + index_step = shr(index_step,1); + + wr = ONE_Q15; + wi = 0; + for ( m = 1; m < mmax; m+=2) + { + for ( i = m; i <= n; i += istep) + { + j = i + mmax; + + // tempr = wr * data[j] - wi * data[j+1] + L_temp1 = L_shr(L_mult(wr,data[j]),1); + L_temp2 = L_shr(L_mult(wi,data[j+1]),1); + L_tempr = L_sub(L_temp1,L_temp2); + + // tempi = wr * data[j+1] + wi * data[j] + L_temp1 = L_shr(L_mult(wr,data[j+1]),1); + L_temp2 = L_shr(L_mult(wi,data[j]),1); + L_tempi = L_add(L_temp1,L_temp2); + + + // data[j] = data[i] - tempr + L_temp1 = L_shr(L_deposit_h(data[i]),1); + data[j] = round(L_sub(L_temp1,L_tempr)); + + // data[i] += tempr + data[i] = round(L_add(L_temp1,L_tempr)); + + // data[j+1] = data[i+1] - tempi + L_temp1 = L_shr(L_deposit_h(data[i+1]),1); + data[j+1] = round(L_sub(L_temp1,L_tempi)); + + // data[i+1] += tempi + data[i+1] = round(L_add(L_temp1,L_tempi)); + } + index = add(index,index_step); + wr = wr_array[index]; + if (isign < 0) + wi = negate(wi_array[index]); + else + wi = wi_array[index]; + } + mmax = istep; + } +} + + diff --git a/imbe_vocoder/dsp_sub.h b/imbe_vocoder/dsp_sub.h new file mode 100644 index 0000000..53590e6 --- /dev/null +++ b/imbe_vocoder/dsp_sub.h @@ -0,0 +1,81 @@ +/* + * 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 _DSP_SUB +#define _DSP_SUB + + +#define CNST_0_5_Q1_15 0x4000 +#define CNST_0_5_Q5_11 0x0400 +#define CNST_1_0_Q1_15 0x7FFF + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform inverse DCT +// +// +// INPUT: +// in - pointer to input data +// m_lim - input data's size +// i_lim - result's size +// out - pointer to save result +// +// OUTPUT: +// None +// +// RETURN: +// Saved in out result of conversion +// +//----------------------------------------------------------------------------- +void idct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out); + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform DCT +// +// +// INPUT: +// in - pointer to input data +// m_lim - input data's size +// i_lim - result's size +// out - pointer to save result +// +// OUTPUT: +// None +// +// RETURN: +// Saved in out result of conversion +// +//----------------------------------------------------------------------------- +void dct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out); + +#define FFTLENGTH 256 + + +void fft_init(void); +void fft(Word16 *datam1, Word16 nn, Word16 isign); + +void c_fft(Word16 * farray_ptr); + +#endif diff --git a/imbe_vocoder/encode.cc b/imbe_vocoder/encode.cc new file mode 100644 index 0000000..ef54ded --- /dev/null +++ b/imbe_vocoder/encode.cc @@ -0,0 +1,142 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "dsp_sub.h" +#include "aux_sub.h" +#include "tbls.h" +#include "encode.h" +#include "dc_rmv.h" +#include "pe_lpf.h" +#include "pitch_est.h" +#include "pitch_ref.h" +#include "v_uv_det.h" +#include "sa_encode.h" +#include "ch_encode.h" +#include "imbe_vocoder_impl.h" + +const uint8_t BIT_MASK_TABLE8[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; +#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE8[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE8[(i)&7]) + + +void imbe_vocoder_impl::encode_init(void) +{ + v_zap(pitch_est_buf, PITCH_EST_BUF_SIZE); + v_zap(pitch_ref_buf, PITCH_EST_BUF_SIZE); + v_zap(pe_lpf_mem, PE_LPF_ORD); + pitch_est_init(); + fft_init(); + dc_rmv_mem = 0; + sa_encode_init(); + pitch_ref_init(); +} + + +void imbe_vocoder_impl::encode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd) +{ + Word16 i; + Word16 *wr_ptr, *sig_ptr; + + for(i = 0; i < PITCH_EST_BUF_SIZE - FRAME; i++) + { + pitch_est_buf[i] = pitch_est_buf[i + FRAME]; + pitch_ref_buf[i] = pitch_ref_buf[i + FRAME]; + } + + dc_rmv(snd, &pitch_ref_buf[PITCH_EST_BUF_SIZE - FRAME], &dc_rmv_mem, FRAME); + pe_lpf(&pitch_ref_buf[PITCH_EST_BUF_SIZE - FRAME], &pitch_est_buf[PITCH_EST_BUF_SIZE - FRAME], pe_lpf_mem, FRAME); + + pitch_est(imbe_param, pitch_est_buf); + + // + // Speech windowing and FFT calculation + // + wr_ptr = (Word16 *)wr; + sig_ptr = &pitch_ref_buf[40]; + for(i = 146; i < 256; i++) + { + fft_buf[i].re = mult(*sig_ptr++, *wr_ptr++); + fft_buf[i].im = 0; + } + fft_buf[0].re = *sig_ptr++; + fft_buf[0].im = 0; + wr_ptr--; + for(i = 1; i < 111; i++) + { + fft_buf[i].re = mult(*sig_ptr++, *wr_ptr--); + fft_buf[i].im = 0; + } + for(i = 111; i < 146; i++) + fft_buf[i].re = fft_buf[i].im = 0; + + fft((Word16 *)&fft_buf, FFTLENGTH, 1); + + pitch_ref(imbe_param, fft_buf); + v_uv_det(imbe_param, fft_buf); + sa_encode(imbe_param); + encode_frame_vector(imbe_param, frame_vector); +} + +void imbe_vocoder_impl::encode_4400(int16_t *pcm, uint8_t *imbe) +{ + int16_t frame_vector[8]; + memset(imbe, 0, 11); + + imbe_encode(frame_vector, pcm); + uint32_t offset = 0U; + int16_t mask = 0x0800; + + for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[0U] & mask) != 0); + + mask = 0x0800; + for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[1U] & mask) != 0); + + mask = 0x0800; + for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[2U] & mask) != 0); + + mask = 0x0800; + for (uint32_t i = 0U; i < 12U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[3U] & mask) != 0); + + mask = 0x0400; + for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[4U] & mask) != 0); + + mask = 0x0400; + for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[5U] & mask) != 0); + + mask = 0x0400; + for (uint32_t i = 0U; i < 11U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[6U] & mask) != 0); + + mask = 0x0040; + for (uint32_t i = 0U; i < 7U; i++, mask >>= 1, offset++) + WRITE_BIT(imbe, offset, (frame_vector[7U] & mask) != 0); +} + diff --git a/imbe_vocoder/encode.h b/imbe_vocoder/encode.h new file mode 100644 index 0000000..685c6a6 --- /dev/null +++ b/imbe_vocoder/encode.h @@ -0,0 +1,33 @@ +/* + * 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 _ENCODE +#define _ENCODE + +#define PITCH_EST_BUF_SIZE 621 +#if 0 +void encode_init(void); +void encode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd); +void encode_4400(int16_t *pcm, uint8_t *imbe); +#endif + +#endif diff --git a/imbe_vocoder/globals.h b/imbe_vocoder/globals.h new file mode 100644 index 0000000..2010e7f --- /dev/null +++ b/imbe_vocoder/globals.h @@ -0,0 +1,62 @@ +/* + * 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 _GLOBALS +#define _GLOBALS + + +//#define PI (double)3.1415926535897932384626433832795 + +#define CNST_0_9254_Q0_16 60647 // 0.9254 in unsigned Q0.16 format +#define CNST_0_33_Q0_16 0x5556 // 0.(3) = 1/3 in unsigned Q0.16 format + + +#define CNST_ONE_Q8_24 0x01000000 +#define CNST_0_7_Q1_15 0x599A +#define CNST_0_4_Q1_15 0x3333 +#define CNST_0_03_Q1_15 0x03D7 +#define CNST_0_05_Q1_15 0x0666 + +#define CNST_1_125_Q8_8 0x0120 +#define CNST_0_5_Q8_8 0x0080 +#define CNST_0_125_Q8_8 0x0020 +#define CNST_0_25_Q8_8 0x0040 + +#define CNST_0_8717_Q1_15 0x6F94 +#define CNST_0_0031_Q1_15 0x0064 +#define CNST_0_48_Q4_12 0x07AE +#define CNST_1_00_Q4_12 0x1000 +#define CNST_0_85_Q4_12 0x0D9B +#define CNST_0_4_Q4_12 0x0666 +#define CNST_0_05_Q4_12 0x00CD +#define CNST_0_5882_Q1_15 0x4B4B +#define CNST_0_2857_Q1_15 0x2492 + + +#define HI_BYTE(a) ((a >> 8) & 0xFF) +#define LO_BYTE(a) (a & 0xFF); + + + + + +#endif diff --git a/imbe_vocoder/imbe.h b/imbe_vocoder/imbe.h new file mode 100644 index 0000000..e7f5f3a --- /dev/null +++ b/imbe_vocoder/imbe.h @@ -0,0 +1,69 @@ +/* + * 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 _IMBE +#define _IMBE + +#include "typedef.h" + +#define FRAME 160 // Number samples in frame +#define NUM_HARMS_MAX 56 // Maximum number of harmonics +#define NUM_HARMS_MIN 9 // Minimum number of harmonics +#define NUM_BANDS_MAX 12 // Maximum number of bands +#define MAX_BLOCK_LEN 10 // Maximum length of block used during spectral amplitude encoding +#define NUM_PRED_RES_BLKS 6 // Number of Prediction Residual Blocks +#define PE_LPF_ORD 21 // Order of Pitch estimation LPF +#define PITCH_EST_FRAME 301 // Pitch estimation frame size + + +#define B_NUM (NUM_HARMS_MAX - 1) + + +typedef struct +{ + Word16 e_p; + Word16 pitch; // Q14.2 + Word16 ref_pitch; // Q8.8 + Word32 fund_freq; + Word16 num_harms; + Word16 num_bands; + Word16 v_uv_dsn[NUM_HARMS_MAX]; + Word16 b_vec[NUM_HARMS_MAX + 3]; + Word16 bit_alloc[B_NUM + 4]; + Word16 sa[NUM_HARMS_MAX]; + Word16 l_uv; + Word16 div_one_by_num_harm; + Word16 div_one_by_num_harm_sh; +} IMBE_PARAM; + +typedef struct +{ + Word16 re; + Word16 im; +} Cmplx16; + +#if 0 +void decode_init(IMBE_PARAM *imbe_param); +void decode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd); +#endif + +#endif diff --git a/imbe_vocoder/imbe_vocoder.cc b/imbe_vocoder/imbe_vocoder.cc new file mode 100644 index 0000000..c932160 --- /dev/null +++ b/imbe_vocoder/imbe_vocoder.cc @@ -0,0 +1,37 @@ +#include "imbe_vocoder_impl.h" +#include "imbe_vocoder.h" + +imbe_vocoder::imbe_vocoder() +{ + Impl = new imbe_vocoder_impl(); +} + +imbe_vocoder::~imbe_vocoder() +{ + delete Impl; +} + +void imbe_vocoder::imbe_encode(int16_t *frame_vector, int16_t *snd) +{ + Impl->imbe_encode(frame_vector, snd); +} + +void imbe_vocoder::imbe_decode(int16_t *frame_vector, int16_t *snd) +{ + Impl->imbe_decode(frame_vector, snd); +} + +void imbe_vocoder::encode_4400(int16_t *snd, uint8_t *imbe) +{ + Impl->encode_4400(snd, imbe); +} + +void imbe_vocoder::decode_4400(int16_t *snd, uint8_t *imbe) +{ + Impl->decode_4400(snd, imbe); +} + +const IMBE_PARAM* imbe_vocoder::param(void) +{ + return Impl->param(); +} diff --git a/imbe_vocoder/imbe_vocoder.h b/imbe_vocoder/imbe_vocoder.h new file mode 100644 index 0000000..2aa832e --- /dev/null +++ b/imbe_vocoder/imbe_vocoder.h @@ -0,0 +1,32 @@ +/* + * * Project 25 IMBE Encoder/Decoder Fixed-Point implementation + * * Developed by Pavel Yazev E-mail: pyazev@gmail.com + * * Version 1.0 (c) Copyright 2009 + * */ +/* -*- c++ -*- */ +#ifndef INCLUDED_IMBE_VOCODER_H +#define INCLUDED_IMBE_VOCODER_H + +#include + +class imbe_vocoder_impl; +class imbe_vocoder +{ +public: + imbe_vocoder(void); // constructor + ~imbe_vocoder(); // destructor + // imbe_encode compresses 160 samples (in unsigned int format) + // outputs u[] vectors as frame_vector[] + void imbe_encode(int16_t *frame_vector, int16_t *snd); + + // imbe_decode decodes IMBE codewords (frame_vector), + // outputs the resulting 160 audio samples (snd) + void imbe_decode(int16_t *frame_vector, int16_t *snd); + void encode_4400(int16_t *snd, uint8_t *imbe); + void decode_4400(int16_t *snd, uint8_t *imbe); + const IMBE_PARAM* param(void); + +private: + imbe_vocoder_impl *Impl; +}; +#endif /* INCLUDED_IMBE_VOCODER_H */ diff --git a/imbe_vocoder/imbe_vocoder_api.h b/imbe_vocoder/imbe_vocoder_api.h new file mode 100644 index 0000000..b45fe10 --- /dev/null +++ b/imbe_vocoder/imbe_vocoder_api.h @@ -0,0 +1,68 @@ +/* + * * Project 25 IMBE Encoder/Decoder Fixed-Point implementation + * * Developed by Pavel Yazev E-mail: pyazev@gmail.com + * * Version 1.0 (c) Copyright 2009 + * */ +/* -*- c++ -*- */ +#ifndef INCLUDED_IMBE_VOCODER_H +#define INCLUDED_IMBE_VOCODER_H + +#include + +#define FRAME 160 // Number samples in frame +#define NUM_HARMS_MAX 56 // Maximum number of harmonics +#define NUM_HARMS_MIN 9 // Minimum number of harmonics +#define NUM_BANDS_MAX 12 // Maximum number of bands +#define MAX_BLOCK_LEN 10 // Maximum length of block used during spectral amplitude encoding +#define NUM_PRED_RES_BLKS 6 // Number of Prediction Residual Blocks +#define PE_LPF_ORD 21 // Order of Pitch estimation LPF +#define PITCH_EST_FRAME 301 // Pitch estimation frame size + + +#define B_NUM (NUM_HARMS_MAX - 1) + + +typedef struct +{ + short e_p; + short pitch; // Q14.2 + short ref_pitch; // Q8.8 + int fund_freq; + short num_harms; + short num_bands; + short v_uv_dsn[NUM_HARMS_MAX]; + short b_vec[NUM_HARMS_MAX + 3]; + short bit_alloc[B_NUM + 4]; + short sa[NUM_HARMS_MAX]; + short l_uv; + short div_one_by_num_harm; + short div_one_by_num_harm_sh; +} IMBE_PARAM; + +typedef struct +{ + short re; + short im; +} Cmplx16; + +class imbe_vocoder_impl; +class imbe_vocoder +{ +public: + imbe_vocoder(void); // constructor + ~imbe_vocoder(); // destructor + // imbe_encode compresses 160 samples (in unsigned int format) + // outputs u[] vectors as frame_vector[] + void imbe_encode(int16_t *frame_vector, int16_t *snd); + + // imbe_decode decodes IMBE codewords (frame_vector), + // outputs the resulting 160 audio samples (snd) + void imbe_decode(int16_t *frame_vector, int16_t *snd); + void encode_4400(int16_t *snd, uint8_t *imbe); + void decode_4400(int16_t *snd, uint8_t *imbe); + const IMBE_PARAM* param(void); + +private: + imbe_vocoder_impl *Impl; +}; +#endif /* INCLUDED_IMBE_VOCODER_H */ diff --git a/imbe_vocoder/imbe_vocoder_impl.cc b/imbe_vocoder/imbe_vocoder_impl.cc new file mode 100644 index 0000000..479388a --- /dev/null +++ b/imbe_vocoder/imbe_vocoder_impl.cc @@ -0,0 +1,42 @@ +/* + * Project 25 IMBE Encoder/Decoder Fixed-Point implementation + * Developed by Pavel Yazev E-mail: pyazev@gmail.com + * Version 1.0 (c) Copyright 2009 + */ + +#include + +#include "imbe_vocoder_impl.h" + +imbe_vocoder_impl::imbe_vocoder_impl (void) : + prev_pitch(0), + prev_prev_pitch(0), + prev_e_p(0), + prev_prev_e_p(0), + seed(1), + num_harms_prev1(0), + num_harms_prev2(0), + num_harms_prev3(0), + fund_freq_prev(0), + th_max(0), + dc_rmv_mem(0) +{ + memset(wr_array, 0, sizeof(wr_array)); + memset(wi_array, 0, sizeof(wi_array)); + memset(pitch_est_buf, 0, sizeof(pitch_est_buf)); + memset(pitch_ref_buf, 0, sizeof(pitch_ref_buf)); + memset(pe_lpf_mem, 0, sizeof(pe_lpf_mem)); + memset(fft_buf, 0, sizeof(fft_buf)); + memset(sa_prev1, 0, sizeof(sa_prev1)); + memset(sa_prev2, 0, sizeof(sa_prev2)); + memset(uv_mem, 0, sizeof(uv_mem)); + memset(ph_mem, 0, sizeof(ph_mem)); + memset(vu_dsn_prev, 0, sizeof(vu_dsn_prev)); + memset(sa_prev3, 0, sizeof(sa_prev3)); + memset(v_uv_dsn, 0, sizeof(v_uv_dsn)); + + memset(&my_imbe_param, 0, sizeof(IMBE_PARAM)); + + decode_init(&my_imbe_param); + encode_init(); +} diff --git a/imbe_vocoder/imbe_vocoder_impl.h b/imbe_vocoder/imbe_vocoder_impl.h new file mode 100644 index 0000000..04d0e3a --- /dev/null +++ b/imbe_vocoder/imbe_vocoder_impl.h @@ -0,0 +1,92 @@ +/* + * Project 25 IMBE Encoder/Decoder Fixed-Point implementation + * Developed by Pavel Yazev E-mail: pyazev@gmail.com + * Version 1.0 (c) Copyright 2009 + */ +/* -*- c++ -*- */ +#ifndef INCLUDED_IMBE_VOCODER_IMPL_H +#define INCLUDED_IMBE_VOCODER_IMPL_H + +#include +#include + +#include "imbe.h" +#include "dsp_sub.h" +#include "basic_op.h" +#include "math_sub.h" +#include "encode.h" +#include "decode.h" + +class imbe_vocoder_impl +{ +public: + imbe_vocoder_impl(void); // constructor + ~imbe_vocoder_impl() {} // destructor + // imbe_encode compresses 160 samples (in unsigned int format) + // outputs u[] vectors as frame_vector[] + void imbe_encode(int16_t *frame_vector, int16_t *snd) { + encode(&my_imbe_param, frame_vector, snd); + } + // imbe_decode decodes IMBE codewords (frame_vector), + // outputs the resulting 160 audio samples (snd) + void imbe_decode(int16_t *frame_vector, int16_t *snd) { + decode(&my_imbe_param, frame_vector, snd); + } + void encode_4400(int16_t *snd, uint8_t *imbe); + void decode_4400(int16_t *snd, uint8_t *imbe); + const IMBE_PARAM* param(void) {return &my_imbe_param;} +private: + IMBE_PARAM my_imbe_param; + + /* data items originally static (moved from individual c++ sources) */ + Word16 prev_pitch, prev_prev_pitch, prev_e_p, prev_prev_e_p; + UWord32 seed ; + Word16 num_harms_prev1; + Word32 sa_prev1[NUM_HARMS_MAX + 2]; + Word16 num_harms_prev2; + Word32 sa_prev2[NUM_HARMS_MAX + 2]; + Word16 uv_mem[105]; + UWord32 ph_mem[NUM_HARMS_MAX]; + Word16 num_harms_prev3; + Word32 fund_freq_prev; + Word16 vu_dsn_prev[NUM_HARMS_MAX]; + Word16 sa_prev3[NUM_HARMS_MAX]; + Word32 th_max; + Word16 v_uv_dsn[NUM_BANDS_MAX]; + Word16 wr_array[FFTLENGTH / 2 + 1]; + Word16 wi_array[FFTLENGTH / 2 + 1]; + Word16 pitch_est_buf[PITCH_EST_BUF_SIZE]; + Word16 pitch_ref_buf[PITCH_EST_BUF_SIZE]; + Word32 dc_rmv_mem; + Cmplx16 fft_buf[FFTLENGTH]; + Word16 pe_lpf_mem[PE_LPF_ORD]; + + /* member functions */ + void idct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out); + void dct(Word16 *in, Word16 m_lim, Word16 i_lim, Word16 *out); + void fft_init(void); + void fft(Word16 *datam1, Word16 nn, Word16 isign); + void encode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd); + void parse(int argc, char **argv); + void pitch_est_init(void); + Word32 autocorr(Word16 *sigin, Word16 shift, Word16 scale_shift); + void e_p(Word16 *sigin, Word16 *res_buf); + void pitch_est(IMBE_PARAM *imbe_param, Word16 *frames_buf); + void sa_decode_init(void); + void sa_decode(IMBE_PARAM *imbe_param); + void sa_encode_init(void); + void sa_encode(IMBE_PARAM *imbe_param); + void uv_synt_init(void); + void uv_synt(IMBE_PARAM *imbe_param, Word16 *snd); + void v_synt_init(void); + void v_synt(IMBE_PARAM *imbe_param, Word16 *snd); + void pitch_ref_init(void); + Word16 voiced_sa_calc(Word32 num, Word16 den); + Word16 unvoiced_sa_calc(Word32 num, Word16 den); + void v_uv_det(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf); + void decode_init(IMBE_PARAM *imbe_param); + void decode(IMBE_PARAM *imbe_param, Word16 *frame_vector, Word16 *snd); + void encode_init(void); +}; + +#endif /* INCLUDED_IMBE_VOCODER_IMPL_H */ diff --git a/imbe_vocoder/math_sub.cc b/imbe_vocoder/math_sub.cc new file mode 100644 index 0000000..6bbc2f8 --- /dev/null +++ b/imbe_vocoder/math_sub.cc @@ -0,0 +1,355 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "math_sub.h" + +//----------------------------------------------------------------------------- +// Table for routine Pow2() table[] = 2^(-1...0) +//----------------------------------------------------------------------------- +static const Word16 pow2_table[33] = +{ + 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911, + 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726, + 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706, + 31379, 32066, 32767 +}; + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes pow(2.0, x) +// +// INPUT: +// x - In signed Q10.22 format +// +// OUTPUT: +// None +// +// RETURN: +// Result in signed Q14.2 format +// +//----------------------------------------------------------------------------- +Word16 Pow2(Word32 x) +{ + Word16 exp, i, a, tmp; + Word32 L_x; + Word16 exponent, fraction; + + exponent = extract_h(L_shr(x, 6)); + if(exponent < 0) + exponent = add(exponent, 1); + fraction = extract_l(L_shr(L_sub(x, L_shl(L_deposit_l(exponent),6 + 16)), 7)); + + if(x < 0) + fraction = negate(fraction); + + L_x = L_mult(fraction, 32); // L_x = fraction<<6 + i = extract_h(L_x); // Extract b10-b16 of fraction + L_x = L_shr(L_x, 1); + a = extract_l(L_x); // Extract b0-b9 of fraction + a = a & (Word16)0x7fff; + + L_x = L_deposit_h (pow2_table[i]); // table[i] << 16 + tmp = sub(pow2_table[i], pow2_table[i + 1]); // table[i] - table[i+1] + L_x = L_msu(L_x, tmp, a); // L_x -= tmp*a*2 + + if(x < 0) + { + L_x = L_deposit_h(div_s(0x4000, extract_h(L_x))); // calculate 1/fraction + exponent = sub(exponent, 1); + } + + exp = sub(12, exponent); + L_x = L_shr_r(L_x, exp); + + return extract_h(L_x); +} + +//----------------------------------------------------------------------------- +// PURPOSE: +// Multiply a 32 bit number (L_var2) and a 16 bit +// number (var1) returning a 32 bit result. L_var2 +// is truncated to 31 bits prior to executing the +// multiply. +// +// INPUT: +// L_var2 - A Word32 input variable +// var1 - A Word16 input variable +// +// OUTPUT: +// None +// +// RETURN: +// A Word32 value +// +//----------------------------------------------------------------------------- +Word32 L_mpy_ls(Word32 L_var2, Word16 var1) +{ + Word32 L_varOut; + Word16 swtemp; + + swtemp = shr(extract_l(L_var2), 1); + swtemp = (Word16)32767 & (Word16) swtemp; + + L_varOut = L_mult(var1, swtemp); + L_varOut = L_shr(L_varOut, 15); + L_varOut = L_mac(L_varOut, var1, extract_h(L_var2)); + return (L_varOut); +} + +//----------------------------------------------------------------------------- +// Table for routine cos_fxp() +//----------------------------------------------------------------------------- +static const Word16 cos_table[129] = +{ + 32767, 32766, 32758, 32746, 32729, 32706, 32679, 32647, 32610, + 32568, 32522, 32470, 32413, 32352, 32286, 32214, 32138, 32058, + 31972, 31881, 31786, 31686, 31581, 31471, 31357, 31238, 31114, + 30986, 30853, 30715, 30572, 30425, 30274, 30118, 29957, 29792, + 29622, 29448, 29269, 29086, 28899, 28707, 28511, 28311, 28106, + 27897, 27684, 27467, 27246, 27020, 26791, 26557, 26320, 26078, + 25833, 25583, 25330, 25073, 24812, 24548, 24279, 24008, 23732, + 23453, 23170, 22884, 22595, 22302, 22006, 21706, 21403, 21097, + 20788, 20475, 20160, 19841, 19520, 19195, 18868, 18538, 18205, + 17869, 17531, 17190, 16846, 16500, 16151, 15800, 15447, 15091, + 14733, 14373, 14010, 13646, 13279, 12910, 12540, 12167, 11793, + 11417, 11039, 10660, 10279, 9896, 9512, 9127, 8740, 8351, + 7962, 7571, 7180, 6787, 6393, 5998, 5602, 5205, 4808, + 4410, 4011, 3612, 3212, 2811, 2411, 2009, 1608, 1206, + 804, 402, 0 +}; + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes the cosine of x whose value is expressed in radians/PI. +// +// INPUT: +// x - argument in Q1.15 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q1.15 +// +//----------------------------------------------------------------------------- +Word16 cos_fxp(Word16 x) +{ + Word16 tx, ty; + Word16 sign; + Word16 index1,index2; + Word16 m; + Word16 temp; + + sign = 0; + if(x < 0) + tx = negate(x); + else + tx = x; + + // if angle > pi/2, cos(angle) = -cos(pi-angle) + if(tx > X05_Q15) + { + tx = sub(ONE_Q15,tx); + sign = -1; + } + // convert input to be within range 0-128 + index1 = shr(tx,7); + index2 = add(index1,1); + + if (index1 == 128) + return (Word16)0; + + m = sub(tx,shl(index1,7)); + // convert decimal part to Q15 + m = shl(m,8); + + temp = sub(cos_table[index2],cos_table[index1]); + temp = mult(m,temp); + ty = add(cos_table[index1],temp); + + if(sign) + return negate(ty); + else + return ty; +} + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes the sinus of x whose value is expressed in radians/PI. +// +// INPUT: +// x - argument in Q1.15 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q1.15 +// +//----------------------------------------------------------------------------- +Word16 sin_fxp(Word16 x) +{ + Word16 tx, ty; + Word16 sign; + + sign = 0; + if(x < 0) + { + tx = negate(x); + sign = 1; + } + else + tx = x; + + if(tx > X05_Q15) + tx = sub(tx, X05_Q15); + else + tx = sub(X05_Q15,tx); + + ty = cos_fxp(tx); + + if(sign) + return negate(ty); + else + return ty; +} + + +//----------------------------------------------------------------------------- +// Table for routine sqrt_l_exp() +// table[] = sqrt((i+16)*2^-6) * 2^15, i.e. sqrt(x) scaled Q15 +//----------------------------------------------------------------------------- +static const Word16 sqrt_table[49] = +{ + 16384, 16888, 17378, 17854, 18318, 18770, 19212, 19644, 20066, 20480, + 20886, 21283, 21674, 22058, 22435, 22806, 23170, 23530, 23884, 24232, + 24576, 24915, 25249, 25580, 25905, 26227, 26545, 26859, 27170, 27477, + 27780, 28081, 28378, 28672, 28963, 29251, 29537, 29819, 30099, 30377, + 30652, 30924, 31194, 31462, 31727, 31991, 32252, 32511, 32767 +}; + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes sqrt(L_x), where L_x is positive. +// +// INPUT: +// L_x - argument in Q1.31 +// *exp - pointer to save denormalization exponent +// OUTPUT: +// Right shift to be applied to result, Q16.0 +// +// RETURN: +// Result in Q1.31 +// Right shift should be applied to it! +// +//----------------------------------------------------------------------------- +Word32 sqrt_l_exp(Word32 L_x, Word16 *exp) +{ + Word16 e, i, a, tmp; + Word32 L_y; + + if(L_x <= (Word32)0) + { + *exp = 0; + return (Word32)0; + } + + e = norm_l(L_x) & 0xFFFE; // get next lower EVEN norm. exp + L_x = L_shl(L_x, e); // L_x is normalized to [0.25..1) + *exp = e >> 1; // return 2*exponent (or Q1) + + L_x = L_shr(L_x, 9); + i = extract_h(L_x); // Extract b25-b31, 16 <= i <= 63 because of normalization + L_x = L_shr(L_x, 1); + a = extract_l(L_x); // Extract b10-b24 + a = a & (Word16)0x7fff; + + i = sub(i, 16); // 0 <= i <= 47 + + L_y = L_deposit_h(sqrt_table[i]); // table[i] << 16 + tmp = sub(sqrt_table[i], sqrt_table[i + 1]); // table[i] - table[i+1]) + L_y = L_msu(L_y, tmp, a); // L_y -= tmp*a*2 + + return L_y; +} + +//----------------------------------------------------------------------------- +// Table for routine Log2() +//----------------------------------------------------------------------------- +static const Word16 log_table[33] = +{ + 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716, + 12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033, + 22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497, + 31266, 32023, 32767 +}; + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes log2 of x +// +// INPUT: +// x - argument in Q14.2 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q10.22 +// +//----------------------------------------------------------------------------- +Word32 Log2(Word16 x) +{ + Word16 exp, i, a, tmp; + Word32 L_y; + + if(x <= (Word16)0) + return 0; + + exp = norm_s(x); + x = shl(x, exp); + + i = shr(x, 9); // Extract b15-b9 + a = shl(x & 0x1FF, 6); // Extract b8-b0 + i = sub (i, 32); + + L_y = L_deposit_h(log_table[i]); // table[i] << 16 + tmp = sub(log_table[i], log_table[i + 1]); // table[i] - table[i+1] + L_y = L_msu(L_y, tmp, a); // L_y -= tmp*a*2 + + L_y = L_shr(L_y, 9); + + exp = sub(12, exp); + L_y = L_add(L_y, L_deposit_h(shl(exp, 6))); + + return L_y; +} + + + + + + + + + diff --git a/imbe_vocoder/math_sub.h b/imbe_vocoder/math_sub.h new file mode 100644 index 0000000..baf75fe --- /dev/null +++ b/imbe_vocoder/math_sub.h @@ -0,0 +1,130 @@ +/* + * 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 _MATH_SUB +#define _MATH_SUB + +#define X05_Q15 16384 // (0.5*(1<<15)) +#define ONE_Q15 32767 // ((1<<15)-1) + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes the cosine of x whose value is expressed in radians/PI. +// +// INPUT: +// x - argument in Q1.15 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q1.15 +// +//----------------------------------------------------------------------------- +Word16 cos_fxp(Word16 x); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes the sinus of x whose value is expressed in radians/PI. +// +// INPUT: +// x - argument in Q1.15 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q1.15 +// +//----------------------------------------------------------------------------- +Word16 sin_fxp(Word16 x); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Multiply a 32 bit number (L_var2) and a 16 bit +// number (var1) returning a 32 bit result. L_var2 +// is truncated to 31 bits prior to executing the +// multiply. +// +// INPUT: +// L_var2 - A Word32 input variable +// var1 - A Word16 input variable +// +// OUTPUT: +// None +// +// RETURN: +// A Word32 value +// +//----------------------------------------------------------------------------- +Word32 L_mpy_ls(Word32 L_var2, Word16 var1); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes pow(2.0, x) +// +// INPUT: +// x - In signed Q10.22 format +// +// OUTPUT: +// None +// +// RETURN: +// Result in signed Q14.2 format +// +//----------------------------------------------------------------------------- +Word16 Pow2 (Word32 x); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes sqrt(L_x), where L_x is positive. +// +// INPUT: +// L_x - argument in Q1.31 +// *exp - pointer to save denormalization exponent +// OUTPUT: +// Right shift to be applied to result, Q16.0 +// +// RETURN: +// Result in Q1.31 +// Right shift should be applied to it! +// +//----------------------------------------------------------------------------- +Word32 sqrt_l_exp (Word32 L_x, Word16 *exp); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Computes log2 of x +// +// INPUT: +// x - argument in Q14.2 +// +// OUTPUT: +// None +// +// RETURN: +// Result in Q10.22 +// +//----------------------------------------------------------------------------- +Word32 Log2(Word16 x); + +#endif diff --git a/imbe_vocoder/pe_lpf.cc b/imbe_vocoder/pe_lpf.cc new file mode 100644 index 0000000..b16547b --- /dev/null +++ b/imbe_vocoder/pe_lpf.cc @@ -0,0 +1,74 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "aux_sub.h" +#include "basic_op.h" +#include "math_sub.h" +#include "pe_lpf.h" + + + +static const Word16 lpf_coef[PE_LPF_ORD] = +{ + -94, -92, 185, 543, 288, -883, -1834, -495, 3891, 9141, 11512, + 9141, 3891, -495, -1834, -883, 288, 543, 185, -92, -94 +}; + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Low-pass filter for pitch estimator +// +// +// INPUT: +// *sigin - pointer to input signal buffer +// *sigout - pointer to output signal buffer +// *mem - pointer to filter's memory element +// len - number of input signal samples +// +// OUTPUT: +// None +// +// RETURN: +// Saved filter state in mem +// +//----------------------------------------------------------------------------- +void pe_lpf(Word16 *sigin, Word16 *sigout, Word16 *mem, Word16 len) +{ + Word16 i; + Word32 L_sum; + + while(len--) + { + for(i = 0; i < PE_LPF_ORD - 1; i++) + mem[i] = mem[i + 1]; + mem[PE_LPF_ORD - 1] = *sigin++; + + L_sum = 0; + for(i = 0; i < PE_LPF_ORD; i++) + L_sum = L_mac(L_sum, mem[i], lpf_coef[i]); + + *sigout++ = round(L_sum); + } +} diff --git a/imbe_vocoder/pe_lpf.h b/imbe_vocoder/pe_lpf.h new file mode 100644 index 0000000..54fd017 --- /dev/null +++ b/imbe_vocoder/pe_lpf.h @@ -0,0 +1,47 @@ +/* + * 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 _PE_LPF +#define _PE_LPF + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Low-pass filter for pitch estimator +// +// +// INPUT: +// *sigin - pointer to input signal buffer +// *sigout - pointer to output signal buffer +// *mem - pointer to filter's memory element +// len - number of input signal samples +// +// OUTPUT: +// None +// +// RETURN: +// Saved filter state in mem +// +//----------------------------------------------------------------------------- +void pe_lpf(Word16 *sigin, Word16 *sigout, Word16 *mem, Word16 len); + + +#endif diff --git a/imbe_vocoder/pitch_est.cc b/imbe_vocoder/pitch_est.cc new file mode 100644 index 0000000..dba94d5 --- /dev/null +++ b/imbe_vocoder/pitch_est.cc @@ -0,0 +1,350 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "aux_sub.h" +#include "math_sub.h" +#include "tbls.h" +#include "pitch_est.h" +#include "encode.h" +#include "dsp_sub.h" +#include "imbe_vocoder_impl.h" + + + +static const UWord16 min_max_tbl[203] = +{ + 0x0008, 0x0009, 0x000a, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, + 0x0014, 0x0115, 0x0216, 0x0218, 0x0319, 0x041a, 0x051b, 0x061c, 0x061e, 0x071f, + 0x0820, 0x0921, 0x0a22, 0x0a24, 0x0b25, 0x0c26, 0x0d27, 0x0e28, 0x0e2a, 0x0f2b, + 0x102c, 0x112d, 0x122e, 0x1230, 0x1331, 0x1432, 0x1533, 0x1634, 0x1636, 0x1737, + 0x1838, 0x1939, 0x1a3a, 0x1a3c, 0x1b3d, 0x1c3e, 0x1d3f, 0x1e40, 0x1e42, 0x1f43, + 0x2044, 0x2145, 0x2246, 0x2248, 0x2349, 0x244a, 0x254b, 0x264c, 0x264e, 0x274f, + 0x2850, 0x2951, 0x2a52, 0x2a54, 0x2b55, 0x2c56, 0x2d57, 0x2e58, 0x2e5a, 0x2f5b, + 0x305c, 0x315d, 0x325e, 0x3260, 0x3361, 0x3462, 0x3563, 0x3664, 0x3666, 0x3767, + 0x3868, 0x3969, 0x3a6a, 0x3a6c, 0x3b6d, 0x3c6e, 0x3d6f, 0x3e70, 0x3e72, 0x3f73, + 0x4074, 0x4175, 0x4276, 0x4278, 0x4379, 0x447a, 0x457b, 0x467c, 0x467e, 0x477f, + 0x4880, 0x4981, 0x4a82, 0x4a84, 0x4b85, 0x4c86, 0x4d87, 0x4e88, 0x4e8a, 0x4f8b, + 0x508c, 0x518d, 0x528e, 0x5290, 0x5391, 0x5492, 0x5593, 0x5694, 0x5696, 0x5797, + 0x5898, 0x5999, 0x5a9a, 0x5a9c, 0x5b9d, 0x5c9e, 0x5d9f, 0x5ea0, 0x5ea2, 0x5fa3, + 0x60a4, 0x61a5, 0x62a6, 0x62a8, 0x63a9, 0x64aa, 0x65ab, 0x66ac, 0x66ae, 0x67af, + 0x68b0, 0x69b1, 0x6ab2, 0x6ab4, 0x6bb5, 0x6cb6, 0x6db7, 0x6eb8, 0x6eba, 0x6fbb, + 0x70bc, 0x71bd, 0x72be, 0x72c0, 0x73c1, 0x74c2, 0x75c3, 0x76c4, 0x76c6, 0x77c7, + 0x78c8, 0x79c9, 0x7aca, 0x7aca, 0x7bca, 0x7cca, 0x7dca, 0x7eca, 0x7eca, 0x7fca, + 0x80ca, 0x81ca, 0x82ca, 0x82ca, 0x83ca, 0x84ca, 0x85ca, 0x86ca, 0x86ca, 0x87ca, + 0x88ca, 0x89ca, 0x8aca, 0x8aca, 0x8bca, 0x8cca, 0x8dca, 0x8eca, 0x8eca, 0x8fca, + 0x90ca, 0x91ca, 0x92ca, 0x92ca, 0x93ca, 0x94ca, 0x95ca, 0x96ca, 0x96ca, 0x97ca, + 0x98ca, 0x99ca, 0x9aca +}; + + + + + +void imbe_vocoder_impl::pitch_est_init(void) +{ + prev_pitch = prev_prev_pitch = 158; // 100 + prev_e_p = prev_prev_e_p = 0; +} + + + +Word32 imbe_vocoder_impl::autocorr(Word16 *sigin, Word16 shift, Word16 scale_shift) +{ + Word32 L_sum; + Word16 i; + + L_sum = 0; + for(i = 0; i < PITCH_EST_FRAME - shift; i++) + L_sum = L_add(L_sum, L_shr(L_mult(sigin[i], sigin[i + shift]), scale_shift) ); + + return L_sum; +} + + + +void imbe_vocoder_impl::e_p(Word16 *sigin, Word16 *res_buf) +{ + Word16 i, j, den_part_acc, tmp; + Word32 L_sum, L_num, L_den, L_e0, L_tmp; + Word16 sig_wndwed[PITCH_EST_FRAME]; + Word32 corr[259]; + Word16 index_beg, index_step; + Word16 scale_shift; + + + // Windowing input signal s * wi^2 + for(i = 0 ; i < PITCH_EST_FRAME; i++) + sig_wndwed[i] = mult_r(sigin[i], wi[i]); + + L_sum = 0; + for(i = 0 ; i < PITCH_EST_FRAME; i++) + L_sum = L_add(L_sum, L_mpy_ls( L_mult(sigin[i], sigin[i]), wi[i]) ); // sum(s^2 * wi^2) + + // Check for the overflow + if(L_sum == MAX_32) + { + // Recalculate with scaling + L_sum = 0; + for(i = 0 ; i < PITCH_EST_FRAME; i++) + L_sum = L_add(L_sum, L_mpy_ls( L_shr(L_mult(sigin[i], sigin[i]), 5), wi[i])); + scale_shift = 5; + } + else + scale_shift = 0; + + L_e0 = 0; + for(i = 0 ; i < PITCH_EST_FRAME; i++) + L_e0 = L_add(L_e0, L_shr( L_mult(sig_wndwed[i], sig_wndwed[i]), scale_shift)); // sum(s^2 * wi^4) + + // Calculate correlation for time shift in range 21...150 with step 0.5 + // For integer shifts + for(tmp = 21, i = 0; tmp <= 150; tmp++, i += 2) + corr[i] = autocorr(sig_wndwed, tmp, scale_shift); + // For intermediate shifts + for(i = 1; i < 258; i += 2) + corr[i] = L_shr( L_add(corr[i - 1], corr[i + 1]), 1); + + + // variable to calculate 1 - P * sum(wi ^4) in denominator + den_part_acc = CNST_0_8717_Q1_15; + + index_step = 42; // Note: 42 = 21 in Q15.1 format, so index_step will be used also as p in Q15.1 format + index_beg = 0; + L_e0 = L_shr(L_e0, 7); // divide by 64 to compensate wi scaling + // p = 21...122 by step 0.5 + for(i = 0; i < 203; i++) + { + + // Calculate sum( corr ( n * p) ) + L_tmp = 0; + j = index_beg; + while(j <= 258) + { + L_tmp = L_add(L_tmp, corr[j]); + j += index_step; + } + + L_tmp = L_shr(L_tmp, 6); // compensate wi scaling + L_tmp = L_add(L_tmp, L_e0); // For n = 0 + L_tmp = L_tmp * index_step; + L_num = L_sub(L_sum, L_tmp); + + index_beg++; + index_step++; + + L_den = L_mpy_ls(L_sum, den_part_acc); + + if(L_num < L_den && L_den != 0) + { + //res_buf[i] = (Word16)((double)L_num/(double)L_den * 4096.); // Q4.12 + + if(L_num <= 0) + res_buf[i] = 0; + else + { + tmp = norm_l(L_den); + tmp = div_s(extract_h(L_shl(L_num, tmp)), extract_h(L_shl(L_den, tmp))); + res_buf[i] = shr(tmp, 3); // convert to Q4.12 + } + } + else if(L_num >= L_den) + { + res_buf[i] = CNST_1_00_Q4_12; + //res_buf[i] = (Word16)((double)L_num/(double)L_den * 4096.); // Q4.12 + } + else + res_buf[i] = CNST_1_00_Q4_12; + + den_part_acc = sub(den_part_acc, CNST_0_0031_Q1_15); + } +} + + + + +void imbe_vocoder_impl::pitch_est(IMBE_PARAM *imbe_param, Word16 *frames_buf) +{ + Word16 e_p_arr0[203], e_p_arr1[203], e_p_arr2[203], e1p1_e2p2_est_save[203]; + Word16 min_index, max_index, p, i, p_index; + UWord16 tmp=0, p_fp; + UWord32 UL_tmp; + Word16 e_p_cur, pb, pf, ceb, s_tmp; + Word16 cef_est, cef, p0_est, p0, p1, p2, p1_max_index, p2_max_index, e1p1_e2p2_est, e1p1_e2p2; + Word16 e_p_arr2_min[203]; + + // Calculate E(p) function for current and two future frames + e_p(&frames_buf[0], e_p_arr0); + + // Look-Back Pitch Tracking + min_index = HI_BYTE(min_max_tbl[prev_pitch]); + max_index = LO_BYTE(min_max_tbl[prev_pitch]); + + p = pb = min_index; + e_p_cur = e_p_arr0[min_index]; + while(++p <= max_index) + if(e_p_arr0[p] < e_p_cur) + { + e_p_cur = e_p_arr0[p]; + pb = p; + } + ceb = add(e_p_cur, add(prev_e_p, prev_prev_e_p)); + + + if(ceb <= CNST_0_48_Q4_12) + { + prev_prev_pitch = prev_pitch; + prev_pitch = pb; + prev_prev_e_p = prev_e_p; + prev_e_p = e_p_arr0[pb]; + + imbe_param->pitch = pb + 42; // Result in Q15.1 format + imbe_param->e_p = prev_e_p; + return; + } + + + // Look-Ahead Pitch Tracking + e_p(&frames_buf[FRAME], e_p_arr1); + e_p(&frames_buf[2 * FRAME], e_p_arr2); + + p0_est = p0 = 0; + cef_est = e_p_arr0[p0] + e_p_arr1[p0] + e_p_arr2[p0]; + e1p1_e2p2 = 1; + + p1 = 0; + while(p1 < 203) + { + p2 = HI_BYTE(min_max_tbl[p1]); + p2_max_index = LO_BYTE(min_max_tbl[p1]); + s_tmp = e_p_arr2[p1]; + while(p2 <= p2_max_index) + { + if(e_p_arr2[p2] < s_tmp) + s_tmp = e_p_arr2[p2]; + p2++; + } + e_p_arr2_min[p1] = s_tmp; + p1++; + } + while(p0 < 203) + { + e1p1_e2p2_est = e_p_arr1[p0] + e_p_arr2_min[p0]; + p1 = HI_BYTE(min_max_tbl[p0]); + p1_max_index = LO_BYTE(min_max_tbl[p0]); + while(p1 <= p1_max_index) + { + if(add(e_p_arr1[p1], e_p_arr2_min[p1]) < e1p1_e2p2_est) + e1p1_e2p2_est = add(e_p_arr1[p1], e_p_arr2_min[p1]); + p1++; + } + e1p1_e2p2_est_save[p0] = e1p1_e2p2_est; + cef = add(e_p_arr0[p0], e1p1_e2p2_est); + if(cef < cef_est) + { + cef_est = cef; + p0_est = p0; + } + p0++; + } + + pf = p0_est; + // Sub-multiples analysis + if(pf >= 42) // Check if Sub-multiples are possible + { + if(pf < 84) + i = 1; + else if(pf < 126) + i = 2; + else if(pf < 168) + i = 3; + else + i = 4; + + p_fp = (pf + 42) << 8; // Convert pitch estimation from array index to unsigned Q7.19 format + + while(i--) + { + switch(i) + { + case 0: + tmp = p_fp >> 1; // P_est/2 + break; + + case 1: + UL_tmp = (UWord32)p_fp * 0x5555; // P_est/3 + tmp = UL_tmp >> 16; + break; + + case 2: + tmp = p_fp >> 2; // P_est/4 + break; + + case 3: + UL_tmp = (UWord32)p_fp * 0x3333; // P_est/5 + tmp = UL_tmp >> 16; + break; + } + + p_index = ((tmp + 0x0080) >> 8) - 42; // Convert fixed-point pitch value to integer array index with rounding + + cef = add(e_p_arr0[p_index], e1p1_e2p2_est_save[p_index]); + + if(cef <= CNST_0_85_Q4_12 && mult_r(cef, CNST_0_5882_Q1_15) <= cef_est) // 1/1.7 = 0.5882 + { + pf = p_index; + break; + } + + if(cef <= CNST_0_4_Q4_12 && mult_r(cef, CNST_0_2857_Q1_15) <= cef_est) // 1/3.5 = 0.2857 + { + pf = p_index; + break; + } + + if(cef <= CNST_0_05_Q4_12) + { + pf = p_index; + break; + } + } + } + + cef = add(e_p_arr0[pf], e1p1_e2p2_est_save[pf]); + + if(ceb <= cef) + p = pb; + else + p = pf; + + prev_prev_pitch = prev_pitch; + prev_pitch = p; + prev_prev_e_p = prev_e_p; + prev_e_p = e_p_arr0[p]; + + + imbe_param->pitch = p + 42; // Result in Q15.1 format + imbe_param->e_p = prev_e_p; +} diff --git a/imbe_vocoder/pitch_est.h b/imbe_vocoder/pitch_est.h new file mode 100644 index 0000000..b6b052d --- /dev/null +++ b/imbe_vocoder/pitch_est.h @@ -0,0 +1,29 @@ +/* + * 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 _PITCH_EST +#define _PITCH_EST + +void pitch_est_init(void); +void pitch_est(IMBE_PARAM *imbe_param, Word16 *frames_buf); + +#endif diff --git a/imbe_vocoder/pitch_ref.cc b/imbe_vocoder/pitch_ref.cc new file mode 100644 index 0000000..85c5a13 --- /dev/null +++ b/imbe_vocoder/pitch_ref.cc @@ -0,0 +1,167 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "aux_sub.h" +#include "math_sub.h" +#include "dsp_sub.h" +#include "tbls.h" +#include "pitch_ref.h" + +#include +#include +#include + + +#define PITCH_REF_FRAME 221 +#define MIN_INDEX 50 + + + + +void pitch_ref(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf) +{ + Word16 i, j, index_a_save, pitch_est, tmp, shift, index_wr, up_lim; + Cmplx16 sp_rec[FFTLENGTH/2]; + Word32 fund_freq, fund_freq_2, fund_freq_acc_a, fund_freq_acc_b, fund_freq_acc, L_tmp, amp_re_acc, amp_im_acc, L_sum, L_diff_min; + Word16 ha, hb, index_a, index_b, index_tbl[20], it_ind, re_tmp, im_tmp, pitch_cand=0; + Word32 fund_freq_cand=0; + + + pitch_est = shl(imbe_param->pitch, 7); // Convert to Q8.8 + pitch_est = sub(pitch_est, CNST_1_125_Q8_8); // Sub 1.125 = 9/8 + + L_diff_min = MAX_32; + for(i = 0; i < 19; i++) + { + shift = norm_s(pitch_est); + tmp = shl(pitch_est, shift); + tmp = div_s(0x4000, tmp); + fund_freq = L_shl(tmp, shift + 11); + + fund_freq_acc = fund_freq; + fund_freq_2 = L_shr(fund_freq, 1); + fund_freq_acc_a = L_sub(fund_freq, fund_freq_2); + fund_freq_acc_b = L_add(fund_freq, fund_freq_2); + + // Calculate upper limit for spectrum reconstruction + up_lim = extract_h(L_shr((UWord32)CNST_0_9254_Q0_16 * pitch_est, 1)); // 0.9254/fund_freq + up_lim = sub(up_lim, CNST_0_5_Q8_8); // sub 0.5 + up_lim = up_lim & 0xFF00; // extract fixed part + up_lim = mult(up_lim, extract_h(fund_freq)); + up_lim = shr(up_lim, 1); + + index_b = 0; + while(index_b <= up_lim) + { + ha = extract_h(fund_freq_acc_a); + hb = extract_h(fund_freq_acc_b); + index_a = (ha >> 8) + ((ha & 0xFF)?1:0); + index_b = (hb >> 8) + ((hb & 0xFF)?1:0); + + if(index_b >= MIN_INDEX) + { + L_tmp = L_shl(L_deposit_h(index_a), 8); + L_tmp = L_sub(L_tmp, fund_freq_acc); + L_tmp = L_add(L_tmp, 0x00020000); // for rounding purpose + L_tmp = L_shr(L_tmp, 2); + + index_a_save = index_a; + it_ind = 0; + + amp_re_acc = amp_im_acc = 0; + while(index_a < index_b) + { + index_wr = extract_h(L_tmp); + if(index_wr < 0 && (L_tmp & 0xFFFF)) // truncating for negative number + index_wr = add(index_wr, 1); + index_wr = add(index_wr, 160); + index_tbl[it_ind++] = index_wr; + if(index_wr >= 0 && index_wr <= 320) + { + amp_re_acc = L_mac(amp_re_acc, fft_buf[index_a].re, wr_sp[index_wr]); + amp_im_acc = L_mac(amp_im_acc, fft_buf[index_a].im, wr_sp[index_wr]); + } + + index_a++; + L_tmp = L_add(L_tmp, 0x400000); + } + + it_ind = 0; + index_a = index_a_save; + while(index_a < index_b) + { + index_wr = index_tbl[it_ind++]; + if(index_wr < 0 || index_wr > 320) + { + sp_rec[index_a].im = sp_rec[index_a].re = 0; + } + else + { + sp_rec[index_a].im = mult(mult(extract_h(amp_im_acc), wr_sp[index_wr]), 0x6666); + sp_rec[index_a].re = mult(mult(extract_h(amp_re_acc), wr_sp[index_wr]), 0x6666); + } + + index_a++; + } + } + + fund_freq_acc_a = L_add(fund_freq_acc_a, fund_freq); + fund_freq_acc_b = L_add(fund_freq_acc_b, fund_freq); + fund_freq_acc = L_add(fund_freq_acc, fund_freq); + } + + L_sum = 0; + for(j = MIN_INDEX; j <= up_lim; j++) + { + re_tmp = sub(fft_buf[j].re, sp_rec[j].re); + im_tmp = sub(fft_buf[j].im, sp_rec[j].im); + L_sum = L_mac(L_sum, re_tmp, re_tmp); + L_sum = L_mac(L_sum, im_tmp, im_tmp); + } + + if(L_sum < L_diff_min) + { + L_diff_min = L_sum; + pitch_cand = pitch_est; + fund_freq_cand = fund_freq; + } + + pitch_est = add(pitch_est, CNST_0_125_Q8_8); // Add 0.125 = 1/8 + } + + imbe_param->ref_pitch = pitch_cand; + imbe_param->fund_freq = fund_freq_cand; +} + + + + + + + + + + diff --git a/imbe_vocoder/pitch_ref.h b/imbe_vocoder/pitch_ref.h new file mode 100644 index 0000000..29ccf8a --- /dev/null +++ b/imbe_vocoder/pitch_ref.h @@ -0,0 +1,28 @@ +/* + * 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 _PITCH_REF +#define _PIRCH_REF + +void pitch_ref(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf); + +#endif diff --git a/imbe_vocoder/qnt_sub.cc b/imbe_vocoder/qnt_sub.cc new file mode 100644 index 0000000..bd0cbe8 --- /dev/null +++ b/imbe_vocoder/qnt_sub.cc @@ -0,0 +1,144 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "qnt_sub.h" + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Dequantize by quantizer step size +// +// +// INPUT: +// qval - quantized value +// step_size - step size used to quantize in unsigned Q0.16 format +// bit_num - the number of bits +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in signed (bit_num).16 format +// +//----------------------------------------------------------------------------- +Word32 deqnt_by_step(Word16 qval, UWord16 step_size, Word16 bit_num) +{ + Word32 res; + + if(bit_num == 0) + return (Word32)0; + + res = (Word32)step_size * (qval - (1 << (bit_num - 1))); + res = L_add(res, ((Word32)step_size * CNST_0_5_Q0_16) >> 16); + + return res; +} + + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Quantize by quantizer step size +// +// +// INPUT: +// val - value to be quantized in Q5.10 format +// step_size - step size used to quantize in unsigned Q0.16 format +// bit_num - the number of bits +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in integer +// +//----------------------------------------------------------------------------- +Word16 qnt_by_step(Word16 val, UWord16 step_size, Word16 bit_num) +{ + Word16 index, min_val, max_val; + Word16 q_index, shift, tmp; + + shift = norm_s(step_size); + + tmp = div_s(0x4000, shl(step_size, shift)); // Remark: To get result in Qxx.16 format it is necessary left shift tmp by (shift + 3) + q_index = shr_r(mult(val, tmp), sub(9, shift)); // q_index here is rounded to the nearest integer + + max_val = 1 << (bit_num - 1); + min_val = negate(max_val); + + if(q_index < min_val) + index = 0; + else if(q_index >= max_val) + index = (1 << bit_num) - 1; + else + index = max_val + q_index; + + return index; +} + +//----------------------------------------------------------------------------- +// PURPOSE: +// Quantize by table +// +// +// INPUT: +// val - value to be quantized +// q_tbl - pointer to table +// q_tbl_size - size of table +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in integer +// +//----------------------------------------------------------------------------- +Word16 tbl_quant(Word16 val, Word16 *q_tbl, Word16 q_tbl_size) +{ + Word16 min_index, max_index, index; + + min_index = 0; + max_index = q_tbl_size - 1; + + if(val >= q_tbl[max_index]) + return max_index; + + if(val <= q_tbl[min_index]) + return min_index; + + while(max_index - min_index != 1) + { + index = min_index + ((max_index - min_index) >> 1); + + if(q_tbl[index] > val) + max_index = index; + else + min_index = index; + } + + if(q_tbl[max_index] - val <= val - q_tbl[min_index]) + return max_index; + else + return min_index; +} diff --git a/imbe_vocoder/qnt_sub.h b/imbe_vocoder/qnt_sub.h new file mode 100644 index 0000000..ee3ac1c --- /dev/null +++ b/imbe_vocoder/qnt_sub.h @@ -0,0 +1,86 @@ +/* + * 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 _QNT_SUB +#define _QNT_SUB + + +#define CNST_0_5_Q0_16 0x8000 + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Dequantize by quantizer step size +// +// +// INPUT: +// qval - quantized value +// step_size - step size used to quantize in unsigned Q0.16 format +// bit_num - the number of bits +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in signed (bit_num).16 format +// +//----------------------------------------------------------------------------- +Word32 deqnt_by_step(Word16 qval, UWord16 step_size, Word16 bit_num); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Quantize by quantizer step size +// +// +// INPUT: +// val - value to be quantized +// step_size - step size used to quantize in unsigned Q0.16 format +// bit_num - the number of bits +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in integer +// +//----------------------------------------------------------------------------- +Word16 qnt_by_step(Word16 val, UWord16 step_size, Word16 bit_num); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Quantize by table +// +// +// INPUT: +// val - value to be quantized +// q_tbl - pointer to table +// q_tbl_size - size of table +// +// OUTPUT: +// None +// +// RETURN: +// Quantized Value in integer +// +//----------------------------------------------------------------------------- +Word16 tbl_quant(Word16 val, Word16 *q_tbl, Word16 q_tbl_size); + +#endif diff --git a/imbe_vocoder/rand_gen.cc b/imbe_vocoder/rand_gen.cc new file mode 100644 index 0000000..b818d64 --- /dev/null +++ b/imbe_vocoder/rand_gen.cc @@ -0,0 +1,61 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" + +static UWord32 seed = 1; + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Generate pseudo-random numbers in range -1...1 +// +// +// INPUT: +// None +// +// OUTPUT: +// None +// +// RETURN: +// Pseudo-random number in signed Q1.16 format +// +//----------------------------------------------------------------------------- +Word16 rand_gen(void) +{ + UWord32 hi, lo; + + lo = 16807 * (seed & 0xFFFF); + hi = 16807 * (seed >> 16); + + lo += (Word32)(hi & 0x7FFF) << 16; + lo += (hi >> 15); + + if(lo > 0x7FFFFFFF) + lo -= 0x7FFFFFFF; + + seed = lo; + + return (Word16)lo; +} diff --git a/imbe_vocoder/rand_gen.h b/imbe_vocoder/rand_gen.h new file mode 100644 index 0000000..f67d15e --- /dev/null +++ b/imbe_vocoder/rand_gen.h @@ -0,0 +1,44 @@ +/* + * 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 _RAND_GEN +#define _RAND_GEN + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Generate pseudo-random numbers in range -1...1 +// +// +// INPUT: +// None +// +// OUTPUT: +// None +// +// RETURN: +// Pseudo-random number in signed Q1.16 format +// +//----------------------------------------------------------------------------- +Word16 rand_gen(void); + +#endif diff --git a/imbe_vocoder/sa_decode.cc b/imbe_vocoder/sa_decode.cc new file mode 100644 index 0000000..94d8f46 --- /dev/null +++ b/imbe_vocoder/sa_decode.cc @@ -0,0 +1,200 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "basic_op.h" +#include "imbe.h" +#include "tbls.h" +#include "qnt_sub.h" +#include "sa_decode.h" +#include "aux_sub.h" +#include "dsp_sub.h" +#include "math_sub.h" +#include "encode.h" +#include "imbe_vocoder_impl.h" + + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Initialization of Spectral Amplitude Decoder +// +// +// INPUT: +// None +// +// OUTPUT: +// None +// +// RETURN: +// None +// +//----------------------------------------------------------------------------- +void imbe_vocoder_impl::sa_decode_init(void) +{ + num_harms_prev1 = 30; + v_zap((Word16 *)sa_prev1, 2 * (NUM_HARMS_MAX + 2)); +} + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform Spectral Amplitude Decoding +// +// +// INPUT: +// IMBE_PARAM *imbe_param - pointer to IMBE_PARAM structure with +// valid num_harms and b_vec items +// +// OUTPUT: +// None +// +// RETURN: +// Decoded Spectral Amplitudes +// +//----------------------------------------------------------------------------- +void imbe_vocoder_impl::sa_decode(IMBE_PARAM *imbe_param) +{ + Word16 gain_vec[6], gain_r[6]; + UWord16 index, index_1, num_harms; + Word16 *gss_ptr, *ba_ptr, i, j, *t_vec_ptr, *b_vec_ptr; + Word16 t_vec[NUM_HARMS_MAX], c_vec[MAX_BLOCK_LEN]; + UWord32 lmprbl_item; + Word16 bl_len, step_size, num_bits, tmp, ro_coef, si_coef, tmp1; + UWord32 k_coef, k_acc; + Word32 sum, tmp_word32, sa_tmp[NUM_HARMS_MAX]; + Word16 *sa; + + num_harms = imbe_param->num_harms; + index = num_harms - NUM_HARMS_MIN; + ba_ptr = imbe_param->bit_alloc; + b_vec_ptr = &imbe_param->b_vec[2]; + sa = imbe_param->sa; + + // Decoding the Gain Vector. gain_vec has signed Q5.11 format + gss_ptr = (Word16 *)&gain_step_size_tbl[index * 5]; + gain_vec[0] = gain_qnt_tbl[*b_vec_ptr++]; + + for(i = 1; i < 6; i++) + gain_vec[i] = extract_l(L_shr(deqnt_by_step(*b_vec_ptr++, *gss_ptr++, *ba_ptr++), 5)); + idct(gain_vec, NUM_PRED_RES_BLKS, NUM_PRED_RES_BLKS, gain_r); + + lmprbl_item = lmprbl_tbl[index]; + v_zap(t_vec, NUM_HARMS_MAX); + + // Decoding the Higher Order DCT Coefficients + t_vec_ptr = t_vec; + for(i = 0; i < NUM_PRED_RES_BLKS; i++) + { + bl_len = (lmprbl_item >> 28) & 0xF; lmprbl_item <<= 4; + v_zap(c_vec, MAX_BLOCK_LEN); + c_vec[0] = gain_r[i]; + for(j = 1; j < bl_len; j++) + { + num_bits = *ba_ptr++; + if(num_bits) + { + step_size = extract_h(((Word32)hi_ord_std_tbl[j - 1] * hi_ord_step_size_tbl[num_bits - 1]) << 1); + c_vec[j] = extract_l(L_shr(deqnt_by_step(*b_vec_ptr, step_size, num_bits), 5)); + } + else + c_vec[j] = 0; + + b_vec_ptr++; + } + idct(c_vec, bl_len, bl_len, t_vec_ptr); + t_vec_ptr += bl_len; + } + + // Calculate num_harms_prev/num_harms. Result save in unsigned format Q8.24 + if(num_harms == num_harms_prev1) + k_coef = (Word32)CNST_ONE_Q8_24; + else if(num_harms > num_harms_prev1) + k_coef = (Word32)div_s(num_harms_prev1 << 9, num_harms << 9) << 9; + else + { + // imbe_param->num_harms < num_harms_prev1 + k_coef = 0; + tmp = num_harms_prev1; + while(tmp > num_harms) + { + tmp -= num_harms; + k_coef += (Word32)CNST_ONE_Q8_24; + } + k_coef += (Word32)div_s(tmp << 9, num_harms << 9) << 9; + } + + if(num_harms <= 15) + ro_coef = CNST_0_4_Q1_15; + else if(num_harms <= 24) + ro_coef = num_harms * CNST_0_03_Q1_15 - CNST_0_05_Q1_15; + else + ro_coef = CNST_0_7_Q1_15; + + k_acc = k_coef; + sum = 0; + + for(i = num_harms_prev1 + 1; i < NUM_HARMS_MAX + 2; i++) + sa_prev1[i] = sa_prev1[num_harms_prev1]; + + for(i = 0; i < num_harms; i++) + { + index = (UWord16)(k_acc >> 24); // Get integer part + si_coef = (Word16)((k_acc - ((UWord32)index << 24)) >> 9); // Get fractional part + + if(si_coef == 0) + { + tmp_word32 = L_mpy_ls(sa_prev1[index], ro_coef); // sa_prev1 here is in Q10.22 format + sa_tmp[i] = L_add(L_shr(L_deposit_h(t_vec[i]), 5), tmp_word32); // Convert t_vec to Q10.22 and add ... + sum = L_add(sum, sa_prev1[index]); // sum in Q10.22 format + } + else + { + index_1 = index + 1; + tmp_word32 = L_mpy_ls(sa_prev1[index], sub(0x7FFF, si_coef)); + sum = L_add(sum, tmp_word32); + sa_tmp[i] = L_add(L_shr(L_deposit_h(t_vec[i]), 5), L_mpy_ls(tmp_word32, ro_coef)); + + tmp_word32 = L_mpy_ls(sa_prev1[index_1], si_coef); + sum = L_add(sum, tmp_word32); + sa_tmp[i] = L_add(sa_tmp[i], L_mpy_ls(tmp_word32, ro_coef)); + } + + k_acc += k_coef; + } + + imbe_param->div_one_by_num_harm_sh = tmp = norm_s(num_harms); + imbe_param->div_one_by_num_harm = tmp1 = div_s(0x4000, num_harms << tmp); // calculate 1/num_harms with scaling for better pricision + // save result to use late + + sum = L_shr(L_mpy_ls(L_mpy_ls(sum, ro_coef), tmp1), (14 - tmp)); + + for(i = 1; i <= num_harms; i++) + { + sa_prev1[i] = L_sub(sa_tmp[i - 1], sum); + sa[i - 1] = Pow2(sa_prev1[i]); + } + + num_harms_prev1 = num_harms; +} diff --git a/imbe_vocoder/sa_decode.h b/imbe_vocoder/sa_decode.h new file mode 100644 index 0000000..88d1e33 --- /dev/null +++ b/imbe_vocoder/sa_decode.h @@ -0,0 +1,64 @@ +/* + * 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 _SA_DECODE +#define _SA_DECODE + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Initialization of Spectral Amplitude Decoder +// +// +// INPUT: +// None +// +// OUTPUT: +// None +// +// RETURN: +// None +// +//----------------------------------------------------------------------------- +#if 0 +void sa_decode_init(void); + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform Spectral Amplitude Decoding +// +// +// INPUT: +// IMBE_PARAM *imbe_param - pointer to IMBE_PARAM structure with +// valid num_harms and b_vec items +// +// OUTPUT: +// None +// +// RETURN: +// Decoded Spectral Amplitudes +// +//----------------------------------------------------------------------------- +void sa_decode(IMBE_PARAM *imbe_param); +#endif + +#endif diff --git a/imbe_vocoder/sa_encode.cc b/imbe_vocoder/sa_encode.cc new file mode 100644 index 0000000..0525fae --- /dev/null +++ b/imbe_vocoder/sa_encode.cc @@ -0,0 +1,296 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "basic_op.h" +#include "imbe.h" +#include "tbls.h" +#include "qnt_sub.h" +#include "sa_encode.h" +#include "aux_sub.h" +#include "dsp_sub.h" +#include "math_sub.h" + +#include +#include +#include "encode.h" +#include "imbe_vocoder_impl.h" + + +void imbe_vocoder_impl::sa_encode_init(void) +{ + Word16 i; + num_harms_prev2 = 30; + for(i = 0; i < NUM_HARMS_MAX + 2; i++) + sa_prev2[i] = 0; +} + +void imbe_vocoder_impl::sa_encode(IMBE_PARAM *imbe_param) +{ + Word16 gain_vec[6], gain_r[6]; + UWord16 index, i, j, num_harms; + Word16 *ba_ptr, *t_vec_ptr, *b_vec_ptr, *gss_ptr, *sa_ptr; + Word16 t_vec[NUM_HARMS_MAX], c_vec[MAX_BLOCK_LEN]; + UWord32 lmprbl_item; + Word16 bl_len, step_size, num_bits, tmp, ro_coef, si_coef, tmp1; + UWord32 k_coef, k_acc; + Word32 sum, tmp_word32, vec32_tmp[NUM_HARMS_MAX], *vec32_ptr; + + num_harms = imbe_param->num_harms; + + // Calculate num_harms_prev2/num_harms. Result save in unsigned format Q8.24 + if(num_harms == num_harms_prev2) + k_coef = (Word32)CNST_ONE_Q8_24; + else if(num_harms > num_harms_prev2) + k_coef = (Word32)div_s(num_harms_prev2 << 9, num_harms << 9) << 9; + else + { + // imbe_param->num_harms < num_harms_prev2 + k_coef = 0; + tmp = num_harms_prev2; + while(tmp > num_harms) + { + tmp -= num_harms; + k_coef += (Word32)CNST_ONE_Q8_24; + } + k_coef += (Word32)div_s(tmp << 9, num_harms << 9) << 9; + } + + // Calculate prediction coefficient + if(num_harms <= 15) + ro_coef = CNST_0_4_Q1_15; + else if(num_harms <= 24) + ro_coef = num_harms * CNST_0_03_Q1_15 - CNST_0_05_Q1_15; + else + ro_coef = CNST_0_7_Q1_15; + + for(i = num_harms_prev2 + 1; i < NUM_HARMS_MAX + 2; i++) + sa_prev2[i] = sa_prev2[num_harms_prev2]; + + k_acc = k_coef; + sum = 0; + sa_ptr = imbe_param->sa; + vec32_ptr = vec32_tmp; + for(i = 0; i < num_harms; i++) + { + index = (UWord16)(k_acc >> 24); // Get integer part + si_coef = (Word16)((k_acc - ((UWord32)index << 24)) >> 9); // Get fractional part + + + if(si_coef == 0) + { + tmp_word32 = L_mpy_ls(sa_prev2[index], ro_coef); // sa_prev2 here is in Q10.22 format + *vec32_ptr++ = L_sub(Log2(*sa_ptr++), tmp_word32); + sum = L_add(sum, sa_prev2[index]); // sum in Q10.22 format + } + else + { + tmp_word32 = L_mpy_ls(sa_prev2[index], sub(0x7FFF, si_coef)); + sum = L_add(sum, tmp_word32); + *vec32_ptr = L_sub(Log2(*sa_ptr++), L_mpy_ls(tmp_word32, ro_coef)); + + tmp_word32 = L_mpy_ls(sa_prev2[index + 1], si_coef); + sum = L_add(sum, tmp_word32); + *vec32_ptr = L_sub(*vec32_ptr, L_mpy_ls(tmp_word32, ro_coef)); + + vec32_ptr++; + } + + k_acc += k_coef; + } + + imbe_param->div_one_by_num_harm_sh = tmp = norm_s(num_harms); + imbe_param->div_one_by_num_harm = tmp1 = div_s(0x4000, num_harms << tmp); // calculate 1/num_harms with scaling for better pricision + // save result to use late + sum = L_shr(L_mpy_ls(L_mpy_ls(sum, ro_coef), tmp1), (14 - tmp)); + + for(i = 0; i < num_harms; i++) + t_vec[i] = extract_h(L_shl(L_add(vec32_tmp[i], sum), 5)); // t_vec has Q5.11 format + ////////////////////////////////////////////// + // + // Encode T vector + // + ////////////////////////////////////////////// + index = num_harms - NUM_HARMS_MIN; + + // Unpack bit allocation table's item + get_bit_allocation(num_harms, imbe_param->bit_alloc); + lmprbl_item = lmprbl_tbl[index]; + + // Encoding the Higher Order DCT Coefficients + t_vec_ptr = t_vec; + b_vec_ptr = &imbe_param->b_vec[8]; + ba_ptr = &imbe_param->bit_alloc[5]; + for(i = 0; i < NUM_PRED_RES_BLKS; i++) + { + bl_len = (lmprbl_item >> 28) & 0xF; lmprbl_item <<= 4; + + dct(t_vec_ptr, bl_len, bl_len, c_vec); + gain_vec[i] = c_vec[0]; +/* + for(j = 0; j < bl_len; j++) + printf("%g ", (double)t_vec_ptr[j]/2048.); + printf("\n"); + for(j = 0; j < bl_len; j++) + printf("%g ", (double)c_vec[j]/2048.); + printf("\n"); + printf("\n"); +*/ + for(j = 1; j < bl_len; j++) + { + num_bits = *ba_ptr++; + if(num_bits) + { + step_size = extract_h(((Word32)hi_ord_std_tbl[j - 1] * hi_ord_step_size_tbl[num_bits - 1]) << 1); + *b_vec_ptr = qnt_by_step(c_vec[j], step_size, num_bits); + } + else + *b_vec_ptr = 0; + + b_vec_ptr++; + } + t_vec_ptr += bl_len; + } + + // Encoding the Gain Vector + dct(gain_vec, NUM_PRED_RES_BLKS, NUM_PRED_RES_BLKS, gain_r); + + b_vec_ptr = &imbe_param->b_vec[2]; + ba_ptr = &imbe_param->bit_alloc[0]; + gss_ptr = (Word16 *)&gain_step_size_tbl[index * 5]; + + *b_vec_ptr++ = tbl_quant(gain_r[0], (Word16 *)&gain_qnt_tbl[0], GAIN_QNT_TBL_SIZE); + for(j = 1; j < 6; j++) + *b_vec_ptr++ = qnt_by_step(gain_r[j], *gss_ptr++, *ba_ptr++); + +/* + for(j = 0; j < NUM_PRED_RES_BLKS; j++) + printf("%g ", (double)gain_vec[j]/2048.); + printf("\n"); + for(j = 0; j < NUM_PRED_RES_BLKS; j++) + printf("%g ", (double)gain_r[j]/2048.); + printf("\n"); + printf("\n"); +*/ + + + + ////////////////////////////////////////////// + // + // Decode T vector + // + ////////////////////////////////////////////// + ba_ptr = imbe_param->bit_alloc; + b_vec_ptr = &imbe_param->b_vec[2]; + + // Decoding the Gain Vector. gain_vec has signed Q5.11 format + gss_ptr = (Word16 *)&gain_step_size_tbl[index * 5]; + gain_vec[0] = gain_qnt_tbl[*b_vec_ptr++]; + + for(i = 1; i < 6; i++) + gain_vec[i] = extract_l(L_shr(deqnt_by_step(*b_vec_ptr++, *gss_ptr++, *ba_ptr++), 5)); +/* + printf("gain deqnt\n"); + for(j = 0; j < 6; j++) + printf("%g ", (double)gain_vec[j]/2048.); + printf("\n"); +*/ + idct(gain_vec, NUM_PRED_RES_BLKS, NUM_PRED_RES_BLKS, gain_r); + + v_zap(t_vec, NUM_HARMS_MAX); + lmprbl_item = lmprbl_tbl[index]; + + // Decoding the Higher Order DCT Coefficients + t_vec_ptr = t_vec; + for(i = 0; i < NUM_PRED_RES_BLKS; i++) + { + bl_len = (lmprbl_item >> 28) & 0xF; lmprbl_item <<= 4; + v_zap(c_vec, MAX_BLOCK_LEN); + c_vec[0] = gain_r[i]; + for(j = 1; j < bl_len; j++) + { + num_bits = *ba_ptr++; + if(num_bits) + { + step_size = extract_h(((Word32)hi_ord_std_tbl[j - 1] * hi_ord_step_size_tbl[num_bits - 1]) << 1); + c_vec[j] = extract_l(L_shr(deqnt_by_step(*b_vec_ptr, step_size, num_bits), 5)); + } + else + c_vec[j] = 0; + + b_vec_ptr++; + } +/* + printf("\n"); + for(j = 0; j < bl_len; j++) + printf("%g ", (double)c_vec[j]/2048.); + printf("\n"); +*/ + idct(c_vec, bl_len, bl_len, t_vec_ptr); + t_vec_ptr += bl_len; + } +/* + printf("\n====t_vec_rec ===\n"); + for(j = 0; j < num_harms; j++) + printf("%g ", (double)t_vec[j]/2048.); + printf("\n"); +*/ + ////////////////////////////////////////////// + // + // Reconstruct Spectral Amplitudes + // + ////////////////////////////////////////////// + k_acc = k_coef; + vec32_ptr = vec32_tmp; + + for(i = num_harms_prev2 + 1; i < NUM_HARMS_MAX + 2; i++) + sa_prev2[i] = sa_prev2[num_harms_prev2]; + + for(i = 0; i < num_harms; i++) + { + index = (UWord16)(k_acc >> 24); // Get integer part + si_coef = (Word16)((k_acc - ((UWord32)index << 24)) >> 9); // Get fractional part + + if(si_coef == 0) + { + tmp_word32 = L_mpy_ls(sa_prev2[index], ro_coef); // sa_prev2 here is in Q10.22 format + *vec32_ptr++ = L_add(L_shr(L_deposit_h(t_vec[i]), 5), tmp_word32); // Convert t_vec to Q10.22 and add ... + } + else + { + tmp_word32 = L_mpy_ls(sa_prev2[index], sub(0x7FFF, si_coef)); + *vec32_ptr = L_add(L_shr(L_deposit_h(t_vec[i]), 5), L_mpy_ls(tmp_word32, ro_coef)); + + tmp_word32 = L_mpy_ls(sa_prev2[index + 1], si_coef); + *vec32_ptr = L_add(*vec32_ptr, L_mpy_ls(tmp_word32, ro_coef)); + + vec32_ptr++; + } + + k_acc += k_coef; + } + + for(i = 1; i <= num_harms; i++) + sa_prev2[i] = L_sub(vec32_tmp[i - 1], sum); + + num_harms_prev2 = num_harms; +} diff --git a/imbe_vocoder/sa_encode.h b/imbe_vocoder/sa_encode.h new file mode 100644 index 0000000..06e4145 --- /dev/null +++ b/imbe_vocoder/sa_encode.h @@ -0,0 +1,30 @@ +/* + * 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 _SA_ENCODE +#define _SA_ENCODE + + +void sa_encode_init(void); +void sa_encode(IMBE_PARAM *imbe_param); + +#endif diff --git a/imbe_vocoder/sa_enh.cc b/imbe_vocoder/sa_enh.cc new file mode 100644 index 0000000..c6586eb --- /dev/null +++ b/imbe_vocoder/sa_enh.cc @@ -0,0 +1,202 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "imbe.h" +#include "qnt_sub.h" +#include "aux_sub.h" +#include "math_sub.h" +#include "sa_enh.h" + + + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform Spectral Amplitude Enhancement +// +// +// INPUT: +// IMBE_PARAM *imbe_param - pointer to IMBE_PARAM structure with +// valid num_harms, sa and fund_freq items +// +// OUTPUT: +// None +// +// RETURN: +// Enhanced Spectral Amplitudes +// +//----------------------------------------------------------------------------- +void sa_enh(IMBE_PARAM *imbe_param) +{ + Word16 *sa, num_harm, sa_tmp[NUM_HARMS_MAX], nm; + Word16 cos_w[NUM_HARMS_MAX], i, tmp; + Word32 L_tmp, Rm0, Rm1; + Word32 w0, cos_acc; + Word32 L_den, L_num, L_Rm0_2, L_Rm1_2, L_sum_Rm02_Rm12, L_sum_mod; + Word16 Rm0Rm1, nm1, nm2, tot_nm; + Word16 Rm0_s, Rm1_s; + + + sa = imbe_param->sa; + num_harm = imbe_param->num_harms; + + v_equ(sa_tmp, sa, num_harm); + + Rm0 = L_v_magsq(sa, num_harm); + + if(Rm0 == 0) + return; + + nm = norm_l (Rm0); + if(Rm0 == MAX_32) + { + nm = 1; + v_equ_shr(sa_tmp, sa, nm, num_harm); + Rm0 = L_v_magsq(sa_tmp, num_harm); + } + else + { + if(nm > 2) + { + nm = -(nm >> 1); + v_equ_shr(sa_tmp, sa, nm, num_harm); + Rm0 = L_v_magsq(sa_tmp, num_harm); + } + } + + w0 = imbe_param->fund_freq; + + cos_acc = 0; Rm1 = 0; + for(i = 0; i < num_harm; i++) + { + cos_acc = L_add(cos_acc, w0); + + cos_w[i] = cos_fxp(extract_h(cos_acc)); + Rm1 = L_add(Rm1, L_mpy_ls(L_mult(sa_tmp[i], sa_tmp[i]), cos_w[i])); + } + + Rm0_s = extract_h(Rm0); + Rm1_s = extract_h(Rm1); + + L_Rm0_2 = L_mult(Rm0_s, Rm0_s); + L_Rm1_2 = L_mult(Rm1_s, Rm1_s); + L_den = L_sub(L_Rm0_2, L_Rm1_2); + L_den = L_mult(extract_h(L_den), Rm0_s); + nm1 = norm_l(L_den); + L_den = L_shl(L_den, nm1); + + nm2 = norm_l(w0); + L_den = L_mpy_ls(L_den, extract_h(L_shl(w0, nm2))); // Calculate w0 * Rm0 * (Rm0^2 - Rm1^2) + nm1 += nm2; // total denominator shift + + if (L_den < 1) return; // fix bug infinite loop due to invalid input + + L_sum_Rm02_Rm12 = L_add(L_shr(L_Rm0_2, 2), L_shr(L_Rm1_2, 2)); + Rm0Rm1 = shr(mult_r(Rm0_s, Rm1_s), 1); + + for(i = 0; i < num_harm; i++) + { + if((((i + 1) << 3) > num_harm) && (sa_tmp[i] != 0x0000)) + { + L_num = L_sub(L_sum_Rm02_Rm12, L_mult(Rm0Rm1, cos_w[i])); + tot_nm = norm_l(L_num); + L_num = L_shl(L_num, tot_nm); + while(L_num >= L_den) + { + L_num = L_shr(L_num, 1); + tot_nm -= 1; + } + + tmp = div_s(extract_h(L_num), extract_h(L_den)); + tot_nm -= nm1; + + L_tmp = L_mult(sa_tmp[i], sa_tmp[i]); + nm2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, nm2); + L_tmp = L_mult(extract_h(L_tmp), tmp); + tot_nm += nm2; + tot_nm -= 2; + + if(tot_nm <= 0) + { + L_tmp = L_shr(L_tmp, add(8, tot_nm)); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm); + L_tmp = L_mult(extract_h(L_tmp), CNST_0_9898_Q1_15); + tmp = extract_h(L_shl(L_tmp, 1)); + } + else + { + if(tot_nm <= 8) + { + L_tmp = L_shr(L_tmp, tot_nm); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm + 1); + tmp = mult(extract_h(L_tmp), CNST_0_9898_Q1_15); + } + else + { + nm1 = tot_nm & 0xFFFE; + L_tmp = L_shr(L_tmp, tot_nm - nm1); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm); + tot_nm = nm1 >> 1; + + nm1 = tot_nm & 0xFFFE; + L_tmp = L_shr(L_tmp, tot_nm - nm1); + L_tmp = sqrt_l_exp(L_tmp, &tot_nm); + L_tmp = L_shr(L_tmp, tot_nm); + L_tmp = L_mult(extract_h(L_tmp), CNST_0_9898_Q1_15); + tot_nm = nm1 >> 1; + tmp = extract_h(L_shr(L_tmp, tot_nm + 1)); + } + } + + if(tmp > CNST_1_2_Q2_14) + sa[i] = extract_h(L_shl(L_mult(sa[i], CNST_1_2_Q2_14), 1)); + else if(tmp < CNST_0_5_Q2_14) + sa[i] = shr(sa[i], 1); + else + sa[i] = extract_h(L_shl(L_mult(sa[i], tmp), 1)); + } + } + + // Compute the correct scale factor + v_equ_shr(sa_tmp, sa, nm, num_harm); + L_sum_mod = L_v_magsq(sa_tmp, num_harm); + if(L_sum_mod > Rm0) + { + tmp = div_s(extract_h(Rm0), extract_h(L_sum_mod)); + L_tmp = sqrt_l_exp(L_deposit_h(tmp), &tot_nm); + tmp = shr(extract_h(L_tmp), tot_nm); + for(i = 0; i < num_harm; i++) + sa[i] = mult_r(sa[i], tmp); + } +} + + + diff --git a/imbe_vocoder/sa_enh.h b/imbe_vocoder/sa_enh.h new file mode 100644 index 0000000..6b3f277 --- /dev/null +++ b/imbe_vocoder/sa_enh.h @@ -0,0 +1,50 @@ +/* + * 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 _SA_ENH +#define _SA_ENH + +#define CNST_0_9898_Q1_15 0x7EB3 +#define CNST_0_5_Q2_14 0x2000 +#define CNST_1_2_Q2_14 0x4CCC + + +//----------------------------------------------------------------------------- +// PURPOSE: +// Perform Spectral Amplitude Enhancement +// +// +// INPUT: +// IMBE_PARAM *imbe_param - pointer to IMBE_PARAM structure with +// valid num_harms, sa and fund_freq items +// +// OUTPUT: +// None +// +// RETURN: +// Enhanced Spectral Amplitudes +// +//----------------------------------------------------------------------------- +void sa_enh(IMBE_PARAM *imbe_param); + + +#endif diff --git a/imbe_vocoder/tbls.cc b/imbe_vocoder/tbls.cc new file mode 100644 index 0000000..1819c8f --- /dev/null +++ b/imbe_vocoder/tbls.cc @@ -0,0 +1,368 @@ +/* + * 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 "typedef.h" +#include "tbls.h" + + +//----------------------------------------------------------------------------- +// +// Bit allocation and ancillary tables +// +//----------------------------------------------------------------------------- +const UWord16 bit_allocation_tbl[] = +{ + 0xA999, 0x9987, + 0x9988, 0x8976, 0x5000, + 0x8887, 0x7976, 0x5400, + 0x8777, 0x7876, 0x5430, + 0x7776, 0x6776, 0x5433, + 0x7666, 0x6775, 0x4434, 0x3000, + 0x7666, 0x5675, 0x4433, 0x3300, + 0x6665, 0x5665, 0x4433, 0x3320, + 0x6655, 0x5555, 0x4443, 0x3232, + 0x6555, 0x5545, 0x5433, 0x3322, 0x2000, + 0x6554, 0x4545, 0x4433, 0x3323, 0x2100, + 0x6554, 0x4545, 0x4433, 0x2321, 0x3210, + 0x5554, 0x4445, 0x4433, 0x2232, 0x1321, + 0x5544, 0x4444, 0x4432, 0x3223, 0x2122, 0x1000, + 0x5444, 0x4434, 0x4343, 0x2322, 0x2212, 0x2100, + 0x5444, 0x4433, 0x4333, 0x3232, 0x1221, 0x2210, + 0x5444, 0x3433, 0x4333, 0x3232, 0x1221, 0x2111, + 0x5443, 0x3433, 0x4333, 0x2232, 0x1221, 0x1221, 0x1000, + 0x5443, 0x3432, 0x4323, 0x2232, 0x2122, 0x1122, 0x1100, + 0x4443, 0x3432, 0x4323, 0x2223, 0x2112, 0x2112, 0x1110, + 0x4443, 0x3332, 0x4322, 0x3222, 0x3211, 0x2111, 0x2111, + 0x4443, 0x3332, 0x2332, 0x2322, 0x1321, 0x1211, 0x1211, 0x1000, + 0x4433, 0x3332, 0x2332, 0x2322, 0x1221, 0x1211, 0x1211, 0x1100, + 0x4433, 0x3332, 0x2332, 0x2322, 0x1221, 0x1211, 0x1121, 0x1100, + 0x4333, 0x3332, 0x2332, 0x2321, 0x1221, 0x1121, 0x1112, 0x1111, + 0x4333, 0x3322, 0x2322, 0x2322, 0x1122, 0x1112, 0x1111, 0x2111, 0x0000, + 0x4333, 0x3322, 0x2322, 0x2232, 0x1112, 0x2111, 0x2111, 0x0211, 0x1000, + 0x4333, 0x3322, 0x2132, 0x2213, 0x2111, 0x2211, 0x1211, 0x1021, 0x1100, + 0x4333, 0x2322, 0x2132, 0x2223, 0x2111, 0x2111, 0x1211, 0x1021, 0x1110, + 0x4333, 0x2322, 0x2132, 0x2213, 0x2111, 0x2111, 0x1211, 0x1102, 0x1111, 0x0000, + 0x4333, 0x2322, 0x2132, 0x2213, 0x2111, 0x2211, 0x1021, 0x1110, 0x2111, 0x0000, + 0x4333, 0x2322, 0x2132, 0x2113, 0x2111, 0x1221, 0x1102, 0x1111, 0x0211, 0x1000, + 0x4332, 0x2322, 0x1132, 0x2211, 0x3211, 0x1122, 0x1110, 0x2111, 0x1021, 0x1100, + 0x4332, 0x2322, 0x2113, 0x2221, 0x1221, 0x1112, 0x2111, 0x0211, 0x1002, 0x1110, 0x0000, + 0x4332, 0x2322, 0x2113, 0x2221, 0x1221, 0x1112, 0x1111, 0x0211, 0x1002, 0x1111, 0x0000, + 0x4332, 0x2322, 0x1113, 0x2221, 0x1221, 0x1112, 0x1111, 0x0211, 0x1100, 0x2111, 0x1000, + 0x4332, 0x2322, 0x1113, 0x2211, 0x1221, 0x1112, 0x2111, 0x0021, 0x1110, 0x0211, 0x1100, + 0x3332, 0x2322, 0x1113, 0x2211, 0x1221, 0x1111, 0x2211, 0x1002, 0x1111, 0x0021, 0x1110, 0x0000, + 0x3332, 0x2322, 0x1113, 0x2211, 0x1122, 0x1111, 0x1221, 0x1100, 0x2111, 0x1002, 0x1110, 0x0000, + 0x3332, 0x2322, 0x1111, 0x3221, 0x1112, 0x2111, 0x1122, 0x1110, 0x0211, 0x1000, 0x2111, 0x0000, + 0x3332, 0x2322, 0x1111, 0x3221, 0x1112, 0x2111, 0x1022, 0x1110, 0x0211, 0x1000, 0x2111, 0x1000, + 0x3332, 0x2322, 0x1111, 0x3221, 0x1112, 0x2111, 0x1022, 0x1110, 0x0211, 0x1100, 0x0211, 0x1000, 0x0000, + 0x3332, 0x2322, 0x1111, 0x3211, 0x1112, 0x2111, 0x1022, 0x1110, 0x0021, 0x1110, 0x0021, 0x1110, 0x0000, + 0x3322, 0x2321, 0x1111, 0x3221, 0x1112, 0x2111, 0x1102, 0x2111, 0x0002, 0x1111, 0x0002, 0x1111, 0x0000, + 0x3322, 0x2321, 0x1111, 0x3221, 0x1111, 0x2211, 0x1110, 0x2211, 0x1000, 0x2111, 0x1000, 0x2111, 0x0000, + 0x3322, 0x2322, 0x1111, 0x0322, 0x1111, 0x0221, 0x1111, 0x0221, 0x1100, 0x0211, 0x1100, 0x0211, 0x1000, 0x0000, + 0x3322, 0x2322, 0x1111, 0x0322, 0x1111, 0x0221, 0x1111, 0x0221, 0x1100, 0x0211, 0x1000, 0x0211, 0x1100, 0x0000, + 0x3322, 0x2322, 0x1111, 0x0322, 0x1111, 0x0221, 0x1111, 0x0221, 0x1100, 0x0211, 0x1100, 0x0021, 0x1100, 0x0000 +}; + +const UWord16 bit_allocation_offset_tbl[] = +{ + 0x0002, 0x000E, 0x001E, 0x0032, 0x004A, 0x0066, 0x0086, 0x00AA, 0x00D2, 0x00FE, 0x012E, 0x0162 +}; + +//----------------------------------------------------------------------------- +// +// Log Magnitude Prediction Residual Block Length +// +//----------------------------------------------------------------------------- +const UWord32 lmprbl_tbl[] = +{ + 0x11122200, + 0x11222200, + 0x12222200, + 0x22222200, + 0x22222300, + 0x22223300, + 0x22233300, + 0x22333300, + 0x23333300, + 0x33333300, + 0x33333400, + 0x33334400, + 0x33344400, + 0x33444400, + 0x34444400, + 0x44444400, + 0x44444500, + 0x44445500, + 0x44455500, + 0x44555500, + 0x45555500, + 0x55555500, + 0x55555600, + 0x55556600, + 0x55566600, + 0x55666600, + 0x56666600, + 0x66666600, + 0x66666700, + 0x66667700, + 0x66677700, + 0x66777700, + 0x67777700, + 0x77777700, + 0x77777800, + 0x77778800, + 0x77788800, + 0x77888800, + 0x78888800, + 0x88888800, + 0x88888900, + 0x88889900, + 0x88899900, + 0x88999900, + 0x89999900, + 0x99999900, + 0x99999A00, + 0x9999AA00 +}; + + + +//----------------------------------------------------------------------------- +// +// Gain Quantizer Levels in signed Q5.11 format +// +//----------------------------------------------------------------------------- +const Word16 gain_qnt_tbl[] = +{ + -5821, -5518, -5239, -4880, -4549, -4292, -4057, -3760, -3370, -2903, + -2583, -2305, -1962, -1601, -1138, -711, -302, 57, 433, 795, + 1132, 1510, 1909, 2333, 2705, 3038, 3376, 3689, 3979, 4339, + 4754, 5129, 5435, 5695, 5991, 6300, 6596, 6969, 7342, 7751, + 8101, 8511, 8835, 9102, 9375, 9698, 10055, 10415, 10762, 11084, + 11403, 11752, 12123, 12468, 12863, 13239, 13615, 13997, 14382, 14770, + 15301, 15849, 16640, 17809 +}; + + +//----------------------------------------------------------------------------- +// +// Gain Ste Size in unsigned Q0.16 format +// +//----------------------------------------------------------------------------- +const UWord16 gain_step_size_tbl[] = +{ + 203, 263, 220, 190, 173, + 406, 263, 440, 380, 346, + 813, 527, 440, 760, 692, + 813, 1054, 881, 760, 692, + 1625, 1054, 881, 1425, 1298, + 1625, 1976, 1652, 1425, 1298, + 1625, 1976, 1652, 1425, 2422, + 3047, 1976, 1652, 2661, 2422, + 3047, 1976, 3083, 2661, 2422, + 3047, 3688, 3083, 2661, 2422, + 3047, 3688, 3083, 3801, 3460, + 3047, 3688, 3083, 3801, 3460, + 5689, 3688, 3083, 3801, 3460, + 5689, 3688, 4404, 3801, 3460, + 5689, 5269, 4404, 3801, 3460, + 5689, 5269, 4404, 3801, 3460, + 5689, 5269, 4404, 3801, 5623, + 5689, 5269, 4404, 6177, 5623, + 5689, 5269, 4404, 6177, 5623, + 8126, 5269, 4404, 6177, 5623, + 8126, 5269, 4404, 6177, 5623, + 8126, 5269, 4404, 6177, 5623, + 8126, 5269, 7157, 6177, 5623, + 8126, 5269, 7157, 6177, 5623, + 8126, 8562, 7157, 6177, 5623, + 8126, 8562, 7157, 6177, 5623, + 8126, 8562, 7157, 6177, 5623, + 8126, 8562, 7157, 6177, 5623, + 8126, 8562, 7157, 6177, 7353, + 8126, 8562, 7157, 6177, 7353, + 8126, 8562, 7157, 6177, 7353, + 8126, 8562, 7157, 6177, 7353, + 8126, 8562, 7157, 8077, 7353, + 8126, 8562, 7157, 8077, 7353, + 8126, 8562, 7157, 8077, 7353, + 8126, 8562, 7157, 8077, 7353, + 8126, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 7157, 8077, 7353, + 13206, 8562, 9359, 8077, 7353, + 13206, 8562, 9359, 8077, 7353, + 13206, 8562, 9359, 8077, 7353, + 13206, 8562, 9359, 8077, 7353, + 13206, 8562, 9359, 8077, 7353 +}; + + +//----------------------------------------------------------------------------- +// +// Standard Deviation of Higher Order DCT Coefficients in unsigned Q0.16 format +// +//----------------------------------------------------------------------------- +const UWord16 hi_ord_std_tbl[] = +{ + 20120, 15794, 13566, 12452, 11731, 11338, 10813, 11141, 11141 +}; + +//----------------------------------------------------------------------------- +// +// Quantizer Step for Higher Order DCT Coefficients in unsigned Q1.15 format +// +//----------------------------------------------------------------------------- +const UWord16 hi_ord_step_size_tbl[] = +{ + 39322, 27853, 21299, 13107, 9175, 4915, 2621, 1311, 655, 328 +}; + +//----------------------------------------------------------------------------- +// +// Speech Synthesis Window +// +//----------------------------------------------------------------------------- +const Word16 ws[49] = +{ + 655, 1310, 1966, 2621, 3276, 3932, 4587, 5242, 5898, 6553, + 7208, 7864, 8519, 9175, 9830, 10485, 11141, 11796, 12451, 13107, + 13762, 14417, 15073, 15728, 16384, 17039, 17694, 18350, 19005, 19660, + 20316, 20971, 21626, 22282, 22937, 23592, 24248, 24903, 25559, 26214, + 26869, 27525, 28180, 28835, 29491, 30146, 30801, 31457, 32112 +}; + +/* +const Word16 ws_ws[49] = +{ + + 17052, 17746, 18467, 19212, 19980, 20770, 21580, 22407, 23246, 24094, + 24945, 25793, 26631, 27453, 28248, 29008, 29724, 30385, 30983, 31507, + 31950, 32302, 32559, 32715, 32767, 32715, 32559, 32302, 31950, 31507, + 30983, 30385, 29724, 29008, 28248, 27453, 26631, 25793, 24945, 24094, + 23246, 22407, 21580, 20770, 19980, 19212, 18467, 17746, 17052 +}; +*/ + +//----------------------------------------------------------------------------- +// +// Squared Pitch Estimation Window 64*wi^2 +// +//----------------------------------------------------------------------------- +const Word16 wi[301] = +{ + 15, 18, 21, 25, 29, 34, 40, 46, 52, 59, + 67, 76, 86, 96, 108, 120, 133, 148, 164, 180, + 199, 218, 239, 261, 285, 311, 338, 367, 398, 431, + 465, 502, 541, 582, 625, 671, 719, 769, 822, 878, + 936, 997, 1061, 1128, 1198, 1271, 1347, 1426, 1508, 1594, + 1683, 1775, 1871, 1970, 2073, 2179, 2289, 2403, 2520, 2641, + 2766, 2894, 3026, 3162, 3301, 3445, 3592, 3742, 3897, 4055, + 4216, 4382, 4551, 4723, 4899, 5078, 5261, 5447, 5636, 5828, + 6023, 6221, 6423, 6626, 6833, 7042, 7253, 7467, 7683, 7900, + 8120, 8341, 8564, 8788, 9014, 9241, 9468, 9696, 9925, 10154, + 10383, 10613, 10842, 11070, 11298, 11525, 11752, 11977, 12200, 12422, + 12642, 12860, 13076, 13289, 13500, 13708, 13912, 14114, 14312, 14506, + 14696, 14882, 15064, 15242, 15414, 15582, 15745, 15903, 16055, 16202, + 16343, 16478, 16608, 16731, 16848, 16958, 17062, 17159, 17250, 17333, + 17410, 17480, 17542, 17597, 17646, 17686, 17720, 17746, 17764, 17776, + 17779, 17776, 17764, 17746, 17720, 17686, 17646, 17597, 17542, 17480, + 17410, 17333, 17250, 17159, 17062, 16958, 16848, 16731, 16608, 16478, + 16343, 16202, 16055, 15903, 15745, 15582, 15414, 15242, 15064, 14882, + 14696, 14506, 14312, 14114, 13912, 13708, 13500, 13289, 13076, 12860, + 12642, 12422, 12200, 11977, 11752, 11525, 11298, 11070, 10842, 10613, + 10383, 10154, 9925, 9696, 9468, 9241, 9014, 8788, 8564, 8341, + 8120, 7900, 7683, 7467, 7253, 7042, 6833, 6626, 6423, 6221, + 6023, 5828, 5636, 5447, 5261, 5078, 4899, 4723, 4551, 4382, + 4216, 4055, 3897, 3742, 3592, 3445, 3301, 3162, 3026, 2894, + 2766, 2641, 2520, 2403, 2289, 2179, 2073, 1970, 1871, 1775, + 1683, 1594, 1508, 1426, 1347, 1271, 1198, 1128, 1061, 997, + 936, 878, 822, 769, 719, 671, 625, 582, 541, 502, + 465, 431, 398, 367, 338, 311, 285, 261, 239, 218, + 199, 180, 164, 148, 133, 120, 108, 96, 86, 76, + 67, 59, 52, 46, 40, 34, 29, 25, 21, 18, + 15 +}; + +//----------------------------------------------------------------------------- +// +// Pitch Refinement Window +// +//----------------------------------------------------------------------------- +const Word16 wr[] = +{ + 487, 570, 658, 753, 854, 962, 1076, 1197, 1325, 1460, + 1602, 1752, 1909, 2074, 2246, 2426, 2614, 2810, 3014, 3227, + 3447, 3675, 3912, 4157, 4410, 4671, 4941, 5219, 5505, 5799, + 6101, 6411, 6729, 7054, 7388, 7728, 8077, 8432, 8795, 9164, + 9541, 9923, 10312, 10707, 11108, 11515, 11927, 12344, 12766, 13192, + 13622, 14056, 14494, 14935, 15379, 15825, 16273, 16724, 17175, 17628, + 18081, 18534, 18988, 19440, 19892, 20342, 20790, 21237, 21680, 22120, + 22557, 22990, 23419, 23842, 24261, 24673, 25080, 25480, 25874, 26259, + 26638, 27008, 27370, 27722, 28066, 28400, 28724, 29037, 29340, 29632, + 29912, 30181, 30438, 30683, 30915, 31135, 31341, 31535, 31715, 31881, + 32033, 32172, 32296, 32406, 32502, 32583, 32649, 32701, 32738, 32760, +}; + +//----------------------------------------------------------------------------- +// +// Real Part Spectrum of Pitch Refinement Window * 256 +// +//----------------------------------------------------------------------------- +const Word16 wr_sp[] = +{ + 16, 43, 71, 102, 135, 170, 207, 247, 289, 333, + 380, 430, 483, 538, 596, 657, 721, 787, 857, 930, + 1006, 1085, 1168, 1254, 1343, 1435, 1531, 1630, 1733, 1840, + 1950, 2063, 2181, 2302, 2426, 2555, 2687, 2823, 2962, 3106, + 3253, 3404, 3559, 3718, 3881, 4047, 4218, 4392, 4570, 4751, + 4937, 5126, 5319, 5516, 5716, 5920, 6128, 6339, 6554, 6772, + 6994, 7219, 7447, 7679, 7914, 8152, 8393, 8637, 8884, 9134, + 9387, 9642, 9900, 10160, 10423, 10688, 10956, 11225, 11497, 11770, + 12045, 12322, 12601, 12881, 13162, 13444, 13728, 14012, 14298, 14584, + 14871, 15158, 15445, 15733, 16020, 16308, 16595, 16882, 17168, 17454, + 17738, 18022, 18305, 18586, 18866, 19145, 19421, 19696, 19969, 20240, + 20508, 20774, 21037, 21298, 21556, 21811, 22062, 22310, 22555, 22796, + 23033, 23267, 23496, 23722, 23943, 24159, 24372, 24579, 24782, 24980, + 25172, 25360, 25542, 25719, 25891, 26057, 26217, 26372, 26520, 26663, + 26800, 26930, 27055, 27173, 27285, 27390, 27489, 27581, 27667, 27746, + 27818, 27884, 27942, 27994, 28039, 28078, 28109, 28133, 28151, 28161, + 28165, 28161, 28151, 28133, 28109, 28078, 28039, 27994, 27942, 27884, + 27818, 27746, 27667, 27581, 27489, 27390, 27285, 27173, 27055, 26930, + 26800, 26663, 26520, 26372, 26217, 26057, 25891, 25719, 25542, 25360, + 25172, 24980, 24782, 24579, 24372, 24159, 23943, 23722, 23496, 23267, + 23033, 22796, 22555, 22310, 22062, 21811, 21556, 21298, 21037, 20774, + 20508, 20240, 19969, 19696, 19421, 19145, 18866, 18586, 18305, 18022, + 17738, 17454, 17168, 16882, 16595, 16308, 16020, 15733, 15445, 15158, + 14871, 14584, 14298, 14012, 13728, 13444, 13162, 12881, 12601, 12322, + 12045, 11770, 11497, 11225, 10956, 10688, 10423, 10160, 9900, 9642, + 9387, 9134, 8884, 8637, 8393, 8152, 7914, 7679, 7447, 7219, + 6994, 6772, 6554, 6339, 6128, 5920, 5716, 5516, 5319, 5126, + 4937, 4751, 4570, 4392, 4218, 4047, 3881, 3718, 3559, 3404, + 3253, 3106, 2962, 2823, 2687, 2555, 2426, 2302, 2181, 2063, + 1950, 1840, 1733, 1630, 1531, 1435, 1343, 1254, 1168, 1085, + 1006, 930, 857, 787, 721, 657, 596, 538, 483, 430, + 380, 333, 289, 247, 207, 170, 135, 102, 71, 43, + 16 +}; + diff --git a/imbe_vocoder/tbls.h b/imbe_vocoder/tbls.h new file mode 100644 index 0000000..fd0ade4 --- /dev/null +++ b/imbe_vocoder/tbls.h @@ -0,0 +1,99 @@ +/* + * 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 _TBLS +#define _TBLS + + +//----------------------------------------------------------------------------- +// +// Bit allocation and ancillary tables +// +//----------------------------------------------------------------------------- +extern const UWord16 bit_allocation_tbl[]; +extern const UWord16 bit_allocation_offset_tbl[]; + +//----------------------------------------------------------------------------- +// +// Log Magnitude Prediction Residual Block Length +// +//----------------------------------------------------------------------------- +extern const UWord32 lmprbl_tbl[]; + +//----------------------------------------------------------------------------- +// +// Gain Quantizer Levels in Q5.11 format +// +//----------------------------------------------------------------------------- +extern const Word16 gain_qnt_tbl[]; +#define GAIN_QNT_TBL_SIZE 64 + +//----------------------------------------------------------------------------- +// +// Gain Ste Size in unsigned Q0.16 format +// +//----------------------------------------------------------------------------- +extern const UWord16 gain_step_size_tbl[]; + +//----------------------------------------------------------------------------- +// +// Standard Deviation of Higher Order DCT Coefficients in unsigned Q0.16 format +// +//----------------------------------------------------------------------------- +extern const UWord16 hi_ord_std_tbl[]; + +//----------------------------------------------------------------------------- +// +// Quantizer Step for Higher Order DCT Coefficients in unsigned Q1.15 format +// +//----------------------------------------------------------------------------- +extern const UWord16 hi_ord_step_size_tbl[]; + +//----------------------------------------------------------------------------- +// +// Speech Synthesis Window +// +//----------------------------------------------------------------------------- +extern const Word16 ws[]; + +//----------------------------------------------------------------------------- +// +// Squared Pitch Estimation Window 64*wi^2 +// +//----------------------------------------------------------------------------- +extern const Word16 wi[]; + +//----------------------------------------------------------------------------- +// +// Pitch Refinement Window +// +//----------------------------------------------------------------------------- +extern const Word16 wr[]; + +//----------------------------------------------------------------------------- +// +// Real Part Spectrum of Pitch Refinement Window * 256 +// +//----------------------------------------------------------------------------- +extern const Word16 wr_sp[]; + +#endif + diff --git a/imbe_vocoder/typedef.h b/imbe_vocoder/typedef.h new file mode 100644 index 0000000..fcf3b4c --- /dev/null +++ b/imbe_vocoder/typedef.h @@ -0,0 +1,74 @@ +/* + * 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. + */ +/* +******************************************************************************** +* +* GSM AMR speech codec Version 7.4.0 January 31, 2000 +* +******************************************************************************** +* +* File : typedef.c +* Purpose : Basic types. +* +******************************************************************************** +*/ +#ifndef typedef_h +#define typedef_h "$Id $" + +#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version + of typedef.h */ + +#ifdef ORIGINAL_TYPEDEF_H +/* + * this is the original code from the ETSI file typedef.h + */ + +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__sun) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef int Flag; + +#elif defined(__unix__) || defined(__unix) +typedef signed char Word8; +typedef short Word16; +typedef int Word32; +typedef int Flag; + +#endif +#else /* not original typedef.h */ + +/* + * use (improved) type definition file typdefs.h and add a "Flag" type + */ +#include "typedefs.h" +typedef int Flag; + +#endif + +#endif + diff --git a/imbe_vocoder/typedefs.h b/imbe_vocoder/typedefs.h new file mode 100644 index 0000000..45fe1a0 --- /dev/null +++ b/imbe_vocoder/typedefs.h @@ -0,0 +1,201 @@ +/* + * 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. + */ +/* +******************************************************************************** +* +* GSM AMR speech codec Version 7.4.0 January 31, 2000 +* +******************************************************************************** +* +* File : typedefs.h +* Description : Definition of platform independent data +* types and constants +* +* +* The following platform independent data types and corresponding +* preprocessor (#define) constants are defined: +* +* defined type meaning corresponding constants +* ---------------------------------------------------------- +* Char character (none) +* Bool boolean true, false +* Word8 8-bit signed minWord8, maxWord8 +* UWord8 8-bit unsigned minUWord8, maxUWord8 +* Word16 16-bit signed minWord16, maxWord16 +* UWord16 16-bit unsigned minUWord16, maxUWord16 +* Word32 32-bit signed minWord32, maxWord32 +* UWord32 32-bit unsigned minUWord32, maxUWord32 +* Float floating point minFloat, maxFloat +* +* +* The following compile switches are #defined: +* +* PLATFORM string indicating platform progam is compiled on +* possible values: "OSF", "PC", "SUN" +* +* OSF only defined if the current platform is an Alpha +* PC only defined if the current platform is a PC +* SUN only defined if the current platform is a Sun +* +* LSBFIRST is defined if the byte order on this platform is +* "least significant byte first" -> defined on DEC Alpha +* and PC, undefined on Sun +* +******************************************************************************** +*/ +#ifndef typedefs_h +#define typedefs_h "$Id $" + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include +#include + +#define __MSDOS__ + +/* +******************************************************************************** +* DEFINITION OF CONSTANTS +******************************************************************************** +*/ +/* + ********* define char type + */ +typedef char Char; + +/* + ********* define 8 bit signed/unsigned types & constants + */ +#if SCHAR_MAX == 127 +typedef signed char Word8; +#define minWord8 SCHAR_MIN +#define maxWord8 SCHAR_MAX + +typedef unsigned char UWord8; +#define minUWord8 0 +#define maxUWord8 UCHAR_MAX +#else +#error cannot find 8-bit type +#endif + + +/* + ********* define 16 bit signed/unsigned types & constants + */ +#if INT_MAX == 32767 +typedef int Word16; +#define minWord16 INT_MIN +#define maxWord16 INT_MAX +typedef unsigned int UWord16; +#define minUWord16 0 +#define maxUWord16 UINT_MAX +#elif SHRT_MAX == 32767 +typedef short Word16; +#define minWord16 SHRT_MIN +#define maxWord16 SHRT_MAX +typedef unsigned short UWord16; +#define minUWord16 0 +#define maxUWord16 USHRT_MAX +#else +#error cannot find 16-bit type +#endif + + +/* + ********* define 32 bit signed/unsigned types & constants + */ +#if INT_MAX == 2147483647 +typedef int Word32; +#define minWord32 INT_MIN +#define maxWord32 INT_MAX +typedef unsigned int UWord32; +#define minUWord32 0 +#define maxUWord32 UINT_MAX +#elif LONG_MAX == 2147483647 +typedef long Word32; +#define minWord32 LONG_MIN +#define maxWord32 LONG_MAX +typedef unsigned long UWord32; +#define minUWord32 0 +#define maxUWord32 ULONG_MAX +#else +#error cannot find 32-bit type +#endif + +/* + ********* define floating point type & constants + */ +/* use "#if 0" below if Float should be double; + use "#if 1" below if Float should be float + */ +#if 0 +typedef float Float; +#define maxFloat FLT_MAX +#define minFloat FLT_MIN +#else +typedef double Float; +#define maxFloat DBL_MAX +#define minFloat DBL_MIN +#endif + +/* + ********* define complex type + */ +typedef struct { + Float r; /* real part */ + Float i; /* imaginary part */ +} CPX; + +/* + ********* define boolean type + */ +typedef int Bool; +#define false 0 +#define true 1 + +/* + ********* Check current platform + */ +#if defined(__MSDOS__) +#define PC +#define PLATFORM "PC" +#define LSBFIRST +#elif defined(__osf__) +#define OSF +#define PLATFORM "OSF" +#define LSBFIRST +#elif defined(__sun__) || defined(__sun) +#define SUN +#define PLATFORM "SUN" +#undef LSBFIRST +#elif defined(linux) && defined(i386) +#define PC +#define PLATFORM "PC" +#define LSBFIRST +#else +#error "can't determine architecture; adapt typedefs.h to your platform" +#endif + +#endif + diff --git a/imbe_vocoder/uv_synt.cc b/imbe_vocoder/uv_synt.cc new file mode 100644 index 0000000..2c319d9 --- /dev/null +++ b/imbe_vocoder/uv_synt.cc @@ -0,0 +1,147 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "imbe.h" +#include "aux_sub.h" +#include "dsp_sub.h" +#include "math_sub.h" +#include "uv_synt.h" +#include "rand_gen.h" +#include "tbls.h" +#include "encode.h" +#include "imbe_vocoder_impl.h" + + + + +void imbe_vocoder_impl::uv_synt_init(void) +{ + fft_init(); + v_zap(uv_mem, 105); +} + + + + + + +void imbe_vocoder_impl::uv_synt(IMBE_PARAM *imbe_param, Word16 *snd) +{ + Cmplx16 Uw[FFTLENGTH]; + Word16 i, index_a, index_b, index_aux, ha, hb, *v_uv_dsn_ptr, *sa_ptr, sa; + Word32 fund_freq, fund_freq_2, fund_freq_acc_a, fund_freq_acc_b; + + sa_ptr = imbe_param->sa; + v_uv_dsn_ptr = imbe_param->v_uv_dsn; + fund_freq = imbe_param->fund_freq; + fund_freq_2 = L_shr(fund_freq, 1); + + v_zap((Word16 *)&Uw, 2 * FFTLENGTH); + + fund_freq_acc_a = L_sub(fund_freq, fund_freq_2); + fund_freq_acc_b = L_add(fund_freq, fund_freq_2); + + for(i = 0; i < imbe_param->num_harms; i++) + { + ha = extract_h(fund_freq_acc_a); + hb = extract_h(fund_freq_acc_b); + index_a = (ha >> 8) + ((ha & 0xFF)?1:0); + index_b = (hb >> 8) + ((hb & 0xFF)?1:0); + + index_aux = 256 - index_a; + + sa = shl(*sa_ptr, 3); + + if(*v_uv_dsn_ptr++) + { + while(index_a < index_b) + { + Uw[index_a].re = Uw[index_a].im = 0; + Uw[index_aux].re = Uw[index_aux].im = 0; + index_a++; + index_aux--; + } + } + else + { + while(index_a < index_b) + { + Uw[index_a].re = mult(sa, rand_gen()); + Uw[index_a].im = mult(sa, rand_gen()); + //Uw[index_a].re = sa; + //Uw[index_a].im = sa; + + Uw[index_aux].re = Uw[index_a].re; + Uw[index_aux].im = negate(Uw[index_a].im); + index_a++; + index_aux--; + } + } + + fund_freq_acc_a = L_add(fund_freq_acc_a, fund_freq); + fund_freq_acc_b = L_add(fund_freq_acc_b, fund_freq); + sa_ptr++; + } + +/* + j = 128; + for(i = 0; i < 128; i++) + Uw_tmp[j++] = Uw[i]; + + j = 128; + for(i = 0; i < 128; i++) + Uw_tmp[i] = Uw[j++]; + + for(i = 0; i < 256; i++) + Uw[i] = Uw_tmp[i]; +*/ + + + fft((Word16 *)&Uw, FFTLENGTH, -1); + + for(i = 0; i < 105; i++) + snd[i] = uv_mem[i]; + + index_aux = 73; + for(i = 105; i < FRAME; i++) + snd[i] = shl(Uw[index_aux++].re, 3); + + + // Weighted Overlap Add Algorithm + index_aux = 24; + index_a = 0; + index_b = 48; + for(i = 56; i < 105; i++) + { + snd[i] = extract_h(L_add(L_mult(snd[i], ws[index_b]), L_mult(shl(Uw[index_aux].re, 3), ws[index_a]))); + + index_aux++; + index_a++; + index_b--; + } + + index_aux = 128; + for(i = 0; i < 105; i++) + uv_mem[i] = shl(Uw[index_aux++].re, 3); +} + diff --git a/imbe_vocoder/uv_synt.h b/imbe_vocoder/uv_synt.h new file mode 100644 index 0000000..ef04cb7 --- /dev/null +++ b/imbe_vocoder/uv_synt.h @@ -0,0 +1,29 @@ +/* + * 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 _UV_SYNT +#define _UV_SYNT + +void uv_synt_init(void); +void uv_synt(IMBE_PARAM *imbe_param, Word16 *snd); +void fft(Word16 *datam1, Word16 nn, Word16 isign); + +#endif diff --git a/imbe_vocoder/v_synt.cc b/imbe_vocoder/v_synt.cc new file mode 100644 index 0000000..13b63a2 --- /dev/null +++ b/imbe_vocoder/v_synt.cc @@ -0,0 +1,248 @@ +/* + * 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 "typedef.h" +#include "basic_op.h" +#include "imbe.h" +#include "aux_sub.h" +#include "dsp_sub.h" +#include "math_sub.h" +#include "v_synt.h" +#include "rand_gen.h" +#include "tbls.h" +#include "encode.h" +#include "imbe_vocoder_impl.h" + + + + + + +#define CNST_0_1_Q1_15 0x0CCD + + + +void imbe_vocoder_impl::v_synt_init(void) +{ + Word16 i; + + for(i = 0; i < NUM_HARMS_MAX; i++) + { + ph_mem[i] = L_deposit_h(rand_gen()); + vu_dsn_prev[i] = 0; + } + + num_harms_prev3 = 0; + fund_freq_prev = 0; +} + + +void imbe_vocoder_impl::v_synt(IMBE_PARAM *imbe_param, Word16 *snd) +{ + Word32 L_tmp, L_tmp1, fund_freq, L_snd[FRAME], L_ph_acc, L_ph_step; + Word32 L_ph_acc_aux, L_ph_step_prev, L_amp_acc, L_amp_step, L_ph_step_aux; + Word16 num_harms, i, j, *vu_dsn, *sa, *s_ptr, *s_ptr_aux, num_harms_max, num_harms_max_4; + UWord32 ph_mem_prev[NUM_HARMS_MAX], dph[NUM_HARMS_MAX]; + Word16 num_harms_inv, num_harms_sh, num_uv; + Word16 freq_flag; + + + fund_freq = imbe_param->fund_freq; + num_harms = imbe_param->num_harms; + vu_dsn = imbe_param->v_uv_dsn; + sa = imbe_param->sa; + num_harms_inv = imbe_param->div_one_by_num_harm; + num_harms_sh = imbe_param->div_one_by_num_harm_sh; + num_uv = imbe_param->l_uv; + + for(i = 0; i < FRAME; i++) + L_snd[i] = 0; + + // Update phases (calculated phase value correspond to bound of frame) + L_tmp = (((fund_freq_prev + fund_freq) >> 7) * FRAME/2) << 7; // It is performed integer multiplication by mod 1 + + L_ph_acc = 0; + for(i = 0; i < NUM_HARMS_MAX; i++) + { + ph_mem_prev[i] = ph_mem[i]; + L_ph_acc += L_tmp; + ph_mem[i] += L_ph_acc; + dph[i] = 0; + } + + num_harms_max = (num_harms >= num_harms_prev3)?num_harms:num_harms_prev3; + num_harms_max_4 = num_harms_max >> 2; + + if(L_abs(L_sub(fund_freq, fund_freq_prev)) >= L_mpy_ls(fund_freq, CNST_0_1_Q1_15)) + freq_flag = 1; + else + freq_flag = 0; + + L_ph_step = L_ph_step_prev = 0; + for(i = 0; i < num_harms_max; i++) + { + L_ph_step += fund_freq; + L_ph_step_prev += fund_freq_prev; + + + if(i > num_harms_max_4) + { + if(num_uv == num_harms) + { + dph[i] = L_deposit_h(rand_gen()); + } + else + { + L_tmp = L_mult(rand_gen(), num_harms_inv); + dph[i] = L_shr(L_tmp, 15 - num_harms_sh) * num_uv; + } + ph_mem[i] += dph[i]; + } + + if(vu_dsn[i] == 0 && vu_dsn_prev[i] == 0) + continue; + + if(vu_dsn[i] == 1 && vu_dsn_prev[i] == 0) // unvoiced => voiced + { + s_ptr = (Word16 *)ws; + L_ph_acc = ph_mem[i] - (((L_ph_step >> 7) * 104) << 7); + for(j = 56; j <= 104; j++) + { + L_tmp = L_mult(*s_ptr++, sa[i]); + L_tmp = L_mpy_ls(L_tmp, cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc += L_ph_step; + } + + for(j = 105; j <= 159; j++) + { + L_tmp = L_mult(sa[i], cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc += L_ph_step; + } + continue; + } + + + if(vu_dsn[i] == 0 && vu_dsn_prev[i] == 1) // voiced => unvoiced + { + s_ptr = (Word16 *)&ws[48]; + L_ph_acc = ph_mem_prev[i]; + + for(j = 0; j <= 55; j++) + { + L_tmp = L_mult(sa_prev3[i], cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc += L_ph_step_prev; + } + + for(j = 56; j <= 104; j++) + { + L_tmp = L_mult(*s_ptr--, sa_prev3[i]); + L_tmp = L_mpy_ls(L_tmp, cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc += L_ph_step_prev; + } + continue; + } + + if(i >=7 || freq_flag) + { + s_ptr_aux = (Word16 *)&ws[48]; + L_ph_acc_aux = ph_mem_prev[i]; + + s_ptr = (Word16 *)ws; + L_ph_acc = ph_mem[i] - (((L_ph_step >> 7) * 104) << 7); + + for(j = 0; j <= 55; j++) + { + L_tmp = L_mult(sa_prev3[i], cos_fxp(extract_h(L_ph_acc_aux))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc_aux += L_ph_step_prev; + } + + for(j = 56; j <= 104; j++) + { + L_tmp = L_mult(*s_ptr_aux--, sa_prev3[i]); + L_tmp = L_mpy_ls(L_tmp, cos_fxp(extract_h(L_ph_acc_aux))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + + L_tmp = L_mult(*s_ptr++, sa[i]); + L_tmp = L_mpy_ls(L_tmp, cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + + L_ph_acc_aux += L_ph_step_prev; + L_ph_acc += L_ph_step; + } + + for(j = 105; j <= 159; j++) + { + L_tmp = L_mult(sa[i], cos_fxp(extract_h(L_ph_acc))); + L_tmp = L_shr(L_tmp, 1); + L_snd[j] = L_add(L_snd[j], L_tmp); + L_ph_acc += L_ph_step; + } + continue; + } + + L_amp_step = L_mpy_ls(L_shr(L_deposit_h(sub(sa[i], sa_prev3[i])), 4 + 1), CNST_0_1_Q1_15); // (sa[i] - sa_prev3[i]) / 160, 1/160 = 0.1/16 + L_amp_acc = L_shr(L_deposit_h(sa_prev3[i]), 1); + + + L_ph_step_aux = L_mpy_ls(L_shr(fund_freq - fund_freq_prev, 4 + 1), CNST_0_1_Q1_15); // (fund_freq - fund_freq_prev)/(2*160) + L_ph_step_aux = ((L_ph_step_aux >> 7) * (i + 1)) << 7; + + L_ph_acc = ph_mem_prev[i]; + + L_tmp1 = L_mpy_ls(L_shr(dph[i], 4), CNST_0_1_Q1_15); // dph[i] / 160 + + for(j = 0; j < 160; j++) + { + L_ph_acc_aux = ((L_ph_step_aux >> 9) * j) << 9; + L_ph_acc_aux = ((L_ph_acc_aux >> 9) * j) << 9; + + L_tmp = L_mpy_ls(L_amp_acc, cos_fxp(extract_h(L_ph_acc + L_ph_acc_aux))); + L_snd[j] = L_add(L_snd[j], L_tmp); + + L_amp_acc = L_add(L_amp_acc, L_amp_step); + L_ph_acc += L_ph_step_prev; + L_ph_acc += L_tmp1; + } + } + + for(i = 0; i < FRAME; i++) + *snd++ = extract_h(L_snd[i]); + + v_zap(vu_dsn_prev, NUM_HARMS_MAX); + v_equ(vu_dsn_prev, imbe_param->v_uv_dsn, num_harms); + v_equ(sa_prev3, imbe_param->sa, num_harms); + + num_harms_prev3 = num_harms; + fund_freq_prev = fund_freq; +} diff --git a/imbe_vocoder/v_synt.h b/imbe_vocoder/v_synt.h new file mode 100644 index 0000000..2139fb2 --- /dev/null +++ b/imbe_vocoder/v_synt.h @@ -0,0 +1,30 @@ +/* + * 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 _V_SYNT +#define _V_SYNT + +void v_synt_init(void); +void v_synt(IMBE_PARAM *imbe_param, Word16 *snd); + + +#endif diff --git a/imbe_vocoder/v_uv_det.cc b/imbe_vocoder/v_uv_det.cc new file mode 100644 index 0000000..bf721cf --- /dev/null +++ b/imbe_vocoder/v_uv_det.cc @@ -0,0 +1,373 @@ +/* + * 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 "typedef.h" +#include "globals.h" +#include "imbe.h" +#include "basic_op.h" +#include "aux_sub.h" +#include "math_sub.h" +#include "dsp_sub.h" +#include "tbls.h" +#include "v_uv_det.h" + +#include +#include +#include +#include "encode.h" +#include "imbe_vocoder_impl.h" + + +#define CNST_0_5625_Q1_15 0x4800 +#define CNST_0_45_Q1_15 0x3999 +#define CNST_0_1741_Q1_15 0x164A +#define CNST_0_1393_Q1_15 0x11D5 +#define CNST_0_99_Q1_15 0x7EB8 +#define CNST_0_01_Q1_15 0x0148 +#define CNST_0_0025_Q1_15 0x0051 +#define CNST_0_25_Q1_15 0x2000 +#define CNST_PI_4_Q1_15 0x6488 +#define CNST_0_55_Q4_12 0x08CD + + + + + + + +extern FILE *fp_in, *fp_out; +extern int frame_cnt; + + +void imbe_vocoder_impl::pitch_ref_init(void) +{ + v_zap(v_uv_dsn, NUM_BANDS_MAX); + th_max = 0; +} + +Word16 imbe_vocoder_impl::voiced_sa_calc(Word32 num, Word16 den) +{ + Word16 tmp; + Word32 L_tmp; + + L_tmp = L_mpy_ls(num, den); + L_tmp = sqrt_l_exp(L_tmp, &tmp); + L_tmp = L_shr(L_tmp, tmp - 3); + + //L_tmp =0; + //return (Word16)(2*256.0*sqrt(2*(double)num/(double)den)); + return extract_h(L_tmp); +} + +Word16 imbe_vocoder_impl::unvoiced_sa_calc(Word32 num, Word16 den) +{ + Word16 shift, tmp; + Word32 L_tmp; + + shift = norm_s(den); + tmp = div_s(0x4000, shl(den, shift)); + L_tmp = L_shl(L_mpy_ls(num, tmp), shift + 2); + L_tmp = sqrt_l_exp(L_tmp, &tmp); + L_tmp = L_shr(L_tmp, tmp - 2 + 6); + L_tmp = L_mpy_ls(L_tmp, 0x4A76); + + //L_tmp =0; + //return (Word16)(2*0.1454 * sqrt(2*256*(double)num/(double)den)); + return extract_h(L_tmp); +} + +//============================================================================= +// +// Voiced/Unvoiced Determination & Spectral Amplitudes Estimation +// +//============================================================================= +void imbe_vocoder_impl::v_uv_det(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf) +{ + Word16 i, j, index_a_save, tmp, index_wr; + Word32 fund_freq, fund_freq_2, fund_freq_acc_a, fund_freq_acc_b, fund_freq_acc, fund_fr_acc, L_tmp, amp_re_acc, amp_im_acc; + Word16 ha, hb, index_a, index_b, index_tbl[30], it_ind, re_tmp, im_tmp, re_tmp2, im_tmp2, sc_coef; + Word32 Sw_sum, M_num[NUM_HARMS_MAX], M_num_sum, M_den_sum, D_num, D_den, th_lf, th_hf, th0, fund_fr_step, M_fcn_num, M_fcn_den; + Word16 sp_rec_re, sp_rec_im, M_fcn; + Word16 band_cnt, num_harms_cnt, uv_harms_cnt, Dk; + Word16 num_harms, num_bands, dsn_thr=0; + Word16 thr[NUM_BANDS_MAX], M_den[NUM_HARMS_MAX], b1_vec; + + + fund_freq = imbe_param->fund_freq; + + tmp = shr( add( shr(imbe_param->ref_pitch, 1), CNST_0_25_Q8_8), 8); // fix(pitch_cand / 2 + 0.5) + num_harms = extract_h((UWord32)CNST_0_9254_Q0_16 * tmp); // fix(0.9254 * fix(pitch_cand / 2 + 0.5)) + if(num_harms < NUM_HARMS_MIN) + num_harms = NUM_HARMS_MIN; + else if(num_harms > NUM_HARMS_MAX) + num_harms = NUM_HARMS_MAX; + + if(num_harms <= 36) + num_bands = extract_h((UWord32)(num_harms + 2) * CNST_0_33_Q0_16); // fix((L+2)/3) + else + num_bands = NUM_BANDS_MAX; + + imbe_param->num_harms = num_harms; + imbe_param->num_bands = num_bands; + + //========================================================================= + // + // M(th) function calculation + // + //========================================================================= + for(j = 0, th_lf = 0; j < 64; j++) + { + th_lf = L_mac(th_lf, fft_buf[j].re, fft_buf[j].re); + th_lf = L_mac(th_lf, fft_buf[j].im, fft_buf[j].im); + } + for(j = 64, th_hf = 0; j < 128; j++) + { + th_hf = L_mac(th_hf, fft_buf[j].re, fft_buf[j].re); + th_hf = L_mac(th_hf, fft_buf[j].im, fft_buf[j].im); + } + th0 = L_add(th_lf, th_hf); + + if(th0 > th_max) + th_max = L_shr(L_add(th_max, th0), 1); + else + th_max = L_add(L_mpy_ls(th_max, CNST_0_99_Q1_15), L_mpy_ls(th0, CNST_0_01_Q1_15)); + + M_fcn_num = L_add(th0, L_mpy_ls(th_max, CNST_0_0025_Q1_15)); + M_fcn_den = L_add(th0, L_mpy_ls(th_max, CNST_0_01_Q1_15)); + if(M_fcn_den == 0) + M_fcn = CNST_0_25_Q1_15; + else + { + tmp = norm_l(M_fcn_den); + M_fcn_den = L_shl(M_fcn_den, tmp); + M_fcn_num = L_shl(M_fcn_num, tmp); + + M_fcn = div_s(extract_h(M_fcn_num), extract_h(M_fcn_den)); + + if(th_lf < (L_tmp= L_add(L_shl(th_hf, 2), th_hf))) // compare th_lf < 5*th_hf + { + tmp = norm_l(L_tmp); + M_fcn_den = L_shl(L_tmp, tmp); + th_lf = L_shl(th_lf, tmp); + + tmp = div_s(extract_h(th_lf), extract_h(M_fcn_den)); + L_tmp = sqrt_l_exp(L_deposit_h(tmp), &tmp); + if(tmp) + L_tmp = L_shr(L_tmp, tmp); + M_fcn = mult(M_fcn, extract_h(L_tmp)); + } + } + // ======================================================================== + fund_fr_step = L_shl(L_mpy_ls(fund_freq, CNST_PI_4_Q1_15), 2); // mult by PI + + uv_harms_cnt = 0; + b1_vec = 0; + band_cnt = 0; + num_harms_cnt = 0; + Sw_sum = 0; + D_num = D_den = 0; + + fund_fr_acc = 0; + fund_freq_acc = fund_freq; + fund_freq_2 = L_shr(fund_freq, 1); + fund_freq_acc_a = L_sub(fund_freq, fund_freq_2); + fund_freq_acc_b = L_add(fund_freq, fund_freq_2); + for(j = 0; j < num_harms; j++) + { + ha = extract_h(fund_freq_acc_a); + hb = extract_h(fund_freq_acc_b); + index_a = (ha >> 8) + ((ha & 0xFF)?1:0); + index_b = (hb >> 8) + ((hb & 0xFF)?1:0); + + L_tmp = L_shl(L_deposit_h(index_a), 8); + L_tmp = L_sub(L_tmp, fund_freq_acc); + L_tmp = L_add(L_tmp, 0x00020000); // for rounding purpose + L_tmp = L_shr(L_tmp, 2); + + index_a_save = index_a; + it_ind = 0; + + // =========== v/uv determination threshold function == + if(num_harms_cnt == 0) // calculate one time per band + { + if(imbe_param->e_p > CNST_0_55_Q4_12 && band_cnt >= 1) + dsn_thr = 0; + else if(v_uv_dsn[band_cnt] == 1) + dsn_thr = mult(M_fcn, sub(CNST_0_5625_Q1_15, mult(CNST_0_1741_Q1_15, extract_h(fund_fr_acc)))); + else + dsn_thr = mult(M_fcn, sub(CNST_0_45_Q1_15, mult(CNST_0_1393_Q1_15, extract_h(fund_fr_acc)))); + + fund_fr_acc = L_add(fund_fr_acc, fund_fr_step); + + thr[band_cnt] = dsn_thr; + } + // ==================================================== + + M_den_sum = 0; + amp_re_acc = amp_im_acc = 0; + while(index_a < index_b) + { + index_wr = extract_h(L_tmp); + if(index_wr < 0 && (L_tmp & 0xFFFF)) // truncating for negative number + index_wr = add(index_wr, 1); + index_wr = add(index_wr, 160); + index_tbl[it_ind++] = index_wr; + if(index_wr >= 0 && index_wr <= 320) + { + amp_re_acc = L_mac(amp_re_acc, fft_buf[index_a].re, wr_sp[index_wr]); + amp_im_acc = L_mac(amp_im_acc, fft_buf[index_a].im, wr_sp[index_wr]); + M_den_sum = L_add(M_den_sum, mult(wr_sp[index_wr], wr_sp[index_wr])); + } + + index_a++; + L_tmp = L_add(L_tmp, 0x400000); + } + sc_coef = div_s(0x4000, extract_l(L_shr(M_den_sum, 1))); + im_tmp2 = mult(extract_h(amp_im_acc), sc_coef); + re_tmp2 = mult(extract_h(amp_re_acc), sc_coef); + + M_num_sum = 0; + it_ind = 0; + index_a = index_a_save; + while(index_a < index_b) + { + index_wr = index_tbl[it_ind++]; + if(index_wr < 0 || index_wr > 320) + sp_rec_re = sp_rec_im = 0; + else + { + sp_rec_im = mult( im_tmp2, wr_sp[index_wr]); + sp_rec_re = mult( re_tmp2, wr_sp[index_wr]); + } + + re_tmp = sub(fft_buf[index_a].re, sp_rec_re); + im_tmp = sub(fft_buf[index_a].im, sp_rec_im); + D_num = L_mac(D_num, re_tmp, re_tmp); + D_num = L_mac(D_num, im_tmp, im_tmp); + + M_num_sum = L_mac(M_num_sum, fft_buf[index_a].re, fft_buf[index_a].re); + M_num_sum = L_mac(M_num_sum, fft_buf[index_a].im, fft_buf[index_a].im); + + index_a++; + } + + M_den[j] = sc_coef; + M_num[j] = M_num_sum; + D_den = L_add(D_den, M_num_sum); + + if(++num_harms_cnt == 3 && band_cnt < num_bands - 1) + { + b1_vec <<= 1; + + if(D_den > D_num && D_den != 0) + { + tmp = norm_l(D_den); + Dk = div_s(extract_h(L_shl(D_num, tmp)), extract_h(L_shl(D_den, tmp))); + } + else + Dk = MAX_16; + + if(Dk < dsn_thr) + { + // voiced band + v_uv_dsn[band_cnt] = 1; + b1_vec |= 1; + i = j - 2; + while(i <= j) + { + imbe_param->sa[i] = voiced_sa_calc(M_num[i], M_den[i]); + imbe_param->v_uv_dsn[i] = 1; + i++; + } + } + else + { + // unvoiced band + v_uv_dsn[band_cnt] = 0; + i = j - 2; + while(i <= j) + { + imbe_param->sa[i] = unvoiced_sa_calc(M_num[i], index_b - index_a_save); + imbe_param->v_uv_dsn[i] = 0; + uv_harms_cnt++; + i++; + } + } + + D_num = D_den = 0; + num_harms_cnt = 0; + band_cnt++; + } + + + fund_freq_acc_a = L_add(fund_freq_acc_a, fund_freq); + fund_freq_acc_b = L_add(fund_freq_acc_b, fund_freq); + fund_freq_acc = L_add(fund_freq_acc, fund_freq); + } + + if(num_harms_cnt) + { + b1_vec <<= 1; + if(D_den > D_num && D_den != 0) + { + tmp = norm_l(D_den); + Dk= div_s(extract_h(L_shl(D_num, tmp)), extract_h(L_shl(D_den, tmp))); + } + else + Dk = MAX_16; + + if(Dk < dsn_thr) + { + // voiced band + v_uv_dsn[band_cnt] = 1; + b1_vec |= 1; + + i = num_harms - num_harms_cnt; + while(i < num_harms) + { + imbe_param->sa[i] = voiced_sa_calc(M_num[i], M_den[i]); + imbe_param->v_uv_dsn[i] = 1; + i++; + } + } + else + { + // unvoiced band + v_uv_dsn[band_cnt] = 0; + i = num_harms - num_harms_cnt; + while(i < num_harms) + { + imbe_param->sa[i] = unvoiced_sa_calc(M_num[i], index_b - index_a_save); + imbe_param->v_uv_dsn[i] = 0; + uv_harms_cnt++; + i++; + } + } + } + + imbe_param->l_uv = uv_harms_cnt; + + + imbe_param->b_vec[1] = b1_vec; // Save encoded voiced/unvoiced decision + imbe_param->b_vec[0] = shr( sub(imbe_param->ref_pitch, 0x1380), 7); // Pitch encode fix(2*pitch - 39) + +} diff --git a/imbe_vocoder/v_uv_det.h b/imbe_vocoder/v_uv_det.h new file mode 100644 index 0000000..ebe270f --- /dev/null +++ b/imbe_vocoder/v_uv_det.h @@ -0,0 +1,28 @@ +/* + * 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 _V_UV_DET +#define _V_UV_DET + +void v_uv_det(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf); + +#endif diff --git a/mbe/ambe3600x2400.c b/mbe/ambe3600x2400.c new file mode 100644 index 0000000..ec44fd3 --- /dev/null +++ b/mbe/ambe3600x2400.c @@ -0,0 +1,746 @@ +/* + * 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 +#include +#include + +#include "mbelib.h" +#include "ambe3600x2400_const.h" + +void +mbe_dumpAmbe2400Data (char *ambe_d) +{ + + int i; + char *ambe; + + ambe = ambe_d; + for (i = 0; i < 49; i++) + { + printf ("%i", *ambe); + ambe++; + } + printf (" "); +} + +void +mbe_dumpAmbe3600x2400Frame (char ambe_fr[4][24]) +{ + + int j; + + // c0 + printf ("ambe_fr c0: "); + for (j = 23; j >= 0; j--) + { + printf ("%i", ambe_fr[0][j]); + } + printf (" "); + // c1 + printf ("ambe_fr c1: "); + for (j = 22; j >= 0; j--) + { + printf ("%i", ambe_fr[1][j]); + } + printf (" "); + // c2 + printf ("ambe_fr c2: "); + for (j = 10; j >= 0; j--) + { + printf ("%i", ambe_fr[2][j]); + } + printf (" "); + // c3 + printf ("ambe_fr c3: "); + for (j = 13; j >= 0; j--) + { + printf ("%i", ambe_fr[3][j]); + } + printf (" "); +} + +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, 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; + +#ifdef AMBE_DEBUG + printf ("\n"); +#endif + + // 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, "index: %d, was <5, invalid!\n", b1); + silence = 1; + } + else if ((b1 >= 5) && (b1 <= 122)) + { + fprintf(stderr, "index: %d, Single tone hz: %f\n", b1, (float)b1*31.25); + } + else if ((b1 > 122) && (b1 < 128)) + { + fprintf(stderr, "index: %d, was >122 and <128, invalid!\n", b1); + silence = 1; + } + else if ((b1 >= 128) && (b1 <= 163)) + { + fprintf(stderr, "index: %d, Dual tone\n", b1); + // note: dual tone index is different on ambe(dstar) and ambe2+ + } + else + { + fprintf(stderr, "index: %d, was >163, invalid!\n", b1); + silence = 1; + } + + if(silence == 1) + { +#ifdef AMBE_DEBUG + printf ("Silence Frame\n"); +#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 + printf ("Tone Frame\n"); +#endif + return (3); + } + //fprintf(stderr,"Voice Frame, Pitch = %f\n", powf(2, ((float)b0+195.626)/-46.368)*8000); // was 45.368 + //fprintf(stderr,"Voice Frame, rawPitch = %02d, Pitch = %f\n", b0, powf(2, ((-1*(float)(17661/((int)1<<12))) - (2.1336e-2 * ((float)b0+0.5))))*8000); + //fprintf(stderr,"Voice Frame, Pitch = %f, ", powf(2, (-4.311767578125 - (2.1336e-2 * ((float)b0+0.5))))*8000); + + // 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; + } + + // 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]; + //fprintf(stderr,"V/UV = %d, ", b1); + 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 + printf ("jl[%i]:%i Vl[%i]:%i\n", l, jl, l, cur_mp->Vl[l]); +#endif + } +#ifdef AMBE_DEBUG + printf ("\nb0:%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[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]; + //fprintf(stderr,"Gain = %d,\n", b2); + deltaGamma = AmbePlusDg[b2]; + cur_mp->gamma = deltaGamma + ((float) 0.5 * prev_mp->gamma); +#ifdef AMBE_DEBUG + printf ("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[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 + printf ("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 + printf ("R%i: %f ", i, Ri[i]); +#endif + } +#ifdef AMBE_DEBUG + printf ("\n"); +#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 + printf ("Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i\n", Ji[1], Ji[2], Ji[3], Ji[4]); + printf ("b5: %i b6: %i b7: %i b8: %i\n", 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 + printf ("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 + printf ("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 + printf ("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 + printf ("C4,%i: %f ", k, Cik[4][k]); +#endif + } + } +#ifdef AMBE_DEBUG + printf ("\n"); +#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 + printf ("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 + printf ("Tl[%i]: %f\n", 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 + printf ("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 + printf ("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 + printf ("\n"); + printf ("Sum43: %f\n", 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 + printf ("flokl[%i]: %f, intkl[%i]: %i ", l, flokl[l], l, intkl[l]); + printf ("deltal[%i]: %f ", l, deltal[l]); + printf ("prev_mp->log2Ml[%i]: %f\n", l, prev_mp->log2Ml[intkl[l]]); + printf ("BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f\n", 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 *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 *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, 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 *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) +{ + + int 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, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); +} + +void +mbe_processAmbe3600x2400Frame (short *aout_buf, 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, errs2, err_str, ambe_fr, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); + mbe_floattoshort (float_buf, aout_buf); +} diff --git a/mbe/ambe3600x2400_const.h b/mbe/ambe3600x2400_const.h new file mode 100644 index 0000000..ff1ec24 --- /dev/null +++ b/mbe/ambe3600x2400_const.h @@ -0,0 +1,884 @@ +/* + * 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. + */ + +#ifndef _AMBE3600x2400_CONST_H +#define _AMBE3600x2400_CONST_H + + +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 diff --git a/mbe/ambe3600x2450.c b/mbe/ambe3600x2450.c new file mode 100644 index 0000000..ac7cab2 --- /dev/null +++ b/mbe/ambe3600x2450.c @@ -0,0 +1,681 @@ +/* + * 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 +#include +#include + +#include "mbelib.h" +#include "ambe3600x2450_const.h" + +void +mbe_dumpAmbe2450Data (char *ambe_d) +{ + + int i; + char *ambe; + + ambe = ambe_d; + for (i = 0; i < 49; i++) + { + printf ("%i", *ambe); + ambe++; + } + printf (" "); +} + +void +mbe_dumpAmbe3600x2450Frame (char ambe_fr[4][24]) +{ + + int j; + + // c0 + printf ("ambe_fr c0: "); + for (j = 23; j >= 0; j--) + { + printf ("%i", ambe_fr[0][j]); + } + printf (" "); + // c1 + printf ("ambe_fr c1: "); + for (j = 22; j >= 0; j--) + { + printf ("%i", ambe_fr[1][j]); + } + printf (" "); + // c2 + printf ("ambe_fr c2: "); + for (j = 10; j >= 0; j--) + { + printf ("%i", ambe_fr[2][j]); + } + printf (" "); + // c3 + printf ("ambe_fr c3: "); + for (j = 13; j >= 0; j--) + { + printf ("%i", ambe_fr[3][j]); + } + printf (" "); +} + +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, 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; + +#ifdef AMBE_DEBUG + printf ("\n"); +#endif + + // 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 + printf ("Erasure Frame\n"); +#endif + return (2); + } + else if ((b0 == 124) || (b0 == 125)) // if w0 bits are 1111100 or 1111101, frame is silence + { +#ifdef AMBE_DEBUG + printf ("Silence Frame\n"); +#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 + printf ("Tone Frame\n"); +#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; + } + + // 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 + printf ("jl[%i]:%i Vl[%i]:%i\n", l, jl, l, cur_mp->Vl[l]); +#endif + } +#ifdef AMBE_DEBUG + printf ("\nb0:%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 + printf ("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 + printf ("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 + printf ("R%i: %f ", i, Ri[i]); +#endif + } +#ifdef AMBE_DEBUG + printf ("\n"); +#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 + printf ("Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i\n", Ji[1], Ji[2], Ji[3], Ji[4]); + printf ("b5: %i b6: %i b7: %i b8: %i\n", 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 + printf ("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 + printf ("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 + printf ("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 + printf ("C4,%i: %f ", k, Cik[4][k]); +#endif + } + } +#ifdef AMBE_DEBUG + printf ("\n"); +#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 + printf ("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 + printf ("Tl[%i]: %f\n", 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 + printf ("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 + printf ("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 + printf ("\n"); + printf ("Sum43: %f\n", 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 + printf ("flokl[%i]: %f, intkl[%i]: %i ", l, flokl[l], l, intkl[l]); + printf ("deltal[%i]: %f ", l, deltal[l]); + printf ("prev_mp->log2Ml[%i]: %f\n", l, prev_mp->log2Ml[intkl[l]]); + printf ("BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f\n", 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 *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 *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, 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 *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) +{ + + int 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, errs2, err_str, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); +} + +void +mbe_processAmbe3600x2450Frame (short *aout_buf, 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, errs2, err_str, ambe_fr, ambe_d, cur_mp, prev_mp, prev_mp_enhanced, uvquality); + mbe_floattoshort (float_buf, aout_buf); +} diff --git a/mbe/ambe3600x2450_const.h b/mbe/ambe3600x2450_const.h new file mode 100644 index 0000000..290c78f --- /dev/null +++ b/mbe/ambe3600x2450_const.h @@ -0,0 +1,971 @@ +/* + * 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. + */ + +#ifndef _AMBE3600x2250_CONST_H +#define _AMBE3600x2250_CONST_H + +/* + * 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 diff --git a/mbe/ecc.c b/mbe/ecc.c new file mode 100644 index 0000000..4a2e41d --- /dev/null +++ b/mbe/ecc.c @@ -0,0 +1,172 @@ +/* + * 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 +#include "ecc_const.h" + +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); +} diff --git a/mbe/ecc_const.h b/mbe/ecc_const.h new file mode 100644 index 0000000..e602f3a --- /dev/null +++ b/mbe/ecc_const.h @@ -0,0 +1,112 @@ +/* + * 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. + */ + +/* + * constants for ecc.c + */ +#ifndef _ECC_H +#define _ECC_H + +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 diff --git a/mbe/mbelib.c b/mbe/mbelib.c new file mode 100644 index 0000000..4fa834c --- /dev/null +++ b/mbe/mbelib.c @@ -0,0 +1,501 @@ +/* + * 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 +#include +#include + +#include "mbelib.h" +#include "mbelib_const.h" + +/** + * \return A pseudo-random float between [0.0, 1.0]. + * See http://www.azillionmonkeys.com/qed/random.html for further improvements + */ +static float +mbe_rand() +{ + return ((float) rand () / (float) RAND_MAX); +} + +/** + * \return A pseudo-random float between [-pi, +pi]. + */ +static float +mbe_rand_phase() +{ + return mbe_rand() * (((float)M_PI) * 2.0F) - ((float)M_PI); +} + +void +mbe_printVersion (char *str) +{ + sprintf (str, "%s", MBELIB_VERSION); +} + +void +mbe_moveMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp) +{ + + int l; + + prev_mp->w0 = cur_mp->w0; + prev_mp->L = cur_mp->L; + prev_mp->K = cur_mp->K; // necessary? + prev_mp->Ml[0] = (float) 0; + prev_mp->gamma = cur_mp->gamma; + prev_mp->repeat = cur_mp->repeat; + for (l = 0; l <= 56; l++) + { + prev_mp->Ml[l] = cur_mp->Ml[l]; + prev_mp->Vl[l] = cur_mp->Vl[l]; + prev_mp->log2Ml[l] = cur_mp->log2Ml[l]; + prev_mp->PHIl[l] = cur_mp->PHIl[l]; + prev_mp->PSIl[l] = cur_mp->PSIl[l]; + } +} + +void +mbe_useLastMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp) +{ + + int l; + + cur_mp->w0 = prev_mp->w0; + cur_mp->L = prev_mp->L; + cur_mp->K = prev_mp->K; // necessary? + cur_mp->Ml[0] = (float) 0; + cur_mp->gamma = prev_mp->gamma; + cur_mp->repeat = prev_mp->repeat; + for (l = 0; l <= 56; l++) + { + cur_mp->Ml[l] = prev_mp->Ml[l]; + cur_mp->Vl[l] = prev_mp->Vl[l]; + cur_mp->log2Ml[l] = prev_mp->log2Ml[l]; + cur_mp->PHIl[l] = prev_mp->PHIl[l]; + cur_mp->PSIl[l] = prev_mp->PSIl[l]; + } +} + +void +mbe_initMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced) +{ + + int l; + + prev_mp->w0 = 0.09378; + prev_mp->L = 30; + prev_mp->K = 10; + prev_mp->gamma = (float) 0; + for (l = 0; l <= 56; l++) + { + prev_mp->Ml[l] = (float) 0; + prev_mp->Vl[l] = 0; + prev_mp->log2Ml[l] = (float) 0; // log2 of 1 == 0 + prev_mp->PHIl[l] = (float) 0; + prev_mp->PSIl[l] = (M_PI / (float) 2); + } + prev_mp->repeat = 0; + mbe_moveMbeParms (prev_mp, cur_mp); + mbe_moveMbeParms (prev_mp, prev_mp_enhanced); +} + +void +mbe_spectralAmpEnhance (mbe_parms * cur_mp) +{ + + float Rm0, Rm1, R2m0, R2m1, Wl[57]; + int l; + float sum, gamma, M; + + Rm0 = 0; + Rm1 = 0; + for (l = 1; l <= cur_mp->L; l++) + { + Rm0 = Rm0 + (cur_mp->Ml[l] * cur_mp->Ml[l]); + Rm1 = Rm1 + ((cur_mp->Ml[l] * cur_mp->Ml[l]) * cosf (cur_mp->w0 * (float) l)); + } + + R2m0 = (Rm0*Rm0); + R2m1 = (Rm1*Rm1); + + for (l = 1; l <= cur_mp->L; l++) + { + if (cur_mp->Ml[l] != 0) + { + Wl[l] = sqrtf (cur_mp->Ml[l]) * powf ((((float) 0.96 * M_PI * ((R2m0 + R2m1) - ((float) 2 * Rm0 * Rm1 * cosf (cur_mp->w0 * (float) l)))) / (cur_mp->w0 * Rm0 * (R2m0 - R2m1))), (float) 0.25); + + if ((8 * l) <= cur_mp->L) + { + } + else if (Wl[l] > 1.2) + { + cur_mp->Ml[l] = 1.2 * cur_mp->Ml[l]; + } + else if (Wl[l] < 0.5) + { + cur_mp->Ml[l] = 0.5 * cur_mp->Ml[l]; + } + else + { + cur_mp->Ml[l] = Wl[l] * cur_mp->Ml[l]; + } + } + } + + // generate scaling factor + sum = 0; + for (l = 1; l <= cur_mp->L; l++) + { + M = cur_mp->Ml[l]; + if (M < 0) + { + M = -M; + } + sum += (M*M); + } + if (sum == 0) + { + gamma = (float) 1.0; + } + else + { + gamma = sqrtf (Rm0 / sum); + } + + // apply scaling factor + for (l = 1; l <= cur_mp->L; l++) + { + cur_mp->Ml[l] = gamma * cur_mp->Ml[l]; + } +} + +void +mbe_synthesizeSilencef (float *aout_buf) +{ + + int n; + float *aout_buf_p; + + aout_buf_p = aout_buf; + for (n = 0; n < 160; n++) + { + *aout_buf_p = (float) 0; + aout_buf_p++; + } +} + +void +mbe_synthesizeSilence (short *aout_buf) +{ + + int n; + short *aout_buf_p; + + aout_buf_p = aout_buf; + for (n = 0; n < 160; n++) + { + *aout_buf_p = (short) 0; + aout_buf_p++; + } +} + +void +mbe_synthesizeSpeechf (float *aout_buf, mbe_parms * cur_mp, mbe_parms * prev_mp, int uvquality) +{ + + int i, l, n, maxl; + float *Ss, loguvquality; + float C1, C2, C3, C4; + //float deltaphil, deltawl, thetaln, aln; + int numUv; + float cw0, pw0, cw0l, pw0l; + float uvsine, uvrand, uvthreshold, uvthresholdf; + float uvstep, uvoffset; + float qfactor; + float rphase[64], rphase2[64]; + + const int N = 160; + + uvthresholdf = (float) 2700; + uvthreshold = ((uvthresholdf * M_PI) / (float) 4000); + + // voiced/unvoiced/gain settings + uvsine = (float) 1.3591409 *M_E; + uvrand = (float) 2.0; + + if ((uvquality < 1) || (uvquality > 64)) + { + printf ("\nmbelib: Error - uvquality must be within the range 1 - 64, setting to default value of 3\n"); + uvquality = 3; + } + + // calculate loguvquality + if (uvquality == 1) + { + loguvquality = (float) 1 / M_E; + } + else + { + loguvquality = log ((float) uvquality) / (float) uvquality; + } + + // calculate unvoiced step and offset values + uvstep = (float) 1.0 / (float) uvquality; + qfactor = loguvquality; + uvoffset = (uvstep * (float) (uvquality - 1)) / (float) 2; + + // count number of unvoiced bands + numUv = 0; + for (l = 1; l <= cur_mp->L; l++) + { + if (cur_mp->Vl[l] == 0) + { + numUv++; + } + } + + cw0 = cur_mp->w0; + pw0 = prev_mp->w0; + + // init aout_buf + Ss = aout_buf; + for (n = 0; n < N; n++) + { + *Ss = (float) 0; + Ss++; + } + + // eq 128 and 129 + if (cur_mp->L > prev_mp->L) + { + maxl = cur_mp->L; + for (l = prev_mp->L + 1; l <= maxl; l++) + { + prev_mp->Ml[l] = (float) 0; + prev_mp->Vl[l] = 1; + } + } + else + { + maxl = prev_mp->L; + for (l = cur_mp->L + 1; l <= maxl; l++) + { + cur_mp->Ml[l] = (float) 0; + cur_mp->Vl[l] = 1; + } + } + + // update phil from eq 139,140 + for (l = 1; l <= 56; l++) + { + cur_mp->PSIl[l] = prev_mp->PSIl[l] + ((pw0 + cw0) * ((float) (l * N) / (float) 2)); + if (l <= (int) (cur_mp->L / 4)) + { + cur_mp->PHIl[l] = cur_mp->PSIl[l]; + } + else + { + cur_mp->PHIl[l] = cur_mp->PSIl[l] + ((numUv * mbe_rand_phase()) / cur_mp->L); + } + } + + for (l = 1; l <= maxl; l++) + { + cw0l = (cw0 * (float) l); + pw0l = (pw0 * (float) l); + if ((cur_mp->Vl[l] == 0) && (prev_mp->Vl[l] == 1)) + { + Ss = aout_buf; + // init random phase + for (i = 0; i < uvquality; i++) + { + rphase[i] = mbe_rand_phase(); + } + for (n = 0; n < N; n++) + { + C1 = 0; + // eq 131 + C1 = Ws[n + N] * prev_mp->Ml[l] * cosf ((pw0l * (float) n) + prev_mp->PHIl[l]); + C3 = 0; + // unvoiced multisine mix + for (i = 0; i < uvquality; i++) + { + C3 = C3 + cosf ((cw0 * (float) n * ((float) l + ((float) i * uvstep) - uvoffset)) + rphase[i]); + if (cw0l > uvthreshold) + { + C3 = C3 + ((cw0l - uvthreshold) * uvrand * mbe_rand()); + } + } + C3 = C3 * uvsine * Ws[n] * cur_mp->Ml[l] * qfactor; + *Ss = *Ss + C1 + C3; + Ss++; + } + } + else if ((cur_mp->Vl[l] == 1) && (prev_mp->Vl[l] == 0)) + { + Ss = aout_buf; + // init random phase + for (i = 0; i < uvquality; i++) + { + rphase[i] = mbe_rand_phase(); + } + for (n = 0; n < N; n++) + { + C1 = 0; + // eq 132 + C1 = Ws[n] * cur_mp->Ml[l] * cosf ((cw0l * (float) (n - N)) + cur_mp->PHIl[l]); + C3 = 0; + // unvoiced multisine mix + for (i = 0; i < uvquality; i++) + { + C3 = C3 + cosf ((pw0 * (float) n * ((float) l + ((float) i * uvstep) - uvoffset)) + rphase[i]); + if (pw0l > uvthreshold) + { + C3 = C3 + ((pw0l - uvthreshold) * uvrand * mbe_rand()); + } + } + C3 = C3 * uvsine * Ws[n + N] * prev_mp->Ml[l] * qfactor; + *Ss = *Ss + C1 + C3; + Ss++; + } + } +// else if (((cur_mp->Vl[l] == 1) || (prev_mp->Vl[l] == 1)) && ((l >= 8) || (fabsf (cw0 - pw0) >= ((float) 0.1 * cw0)))) + else if ((cur_mp->Vl[l] == 1) || (prev_mp->Vl[l] == 1)) + { + Ss = aout_buf; + for (n = 0; n < N; n++) + { + C1 = 0; + // eq 133-1 + C1 = Ws[n + N] * prev_mp->Ml[l] * cosf ((pw0l * (float) n) + prev_mp->PHIl[l]); + C2 = 0; + // eq 133-2 + C2 = Ws[n] * cur_mp->Ml[l] * cosf ((cw0l * (float) (n - N)) + cur_mp->PHIl[l]); + *Ss = *Ss + C1 + C2; + Ss++; + } + } +/* + // expensive and unnecessary? + else if ((cur_mp->Vl[l] == 1) || (prev_mp->Vl[l] == 1)) + { + Ss = aout_buf; + // eq 137 + deltaphil = cur_mp->PHIl[l] - prev_mp->PHIl[l] - (((pw0 + cw0) * (float) (l * N)) / (float) 2); + // eq 138 + deltawl = ((float) 1 / (float) N) * (deltaphil - ((float) 2 * M_PI * (int) ((deltaphil + M_PI) / (M_PI * (float) 2)))); + for (n = 0; n < N; n++) + { + // eq 136 + thetaln = prev_mp->PHIl[l] + ((pw0l + deltawl) * (float) n) + (((cw0 - pw0) * ((float) (l * n * n)) / (float) (2 * N))); + // eq 135 + aln = prev_mp->Ml[l] + (((float) n / (float) N) * (cur_mp->Ml[l] - prev_mp->Ml[l])); + // eq 134 + *Ss = *Ss + (aln * cosf (thetaln)); + Ss++; + } + } +*/ + else + { + Ss = aout_buf; + // init random phase + for (i = 0; i < uvquality; i++) + { + rphase[i] = mbe_rand_phase(); + } + // init random phase + for (i = 0; i < uvquality; i++) + { + rphase2[i] = mbe_rand_phase(); + } + for (n = 0; n < N; n++) + { + C3 = 0; + // unvoiced multisine mix + for (i = 0; i < uvquality; i++) + { + C3 = C3 + cosf ((pw0 * (float) n * ((float) l + ((float) i * uvstep) - uvoffset)) + rphase[i]); + if (pw0l > uvthreshold) + { + C3 = C3 + ((pw0l - uvthreshold) * uvrand * mbe_rand()); + } + } + C3 = C3 * uvsine * Ws[n + N] * prev_mp->Ml[l] * qfactor; + C4 = 0; + // unvoiced multisine mix + for (i = 0; i < uvquality; i++) + { + C4 = C4 + cosf ((cw0 * (float) n * ((float) l + ((float) i * uvstep) - uvoffset)) + rphase2[i]); + if (cw0l > uvthreshold) + { + C4 = C4 + ((cw0l - uvthreshold) * uvrand * mbe_rand()); + } + } + C4 = C4 * uvsine * Ws[n] * cur_mp->Ml[l] * qfactor; + *Ss = *Ss + C3 + C4; + Ss++; + } + } + } +} + +void +mbe_synthesizeSpeech (short *aout_buf, mbe_parms * cur_mp, mbe_parms * prev_mp, int uvquality) +{ + float float_buf[160]; + + mbe_synthesizeSpeechf (float_buf, cur_mp, prev_mp, uvquality); + mbe_floattoshort (float_buf, aout_buf); +} + +void +mbe_floattoshort (float *float_buf, short *aout_buf) +{ + + short *aout_buf_p; + float *float_buf_p; + int i, again; + float audio; + + again = 7; + aout_buf_p = aout_buf; + float_buf_p = float_buf; + for (i = 0; i < 160; i++) + { + audio = again * *float_buf_p; + if (audio > 32760) + { +#ifdef MBE_DEBUG + printf ("audio clip: %f\n", audio); +#endif + audio = 32760; + } + else if (audio < -32760) + { +#ifdef MBE_DEBUG + printf ("audio clip: %f\n", audio); +#endif + audio = -32760; + } + *aout_buf_p = (short) (audio); + aout_buf_p++; + float_buf_p++; + } +} + diff --git a/mbe/mbelib.h b/mbe/mbelib.h new file mode 100644 index 0000000..c486cfb --- /dev/null +++ b/mbe/mbelib.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef _MBELIB_H +#define _MBELIB_H + +#define MBELIB_VERSION "1.3.0" + +struct mbe_parameters +{ + float w0; + int L; + int K; + int Vl[57]; + float Ml[57]; + float log2Ml[57]; + float PHIl[57]; + float PSIl[57]; + float gamma; + int un; + int repeat; +}; + +typedef struct mbe_parameters mbe_parms; + +/* + * Prototypes from ecc.c + */ +void mbe_checkGolayBlock (long int *block); +int mbe_golay2312 (char *in, char *out); +int mbe_hamming1511 (char *in, char *out); +int mbe_7100x4400hamming1511 (char *in, char *out); + +/* + * Prototypes from ambe3600x2400.c + */ +int mbe_eccAmbe3600x2400C0 (char ambe_fr[4][24]); +int mbe_eccAmbe3600x2400Data (char ambe_fr[4][24], char *ambe_d); +int mbe_decodeAmbe2400Parms (char *ambe_d, mbe_parms * cur_mp, mbe_parms * prev_mp); +void mbe_demodulateAmbe3600x2400Data (char ambe_fr[4][24]); +void mbe_processAmbe2400Dataf (float *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processAmbe2400Data (short *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processAmbe3600x2400Framef (float *aout_buf, 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); +void mbe_processAmbe3600x2400Frame (short *aout_buf, 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); + +/* + * Prototypes from ambe3600x2450.c + */ +int mbe_eccAmbe3600x2450C0 (char ambe_fr[4][24]); +int mbe_eccAmbe3600x2450Data (char ambe_fr[4][24], char *ambe_d); +int mbe_decodeAmbe2450Parms (char *ambe_d, mbe_parms * cur_mp, mbe_parms * prev_mp); +void mbe_demodulateAmbe3600x2450Data (char ambe_fr[4][24]); +void mbe_processAmbe2450Dataf (float *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processAmbe2450Data (short *aout_buf, int *errs2, char *err_str, char ambe_d[49], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processAmbe3600x2450Framef (float *aout_buf, 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); +void mbe_processAmbe3600x2450Frame (short *aout_buf, 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); + +/* + * Prototypes from imbe7200x4400.c + */ +void mbe_dumpImbe4400Data (char *imbe_d); +void mbe_dumpImbe7200x4400Data (char *imbe_d); +void mbe_dumpImbe7200x4400Frame (char imbe_fr[8][23]); +int mbe_eccImbe7200x4400C0 (char imbe_fr[8][23]); +int mbe_eccImbe7200x4400Data (char imbe_fr[8][23], char *imbe_d); +int mbe_decodeImbe4400Parms (char *imbe_d, mbe_parms * cur_mp, mbe_parms * prev_mp); +void mbe_demodulateImbe7200x4400Data (char imbe[8][23]); +void mbe_processImbe4400Dataf (float *aout_buf, int *errs2, char *err_str, char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processImbe4400Data (short *aout_buf, int *errs2, char *err_str, char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processImbe7200x4400Framef (float *aout_buf, int *errs2, char *err_str, char imbe_fr[8][23], char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processImbe7200x4400Frame (short *aout_buf, int *errs2, char *err_str, char imbe_fr[8][23], char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); + +/* + * Prototypes from imbe7100x4400.c + */ +void mbe_dumpImbe7100x4400Data (char *imbe_d); +void mbe_dumpImbe7100x4400Frame (char imbe_fr[7][24]); +int mbe_eccImbe7100x4400C0 (char imbe_fr[7][24]); +int mbe_eccImbe7100x4400Data (char imbe_fr[7][24], char *imbe_d); +void mbe_demodulateImbe7100x4400Data (char imbe[7][24]); +void mbe_convertImbe7100to7200 (char *imbe_d); +void mbe_processImbe7100x4400Framef (float *aout_buf, int *errs, int *errs2, char *err_str, char imbe_fr[7][24], char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); +void mbe_processImbe7100x4400Frame (short *aout_buf, int *errs, int *errs2, char *err_str, char imbe_fr[7][24], char imbe_d[88], mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced, int uvquality); + +/* + * Prototypes from mbelib.c + */ +void mbe_printVersion (char *str); +void mbe_moveMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp); +void mbe_useLastMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp); +void mbe_initMbeParms (mbe_parms * cur_mp, mbe_parms * prev_mp, mbe_parms * prev_mp_enhanced); +void mbe_spectralAmpEnhance (mbe_parms * cur_mp); +void mbe_synthesizeSilencef (float *aout_buf); +void mbe_synthesizeSilence (short *aout_buf); +void mbe_synthesizeSpeechf (float *aout_buf, mbe_parms * cur_mp, mbe_parms * prev_mp, int uvquality); +void mbe_synthesizeSpeech (short *aout_buf, mbe_parms * cur_mp, mbe_parms * prev_mp, int uvquality); +void mbe_floattoshort (float *float_buf, short *aout_buf); + +#endif diff --git a/mbe/mbelib_const.h b/mbe/mbelib_const.h new file mode 100644 index 0000000..6258ab1 --- /dev/null +++ b/mbe/mbelib_const.h @@ -0,0 +1,371 @@ +/* + * 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. + */ + +#ifndef _MBELIB_CONST_H +#define _MBELIB_CONST_H + +/* + * Speech Synthesis Window 8k version + */ +const float Ws[321] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, + 0.2, 0.22, 0.24, 0.26, 0.28, 0.3, 0.32, 0.34, 0.36, 0.38, + 0.4, 0.42, 0.44, 0.46, 0.48, 0.5, 0.52, 0.54, 0.56, 0.58, + 0.6, 0.62, 0.64, 0.66, 0.68, 0.7, 0.72, 0.74, 0.76, 0.78, + 0.8, 0.82, 0.84, 0.86, 0.88, 0.9, 0.92, 0.94, 0.96, 0.98, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0.98, 0.96, 0.94, 0.92, 0.9, 0.88, 0.86, 0.84, 0.82, 0.8, + 0.78, 0.76, 0.74, 0.72, 0.7, 0.68, 0.66, 0.64, 0.62, 0.6, + 0.58, 0.56, 0.54, 0.52, 0.5, 0.48, 0.46, 0.44, 0.42, 0.4, + 0.38, 0.36, 0.34, 0.32, 0.3, 0.28, 0.26, 0.24, 0.22, 0.2, + 0.18, 0.16, 0.14, 0.12, 0.1, 0.08, 0.06, 0.04, 0.02, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Speech Synthesis Window, 48k version + */ +/* +const float Ws48k[1926] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0.000, 0.003, 0.007, + 0.010, 0.013, 0.017, + 0.020, 0.023, 0.027, + 0.030, 0.033, 0.037, + 0.040, 0.043, 0.047, + 0.050, 0.053, 0.057, + 0.060, 0.063, 0.067, + 0.070, 0.073, 0.077, + 0.080, 0.083, 0.087, + 0.090, 0.093, 0.097, + 0.100, 0.103, 0.107, + 0.110, 0.113, 0.117, + 0.120, 0.123, 0.127, + 0.130, 0.133, 0.137, + 0.140, 0.143, 0.147, + 0.150, 0.153, 0.157, + 0.160, 0.163, 0.167, + 0.170, 0.173, 0.177, + 0.180, 0.183, 0.187, + 0.190, 0.193, 0.197, + 0.200, 0.203, 0.207, + 0.210, 0.213, 0.217, + 0.220, 0.223, 0.227, + 0.230, 0.233, 0.237, + 0.240, 0.243, 0.247, + 0.250, 0.253, 0.257, + 0.260, 0.263, 0.267, + 0.270, 0.273, 0.277, + 0.280, 0.283, 0.287, + 0.290, 0.293, 0.297, + 0.300, 0.303, 0.307, + 0.310, 0.313, 0.317, + 0.320, 0.323, 0.327, + 0.330, 0.333, 0.337, + 0.340, 0.343, 0.347, + 0.350, 0.353, 0.357, + 0.360, 0.363, 0.367, + 0.370, 0.373, 0.377, + 0.380, 0.383, 0.387, + 0.390, 0.393, 0.397, + 0.400, 0.403, 0.407, + 0.410, 0.413, 0.417, + 0.420, 0.423, 0.427, + 0.430, 0.433, 0.437, + 0.440, 0.443, 0.447, + 0.450, 0.453, 0.457, + 0.460, 0.463, 0.467, + 0.470, 0.473, 0.477, + 0.480, 0.483, 0.487, + 0.490, 0.493, 0.497, + 0.500, 0.503, 0.507, + 0.510, 0.513, 0.517, + 0.520, 0.523, 0.527, + 0.530, 0.533, 0.537, + 0.540, 0.543, 0.547, + 0.550, 0.553, 0.557, + 0.560, 0.563, 0.567, + 0.570, 0.573, 0.577, + 0.580, 0.583, 0.587, + 0.590, 0.593, 0.597, + 0.600, 0.603, 0.607, + 0.610, 0.613, 0.617, + 0.620, 0.623, 0.627, + 0.630, 0.633, 0.637, + 0.640, 0.643, 0.647, + 0.650, 0.653, 0.657, + 0.660, 0.663, 0.667, + 0.670, 0.673, 0.677, + 0.680, 0.683, 0.687, + 0.690, 0.693, 0.697, + 0.700, 0.703, 0.707, + 0.710, 0.713, 0.717, + 0.720, 0.723, 0.727, + 0.730, 0.733, 0.737, + 0.740, 0.743, 0.747, + 0.750, 0.753, 0.757, + 0.760, 0.763, 0.767, + 0.770, 0.773, 0.777, + 0.780, 0.783, 0.787, + 0.790, 0.793, 0.797, + 0.800, 0.803, 0.807, + 0.810, 0.813, 0.817, + 0.820, 0.823, 0.827, + 0.830, 0.833, 0.837, + 0.840, 0.843, 0.847, + 0.850, 0.853, 0.857, + 0.860, 0.863, 0.867, + 0.870, 0.873, 0.877, + 0.880, 0.883, 0.887, + 0.890, 0.893, 0.897, + 0.900, 0.903, 0.907, + 0.910, 0.913, 0.917, + 0.920, 0.923, 0.927, + 0.930, 0.933, 0.937, + 0.940, 0.943, 0.947, + 0.950, 0.953, 0.957, + 0.960, 0.963, 0.967, + 0.970, 0.973, 0.977, + 0.980, 0.983, 0.987, + 0.990, 0.993, 0.997, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0.997, 0.993, 0.990, + 0.987, 0.983, 0.980, + 0.977, 0.973, 0.970, + 0.967, 0.963, 0.960, + 0.957, 0.953, 0.950, + 0.947, 0.943, 0.940, + 0.937, 0.933, 0.930, + 0.927, 0.923, 0.920, + 0.917, 0.913, 0.910, + 0.907, 0.903, 0.900, + 0.897, 0.893, 0.890, + 0.887, 0.883, 0.880, + 0.877, 0.873, 0.870, + 0.867, 0.863, 0.860, + 0.857, 0.853, 0.850, + 0.847, 0.843, 0.840, + 0.837, 0.833, 0.830, + 0.827, 0.823, 0.820, + 0.817, 0.813, 0.810, + 0.807, 0.803, 0.800, + 0.797, 0.793, 0.790, + 0.787, 0.783, 0.780, + 0.777, 0.773, 0.770, + 0.767, 0.763, 0.760, + 0.757, 0.753, 0.750, + 0.747, 0.743, 0.740, + 0.737, 0.733, 0.730, + 0.727, 0.723, 0.720, + 0.717, 0.713, 0.710, + 0.707, 0.703, 0.700, + 0.697, 0.693, 0.690, + 0.687, 0.683, 0.680, + 0.677, 0.673, 0.670, + 0.667, 0.663, 0.660, + 0.657, 0.653, 0.650, + 0.647, 0.643, 0.640, + 0.637, 0.633, 0.630, + 0.627, 0.623, 0.620, + 0.617, 0.613, 0.610, + 0.607, 0.603, 0.600, + 0.597, 0.593, 0.590, + 0.587, 0.583, 0.580, + 0.577, 0.573, 0.570, + 0.567, 0.563, 0.560, + 0.557, 0.553, 0.550, + 0.547, 0.543, 0.540, + 0.537, 0.533, 0.530, + 0.527, 0.523, 0.520, + 0.517, 0.513, 0.510, + 0.507, 0.503, 0.500, + 0.497, 0.493, 0.490, + 0.487, 0.483, 0.480, + 0.477, 0.473, 0.470, + 0.467, 0.463, 0.460, + 0.457, 0.453, 0.450, + 0.447, 0.443, 0.440, + 0.437, 0.433, 0.430, + 0.427, 0.423, 0.420, + 0.417, 0.413, 0.410, + 0.407, 0.403, 0.400, + 0.397, 0.393, 0.390, + 0.387, 0.383, 0.380, + 0.377, 0.373, 0.370, + 0.367, 0.363, 0.360, + 0.357, 0.353, 0.350, + 0.347, 0.343, 0.340, + 0.337, 0.333, 0.330, + 0.327, 0.323, 0.320, + 0.317, 0.313, 0.310, + 0.307, 0.303, 0.300, + 0.297, 0.293, 0.290, + 0.287, 0.283, 0.280, + 0.277, 0.273, 0.270, + 0.267, 0.263, 0.260, + 0.257, 0.253, 0.250, + 0.247, 0.243, 0.240, + 0.237, 0.233, 0.230, + 0.227, 0.223, 0.220, + 0.217, 0.213, 0.210, + 0.207, 0.203, 0.200, + 0.197, 0.193, 0.190, + 0.187, 0.183, 0.180, + 0.177, 0.173, 0.170, + 0.167, 0.163, 0.160, + 0.157, 0.153, 0.150, + 0.147, 0.143, 0.140, + 0.137, 0.133, 0.130, + 0.127, 0.123, 0.120, + 0.117, 0.113, 0.110, + 0.107, 0.103, 0.100, + 0.097, 0.093, 0.090, + 0.087, 0.083, 0.080, + 0.077, 0.073, 0.070, + 0.067, 0.063, 0.060, + 0.057, 0.053, 0.050, + 0.047, 0.043, 0.040, + 0.037, 0.033, 0.030, + 0.027, 0.023, 0.020, + 0.017, 0.013, 0.010, + 0.007, 0.003, 0.000, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +*/ + +#endif diff --git a/mbe/mbelib_parms.h b/mbe/mbelib_parms.h new file mode 100644 index 0000000..d7267c3 --- /dev/null +++ b/mbe/mbelib_parms.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef MBELIB_H_ +#define MBELIB_H_ + +#include +extern "C" { +#include "mbelib.h" + + +struct mbelibParms +{ + mbe_parms *m_cur_mp; + mbe_parms *m_prev_mp; + mbe_parms *m_prev_mp_enhanced; + + 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)); + } + + ~mbelibParms() + { + free(m_prev_mp_enhanced); + free(m_prev_mp); + free(m_cur_mp); + } +}; +} +#endif /* MBELIB_H_ */ diff --git a/mbe/vocoder_plugin.cpp b/mbe/vocoder_plugin.cpp new file mode 100644 index 0000000..a365ed0 --- /dev/null +++ b/mbe/vocoder_plugin.cpp @@ -0,0 +1,1299 @@ +/* + * 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 +#include +#include + +#include "vocoder_plugin.h" +#include "vocoder_tables.h" +#include "ambe3600x2400_const.h" +#include "ambe3600x2450_const.h" + +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 +}; + +static const int m_list[] = {0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 7, 8, 9, 10, 15, 16, 24, 25, 31, 32, 6}; +static const int d_list[] = {7, 1, 11, 21, 31, 25, 35, 45, 55, 49, 59, 69, 6, 0, 10, 20, 30, 24, 34, 44, 54, 48, 58, 68, 5, 15, 9, 19, 29, 39, 33, 43, 53, 63, 57, 67, 4, 14, 8, 18, 28, 38, 32, 42, 52, 62, 56, 66, 3, 13, 23, 17, 27, 37, 47, 41, 51, 61, 71, 65, 2, 12, 22, 16, 26, 36, 46, 40, 50, 60, 70, 64}; +static const int alt_d_list[] = {0, 12, 24, 36, 48, 60, 1, 13, 25, 37, 49, 61, 2, 14, 26, 38, 50, 62, 3, 15, 27, 39, 51, 63, 4, 16, 28, 40, 52, 64, 5, 17, 29, 41, 53, 65, 6, 18, 30, 42, 54, 66, 7, 19, 31, 43, 55, 67, 8, 20, 32, 44, 56, 68, 9, 21, 33, 45, 57, 69, 10, 22, 34, 46, 58, 70, 11, 23, 35, 47, 59, 71}; +static const int b_lengths[] = {7,4,6,9,7,4,4,4,3}; + +const int 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 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 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 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 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 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 +}; + + +static inline uint32_t golay_24_encode(uint32_t code_word_in) +{ + static const uint32_t encoding[12] = { + 040006165, + 020003073, + 010007550, + 04003664, + 02001732, + 01006631, + 0403315, + 0201547, + 0106706, + 045227, + 024476, + 014353 + }; + + uint32_t code_word_out = 0; + for(uint16_t i = 0; i < 12; i++) { + uint32_t temp_word = code_word_in & (1 << (11 - i)); + if(temp_word >= 1) { + code_word_out = code_word_out ^ encoding[i]; + } + } + return(code_word_out); +} + +static inline uint32_t golay_23_encode(uint32_t code_word_in) +{ + return golay_24_encode(code_word_in) >> 1; +} + +static inline void dump_i(uint8_t dest[], int src, int count) +{ + for (int i=0; i> 1; + } +} + +static inline void store_reg(int reg, uint8_t val[], int len) +{ + for (int i=0; i> (len-1-i)) & 1; + } +} + +static inline int load_reg(const uint8_t val[], int len) +{ + int acc = 0; + for (int i=0; irepeat = prev_mp->repeat; + + if ((b0 >= 120) && (b0 <= 123)) + { +#ifdef AMBE_DEBUG + fprintf (stderr, "AMBE Erasure Frame\n"); +#endif + return (2); + } + else if ((b0 == 124) || (b0 == 125)) + { +#ifdef AMBE_DEBUG + fprintf (stderr, "AMBE Silence Frame\n"); +#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, "AMBE Tone Frame\n"); +#endif + return (3); + } + + if (silence == 0) + { + if (dstar) + f0 = powf(2, (-4.311767578125 - (2.1336e-2 * ((float)b0+0.5)))); + else + // 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 + if (dstar) + L = AmbePlusLtable[b0]; + else + 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) + { + if (dstar) + cur_mp->Vl[l] = AmbePlusVuv[b1][jl]; + else + cur_mp->Vl[l] = AmbeVuv[b1][jl]; + } +#ifdef AMBE_DEBUG + fprintf (stderr, "jl[%i]:%i Vl[%i]:%i\n", l, jl, l, cur_mp->Vl[l]); +#endif + } +#ifdef AMBE_DEBUG + fprintf (stderr, "\nb0:%i w0:%f L:%i b1:%i\n", b0, cur_mp->w0, L, b1); +#endif + if (dstar) { + deltaGamma = AmbePlusDg[b2]; + cur_mp->gamma = deltaGamma + ((float) 0.5 * prev_mp->gamma); + } else { + deltaGamma = AmbeDg[b2]; + cur_mp->gamma = deltaGamma + ((float) 0.5 * prev_mp->gamma); + } +#ifdef AMBE_DEBUG + fprintf (stderr, "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; + + if (dstar) { + Gm[2] = AmbePlusPRBA24[b3][0]; + Gm[3] = AmbePlusPRBA24[b3][1]; + Gm[4] = AmbePlusPRBA24[b3][2]; + + Gm[5] = AmbePlusPRBA58[b4][0]; + Gm[6] = AmbePlusPRBA58[b4][1]; + Gm[7] = AmbePlusPRBA58[b4][2]; + Gm[8] = AmbePlusPRBA58[b4][3]; + } else { + 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, "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, "R%i: %f ", i, Ri[i]); +#endif + } +#ifdef AMBE_DEBUG + fprintf (stderr, "\n"); +#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 + if (dstar) { + Ji[1] = AmbePlusLmprbl[L][0]; + Ji[2] = AmbePlusLmprbl[L][1]; + Ji[3] = AmbePlusLmprbl[L][2]; + Ji[4] = AmbePlusLmprbl[L][3]; + } else { + 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, "Ji[1]: %i Ji[2]: %i Ji[3]: %i Ji[4]: %i\n", Ji[1], Ji[2], Ji[3], Ji[4]); + fprintf (stderr, "b5: %i b6: %i b7: %i b8: %i\n", 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 + { + if (dstar) + Cik[1][k] = AmbePlusHOCb5[b5][k - 3]; + else + Cik[1][k] = AmbeHOCb5[b5][k - 3]; +#ifdef AMBE_DEBUG + fprintf (stderr, "C1,%i: %f ", k, Cik[1][k]); +#endif + } + } + for (k = 3; k <= Ji[2]; k++) + { + if (k > 6) + { + Cik[2][k] = 0; + } + else + { + if (dstar) + Cik[2][k] = AmbePlusHOCb6[b6][k - 3]; + else + Cik[2][k] = AmbeHOCb6[b6][k - 3]; +#ifdef AMBE_DEBUG + fprintf (stderr, "C2,%i: %f ", k, Cik[2][k]); +#endif + } + } + for (k = 3; k <= Ji[3]; k++) + { + if (k > 6) + { + Cik[3][k] = 0; + } + else + { + if (dstar) + Cik[3][k] = AmbePlusHOCb7[b7][k - 3]; + else + Cik[3][k] = AmbeHOCb7[b7][k - 3]; +#ifdef AMBE_DEBUG + fprintf (stderr, "C3,%i: %f ", k, Cik[3][k]); +#endif + } + } + for (k = 3; k <= Ji[4]; k++) + { + if (k > 6) + { + Cik[4][k] = 0; + } + else + { + if (dstar) + Cik[4][k] = AmbePlusHOCb8[b8][k - 3]; + else + Cik[4][k] = AmbeHOCb8[b8][k - 3]; +#ifdef AMBE_DEBUG + fprintf (stderr, "C4,%i: %f ", k, Cik[4][k]); +#endif + } + } +#ifdef AMBE_DEBUG + fprintf (stderr, "\n"); +#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, "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, "Tl[%i]: %f\n", 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, "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, "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, "\n"); + fprintf (stderr, "Sum43: %f\n", 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, "flokl[%i]: %f, intkl[%i]: %i ", l, flokl[l], l, intkl[l]); + fprintf (stderr, "deltal[%i]: %f ", l, deltal[l]); + fprintf (stderr, "prev_mp->log2Ml[%i]: %f\n", l, prev_mp->log2Ml[intkl[l]]); + fprintf (stderr, "BigGamma: %f c1: %f c2: %f Sum43: %f Tl[%i]: %f log2Ml[%i]: %f Ml[%i]: %f\n", BigGamma, c1, c2, Sum43, l, Tl[l], l, cur_mp->log2Ml[l], l, cur_mp->Ml[l]); +#endif + } + + return (0); +} + +int +mbe_dequantizeAmbe2400Parms (mbe_parms * cur_mp, mbe_parms * prev_mp, const int *b){ + int dstar = 1; + return (mbe_dequantizeAmbeParms (cur_mp, prev_mp, b, dstar)); +} + +int +mbe_dequantizeAmbe2250Parms (mbe_parms * cur_mp, mbe_parms * prev_mp, const int *b){ + int dstar = 0; + return (mbe_dequantizeAmbeParms (cur_mp, prev_mp, b, dstar)); +} + + +void encode_ambe(const IMBE_PARAM *imbe_param, int b[], mbe_parms*cur_mp, mbe_parms*prev_mp, bool dstar, float gain_adjust) { + 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; + if (dstar) + L = (int) AmbePlusLtable[b[0]]; + else + L = (int) AmbeLtable[b[0]]; +#if 1 + // 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]; + if (dstar) + L = (int) AmbePlusLtable[b[0]]; + else + L = (int) AmbeLtable[b[0]]; + } +#endif + 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 = (dstar) ? 16 : 17; + for (int n=0; n < vuv_max; n++) { + float En = 0; + for (int l=1; l <= L; l++) { + int jl; + if (dstar) + jl = (int) ((float) l * (float) 16.0 * make_f0(b[0])); + else + jl = (int) ((float) l * (float) 16.0 * AmbeW0table[b[0]]); + int kl = 12; + if (l <= 36) + kl = (l + 2) / 3; + if (dstar) { + if (imbe_param->v_uv_dsn[(kl-1)*3] != AmbePlusVuv[n][jl]) + En += m_float2[l-1]; + } else { + 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; + if (dstar) + log_l_w0 = 0.5 * log2f(num_harms_f * make_f0(b[0]) * 2.0 * M_PI) + 2.289; + else + 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; + if (dstar) + diff_gain = gain; + else + diff_gain = gain - 0.5 * prev_mp->gamma; + + diff_gain -= gain_adjust; + + float error; + int error_index; + int max_dg = (dstar) ? 64 : 32; + for (int i1 = 0; i1 < max_dg; i1++) { + float diff; + if (dstar) + diff = fabsf(diff_gain - AmbePlusDg[i1]); + else + diff = fabsf(diff_gain - AmbeDg[i1]); + //fprintf(stderr, "%2.4f:%2.4f ", diff, error); + if ((i1 == 0) || (diff < error)) { + error = diff; + error_index = i1; + } + } + //fprintf(stderr, "\n"); + 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; + if (dstar) + J = AmbePlusLmprbl[imbe_param->num_harms]; + else + 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; + if (dstar) { + diff = G[1] - AmbePlusPRBA24[i][0]; + err += (diff * diff); + diff = G[2] - AmbePlusPRBA24[i][1]; + err += (diff * diff); + diff = G[3] - AmbePlusPRBA24[i][2]; + err += (diff * diff); + } else { + 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; + if (dstar) { + diff = G[4] - AmbePlusPRBA58[i][0]; + err += (diff * diff); + diff = G[5] - AmbePlusPRBA58[i][1]; + err += (diff * diff); + diff = G[6] - AmbePlusPRBA58[i][2]; + err += (diff * diff); + diff = G[7] - AmbePlusPRBA58[i][3]; + err += (diff * diff); + } else { + 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 = (dstar) ? 16 : 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++) { + if (dstar) + diff = AmbePlusHOCb5[n][j-1] - C[ii-1][j+2-1]; + else + 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++) { + if (dstar) + diff = AmbePlusHOCb6[n][j-1] - C[ii-1][j+2-1]; + else + 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++) { + if (dstar) + diff = AmbePlusHOCb7[n][j-1] - C[ii-1][j+2-1]; + else + 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 = (dstar) ? 16 : 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++) { + if (dstar) + diff = AmbePlusHOCb8[n][j-1] - C[ii-1][j+2-1]; + else + 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; + } + //fprintf (stderr, "B\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]); + //int rc; + if (dstar) + mbe_dequantizeAmbe2400Parms (cur_mp, prev_mp, b); + else + mbe_dequantizeAmbe2250Parms (cur_mp, prev_mp, b); + mbe_moveMbeParms (cur_mp, prev_mp); +} + + VocoderPlugin::VocoderPlugin() + { + m_mbelibParms = new mbelibParms(); + m_audio_out_temp_buf_p = m_audio_out_temp_buf; + + memset(m_audio_out_buf, 0, sizeof(short) * 2 * 48000); + m_audio_out_buf_p = m_audio_out_buf; + m_audio_out_nb_samples = 0; + m_audio_out_buf_size = 48000; // given in number of unique samples + + initMbeParms(); + memset(ambe_d, 0, 49); + } + + VocoderPlugin::~VocoderPlugin() + { + } + + void VocoderPlugin::decode_2400x1200(int16_t *pcm, uint8_t *ambe) + { + int samples = 0; + process_2400x1200(ambe); + int16_t *p = getAudio(samples); + memcpy(pcm, p, samples * sizeof(int16_t)); + resetAudio(); + } + + void VocoderPlugin::decode_2450x1150(int16_t *pcm, uint8_t *ambe) + { + int samples = 0; + process_2450x1150(ambe); + int16_t *p = getAudio(samples); + memcpy(pcm, p, samples * sizeof(int16_t)); + resetAudio(); + } + + void VocoderPlugin::decode_2450(int16_t *pcm, uint8_t *ambe) + { + int samples = 0; + process_2450(ambe); + int16_t *p = getAudio(samples); + memcpy(pcm, p, samples * sizeof(int16_t)); + resetAudio(); + } + + void VocoderPlugin::encode_2400x1200(int16_t *pcm, uint8_t *ambe) + { + int b[9]; + int16_t frame_vector[8]; // result ignored + uint8_t ambe_frame[72]; + + uint8_t pbuf[48]; + uint8_t tbuf[48]; + int tbufp = 0; + + vocoder.imbe_encode(frame_vector, pcm); + encode_ambe(vocoder.param(), b, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, true, 1.0); + + for (int i=0; i < 9; i++) { + store_reg(b[i], &tbuf[tbufp], b_lengths[i]); + tbufp += b_lengths[i]; + } + + for (int i=0; i < 48; i++) + pbuf[i] = tbuf[m_list[i]]; + + int u0 = load_reg(pbuf+0, 12); + int u1 = load_reg(pbuf+12, 12); + + int m1 = PRNG_TABLE[u0]; + int c0 = golay_24_encode(u0); + int c1 = golay_24_encode(u1) ^ m1; + + uint8_t pre_buf[72]; + store_reg(c0, pre_buf, 24); + store_reg(c1, pre_buf+24, 24); + memcpy(pre_buf+48, pbuf+24, 24); + + for (int i=0; i < 72; i++) + ambe_frame[d_list[i]] = pre_buf[i]; + + for(int i = 0; i < 9; ++i){ + for(int j = 0; j < 8; ++j){ + ambe[i] |= (ambe_frame[(i*8)+j] << j); + } + } + } + + void VocoderPlugin::encode_2450x1150(int16_t *pcm, uint8_t *ambe) + { + unsigned int aOrig = 0U; + unsigned int bOrig = 0U; + unsigned int cOrig = 0U; + unsigned int MASK = 0x000800U; + uint8_t tmp[9]; + + memset(tmp, 0, 9); + memset(ambe, 0, 9); + encode_2450(pcm, tmp); + + for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) { + unsigned int n1 = i; + unsigned int n2 = i + 12U; + if (READ_BIT(tmp, n1)) + aOrig |= MASK; + if (READ_BIT(tmp, n2)) + bOrig |= MASK; + } + + MASK = 0x1000000U; + for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) { + unsigned int n = i + 24U; + if (READ_BIT(tmp, n)) + cOrig |= MASK; + } + + unsigned int a = golay_24_encode(aOrig); + + // The PRNG + unsigned int p = PRNG_TABLE[aOrig] >> 1; + + unsigned int b = golay_23_encode(bOrig); + b ^= p; + + MASK = 0x800000U; + for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) { + unsigned int aPos = A_TABLE[i]; + WRITE_BIT(ambe, aPos, a & MASK); + } + + MASK = 0x400000U; + for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) { + unsigned int bPos = B_TABLE[i]; + WRITE_BIT(ambe, bPos, b & MASK); + } + + MASK = 0x1000000U; + for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) { + unsigned int cPos = C_TABLE[i]; + WRITE_BIT(ambe, cPos, cOrig & MASK); + } + } + + void VocoderPlugin::encode_2450(int16_t *pcm, uint8_t *ambe) + { + int b[9]; + int16_t frame_vector[8]; // result ignored + uint8_t ambe_frame[49]; + + vocoder.imbe_encode(frame_vector, pcm); + encode_ambe(vocoder.param(), b, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, false, 1.0); + + ambe_frame[0] = (b[0] >> 6) & 1; + ambe_frame[1] = (b[0] >> 5) & 1; + ambe_frame[2] = (b[0] >> 4) & 1; + ambe_frame[3] = (b[0] >> 3) & 1; + ambe_frame[4] = (b[1] >> 4) & 1; + ambe_frame[5] = (b[1] >> 3) & 1; + ambe_frame[6] = (b[1] >> 2) & 1; + ambe_frame[7] = (b[1] >> 1) & 1; + ambe_frame[8] = (b[2] >> 4) & 1; + ambe_frame[9] = (b[2] >> 3) & 1; + ambe_frame[10] = (b[2] >> 2) & 1; + ambe_frame[11] = (b[2] >> 1) & 1; + ambe_frame[12] = (b[3] >> 8) & 1; + ambe_frame[13] = (b[3] >> 7) & 1; + ambe_frame[14] = (b[3] >> 6) & 1; + ambe_frame[15] = (b[3] >> 5) & 1; + ambe_frame[16] = (b[3] >> 4) & 1; + ambe_frame[17] = (b[3] >> 3) & 1; + ambe_frame[18] = (b[3] >> 2) & 1; + ambe_frame[19] = (b[3] >> 1) & 1; + ambe_frame[20] = (b[4] >> 6) & 1; + ambe_frame[21] = (b[4] >> 5) & 1; + ambe_frame[22] = (b[4] >> 4) & 1; + ambe_frame[23] = (b[4] >> 3) & 1; + ambe_frame[24] = (b[5] >> 4) & 1; + ambe_frame[25] = (b[5] >> 3) & 1; + ambe_frame[26] = (b[5] >> 2) & 1; + ambe_frame[27] = (b[5] >> 1) & 1; + ambe_frame[28] = (b[6] >> 3) & 1; + ambe_frame[29] = (b[6] >> 2) & 1; + ambe_frame[30] = (b[6] >> 1) & 1; + ambe_frame[31] = (b[7] >> 3) & 1; + ambe_frame[32] = (b[7] >> 2) & 1; + ambe_frame[33] = (b[7] >> 1) & 1; + ambe_frame[34] = (b[8] >> 2) & 1; + ambe_frame[35] = b[1] & 1; + ambe_frame[36] = b[2] & 1; + ambe_frame[37] = (b[0] >> 2) & 1; + ambe_frame[38] = (b[0] >> 1) & 1; + ambe_frame[39] = b[0] & 1; + ambe_frame[40] = b[3] & 1; + ambe_frame[41] = (b[4] >> 2) & 1; + ambe_frame[42] = (b[4] >> 1) & 1; + ambe_frame[43] = b[4] & 1; + ambe_frame[44] = b[5] & 1; + ambe_frame[45] = b[6] & 1; + ambe_frame[46] = b[7] & 1; + ambe_frame[47] = (b[8] >> 1) & 1; + ambe_frame[48] = b[8] & 1; + + for(int i = 0; i < 7; ++i){ + for(int j = 0; j < 8; ++j){ + ambe[i] |= (ambe_frame[(i*8)+j] << (7-j)); + } + } + } + + void VocoderPlugin::initMbeParms() + { + mbe_initMbeParms(m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced); + //m_errs = 0; + m_errs2 = 0; + m_err_str[0] = 0; + } + + void VocoderPlugin::process_2400x1200(unsigned char *d) + { + char ambe_fr[4][24]; + + memset(ambe_fr, 0, 96); + w = dW; + x = dX; + + for(int i = 0; i < 9; ++i){ + for(int j = 0; j < 8; ++j){ + ambe_fr[*w][*x] = (1 & (d[i] >> j)); + w++; + x++; + } + } + + mbe_processAmbe3600x2400Framef(m_audio_out_temp_buf, &m_errs2, m_err_str, ambe_fr, ambe_d,m_mbelibParms-> m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3); + processAudio(); + } + + void VocoderPlugin::process_2450x1150(unsigned char *d) + { + char ambe_fr[4][24]; + + memset(ambe_fr, 0, 96); + 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 & (d[i] >> (7 - (j+1)))); + ambe_fr[*w][*x] = (1 & (d[i] >> (7 - j))); + w++; + x++; + y++; + z++; + } + } + + mbe_processAmbe3600x2450Framef(m_audio_out_temp_buf, &m_errs2, m_err_str, ambe_fr, ambe_d,m_mbelibParms-> m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3); + processAudio(); + } + + void VocoderPlugin::process_2450(unsigned char *d) + { + char ambe_data[49]; + char dvsi_data[7]; + memset(dvsi_data, 0, 7); + + for(int i = 0; i < 6; ++i){ + for(int j = 0; j < 8; j++){ + ambe_data[j+(8*i)] = (1 & (d[i] >> (7 - j))); + } + } + ambe_data[48] = (1 & (d[6] >> 7)); + processData(ambe_data); + } + + void VocoderPlugin::processData(char ambe_data[49]) + { + mbe_processAmbe2450Dataf(m_audio_out_temp_buf, &m_errs2, m_err_str, ambe_data, m_mbelibParms->m_cur_mp,m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3); + processAudio(); + } + + short * VocoderPlugin::getAudio(int& nbSamples) + { + nbSamples = m_audio_out_nb_samples; + return m_audio_out_buf; + } + + void VocoderPlugin::resetAudio() + { + m_audio_out_nb_samples = 0; + m_audio_out_buf_p = m_audio_out_buf; + } + + void VocoderPlugin::processAudio() + { + m_audio_out_temp_buf_p = m_audio_out_temp_buf; + + if (m_audio_out_nb_samples + 160 >= m_audio_out_buf_size){ + resetAudio(); + } + + for (int i = 0; i < 160; i++){ + if (*m_audio_out_temp_buf_p > static_cast(32760)){ + *m_audio_out_temp_buf_p = static_cast(32760); + } + else if (*m_audio_out_temp_buf_p < static_cast(-32760)){ + *m_audio_out_temp_buf_p = static_cast(-32760); + } + + *m_audio_out_buf_p = static_cast(*m_audio_out_temp_buf_p); + m_audio_out_buf_p++; + + m_audio_out_nb_samples++; + m_audio_out_temp_buf_p++; + } + } diff --git a/mbe/vocoder_plugin.h b/mbe/vocoder_plugin.h new file mode 100644 index 0000000..f2ccb80 --- /dev/null +++ b/mbe/vocoder_plugin.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef VOCODER_PLUGIN_H +#define VOCODER_PLUGIN_H + +#include +#include "imbe_vocoder/imbe_vocoder_api.h" +#include "mbelib_parms.h" + +class VocoderPlugin +{ +public: + VocoderPlugin(); + ~VocoderPlugin(); + void decode_2400x1200(int16_t *pcm, uint8_t *codec); + void decode_2450x1150(int16_t *pcm, uint8_t *codec); + void decode_2450(int16_t *pcm, uint8_t *codec); + void encode_2400x1200(int16_t *pcm, uint8_t *codec); + void encode_2450x1150(int16_t *pcm, uint8_t *codec); + void encode_2450(int16_t *pcm, uint8_t *codec); + +private: + imbe_vocoder vocoder; + mbelibParms *m_mbelibParms; + int m_errs2; + char m_err_str[64]; + + float m_audio_out_temp_buf[160]; //!< output of decoder + float *m_audio_out_temp_buf_p; + float m_aout_max_buf[200]; + float *m_aout_max_buf_p; + int m_aout_max_buf_idx; + short m_audio_out_buf[2*48000]; //!< final result - 1s of L+R S16LE samples + short *m_audio_out_buf_p; + int m_audio_out_nb_samples; + int m_audio_out_buf_size; + const int *w, *x, *y, *z; + char ambe_d[49]; + + void initMbeParms(); + void process_2400x1200(unsigned char *d); + void process_2450x1150(unsigned char *d); + void process_2450(unsigned char *d); + void processData(char ambe_data[49]); + short *getAudio(int& nbSamples); + void resetAudio(); + void processAudio(); +}; + +#endif // VOCODER_PLUGIN_H diff --git a/mbe/vocoder_plugin_api.h b/mbe/vocoder_plugin_api.h new file mode 100644 index 0000000..d50e90d --- /dev/null +++ b/mbe/vocoder_plugin_api.h @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#ifndef VOCODER_PLUGIN_API_H +#define VOCODER_PLUGIN_API_H + +#include + +extern "C" { + +struct mbe_parameters +{ + float w0; + int L; + int K; + int Vl[57]; + float Ml[57]; + float log2Ml[57]; + float PHIl[57]; + float PSIl[57]; + float gamma; + int un; + int repeat; +}; + +typedef struct mbe_parameters mbe_parms; + +struct mbelibParms +{ + mbe_parms *m_cur_mp; + mbe_parms *m_prev_mp; + mbe_parms *m_prev_mp_enhanced; + + 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)); + } + + ~mbelibParms() + { + free(m_prev_mp_enhanced); + free(m_prev_mp); + free(m_cur_mp); + } +}; +} + +class VocoderPlugin +{ +public: + VocoderPlugin(); + ~VocoderPlugin(); + void decode_2400x1200(int16_t *pcm, uint8_t *codec); + void decode_2450x1150(int16_t *pcm, uint8_t *codec); + void decode_2450(int16_t *pcm, uint8_t *codec); + void encode_2400x1200(int16_t *pcm, uint8_t *codec); + void encode_2450x1150(int16_t *pcm, uint8_t *codec); + void encode_2450(int16_t *pcm, uint8_t *codec); + +private: + imbe_vocoder vocoder; + mbe_parms cur_mp; + mbe_parms prev_mp; + mbelibParms *m_mbelibParms; + //int m_errs; + int m_errs2; + char m_err_str[64]; + + float m_audio_out_temp_buf[160]; //!< output of decoder + float *m_audio_out_temp_buf_p; + float m_aout_max_buf[200]; + float *m_aout_max_buf_p; + int m_aout_max_buf_idx; + short m_audio_out_buf[2*48000]; //!< final result - 1s of L+R S16LE samples + short *m_audio_out_buf_p; + int m_audio_out_nb_samples; + int m_audio_out_buf_size; + const int *w, *x, *y, *z; + char ambe_d[49]; + + void initMbeParms(); + void process_2400x1200(unsigned char *d); + void process_2450x1150(unsigned char *d); + void process_2450(unsigned char *d); + void processData(char ambe_data[49]); + short *getAudio(int& nbSamples); + void resetAudio(); + void processAudio(); +}; + +#endif // VOCODER_PLUGIN_API_H diff --git a/mbe/vocoder_tables.h b/mbe/vocoder_tables.h new file mode 100644 index 0000000..ebf6023 --- /dev/null +++ b/mbe/vocoder_tables.h @@ -0,0 +1,489 @@ +/* + * 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. + */ + +const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +const unsigned int A_TABLE[] = {0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, + 48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U}; +const unsigned int B_TABLE[] = {25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, + 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U}; +const unsigned int C_TABLE[] = {46U, 50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U, 23U, + 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U}; +const unsigned int PRNG_TABLE[] = { + 0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU, + 0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U, + 0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU, + 0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU, + 0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU, + 0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U, + 0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU, + 0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U, + 0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU, + 0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU, + 0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU, + 0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U, + 0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U, + 0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U, + 0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U, + 0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U, + 0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U, + 0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U, + 0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U, + 0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U, + 0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U, + 0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U, + 0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U, + 0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U, + 0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU, + 0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU, + 0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U, + 0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU, + 0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU, + 0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU, + 0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU, + 0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU, + 0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U, + 0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU, + 0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU, + 0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU, + 0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U, + 0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U, + 0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U, + 0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U, + 0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U, + 0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U, + 0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U, + 0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U, + 0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U, + 0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U, + 0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U, + 0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U, + 0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U, + 0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U, + 0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U, + 0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU, + 0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU, + 0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU, + 0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U, + 0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU, + 0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U, + 0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU, + 0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU, + 0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U, + 0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU, + 0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU, + 0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU, + 0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U, + 0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U, + 0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U, + 0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U, + 0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U, + 0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U, + 0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U, + 0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U, + 0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U, + 0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U, + 0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U, + 0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U, + 0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U, + 0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU, + 0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU, + 0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU, + 0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU, + 0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU, + 0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U, + 0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU, + 0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU, + 0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU, + 0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU, + 0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU, + 0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U, + 0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU, + 0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U, + 0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U, + 0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U, + 0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U, + 0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U, + 0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U, + 0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U, + 0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U, + 0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U, + 0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U, + 0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U, + 0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U, + 0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U, + 0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U, + 0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU, + 0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU, + 0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU, + 0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U, + 0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU, + 0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U, + 0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU, + 0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU, + 0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU, + 0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U, + 0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU, + 0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU, + 0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U, + 0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U, + 0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U, + 0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U, + 0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U, + 0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U, + 0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U, + 0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U, + 0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U, + 0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U, + 0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U, + 0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U, + 0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U, + 0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU, + 0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU, + 0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U, + 0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU, + 0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU, + 0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU, + 0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU, + 0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU, + 0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U, + 0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU, + 0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU, + 0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU, + 0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU, + 0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U, + 0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U, + 0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U, + 0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U, + 0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U, + 0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U, + 0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U, + 0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U, + 0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U, + 0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U, + 0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U, + 0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U, + 0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U, + 0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU, + 0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U, + 0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU, + 0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U, + 0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU, + 0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU, + 0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU, + 0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U, + 0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU, + 0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU, + 0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU, + 0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU, + 0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU, + 0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U, + 0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U, + 0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U, + 0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U, + 0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U, + 0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U, + 0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U, + 0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U, + 0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U, + 0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U, + 0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U, + 0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U, + 0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U, + 0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU, + 0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU, + 0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U, + 0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU, + 0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU, + 0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU, + 0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U, + 0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU, + 0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U, + 0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU, + 0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU, + 0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU, + 0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U, + 0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U, + 0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U, + 0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U, + 0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U, + 0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U, + 0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U, + 0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U, + 0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U, + 0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U, + 0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U, + 0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U, + 0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U, + 0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U, + 0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U, + 0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU, + 0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU, + 0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU, + 0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U, + 0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU, + 0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU, + 0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU, + 0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU, + 0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU, + 0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U, + 0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU, + 0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU, + 0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U, + 0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U, + 0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U, + 0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U, + 0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U, + 0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U, + 0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U, + 0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U, + 0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U, + 0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U, + 0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U, + 0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U, + 0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U, + 0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU, + 0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU, + 0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU, + 0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU, + 0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU, + 0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U, + 0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU, + 0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU, + 0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU, + 0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U, + 0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU, + 0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U, + 0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU, + 0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U, + 0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U, + 0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U, + 0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U, + 0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U, + 0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U, + 0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U, + 0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U, + 0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U, + 0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U, + 0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U, + 0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U, + 0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U, + 0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU, + 0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U, + 0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU, + 0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU, + 0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU, + 0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU, + 0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU, + 0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU, + 0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU, + 0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU, + 0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U, + 0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU, + 0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU, + 0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U, + 0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U, + 0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U, + 0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U, + 0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U, + 0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U, + 0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U, + 0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U, + 0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U, + 0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U, + 0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U, + 0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U, + 0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU, + 0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU, + 0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU, + 0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U, + 0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU, + 0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU, + 0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU, + 0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U, + 0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU, + 0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U, + 0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU, + 0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU, + 0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU, + 0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U, + 0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U, + 0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U, + 0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U, + 0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U, + 0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U, + 0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U, + 0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U, + 0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U, + 0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U, + 0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U, + 0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U, + 0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U, + 0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU, + 0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU, + 0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U, + 0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU, + 0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU, + 0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU, + 0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU, + 0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU, + 0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U, + 0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU, + 0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU, + 0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU, + 0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU, + 0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U, + 0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U, + 0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U, + 0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U, + 0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U, + 0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U, + 0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U, + 0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U, + 0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U, + 0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U, + 0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U, + 0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U, + 0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U, + 0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U, + 0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU, + 0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU, + 0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU, + 0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U, + 0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU, + 0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U, + 0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU, + 0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU, + 0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU, + 0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU, + 0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU, + 0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU, + 0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U, + 0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U, + 0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U, + 0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U, + 0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U, + 0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U, + 0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U, + 0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U, + 0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U, + 0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U, + 0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U, + 0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U, + 0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U, + 0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU, + 0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU, + 0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU, + 0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU, + 0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU, + 0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U, + 0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU, + 0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU, + 0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU, + 0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU, + 0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU, + 0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U, + 0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU, + 0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U, + 0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U, + 0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U, + 0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U, + 0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U, + 0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U, + 0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U, + 0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U, + 0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U, + 0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U, + 0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U, + 0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U, + 0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U, + 0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U, + 0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU, + 0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU, + 0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU, + 0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U, + 0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU, + 0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U, + 0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU, + 0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU, + 0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU, + 0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U, + 0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU, + 0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U, + 0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U, + 0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U, + 0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U, + 0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U, + 0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U, + 0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U, + 0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U, + 0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U, + 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, + 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U}; + +const unsigned int INTERLEAVE_TABLE_5_20[] = { + 0U, 40U, 80U, 120U, 160U, + 2U, 42U, 82U, 122U, 162U, + 4U, 44U, 84U, 124U, 164U, + 6U, 46U, 86U, 126U, 166U, + 8U, 48U, 88U, 128U, 168U, + 10U, 50U, 90U, 130U, 170U, + 12U, 52U, 92U, 132U, 172U, + 14U, 54U, 94U, 134U, 174U, + 16U, 56U, 96U, 136U, 176U, + 18U, 58U, 98U, 138U, 178U, + 20U, 60U, 100U, 140U, 180U, + 22U, 62U, 102U, 142U, 182U, + 24U, 64U, 104U, 144U, 184U, + 26U, 66U, 106U, 146U, 186U, + 28U, 68U, 108U, 148U, 188U, + 30U, 70U, 110U, 150U, 190U, + 32U, 72U, 112U, 152U, 192U, + 34U, 74U, 114U, 154U, 194U, + 36U, 76U, 116U, 156U, 196U, + 38U, 78U, 118U, 158U, 198U}; + +const unsigned int INTERLEAVE_TABLE_9_20[] = { + 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, + 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, + 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, + 6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U, + 8U, 48U, 88U, 128U, 168U, 208U, 248U, 288U, 328U, + 10U, 50U, 90U, 130U, 170U, 210U, 250U, 290U, 330U, + 12U, 52U, 92U, 132U, 172U, 212U, 252U, 292U, 332U, + 14U, 54U, 94U, 134U, 174U, 214U, 254U, 294U, 334U, + 16U, 56U, 96U, 136U, 176U, 216U, 256U, 296U, 336U, + 18U, 58U, 98U, 138U, 178U, 218U, 258U, 298U, 338U, + 20U, 60U, 100U, 140U, 180U, 220U, 260U, 300U, 340U, + 22U, 62U, 102U, 142U, 182U, 222U, 262U, 302U, 342U, + 24U, 64U, 104U, 144U, 184U, 224U, 264U, 304U, 344U, + 26U, 66U, 106U, 146U, 186U, 226U, 266U, 306U, 346U, + 28U, 68U, 108U, 148U, 188U, 228U, 268U, 308U, 348U, + 30U, 70U, 110U, 150U, 190U, 230U, 270U, 310U, 350U, + 32U, 72U, 112U, 152U, 192U, 232U, 272U, 312U, 352U, + 34U, 74U, 114U, 154U, 194U, 234U, 274U, 314U, 354U, + 36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U, + 38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U}; + +const unsigned int INTERLEAVE_TABLE_26_4[] = { + 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, 48U, 52U, 56U, 60U, 64U, 68U, 72U, 76U, 80U, 84U, 88U, 92U, 96U, 100U, + 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, 81U, 85U, 89U, 93U, 97U, 101U, + 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U, 50U, 54U, 58U, 62U, 66U, 70U, 74U, 78U, 82U, 86U, 90U, 94U, 98U, 102U, + 3U, 7U, 11U, 15U, 19U, 23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U, 75U, 79U, 83U, 87U, 91U, 95U, 99U, 103U}; + +const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, + 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U}; diff --git a/mode.h b/mode.h index 967d422..50965c8 100644 --- a/mode.h +++ b/mode.h @@ -23,11 +23,11 @@ #ifdef USE_FLITE #include #endif -#include +#include "imbe_vocoder/imbe_vocoder_api.h" #ifdef VOCODER_PLUGIN #include "vocoder_plugin.h" #else -#include +#include "mbe/vocoder_plugin_api.h" #endif #include "audioengine.h" #if !defined(Q_OS_IOS)